Author: dda
Date: 2007-12-12 13:56:08 -0800 (Wed, 12 Dec 2007)
New Revision: 7524

Modified:
   
openlaszlo/branches/devildog/WEB-INF/lps/server/sc/src/org/openlaszlo/sc/parser/ASTIdentifier.java
   
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/CommonGenerator.java
   
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/Compiler.java
   
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9Generator.java
   
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/Translator.java
Log:
Change 20071212-dda-n by [EMAIL PROTECTED] on 2007-12-12 16:28:59 EST
    in /Users/dda/laszlo/src/svn/openlaszlo/branches/devildog
    for http://svn.openlaszlo.org/openlaszlo/branches/devildog

Summary: SWF9 changes to get LzNode to build

New Features: none

Bugs Fixed: LPP-5234

Technical Reviewer: ptw (pending)
QA Reviewer: hminsky (pending)
Doc Reviewer: (pending)

Documentation: none

Release Notes: none

Details:
    Changes to get buildlfc (using just LzNode) to complete:

 +  program variables -- those vars that are declared outside
    of any method or class, are now treated as globals, going
    into their own file.  Since some names use $ (like $swf9),
    they must be in file $varname.as, and we now take care to show these
    on debug output as \$varname.as on Unix to make it easier to cut
    and paste.  We do not do this escape for the command line handed
    to the system, I don't believe this is necessary.

 +  with the new handling of program variables, removed the implicit
    'with (lzApplicationInstance)' that was being inserted.

 +  more debugging - each /tmp/lzswf9/* directory now has three new debug
    files: source.txt, program.txt, progdump.txt showing various views
    of the program at different stages of processing.  This is very
    helpful for debugging.  At the current time, they are conditional
    on a DEBUG_OUTPUT variable in SWF9Generator, this will probably change
    to a command line option.

 +  added -debug=true option to compile command line, this is also controlled
    by a class variable, and should be a command line option eventually.

Tests:
  Only running buildlfc in devildog



Modified: 
openlaszlo/branches/devildog/WEB-INF/lps/server/sc/src/org/openlaszlo/sc/parser/ASTIdentifier.java
===================================================================
--- 
openlaszlo/branches/devildog/WEB-INF/lps/server/sc/src/org/openlaszlo/sc/parser/ASTIdentifier.java
  2007-12-12 21:55:18 UTC (rev 7523)
+++ 
openlaszlo/branches/devildog/WEB-INF/lps/server/sc/src/org/openlaszlo/sc/parser/ASTIdentifier.java
  2007-12-12 21:56:08 UTC (rev 7524)
@@ -18,6 +18,15 @@
         public String typeName = null;
         public boolean nullable = false; // has "?"
         public boolean notnullable = false; // has "!"
+
+        public String toString() {
+            String result = typeName;
+            if (nullable)
+                result += "?";
+            if (notnullable)
+                result += "!";
+            return result;
+        }
     }
 
     public ASTIdentifier(int id) {
@@ -65,12 +74,7 @@
     public String toString() {
         String typesuffix = "";
         if (type != null) {
-            typesuffix = ": ";
-            if (type.nullable)
-                typesuffix += "?";
-            typesuffix += type.typeName;
-            if (type.notnullable)
-                typesuffix += "!";
+            typesuffix = ": " + type.toString();
         }
         return "ASTIdentifier(" + name + typesuffix + ")";
     }

Modified: 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/CommonGenerator.java
===================================================================
--- 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/CommonGenerator.java
  2007-12-12 21:55:18 UTC (rev 7523)
+++ 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/CommonGenerator.java
  2007-12-12 21:56:08 UTC (rev 7524)
@@ -105,6 +105,13 @@
     setRuntime(this.runtime);
   }
 
+  // Give the generators an option to save the original
+  // input source for debugging.
+
+  public void setOriginalSource(String source) {
+    // no action by default
+  }
+
   public InstructionCollector getCollector() {
     return collector;
   }

Modified: 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/Compiler.java
===================================================================
--- 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/Compiler.java
 2007-12-12 21:55:18 UTC (rev 7523)
+++ 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/Compiler.java
 2007-12-12 21:56:08 UTC (rev 7524)
@@ -344,6 +344,7 @@
           cg = new JavascriptGenerator();
         }
         cg.setOptions(options);
+        cg.setOriginalSource(source);
         SimpleNode translated = cg.translate(program);
         List tunits = cg.makeTranslationUnits(translated, compress, obfuscate);
         bytes = cg.postProcess(tunits);
@@ -351,6 +352,7 @@
       } else {
         cg = new CodeGenerator();
         cg.setOptions(options);
+        cg.setOriginalSource(source);
         cg.translate(program);
         if (options.getBoolean(PROGRESS)) {
           System.err.println("Assembling...");

Modified: 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9Generator.java
===================================================================
--- 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9Generator.java
    2007-12-12 21:55:18 UTC (rev 7523)
+++ 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9Generator.java
    2007-12-12 21:56:08 UTC (rev 7524)
@@ -32,18 +32,50 @@
  */
 public class SWF9Generator extends JavascriptGenerator {
 
+  // TODO: [2007-12-12 dda] make DEBUG_OUTPUT a compiler option.
+  /**
+   * When set, some extra debugging files are saved.
+   */
+  public static final boolean DEBUG_OUTPUT = true;
+
+  // TODO: [2007-12-12 dda] make USE_COMPILER_DEBUG_FLAG a compiler option.
+  /**
+   * When set, use the debug flag for the compiler
+   */
+  public static final boolean USE_COMPILER_DEBUG_FLAG = true;
+
+  /**
+   * Saved program node, to show during debugging
+   */
+  SimpleNode savedProgram = null;
+
+  /**
+   * Saved source, to show during debugging
+   */
+  String savedSource = null;
+
+  /**
+   * Any 'program' variables, which will become globals.
+   */
   Map programVars = new HashMap();
 
-  // this is set when we are visiting class definitions.
-  // The 'default' class is implicit and will encompass everything else.
-  //
-  // Use of this variable to save state during 'visit' calls means that
-  // visit methods are not reentrant.  This is not really
-  // a new concern in the generators, as compiler options are often
-  // twiddled as we parse.
-  //
-  boolean inNonDefaultClass = false;
+  /**
+   * The 'default' class is implicit and encompasses everything
+   * not declared within an explicit 'class' definition.  This variable
+   * is set when we are outside of exlicit classes.
+   *
+   * Use of this variable to save state during 'visit' calls means that
+   * visit methods are not reentrant.  This is not really
+   * a new concern in the generators, as compiler options are often
+   * twiddled as we parse.
+   */
+  boolean inDefaultClass = true;
 
+  /*
+   * inMethod is set when we are visiting any method.
+   */
+  boolean inMethod = false;
+
   // override superclass version - we don't want to remap names
   // of class variables
 
@@ -100,13 +132,13 @@
     }
     node.setChildren(newch);
 
