1 #pragma once
2 
3 #include <string>
4 #include <vector>
5 #include "value.h"
6 #include "memory.h"
7 #include "boost-utils.h"
8 #include "Assignment.h"
9 
10 class Expression : public ASTNode
11 {
12 public:
Expression(const Location & loc)13 	Expression(const Location &loc) : ASTNode(loc) {}
~Expression()14 	~Expression() {}
15 	virtual bool isLiteral() const;
16 	virtual Value evaluate(const std::shared_ptr<Context>& context) const = 0;
17 	Value checkUndef(Value&& val, const std::shared_ptr<Context>& context) const;
18 };
19 
20 class UnaryOp : public Expression
21 {
22 public:
23 	enum class Op {
24 		Not,
25 		Negate
26 	};
27 	bool isLiteral() const override;
28 	UnaryOp(Op op, Expression *expr, const Location &loc);
29 	Value evaluate(const std::shared_ptr<Context>& context) const override;
30 	void print(std::ostream &stream, const std::string &indent) const override;
31 
32 private:
33 	const char *opString() const;
34 
35 	Op op;
36 	shared_ptr<Expression> expr;
37 };
38 
39 class BinaryOp : public Expression
40 {
41 public:
42 	enum class Op {
43 		LogicalAnd,
44 		LogicalOr,
45 		Exponent,
46 		Multiply,
47 		Divide,
48 		Modulo,
49 		Plus,
50 		Minus,
51 		Less,
52 		LessEqual,
53 		Greater,
54 		GreaterEqual,
55 		Equal,
56 		NotEqual
57 	};
58 
59 	BinaryOp(Expression *left, Op op, Expression *right, const Location &loc);
60 	Value evaluate(const std::shared_ptr<Context>& context) const override;
61 	void print(std::ostream &stream, const std::string &indent) const override;
62 
63 private:
64 	const char *opString() const;
65 
66 	Op op;
67 	shared_ptr<Expression> left;
68 	shared_ptr<Expression> right;
69 };
70 
71 class TernaryOp : public Expression
72 {
73 public:
74 	TernaryOp(Expression *cond, Expression *ifexpr, Expression *elseexpr, const Location &loc);
75 	const shared_ptr<Expression>& evaluateStep(const std::shared_ptr<Context>& context) const;
76 	Value evaluate(const std::shared_ptr<Context>& context) const override;
77 	void print(std::ostream &stream, const std::string &indent) const override;
78 private:
79 	shared_ptr<Expression> cond;
80 	shared_ptr<Expression> ifexpr;
81 	shared_ptr<Expression> elseexpr;
82 };
83 
84 class ArrayLookup : public Expression
85 {
86 public:
87 	ArrayLookup(Expression *array, Expression *index, const Location &loc);
88 	Value evaluate(const std::shared_ptr<Context>& context) const override;
89 	void print(std::ostream &stream, const std::string &indent) const override;
90 private:
91 	shared_ptr<Expression> array;
92 	shared_ptr<Expression> index;
93 };
94 
95 class Literal : public Expression
96 {
97 public:
98 	Literal(Value val, const Location &loc = Location::NONE);
99 	Value evaluate(const std::shared_ptr<Context>& context) const override;
100 	void print(std::ostream &stream, const std::string &indent) const override;
isLiteral()101 	bool isLiteral() const override { return true;}
102 private:
103 	const Value value;
104 };
105 
106 class Range : public Expression
107 {
108 public:
109 	Range(Expression *begin, Expression *end, const Location &loc);
110 	Range(Expression *begin, Expression *step, Expression *end, const Location &loc);
111 	Value evaluate(const std::shared_ptr<Context>& context) const override;
112 	void print(std::ostream &stream, const std::string &indent) const override;
113 	bool isLiteral() const override;
114 private:
115 	shared_ptr<Expression> begin;
116 	shared_ptr<Expression> step;
117 	shared_ptr<Expression> end;
118 };
119 
120 class Vector : public Expression
121 {
122 public:
123 	Vector(const Location &loc);
124 	Value evaluate(const std::shared_ptr<Context>& context) const override;
125 	void print(std::ostream &stream, const std::string &indent) const override;
126 	void emplace_back(Expression *expr);
127 	bool isLiteral() const override;
128 private:
129 	std::vector<shared_ptr<Expression>> children;
130 	mutable boost::tribool literal_flag; // cache if already computed
131 };
132 
133 class Lookup : public Expression
134 {
135 public:
136 	Lookup(const std::string &name, const Location &loc);
137 	Value evaluate(const std::shared_ptr<Context>& context) const override;
138 	const Value& evaluateSilently(const std::shared_ptr<Context>& context) const;
139 	void print(std::ostream &stream, const std::string &indent) const override;
get_name()140 	const std::string& get_name() const { return name; }
141 private:
142 	std::string name;
143 };
144 
145 class MemberLookup : public Expression
146 {
147 public:
148 	MemberLookup(Expression *expr, const std::string &member, const Location &loc);
149 	Value evaluate(const std::shared_ptr<Context>& context) const override;
150 	void print(std::ostream &stream, const std::string &indent) const override;
151 private:
152 	shared_ptr<Expression> expr;
153 	std::string member;
154 };
155 
156 class FunctionCall : public Expression
157 {
158 public:
159 	FunctionCall(Expression *expr, const AssignmentList &arglist, const Location &loc);
160 	void prepareTailCallContext(const std::shared_ptr<Context> context, std::shared_ptr<Context> tailCallContext, const AssignmentList &definition_arguments);
161 	Value evaluate(const std::shared_ptr<Context>& context) const override;
162 	void print(std::ostream &stream, const std::string &indent) const override;
get_name()163 	const std::string& get_name() const { return name; }
164 	static Expression * create(const std::string &funcname, const AssignmentList &arglist, Expression *expr, const Location &loc);
165 	shared_ptr<class FunctionDefinition> getFunctionDefinition(const Value& v) const;
166 public:
167 	bool isLookup;
168 	std::string name;
169 	shared_ptr<Expression> expr;
170 	AssignmentList arguments;
171 	AssignmentMap resolvedArguments;
172 	std::vector<std::pair<std::string, Value>> defaultArguments; // Only the ones not mentioned in 'resolvedArguments'
173 };
174 
175 class FunctionDefinition : public Expression
176 {
177 public:
178 	FunctionDefinition(Expression *expr, const AssignmentList &definition_arguments, const Location &loc);
179 	Value evaluate(const std::shared_ptr<Context>& context) const override;
180 	void print(std::ostream &stream, const std::string &indent) const override;
181 public:
182 	shared_ptr<Context> ctx;
183 	AssignmentList definition_arguments;
184 	shared_ptr<Expression> expr;
185 };
186 
187 class Assert : public Expression
188 {
189 public:
190 	Assert(const AssignmentList &args, Expression *expr, const Location &loc);
191 	const shared_ptr<Expression>& evaluateStep(const std::shared_ptr<Context>& context) const;
192 	Value evaluate(const std::shared_ptr<Context>& context) const override;
193 	void print(std::ostream &stream, const std::string &indent) const override;
194 private:
195 	AssignmentList arguments;
196 	shared_ptr<Expression> expr;
197 };
198 
199 class Echo : public Expression
200 {
201 public:
202 	Echo(const AssignmentList &args, Expression *expr, const Location &loc);
203 	const shared_ptr<Expression>& evaluateStep(const std::shared_ptr<Context>& context) const;
204 	Value evaluate(const std::shared_ptr<Context>& context) const override;
205 	void print(std::ostream &stream, const std::string &indent) const override;
206 private:
207 	AssignmentList arguments;
208 	shared_ptr<Expression> expr;
209 };
210 
211 class Let : public Expression
212 {
213 public:
214 	Let(const AssignmentList &args, Expression *expr, const Location &loc);
215 	const shared_ptr<Expression>& evaluateStep(const std::shared_ptr<Context>& context) const;
216 	Value evaluate(const std::shared_ptr<Context>& context) const override;
217 	void print(std::ostream &stream, const std::string &indent) const override;
218 private:
219 	AssignmentList arguments;
220 	shared_ptr<Expression> expr;
221 };
222 
223 class ListComprehension : public Expression
224 {
225 public:
226 	ListComprehension(const Location &loc);
227 	~ListComprehension() = default;
228 };
229 
230 class LcIf : public ListComprehension
231 {
232 public:
233 	LcIf(Expression *cond, Expression *ifexpr, Expression *elseexpr, const Location &loc);
234 	Value evaluate(const std::shared_ptr<Context>& context) const override;
235 	void print(std::ostream &stream, const std::string &indent) const override;
236 private:
237 	shared_ptr<Expression> cond;
238 	shared_ptr<Expression> ifexpr;
239 	shared_ptr<Expression> elseexpr;
240 };
241 
242 class LcFor : public ListComprehension
243 {
244 public:
245 	LcFor(const AssignmentList &args, Expression *expr, const Location &loc);
246 	Value evaluate(const std::shared_ptr<Context>& context) const override;
247 	void print(std::ostream &stream, const std::string &indent) const override;
248 private:
249 	AssignmentList arguments;
250 	shared_ptr<Expression> expr;
251 };
252 
253 class LcForC : public ListComprehension
254 {
255 public:
256 	LcForC(const AssignmentList &args, const AssignmentList &incrargs, Expression *cond, Expression *expr, const Location &loc);
257 	Value evaluate(const std::shared_ptr<Context>& context) const override;
258 	void print(std::ostream &stream, const std::string &indent) const override;
259 private:
260 	AssignmentList arguments;
261 	AssignmentList incr_arguments;
262 	shared_ptr<Expression> cond;
263 	shared_ptr<Expression> expr;
264 };
265 
266 class LcEach : public ListComprehension
267 {
268 public:
269 	LcEach(Expression *expr, const Location &loc);
270 	Value evaluate(const std::shared_ptr<Context>& context) const override;
271 	void print(std::ostream &stream, const std::string &indent) const override;
272 private:
273 	Value evalRecur(Value &&v, const std::shared_ptr<Context>& context) const;
274 	shared_ptr<Expression> expr;
275 };
276 
277 class LcLet : public ListComprehension
278 {
279 public:
280 	LcLet(const AssignmentList &args, Expression *expr, const Location &loc);
281 	Value evaluate(const std::shared_ptr<Context>& context) const override;
282 	void print(std::ostream &stream, const std::string &indent) const override;
283 private:
284 	AssignmentList arguments;
285 	shared_ptr<Expression> expr;
286 };
287 
288 void evaluate_assert(const std::shared_ptr<Context>& context, const std::shared_ptr<class EvalContext> evalctx);
289 
290 Value evaluate_function(const std::string& name,
291 		const std::shared_ptr<Expression>& expr, const AssignmentList& definition_arguments,
292 		const std::shared_ptr<Context>& ctx, const std::shared_ptr<EvalContext>& evalctx,
293 		const Location& loc);
294