Example #1
0
void MemberAccessAST::generateCode(CodeGenerator& codeGen, GeneratedFunction& func) {
	auto memberName = getMemberName();
	auto typeRef = mAccessExpression->expressionType(codeGen.typeChecker());

	//Special handling of the 'length' field on arrays.
	if (memberName == "length" && std::dynamic_pointer_cast<ArrayType>(typeRef)) {
		mAccessExpression->generateCode(codeGen, func);
		func.addInstruction("LDLEN");
	} else {
		auto classTypeRef = std::dynamic_pointer_cast<ClassType>(typeRef);
		mAccessExpression->generateCode(codeGen, func);
		func.addInstruction("LDFIELD " + classTypeRef->vmClassName() + "::" + memberName);

		if (auto arrayMember = std::dynamic_pointer_cast<ArrayAccessAST>(mMemberExpression)) {
			arrayMember->generateCode(codeGen, func, expressionType(codeGen.typeChecker()));
		}
	}
}
Example #2
0
void Expression::expressionValue( QString expr, BTreeBase */*tree*/, BTreeNode *node)
{
	/* The "end of the line" for the expression parsing, the
	expression has been broken down into the fundamental elements of expr.value()=="to"||
	variable, number, special etc... so we now just set value and type */
	
	
	
	/* Alternatively we might have a function call
	e.g. somefunction(3,potatoes,hairstyle + 6)
	In which case we need to call back to parseExpr to process the arguments,
	saving them on the basic stack then  making the function call.
	Of course we also need to mark the terminal node type as a function.
	*/
	expr = expr.trimmed();
	
	// My intention is so that these error checks are ordered
	// so that e.g. for x = 3 it picks up the = rather than the spaces first.
	
	
	expr = mb->alias(expr);
	ExprType t = expressionType(expr);

	
	// See if it is a single qouted character, e.g. 'A'
	if( expr.left(1) == "\'" && expr.right(1) == "\'" ) 
	{
		if( expr.length() == 3 ) // fall through to report as unknown variable if not of form 'x'
		{
			// If so, turn it into a number, and use the ASCII code as the value
			t = number;
			expr =  QString::number(expr[1].toLatin1());
		}
	}
	
	// Check for the most common mistake ever!
	if(expr.contains("="))
		mistake( Microbe::InvalidEquals );
	// Check for reserved keywords
	if(expr=="to"||expr=="step"||expr=="then")
		mistake( Microbe::ReservedKeyword, expr );

	// Check for empty expressions, or expressions contating spaces
	// both indicating a Mistake.
	if(expr.isEmpty())
		mistake( Microbe::ConsecutiveOperators );
	else if(expr.contains(QRegExp("\\s")) && t!= extpin)
		mistake( Microbe::MissingOperator );

//***************modified isValidRegister is included ***********************//	

	if( t == variable && !mb->isVariableKnown(expr) && !m_pic->isValidPort( expr ) && !m_pic->isValidTris( expr )&&!m_pic->isValidRegister( expr ) )
		mistake( Microbe::UnknownVariable, expr );

//modification ends

	if ( mb->isVariableKnown(expr) && !mb->variable(expr).isReadable() )
		mistake( Microbe::WriteOnlyVariable, expr );
	
	node->setType(t);
	
	// Since we currently only implement 8 bit unsigned integers, we should disallow
	// anything outside the range [0-255].
	if( t == number && !m_bSupressNumberTooBig && (expr.toInt() > 255) )
	{
		mistake( Microbe::NumberTooBig );
	}
	
	// if there was a pin, we need to decocde it.
	// For now and sacrificing syntax error checking
	// we just look for the word "is" then "high" or "low".
	if( t == extpin )
	{
		bool NOT;
		int i = expr.indexOf("is");
		if(i > 0)
		{
			NOT = expr.contains("low");
			if(!expr.contains("high") && !expr.contains("low"))
				mistake( Microbe::HighLowExpected, expr );
			expr = expr.left(i-1);
		}
		else NOT = false;
		node->setChildOp(NOT?notpin:pin);
	}
	
	else if ( t == keypad )
		node->setChildOp( read_keypad );
	
	node->setValue(expr);
}