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