Charj: add support for readonly variables
authorAaron Becker <akbecker@gmail.com>
Tue, 1 Jun 2010 10:44:40 +0000 (05:44 -0500)
committerAaron Becker <akbecker@gmail.com>
Tue, 1 Jun 2010 10:44:40 +0000 (05:44 -0500)
src/langs/charj/src/charj/translator/Charj.g
src/langs/charj/src/charj/translator/Charj.stg
src/langs/charj/src/charj/translator/CharjASTModifier.g
src/langs/charj/src/charj/translator/CharjEmitter.g
src/langs/charj/src/charj/translator/CharjSemantics.g

index bac135126374628754be9d18cb60637ceadc7d70..8138c33b44d118ce65790b8ea84fd5cc1b17a4e1 100644 (file)
@@ -52,6 +52,7 @@ tokens {
     GROUP                   = 'group'           ;
     NODEGROUP               = 'nodegroup'       ;
     ENUM                    = 'enum'            ;
+    READONLY                = 'readonly'        ;
 
     FOR                     = 'for'             ;
     WHILE                   = 'while'           ;
@@ -216,8 +217,13 @@ charjSource
 
 compilationUnit
     :   packageDeclaration? 
-        importDeclaration* 
-        typeDeclaration*
+        topLevelDeclaration+ 
+    ;
+
+topLevelDeclaration
+    :   importDeclaration
+    |   readonlyDeclaration
+    |   typeDeclaration
     ;
 
 packageDeclaration
@@ -229,6 +235,10 @@ importDeclaration
     :   IMPORT^ qualifiedIdentifier '.*'? ';'!
     ;
 
+readonlyDeclaration
+    :   READONLY^ localVariableDeclaration ';'!
+    ;
+
 typeDeclaration
     :   classDefinition
     |   interfaceDefinition
index 098481bf7f886a14d043321a88e3843d7ef69ffc..a28910c4c1d6d35f2f9ee01077b61b541bd656f2 100644 (file)
@@ -1,15 +1,21 @@
 group Charj;
 
-charjSource_ci(basename, pd, ids, tds, debug) ::=
+charjSource_ci(basename, pd, imports, types, ros, debug) ::=
 <<
 
 // interface for <basename>
-<tds; separator="\n\n">
+<imports; separator="\n">
+<types; separator="\n\n">
+<if(ros)>
 
+module readonly_<basename> {
+    <ros; separator="\n">
+}
+<endif>
 >>
 
 
-charjSource_h(basename, pd, ids, tds, debug) ::=
+charjSource_h(basename, pd, imports, types, ros, debug) ::=
 <<
 #ifndef __<basename>__
 #define __<basename>__
@@ -21,20 +27,55 @@ charjSource_h(basename, pd, ids, tds, debug) ::=
  * It is not meant to be edited by hand and may be overwritten by charjc. *
  **************************************************************************/
 
-<ids>
-<tds; separator="\n\n">
+<imports; separator="\n">
+<types; separator="\n\n">
+<if(ros)>
+/* Readonly variables */
+<readonlys_h(pds = pd, ros = ros)>
+#include "<basename>_readonly.decl.h"
+<endif>
+
 
 #endif // __<basename>__
 
->>
 
+>>
 
-charjSource_cc(basename, pd, ids, tds, debug) ::=
+charjSource_cc(basename, pd, imports, types, ros, debug) ::=
 <<
 #include "<basename>.h"
 
-<ids>
-<tds; separator="\n\n">
+<imports; separator="\n">
+<types; separator="\n\n">
+<if(ros)>
+
+/* Readonly variable support */
+<readonlys_cc(pds = pd, basename = basename)>
+<endif>
+
+
+>>
+
+readonlys_h(pds, ros) ::=
+<<
+<if(first(pds))>namespace <first(pds)>
+{
+    <readonlys_h(pds = rest(pds), ros = ros)>
+} // namespace <first(pds)>
+<else>
+<ros; separator="\n">
+<endif>
+>>
+
+readonlys_cc(pds, basename) ::=
+<<
+<if(first(pds))>namespace <first(pds)>
+{
+    <readonlys_cc(pds = rest(pds), basename = basename)>
+} // namespace <first(pds)>
+<else>
+#include "<basename>_readonly.def.h"
+<endif>
 
 >>
 
@@ -65,10 +106,25 @@ type_preamble_h(sym) ::=
 }>
 >>
 
