Exemplo n.º 1
0
void MultiDimArrayDeclarationAST::generateCode(CodeGenerator& codeGen, GeneratedFunction& func) {
	if (mLengthExpressions.size() > 2) {
		codeGen.codeGenError("Array creation of dimension larger than 2 is not supported.");
	}

	auto& typeChecker = codeGen.typeChecker();

	int outerLocal = func.newLocal("$local$_outer_" + std::to_string(func.numLocals()), typeChecker.findType(typeString()));
	int subArrayLocal = func.newLocal("$local$_sub_" + std::to_string(func.numLocals()), typeChecker.findType("Int"));

	//Create the outer array
	mLengthExpressions.at(0)->generateCode(codeGen, func);
	func.addInstruction("NEWARR " + typeChecker.findType(typeString(mLengthExpressions.size() - 1))->vmType());
	func.addInstruction("STLOC " + std::to_string(outerLocal));

	int condStart = func.numInstructions();
	int condIndex = -1;

	//Condition
	mLengthExpressions.at(0)->generateCode(codeGen, func);
	func.addInstruction("LDLOC " + std::to_string(subArrayLocal));
	condIndex = func.numInstructions();
	func.addInstruction("BLE");

	//Body
	func.addInstruction("LDLOC " + std::to_string(outerLocal));
	func.addInstruction("LDLOC " + std::to_string(subArrayLocal));
	mLengthExpressions.at(1)->generateCode(codeGen, func);
	func.addInstruction("NEWARR " + typeChecker.findType(typeString(mLengthExpressions.size() - 2))->vmType());

	func.addInstruction("STELEM " + typeChecker.findType(typeString(mLengthExpressions.size() - 1))->vmType());

	func.addInstruction("LDLOC " + std::to_string(subArrayLocal));
	func.addInstruction("LDINT 1");
	func.addInstruction("ADD");
	func.addInstruction("STLOC " + std::to_string(subArrayLocal));

	func.addInstruction("BR " + std::to_string(condStart));
	func.instruction(condIndex) += " " + std::to_string(func.numInstructions());

	func.addInstruction("LDLOC " + std::to_string(outerLocal));
}
Exemplo n.º 2
0
void BinaryOpExpressionAST::generateCode(CodeGenerator& codeGen, GeneratedFunction& func) {
	if (mOp == Operator('+')) {
		generateSidesCode(codeGen, func);
		func.addInstruction("ADD");
	} else if (mOp == Operator('-')) {
		generateSidesCode(codeGen, func);
		func.addInstruction("SUB");
	} else if (mOp == Operator('*')) {
		generateSidesCode(codeGen, func);
		func.addInstruction("MUL");
	} else if (mOp == Operator('/')) {
		generateSidesCode(codeGen, func);
		func.addInstruction("DIV");
	} else if (mOp == Operator('=')) {
		if (auto varDec = std::dynamic_pointer_cast<VariableDeclarationExpressionAST>(mLeftHandSide)) {
			auto varRefSymbol = std::dynamic_pointer_cast<VariableSymbol>(mSymbolTable->find(varDec->name()));
			generateSidesCode(codeGen, func);
			func.addInstruction("STLOC " + std::to_string(func.getLocal(varRefSymbol).first));
		} else if (auto varRef = std::dynamic_pointer_cast<VariableReferenceExpressionAST>(mLeftHandSide)) {
			mRightHandSide->generateCode(codeGen, func);
			auto varRefSymbol = std::dynamic_pointer_cast<VariableSymbol>(mSymbolTable->find(varRef->name()));

			if (varRefSymbol->attribute() != VariableSymbolAttribute::FUNCTION_PARAMETER) {
				func.addInstruction("STLOC " + std::to_string(func.getLocal(varRefSymbol).first));
			}
		}
	} else if(mOp == Operator('=', '=')) {
		generateSidesCode(codeGen, func);
		func.addInstruction("CMPEQ");
	} else if(mOp == Operator('!', '=')) {
		generateSidesCode(codeGen, func);
		func.addInstruction("CMPNE");
	} else if(mOp == Operator('>')) {
		generateSidesCode(codeGen, func);
		func.addInstruction("CMPGT");
	} else if(mOp == Operator('>', '=')) {
		generateSidesCode(codeGen, func);
		func.addInstruction("CMPGE");
	} else if(mOp == Operator('<')) {
		generateSidesCode(codeGen, func);
		func.addInstruction("CMPLT");
	} else if(mOp == Operator('<', '=')) {
		generateSidesCode(codeGen, func);
		func.addInstruction("CMPLE");
	} else if(mOp == Operator('&', '&')) {
		//Generate with short circuit
		int resLocal = func.newLocal("$tmp$_" + std::to_string(func.numLocals()), codeGen.typeChecker().findType("Bool"));

		mLeftHandSide->generateCode(codeGen, func);
		func.addInstruction("LDTRUE");
		int branchIndex = func.numInstructions();
		func.addInstruction("BNE ");

		mRightHandSide->generateCode(codeGen, func);
		func.addStoreLocal(resLocal);

		int skipIndex = func.numInstructions();
		func.addInstruction("BR ");
		func.instruction(branchIndex) += std::to_string(func.numInstructions());
		func.addInstruction("LDFALSE");
		func.addStoreLocal(resLocal);
		func.instruction(skipIndex) += std::to_string(func.numInstructions());

		func.addLoadLocal(resLocal);
	} else if(mOp == Operator('|', '|')) {
		//Generate with short circuit
		int resLocal = func.newLocal("$tmp$_" + std::to_string(func.numLocals()), codeGen.typeChecker().findType("Bool"));

		mLeftHandSide->generateCode(codeGen, func);
		func.addInstruction("LDTRUE");
		int branchIndex = func.numInstructions();
		func.addInstruction("BEQ ");

		mRightHandSide->generateCode(codeGen, func);
		func.addStoreLocal(resLocal);

		int skipIndex = func.numInstructions();
		func.addInstruction("BR ");
		func.instruction(branchIndex) += std::to_string(func.numInstructions());
		func.addInstruction("LDTRUE");
		func.addStoreLocal(resLocal);
		func.instruction(skipIndex) += std::to_string(func.numInstructions());

		func.addLoadLocal(resLocal);
	} else {
		codeGen.codeGenError("Operator '" + mOp.asString() + "' is not defined.");
	}
}