1 module zua.parser.ast;
2 import zua.parser.lexer;
3 import zua.compiler.ir : BinaryOperation, UnaryOperation;
4 import std.typecons;
5 import std.variant;
6 
7 /** Represents a single AST node */
8 abstract class AstNode {
9 	/** The range of tokens that represent this AST node */
10 	Token start;
11 	Token end; /// ditto
12 }
13 
14 /** A statement */
15 abstract class Stat : AstNode {}
16 
17 /** An erroneous statement */
18 final class ErrorStat : Stat {}
19 
20 /** An assignment statement */
21 final class AssignStat : Stat {
22 	/** A list of lvalues to modify */
23 	LvalueExpr[] keys;
24 
25 	/** The values to set each variable to */
26 	Expr[] values;
27 }
28 
29 /** An expression statement */
30 final class ExprStat : Stat {
31 	/** The expression to evaluate in this statement */
32 	Expr expr;
33 }
34 
35 /** A block statement */
36 final class Block : Stat {
37 	/** A list of statements to be executed by this block */
38 	Stat[] body;
39 }
40 
41 /** A local variable declaration statement */
42 final class DeclarationStat : Stat {
43 	/** A list of variables to declare */
44 	string[] keys;
45 
46 	/** The values to set each variable to */
47 	Expr[] values;
48 }
49 
50 /** A local function declaration statement */
51 final class FunctionDeclarationStat : Stat {
52 	/** The variable to declare */
53 	string key;
54 
55 	/** The value to assign it */
56 	FunctionExpr value;
57 }
58 
59 /** A while statement */
60 final class WhileStat : Stat {
61 	/** The condition for this while statement */
62 	Expr cond;
63 
64 	/** The body of this while statement */
65 	Block body;
66 }
67 
68 /** A repeat statement */
69 final class RepeatStat : Stat {
70 	/** The end condition for this repeat statement */
71 	Expr endCond;
72 
73 	/** The body of this repeat statement */
74 	Block body;
75 }
76 
77 alias IfEntry = Tuple!(Expr, "cond", Block, "body");
78 
79 /** An if statement */
80 final class IfStat : Stat {
81 	/** The various condition-code pairs in this if statement */
82 	IfEntry[] entries;
83 
84 	/** The 'else' body of this if statement */
85 	Nullable!Block elseBody;
86 }
87 
88 /** A numeric for loop */
89 final class NumericForStat : Stat {
90 	/** The variable to use in this for loop */
91 	string var;
92 
93 	/** Defines the range to loop over */
94 	Expr low;
95 	Expr high; /// ditto
96 	Nullable!Expr step; /// ditto
97 
98 	/** The body of the for loop */
99 	Block body;
100 }
101 
102 /** A foreach loop */
103 final class ForeachStat : Stat {
104 	/** The variables to use in this for loop */
105 	string[] vars;
106 
107 	/** Defines the iterator to loop over */
108 	Expr[] iter;
109 
110 	/** The body of the for loop */
111 	Block body;
112 }
113 
114 /** A return statement */
115 final class ReturnStat : Stat {
116 	/** The values to return */
117 	Expr[] values;
118 }
119 
120 /** A type of atomic statement */
121 enum AtomicStatType {
122 	Break
123 }
124 
125 /** An atomic statement */
126 final class AtomicStat : Stat {
127 	/** The type of atomic statement this represents */
128 	AtomicStatType type;
129 }
130 
131 /** An expression */
132 abstract class Expr : AstNode {}
133 
134 /** An erroneous expression */
135 final class ErrorExpr : LvalueExpr {}
136 
137 /** A prefix expression */
138 abstract class PrefixExpr : Expr {}
139 
140 /** An expression whose value can be set */
141 abstract class LvalueExpr : PrefixExpr {}
142 
143 /** A variable expression */
144 final class VariableExpr : LvalueExpr {
145 	/** The name of this variable */
146 	string name;
147 }
148 
149 /** An index expression */
150 final class IndexExpr : LvalueExpr {
151 	/** The object to index */
152 	Expr base;
153 
154 	/** The key to use in indexing the given object */
155 	Expr key;
156 }
157 
158 /** A bracket expression */
159 final class BracketExpr : PrefixExpr {
160 	/** The expression in the bracket expression */
161 	Expr expr;
162 }
163 
164 /** A function call expression */
165 final class CallExpr : PrefixExpr {
166 	Expr base; /** The base of the call expression */
167 	Expr[] args; /** The arguments to use in the call */
168 
169 	/**
170 	 * The method name to use in the call.
171 	 * If supplied, the call is a selfcall, i.e. 'base:method(args)' is called.
172 	 * Otherwise, 'base' is treated as a function, i.e. 'base(args)' is called.
173 	 */
174 	Nullable!string method;
175 }
176 
177 /** A type of atomic expression */
178 enum AtomicExprType {
179 	Nil,
180 	False,
181 	True,
182 	VariadicTuple
183 }
184 
185 /** An atomic expression */
186 final class AtomicExpr : Expr {
187 	/** The type of atomic expression this represents */
188 	AtomicExprType type;
189 }
190 
191 /** A number expression */
192 final class NumberExpr : Expr {
193 	/** The value of this expression */
194 	double value;
195 }
196 
197 /** A string expression */
198 final class StringExpr : Expr {
199 	/** The value of this expression */
200 	string value;
201 }
202 
203 /** A function expression */
204 final class FunctionExpr : Expr {
205 	/** A list of argument names */
206 	string[] args;
207 
208 	/** Determines if the function is variadic */
209 	bool variadic;
210 
211 	/** The body of the function */
212 	Block body;
213 }
214 
215 /** A binary operation expression */
216 final class BinaryExpr : Expr {
217 	/** The token representing this operation */
218 	Token opToken;
219 
220 	/** The operation performed on the two sides */
221 	BinaryOperation op;
222 
223 	Expr lhs; /** The left-hand side of the expression */
224 	Expr rhs; /** The right-hand side of the expression */
225 }
226 
227 /** A unary operation expression */
228 final class UnaryExpr : Expr {
229 	/** The operation performed on the given expression */
230 	UnaryOperation op;
231 
232 	/** The expression to manipulate using the given unary operation */
233 	Expr expr;
234 }
235 
236 /** A single field in a table */
237 struct TableField {
238 	/** The key component of this field */
239 	Expr key;
240 
241 	/** The value component of this field */
242 	Expr value;
243 }
244 
245 alias FieldEntry = Algebraic!(TableField, Expr);
246 
247 /** A table constructor expression */
248 final class TableExpr : Expr {
249 	/** A list of fields in the table */
250 	FieldEntry[] fields;
251 }