-    boolean savedInNonDefault = inNonDefaultClass;
-    inNonDefaultClass = true;
+    boolean savedInDefault = inDefaultClass;
+    inDefaultClass = false;
     try {
       visitChildren(node);
     }
     finally {
-      inNonDefaultClass = savedInNonDefault;
+      inDefaultClass = savedInDefault;
     }
 
     return node;
@@ -117,53 +149,48 @@
    * We keep track of variables that are implicitly global.
    */
   public SimpleNode visitVariableDeclaration(SimpleNode node, SimpleNode[] 
children) {
-    if (options.getBoolean(Compiler.SCRIPT_ELEMENT)) {
+    if (inDefaultClass && !inMethod) {
+      String initializer = null;
       if (children.length > 1) {
-        String idname = ((ASTIdentifier)children[0]).getName();
-        programVars.put(idname, idname);
+        initializer = (new SWF9ParseTreePrinter()).text(children[1]);
       }
+      if (children.length > 0) {
+        ASTIdentifier id = (ASTIdentifier)children[0];
+        ASTIdentifier.Type type = id.getType();
+        addGlobalVar(id.getName(), type == null ? null : type.toString(), 
initializer);
+        return node;
+      }
     }
     return super.visitVariableDeclaration(node, children);
   }
 
+  public void setOriginalSource(String source) {
+    savedSource = source;
+  }
+
   /**
    * Intercept JavascriptGenerator version.
-   * We insert a with (this) or with (defaultApplication)
-   * as appropriate.
+   * We keep a copy of the original program so we can emit it
+   * for debugging purposes.
    */
+  public SimpleNode translate(SimpleNode program) {
+    savedProgram = program;
+    return super.translate(program);
+  }
+
+  /**
+   * Intercept JavascriptGenerator version, just to
+   * track that we are within a function.
+   */
   public SimpleNode translateFunction(SimpleNode node, boolean isReferenced, 
SimpleNode[] children) {
-    int stmtPos = children.length - 1;
-    SimpleNode stmts = children[stmtPos];
-    assert stmts instanceof ASTStatementList;
-    List stmtList = new ArrayList(Arrays.asList(stmts.getChildren()));
-    boolean needsApp = false;
-    for (int i = 0, len = stmtList.size(); i < len; i++) {
-      SimpleNode stmt = (SimpleNode)stmtList.get(i);
-      if (stmt instanceof ASTPragmaDirective) {
-        String key = (String)((ASTLiteral)stmt.getChildren()[0]).getValue();
-        if (key.equals("withThis")) {
-          needsApp = true;
-          break;
-        }
-      } else {
-        break;
-      }
-    }
 
-    // TODO: [2007-12-11 dda] always reference the app?  rethink this.
-    // needsApp is set unconditionally for now to get through some
-    // test cases
-    needsApp = true;
-    if (needsApp) {
-      String withVariable = (inNonDefaultClass ? "lzApplicationInstance" : 
"this");
-
-      Map map = new HashMap();
-      map.put("_1", new Compiler.Splice(stmts.getChildren()));
-      //      SimpleNode newNode = (new 
Compiler.Parser()).substitute("(function () { with (lzApplicationInstance) { _1 
}})()", map);
-      SimpleNode newNode = (new Compiler.Parser()).substituteStmt("with (" + 
withVariable + ") { _1 }", map);
-      children[stmtPos] = visitStatement(newNode);
+    boolean savedInMethod = inMethod;
+    try {
+      return super.translateFunction(node, isReferenced, children);
     }
