1 /*
2 * The contents of this file are subject to the Mozilla Public License
3 * Version 1.0 (the "License"); you may not use this file except in
4 * compliance with the License. You may obtain a copy of the License at
5 * http://www.mozilla.org/MPL/
6 *
7 * Software distributed under the License is distributed on an "AS IS"
8 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
9 * License for the specific language governing rights and limitations
10 * under the License.
11 *
12 * The Initial Developer of this code is David Baum.
13 * Portions created by David Baum are Copyright (C) 1999 David Baum.
14 * All Rights Reserved.
15 *
16 * Portions created by John Hansen are Copyright (C) 2005 John Hansen.
17 * All Rights Reserved.
18 *
19 */
20
21
22 #include "parse_util.h"
23 #include "Expr.h"
24 #include "parser.h"
25 #include "AssignStmt.h"
26 #include "AssignMathStmt.h"
27 #include "Symbol.h"
28 #include "GosubStmt.h"
29 #include "Program.h"
30 #include "UnaryExpr.h"
31 #include "BinaryExpr.h"
32 #include "AtomExpr.h"
33 #include "ValueExpr.h"
34 #include "Error.h"
35 #include "ModExpr.h"
36 #include "CaseStmt.h"
37 #include "FunctionDef.h"
38 #include "AsmStmt.h"
39 #include "ScopeStmt.h"
40 #include "AcquireStmt.h"
41 #include "DeclareStmt.h"
42 #include "ArrayExpr.h"
43 #include "TaskIdExpr.h"
44 #include "IndirectExpr.h"
45 #include "CatchStmt.h"
46 #include "ShiftExpr.h"
47 #include "IncDecExpr.h"
48 #include "AddrOfExpr.h"
49 #include "DerefExpr.h"
50 #include "Resource.h"
51
52
53 // template class to auto-delete an object upon destruction
54 template <class T> class Deleter
55 {
56 public:
Deleter(T * t)57 Deleter(T *t) : t_(t) {};
~Deleter()58 ~Deleter() { delete t_; }
59
60 private:
61 T* t_;
62 };
63
64
65
GetConstantValue(const Expr * e)66 int GetConstantValue(const Expr *e)
67 {
68 Deleter<const Expr> d(e);
69 int v = 0;
70 bool ok;
71
72 ok = e->Evaluate(v);
73 if (!ok)
74 Error(kErr_ConstantNeeded).Raise(&e->GetLoc());
75
76 return v;
77 }
78
79
GetLValue(const Expr * e)80 int GetLValue(const Expr *e)
81 {
82 Deleter<const Expr> d(e);
83
84 int lv = e->GetLValue();
85 if (lv==kIllegalVar)
86 Error(kErr_LValueNeeded).Raise(&e->GetLoc());
87
88 return lv;
89 }
90
91
CheckLValue(Expr * lval)92 void CheckLValue(Expr *lval)
93 {
94 if (!lval->PotentialLValue())
95 Error(kErr_LValueNeeded).Raise(&lval->GetLoc());
96 }
97
98
MakeUnaryExpr(int op,Expr * arg)99 Expr *MakeUnaryExpr(int op, Expr *arg)
100 {
101 if (!UnaryExpr::NeedsConstant(op) || arg->PromiseConstant())
102 return new UnaryExpr(op, arg);
103
104 // Swan target handles this elsewhere
105 if (op == '~') {
106 // special case transform ~x -> -1 - x
107 return new BinaryExpr(
108 new AtomExpr(kRCX_ConstantType, -1, arg->GetLoc()),
109 '-',
110 arg
111 );
112 }
113
114 Error(kErr_ConstantNeeded).RaiseLex();
115 // return a dummy expr so the parse tree is still valid
116 return arg;
117 }
118
119
MakeBinaryExpr(Expr * lhs,int op,Expr * rhs)120 Expr *MakeBinaryExpr(Expr *lhs, int op, Expr *rhs)
121 {
122 if (!BinaryExpr::NeedsConstant(op) ||
123 (rhs->PromiseConstant() &&
124 lhs->PromiseConstant()))
125 {
126 return new BinaryExpr(lhs, op, rhs);
127 }
128
129 // modulo is a special case (Swan target handles this elsewhere)
130 if (op == '%')
131 {
132 return new ModExpr(lhs, rhs);
133 }
134
135 // shifts are also special cases (Swan target handles these elsewhere)
136 if (op == LEFT || op == RIGHT)
137 {
138 // right argument must be a constant
139 if (rhs->PromiseConstant())
140 {
141 return new ShiftExpr(lhs, rhs, (op==LEFT) ? ShiftExpr::kLeft : ShiftExpr::kRight);
142 }
143
144 // if rhs is not constant, this will just fall through to
145 // the normal binary expression case, which is an error
146 }
147
148 // xor handled by a transform (Swan target handles this elsewhere
149 if (op == '^')
150 {
151 // a^b -> (-1 - (a&b)) & (a | b)
152 Expr *lhc = lhs->Clone(0);
153 Expr *rhc = rhs->Clone(0);
154
155 Expr *nand = new BinaryExpr(
156 new AtomExpr(kRCX_ConstantType, -1, lhs->GetLoc()),
157 '-',
158 new BinaryExpr(
159 lhc,
160 '&',
161 rhc
162 )
163 );
164
165 return new BinaryExpr(
166 nand,
167 '&',
168 new BinaryExpr(lhs, '|', rhs)
169 );
170 }
171
172
173 Error(kErr_ConstantNeeded).RaiseLex();
174 // return a dummy expr so the parse tree is still valid
175 delete rhs;
176 return lhs;
177 }
178
179
MakeValueExpr(Expr * e)180 Expr *MakeValueExpr(Expr *e)
181 {
182 if (!e->PromiseConstant())
183 {
184 Error(kErr_ConstantNeeded).RaiseLex();
185 // return a dummy expr so the parse tree is still valid
186 return e;
187 }
188
189 // if e can be evaluated, return AtomExpr, otherwise return ValueExpr
190 int value;
191 if (e->Evaluate(value))
192 {
193 Expr *newExpr;
194 newExpr = new AtomExpr(RCX_VALUE_TYPE(value), RCX_VALUE_DATA_INT(value), e->GetLoc());
195 delete e;
196 return newExpr;
197 }
198 else
199 return new ValueExpr(e);
200 }
201
VarCodeToChar(int op)202 int VarCodeToChar(int op)
203 {
204 switch((RCX_VarCode)op)
205 {
206 case kRCX_AddVar:
207 return '+';
208 case kRCX_SubVar:
209 return '-';
210 case kRCX_MulVar:
211 return '*';
212 case kRCX_DivVar:
213 return '/';
214 case kRCX_AndVar:
215 return '&';
216 case kRCX_OrVar:
217 return '|';
218 case kRCX_NotVar:
219 return '~';
220 case kRCX_ModVar:
221 return '%';
222 case kRCX_ShlVar:
223 return LEFT;
224 case kRCX_ShrVar:
225 return RIGHT;
226 case kRCX_XOrVar:
227 return '^';
228 }
229 return 0;
230 }
231
MakeAssignStmt(Expr * lhs,int op,Expr * rhs)232 Stmt *MakeAssignStmt(Expr *lhs, int op, Expr *rhs)
233 {
234 const RCX_Target *t = gProgram->GetTarget();
235 if ((t->fType != kRCX_SwanTarget) && (lhs->GetLValue()==kIllegalVar))
236 {
237 switch((RCX_VarCode)op)
238 {
239 case kRCX_AbsVar:
240 return new AssignStmt(lhs, MakeUnaryExpr(ABS, rhs));
241 case kRCX_SgnVar:
242 return new AssignStmt(lhs, MakeUnaryExpr(SIGN, rhs));
243 default:
244 return MakeAssign2Stmt(lhs, VarCodeToChar(op), rhs);
245 }
246 }
247 else
248 {
249 return new AssignMathStmt(lhs, (RCX_VarCode)op, rhs);
250 }
251 }
252
MakeAssign2Stmt(Expr * lhs,int op,Expr * rhs)253 Stmt *MakeAssign2Stmt(Expr *lhs, int op, Expr *rhs)
254 {
255 const RCX_Target *t = gProgram->GetTarget();
256 if (t->fType == kRCX_SwanTarget)
257 {
258 // Swan has opcodes for %=, ^=, <<=, and >>=
259 RCX_VarCode code;
260 switch (op)
261 {
262 case '%' : code = kRCX_ModVar; break;
263 case '^' : code = kRCX_XOrVar; break;
264 case RIGHT : code = kRCX_ShrVar; break;
265 default : code = kRCX_ShlVar; break;
266 }
267 return MakeAssignStmt(lhs, code, rhs);
268 }
269 else
270 {
271 Expr *dst = lhs->Clone(0);
272 Expr *math = MakeBinaryExpr(lhs, op, rhs);
273
274 return new AssignStmt(dst, math);
275 }
276 }
277
MakeIncDecExpr(Expr * lhs,bool inc,bool pre,const LexLocation & loc)278 Expr *MakeIncDecExpr(Expr *lhs, bool inc, bool pre, const LexLocation &loc)
279 {
280 return new IncDecExpr(GetLValue(lhs), inc, pre, loc);
281 }
282
MakeCaseStmt(const Expr * e,const struct LexLocation & loc)283 CaseStmt* MakeCaseStmt(const Expr *e, const struct LexLocation &loc)
284 {
285 int v = GetConstantValue(e);
286
287 if (v < -32768 || v > 32767)
288 Error(kErr_CaseRange).RaiseLex();
289
290
291 return new CaseStmt(v, loc);
292 }
293
294
MakeAcquireStmt(const Expr * e,Stmt * body,Stmt * handler,LocationNode * ln)295 Stmt *MakeAcquireStmt(const Expr *e, Stmt *body, Stmt *handler, LocationNode *ln)
296 {
297 Deleter<LocationNode> d(ln);
298 int v = GetConstantValue(e);
299
300 return new AcquireStmt(v, body, handler, ln->GetLoc());
301 }
302
303
MakeCatchStmt(const Expr * e,Stmt * body,LocationNode * ln)304 Stmt *MakeCatchStmt(const Expr *e, Stmt *body, LocationNode *ln)
305 {
306 Deleter<LocationNode> d(ln);
307
308 int v;
309
310 if (e)
311 v = GetConstantValue(e);
312 else
313 v = -1;
314
315 return new CatchStmt(v, body, ln->GetLoc());
316 }
317
318
DefineSubArg(Fragment * f,const Symbol * name,int type)319 void DefineSubArg(Fragment *f, const Symbol *name, int type)
320 {
321 const RCX_Target *t = gProgram->GetTarget();
322 if (!t->fSubParams)
323 Error(kErr_NoTargetSubParams, t->fName).RaiseLex();
324 if (!f->AddArg(name, (FunctionDef::ArgType)type))
325 Error(kErr_SymRedef, name->GetKey()).RaiseLex();
326 }
327
328
DefineArg(FunctionDef * f,const Symbol * name,int type)329 void DefineArg(FunctionDef *f, const Symbol *name, int type)
330 {
331 if (!f->AddArg(name, (FunctionDef::ArgType)type))
332 Error(kErr_SymRedef, name->GetKey()).RaiseLex();
333 }
334
335
BeginScope()336 void BeginScope()
337 {
338 gProgram->PushScope();
339 }
340
341
EndScope(Stmt * body)342 Stmt *EndScope(Stmt *body)
343 {
344 gProgram->PopScope();
345 return new ScopeStmt(body);
346 }
347
348
CreateSubroutine(Fragment * f,Symbol * name,Stmt * body)349 Fragment* CreateSubroutine(Fragment *f, Symbol *name, Stmt *body)
350 {
351 f->SetName(name);
352 gProgram->PushScope();
353 f->CreateArgVars();
354 f->SetBody(body);
355 gProgram->PopScope();
356 // f->CreateArgVars();
357 return f;
358 }
359
360
BeginSubWithParams(Fragment * f,Symbol * name)361 Fragment* BeginSubWithParams(Fragment *f, Symbol *name)
362 {
363 f->SetName(name);
364 gProgram->PushScope();
365 f->CreateArgVars();
366 return f;
367 }
368
369
EndSubWithParams(Fragment * f,Stmt * body,LocationNode * start,LocationNode * end)370 void EndSubWithParams(Fragment *f, Stmt *body, LocationNode *start, LocationNode *end)
371 {
372 f->SetLocations(start, end);
373 f->SetBody(body);
374 gProgram->PopScope();
375 }
376
377
BeginFunction(FunctionDef * f,const Symbol * name,bool listing)378 FunctionDef* BeginFunction(FunctionDef *f, const Symbol *name, bool listing)
379 {
380 f->SetName(name);
381 gProgram->AddFunction(f);
382 gProgram->PushScope();
383 f->CreateArgVars();
384 f->SetListingEnabled(listing);
385 return f;
386 }
387
388
EndFunction(FunctionDef * f,Stmt * body,LocationNode * start,LocationNode * end)389 void EndFunction(FunctionDef *f, Stmt *body, LocationNode *start, LocationNode *end)
390 {
391 f->SetLocations(start, end);
392 f->SetBody(body);
393 gProgram->PopScope();
394 }
395
396
MakeConstField(Expr * e)397 ConstField *MakeConstField(Expr *e)
398 {
399 ConstField *c = new ConstField(e);
400
401 if (!e->PromiseConstant())
402 {
403 Error(kErr_ConstantNeeded).RaiseLex();
404 }
405 return c;
406 }
407
408
MakeVarExpr(const Symbol * name,LocationNode * ln)409 Expr *MakeVarExpr(const Symbol *name, LocationNode *ln)
410 {
411 Deleter<LocationNode> d(ln);
412 bool array, ptr, stack;
413
414 int var = gProgram->GetVar(name, array, ptr, stack);
415 if (var == kIllegalVar)
416 {
417 // check to see if name is for resource
418 const Resource *resource = gProgram->GetResource(name);
419 if (resource)
420 {
421 return new AtomExpr(kRCX_ConstantType, resource->GetNumber() , ln->GetLoc());
422 }
423
424 Error(kErr_UndefinedVar, name->GetKey()).Raise(&ln->GetLoc());
425 }
426 else if (array)
427 {
428 Error(kErr_VarIsArray, name->GetKey()).Raise(&ln->GetLoc());
429 }
430
431 return new AtomExpr(kRCX_VariableType, var, ln->GetLoc(), ptr);
432 }
433
434
MakeIndirectExpr(Expr * src,Expr * idx)435 Expr *MakeIndirectExpr(Expr *src, Expr *idx)
436 {
437 if (!src->PromiseConstant())
438 {
439 Error(kErr_ConstantNeeded).RaiseLex();
440 delete src;
441 return idx;
442 }
443
444 return new IndirectExpr(src, idx);
445 }
446
447
MakeTaskIdExpr(LocationNode * ln)448 Expr *MakeTaskIdExpr(LocationNode *ln)
449 {
450 Deleter<LocationNode> d(ln);
451
452 return new TaskIdExpr(ln->GetLoc());
453 }
454
455
MakeArrayExpr(const Symbol * name,LocationNode * ln,Expr * index)456 Expr *MakeArrayExpr(const Symbol *name, LocationNode *ln, Expr *index)
457 {
458 Deleter<LocationNode> d(ln);
459 bool array, ptr, stack;
460
461 int var = gProgram->GetVar(name, array, ptr, stack);
462 if (var == kIllegalVar)
463 {
464 Error(kErr_UndefinedVar, name->GetKey()).Raise(&ln->GetLoc());
465 }
466 else if (!array)
467 {
468 Error(kErr_VarIsNotArray, name->GetKey()).Raise(&ln->GetLoc());
469 }
470
471 return new ArrayExpr(var, index);
472 }
473
MakeAddrOfExpr(const Symbol * name,LocationNode * ln,Expr * index)474 Expr *MakeAddrOfExpr(const Symbol *name, LocationNode *ln, Expr * index)
475 {
476 Deleter<LocationNode> d(ln);
477 bool array, ptr, stack;
478 int value=0;
479
480 int var = gProgram->GetVar(name, array, ptr, stack);
481 if (var == kIllegalVar)
482 {
483 Error(kErr_UndefinedVar, name->GetKey()).Raise(&ln->GetLoc());
484 }
485 else if (array)
486 {
487 // if the expression is a constant then we can take the address of it
488 if (index)
489 {
490 if (!index->Evaluate(value))
491 {
492 Error(kErr_AddrOfNonConstantIndex).Raise(&ln->GetLoc());
493 }
494 }
495 }
496 return new AddrOfExpr(var, value, ln->GetLoc());
497 }
498
MakeDerefExpr(const Symbol * name,LocationNode * ln)499 Expr *MakeDerefExpr(const Symbol *name, LocationNode *ln)
500 {
501 Deleter<LocationNode> d(ln);
502 bool array, ptr, stack;
503
504 const RCX_Target *t = gProgram->GetTarget();
505
506 if (!t->SourceWritable(kRCX_IndirectType))
507 Error(kErr_NoTargetIndirect, t->fName).Raise(&ln->GetLoc());
508
509 int var = gProgram->GetVar(name, array, ptr, stack);
510 if (var == kIllegalVar)
511 {
512 Error(kErr_UndefinedVar, name->GetKey()).Raise(&ln->GetLoc());
513 }
514 else if (array)
515 {
516 Error(kErr_VarIsArray, name->GetKey()).Raise(&ln->GetLoc());
517 }
518 else if (!ptr)
519 {
520 Error(kErr_VarIsNotPointer, name->GetKey()).Raise(&ln->GetLoc());
521 }
522
523 return new DerefExpr(var, ln->GetLoc());
524 }
525
526
527
MakeDeclareStmt(const Symbol * name,LocationNode * ln,Expr * arraySize,bool ptr,bool stack)528 DeclareStmt *MakeDeclareStmt(const Symbol *name, LocationNode *ln, Expr *arraySize, bool ptr, bool stack)
529 {
530 Deleter<LocationNode> d(ln);
531
532 int var = gProgram->CreateVar(name, arraySize, ptr, stack);
533
534 int size = 1;
535 if (arraySize)
536 {
537 const RCX_Target *t = gProgram->GetTarget();
538
539 if (!t->fArrays)
540 Error(kErr_NoTargetArrays, t->fName).Raise(&ln->GetLoc());
541
542 if (!arraySize->Evaluate(size))
543 {
544 Error(kErr_ConstantNeeded).Raise(&arraySize->GetLoc());
545 }
546 delete arraySize;
547 }
548 if (ptr)
549 {
550 }
551
552
553 return new DeclareStmt(name, var, ln->GetLoc(), size, ptr, stack);
554 }
555