major improvements to symbol table
authorAaron Becker <abecker3@illinois.edu>
Mon, 18 Aug 2008 20:08:14 +0000 (20:08 +0000)
committerAaron Becker <abecker3@illinois.edu>
Mon, 18 Aug 2008 20:08:14 +0000 (20:08 +0000)
added some type resolution logic
greatly improved efficiency of translation passes
added AST output capability
simplified scope objects
better flow control and less redundancy in main driver
small tweaks to language grammar

src/langs/charj/Makefile
src/langs/charj/bin/charjc
src/langs/charj/src/charj/Main.java
src/langs/charj/src/charj/translator/Charj.g
src/langs/charj/src/charj/translator/CharjAST.java
src/langs/charj/src/charj/translator/CharjSemantics.g
src/langs/charj/src/charj/translator/ClassSymbol.java
src/langs/charj/src/charj/translator/PackageScope.java
src/langs/charj/src/charj/translator/Symbol.java
src/langs/charj/src/charj/translator/SymbolTable.java
src/langs/charj/src/charj/translator/Translator.java

index 27318042bc0ea861417639eabe6fdbd40b87f50a..4c5aa74223e1baa7896a1d8cb4cdeaeb76f93e88 100644 (file)
@@ -14,7 +14,7 @@ all:
        $(ANT) all
 
 test:
-       ./bin/charjc --debug --verbose --stdout tests/Hello.cj
+       ./bin/charjc --debug --verbose --AST --stdout tests/Hello.cj
 
 
 # The lousy antlrv3 ant task won't give proper output from antlr errors, so
