|
6 | 6 | using System.Collections.Generic; |
7 | 7 | using System.Linq; |
8 | 8 | using Antlr4.Runtime.Misc; |
| 9 | +using Antlr4.Runtime.Tree; |
9 | 10 | using Kaleidoscope.Grammar; |
10 | 11 | using Llvm.NET; |
11 | 12 | using Llvm.NET.Instructions; |
@@ -64,22 +65,67 @@ public override Value VisitVariableExpression( [NotNull] VariableExpressionConte |
64 | 65 | string varName = context.Name; |
65 | 66 | if( !NamedValues.TryGetValue( varName, out Value value ) ) |
66 | 67 | { |
67 | | - throw new ArgumentException( "Unknown variable name", nameof( context ) ); |
| 68 | + throw new CodeGeneratorException( $"Unknown variable name: {context}" ); |
68 | 69 | } |
69 | 70 |
|
70 | 71 | return value; |
71 | 72 | } |
72 | 73 |
|
73 | | - public override Value VisitBinaryOpExpression( [NotNull] BinaryOpExpressionContext context ) |
| 74 | + public override Value VisitFunctionCallExpression( [NotNull] FunctionCallExpressionContext context ) |
| 75 | + { |
| 76 | + var function = GetFunction( context.CaleeName ); |
| 77 | + if( function == null ) |
| 78 | + { |
| 79 | + throw new CodeGeneratorException( $"function '{context.CaleeName}' is unknown" ); |
| 80 | + } |
| 81 | + |
| 82 | + var args = context.Args.Select( ctx => ctx.Accept( this ) ).ToArray( ); |
| 83 | + return InstructionBuilder.Call( function, args ).RegisterName( "calltmp" ); |
| 84 | + } |
| 85 | + |
| 86 | + public override Value VisitFunctionPrototype( [NotNull] FunctionPrototypeContext context ) |
| 87 | + { |
| 88 | + return GetOrDeclareFunction( new Prototype( context ) ); |
| 89 | + } |
| 90 | + |
| 91 | + public override Value VisitFunctionDefinition( [NotNull] FunctionDefinitionContext context ) |
| 92 | + { |
| 93 | + return DefineFunction( ( Function )context.Signature.Accept( this ) |
| 94 | + , context.BodyExpression |
| 95 | + ); |
| 96 | + } |
| 97 | + |
| 98 | + public override Value VisitTopLevelExpression( [NotNull] TopLevelExpressionContext context ) |
| 99 | + { |
| 100 | + var function = GetOrDeclareFunction( new Prototype( $"anon_expr_{AnonNameIndex++}" ) ); |
| 101 | + |
| 102 | + return DefineFunction( function, context.expression() ); |
| 103 | + } |
| 104 | + |
| 105 | + public override Value VisitExpression( [NotNull] ExpressionContext context ) |
| 106 | + { |
| 107 | + // Expression: PrimaryExpression (op expression)* |
| 108 | + // the sub-expressions are in evaluation order |
| 109 | + var lhs = context.primaryExpression( ).Accept( this ); |
| 110 | + foreach( var (op, rhs) in context.OperatorExpressions ) |
| 111 | + { |
| 112 | + lhs = EmitBinaryOperator( lhs, op, rhs ); |
| 113 | + } |
| 114 | + |
| 115 | + return lhs; |
| 116 | + } |
| 117 | + |
| 118 | + protected override Value DefaultResult => null; |
| 119 | + |
| 120 | + private Value EmitBinaryOperator( Value lhs, OpsymbolContext opSymbol, IParseTree rightTree ) |
74 | 121 | { |
75 | | - var lhs = context.Lhs.Accept( this ); |
76 | | - var rhs = context.Rhs.Accept( this ); |
| 122 | + var rhs = rightTree.Accept( this ); |
77 | 123 | if( lhs == null || rhs == null ) |
78 | 124 | { |
79 | 125 | return null; |
80 | 126 | } |
81 | 127 |
|
82 | | - switch( context.Op ) |
| 128 | + switch( opSymbol.Op ) |
83 | 129 | { |
84 | 130 | case '<': |
85 | 131 | { |
@@ -109,43 +155,10 @@ public override Value VisitBinaryOpExpression( [NotNull] BinaryOpExpressionConte |
109 | 155 | return InstructionBuilder.FDiv( lhs, rhs ).RegisterName( "divtmp" ); |
110 | 156 |
|
111 | 157 | default: |
112 | | - throw new ArgumentException( $"Invalid binary operator {context.Op}", nameof( context ) ); |
113 | | - } |
114 | | - } |
115 | | - |
116 | | - public override Value VisitFunctionCallExpression( [NotNull] FunctionCallExpressionContext context ) |
117 | | - { |
118 | | - var function = GetFunction( context.CaleeName ); |
119 | | - if( function == null ) |
120 | | - { |
121 | | - throw new ArgumentException( $"Unknown function reference {context.CaleeName}", nameof( context ) ); |
| 158 | + throw new CodeGeneratorException( $"Invalid binary operator {opSymbol.Op}" ); |
122 | 159 | } |
123 | | - |
124 | | - var args = context.Args.Select( ctx => ctx.Accept( this ) ).ToArray( ); |
125 | | - return InstructionBuilder.Call( function, args ).RegisterName( "calltmp" ); |
126 | 160 | } |
127 | 161 |
|
128 | | - public override Value VisitFunctionPrototype( [NotNull] FunctionPrototypeContext context ) |
129 | | - { |
130 | | - return GetOrDeclareFunction( new Prototype( context ) ); |
131 | | - } |
132 | | - |
133 | | - public override Value VisitFunctionDefinition( [NotNull] FunctionDefinitionContext context ) |
134 | | - { |
135 | | - return DefineFunction( ( Function )context.Signature.Accept( this ) |
136 | | - , context.BodyExpression |
137 | | - ); |
138 | | - } |
139 | | - |
140 | | - public override Value VisitTopLevelExpression( [NotNull] TopLevelExpressionContext context ) |
141 | | - { |
142 | | - var function = GetOrDeclareFunction( new Prototype( $"anon_expr_{AnonNameIndex++}" ) ); |
143 | | - |
144 | | - return DefineFunction( function, context.expression() ); |
145 | | - } |
146 | | - |
147 | | - protected override Value DefaultResult => null; |
148 | | - |
149 | 162 | private Function GetFunction( string name ) |
150 | 163 | { |
151 | 164 | return Module.GetFunction( name ); |
@@ -178,7 +191,7 @@ private Function DefineFunction( Function function, ExpressionContext body ) |
178 | 191 | { |
179 | 192 | if( !function.IsDeclaration ) |
180 | 193 | { |
181 | | - throw new ArgumentException( $"Function {function.Name} cannot be redefined", nameof( function ) ); |
| 194 | + throw new CodeGeneratorException( $"Function {function.Name} cannot be redefined in the same module" ); |
182 | 195 | } |
183 | 196 |
|
184 | 197 | var basicBlock = function.AppendBasicBlock( "entry" ); |
|
0 commit comments