예제 #1
0
파일: n-loop.c 프로젝트: mbk/ren-c
*/	static void Loop_Number(REBVAL *out, REBVAL *var, REBSER* body, REBVAL *start, REBVAL *end, REBVAL *incr)
/*
***********************************************************************/
{
	REBDEC s;
	REBDEC e;
	REBDEC i;

	if (IS_INTEGER(start)) s = cast(REBDEC, VAL_INT64(start));
	else if (IS_DECIMAL(start) || IS_PERCENT(start)) s = VAL_DECIMAL(start);
	else { Trap_Arg(start); DEAD_END_VOID; }

	if (IS_INTEGER(end)) e = cast(REBDEC, VAL_INT64(end));
	else if (IS_DECIMAL(end) || IS_PERCENT(end)) e = VAL_DECIMAL(end);
	else { Trap_Arg(end); DEAD_END_VOID; }

	if (IS_INTEGER(incr)) i = cast(REBDEC, VAL_INT64(incr));
	else if (IS_DECIMAL(incr) || IS_PERCENT(incr)) i = VAL_DECIMAL(incr);
	else { Trap_Arg(incr); DEAD_END_VOID; }

	VAL_SET(var, REB_DECIMAL);

	SET_NONE(out); // Default result to NONE if the loop does not run

	for (; (i > 0.0) ? s <= e : s >= e; s += i) {
		VAL_DECIMAL(var) = s;

		if (!DO_BLOCK(out, body, 0) && Check_Error(out) >= 0) break;

		if (!IS_DECIMAL(var)) Trap_Type(var);
		s = VAL_DECIMAL(var);
	}
}
예제 #2
0
파일: n-loop.c 프로젝트: mbk/ren-c
*/	static void Loop_Series(REBVAL *out, REBVAL *var, REBSER* body, REBVAL *start, REBINT ei, REBINT ii)
/*
***********************************************************************/
{
	REBINT si = VAL_INDEX(start);
	REBCNT type = VAL_TYPE(start);

	*var = *start;

	if (ei >= cast(REBINT, VAL_TAIL(start)))
		ei = cast(REBINT, VAL_TAIL(start));

	if (ei < 0) ei = 0;

	SET_NONE(out); // Default result to NONE if the loop does not run

	for (; (ii > 0) ? si <= ei : si >= ei; si += ii) {
		VAL_INDEX(var) = si;

		if (!DO_BLOCK(out, body, 0) && Check_Error(out) >= 0) break;

		if (VAL_TYPE(var) != type) Trap1(RE_INVALID_TYPE, var);
		si = VAL_INDEX(var);
	}
}
예제 #3
0
*/	static void Loop_Number(REBVAL *var, REBSER* body, REBVAL *start, REBVAL *end, REBVAL *incr)
/*
***********************************************************************/
{
	REBVAL *result;
	REBDEC s;
	REBDEC e;
	REBDEC i;

	if (IS_INTEGER(start)) s = (REBDEC)VAL_INT64(start);
	else if (IS_DECIMAL(start) || IS_PERCENT(start)) s = VAL_DECIMAL(start);
	else Trap_Arg(start);

	if (IS_INTEGER(end)) e = (REBDEC)VAL_INT64(end);
	else if (IS_DECIMAL(end) || IS_PERCENT(end)) e = VAL_DECIMAL(end);
	else Trap_Arg(end);

	if (IS_INTEGER(incr)) i = (REBDEC)VAL_INT64(incr);
	else if (IS_DECIMAL(incr) || IS_PERCENT(incr)) i = VAL_DECIMAL(incr);
	else Trap_Arg(incr);

	VAL_SET(var, REB_DECIMAL);

	for (; (i > 0.0) ? s <= e : s >= e; s += i) {
		VAL_DECIMAL(var) = s;
		result = Do_Blk(body, 0);
		if (THROWN(result) && Check_Error(result) >= 0) break;
		if (!IS_DECIMAL(var)) Trap_Type(var);
		s = VAL_DECIMAL(var);
	}
}
예제 #4
0
파일: main.cpp 프로젝트: StrausMG/learning
int main()
{
    cpu* the_cpu = Cpu_Construct();
	if (the_cpu == NULL)
	{
		printf ("Cpu_Construct was failed");
		return -1;
	}

	FILE* output      = fopen ("output.txt", "w");
	FILE* the_log	  = fopen ("the_log.txt", "w");
	
    OUT printf ("# This is an emulator of Intel Core i7\n"
                "# The developer:     Yura Gorishniy     <*****@*****.**>\n"
                "# Version 4.00\n"
                "# The file: %s\n"
                "# The compilation time: %s, %s\n\n", strrchr (__FILE__, '\\'), __DATE__, __TIME__);
	
	FILE* the_program = fopen ("the_program.txt", "r");
	FILE* binary	  = fopen ("binary.txt", "w");
	Check_Error (the_asm  (the_program, binary, the_log), the_log);
	fclose (binary);
	fclose (the_program);

	the_program = fopen ("the_program.txt", "r");
	binary = fopen ("binary.txt", "w");
	Check_Error (the_asm  (the_program, binary, the_log), the_log);
	fclose (binary);

	binary = fopen ("binary.txt", "r");
	Check_Error (Cpu_Load (the_cpu, binary), the_log);
	Check_Error (Cpu_Run  (the_cpu, output, the_log), the_log);

	fclose (the_log);
	fclose (the_program);
	fclose (binary);
	fclose (output);

return 0;
}
예제 #5
0
*/	static void Loop_Integer(REBVAL *var, REBSER* body, REBI64 start, REBI64 end, REBI64 incr)
/*
***********************************************************************/
{
	REBVAL *result;

	VAL_SET(var, REB_INTEGER);
	
	while ((incr > 0) ? start <= end : start >= end) {
		VAL_INT64(var) = start;
		result = Do_Blk(body, 0);
		if (THROWN(result) && Check_Error(result) >= 0) break;
		if (!IS_INTEGER(var)) Trap_Type(var);
		start = VAL_INT64(var);
		
		if (REB_I64_ADD_OF(start, incr, &start)) {
			Trap0(RE_OVERFLOW);
		}
	}
}
예제 #6
0
파일: n-loop.c 프로젝트: mbk/ren-c
*/	static void Loop_Integer(REBVAL *out, REBVAL *var, REBSER* body, REBI64 start, REBI64 end, REBI64 incr)
/*
***********************************************************************/
{
	VAL_SET(var, REB_INTEGER);

	SET_NONE(out); // Default result to NONE if the loop does not run

	while ((incr > 0) ? start <= end : start >= end) {
		VAL_INT64(var) = start;

		if (!DO_BLOCK(out, body, 0) && Check_Error(out) >= 0) break;

		if (!IS_INTEGER(var)) Trap_Type(var);
		start = VAL_INT64(var);

		if (REB_I64_ADD_OF(start, incr, &start)) {
			Trap(RE_OVERFLOW);
		}
	}
}
예제 #7
0
*/	static void Loop_Series(REBVAL *var, REBSER* body, REBVAL *start, REBINT ei, REBINT ii)
/*
***********************************************************************/
{
	REBVAL *result;
	REBINT si = VAL_INDEX(start);
	REBCNT type = VAL_TYPE(start);

	*var = *start;
	
	if (ei >= (REBINT)VAL_TAIL(start)) ei = (REBINT)VAL_TAIL(start);
	if (ei < 0) ei = 0;

	for (; (ii > 0) ? si <= ei : si >= ei; si += ii) {
		VAL_INDEX(var) = si;
		result = Do_Blk(body, 0);
		if (THROWN(result) && Check_Error(result) >= 0) break;
		if (VAL_TYPE(var) != type) Trap1(RE_INVALID_TYPE, var);
		si = VAL_INDEX(var);
	}
}
예제 #8
0
파일: main.cpp 프로젝트: StrausMG/learning
int main()
{
	FILE* the_expression = fopen ("the_expression.txt", "r");

	assert (THE_LOG);
	assert (the_expression);

	node* exp_tree = Node_NEW();

	Check_Error (Tree_Read_in (the_expression, exp_tree));

	int nTabs = 0;
	Tree_Dump (exp_tree, nTabs);
	fprintf (THE_LOG, "\n\n\n");
	Tree_Print (exp_tree);

	Tree_Delete (exp_tree);

	fclose (the_expression);
	fclose (THE_LOG);
return 0;
}
예제 #9
0
파일: tree.cpp 프로젝트: StrausMG/learning
int Node_Dump (node* my_node)
{
	//fprintf (LOG, "\n==================================================");
	char tmp_type[TMPLEN] = {};
	DEF_TYPE (my_node -> type);

	fprintf (LOG, "{%s}\t", tmp_type);

	switch (my_node -> type)
	{
		case PGM:	case OP:	case OP_PRINT:	case OP_IF:	case OP_WHILE:	case OP_ASSIGN:
		case OP_ELSE:
			break;

		case FUNC:	case MATH_OP:	case CMP:
			fprintf (LOG, "[%d]", my_node -> op);
			break;

		case VAR:	case STR:
			fprintf (LOG, "[%s]", my_node -> word);
			break;

		case NUMBER:
			fprintf (LOG, "[%lg]", my_node -> num);
			break;
	}
	int err_index = Node_OK (my_node);
	if (err_index == HAPPY) fprintf (LOG, "\t\t\tNode [%.8x] is OK\t", my_node);
	else 
	{
		fprintf (LOG, "Node [%.8x] is NOT ok!\t", my_node);
		Check_Error (err_index);
		fputc ('\n', LOG);
		return HAPPY;
	}
	fprintf (LOG, "left [%.8x] right [%.8x] prev [%.8x]\n",
					   my_node -> left, my_node -> right, my_node -> prev);
	return HAPPY;
}
예제 #10
0
파일: n-loop.c 프로젝트: mbk/ren-c
*/	static REB_R Loop_Each(struct Reb_Call *call_, REBINT mode)
/*
**		Supports these natives (modes):
**			0: foreach
**			1: remove-each
**			2: map
**
***********************************************************************/
{
	REBSER *body;
	REBVAL *vars;
	REBVAL *words;
	REBSER *frame;
	REBVAL *value;
	REBSER *series;
	REBSER *out;	// output block (for MAP, mode = 2)

	REBINT index;	// !!!! should these be REBCNT?
	REBINT tail;
	REBINT windex;	// write
	REBINT rindex;	// read
	REBINT err;
	REBCNT i;
	REBCNT j;
	REBVAL *ds;

	assert(mode >= 0 && mode < 3);

	value = D_ARG(2); // series
	if (IS_NONE(value)) return R_NONE;

	body = Init_Loop(D_ARG(1), D_ARG(3), &frame); // vars, body
	SET_OBJECT(D_ARG(1), frame); // keep GC safe
	Set_Block(D_ARG(3), body);	 // keep GC safe

	SET_NONE(D_OUT); // Default result to NONE if the loop does not run

	// If it's MAP, create result block:
	if (mode == 2) {
		out = Make_Block(VAL_LEN(value));
		SAVE_SERIES(out);
	}

	// Get series info:
	if (ANY_OBJECT(value)) {
		series = VAL_OBJ_FRAME(value);
		out = FRM_WORD_SERIES(series); // words (the out local reused)
		index = 1;
		//if (frame->tail > 3) Trap_Arg_DEAD_END(FRM_WORD(frame, 3));
	}
	else if (IS_MAP(value)) {
		series = VAL_SERIES(value);
		index = 0;
		//if (frame->tail > 3) Trap_Arg_DEAD_END(FRM_WORD(frame, 3));
	}
	else {
		series = VAL_SERIES(value);
		index  = VAL_INDEX(value);
		if (index >= cast(REBINT, SERIES_TAIL(series))) {
			if (mode == 1) {
				SET_INTEGER(D_OUT, 0);
			} else if (mode == 2) {
				Set_Block(D_OUT, out);
				UNSAVE_SERIES(out);
			}
			return R_OUT;
		}
	}

	windex = index;

	// Iterate over each value in the series block:
	while (index < (tail = SERIES_TAIL(series))) {

		rindex = index;  // remember starting spot
		j = 0;

		// Set the FOREACH loop variables from the series:
		for (i = 1; i < frame->tail; i++) {

			vars = FRM_VALUE(frame, i);
			words = FRM_WORD(frame, i);

			// var spec is WORD
			if (IS_WORD(words)) {

				if (index < tail) {

					if (ANY_BLOCK(value)) {
						*vars = *BLK_SKIP(series, index);
					}

					else if (ANY_OBJECT(value)) {
						if (!VAL_GET_EXT(BLK_SKIP(out, index), EXT_WORD_HIDE)) {
							// Alternate between word and value parts of object:
							if (j == 0) {
								Init_Word(vars, REB_WORD, VAL_WORD_SYM(BLK_SKIP(out, index)), series, index);
								if (NOT_END(vars+1)) index--; // reset index for the value part
							}
							else if (j == 1)
								*vars = *BLK_SKIP(series, index);
							else
								Trap_Arg_DEAD_END(words);
							j++;
						}
						else {
							// Do not evaluate this iteration
							index++;
							goto skip_hidden;
						}
					}

					else if (IS_VECTOR(value)) {
						Set_Vector_Value(vars, series, index);
					}

					else if (IS_MAP(value)) {
						REBVAL *val = BLK_SKIP(series, index | 1);
						if (!IS_NONE(val)) {
							if (j == 0) {
								*vars = *BLK_SKIP(series, index & ~1);
								if (IS_END(vars+1)) index++; // only words
							}
							else if (j == 1)
								*vars = *BLK_SKIP(series, index);
							else
								Trap_Arg_DEAD_END(words);
							j++;
						}
						else {
							index += 2;
							goto skip_hidden;
						}
					}

					else { // A string or binary
						if (IS_BINARY(value)) {
							SET_INTEGER(vars, (REBI64)(BIN_HEAD(series)[index]));
						}
						else if (IS_IMAGE(value)) {
							Set_Tuple_Pixel(BIN_SKIP(series, index), vars);
						}
						else {
							VAL_SET(vars, REB_CHAR);
							VAL_CHAR(vars) = GET_ANY_CHAR(series, index);
						}
					}
					index++;
				}
				else SET_NONE(vars);
			}

			// var spec is SET_WORD:
			else if (IS_SET_WORD(words)) {
				if (ANY_OBJECT(value) || IS_MAP(value)) {
					*vars = *value;
				} else {
					VAL_SET(vars, REB_BLOCK);
					VAL_SERIES(vars) = series;
					VAL_INDEX(vars) = index;
				}
				//if (index < tail) index++; // do not increment block.
			}
			else Trap_Arg_DEAD_END(words);
		}
		if (index == rindex) index++; //the word block has only set-words: foreach [a:] [1 2 3][]

		if (!DO_BLOCK(D_OUT, body, 0)) {
			if ((err = Check_Error(D_OUT)) >= 0) {
				index = rindex;
				break;
			}
			// else CONTINUE:
			if (mode == 1) SET_FALSE(D_OUT); // keep the value (for mode == 1)
		} else {
			err = 0; // prevent later test against uninitialized value
		}

		if (mode > 0) {
			//if (ANY_OBJECT(value)) Trap_Types_DEAD_END(words, REB_BLOCK, VAL_TYPE(value)); //check not needed

			// If FALSE return, copy values to the write location:
			if (mode == 1) {  // remove-each
				if (IS_CONDITIONAL_FALSE(D_OUT)) {
					REBCNT wide = SERIES_WIDE(series);
					// memory areas may overlap, so use memmove and not memcpy!
					memmove(series->data + (windex * wide), series->data + (rindex * wide), (index - rindex) * wide);
					windex += index - rindex;
					// old: while (rindex < index) *BLK_SKIP(series, windex++) = *BLK_SKIP(series, rindex++);
				}
			}
			else
				if (!IS_UNSET(D_OUT)) Append_Value(out, D_OUT); // (mode == 2)
		}
skip_hidden: ;
	}

	// Finish up:
	if (mode == 1) {
		// Remove hole (updates tail):
		if (windex < index) Remove_Series(series, windex, index - windex);
		SET_INTEGER(D_OUT, index - windex);

		return R_OUT;
	}

	// If MAP...
	if (mode == 2) {
		UNSAVE_SERIES(out);
		if (err != 2) {
			// ...and not BREAK/RETURN:
			Set_Block(D_OUT, out);
			return R_OUT;
		}
	}

	return R_OUT;
}
예제 #11
0
파일: n-loop.c 프로젝트: mbk/ren-c
*/	static int Loop_All(struct Reb_Call *call_, REBINT mode)
/*
**		0: forall
**		1: forskip
**
***********************************************************************/
{
	REBVAL *var;
	REBSER *body;
	REBCNT bodi;
	REBSER *dat;
	REBINT idx;
	REBINT inc = 1;
	REBCNT type;
	REBVAL *ds;

	var = GET_MUTABLE_VAR(D_ARG(1));
	if (IS_NONE(var)) return R_NONE;

	// Save the starting var value:
	*D_ARG(1) = *var;

	SET_NONE(D_OUT);

	if (mode == 1) inc = Int32(D_ARG(2));

	type = VAL_TYPE(var);
	body = VAL_SERIES(D_ARG(mode+2));
	bodi = VAL_INDEX(D_ARG(mode+2));

	// Starting location when past end with negative skip:
	if (inc < 0 && VAL_INDEX(var) >= VAL_TAIL(var)) {
		VAL_INDEX(var) = VAL_TAIL(var) + inc;
	}

	// NOTE: This math only works for index in positive ranges!

	if (ANY_SERIES(var)) {
		while (TRUE) {
			dat = VAL_SERIES(var);
			idx = VAL_INDEX(var);
			if (idx < 0) break;
			if (idx >= cast(REBINT, SERIES_TAIL(dat))) {
				if (inc >= 0) break;
				idx = SERIES_TAIL(dat) + inc; // negative
				if (idx < 0) break;
				VAL_INDEX(var) = idx;
			}

			if (!DO_BLOCK(D_OUT, body, bodi)) {	// Break, throw, continue, error.
				if (Check_Error(D_OUT) >= 0) {
					break;
				}
			}

			if (VAL_TYPE(var) != type) Trap_Arg_DEAD_END(var);

			VAL_INDEX(var) += inc;
		}
	}
	else Trap_Arg_DEAD_END(var);

	// !!!!! ???? allowed to write VAR????
	*var = *D_ARG(1);

	return R_OUT;
}
예제 #12
0
파일: cpu.cpp 프로젝트: StrausMG/learning
//========================================================================================================
int Cpu_Run (cpu* my_cpu, FILE* output)
{
	ASSERT_CPU_OK (my_cpu);

	int cur = 0;
	int command = 0;
	int exit = 0;

	double a = 0; //temporary value 
	double b = 0; //temporary value

	for (cur = 0; cur < CODES_SIZE; ++cur)
	{
		if (exit) break;
		command = int (my_cpu -> codes[cur]);
		OUT printf ("***%d\n", command);
		switch (command)
		{
			case CMD_PUSH: case CMD_PUSH_RX: case CMD_PUSH_VAR:
				Check_Error (Cpu_Push (my_cpu, &cur, command));
				break;

			case CMD_DUP:
				Check_Error (Cpu_Dup (my_cpu));
				break;

			case CMD_POP: case CMD_POP_VAR:
				Check_Error (Cpu_Pop (my_cpu, &cur));
				break;

			case CMD_IN: case CMD_IN_RX: case CMD_IN_VAR:
				Check_Error (Cpu_In (my_cpu, &cur, command));
				break;

			case CMD_OUT: case CMD_OUT_RX: case CMD_OUT_CH: case CMD_OUT_VAR:
				Check_Error (Cpu_Out (my_cpu, &cur, command, output));
				break;

			case CMD_MOV: case CMD_MOV_RX:
				Check_Error (Cpu_Mov (my_cpu, &cur, command));
				break;

			case CMD_ADD:
				Check_Error (Cpu_Add (my_cpu));
				break;

			case CMD_SUB:
				Check_Error (Cpu_Sub (my_cpu));
				break;

			case CMD_MUL:
				Check_Error (Cpu_Mul (my_cpu));
				break;

			case CMD_DIV:
				Check_Error (Cpu_Div (my_cpu));
				break;

			case CMD_SQR:
				Check_Error (Cpu_Sqr (my_cpu));
				break;

			case CMD_POW:
				Check_Error (Cpu_Pow (my_cpu));
				break;

			case CMD_SQRT:
				Check_Error (Cpu_Sqrt (my_cpu));
				break;

			case CMD_SIN:
				Check_Error (Cpu_Sin (my_cpu));
				break;

			case CMD_COS:
				Check_Error (Cpu_Cos (my_cpu));
				break;

			case CMD_TAN:
				Check_Error (Cpu_Tan (my_cpu));
				break;

			case CMD_CTAN:
				Check_Error (Cpu_Ctan (my_cpu));
				break;

			case CMD_DUMP:
				Cpu_Dump (my_cpu);
				break;

			case CMD_END:
				Check_Error (Cpu_End (my_cpu, output, &exit));
				break;

			case CMD_CALL:
				my_cpu -> call_funcs -> Push (cur + 1);
				cur = int (my_cpu -> codes[cur + 1] - 1);
				break;

			case CMD_RET:
				my_cpu -> call_funcs -> Pop (&a);
				cur = int(a);
				break;

			case CMD_JMP:
				cur = int (my_cpu -> codes[cur + 1] - 1);
				break;

			case CMD_JB:
				if (my_cpu -> cpu_stack -> size_now < 2) return ERR_JB;
				my_cpu -> cpu_stack -> Pop (&b);
				my_cpu -> cpu_stack -> Pop (&a);
				if (a < b) cur = int (my_cpu -> codes[cur + 1] - 1);
				else ++cur;
				break;

			case CMD_JBE:
				if (my_cpu -> cpu_stack -> size_now < 2) return ERR_JBE;
				my_cpu -> cpu_stack -> Pop (&b);
				my_cpu -> cpu_stack -> Pop (&a);
				if (a <= b) cur = int (my_cpu -> codes[cur + 1] - 1);
				else ++cur;
				break;

			case CMD_JE:
				if (my_cpu -> cpu_stack -> size_now < 2) return ERR_JE;
				my_cpu -> cpu_stack -> Pop (&b);
				my_cpu -> cpu_stack -> Pop (&a);
				if (a == b) cur = int (my_cpu -> codes[cur + 1] - 1);
				else ++cur;
				break;

			case CMD_JAE:
				if (my_cpu -> cpu_stack -> size_now < 2) return ERR_JAE;
				my_cpu -> cpu_stack -> Pop (&b);
				my_cpu -> cpu_stack -> Pop (&a);
				if (a >= b) cur = int (my_cpu -> codes[cur + 1] - 1);
				else ++cur;
				break;

			case CMD_JA:
				if (my_cpu -> cpu_stack -> size_now < 2) return ERR_JA;
				my_cpu -> cpu_stack -> Pop (&b);
				my_cpu -> cpu_stack -> Pop (&a);
				if (a > b) cur = int (my_cpu -> codes[cur + 1] - 1);
				else ++cur;
				break;

			case CMD_JUE:
				if (my_cpu -> cpu_stack -> size_now < 2) return ERR_JUE;
				my_cpu -> cpu_stack -> Pop (&b);
				my_cpu -> cpu_stack -> Pop (&a);
				if (a != b) cur = int (my_cpu -> codes[cur + 1] - 1);
				else ++cur;
				break;


			default:
				fprintf (LOG, "\nCPU got wrong command\n"
								 "Your command doesn't exist. "
								 "Current number of the command = [%d], the command = [%d]\n", cur, command);
				return ERR_RUN_WRONG_CMD;
				break;
		}
	}

	ASSERT_CPU_OK (my_cpu);
return HAPPY;
}
예제 #13
0
*/	static int Loop_All(REBVAL *ds, REBINT mode)
/*
**		0: forall
**		1: forskip
**
***********************************************************************/
{
	REBVAL *var;
	REBSER *body;
	REBCNT bodi;
	REBSER *dat;
	REBINT idx;
	REBINT inc = 1;
	REBCNT type;

	var = Get_Var(D_ARG(1));
	if (IS_NONE(var)) return R_NONE;

	// Save the starting var value:
	*D_ARG(1) = *var;

	SET_NONE(D_RET);

	if (mode == 1) inc = Int32(D_ARG(2));

	type = VAL_TYPE(var);
	body = VAL_SERIES(D_ARG(mode+2));
	bodi = VAL_INDEX(D_ARG(mode+2));

	// Starting location when past end with negative skip:
	if (inc < 0 && VAL_INDEX(var) >= (REBINT)VAL_TAIL(var)) {
		VAL_INDEX(var) = (REBINT)VAL_TAIL(var) + inc;
	}

	// NOTE: This math only works for index in positive ranges!

	if (ANY_SERIES(var)) {
		while (TRUE) {
			dat = VAL_SERIES(var);
			idx = (REBINT)VAL_INDEX(var);
			if (idx < 0) break;
			if (idx >= (REBINT)SERIES_TAIL(dat)) {
				if (inc >= 0) break;
				idx = (REBINT)SERIES_TAIL(dat) + inc; // negative
				if (idx < 0) break;
				VAL_INDEX(var) = idx;
			}

			ds = Do_Blk(body, bodi); // (may move stack)

			if (THROWN(ds)) {	// Break, throw, continue, error.
				if (Check_Error(ds) >= 0) {
					*DS_RETURN = *DS_NEXT;
					break;
				}
			}
			*DS_RETURN = *ds;

			if (VAL_TYPE(var) != type) Trap_Arg(var);

			VAL_INDEX(var) += inc;
		}
	}
	else Trap_Arg(var);

	// !!!!! ???? allowed to write VAR????
	*var = *DS_ARG(1);

	return R_RET;
}