index e106cbbc033f563abc08b0edf9235293df694f0d..6247815b81bbb2665c8a5e4a8c93bafd9db37745 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-ECHO="false"                        # should we echo the our command to stdout?
+ECHO="true"                        # should we echo the our command to stdout?
 CHARJCHOME=${0%${0##*/}}            # location of charjc
 ANTLRHOME=$CHARJCHOME/../lib        # location of antlr jars
 ANTLR_VERSION="3.1"
@@ -48,6 +48,9 @@ processArgs() {
             VERBOSE=true
             ARGS="$ARGS $arg"
             ;;
+        "--AST")
+            ARGS="$ARGS $arg"
+            ;;
         "--debug")
             ARGS="$ARGS $arg"
             ;;
index db95c616f47e8738d464694ca7af4523eab72dd3..58d6c6976a44dfe3e8812e25cf8e61fc4224bc2b 100644 (file)
@@ -12,6 +12,7 @@ public class Main
     public static List<String> m_usrlibs;
     public static boolean m_debug;
     public static boolean m_verbose;
+    public static boolean m_printAST;
     public static boolean m_stdout;
 
     public static void main(String[] args) throws Exception
@@ -21,6 +22,7 @@ public class Main
                 m_charmc, 
                 m_debug, 
                 m_verbose,
+                m_printAST,
                 m_stdlib,
                 m_usrlibs);
         for (String filename : files) { 
@@ -74,6 +76,11 @@ public class Main
         _verbose.setHelp("output extra information");
         processor.registerParameter(_verbose);
 
+        Switch _printAST = new Switch("printAST")
+            .setLongFlag("AST");
+        _verbose.setHelp("print abstract syntax tree");
+        processor.registerParameter(_printAST);
+
         Switch _stdout = new Switch("stdout")
             .setShortFlag(JSAP.NO_SHORTFLAG)
             .setLongFlag("stdout");
@@ -102,6 +109,7 @@ public class Main
         m_stdlib = config.getString("stdlib");
         m_debug = config.getBoolean("debug", false);
         m_verbose = config.getBoolean("verbose", false);
+        m_printAST = config.getBoolean("printAST", false);
         m_stdout = config.getBoolean("stdout", false);
         
         String usrlib = config.getString("usrlib");
index d69970a341b8a78a19933471b9898420e3487365..badee37398fd0d98ae9a2207566dad7bda65e431 100644 (file)
@@ -957,13 +957,17 @@ qualifiedIdentExpression
 
 newExpression
     :   NEW  
-        (   primitiveType newArrayConstruction      // new static array of primitive type elements
-            ->  ^(STATIC_ARRAY_CREATOR[$NEW, "STATIC_ARRAY_CREATOR"] primitiveType newArrayConstruction)
-        |   genericTypeArgumentListSimplified? qualifiedTypeIdentSimplified
+            (   primitiveType newArrayConstruction      // new static array of primitive type elements
+                ->  ^(STATIC_ARRAY_CREATOR[$NEW, "STATIC_ARRAY_CREATOR"] primitiveType newArrayConstruction
+            )
+    |   genericTypeArgumentListSimplified? qualifiedTypeIdentSimplified
             (   newArrayConstruction                // new static array of object type reference elements
-                ->  ^(STATIC_ARRAY_CREATOR[$NEW, "STATIC_ARRAY_CREATOR"] genericTypeArgumentListSimplified? qualifiedTypeIdentSimplified newArrayConstruction)
-            |   arguments classBody?                // new object type via constructor invocation
-                ->  ^(CLASS_CONSTRUCTOR_CALL[$NEW, "STATIC_ARRAY_CREATOR"] genericTypeArgumentListSimplified? qualifiedTypeIdentSimplified arguments classBody?)
+                ->  ^(STATIC_ARRAY_CREATOR[$NEW, "STATIC_ARRAY_CREATOR"] 
+                    genericTypeArgumentListSimplified? qualifiedTypeIdentSimplified newArrayConstruction
+            )
+    |   arguments classBody?                // new object type via constructor invocation
+                ->  ^(CLASS_CONSTRUCTOR_CALL[$NEW, "STATIC_ARRAY_CREATOR"] genericTypeArgumentListSimplified? 
+                    qualifiedTypeIdentSimplified arguments classBody?)
             )
         )
     ;
index 8aa3e0b22a7b1c0457180c56eb81821a49342733..53ef518b7c5b241fe909e6f581a5963c5518e406 100644 (file)
@@ -10,6 +10,10 @@ import org.antlr.runtime.CommonToken;
  */
 public class CharjAST extends CommonTree
 {
+    /** Semantic information about this node. Includes type, scope, location
+     * of definition, etc. */
+    public Symbol symbol;
+
     public CharjAST(Token t) {
         super(t);
     }
@@ -17,4 +21,13 @@ public class CharjAST extends CommonTree
     public CharjAST(int type, String text) {
         super(new CommonToken(type, text));
     }
+
+    public String toString() {
+        String s = super.toString();
+        if (symbol != null) {
+            s += "(" + symbol + ")" ;
+        }
+        return s;
+    }
+
 }
index 2fe8a5453fd619dcad86b5f7f92d9f3ff3823c94..7c68965b242170416afefdaad61e4392dd4e80c2 100644 (file)
@@ -11,7 +11,6 @@ options {
     memoize = true;
     tokenVocab = Charj;
     ASTLabelType = CharjAST;
-    output = template;
 }
 
 
@@ -133,10 +132,10 @@ 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 
-        (p=packageDeclaration)? 
-        (i+=importDeclaration)* 
-        (t=typeDeclaration))
-        //(t+=typeDeclaration)*)
+        (packageDeclaration)? 
+        (importDeclaration)* 
+        (typeDeclaration))
+        //(typeDeclaration)*)
         { $cs = null; }
     ;
 
@@ -174,7 +173,7 @@ classExtendsClause
     ;   
 
 interfaceExtendsClause 
-    :   ^(EXTENDS_CLAUSE (typeList+=type)+) 
+    :   ^(EXTENDS_CLAUSE (type)+) 
     ;   
     
 implementsClause
@@ -203,7 +202,7 @@ enumConstant
     
     
 classTopLevelScope
-    :   ^(CLASS_TOP_LEVEL_SCOPE (csd+=classScopeDeclarations)*) 
+    :   ^(CLASS_TOP_LEVEL_SCOPE (classScopeDeclarations)*) 
     ;
     
 classScopeDeclarations
@@ -268,7 +267,7 @@ throwsClause
     ;
 
 modifierList
-    :   ^(MODIFIER_LIST (m+=modifier)*)
+    :   ^(MODIFIER_LIST (modifier)*)
     ;
 
 modifier
@@ -306,14 +305,14 @@ typeIdent
     ;
 
 primitiveType
