# Patch for ALPHA release 1.8.0alpha6 of LambdaMOO

Pavel Curtis (pavel@parc.xerox.com)
Wed, 17 Jan 1996 22:08:44 PST

- Messages sorted by:[ date ][ thread ][ subject ][ author ]

    The following patch fixes a very nasty set of bugs in the implementation of the
    new scattering assignment facility.  In the function run() in execute.c, at
    about line 1580, replace this entire case for EOP_SCATTER:
    -------------------------------------------------------------------------------
    	      case EOP_SCATTER:
    		{
    		    int		nargs = READ_BYTES(bv, 1);
    		    int		nreq = READ_BYTES(bv, 1);
    		    int		rest = READ_BYTES(bv, 1);
    		    int		have_rest = (rest > nargs ? 0 : 1);
    		    Var		list;
    		    int		len, nopt_avail, nrest, i, offset;
    		    int		done, where = 0;

    		    list = TOP_RT_VALUE;
    		    len = list.v.list[0].v.num;
    		    if (len < nreq  ||  (!have_rest  &&  len > nargs)) {
    			free_var(POP()); /* replace list with error code */
    			PUSH_ERROR(E_ARGS);
    		    } else {
    			nopt_avail = len - nreq;
    			nrest = (have_rest && len >= nargs ? len - nargs + 1
    							   : 0);
    			for (offset = 0, i = 1; i <= nargs; i++) {
    			    int	id = READ_BYTES(bv, bc.numbytes_var_name);
    			    int	label = READ_BYTES(bv, bc.numbytes_label);

    			    if (i == rest) { 		/* rest */
    				free_var(RUN_ACTIV.rt_env[id]);
    				RUN_ACTIV.rt_env[id] = sublist(var_ref(list),
    							       i,
    							       i + nrest - 1);
    				offset += nrest - 1;
    			    } else if (label == 0) { 	/* required */
    				free_var(RUN_ACTIV.rt_env[id]);
    				RUN_ACTIV.rt_env[id] =
    				    var_ref(list.v.list[i + offset]);
    			    } else {			/* optional */
    				if (nopt_avail > 0) {
    				    nopt_avail--;
    				    free_var(RUN_ACTIV.rt_env[id]);
    				    RUN_ACTIV.rt_env[id] =
    					var_ref(list.v.list[i + offset]);
    				} else {
    				    offset--;
    				    if (where == 0  &&  label != 1)
    					where = label;
    				}
    			    }
    			}

    			done = READ_BYTES(bv, bc.numbytes_label);
    			if (where == 0)
    			    JUMP(done);
    			else
    			    JUMP(where);
    		    }
    		}
    		break;
    -------------------------------------------------------------------------------
    with the following new version:
    -------------------------------------------------------------------------------
    	      case EOP_SCATTER:
    		{
    		    int		nargs = READ_BYTES(bv, 1);
    		    int		nreq = READ_BYTES(bv, 1);
    		    int		rest = READ_BYTES(bv, 1);
    		    int		have_rest = (rest > nargs ? 0 : 1);
    		    Var		list;
    		    int		len = 0, nopt_avail, nrest, i, offset;
    		    int		done, where = 0;
    		    enum error	e = E_NONE;

    		    list = TOP_RT_VALUE;
    		    if (list.type != TYPE_LIST)
    			e = E_TYPE;
    		    else if ((len = list.v.list[0].v.num) < nreq
    			     ||  (!have_rest  &&  len > nargs))
    			e = E_ARGS;

    		    if (e != E_NONE) { /* skip rest of operands */
    			free_var(POP()); /* replace list with error code */
    			PUSH_ERROR(e);
    			for (i = 1; i <= nargs; i++) {
    			    READ_BYTES(bv, bc.numbytes_var_name);
    			    READ_BYTES(bv, bc.numbytes_label);
    			}
    		    } else {
    			nopt_avail = len - nreq;
    			nrest = (have_rest && len >= nargs ? len - nargs + 1
    							   : 0);
    			for (offset = 0, i = 1; i <= nargs; i++) {
    			    int	id = READ_BYTES(bv, bc.numbytes_var_name);
    			    int	label = READ_BYTES(bv, bc.numbytes_label);

    			    if (i == rest) { 		/* rest */
    				free_var(RUN_ACTIV.rt_env[id]);
    				RUN_ACTIV.rt_env[id] = sublist(var_ref(list),
    							       i,
    							       i + nrest - 1);
    				offset += nrest - 1;
    			    } else if (label == 0) { 	/* required */
    				free_var(RUN_ACTIV.rt_env[id]);
    				RUN_ACTIV.rt_env[id] =
    				    var_ref(list.v.list[i + offset]);
    			    } else {			/* optional */
    				if (nopt_avail > 0) {
    				    nopt_avail--;
    				    free_var(RUN_ACTIV.rt_env[id]);
    				    RUN_ACTIV.rt_env[id] =
    					var_ref(list.v.list[i + offset]);
    				} else {
    				    offset--;
    				    if (where == 0  &&  label != 1)
    					where = label;
    				}
    			    }
    			}
    		    }

    		    done = READ_BYTES(bv, bc.numbytes_label);
    		    if (where == 0)
    			JUMP(done);
    		    else
    			JUMP(where);
    		}
    		break;
    -------------------------------------------------------------------------------
    This should fix the major problems recently reported on the MOO-Cows list.

    	Pavel