Ejemplo n.º 1
0
def_t *PR_Expression (int priority)
{
	opcode_t	*op, *oldop;
	def_t		*e, *e2;
	etype_t		type_a, type_b, type_c;
	
	if (priority == 0)
		return PR_Term ();
		
	e = PR_Expression (priority-1);
		
	while (1)
	{
		if (priority == 1 && PR_Check ("(") )
			return PR_ParseFunctionCall (e);

		for (op=pr_opcodes ; op->name ; op++)
		{
			if (op->priority != priority)
				continue;
			if (!PR_Check (op->name))
				continue;
			if ( op->right_associative )
			{
			// if last statement is an indirect, change it to an address of
				if ( (unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 )
				{
					statements[numstatements-1].op = OP_ADDRESS;
					def_pointer.type->aux_type = e->type;
					e->type = def_pointer.type;
				}
				e2 = PR_Expression (priority);
			}
			else
				e2 = PR_Expression (priority-1);
				
		// type check
			type_a = e->type->type;
			type_b = e2->type->type;

			if (op->name[0] == '.')// field access gets type from field
			{
				if (e2->type->aux_type)
					type_c = e2->type->aux_type->type;
				else
					type_c = -1;	// not a field
			}
			else
				type_c = ev_void;
				
			oldop = op;
			while (type_a != op->type_a->type->type
			|| type_b != op->type_b->type->type
			|| (type_c != ev_void && type_c != op->type_c->type->type) )
			{
				op++;
				if (!op->name || strcmp (op->name , oldop->name))
					PR_ParseError ("type mismatch for %s", oldop->name);
			}
			
			if (type_a == ev_pointer && type_b != e->type->aux_type->type)
				PR_ParseError ("type mismatch for %s", op->name);
			
			
			if (op->right_associative)
				e = PR_Statement (op, e2, e);
			else
				e = PR_Statement (op, e, e2);
			
			if (type_c != ev_void)	// field access gets type from field
				e->type = e2->type->aux_type;
			
			break;
		}
		if (!op->name)
			break;	// next token isn't at this priority level
	}
	
	return e;
}
Ejemplo n.º 2
0
/*
==============
PR_Expression
==============
*/
def_t *PR_Expression (int priority)
{
	opcode_t	*op, *oldop;
	def_t		*e, *e2;
	etype_t		type_a, type_b, type_c;

	if (priority == 0)
		return PR_Term ();

	e = PR_Expression (priority-1);

	while (1)
	{
		if (priority == 1 && PR_Check ("(") )
			return PR_ParseFunctionCall (e);

		for (op=pr_opcodes ; op->name ; op++)
		{
			if (op->priority != priority)
				continue;
			if (!PR_Check (op->name))
				continue;

			if (op->name[0] == '.')
			{
				char *name = PR_ParseName ();

				if (e->type != &type_entity)
					PR_ParseError ("left of '.%s' must have entity type", name);

				e2 = PR_FindDef (name, pr_scope);
				if (!e2 || e2->type->type != ev_field)
					PR_ParseError ("'%s' is not a field", name);

				type_c = e2->type->aux_type->type;

				// we still allow ".void foo" so need to check
				if (type_c == ev_void)
					PR_ParseError ("tried to access a 'void' field");

				assert (type_c != ev_pointer && type_c != ev_void);
				while (type_c != op->type_c) {
					op++;
					assert (op->name);
				}

				e = PR_Statement (op, e, e2);

				// field access gets type from field
				e->type = e2->type->aux_type;
				break;
			}

			if (op->right_associative)
			{
				if (e->type->constant)
					PR_ParseError ("assignment to constant");

			// if last statement is an indirect, change it to an address of
				if ( (unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 )
				{
					statements[numstatements-1].op = (unsigned short)OP_ADDRESS;
					def_pointer.type->aux_type = e->type;
					e->type = def_pointer.type;
				}
				e2 = PR_Expression (priority);
			}
			else
				e2 = PR_Expression (priority-1);

		// type check
			type_a = e->type->type;
			type_b = e2->type->type;

			oldop = op;
			while (type_a != op->type_a || type_b != op->type_b )
			{
				op++;
				if (!op->name || strcmp (op->name , oldop->name))
					PR_ParseError ("type mismatch for %s", oldop->name);
			}

			if (type_a == ev_pointer && type_b != e->type->aux_type->type)
				PR_ParseError ("type mismatch for %s", op->name);

#if 0
			if (e->type->constant && e2->type->constant) {
				// try to calculate the expression at compile time
				eval_t result;
				if (PR_Calc(op - pr_opcodes, (eval_t *)(pr_globals + e->ofs),
						(eval_t *)(pr_globals + e2->ofs), &result))
				{
//					printf ("line %i: folding %s %s %s into %s\n", pr_source_line, e->name, op->name, e2->name,
//						PR_ValueString(op->type_c, &val));

					type_t *resulttype;
					switch (op->type_c) {
						case ev_float: resulttype = &type_const_float; break;
						//case ev_string: resulttype = &type_const_string; break;
						case ev_vector: resulttype = &type_const_vector; break;
						default: assert (false);
					}

					e = PR_GetImmediate (resulttype, result);
					break;
				}
			}
#endif

			if (op->right_associative)
				e = PR_Statement (op, e2, e);
			else
				e = PR_Statement (op, e, e2);

			break;
		}
		if (!op->name)
			break;	// next token isn't at this priority level
	}

	return e;
}