-    :   BOOLEAN
-    |   CHAR
-    |   BYTE
-    |   SHORT
-    |   INT
-    |   LONG
-    |   FLOAT
-    |   DOUBLE
+    :   BOOLEAN     { $start.symbol = new Symbol(symtab, "bool_primitive", symtab.resolveBuiltinType("bool")); }
+    |   CHAR        { $start.symbol = new Symbol(symtab, "char_primitive", symtab.resolveBuiltinType("char")); }
+    |   BYTE        { $start.symbol = new Symbol(symtab, "byte_primitive", symtab.resolveBuiltinType("char")); }
+    |   SHORT       { $start.symbol = new Symbol(symtab, "short_primitive", symtab.resolveBuiltinType("short")); }
+    |   INT         { $start.symbol = new Symbol(symtab, "int_primitive", symtab.resolveBuiltinType("int")); }
+    |   LONG        { $start.symbol = new Symbol(symtab, "long_primitive", symtab.resolveBuiltinType("long")); }
+    |   FLOAT       { $start.symbol = new Symbol(symtab, "float_primitive", symtab.resolveBuiltinType("float")); }
+    |   DOUBLE      { $start.symbol = new Symbol(symtab, "double_primitive", symtab.resolveBuiltinType("double")); }
     ;
 
 genericTypeArgumentList
@@ -348,9 +347,7 @@ qualifiedIdentifier
     ;
     
 block
-@init { boolean emptyBlock = true; }
-    :   ^(BLOCK_SCOPE (b+=blockStatement)*)
-        { emptyBlock = ($b == null || $b.size() == 0); }
+    :   ^(BLOCK_SCOPE (blockStatement)*)
     ;
     
 blockStatement
@@ -535,7 +532,7 @@ literal
     |   DECIMAL_LITERAL
     |   FLOATING_POINT_LITERAL
     |   CHARACTER_LITERAL
-    |   STRING_LITERAL
+    |   STRING_LITERAL          
     |   TRUE
     |   FALSE
     |   NULL