-    return super.translateFunction(node, isReferenced, children);
+    finally {
+      inMethod = savedInMethod;
+    }
   }
 
 
@@ -211,6 +238,39 @@
     reader.close();
   }
 
+  public static class GlobalVariable {
+    String name;
+    String type;
+    String initializer;
+  }
+
+  private String checkGlobalValue(String valueName, String curval, String 
newval, String emsg) {
+    if (curval != null && newval != null && !curval.equals(newval))
+        throw new CompilerError(valueName + ": variable declared twice with " +
+                                emsg + ": \"" +
+                                curval + "\" and \"" + newval + "\"");
+    if (curval != null)
+      return curval;
+    else
+      return newval;
+  }
+
+  private void addGlobalVar(String name, String type, String initializer)
+  {
+    GlobalVariable glovar = (GlobalVariable)programVars.get(name);
+    if (glovar == null) {
+      glovar = new GlobalVariable();
+      glovar.name = name;
+      glovar.type = type;
+      glovar.initializer = initializer;
+      programVars.put(name, glovar);
+    }
+    else {
+      glovar.type = checkGlobalValue(name, glovar.type, type, "different 
types");
+      glovar.initializer = checkGlobalValue(name, glovar.initializer, 
initializer, "different initializers");
+    }
+  }
+
   private File tempdir = null;
   public File getCompilationTempDir()
   {
@@ -440,11 +500,26 @@
     }
   }
 
+  /**
+   * Return a more nicely formatted command line.
+   * On UNIX systems, we change '$' to \$' so the
+   * output line can be cut and pasted into a shell.
+   */
+  public String prettyCommand(String cmd)
+  {
+    String osname = System.getProperty("os.name");
+    if (!osname.startsWith("Windows")) {
+      // goodness, both $ and \ are special characters for regex.
+      cmd = cmd.replaceAll("[$]", "\\\\\\$");
+    }
+    return cmd;
+  }
+
   public void execCompileCommand(String cmd, String dir, List tunits,
                                  String outfileName)
     throws IOException          // TODO: [2007-11-20 dda] clean up, why catch 
