compiler/libec2: Support for class value initializers, error recovery before initiali...
[sdk] / compiler / libec2 / src / expressions.ec
1 import "lexing"
2 import "astNode"
3 import "specifiers"
4 import "declarators"
5
6 static TokenType opPrec[][4] =
7 {
8    { '*', '/', '%' },
9    { '+', '-' },
10    { LEFT_OP, RIGHT_OP },
11    { '<', '>', LE_OP, GE_OP },
12    { EQ_OP, NE_OP },
13    { '&' },
14    { '^' },
15    { '|' },
16    { AND_OP },
17    { OR_OP }
18 };
19
20 static define numPrec = sizeof(opPrec) / sizeof(opPrec[0]);
21
22 static bool isPrecedence(TokenType 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          TokenType 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       return ExpIdentifier::parse();
197    else if(nextToken.type == STRING_LITERAL)
198       return ExpString::parse();
199    else
200       return null;
201 }
202
203 static ASTExpression parsePrimaryExpression()
204 {
205    if(peekToken().type == '(')
206    {
207       ExpBrackets exp { };
208       readToken();
209       exp.list = ExpList::parse();
210       if(peekToken().type == ')')
211          readToken();
212       return exp;
213    }
214    else
215       return parseSimplePrimaryExpression();
216 }
217
218 static ASTExpression parsePostfixExpression()
219 {
220    ASTExpression exp = parsePrimaryExpression();
221    while(true)
222    {
223       if(peekToken().type == '[')
224          exp = ExpIndex::parse(exp);
225       else if(nextToken.type == '(')
226          exp = ExpCall::parse(exp);
227       else if(nextToken.type == '.')
228          exp = ExpMember::parse(exp);
229       else if(nextToken.type == PTR_OP)
230          exp = ExpPointer::parse(exp);
231       else if(nextToken.type == INC_OP || nextToken.type == DEC_OP)
232       {
233          readToken();
234          exp = ExpOperation { exp1 = exp, op = token.type };
235       }
236       else
237          break;
238    }
239    return exp;
240 }
241
242 static ASTExpression parseUnaryExpression()
243 {
244    peekToken();
245    if(nextToken.type == INC_OP || nextToken.type == DEC_OP)
246    {
247       readToken();
248       return ExpOperation { op = token.type, exp2 = parseUnaryExpression() };
249    }
250    else if(nextToken.type.isUnaryOperator)
251    {
252       readToken();
253       return ExpOperation { op = token.type, exp2 = ExpCast::parse() };
254    }
255    /*
256    else if(nextToken.type == SIZEOF)
257       return ExpSizeof::parse();
258    else if(nextToken.type == ALIGNOF)
259       return ExpAlignOf::parse();
260    */
261    else
262       return parsePostfixExpression();
263 }
264
265 public class ExpConstant : ASTExpression
266 {
267    String constant;
268
269    void print()
270    {
271       Print(constant);
272    }
273
274    ExpConstant ::parse()
275    {
276       return { constant = CopyString(readToken().text); };
277    }
278
279    float Compute()
280    {
281       return (float)atof(constant);
282    }
283 }
284
285 public class ExpString : ASTExpression
286 {
287    String string;
288
289    void print()
290    {
291       Print(string);
292    }
293
294    ExpString ::parse()
295    {
296       return { string = CopyString(readToken().text) };
297    }
298 }
299
300 public class ExpIdentifier : ASTExpression
301 {
302    ASTIdentifier identifier;
303
304    void print()
305    {
306       identifier.print();
307    }
308
309    ExpIdentifier ::parse()
310    {
311       return { identifier = ASTIdentifier::parse() };
312    }
313 }
314
315 public class ExpOperation : ASTExpression
316 {
317    TokenType op;
318    ASTExpression exp1, exp2;
319
320    void print()
321    {
322       if(exp1) { exp1.print(); if(exp2) Print(" "); }
323       op.print();
324       if(exp2) { if(exp1) Print(" "); exp2.print(); }
325    }
326
327    ASTExpression ::parse(int prec)
328    {
329       ASTExpression exp = (prec > 0) ? parse(prec-1) : ExpCast::parse();
330       while(isPrecedence(peekToken().type, prec))
331          exp = ExpOperation { exp1 = exp, op = readToken().type, exp2 = (prec > 0) ? parse(prec-1) : ExpCast::parse() };
332       return exp;
333    }
334
335    float Compute()
336    {
337       if(exp1 && exp2)
338       {
339          switch(op)
340          {
341             case '*': return exp1.Compute() * exp2.Compute();
342             case '/': return exp1.Compute() / exp2.Compute();
343             case '-': return exp1.Compute() - exp2.Compute();
344             case '+': return exp1.Compute() + exp2.Compute();
345          }
346       }
347       else if(exp2)
348       {
349          switch(op)
350          {
351             case '-': return -exp2.Compute();
352             case '+': return  exp2.Compute();
353          }
354       }
355       return 0;
356    }
357 }
358
359 public class ExpAssignment : ExpOperation
360 {
361    ASTExpression ::parse()
362    {
363       ASTExpression exp = ExpConditional::parse();
364       if(peekToken().type.isAssignmentOperator)
365          exp = ExpAssignment { exp1 = exp, op = readToken().type, exp2 = ExpAssignment::parse() };
366       return exp;
367    }
368 }
369
370 public class ExpBrackets : ASTExpression
371 {
372 public:
373    ExpList list;
374
375    void print()
376    {
377       Print("(");
378       if(list) list.print();
379       Print(")");
380    }
381
382    float Compute()
383    {
384       return (list && list.lastIterator.data) ? list.lastIterator.data.Compute() : 0;
385    }
386 }
387
388 public class ExpConditional : ASTExpression
389 {
390 public:
391    ASTExpression condition;
392    ExpList expList;
393    ASTExpression elseExp;
394
395    void print()
396    {
397       if(condition) condition.print();
398       Print(" ? ");
399       if(expList) expList.print();
400       Print(" : ");
401       if(elseExp)
402          elseExp.print();
403    }
404
405    ASTExpression ::parse()
406    {
407       ASTExpression exp = ExpOperation::parse(numPrec-1);
408       if(peekToken().type == '?')
409       {
410          exp = ExpConditional { condition = exp, expList = ExpList::parse() };
411          if(peekToken().type == ':')
412             ((ExpConditional)exp).elseExp = ExpConditional::parse();
413       }
414       return exp;
415    }
416 }
417
418 public class ExpIndex : ASTExpression
419 {
420    ASTExpression exp;
421    ExpList index;
422
423    void print()
424    {
425       if(exp) exp.print();
426       Print("[");
427       if(index) index.print();
428       Print("]");
429    }
430
431    ExpIndex ::parse(ASTExpression e)
432    {
433       ExpIndex exp;
434       readToken();
435       exp = ExpIndex { exp = e, index = ExpList::parse() };
436       if(peekToken().type == ']')
437          readToken();
438       return exp;
439    }
440 }
441
442 public class ExpMember : ASTExpression
443 {
444    ASTExpression exp;
445    ASTIdentifier member;
446    // MemberType memberType;
447    // bool thisPtr;
448
449    void print()
450    {
451       if(exp) exp.print();
452       Print(".");
453       if(member)
454          member.print();
455    }
456
457    ExpMember ::parse(ASTExpression e)
458    {
459       readToken();
460       return { exp = e, member = ASTIdentifier::parse() };
461    }
462 }
463
464 public class ExpPointer : ExpMember
465 {
466    void print()
467    {
468       if(exp) exp.print();
469       Print("->");
470       if(member)
471          member.print();
472    }
473
474    ExpPointer ::parse(ASTExpression e)
475    {
476       readToken();
477       return { exp = e, member = ASTIdentifier::parse() };
478    }
479 }
480
481 public class ExpCall : ASTExpression
482 {
483    ASTExpression exp;
484    ExpList arguments;
485    // Location argLoc;
486
487    void print()
488    {
489       if(exp) exp.print();
490       Print("(");
491       if(arguments) arguments.print();
492       Print(")");
493    }
494
495    ExpCall ::parse(ASTExpression e)
496    {
497       ExpCall exp;
498       readToken();
499       exp = ExpCall { exp = e, arguments = ExpList::parse() };
500       if(peekToken().type == ')')
501          readToken();
502       return exp;
503    }
504 }
505
506 public class ExpCast : ASTExpression
507 {
508    ASTTypeName typeName;
509    ASTExpression exp;
510
511    ASTExpression ::parse()
512    {
513       ASTExpression exp = parseUnaryExpression();
514       // TODO: Deal with cast ambiguity
515       return exp;
516    }
517 }
518
519 public class ExpInstance : ASTExpression
520 {
521    ASTInstantiation instance;
522 }
523 /*
524 public class ExpSizeOf : ASTExpression
525 {
526    ASTTypeName typeName;
527
528    ExpSizeOf ::parse()
529    {
530
531    }
532 }
533
534 public class ExpAlignOf : ASTExpression
535 {
536    ASTTypeName typeName;
537
538    ExpAlignOf ::parse()
539    {
540    }
541 }
542 */
543 /*
544    union
545    {
546       struct
547       {
548          OldList * specifiers;
549          ASTDeclarator decl;
550       } _classExp;
551       struct
552       {
553          Identifier id;
554       } classData;
555       TypeName typeName;
556       Specifier _class;
557       struct
558       {
559          TypeName typeName;
560          Expression size;
561       } _new;
562       struct
563       {
564          TypeName typeName;
565          Expression size;
566          Expression exp;
567       } _renew;
568       struct
569       {
570          char * table;
571          Identifier id;
572       } db;
573       struct
574       {
575          Expression ds;
576          Expression name;
577       } dbopen;
578       struct
579       {
580          TypeName typeName;
581          Initializer initializer;
582       } initializer;
583       struct
584       {
585          Expression exp;
586          TypeName typeName;
587       } vaArg;
588    };
589 };
590 */
591
592 public class InstanceInit : ASTNode { }
593
594 public class InstInitMember : InstanceInit
595 {
596    MemberInitList members;
597 }
598
599 public class InstInitFunction : InstanceInit
600 {
601    ASTClassFunction function;
602 }
603
604 public class ASTInstantiation : ASTNode
605 {
606 public:
607    ASTSpecifier _class;
608    ASTExpression exp;
609    List<InstanceInit> members;
610    Symbol symbol;
611    bool fullSet;
612    bool isConstant;
613    byte * data;
614    Location nameLoc, insideLoc;
615    bool built;
616 };