lots of code gen improvements, working on symtab import
[charm.git] / src / langs / charj / src / charj / translator / CharjSemantics.g
1 /**
2  * The semantic phase walks the tree and builds the symbol table, handles
3  * all the imports, and does the semantic checks. The resulting tree and
4  * symbol table are used by the emitter to generate the output. 
5  */
6
7 tree grammar CharjSemantics;
8
9 options {
10     backtrack = true; 
11     memoize = true;
12     tokenVocab = Charj;
13     ASTLabelType = CharjAST;
14 }
15
16 scope ScopeStack {
17     Scope current;
18 }
19
20 @header {
21 package charj.translator;
22 }
23
24 @members {
25     SymbolTable symtab = null;
26
27     PackageScope currentPackage = null;
28     ClassSymbol currentClass = null;
29     MethodSymbol currentMethod = null;
30     LocalScope currentLocalScope = null;
31
32     Translator translator;
33
34     boolean m_messageCollectionEnabled = false;
35     private boolean m_hasErrors = false;
36     List<String> m_messages;
37
38     /**
39      *  Switches error message collection on or off.
40      *
41      *  The standard destination for parser error messages is 
42      *  <code>System.err</code>.
43      *  However, if <code>true</code> gets passed to this method this default
44      *  behaviour will be switched off and all error messages will be collected
45      *  instead of written to anywhere.
46      *
47      *  The default value is <code>false</code>.
48      *
49      *  @param newState  <code>true</code> if error messages should be collected.
50      */
51     public void enableErrorMessageCollection(boolean newState) {
52         m_messageCollectionEnabled = newState;
53         if (m_messages == null && m_messageCollectionEnabled) {
54             m_messages = new ArrayList<String>();
55         }
56     }
57     
58     /**
59      *  Collects an error message or passes the error message to <code>
60      *  super.emitErrorMessage(...)</code>.
61      *
62      *  The actual behaviour depends on whether collecting error messages
63      *  has been enabled or not.
64      *
65      *  @param message  The error message.
66      */
67      @Override
68     public void emitErrorMessage(String message) {
69         if (m_messageCollectionEnabled) {
70             m_messages.add(message);
71         } else {
72             super.emitErrorMessage(message);
73         }
74     }
75     
76     /**
77      *  Returns collected error messages.
78      *
79      *  @return  A list holding collected error messages or <code>null</code> if
80      *           collecting error messages hasn't been enabled. Of course, this
81      *           list may be empty if no error message has been emited.
82      */
83     public List<String> getMessages() {
84         return m_messages;
85     }
86     
87     /**
88      *  Tells if parsing a Charj source has caused any error messages.
89      *
90      *  @return  <code>true</code> if parsing a Charj source has caused at 
91      *           least one error message.
92      */
93     public boolean hasErrors() {
94         return m_hasErrors;
95     }
96
97     /**
98      *  Test a list of CharjAST nodes to see if any of them has the given token
99      *  type.
100      */
101     public boolean listContainsToken(List<CharjAST> list, int tokenType) {
102         for (CharjAST node : list) {
103             if (node.token.getType() == tokenType) {
104                 return true;
105             }
106         }
107         return false;
108     }
109
110     public void importPackages(ClassSymbol cs, List<CharjAST> imports) {
111         if (imports == null) {
112             return;
113         }
114
115         for (CharjAST pkg : imports) {
116             String pkgName = input.getTokenStream().toString(
117                     pkg.getTokenStartIndex(),
118                     pkg.getTokenStopIndex());
119             // find imported class and add to cs.imports
120             PackageScope p = cs.importPackage(pkgName);
121             if (p == null) {
122                 translator.error(
123                     this, 
124                     "package " + pkgName + " not found.",
125                     pkg);
126             }
127         }
128     }
129
130 }
131
132 // Starting point for parsing a Charj file.
133 charjSource[SymbolTable _symtab] returns [ClassSymbol cs]
134 scope ScopeStack; // default scope
135 @init {
136     symtab = _symtab;
137     $ScopeStack::current = symtab.getDefaultPkg();
138 }
139     // TODO: go back to allowing multiple type definitions per file, check that
140     // there is exactly one public type and return that one.
141     :   ^(CHARJ_SOURCE 
142         (packageDeclaration)? 
143         (importDeclarations) 
144         (typeDeclaration[$importDeclarations.packageNames]))
145         //(typeDeclaration)*)
146         { $cs = $typeDeclaration.sym; }
147     ;
148
149 // note: no new scope here--this replaces the default scope
150 packageDeclaration
151 @init { 
152     List<String> names = null; 
153 }
154     :   ^(PACKAGE qualifiedIdentifier)  {
155             String packageName = $qualifiedIdentifier.text;
156             PackageScope ps = symtab.resolvePackage(packageName);
157             if (ps == null) {
158                 ps = symtab.definePackage(packageName);
159                 symtab.addScope(ps);
160             }
161             currentPackage = ps;
162             $ScopeStack::current = ps;
163             $qualifiedIdentifier.start.symbol = ps;
164         }
165     ;
166     
167 importDeclarations returns [List<CharjAST> packageNames]
168 @init {
169         packageNames = new ArrayList<CharjAST>();
170 }
171     :   (^(IMPORT STATIC? qualifiedIdentifier DOTSTAR?)
172                 { packageNames.add($qualifiedIdentifier.start); })*
173     ;
174
175
176 typeDeclaration[List<CharjAST> imports] returns [ClassSymbol sym]
177 scope ScopeStack; // top-level type scope
178     :   ^(CLASS m=modifierList IDENT g=genericTypeParameterList? 
179                 e=classExtendsClause? i=implementsClause? c=classTopLevelScope) 
180         {
181             Scope outerScope = $ScopeStack[-1]::current;
182             $sym = new ClassSymbol(symtab, $IDENT.text, null, outerScope);
183             outerScope.define($sym.name, $sym);
184             currentClass = $sym;
185             $sym.definition = $typeDeclaration.start;
186             $sym.definitionTokenStream = input.getTokenStream();
187             $IDENT.symbol = $sym;
188             $ScopeStack::current = $sym;
189                         importPackages($sym, $imports);
190         }
191     |   ^(INTERFACE modifierList IDENT genericTypeParameterList? 
192                 interfaceExtendsClause? interfaceTopLevelScope)
193     |   ^(ENUM modifierList IDENT implementsClause? enumTopLevelScope)
194     ;
195
196
197 classExtendsClause
198     :   ^(EXTENDS_CLAUSE t=type) 
199     ;   
200
201 interfaceExtendsClause 
202     :   ^(EXTENDS_CLAUSE (type)+) 
203     ;   
204     
205 implementsClause
206     :   ^(IMPLEMENTS_CLAUSE type+)
207     ;
208         
209 genericTypeParameterList
210     :   ^(GENERIC_TYPE_PARAM_LIST genericTypeParameter+)
211     ;
212
213 genericTypeParameter
214     :   ^(IDENT bound?)
215     ;
216         
217 bound
218     :   ^(EXTENDS_BOUND_LIST type+)
219     ;
220
221 enumTopLevelScope
222     :   ^(ENUM_TOP_LEVEL_SCOPE enumConstant+ classTopLevelScope?)
223     ;
224     
225 enumConstant
226     :   ^(IDENT arguments? classTopLevelScope?)
227     ;
228     
229     
230 classTopLevelScope
231     :   ^(CLASS_TOP_LEVEL_SCOPE (classScopeDeclarations)*) 
232     ;
233     
234 classScopeDeclarations
235     :   ^(CLASS_INSTANCE_INITIALIZER block)
236     |   ^(CLASS_STATIC_INITIALIZER block)
237     |   ^(FUNCTION_METHOD_DECL m=modifierList g=genericTypeParameterList? 
238             ty=type IDENT f=formalParameterList a=arrayDeclaratorList? 
239             tc=throwsClause? b=block?)
240     |   ^(VOID_METHOD_DECL m=modifierList g=genericTypeParameterList? IDENT 
241             f=formalParameterList t=throwsClause? b=block?)
242     |   ^(PRIMITIVE_VAR_DECLARATION modifierList simpleType variableDeclaratorList)
243     |   ^(OBJECT_VAR_DECLARATION modifierList objectType variableDeclaratorList)
244     |   ^(CONSTRUCTOR_DECL m=modifierList g=genericTypeParameterList? IDENT f=formalParameterList 
245             t=throwsClause? b=block)
246     |   d=typeDeclaration[null]
247     ;
248     
249 interfaceTopLevelScope
250     :   ^(INTERFACE_TOP_LEVEL_SCOPE interfaceScopeDeclarations*)
251     ;
252     
253 interfaceScopeDeclarations
254     :   ^(FUNCTION_METHOD_DECL modifierList genericTypeParameterList? type IDENT formalParameterList arrayDeclaratorList? throwsClause?)
255     |   ^(VOID_METHOD_DECL modifierList genericTypeParameterList? IDENT formalParameterList throwsClause?)
256         // Interface constant declarations have been switched to variable
257         // declarations by Charj.g; the parser has already checked that
258         // there's an obligatory initializer.
259     |   ^(PRIMITIVE_VAR_DECLARATION modifierList simpleType variableDeclaratorList)
260     |   ^(OBJECT_VAR_DECLARATION modifierList objectType variableDeclaratorList)
261     |   typeDeclaration[null]
262     ;
263
264 variableDeclaratorList
265     :   ^(VAR_DECLARATOR_LIST variableDeclarator+)
266     ;
267
268 variableDeclarator
269     :   ^(VAR_DECLARATOR variableDeclaratorId variableInitializer?)
270     ;
271     
272 variableDeclaratorId
273     :   ^(IDENT arrayDeclaratorList?)
274     ;
275
276 variableInitializer
277     :   arrayInitializer
278     |   expression
279     ;
280
281 arrayDeclarator
282     :   LBRACK RBRACK
283     ;
284
285 arrayDeclaratorList
286     :   ^(ARRAY_DECLARATOR_LIST ARRAY_DECLARATOR*)  
287     ;
288     
289 arrayInitializer
290     :   ^(ARRAY_INITIALIZER variableInitializer*)
291     ;
292
293 throwsClause
294     :   ^(THROWS_CLAUSE qualifiedIdentifier+)
295     ;
296
297 modifierList
298     :   ^(MODIFIER_LIST (modifier)*)
299     ;
300
301 modifier
302     :   PUBLIC
303     |   PROTECTED
304     |   PRIVATE
305     |   ENTRY
306     |   STATIC
307     |   ABSTRACT
308     |   NATIVE
309     |   SYNCHRONIZED
310     |   TRANSIENT
311     |   VOLATILE
312     |   localModifier
313     ;
314
315 localModifierList
316     :   ^(LOCAL_MODIFIER_LIST localModifier*)
317     ;
318
319 localModifier
320     :   FINAL
321     ;
322
323 type
324     :   simpleType
325     |   objectType 
326     ;
327
328 simpleType
329     :   ^(TYPE primitiveType arrayDeclaratorList?)
330     ;
331     
332 objectType
333     :   ^(TYPE qualifiedTypeIdent arrayDeclaratorList?)
334     ;
335
336 qualifiedTypeIdent
337     :   ^(QUALIFIED_TYPE_IDENT typeIdent+) 
338     ;
339
340 typeIdent
341     :   ^(IDENT genericTypeArgumentList?)
342     ;
343
344 primitiveType
345     :   BOOLEAN     { $start.symbol = new Symbol(symtab, "bool_primitive", symtab.resolveBuiltinType("bool")); }
346     |   CHAR        { $start.symbol = new Symbol(symtab, "char_primitive", symtab.resolveBuiltinType("char")); }
347     |   BYTE        { $start.symbol = new Symbol(symtab, "byte_primitive", symtab.resolveBuiltinType("char")); }
348     |   SHORT       { $start.symbol = new Symbol(symtab, "short_primitive", symtab.resolveBuiltinType("short")); }
349     |   INT         { $start.symbol = new Symbol(symtab, "int_primitive", symtab.resolveBuiltinType("int")); }
350     |   LONG        { $start.symbol = new Symbol(symtab, "long_primitive", symtab.resolveBuiltinType("long")); }
351     |   FLOAT       { $start.symbol = new Symbol(symtab, "float_primitive", symtab.resolveBuiltinType("float")); }
352     |   DOUBLE      { $start.symbol = new Symbol(symtab, "double_primitive", symtab.resolveBuiltinType("double")); }
353     ;
354
355 genericTypeArgumentList
356     :   ^(GENERIC_TYPE_ARG_LIST genericTypeArgument+)
357     ;
358     
359 genericTypeArgument
360     :   type
361     |   ^(QUESTION genericWildcardBoundType?)
362     ;
363
364 genericWildcardBoundType                                                                                                                      
365     :   ^(EXTENDS type)
366     |   ^(SUPER type)
367     ;
368
369 formalParameterList
370     :   ^(FORMAL_PARAM_LIST formalParameterStandardDecl* formalParameterVarargDecl?) 
371     ;
372     
373 formalParameterStandardDecl
374     :   ^(FORMAL_PARAM_STD_DECL localModifierList type variableDeclaratorId)
375     ;
376     
377 formalParameterVarargDecl
378     :   ^(FORMAL_PARAM_VARARG_DECL localModifierList type variableDeclaratorId)
379     ;
380     
381 qualifiedIdentifier
382     :   IDENT
383     |   ^(DOT qualifiedIdentifier IDENT)
384     ;
385     
386 block
387     :   ^(BLOCK_SCOPE (blockStatement)*)
388     ;
389     
390 blockStatement
391     :   localVariableDeclaration
392     |   typeDeclaration[null]
393     |   statement
394     ;
395     
396 localVariableDeclaration
397     :   ^(PRIMITIVE_VAR_DECLARATION localModifierList simpleType variableDeclaratorList)
398     |   ^(OBJECT_VAR_DECLARATION localModifierList objectType variableDeclaratorList)
399     ;
400
401
402 statement
403     :   block
404     |   ^(ASSERT expression expression?)
405     |   ^(IF parenthesizedExpression statement statement?)
406     |   ^(FOR forInit forCondition forUpdater statement)
407     |   ^(FOR_EACH localModifierList type IDENT expression statement) 
408     |   ^(WHILE parenthesizedExpression statement)
409     |   ^(DO statement parenthesizedExpression)
410     |   ^(TRY block catches? block?)  // The second optional block is the optional finally block.
411     |   ^(SWITCH parenthesizedExpression switchBlockLabels)
412     |   ^(SYNCHRONIZED parenthesizedExpression block)
413     |   ^(RETURN expression?)
414     |   ^(THROW expression)
415     |   ^(BREAK IDENT?)
416     |   ^(CONTINUE IDENT?)
417     |   ^(LABELED_STATEMENT IDENT statement)
418     |   expression
419     |   ^(EMBED STRING_LITERAL EMBED_BLOCK)
420     |   SEMI // Empty statement.
421     ;
422         
423 catches
424     :   ^(CATCH_CLAUSE_LIST catchClause+)
425     ;
426     
427 catchClause
428     :   ^(CATCH formalParameterStandardDecl block)
429     ;
430
431 switchBlockLabels
432     :   ^(SWITCH_BLOCK_LABEL_LIST switchCaseLabel* switchDefaultLabel? switchCaseLabel*)
433     ;
434         
435 switchCaseLabel
436     :   ^(CASE expression blockStatement*)
437     ;
438     
439 switchDefaultLabel
440     :   ^(DEFAULT blockStatement*)
441     ;
442     
443 forInit
444     :   ^(FOR_INIT (localVariableDeclaration | expression*)?)
445     ;
446     
447 forCondition
448     :   ^(FOR_CONDITION expression?)
449     ;
450     
451 forUpdater
452     :   ^(FOR_UPDATE expression*)
453     ;
454     
455 // EXPRESSIONS
456
457 parenthesizedExpression
458     :   ^(PARENTESIZED_EXPR expression)
459     ;
460     
461 expression
462     :   ^(EXPR expr)
463     ;
464
465 expr
466     :   ^(ASSIGN expr expr)
467     |   ^(PLUS_ASSIGN expr expr)
468     |   ^(MINUS_ASSIGN expr expr)
469     |   ^(STAR_ASSIGN expr expr)
470     |   ^(DIV_ASSIGN expr expr)
471     |   ^(AND_ASSIGN expr expr)
472     |   ^(OR_ASSIGN expr expr)
473     |   ^(XOR_ASSIGN expr expr)
474     |   ^(MOD_ASSIGN expr expr)
475     |   ^(BIT_SHIFT_RIGHT_ASSIGN expr expr)
476     |   ^(SHIFT_RIGHT_ASSIGN expr expr)
477     |   ^(SHIFT_LEFT_ASSIGN expr expr)
478     |   ^(QUESTION expr expr expr)
479     |   ^(LOGICAL_OR expr expr)
480     |   ^(LOGICAL_AND expr expr)
481     |   ^(OR expr expr)
482     |   ^(XOR expr expr)
483     |   ^(AND expr expr)
484     |   ^(EQUAL expr expr)
485     |   ^(NOT_EQUAL expr expr)
486     |   ^(INSTANCEOF expr type)
487     |   ^(LESS_OR_EQUAL expr expr)
488     |   ^(GREATER_OR_EQUAL expr expr)
489     |   ^(BIT_SHIFT_RIGHT expr expr)
490     |   ^(SHIFT_RIGHT expr expr)
491     |   ^(GREATER_THAN expr expr)
492     |   ^(SHIFT_LEFT expr expr)
493     |   ^(LESS_THAN expr expr)
494     |   ^(PLUS expr expr)
495     |   ^(MINUS expr expr)
496     |   ^(STAR expr expr)
497     |   ^(DIV expr expr)
498     |   ^(MOD expr expr)
499     |   ^(UNARY_PLUS expr)
500     |   ^(UNARY_MINUS expr)
501     |   ^(PRE_INC expr)
502     |   ^(PRE_DEC expr)
503     |   ^(POST_INC expr)
504     |   ^(POST_DEC expr)
505     |   ^(NOT expr)
506     |   ^(LOGICAL_NOT expr)
507     |   ^(CAST_EXPR type expr)
508     |   primaryExpression
509     ;
510     
511 primaryExpression
512     :   ^(  DOT
513             (   primaryExpression
514                 (   IDENT
515                 |   THIS
516                 |   SUPER
517                 |   innerNewExpression
518                 |   CLASS
519                 )
520             |   primitiveType CLASS
521             |   VOID CLASS
522             )
523         )
524     |   parenthesizedExpression
525     |   IDENT
526     |   ^(METHOD_CALL primaryExpression genericTypeArgumentList? arguments)
527     |   explicitConstructorCall
528     |   ^(ARRAY_ELEMENT_ACCESS primaryExpression expression)
529     |   literal
530     |   newExpression
531     |   THIS
532     |   arrayTypeDeclarator
533     |   SUPER
534     ;
535     
536 explicitConstructorCall
537     :   ^(THIS_CONSTRUCTOR_CALL genericTypeArgumentList? arguments)
538     |   ^(SUPER_CONSTRUCTOR_CALL primaryExpression? genericTypeArgumentList? arguments)
539     ;
540
541 arrayTypeDeclarator
542     :   ^(ARRAY_DECLARATOR (arrayTypeDeclarator | qualifiedIdentifier | primitiveType))
543     ;
544
545 newExpression
546     :   ^(  STATIC_ARRAY_CREATOR
547             (   primitiveType newArrayConstruction
548             |   genericTypeArgumentList? qualifiedTypeIdent newArrayConstruction
549             )
550         )
551     |   ^(CLASS_CONSTRUCTOR_CALL genericTypeArgumentList? qualifiedTypeIdent arguments classTopLevelScope?)
552     ;
553
554 innerNewExpression // something like 'InnerType innerType = outer.new InnerType();'
555     :   ^(CLASS_CONSTRUCTOR_CALL genericTypeArgumentList? IDENT arguments classTopLevelScope?)
556     ;
557     
558 newArrayConstruction
559     :   arrayDeclaratorList arrayInitializer
560     |   expression+ arrayDeclaratorList?
561     ;
562
563 arguments
564     :   ^(ARGUMENT_LIST expression*)
565     ;
566
567 literal 
568     :   HEX_LITERAL
569     |   OCTAL_LITERAL
570     |   DECIMAL_LITERAL
571     |   FLOATING_POINT_LITERAL
572     |   CHARACTER_LITERAL
573     |   STRING_LITERAL          
574     |   TRUE
575     |   FALSE
576     |   NULL
577     ;