98c52c530525e155f11b798faeed81fbcc7ba2a2
[sdk] / compiler / libec2 / src / expressions.ec
1 import "lexing"
2 import "astNode"
3 import "specifiers"
4 import "declarators"
5
6 static TokenType2 opPrec[][4] =
7 {
8    { '*', '/', '%' },
9    { '+', '-' },
10    { leftOp, rightOp },
11    { '<', '>', leOp, geOp },
12    { eqOp, neOp },
13    { '&' },
14    { '^' },
15    { '|' },
16    { andOp },
17    { orOp }
18 };
19
20 static define numPrec = sizeof(opPrec) / sizeof(opPrec[0]);
21
22 static bool isPrecedence(TokenType2 this, int l)
23 {
24    // TO OPTIMIZE: return opPrec[this] == l
25    if(this)
26    {
27       int o;
28       for(o = 0; o < sizeof(opPrec[0]) / sizeof(opPrec[0][0]); o++)
29       {
30          TokenType2 op = opPrec[l][o];
31          if(this == op)
32             return true;
33          else if(!op)
34             break;
35       }
36    }
37    return false;
38 }
39
40 public class ASTIdentifier : ASTNode
41 {
42 public:
43    // Symbol classSym;
44    // Specifier _class;
45    String string;
46    // Identifier badID;
47
48    void print()
49    {
50       Print(string);
51    }
52
53    ASTIdentifier ::parse()
54    {
55       readToken();
56       return { string = CopyString(token.text) };
57    }
58 };
59
60 public class ASTTypeName : ASTNode
61 {
62 public:
63    SpecsList qualifiers;
64    ASTDeclarator declarator;
65    ClassObjectType classObjectType;
66    ASTExpression bitCount;
67
68    ASTTypeName ::parse()
69    {
70       SpecsList specs = SpecsList::parse();
71       ASTDeclarator decl = ASTDeclarator::parse();
72       if(specs || decl)
73          return { qualifiers = specs, declarator = decl };
74       return null;
75    }
76
77    void print()
78    {
79       if(qualifiers) qualifiers.print();
80       if(declarator) { if(qualifiers) Print(" "); declarator.print(); }
81    }
82 };
83
84 // Expressions
85 public class ASTExpression : ASTNode
86 {
87 public:
88    ExpressionType type;
89
90    virtual float Compute();
91
92    bool debugValue;
93
94    DataValue val;
95
96    uint64 address;
97    bool hasAddress;
98
99    // *** COMPILING DATA ***
100    Type expType;
101    Type destType;
102
103    ExpUsage usage;
104    int tempCount;
105    bool byReference;
106    bool isConstant;
107    bool addedThis;
108    bool needCast;
109    bool thisPtr;
110
111    ASTExpression ::parse()
112    {
113       return ExpAssignment::parse();
114    }
115 /*
116    void Clear()
117    {
118       debugValue = false;
119       val = { 0 };
120       address = 0;
121       hasAddress = false;
122
123       expType = null;
124       destType = null;
125
126       usage = 0;
127       tempCount = 0;
128       byReference = false;
129       isConstant = false;
130       addedThis = false;
131       needCast = false;
132       thisPtr = false;
133    }
134 */
135 }
136
137 public class ExpList : ASTList<ASTExpression>
138 {
139    ExpList ::parse()
140    {
141       return (ExpList)ASTList::parse(class(ExpList), ASTExpression::parse, ',');
142    }
143 }
144
145 /*
146 public class ExpCompound : ASTExpression
147 {
148    ASTStatement compound;
149 }
150 */
151
152 static ASTExpression parseSimplePrimaryExpression()
153 {
154 /*
155 simple_primary_expression:
156      instantiation_unnamed      { $$ = MkExpInstance($1); $$.loc = @$; }
157    | EXTENSION '(' compound_statement ')'    { $$ = MkExpExtensionCompound($3); $$.loc = @$; }
158    | EXTENSION '(' expression ')'    { $$ = MkExpExtensionExpression($3); $$.loc = @$; }
159    | EXTENSION '(' type_name ')' initializer     { $$ = MkExpExtensionInitializer($3, $5); $$.loc = @$; }
160    | EXTENSION '(' type_name ')' '(' type_name ')' initializer     { $$ = MkExpExtensionInitializer($3, MkInitializerAssignment(MkExpExtensionInitializer($6, $8))); $$.loc = @$; }
161    | i18n_string
162    | '(' ')' { Expression exp = MkExpDummy(); exp.loc.start = @1.end; exp.loc.end = @2.start; $$ = MkExpBrackets(MkListOne(exp)); $$.loc = @$; yyerror(); }
163    | NEWOP new_specifiers abstract_declarator_noarray '[' constant_expression ']' { $$ = MkExpNew(MkTypeName($2,$3), $5); $$.loc = @$; }
164    | NEWOP new_specifiers abstract_declarator_noarray '[' constant_expression_error ']' { $$ = MkExpNew(MkTypeName($2,$3), $5); $$.loc = @$; }
165    | NEWOP new_specifiers '[' constant_expression ']' { $$ = MkExpNew(MkTypeName($2,null), $4); $$.loc = @$; }
166    | NEWOP new_specifiers '[' constant_expression_error ']' { $$ = MkExpNew(MkTypeName($2,null), $4); $$.loc = @$; }
167    | NEW0OP new_specifiers abstract_declarator_noarray '[' constant_expression ']' { $$ = MkExpNew0(MkTypeName($2,$3), $5); $$.loc = @$; }
168    | NEW0OP new_specifiers abstract_declarator_noarray '[' constant_expression_error ']' { $$ = MkExpNew0(MkTypeName($2,$3), $5); $$.loc = @$; }
169    | NEW0OP new_specifiers '[' constant_expression ']' { $$ = MkExpNew0(MkTypeName($2,null), $4); $$.loc = @$; }
170    | NEW0OP new_specifiers '[' constant_expression_error ']' { $$ = MkExpNew0(MkTypeName($2,null), $4); $$.loc = @$; }
171    | RENEW constant_expression renew_specifiers abstract_declarator_noarray '[' constant_expression ']' { $$ = MkExpRenew($2, MkTypeName($3,$4), $6); $$.loc = @$; }
172    | RENEW constant_expression renew_specifiers abstract_declarator_noarray '[' constant_expression_error ']' { $$ = MkExpRenew($2, MkTypeName($3,$4), $6); $$.loc = @$; }
173    | RENEW constant_expression renew_specifiers '[' constant_expression ']' { $$ = MkExpRenew($2, MkTypeName($3,null), $5); $$.loc = @$; }
174    | RENEW constant_expression renew_specifiers '[' constant_expression_error ']' { $$ = MkExpRenew($2, MkTypeName($3,null), $5); $$.loc = @$; }
175    | RENEW0 constant_expression renew_specifiers abstract_declarator_noarray '[' constant_expression ']' { $$ = MkExpRenew0($2, MkTypeName($3,$4), $6); $$.loc = @$; }
176    | RENEW0 constant_expression renew_specifiers abstract_declarator_noarray '[' constant_expression_error ']' { $$ = MkExpRenew0($2, MkTypeName($3,$4), $6); $$.loc = @$; }
177    | RENEW0 constant_expression renew_specifiers '[' constant_expression ']' { $$ = MkExpRenew0($2, MkTypeName($3,null), $5); $$.loc = @$; }
178    | RENEW0 constant_expression renew_specifiers '[' constant_expression_error ']' { $$ = MkExpRenew0($2, MkTypeName($3,null), $5); $$.loc = @$; }
179    | CLASS '(' declaration_specifiers ')' { $$ = MkExpClass($3, null); $$.loc = @$; }
180    | CLASS '(' declaration_specifiers abstract_declarator ')' { $$ = MkExpClass($3, $4); $$.loc = @$; }
181    | CLASS '(' identifier ')' { $$ = MkExpClass(MkListOne(MkSpecifierName($3.string)), null); FreeIdentifier($3); $$.loc = @$; }
182    | VAARG '(' assignment_expression ',' type_name ')' { $$ = MkExpVaArg($3, $5); $$.loc = @$; }
183
184    | CLASS_DATA '(' identifier ')' { $$ = MkExpClassData($3); $$.loc = @$; }
185    | database_open
186    | dbfield
187    | dbindex
188    | dbtable
189
190    | '[' argument_expression_list ']' { $$ = MkExpArray($2); $$.loc = @$; }
191    ;
192 */
193    if(peekToken().type == constant)
194       return ExpConstant::parse();
195    else if(nextToken.type == identifier)
196    {
197       ExpIdentifier exp = ExpIdentifier::parse();
198       if(peekToken().type == '{')
199       {
200          SpecsList specs { };
201          specs.Add(SpecName { name = exp.identifier.string });
202          return ExpInstance::parse(specs, null);
203       }
204       return exp;
205    }
206    else if(nextToken.type == stringLiteral)
207       return ExpString::parse();
208    else if(nextToken.type == '{')
209       return ExpInstance::parse(null, null);
210    else
211       return null;
212 }
213
214 static ASTExpression parsePrimaryExpression()
215 {
216    if(peekToken().type == '(')
217    {
218       ExpBrackets exp { };
219       readToken();
220       exp.list = ExpList::parse();
221       if(peekToken().type == ')')
222          readToken();
223       return exp;
224    }
225    else
226       return parseSimplePrimaryExpression();
227 }
228
229 static ASTExpression parsePostfixExpression()
230 {
231    ASTExpression exp = parsePrimaryExpression();
232    while(true)
233    {
234       if(peekToken().type == '[')
235          exp = ExpIndex::parse(exp);
236       else if(nextToken.type == '(')
237          exp = ExpCall::parse(exp);
238       else if(nextToken.type == '.')
239          exp = ExpMember::parse(exp);
240       else if(nextToken.type == ptrOp)
241          exp = ExpPointer::parse(exp);
242       else if(nextToken.type == incOp || nextToken.type == decOp)
243       {
244          readToken();
245          exp = ExpOperation { exp1 = exp, op = token.type };
246       }
247       else
248          break;
249    }
250    return exp;
251 }
252
253 static ASTExpression parseUnaryExpression()
254 {
255    peekToken();
256    if(nextToken.type == incOp || nextToken.type == decOp)
257    {
258       readToken();
259       return ExpOperation { op = token.type, exp2 = parseUnaryExpression() };
260    }
261    else if(nextToken.type.isUnaryOperator)
262    {
263       readToken();
264       return ExpOperation { op = token.type, exp2 = ExpCast::parse() };
265    }
266    /*
267    else if(nextToken.type == SIZEOF)
268       return ExpSizeof::parse();
269    else if(nextToken.type == ALIGNOF)
270       return ExpAlignOf::parse();
271    */
272    else
273       return parsePostfixExpression();
274 }
275
276 public class ExpConstant : ASTExpression
277 {
278    String constant;
279
280    void print()
281    {
282       Print(constant);
283    }
284
285    ExpConstant ::parse()
286    {
287       return { constant = CopyString(readToken().text); };
288    }
289
290    float Compute()
291    {
292       return (float)atof(constant);
293    }
294 }
295
296 public class ExpString : ASTExpression
297 {
298    String string;
299
300    void print()
301    {
302       Print(string);
303    }
304
305    ExpString ::parse()
306    {
307       return { string = CopyString(readToken().text) };
308    }
309 }
310
311 public class ExpIdentifier : ASTExpression
312 {
313    ASTIdentifier identifier;
314
315    void print()
316    {
317       identifier.print();
318    }
319
320    ExpIdentifier ::parse()
321    {
322       return { identifier = ASTIdentifier::parse() };
323    }
324 }
325
326 public class ExpOperation : ASTExpression
327 {
328    TokenType2 op;
329    ASTExpression exp1, exp2;
330
331    void print()
332    {
333       if(exp1) { exp1.print(); if(exp2) Print(" "); }
334       op.print();
335       if(exp2) { if(exp1) Print(" "); exp2.print(); }
336    }
337
338    ASTExpression ::parse(int prec)
339    {
340       ASTExpression exp = (prec > 0) ? parse(prec-1) : ExpCast::parse();
341       while(isPrecedence(peekToken().type, prec))
342          exp = ExpOperation { exp1 = exp, op = readToken().type, exp2 = (prec > 0) ? parse(prec-1) : ExpCast::parse() };
343       return exp;
344    }
345
346    float Compute()
347    {
348       if(exp1 && exp2)
349       {
350          switch(op)
351          {
352             case '*': return exp1.Compute() * exp2.Compute();
353             case '/': return exp1.Compute() / exp2.Compute();
354             case '-': return exp1.Compute() - exp2.Compute();
355             case '+': return exp1.Compute() + exp2.Compute();
356          }
357       }
358       else if(exp2)
359       {
360          switch(op)
361          {
362             case '-': return -exp2.Compute();
363             case '+': return  exp2.Compute();
364          }
365       }
366       return 0;
367    }
368 }
369
370 public class ExpAssignment : ExpOperation
371 {
372    ASTExpression ::parse()
373    {
374       ASTExpression exp = ExpConditional::parse();
375       if(peekToken().type.isAssignmentOperator)
376          exp = ExpAssignment { exp1 = exp, op = readToken().type, exp2 = ExpAssignment::parse() };
377       return exp;
378    }
379 }
380
381 public class ExpBrackets : ASTExpression
382 {
383 public:
384    ExpList list;
385
386    void print()
387    {
388       Print("(");
389       if(list) list.print();
390       Print(")");
391    }
392
393    float Compute()
394    {
395       return (list && list.lastIterator.data) ? list.lastIterator.data.Compute() : 0;
396    }
397 }
398
399 public class ExpConditional : ASTExpression
400 {
401 public:
402    ASTExpression condition;
403    ExpList expList;
404    ASTExpression elseExp;
405
406    void print()
407    {
408       if(condition) condition.print();
409       Print(" ? ");
410       if(expList) expList.print();
411       Print(" : ");
412       if(elseExp)
413          elseExp.print();
414    }
415
416    ASTExpression ::parse()
417    {
418       ASTExpression exp = ExpOperation::parse(numPrec-1);
419       if(peekToken().type == '?')
420       {
421          exp = ExpConditional { condition = exp, expList = ExpList::parse() };
422          if(peekToken().type == ':')
423             ((ExpConditional)exp).elseExp = ExpConditional::parse();
424       }
425       return exp;
426    }
427 }
428
429 public class ExpIndex : ASTExpression
430 {
431    ASTExpression exp;
432    ExpList index;
433
434    void print()
435    {
436       if(exp) exp.print();
437       Print("[");
438       if(index) index.print();
439       Print("]");
440    }
441
442    ExpIndex ::parse(ASTExpression e)
443    {
444       ExpIndex exp;
445       readToken();
446       exp = ExpIndex { exp = e, index = ExpList::parse() };
447       if(peekToken().type == ']')
448          readToken();
449       return exp;
450    }
451 }
452
453 public class ExpMember : ASTExpression
454 {
455    ASTExpression exp;
456    ASTIdentifier member;
457    // MemberType memberType;
458    // bool thisPtr;
459
460    void print()
461    {
462       if(exp) exp.print();
463       Print(".");
464       if(member)
465          member.print();
466    }
467
468    ExpMember ::parse(ASTExpression e)
469    {
470       readToken();
471       return { exp = e, member = ASTIdentifier::parse() };
472    }
473 }
474
475 public class ExpPointer : ExpMember
476 {
477    void print()
478    {
479       if(exp) exp.print();
480       Print("->");
481       if(member)
482          member.print();
483    }
484
485    ExpPointer ::parse(ASTExpression e)
486    {
487       readToken();
488       return { exp = e, member = ASTIdentifier::parse() };
489    }
490 }
491
492 public class ExpCall : ASTExpression
493 {
494    ASTExpression exp;
495    ExpList arguments;
496    // Location argLoc;
497
498    void print()
499    {
500       if(exp) exp.print();
501       Print("(");
502       if(arguments) arguments.print();
503       Print(")");
504    }
505
506    ExpCall ::parse(ASTExpression e)
507    {
508       ExpCall exp;
509       readToken();
510       exp = ExpCall { exp = e, arguments = ExpList::parse() };
511       if(peekToken().type == ')')
512          readToken();
513       return exp;
514    }
515 }
516
517 public class ExpCast : ASTExpression
518 {
519    ASTTypeName typeName;
520    ASTExpression exp;
521
522    ASTExpression ::parse()
523    {
524       ASTExpression exp = parseUnaryExpression();
525       // TODO: Deal with cast ambiguity
526       return exp;
527    }
528 }
529
530 public class ExpInstance : ASTExpression
531 {
532    ASTInstantiation instance;
533
534    ExpInstance ::parse(SpecsList specs, InitDeclList decls)
535    {
536       return { instance = ASTInstantiation::parse(specs, decls) };
537    }
538
539    void print()
540    {
541       if(instance) instance.print();
542    }
543 }
544 /*
545 public class ExpSizeOf : ASTExpression
546 {
547    ASTTypeName typeName;
548
549    ExpSizeOf ::parse()
550    {
551
552    }
553 }
554
555 public class ExpAlignOf : ASTExpression
556 {
557    ASTTypeName typeName;
558
559    ExpAlignOf ::parse()
560    {
561    }
562 }
563 */
564 /*
565    union
566    {
567       struct
568       {
569          OldList * specifiers;
570          ASTDeclarator decl;
571       } _classExp;
572       struct
573       {
574          Identifier id;
575       } classData;
576       TypeName typeName;
577       Specifier _class;
578       struct
579       {
580          TypeName typeName;
581          Expression size;
582       } _new;
583       struct
584       {
585          TypeName typeName;
586          Expression size;
587          Expression exp;
588       } _renew;
589       struct
590       {
591          char * table;
592          Identifier id;
593       } db;
594       struct
595       {
596          Expression ds;
597          Expression name;
598       } dbopen;
599       struct
600       {
601          TypeName typeName;
602          Initializer initializer;
603       } initializer;
604       struct
605       {
606          Expression exp;
607          TypeName typeName;
608       } vaArg;
609    };
610 };
611 */
612
613 public class InstanceInit : ASTNode
614 {
615    InstanceInit ::parse()
616    {
617       int a = pushAmbiguity();
618       SpecsList specs = SpecsList::parse();
619       InitDeclList decls = InitDeclList::parse();
620
621       peekToken();
622       if(nextToken.type == '{' || (specs && decls))
623       {
624          clearAmbiguity();
625          return InstInitFunction::parse(specs, decls);
626       }
627       else if(nextToken.type != '}')
628       {
629          popAmbiguity(a);
630          return InstInitMember::parse();
631       }
632       return null;
633    }
634 }
635
636 public class InstInitMember : InstanceInit
637 {
638    MemberInitList members;
639
640    InstInitMember ::parse()
641    {
642       MemberInitList list = MemberInitList::parse();
643
644       return { members = list };
645    }
646
647    void print()
648    {
649       if(members) members.print();
650    }
651 }
652
653 public class InstInitFunction : InstanceInit
654 {
655    ASTClassFunction function;
656
657    InstInitFunction ::parse(SpecsList specs, InitDeclList decls)
658    {
659       return { function = ASTClassFunction::parse(specs, decls) };
660    }
661
662    void print()
663    {
664       if(function) function.print();
665    }
666 }
667
668 public class InstInitList : ASTList<InstanceInit>
669 {
670    InstInitList ::parse()
671    {
672       return (InstInitList)ASTList::parse(class(InstInitList), InstanceInit::parse, 0);
673    }
674
675    void print()
676    {
677       ASTList::print();
678    }
679 }
680
681 public class ASTInstantiation : ASTNode
682 {
683 public:
684    ASTSpecifier _class;
685    ASTExpression exp;
686
687    InstInitList members;
688    Symbol symbol;
689    bool fullSet;
690    bool isConstant;
691    byte * data;
692    Location nameLoc, insideLoc;
693    bool built;
694
695    ASTInstantiation ::parse(SpecsList specs, InitDeclList decls)
696    {
697       ASTInstantiation inst { };
698       if(specs && specs[0])
699          inst._class = specs[0];
700
701       if(decls && decls[0] && decls[0].declarator && decls[0].declarator._class == class(DeclIdentifier))
702          inst.exp = ExpIdentifier { identifier = ((DeclIdentifier)decls[0].declarator).identifier };
703
704       readToken();
705       inst.members = InstInitList::parse();
706       if(peekToken().type == '}')
707          readToken();
708       return inst;
709    }
710
711    void print()
712    {
713       bool multiLine = false;
714       if(members)
715       {
716          for(m : members; m._class == class(InstInitFunction))
717          {
718             multiLine = true;
719             break;
720          }
721       }
722
723       if(_class) { _class.print(); if(!multiLine || exp) Print(" "); }
724       if(exp) { exp.print(); if(!multiLine) Print(" "); }
725       if(multiLine)
726       {
727          PrintLn("");
728          printIndent();
729       }
730       Print("{");
731       if(multiLine)
732       {
733          PrintLn("");
734          indent++;
735       }
736       if(members && members[0])
737       {
738          if(multiLine)
739          {
740             Iterator<InstanceInit> it { members };
741             while(it.Next())
742             {
743                InstanceInit init = it.data;
744                Link nextLink = (Link)members.GetNext(it.pointer);
745                if(init._class != class(InstInitFunction))
746                   printIndent();
747                init.print();
748                if(init._class == class(InstInitMember))
749                   Print(";");
750                if(nextLink)
751                {
752                   InstanceInit next = nextLink ? (InstanceInit)nextLink.data : null;
753                   PrintLn("");
754                   if(next._class == class(InstInitFunction))
755                      PrintLn("");
756                }
757                else if(init._class != class(InstInitFunction))
758                   PrintLn("");
759             }
760          }
761          else
762          {
763             Print(" ");
764             members.print();
765             Print(" ");
766          }
767       }
768       else
769          Print(" ");
770       if(multiLine)
771       {
772          indent--;
773          printIndent();
774       }
775       Print("}");
776    }
777 };