only some exceptions?
   {
-    System.err.println("Executing compiler: (cd " + dir + "; " + cmd + ")");
+    System.err.println("Executing compiler: (cd " + dir + "; " + 
prettyCommand(cmd) + ")");
     Process proc = Runtime.getRuntime().exec(cmd, null, new File(dir));
     try {
       OutputStream os = proc.getOutputStream();
@@ -545,6 +620,8 @@
       cmd += " -compiler.show-actionscript-warnings=false";
     cmd += " -compiler.source-path+=.";
     cmd += " -library-path+=" + getLFCLibrary();
+    if (USE_COMPILER_DEBUG_FLAG)
+      cmd += " -debug=true";
     cmd += " -output " + swcfilebase;
     cmd += " --";
     for (Iterator iter = tunits.iterator(); iter.hasNext(); ) {
@@ -568,6 +645,8 @@
     cmd += " -compiler.source-path+=.";
     cmd += " -library-path+=" + getLFCLibrary();
     cmd += " -library-path+=" + swcfilename;
+    if (USE_COMPILER_DEBUG_FLAG)
+      cmd += " -debug=true";
     cmd += " -output " + outfilebase;
     cmd += " _stubapp";
 
@@ -616,14 +695,79 @@
   public static final String DEFAULT_FILE_PREAMBLE = "package {\n";
   public static final String DEFAULT_FILE_EPILOG = "}\n";
 
+  // This is used for debugging only, so errors are ignored.
+  public interface TextEmitter {
+    void emit(Writer writer)
+      throws IOException;
+  }
+
+  public static void emitFile(String filename, TextEmitter tw) {
+    FileWriter writer = null;
+    try {
+      File f = new File(filename);
+      f.delete();
+      writer = new FileWriter(f);
+      tw.emit(writer);
+      writer.close();
+      writer = null;
+    }
+    catch (IOException ioe) {
+      System.err.println("Cannot write to " + filename);
+      if (writer != null) {
+        try {
+          writer.close();
+        }
+        catch (IOException ioe2) {
+          // ignored.
+        }
+      }
+    }
+  }
+
+  public static void emitFile(String filename, final String txt) {
+    emitFile(filename, new TextEmitter() {
+        public void emit(Writer writer)
+          throws IOException {
+          writer.write(txt);
+        }
+      });
+  }
+
+  public static void emitFile(String filename, final SimpleNode node) {
+    emitFile(filename, new TextEmitter() {
+        public void emit(Writer writer)
+          throws IOException {
+          nodeFileDump(writer, "", node);
+        }
+      });
+  }
+
+  public static void nodeFileDump(Writer writer, String prefix, SimpleNode 
node)
+    throws IOException
+  {
+    writer.write(node.toString(prefix) + "\n");
+    SimpleNode[] children = node.getChildren();
+    if (children != null) {
+      for (int i = 0; i < children.length; ++i) {
+        SimpleNode n = (SimpleNode)children[i];
+        if (n != null) {
+          nodeFileDump(writer, prefix + " ", n);
+        }
+      }
+    }
+  }
+
   public byte[] postProcess(List tunits)
   {
     String tempdir = getCompilationTempDir().getPath();
     boolean hasErrors = false;
     String apptype = null;
 
-    TranslationUnit globalVar = null;
-    List globalVars = new ArrayList();
+    if (DEBUG_OUTPUT) {
+      emitFile(tempdir + File.separator + "source.txt", savedSource);
+      emitFile(tempdir + File.separator + "program.txt", (new 
SWF9ParseTreePrinter()).text(savedProgram));
+      emitFile(tempdir + File.separator + "progdump.txt", savedProgram);
+    }
 
     for (Iterator iter = tunits.iterator(); iter.hasNext(); ) {
       TranslationUnit tunit = (TranslationUnit)iter.next();
@@ -646,24 +790,36 @@
 
         epilog = "\n}" + epilog;
 
-        globalVar = new TranslationUnit();
-        globalVar.setName("lzApplicationInstance");
-        globalVar.addText("public var lzApplicationInstance:" + name + " = 
null;");
-        globalVars.add(globalVar);
-        
-        for (Iterator variter = programVars.keySet().iterator(); 
variter.hasNext(); ) {
-          String varname = (String)variter.next();
-          globalVar = new TranslationUnit();
-          globalVar.setName(varname);
-          globalVar.addText("public var " + varname + " = null;");
-          globalVars.add(globalVar);
-        }
-        programVars = new HashMap();
-
+        addGlobalVar("lzApplicationInstance", name, null);
       }
       writeOutputFile(name, preamble, tunit.getContents(), epilog);
     }
-    for (Iterator iter = globalVars.iterator(); iter.hasNext(); ) {
+
+    // For each global variable defined in programVars,
+    // write it to its own translation unit.
+
+    List glotunits = new ArrayList();
+    for (Iterator variter = programVars.keySet().iterator(); 
variter.hasNext(); ) {
+      String varname = (String)variter.next();
+      GlobalVariable glovar = (GlobalVariable)programVars.get(varname);
+
+      TranslationUnit tunit = new TranslationUnit();
+      tunit.setName(varname);
+      String decl = "public var " + varname;
+      if (glovar.type != null)
+        decl += ":" + glovar.type;
+      if (glovar.initializer != null)
+        decl += " = " + glovar.initializer;
+      decl += ";";
+      tunit.addText(decl);
+      glotunits.add(tunit);
+    }
+    programVars = new HashMap();
+
+    // Emit the global variable translation units, and
+    // add them to the final list.
+
+    for (Iterator iter = glotunits.iterator(); iter.hasNext(); ) {
       TranslationUnit tunit = (TranslationUnit)iter.next();
       writeOutputFile(tunit.getName(), DEFAULT_FILE_PREAMBLE,
                       tunit.getContents(), DEFAULT_FILE_EPILOG);

Modified: 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/Translator.java
===================================================================
--- 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/Translator.java
       2007-12-12 21:55:18 UTC (rev 7523)
+++ 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/Translator.java
       2007-12-12 21:56:08 UTC (rev 7524)
@@ -22,6 +22,8 @@
 
   public void setOptions(Compiler.OptionMap options);
 
+  public void setOriginalSource(String source);
+
   public SimpleNode translate(SimpleNode program);
 
   public InstructionCollector getCollector();


_______________________________________________
Laszlo-checkins mailing list
[email protected]
http://www.openlaszlo.org/mailman/listinfo/laszlo-checkins

Reply via email to