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)); }
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."); } }