+chare_preamble_h(sym) ::=
+<<
+<type_preamble_h(sym)>
+>>
+
+type_epilogue_h(sym) ::=
+<<
+>>
+
+chare_epilogue_h(sym) ::=
+<<
+<type_epilogue_h(sym)>
+>>
+
 classDeclaration_h(sym, ident, ext, csds) ::=
 <<
 <type_preamble_h(sym)>
 <classDeclaration_h_cont(pds = sym.packageNames, sym = sym, ident = ident, ext = ext, csds = csds)>
+<type_epilogue_h(sym)>
 >>
 
 classDeclaration_h_cont(pds, sym, ident, ext, csds) ::=
@@ -127,9 +183,10 @@ chareDeclaration_cc_cont(pds, sym, ident, ext, csds) ::=
 
 chareDeclaration_h(sym, ident, ext, csds) ::=
 <<
-<type_preamble_h(sym)>
+<chare_preamble_h(sym)>
 #include "<ident>.decl.h"
 <chareDeclaration_h_cont(pds = sym.packageNames, sym = sym, ident = ident, ext = ext, csds = csds)>
+<chare_epilogue_h(sym)>
 >>
 
 chareDeclaration_h_cont(pds, sym, ident, ext, csds) ::=
index 12476d031b2771e4d8b5c4c64e877e2def80ef49..29e30e7577da4833e3c6ab8c250596db77aa0d56 100644 (file)
@@ -44,21 +44,25 @@ charjSource[SymbolTable _symtab] returns [ClassSymbol cs]
     // TODO: go back to allowing multiple type definitions per file, check that
     // there is exactly one public type and return that one.
     :   ^(CHARJ_SOURCE 
-        (packageDeclaration)? 
-        (importDeclarations) 
-        (typeDeclaration[$importDeclarations.packageNames])*)
-        { $cs = $typeDeclaration.sym; }
+        packageDeclaration?
+        importDeclaration*
+        readonlyDeclaration*
+        (typeDeclaration { $cs = $typeDeclaration.sym; })*)
     ;
 
 packageDeclaration
     :   ^(PACKAGE (ids+=IDENT)+)  
     ;
     
-importDeclarations returns [List<CharjAST> packageNames]
-    :   (^(IMPORT qualifiedIdentifier '.*'?))*
+importDeclaration
+    :   ^(IMPORT qualifiedIdentifier '.*'?)
     ;
 
-typeDeclaration[List<CharjAST> imports] returns [ClassSymbol sym]
+readonlyDeclaration
+    :   ^(READONLY localVariableDeclaration)
+    ;
+
+typeDeclaration returns [ClassSymbol sym]
     :   ^(TYPE (CLASS | chareType) IDENT (^('extends' parent=type))? (^('implements' type+))? classScopeDeclaration*)
         {
             $TYPE.tree.addChild(astmod.getPupRoutineNode());
@@ -130,7 +134,7 @@ variableDeclarator
 variableDeclaratorId
     :   ^(IDENT arrayDeclaratorList?)
         {
-            astmod.varPup($IDENT);
+            if (currentClass != null) astmod.varPup($IDENT);
         }
     ;
 
index b125704bfb039927bb13bad5f68ccd2309d408a4..aa392746a5090c3f988ac491c2211b99c3923da4 100644 (file)
@@ -84,14 +84,20 @@ charjSource[SymbolTable symtab, OutputMode m]
     this.mode_ = m;
 }
     :   ^(CHARJ_SOURCE (p=packageDeclaration)? 
-        (i+=importDeclaration)* 
+        (i+=importDeclaration)*
+        (r+=readonlyDeclaration)*
         (t+=typeDeclaration)*)
-        -> {emitCC()}? charjSource_cc(basename={basename()}, pd={$p.names}, ids={$i}, tds={$t}, debug={debug()})
-        -> {emitCI()}? charjSource_ci(basename={basename()}, pd={$p.names}, ids={$i}, tds={$t}, debug={debug()})
-        -> {emitH()}? charjSource_h(basename={basename()}, pd={$p.names}, ids={$i}, tds={$t}, debug={debug()})
+        -> {emitCC()}? charjSource_cc(basename={basename()}, pd={$p.names}, imports={$i}, types={$t}, ros={$r}, debug={debug()})
+        -> {emitCI()}? charjSource_ci(basename={basename()}, pd={$p.names}, imports={$i}, types={$t}, ros={$r}, debug={debug()})
+        -> {emitH()}? charjSource_h(basename={basename()}, pd={$p.names}, imports={$i}, types={$t}, ros={$r}, debug={debug()})
         ->
     ;
 
