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
void evaluate(SymbolTable table) {
final strLiteral = literal.evaluate(table);
List<(String, String)> irLines = [];
for (var identifier in identifiers) {
var varData = table.get(identifier.nodeValue);
if (varData == null) {
throw Exception("Variable ${identifier.nodeValue} not found");
}
String ptr = varData.ptrName;
if (varData.type is ArrayType && identifier is !IndexedIdentifierNode) {
throw Exception("Cannot scan into array");
}
if (varData.type is! ArrayType && identifier is IndexedIdentifierNode) {
throw Exception("Cannot index non-array");
}
if (varData.type is ArrayType) {
final indexedId = identifier as IndexedIdentifierNode;
final indexResult = indexedId.index.evaluate(table);
if (indexResult.type.primitiveType != PrimitiveTypes.int) {
throw Exception("Index must be int");
}
Node.addIrLine(
"%arrayPtr.${identifier.id} = getelementptr ${varData.type.primitiveType.irType}, ${varData.type.irType} ${varData.ptrName}, i64 ${indexResult.regName}");
ptr = "%arrayPtr.${identifier.id}";
}
irLines.add((ptr, varData.type.primitiveType.irType));
}
final childrenStr = irLines.map((e) => "${e.$2}* ${e.$1}").join(", ");
Node.addIrLine(
"call i32 (i8*, ...) @scanf(i8* $strLiteral, $childrenStr)");
}