index 097540dcfe9f51e0416142dcb7852794ef1908af..8c8cdab7d20218f30c3f014fffed6fe0d33ae0a4 100644 (file)
@@ -33,7 +33,7 @@ public class ClassSymbol extends SymbolWithScope implements Scope {
             String name) 
     {
         super(symtab, name);
-        type = this;;
+        type = this;
         for (String pkg : SymbolTable.AUTO_IMPORTS) {
             importPackage(pkg);
         }
@@ -42,8 +42,7 @@ public class ClassSymbol extends SymbolWithScope implements Scope {
     public ClassSymbol(
             SymbolTable symtab, 
             String name,
-            ClassSymbol
-            superClass,
+            ClassSymbol superClass,
             Scope scope)
     {
         this(symtab, name);
@@ -249,18 +248,6 @@ public class ClassSymbol extends SymbolWithScope implements Scope {
         return name;
     }
 
-    public String getFullyQualifiedJavaName() 
-    {
-        String parent = null;
-        if ( scope!=null ) { // in a package?
-            parent = scope.getFullyQualifiedJavaName();
-        }
-        if ( parent!=null ) {
-            return parent+"."+getMangledName();
-        }
-        return name;
-    }
-
     public String getMangledName() 
     {
         if ( SymbolTable.TYPE_NAMES_TO_MANGLE.contains(name) ) {
index eeccdda79e03e1d12d426a481f7847b0b4d3e151..02f5572bc5cf53f29d83a38c7c2ae2f48b5ce6c9 100644 (file)
@@ -26,7 +26,7 @@ public class PackageScope extends SymbolWithScope {
 
     /** See if type is already defined in this package.  If not, look
      *  for type on the disk in same package.  For example, first time
-     *  charj.io.File fails to resolve.  Load from disk and put File
+     *  charj.lang.Chare fails to resolve.  Load from disk and put File
      *  in package io which is in package charj.  Next time, File will
      *  be found.
      */
@@ -62,14 +62,6 @@ public class PackageScope extends SymbolWithScope {
         return super.getFullyQualifiedName();
     }
 
-    public String getFullyQualifiedJavaName() 
-    {
-        if ( name.equals(SymbolTable.DEFAULT_PACKAGE_NAME) ) {
-            return null;
-        }
-        return super.getFullyQualifiedJavaName();
-    }
-
     public String toString() 
     {
         return "PackageScope[" + name + "]: " + members.keySet();
index 0ce4c6e89a1da755ad64ca6618937796f3e26830..14b71b2b1e36224f538ddc72ee3e21ada5a06bf7 100644 (file)
@@ -38,9 +38,7 @@ public class Symbol {
         type = _type;
     }
 
-    /** Some mantra types and methods must be mangled before
-     *  emitting to Java like int.
-     */
+    /** Just in case we need to do some name mangling */
     public String getMangledName() 
     {
         return name;
@@ -50,4 +48,15 @@ public class Symbol {
     {
         return symtab.translator.debug();
     }
+
+    public String toString() {
+        String info = "";
+        if (name != null)
+            info += name + ", ";
+        if (type != null)
+            info += type + ", ";
+        if (scope != null)
+            info += scope;
+        return "Symbol(" + info + ")";
+    }
 }
index 7c23bcd4c63e8065f26a280a00c8c709bb9143e2..6f0262c63897cc4f4c21f158fd46d68765250a6b 100644 (file)
@@ -20,6 +20,9 @@ public class SymbolTable {
     public static final Set<String> METHOD_NAMES_TO_MANGLE = 
         new HashSet<String>() { {} };
 
+    public static Map<String, ClassSymbol> primitiveTypes =
+        new HashMap<String, ClassSymbol>() { {} };
+
     /** Provides runtime variables and loads classes */
     public Translator translator;
 
@@ -31,7 +34,7 @@ public class SymbolTable {
     /** This is the list of all scopes created during symbol table building. */
     public List scopes = new ArrayList();
 
-    /** Root of the object hierarchy, Charj.Object */
+    /** Root of the object hierarchy, Charj.lang.Object */
     ClassSymbol objectRoot;
 
     public SymbolTable(Translator _translator) 
@@ -42,6 +45,7 @@ public class SymbolTable {
         topLevelPackageScopes.put(DEFAULT_PACKAGE_NAME, defaultPkg);
         PackageScope lang = definePackage("charj.lang");
         addScope(defaultPkg);
+        initObjectHierarchy();
     }
 
     public boolean debug() {
@@ -54,9 +58,17 @@ public class SymbolTable {
         objectRoot = new ClassSymbol(this, "Object", null, lang);
         objectRoot.define("EOF", new VariableSymbol(this,"EOF",null));
         lang.define("Object", objectRoot);
+
+        primitiveTypes.put("int",    new ClassSymbol(this, "int",    null, lang));
+        primitiveTypes.put("float",  new ClassSymbol(this, "float",  null, lang));
+        primitiveTypes.put("double", new ClassSymbol(this, "double", null, lang));
+        primitiveTypes.put("char",   new ClassSymbol(this, "char",   null, lang)); 
+        primitiveTypes.put("short",  new ClassSymbol(this, "short",  null, lang)); 
     }
 
-    public ClassSymbol resolveBuiltInType(String type) {
+    public ClassSymbol resolveBuiltinType(String type) {
+        ClassSymbol ptype = primitiveTypes.get(type);
+        if (ptype != null) return ptype;
         return objectRoot.resolveType(type);
     }
 
index bf8a497e7f64b07c8637d024e8433437df91dfbd..2949e0a347d0504bb83dda1ef1f964fa1ee50214 100644 (file)
@@ -24,23 +24,28 @@ public class Translator {
     private boolean m_debug;
     private boolean m_verbose;
     private boolean m_errorCondition;
+    private boolean m_printAST;
 
     // library locations to search for classes
     private String m_stdlib;
     private List<String> m_usrlibs;
 
     private SymbolTable m_symtab;
+    private CommonTree m_ast;
+    private CommonTreeNodeStream m_nodes;
 
     public Translator(
             String _charmc,
             boolean _debug,
             boolean _verbose,
+            boolean _printAST,
             String _stdlib,
             List<String> _usrlibs)
     {
         m_charmc    = _charmc;
         m_debug     = _debug;
         m_verbose   = _verbose;
+        m_printAST  = _printAST;
         m_stdlib    = _stdlib;
         m_usrlibs   = _usrlibs;
         m_symtab    = new SymbolTable(this);
@@ -68,19 +73,33 @@ public class Translator {
         ANTLRFileStream input = new ANTLRFileStream(filename);
             
         CharjLexer lexer = new CharjLexer(input);
+        CommonTokenStream tokens = new CommonTokenStream(lexer);
 
-        semanticPass(lexer);
+        // Use lexer tokens to feed tree parser
+        CharjParser parser = new CharjParser(tokens);
+        parser.setTreeAdaptor(m_adaptor);
+        CharjParser.charjSource_return r = parser.charjSource();
 
-        input.seek(0);
-        String ciOutput = translationPass(lexer, OutputMode.ci);
+        // Create node stream for AST traversals
+        m_ast = (CommonTree)r.getTree();
+        m_nodes = new CommonTreeNodeStream(m_ast);
+        m_nodes.setTokenStream(tokens);
+        m_nodes.setTreeAdaptor(m_adaptor);
+
+        printAST("Before Semantic Pass");
+        semanticPass();
+        printAST("After Semantic Pass");
+
+        m_nodes.reset();
+        String ciOutput = translationPass(OutputMode.ci);
         writeTempFile(filename, ciOutput, OutputMode.ci);
 
-        input.seek(0);
-        String hOutput = translationPass(lexer, OutputMode.h);
+        m_nodes.reset();
+        String hOutput = translationPass(OutputMode.h);
         writeTempFile(filename, hOutput, OutputMode.h);
         
-        input.seek(0);
-        String ccOutput = translationPass(lexer, OutputMode.cc);
+        m_nodes.reset();
+        String ccOutput = translationPass(OutputMode.cc);
         writeTempFile(filename, ccOutput, OutputMode.cc);
         compileTempFiles(filename, m_charmc);
 
@@ -94,57 +113,17 @@ public class Translator {
             ccHeader + ccOutput + footer;
     }
 
-    private CommonTreeNodeStream prepareNodes(
-            CommonTokenStream tokens,
-            CharjLexer lexer) throws
+    private ClassSymbol semanticPass() throws
         RecognitionException, IOException, InterruptedException
     {
-        // Use lexer tokens to feed tree parser
-        CharjParser parser = new CharjParser(tokens);
-        parser.setTreeAdaptor(m_adaptor);
-        CharjParser.charjSource_return r = parser.charjSource();
-
-        // Create node stream for emitters
-        CommonTree t = (CommonTree)r.getTree();
-        CommonTreeNodeStream nodes = new CommonTreeNodeStream(t);
-        nodes.setTokenStream(tokens);
-        nodes.setTreeAdaptor(m_adaptor);
-        return nodes;
+        CharjSemantics sem = new CharjSemantics(m_nodes);
+        return sem.charjSource(m_symtab);
     }
 
-    private String translationPass(
-            CharjLexer lexer, 
-            OutputMode m) throws
+    private String translationPass(OutputMode m) throws
         RecognitionException, IOException, InterruptedException
     {
-        CommonTokenStream tokens = new CommonTokenStream(lexer);
-        CommonTreeNodeStream nodes = prepareNodes(tokens, lexer);
-        nodes.setTokenStream(tokens);
-        nodes.setTreeAdaptor(m_adaptor);
-
-        String output = emit(nodes, m);
-        return output;
-    }
-
-    private ClassSymbol semanticPass(CharjLexer lexer) throws
-        RecognitionException, IOException, InterruptedException
-    {
-        CommonTokenStream tokens = new CommonTokenStream(lexer);
-        CommonTreeNodeStream nodes = prepareNodes(tokens, lexer);
-        nodes.setTokenStream(tokens);
-        nodes.setTreeAdaptor(m_adaptor);
-
-        CharjSemantics sem = new CharjSemantics(nodes);
-        ClassSymbol cs = sem.charjSource(m_symtab).cs;
-        return cs;
-    }
-
-    private String emit(
-            CommonTreeNodeStream nodes, 
-            OutputMode m) throws
-        RecognitionException, IOException, InterruptedException
-    {
-        CharjEmitter emitter = new CharjEmitter(nodes);
+        CharjEmitter emitter = new CharjEmitter(m_nodes);
         StringTemplateGroup templates = getTemplates(templateFile);
         emitter.setTemplateLib(templates);
         StringTemplate st = 
@@ -152,8 +131,6 @@ public class Translator {
         return st.toString();
     }
 
-
-
     private StringTemplateGroup getTemplates(String templateFile)
     {
         StringTemplateGroup templates = null;
@@ -241,7 +218,7 @@ public class Translator {
             fs.name = packageDir + "/" + typeName + ".cj";
             CharjLexer lexer = new CharjLexer(fs);
             
-            cs = semanticPass(lexer);
+            cs = semanticPass();
         } catch (Exception e) {
             e.printStackTrace();
         }
@@ -349,6 +326,19 @@ public class Translator {
         int retVal = p.exitValue();
         return retVal;
     }
+
+    public void printAST(String message)
+    {
+        String header = "----------\n" + "AST: " + message + "\n----------\n";
+        String footer = "\n----------\n";
+        String body = null;
+        if (m_printAST && m_ast != null) {
+            body = m_ast.toStringTree();
+        } else if (m_printAST) {
+            body = "Null tree, no AST available";
+        }
+        System.out.println(header + body + footer);
+    }
     
     public void error(
             BaseRecognizer recog,