Exemple #1
0
Fichier : lvn.c Projet : 5HT/mumps
int lvn(oprtype *a,opctype index_op,triple *parent)
{
	oprtype subscripts[MAX_LVSUBSCRIPTS],*sb1,*sb2,*sb;
	triple *ref,*s, *root;
	char x;
	error_def(ERR_MAXNRSUBSCRIPTS);
	error_def(ERR_RPARENMISSING);
	error_def(ERR_VAREXPECTED);

	if (window_token != TK_IDENT)
	{
		stx_error(ERR_VAREXPECTED);
		return FALSE;
	}
	*a = put_mvar(&window_ident);
	advancewindow();
	if (window_token != TK_LPAREN)
		return TRUE;
	assert(a->oprclass == TRIP_REF);
	ref = a->oprval.tref;
	assert(ref->opcode == OC_VAR);
	sb1 = sb2 = subscripts;
	*sb1++ = *a;
	for (;;)
	{
		if (sb1 >= &subscripts[MAX_LVSUBSCRIPTS])
		{
			stx_error(ERR_MAXNRSUBSCRIPTS);
			return FALSE;
		}
		advancewindow();
		if (!expr(sb1++))
			return FALSE;
		if ((x = window_token) == TK_RPAREN)
		{
			advancewindow();
			break;
		}
		if (x != TK_COMMA)
		{
			stx_error(ERR_RPARENMISSING);
			return FALSE;
		}
	}
	if (parent)
	{	/* only $ORDER, $NEXT, $ZPREV have parent */
		sb1--;
		if (sb1 - sb2 == 1)	/* only name and 1 subscript */
		{	/* SRCHINDX not necessary if only 1 subscript */
			sb = &parent->operand[1];  *sb = *sb1;
			return TRUE;
		}
	}

	root = ref = newtriple(index_op);
	ref->operand[0] = put_ilit((mint)(sb1 - sb2));
	while (sb2 < sb1)
	{
		s = newtriple(OC_PARAMETER);
		ref->operand[1] = put_tref(s);
		s->operand[0] = *sb2++;
		ref = s;
	}
	if (parent)
	{
		parent->operand[0] = put_tref(root);
		sb = &parent->operand[1];
		*sb = *sb2;
		return TRUE;
	}
	*a = put_tref(root);
	return TRUE;
}
Exemple #2
0
int m_for(void)
{
	unsigned int	arg_cnt, arg_index, for_stack_level;
	oprtype		arg_eval_addr[MAX_FORARGS], increment[MAX_FORARGS], terminate[MAX_FORARGS],
			arg_next_addr, arg_value, dummy, control_variable,
			*iteration_start_addr, iteration_start_addr_indr, *not_even_once_addr;
	triple		*eval_next_addr[MAX_FORARGS], *control_ref,
			*forchk1opc, forpos_in_chain, *init_ref, *ref, *step_ref, *term_ref, *var_ref;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	forpos_in_chain = TREF(pos_in_chain);
	FOR_PUSH();
	if (TK_SPACE == TREF(window_token))
	{	/* "argumentless" form */
		FOR_END_OF_SCOPE(1, dummy);
		ref = newtriple(OC_FORCHK1);
		if (!linetail())
		{
			TREF(pos_in_chain) = forpos_in_chain;
			assert(TREF(source_error_found));
			stx_error(TREF(source_error_found));
			FOR_POP(BLOWN_FOR);
			return FALSE;
		}
		SAVE_FOR_OVER_ADDR();				/* stash address of next op in the for_stack array */
		newtriple(OC_JMP)->operand[0] = put_tjmp(ref);	/* transfer back to just before the begining of the body */
		FOR_POP(GOOD_FOR);				/* and pop the array */
		return TRUE;
	}
	for_stack_level = (TREF(for_stack_ptr) - TADR(for_stack));
	init_ref = newtriple(OC_FORNESTLVL);
	init_ref->operand[0] = put_ilit(for_stack_level);
	if (TK_ATSIGN == TREF(window_token))
	{
		if (!indirection(&control_variable))
		{
			FOR_POP(BLOWN_FOR);
			return FALSE;
		}
		ref = newtriple(OC_INDLVADR);
		ref->operand[0] = control_variable;
		control_variable = put_tref(ref);
		control_ref = NULL;
	} else
	{
		/* The following relies on the fact that lvn() always generates an OC_VAR triple first */
		control_ref = (TREF(curtchain))->exorder.bl;
		if (!lvn(&control_variable, OC_SAVPUTINDX, NULL))
		{
			FOR_POP(BLOWN_FOR);
			return FALSE;
		}
		assert(OC_VAR == control_ref->exorder.fl->opcode);
		assert(MVAR_REF == control_ref->exorder.fl->operand[0].oprclass);
	}
	if (TK_EQUAL != TREF(window_token))
	{
		stx_error(ERR_EQUAL);
		FOR_POP(BLOWN_FOR);
		return FALSE;
	}
	newtriple(OC_PASSTHRU)->operand[0] = control_variable;	/* make sure optimizer doesn't ditch control_variable */
	FOR_END_OF_SCOPE(1, dummy);
	assert((0 < for_stack_level) && (MAX_FOR_STACK >= for_stack_level));
	if ((OC_SAVPUTINDX == control_variable.oprval.tref->opcode) || (OC_INDLVADR == control_variable.oprval.tref->opcode))
		TAREF1(for_temps, for_stack_level) = TRUE_WITH_INDX;	/* most uses treat this as a boolean, but some need more */
	else
		init_ref->opcode = OC_NOOP;
	iteration_start_addr = (oprtype *)mcalloc(SIZEOF(oprtype));
	iteration_start_addr_indr = put_indr(iteration_start_addr);
	arg_next_addr.oprclass = NOCLASS;
	not_even_once_addr = NULL;	/* used to skip processing where the initial control exceeds the termination */
	for (arg_cnt = 0; ; ++arg_cnt)
	{
		if (MAX_FORARGS <= arg_cnt)
		{
			stx_error(ERR_MAXFORARGS);
			FOR_POP(BLOWN_FOR);
			return FALSE;
		}
		assert((TK_COMMA == TREF(window_token)) || (TK_EQUAL == TREF(window_token)));
		advancewindow();
		tnxtarg(&arg_eval_addr[arg_cnt]);		/* put location of this arg eval in arg_eval_addr array */
		if (NULL != not_even_once_addr)
		{
			*not_even_once_addr = arg_eval_addr[arg_cnt];
			not_even_once_addr = NULL;
		}
		if (EXPR_FAIL == expr(&arg_value, MUMPS_EXPR))	/* starting (possibly only) value */
		{
			FOR_POP(BLOWN_FOR);
			return FALSE;
		}
		assert(TRIP_REF == arg_value.oprclass);
		if (TK_COLON != TREF(window_token))
		{	/* list point value? */
			increment[arg_cnt].oprclass = terminate[arg_cnt].oprclass = 0;
			DEAL_WITH_DANGER(for_stack_level, control_variable, arg_value);
		} else
		{	/* stepping value */
			init_ref = newtriple(OC_STOTEMP);		/* tuck it in a temp undisturbed by coming evals */
			init_ref->operand[0] = arg_value;
			newtriple(OC_CONUM)->operand[0] = put_tref(init_ref);	/* make start numeric */
			advancewindow();				/* past the first colon */
			var_ref = (TREF(curtchain))->exorder.bl;
			if (EXPR_FAIL == expr(&increment[arg_cnt], MUMPS_EXPR))	/* pick up step */
			{
				FOR_POP(BLOWN_FOR);
				return FALSE;
			}
			assert(TRIP_REF == increment[arg_cnt].oprclass);
			ref = increment[arg_cnt].oprval.tref;
			if (OC_LIT != var_ref->exorder.fl->opcode)
			{
				if (!TAREF1(for_temps, for_stack_level))
					TAREF1(for_temps, for_stack_level) = TRUE;
				if (OC_VAR == var_ref->exorder.fl->opcode)
				{	/* The above relies on lvn() always generating an OC_VAR triple first - asserted earlier */
					step_ref = newtriple(OC_STOTEMP);
					step_ref->operand[0] = put_tref(ref);
					increment[arg_cnt] = put_tref(step_ref);
				}
			}
			if (TK_COLON != TREF(window_token))
			{
				DEAL_WITH_DANGER(for_stack_level, control_variable, put_tref(init_ref));
				terminate[arg_cnt].oprclass = 0;	/* no termination on iteration for this arg */
			} else
			{
				advancewindow();	/* past the second colon */
				var_ref = (TREF(curtchain))->exorder.bl;
				if (EXPR_FAIL == expr(&terminate[arg_cnt], MUMPS_EXPR))		/* termination control value */
				{
					FOR_POP(BLOWN_FOR);
					return FALSE;
				}
				assert(TRIP_REF == terminate[arg_cnt].oprclass);
				ref = terminate[arg_cnt].oprval.tref;
				if (OC_LIT != ref->opcode)
				{
					if (!TAREF1(for_temps, for_stack_level))
						TAREF1(for_temps, for_stack_level) = TRUE;
					if (OC_VAR == var_ref->exorder.fl->opcode)
					{	/* The above relies on lvn() always generating an OC_VAR triple first */
						term_ref = newtriple(OC_STOTEMP);
						term_ref->operand[0] = put_tref(ref);
						terminate[arg_cnt] = put_tref(term_ref);
					}
				}
				DEAL_WITH_DANGER(for_stack_level, control_variable, put_tref(init_ref));
				term_ref = newtriple(OC_PARAMETER);
				term_ref->operand[0] = terminate[arg_cnt];
				step_ref = newtriple(OC_PARAMETER);
				step_ref->operand[0] = increment[arg_cnt];
				step_ref->operand[1] = put_tref(term_ref);
				ref = newtriple(OC_FORINIT);
				ref->operand[0] = control_variable;
				ref->operand[1] = put_tref(step_ref);
				not_even_once_addr = newtriple(OC_JMPGTR)->operand;
			}
		}
		if ((0 < arg_cnt) || (TK_COMMA == TREF(window_token)))
		{
			if (!TAREF1(for_temps, for_stack_level))
				TAREF1(for_temps, for_stack_level) = TRUE;
			if (NOCLASS == arg_next_addr.oprclass)
				arg_next_addr = put_tref(newtriple(OC_CDADDR));
			(eval_next_addr[arg_cnt] = newtriple(OC_LDADDR))->destination = arg_next_addr;
		}
		if (TK_COMMA != TREF(window_token))
			break;
		newtriple(OC_JMP)->operand[0] = iteration_start_addr_indr;
	}
	if (not_even_once_addr)
		 FOR_END_OF_SCOPE(1, *not_even_once_addr);	/* 1 means down a level */
	forchk1opc = newtriple(OC_FORCHK1);	/* FORCHK1 is a do-nothing routine used by the out-of-band mechanism */
	*iteration_start_addr = put_tjmp(forchk1opc);
	if ((TK_EOL != TREF(window_token)) && (TK_SPACE != TREF(window_token)))
	{
		stx_error(ERR_SPOREOL);
		FOR_POP(BLOWN_FOR);
		return FALSE;
	}
	if (!linetail())
	{
		TREF(pos_in_chain) = forpos_in_chain;
		assert(TREF(source_error_found));
		stx_error(TREF(source_error_found));
		FOR_POP(BLOWN_FOR);
		return FALSE;
	}
	SAVE_FOR_OVER_ADDR();		/* stash address of next op in the for_stack array */
	if (0 < arg_cnt)
		newtriple(OC_JMPAT)->operand[0] = put_tref(eval_next_addr[0]);
	for (arg_index = 0; arg_index <= arg_cnt; ++arg_index)
	{
		if (0 < arg_cnt)
			tnxtarg(eval_next_addr[arg_index]->operand);
			if (TRUE_WITH_INDX == TAREF1(for_temps, for_stack_level))
			{	/* since it might have moved, before touching the control variable get a fix on it */
				ref = newtriple(OC_RFRSHINDX);
				ref->operand[0] = put_ilit(for_stack_level);
				ref->operand[1] = put_ilit((increment[arg_index].oprclass || terminate[arg_index].oprclass)
					? FALSE : TRUE); /* if increment rather than new value, rfrsh w/ srchindx else putindx */
				control_variable = put_tref(ref);
			} else
			{
				assert(control_ref);
				control_variable = put_mvar(&control_ref->exorder.fl->operand[0].oprval.vref->mvname);
			}
			newtriple(OC_PASSTHRU)->operand[0] = control_variable;	/* warn off optimizer */
		if (terminate[arg_index].oprclass)
		{
			term_ref = newtriple(OC_PARAMETER);
			term_ref->operand[0] = terminate[arg_index];
			step_ref = newtriple(OC_PARAMETER);
			step_ref->operand[0] = increment[arg_index];
			step_ref->operand[1] = put_tref(term_ref);
			init_ref = newtriple(OC_PARAMETER);
			init_ref->operand[0] = control_variable;
			init_ref->operand[1] = put_tref(step_ref);
			ref = newtriple(OC_FORLOOP);
			/* redirects back to forchk1, which is at the beginning of new iteration */
			ref->operand[0] = *iteration_start_addr;
			ref->operand[1] = put_tref(init_ref);
		} else if (increment[arg_index].oprclass)
		{
			step_ref = newtriple(OC_ADD);
			step_ref->operand[0] = control_variable;
			step_ref->operand[1] = increment[arg_index];
			ref = newtriple(OC_STO);
			ref->operand[0] = control_variable;
			ref->operand[1] = put_tref(step_ref);
			newtriple(OC_JMP)->operand[0] = *iteration_start_addr;
		}
		if (arg_index < arg_cnt)	/* go back and evaluate the next argument */
			newtriple(OC_JMP)->operand[0] = arg_eval_addr[arg_index + 1];
	}
	FOR_POP(GOOD_FOR);
	return TRUE;
}
Exemple #3
0
int actuallist (oprtype *opr)
{
	triple		*ref0, *ref1, *ref2, *masktrip, *counttrip;
	oprtype		ot;
	int		mask, parmcount;
	error_def	(ERR_MAXACTARG);
	error_def	(ERR_NAMEEXPECTED);
	error_def	(ERR_COMMAORRPARENEXP);

	assert (window_token == TK_LPAREN);
	advancewindow ();
	masktrip = newtriple (OC_PARAMETER);
	mask = 0;
	counttrip = newtriple (OC_PARAMETER);
	masktrip->operand[1] = put_tref (counttrip);
	ref0 = counttrip;
	if (window_token == TK_RPAREN)
		parmcount = 0;
	else
	for (parmcount = 1; ; parmcount++)
	{
		if (parmcount > MAX_ACTUALS)
		{
			stx_error (ERR_MAXACTARG);
			return FALSE;
		}
		if (window_token == TK_PERIOD)
		{
			advancewindow ();
			if (window_token == TK_IDENT)
			{
				ot = put_mvar (&window_ident);
				mask |= (1 << parmcount - 1);
				advancewindow ();
			}
			else if (window_token == TK_ATSIGN)
			{
				if (!indirection(&ot))
					return FALSE;
				ref2 = newtriple(OC_INDLVNAMADR);
				ref2->operand[0] = ot;
				ot = put_tref(ref2);
				mask |= (1 << parmcount - 1);
			}
			else
			{
				stx_error (ERR_NAMEEXPECTED);
				return FALSE;
			}
		}
		else if (window_token == TK_COMMA)
		{
			ref2 = newtriple(OC_NULLEXP);
			ot = put_tref(ref2);
		}
		else
			if (!expr (&ot)) return FALSE;
		ref1 = newtriple (OC_PARAMETER);
		ref0->operand[1] = put_tref (ref1);
		ref1->operand[0] = ot;
		if (window_token == TK_COMMA)
		{	advancewindow ();
			if (window_token == TK_RPAREN)
			{	ref0 = ref1;
				ref2 = newtriple(OC_NULLEXP);
				ot = put_tref(ref2);
				ref1 = newtriple (OC_PARAMETER);
				ref0->operand[1] = put_tref (ref1);
				ref1->operand[0] = ot;
				parmcount++;
				break;
			}
		}
		else
		if (window_token == TK_RPAREN)
			break;
		else
		{
			stx_error (ERR_COMMAORRPARENEXP);
			return FALSE;
		}
		ref0 = ref1;
	}
	advancewindow ();
	masktrip->operand[0] = put_ilit (mask);
	counttrip->operand[0] = put_ilit (parmcount);
	parmcount += 2;
	*opr = put_tref (masktrip);
	return parmcount;
}