evaluate method
- SymbolTable table
override
Evaluates this AST node and generates corresponding LLVM IR code.
This is the main method that each AST node must implement to:
- Perform semantic analysis (type checking, symbol resolution)
- Generate LLVM IR instructions for the node's operation
- Return the result value (if this is an expression)
Parameters:
table
: The current symbol table for variable and function lookups
Returns: The result of evaluating this node (type depends on node type)
Throws:
- Exception for semantic errors (undefined variables, type mismatches, etc.)
- Various specific exceptions for different error conditions
Note: The base implementation throws "Not implemented" - concrete subclasses must override this method with their specific evaluation logic.
Implementation
@override
LangVal evaluate(SymbolTable table) {
var leftResult = left.evaluate(table);
var rightResult = right.evaluate(table);
// cant be array
if (leftResult.type is ArrayType || rightResult.type is ArrayType) {
throw Exception("Cannot apply binary operator to array");
}
if (leftResult.type != rightResult.type) {
if (leftResult.type.primitiveType == PrimitiveTypes.float) {
Node.addIrLine(
"%conv.$id = sitofp i64 ${rightResult.regName} to double");
rightResult =
LangVal("%conv.$id", const PrimitiveType(PrimitiveTypes.float));
} else {
Node.addIrLine(
"%conv.$id = sitofp i64 ${leftResult.regName} to double");
leftResult =
LangVal("%conv.$id", const PrimitiveType(PrimitiveTypes.float));
}
}
if (leftResult.type.primitiveType == PrimitiveTypes.float) {
switch (nodeValue) {
case MathOp.add:
Node.addIrLine(
"%binOp.$id = fadd double ${leftResult.regName}, ${rightResult.regName}");
return LangVal("%binOp.$id", leftResult.type);
case MathOp.sub:
Node.addIrLine(
"%binOp.$id = fsub double ${leftResult.regName}, ${rightResult.regName}");
return LangVal("%binOp.$id", leftResult.type);
case MathOp.mul:
Node.addIrLine(
"%binOp.$id = fmul double ${leftResult.regName}, ${rightResult.regName}");
return LangVal("%binOp.$id", leftResult.type);
case MathOp.div:
Node.addIrLine(
"%binOp.$id = fdiv double ${leftResult.regName}, ${rightResult.regName}");
return LangVal("%binOp.$id", leftResult.type);
default:
throw Exception("Unknown operator: $nodeValue");
}
}
switch (nodeValue) {
case MathOp.add:
Node.addIrLine(
"%binOp.$id = add ${leftResult.type.irType} ${leftResult.regName}, ${rightResult.regName}");
return LangVal("%binOp.$id", leftResult.type);
case MathOp.sub:
Node.addIrLine(
"%binOp.$id = sub ${leftResult.type.irType} ${leftResult.regName}, ${rightResult.regName}");
return LangVal("%binOp.$id", leftResult.type);
case MathOp.mul:
Node.addIrLine(
"%binOp.$id = mul ${leftResult.type.irType} ${leftResult.regName}, ${rightResult.regName}");
return LangVal("%binOp.$id", leftResult.type);
case MathOp.div:
Node.addIrLine(
"%binOp.$id = sdiv ${leftResult.type.irType} ${leftResult.regName}, ${rightResult.regName}");
return LangVal("%binOp.$id", leftResult.type);
case MathOp.mod:
Node.addIrLine(
"%binOp.$id = srem ${leftResult.type.irType} ${leftResult.regName}, ${rightResult.regName}");
return LangVal("%binOp.$id", leftResult.type);
default:
throw Exception("Unknown operator: $nodeValue");
}
}