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