Problem
Several AST node fields are marked `mutable` to allow the typechecker to annotate them:
// In ast.hpp
struct FunctionCall : ASTNode {
string name;
vector<unique_ptr<ASTNode>> args;
mutable string resolved_struct; // Set by type checker
};
struct MethodCall : ASTNode {
unique_ptr<ASTNode> object;
string method_name;
vector<unique_ptr<ASTNode>> args;
mutable string object_type; // Set by type checker
};
struct VariableDecl : ASTNode {
mutable string type; // May be updated by typechecker
// ...
};
This breaks const-correctness and makes it unclear when/where these fields are set.
Current Pattern
- Parser creates AST nodes with some fields empty
- Typechecker fills in mutable fields during analysis
- Codegen reads all fields
This creates implicit coupling between phases.
Suggested Solution
Option 1: Separate annotation data
struct TypeCheckAnnotations {
map<const ASTNode*, string> object_types;
map<const FunctionCall*, string> resolved_structs;
map<const VariableDecl*, string> inferred_types;
};
string codegen::generate(const Program& prog, const TypeCheckAnnotations& annotations);
Option 2: Create annotated AST types
struct TypedMethodCall {
const MethodCall& call;
string object_type;
};
Option 3: Document the contract (minimal change)
Add clear documentation about which fields are parser-set vs typechecker-set.
Impact
- Cleaner phase separation
- Easier to reason about data flow
- Potential for parallel type checking
Problem
Several AST node fields are marked `mutable` to allow the typechecker to annotate them:
This breaks const-correctness and makes it unclear when/where these fields are set.
Current Pattern
This creates implicit coupling between phases.
Suggested Solution
Option 1: Separate annotation data
Option 2: Create annotated AST types
Option 3: Document the contract (minimal change)
Add clear documentation about which fields are parser-set vs typechecker-set.
Impact