+topLevelDeclaration
+    :   importDeclaration -> {$importDeclaration.st;}
+    |   typeDeclaration -> {$typeDeclaration.st;}
+    ;
+
 packageDeclaration returns [List names]
     :   ^('package' (ids+=IDENT)+)
         {
@@ -99,6 +105,13 @@ packageDeclaration returns [List names]
         }
         ->
     ;
+
+readonlyDeclaration
+    :   ^(READONLY lvd=localVariableDeclaration)
+        -> {emitCI()}? template(bn={basename()}, v={$lvd.st}) "readonly <v>"
+        -> {emitH()}? template(v={$lvd.st}) "extern <v>"
+        ->
+    ;
     
 importDeclaration
 @init {
index 5036f9987e425baf90f12260285fc291dd86daa0..60aa19bfdbf7cf0f7060db46c9208760c57b3b18 100644 (file)
@@ -28,6 +28,7 @@ package charj.translator;
     MethodSymbol currentMethod = null;
     LocalScope currentLocalScope = null;
     Translator translator;
+    List<CharjAST> imports = new ArrayList<CharjAST>();
 
     /**
      *  Test a list of CharjAST nodes to see if any of them has the given token
@@ -62,6 +63,10 @@ package charj.translator;
             }
         }
     }
+
+    public void addImport(CharjAST importNode) {
+        imports.add(importNode);
+    }
 }
 
 
@@ -81,13 +86,11 @@ scope ScopeStack; // default scope
     symtab = _symtab;
     $ScopeStack::current = symtab.getDefaultPkg();
 }
-    // TODO: go back to allowing multiple type definitions per file, check that
-    // there is exactly one public type and return that one.
     :   ^(CHARJ_SOURCE 
         (packageDeclaration)? 
-        (importDeclarations) 
-        (typeDeclaration[$importDeclarations.packageNames])*)
-        { $cs = $typeDeclaration.sym; }
+        (importDeclaration
+        | typeDeclaration { $cs = $typeDeclaration.sym; }
+        | readonlyDeclaration)*)
     ;
 
 // note: no new scope here--this replaces the default scope
@@ -109,16 +112,16 @@ packageDeclaration
         }
     ;
     
-importDeclarations returns [List<CharjAST> packageNames]
-@init {
-    packageNames = new ArrayList<CharjAST>();
-}
-    :   (^(IMPORT qualifiedIdentifier '.*'?)
-               { packageNames.add($qualifiedIdentifier.start); })*
+importDeclaration
+    :   ^(IMPORT qualifiedIdentifier '.*'?)
+        { addImport($qualifiedIdentifier.start); }
     ;
 
+readonlyDeclaration
+    :   ^(READONLY localVariableDeclaration)
+    ;
 
-typeDeclaration[List<CharjAST> imports] returns [ClassSymbol sym]
+typeDeclaration returns [ClassSymbol sym]
 scope ScopeStack; // top-level type scope
     :   ^(TYPE classType IDENT
             (^('extends' parent=type))? (^('implements' type+))?
@@ -145,7 +148,7 @@ scope ScopeStack; // top-level type scope
                     currentClass.isChare = true;
                     currentClass.isMainChare = true;
                 } else System.out.println("Error: type " + classTypeName + " not recognized.");
-                importPackages($sym, $imports);
+                importPackages($sym, imports);
             }
             classScopeDeclaration*)
             {
@@ -335,7 +338,7 @@ String name = "";
         {
             $type = null;
             //System.out.println("trying to resolve type " + name + " in type " + currentClass);
-            $type = currentClass.resolveType(name);
+            if (currentClass != null) $type = currentClass.resolveType(name);
             //System.out.println("got " + $type);
             //if ($type == null) $type = symtab.resolveBuiltinType(name);
             $QUALIFIED_TYPE_IDENT.symbol = $type;