Skip to content
Browse files

Merge branch 'master' of github.com:Whiteknight/jaesop

  • Loading branch information...
2 parents 4343c8c + 484a8a2 commit 8478c3b66b67b35112332ab58707ddc51f19dae5 @Whiteknight committed Sep 10, 2011
Showing with 178 additions and 61 deletions.
  1. +34 −0 stage0/README.md
  2. +11 −3 stage0/js/nodes.js
  3. +113 −58 stage0/js/wast.js
  4. +20 −0 t/stage0/try_catch.t
View
34 stage0/README.md
@@ -0,0 +1,34 @@
+The purpose of the stage 0 compiler is to be a suitable bootstrapping tool
+for writing a JavaScript compiler in JavaScript. Stage 0 does not intend to
+be complete or perfect. It will be a subset, missing certain features.
+
+Here we list the items which are purposefully omitted from the compiler, and
+the items which are intended to be included but which have not yet been
+implemented.
+
+## Known Feature Omissions:
+
+The stage 0 compiler is not a full or complete JavaScript compiler. Some
+features have been purposefully omitted and will not be supported:
+
+* `with` will not be supported
+* Primitive strings do not autobox to String. Must use `newString(...)`
+
+## Features Not Yet Implemented:
+
+This is a list of items which are yet to be done, but should be implemented
+before stage 0 is called "complete" and usable for stage 1:
+
+* switch/case/default statements
+* continue/break statements
+* new String()
+* methods on Object
+* methods on Array
+* pcre bindings and RegExpExpr
+* Handling empty statements
+
+## Features to Maybe Implement:
+
+These features might or might not need to be implemented:
+
+* `arguments`
View
14 stage0/js/nodes.js
@@ -310,7 +310,10 @@ def(stmt,'ReturnStmt', {
def(stmt,'TryStmt', {
toWast : function() {
- return errorWast(this.nodeType);
+ var w = getWast("TryStatement");
+ w.setTryBlock(this.children[0].toWast());
+ w.setCatchClause(this.children[1].toWast());
+ return w;
}
});
@@ -324,13 +327,18 @@ def(stmt,'BlockStmt', {
def(node,'CatchClause', {
toWast : function() {
- return errorWast(this.nodeType);
+ var w = getWast("CatchClause");
+ w.setExceptionVar(this.children[0].toWast());
+ w.setCatchBlock(this.children[1].toWast());
+ return w;
}
});
def(stmt,'ThrowStmt', {
toWast : function() {
- return errorWast(this.nodeType);
+ var w = getWast("ThrowStatement");
+ w.setPayload(this.children[0].toWast());
+ return w;
}
});
View
171 stage0/js/wast.js
@@ -4,7 +4,7 @@ var constructors = exports.constructors = [];
var FUNC_INDENT = "";
var STMT_INDENT = " ";
var ARG_INDENT = " ";
-var BLCK_INDENT = " ";
+var BLCK_INDENT = " ";
var FUNC_ENTRY = " /* Standard preamble */\n" +
" using JavaScript.__fetch_global;\n" +
" using JavaScript.__store_global;\n" +
@@ -74,7 +74,8 @@ var wast = prototypes.base = {
},
winxedValue : function(v) { w.literalValue = v; },
- toWinxed : function(g, l) { return "[!!! Wast error: " + this.nodeType + " has no .toWinxed() method !!!]"; },
+ toWinxed : function(st) { return "[!!! Wast error: " + this.nodeType + " has no .toWinxed() method !!!]"; },
+ wrapWinxed : function(st) { return this.toWinxed(st); },
toWinxedError : function(msg) { return "[!!! Wast error: " + msg + " !!!]"; }
}
@@ -103,6 +104,16 @@ var def = function def(proto, name, extend, construct) {
var expr = prototypes.expr = wast.clone();
var stmt = prototypes.stmt = wast.clone();
+var blck = prototypes.blck = wast.clone({
+ wrapWinxed : function(st) {
+ var lines = this.toWinxed(st).split("\n");
+ var wx = STMT_INDENT + lines[0] + "\n";
+ for (var i = 1; i < lines.length - 1; i++)
+ wx += BLCK_INDENT + lines[i] + "\n";
+ wx += STMT_INDENT + lines[lines.length - 1];
+ return wx;
+ }
+});
def(wast, "Program", {
addFunction: function(f) { this.children.push(f); },
@@ -128,7 +139,7 @@ def(wast, "Program", {
" var __f;\n";
wx += this.children.map(function(c) {
if (c.name != null) {
- var name = c.name.toWinxed(st);
+ var name = c.name.wrapWinxed(st);
st.addGlobal(name);
return " using " + name + ";\n" +
" __f = box_function(" + name + ");\n" +
@@ -140,12 +151,14 @@ def(wast, "Program", {
" /* Call the real main function */\n" +
" __js_main__(arguments);\n" +
" } catch (__e__) {\n" +
- " say(__e__.message);\n" +
+ " string __msg__ = string(__e__.payload);\n" +
+ " if (__msg__ == null) __msg__ = string(__e__.message);\n" +
+ " say(__msg__);\n" +
" for (string bt in __e__.backtrace_strings())\n" +
" say(bt);\n" +
" }\n" +
"}\n\n";
- wx += this.children.map(function(c) { return c.toWinxed(); }).join("\n\n") + "\n";
+ wx += this.children.map(function(c) { return c.wrapWinxed(); }).join("\n\n") + "\n";
//wx += "} // JavaScript HLL\n";
return wx;
}
@@ -159,7 +172,7 @@ def(wast, "MainFunctionDecl", {
var wx = "function __js_main__[anon](var argumentss)\n" +
"{\n" +
FUNC_ENTRY;
- var stmts = this.children.map(function(c) { return STMT_INDENT + c.toWinxed(st); }).join(";\n");
+ var stmts = this.children.map(function(c) { return STMT_INDENT + c.wrapWinxed(st) + ";\n"; }).join("");
var fwd_fetch = "";
for (var g in st_globals) {
@@ -173,7 +186,7 @@ def(wast, "MainFunctionDecl", {
wx += fwd_fetch;
wx += STMT_INDENT + "/* Begin user code */\n" +
- stmts + (stmts == "" ? "" : ";\n") +
+ stmts + "\n" +
STMT_INDENT + "/* End user code */\n" +
"}";
return wx;
@@ -187,11 +200,11 @@ def(wast, "FunctionDecl", {
toWinxed : function() {
var st = new SymbolTable(null);
st.declareVarsLocally(true);
- var this_name = this.name.toWinxed(st);
- var wx = "function " + this_name + "[anon] (" + this.args.toWinxed(st) + ")\n" +
+ var this_name = this.name.wrapWinxed(st);
+ var wx = "function " + this_name + "[anon] (" + this.args.wrapWinxed(st) + ")\n" +
"{\n" +
FUNC_ENTRY;
- var stmts = this.children.map(function(c) { return STMT_INDENT + c.toWinxed(st); }).join(";\n");
+ var stmts = this.children.map(function(c) { return STMT_INDENT + c.wrapWinxed(st) + ";\n"; }).join("\n");
var fwd_fetch = "";
for (var gul in st.globals_seen_locally) {
@@ -219,8 +232,8 @@ def(wast, "ClosureDecl", {
addStatement : function(s) { this.children.push(s); },
toWinxed : function(st) {
st = new SymbolTable(st);
- var wx = "JavaScript.JSObject.box_function(function (" + this.args.map(function(a) { return a.toWinxed(st); }).join(", ") + ") {\n";
- var stmts = this.children.map(function(c) { return "\n" + BLCK_INDENT + c.toWinxed(st); }).join(";");
+ var wx = "JavaScript.JSObject.box_function(function (" + this.args.map(function(a) { return a.wrapWinxed(st); }).join(", ") + ") {\n";
+ var stmts = this.children.map(function(c) { return "\n" + BLCK_INDENT + c.wrapWinxed(st); }).join(";");
for (var gsl in st.globals_seen_locally)
wx += BLCK_INDENT + "var " + gsl + " = __fetch_global('" + gsl + "');\n";
wx += stmts +
@@ -232,7 +245,7 @@ def(wast, "ClosureDecl", {
def(stmt, "ReturnStatement", {
addValue : function(v) { this.children.push(v); },
toWinxed : function() {
- return "return " + (this.children.length == 1 ? this.children[0].toWinxed() : "");
+ return "return " + (this.children.length == 1 ? this.children[0].wrapWinxed() : "");
}
});
@@ -245,7 +258,7 @@ def(expr, "Literal", {
def(wast, "ParametersList", {
addParameter : function(p) { this.children.push(p); },
toWinxed : function(st) {
- return this.children.map(function(c) { return c.toWinxed(st) + ", "; }).join("") +
+ return this.children.map(function(c) { return c.wrapWinxed(st) + ", "; }).join("") +
"var this [named,optional]";
}
});
@@ -272,13 +285,13 @@ def(stmt, "VariableDeclare", {
// In a normal function. Declare the variable like normal.
wx = "var " + n;
if (this.initializer != null)
- wx += " = " + this.initializer.toWinxed(st);
+ wx += " = " + this.initializer.wrapWinxed(st);
st.addLocal(n);
} else {
// In the top-level scope. The variable is already declared as a
// global. Initialize it if necessary, otherwise do nothing.
if (this.initializer != null)
- wx += n + " = " + this.initializer.toWinxed(st) + "; __store_global('" + n + "', " + n + ")";
+ wx += n + " = " + this.initializer.wrapWinxed(st) + "; __store_global('" + n + "', " + n + ")";
st.addGlobal(n);
}
return wx;
@@ -304,18 +317,18 @@ def(wast, "StatementBlock", {
addStatement : function(s) { this.children.push(s); },
toWinxed : function(st) {
st = new SymbolTable(st);
- return "{\n " +
- this.children.map(function(c) { return c.toWinxed(st); }).join(";\n" + BLCK_INDENT) +
- ";\n }";
+ return "{\n" +
+ this.children.map(function(c) { return BLCK_INDENT + c.wrapWinxed(st) + ";\n"; }).join("") +
+ STMT_INDENT + "}";
}
});
-def(expr, "Assignment", {
+def(stmt, "Assignment", {
setDestination : function(d) { this.children[0] = d; },
setValue : function(v) { this.children[1] = v; },
toWinxed : function(st) {
- var c1 = this.children[0].toWinxed(st);
- var wx = c1 + " = " + this.children[1].toWinxed(st);
+ var c1 = this.children[0].wrapWinxed(st);
+ var wx = c1 + " = " + this.children[1].wrapWinxed(st);
if (this.children[0].nodeType == "VariableName") {
if (st.findSymbol(c1) == "global")
wx += "; __store_global('" + c1 + "', " + c1 + ")";
@@ -329,7 +342,7 @@ def(expr, "BinaryOperator", {
setOperator : function(o) { this.op = o; },
setOperands : function(a,b) { this.children.push(a); this.children.push(b); },
toWinxed : function(st) {
- return this.children.map(function(c) { return c.toWinxed(st); }).join(" " + this.op + " ");
+ return this.children.map(function(c) { return c.wrapWinxed(st); }).join(" " + this.op + " ");
}
});
@@ -341,9 +354,9 @@ def(expr, "UnaryOperator", {
setOperand : function(a) { this.children.push(a); },
toWinxed : function(st) {
if (this.location == "prefix")
- return this.op + " " + this.children[0].toWinxed(st);
+ return this.op + " " + this.children[0].wrapWinxed(st);
else if (this.location == "postfix")
- return this.children[0].toWinxed(st) + this.op;
+ return this.children[0].wrapWinxed(st) + this.op;
}
});
@@ -352,7 +365,7 @@ def(expr, "ArrayLiteral", {
toWinxed : function(st) {
// TODO: Need to redo this to fetch the Array constructor
return "JavaScript.JSObject.construct(null, __ARRAY_CONSTRUCTOR__" +
- this.children.map(function(c) { return ", " + c.toWinxed(st); }).join("") +
+ this.children.map(function(c) { return ", " + c.wrapWinxed(st); }).join("") +
")";
}
});
@@ -362,7 +375,7 @@ def(expr, "jsObjectLiteral", {
toWinxed : function(st) {
var wx = "new JavaScript.JSObject(null, __OBJECT_CONSTRUCTOR__";
for (var key in this.children)
- wx += ",\n" + ARG_INDENT + this.children[key].toWinxed(st) + ":[named('" + key.toString() + "')]";
+ wx += ",\n" + ARG_INDENT + this.children[key].wrapWinxed(st) + ":[named('" + key.toString() + "')]";
return wx + ")";
}
});
@@ -372,8 +385,8 @@ def(expr, "SubInvokeExpr", {
addArgument : function(a) { this.children.push(a); },
toWinxed : function(st) {
var wx = "";
- wx += this.name.toWinxed(st) + "(" +
- this.children.map(function(c) { return c.toWinxed(st); }).join(",\n" + ARG_INDENT) +
+ wx += this.name.wrapWinxed(st) + "(" +
+ this.children.map(function(c) { return c.wrapWinxed(st); }).join(",\n" + ARG_INDENT) +
")";
return wx;
}
@@ -386,18 +399,18 @@ def(expr, "MethodInvokeExpr", {
addArgument : function(a) { this.children.push(a); },
toWinxed : function(st) {
var wx = "";
- var n = this.name.toWinxed(st);
+ var n = this.name.wrapWinxed(st);
if (this.object == null)
return this.toWinxedError("Object cannot be null in a MethodInvokeExpr (" + n + ")");
var obj = "";
if (this.object.nodeType == "Literal" || this.object.nodeType == "MemberExpr" || this.object.nodeType == "VariableName")
- obj = this.object.toWinxed(st);
+ obj = this.object.wrapWinxed(st);
else
- obj= "(" + this.object.toWinxed(st) + ")";
+ obj= "(" + this.object.wrapWinxed(st) + ")";
wx += "var(" + obj + ".*'" + n + "')(" +
- this.children.map(function(c) { return "\n" + ARG_INDENT + c.toWinxed(st) + ","; }).join("") +
+ this.children.map(function(c) { return "\n" + ARG_INDENT + c.wrapWinxed(st) + ","; }).join("") +
"\n" + ARG_INDENT + obj + ":[named('this')])";
return wx;
}
@@ -410,91 +423,133 @@ def(expr, "NewOperator", {
toWinxed : function(st) {
var wx = "JavaScript.JSObject.construct(null, ";
if (this.name.nodeType == "Literal" || this.name.nodeType == "MemberExpr" || this.name.nodeType == "VariableName")
- wx += this.name.toWinxed(st);
+ wx += this.name.wrapWinxed(st);
else
- wx += "(" + this.name.toWinxed(st) + ")";
- wx += this.children.map(function(c) { return ",\n" + ARG_INDENT + c.toWinxed(st); }).join("") + ")";
+ wx += "(" + this.name.wrapWinxed(st) + ")";
+ wx += this.children.map(function(c) { return ",\n" + ARG_INDENT + c.wrapWinxed(st); }).join("") + ")";
return wx;
}
});
def(expr, "MemberExpr", {
addMember : function(m) { this.children.push(m); },
toWinxed : function(st) {
- return this.children.map(function(c) { return c.toWinxed(st); }).join(".");
+ return this.children.map(function(c) { return c.wrapWinxed(st); }).join(".");
}
});
def(expr, "KeyedIndexExpr", {
addKey : function(m) { this.children.push(m); },
toWinxed : function(st) {
- return this.children[0].toWinxed(st) + "[" + this.children[1].toWinxed(st) + "]";
+ return this.children[0].wrapWinxed(st) + "[" + this.children[1].wrapWinxed(st) + "]";
}
});
-def(stmt, "WhileStatement", {
+def(blck, "WhileStatement", {
setCondition : function(c) { this.children[0] = c; },
setBlock : function(c) { this.children[1] = c; },
toWinxed: function(st) {
- return "while (" + this.children[0].toWinxed(st) + ") " + this.children[1].toWinxed(st);
+ return "while (" + this.children[0].wrapWinxed(st) + ") " + this.children[1].wrapWinxed(st);
}
});
-def(stmt, "DoWhileStatement", {
+def(blck, "DoWhileStatement", {
setCondition : function(c) { this.children[1] = c; },
setBlock : function(c) { this.children[0] = c; },
toWinxed: function(st) {
- return "do " + this.children[0].toWinxed(st) +
- " while (" + this.children[1].toWinxed(st) + ")";
+ return "do " + this.children[0].wrapWinxed(st) +
+ " while (" + this.children[1].wrapWinxed(st) + ")";
}
});
-def(stmt, "IfStatement", {
+def(blck, "IfStatement", {
setCondition : function(c) { this.children[0] = c; },
thenStatement : function(s) { this.children[1] = s; },
elseStatement : function(s) { this.children[2] = s; },
toWinxed : function(st) {
- var wx = "if (" + this.children[0].toWinxed(st) + ")" +
- this.children[1].toWinxed(st);
+ var wx = "if (" + this.children[0].wrapWinxed(st) + ")" +
+ this.children[1].wrapWinxed(st);
if (this.children.length >= 3)
- wx += " else " + this.children[2].toWinxed(st);
+ wx += " else " + this.children[2].wrapWinxed(st);
return wx;
}
});
-def(stmt, "ForStatement", {
+def(blck, "ForStatement", {
setCondition : function(a, b, c) {
this.children[0] = a;
this.children[1] = b;
this.children[2] = c;
},
setStatement : function(s) { this.children[3] = s; },
toWinxed : function(st) {
- return "for (" + this.children[0].toWinxed(st) + " ; " +
- this.children[1].toWinxed(st) + " ; " +
- this.children[2].toWinxed(st) + ") " +
- this.children[3].toWinxed(st);
+ return "for (" + this.children[0].wrapWinxed(st) + " ; " +
+ this.children[1].wrapWinxed(st) + " ; " +
+ this.children[2].wrapWinxed(st) + ") " +
+ this.children[3].wrapWinxed(st);
}
});
-def(stmt, "ForInStatement", {
+def(blck, "ForInStatement", {
setEnumerator : function(a, b) {
this.children[0] = a;
this.children[1] = b;
},
setStatement : function(s) { this.children[2] = s; },
toWinxed : function(st) {
- return "for (" + this.children[0].toWinxed(st) + " in " + this.children[1].toWinxed(st) + ") "
- + this.children[2].toWinxed(st);
+ return "for (" + this.children[0].wrapWinxed(st) + " in " + this.children[1].wrapWinxed(st) + ") "
+ + this.children[2].wrapWinxed(st);
}
});
def(expr, "ConditionalExpr", {
setCondition : function(c) { this.children[0] = c; },
setOptions : function(a, b) { this.children[1] = a; this.children[2] = b; },
toWinxed : function(st) {
- return this.children[0].toWinxed(st) + " ? " +
- this.children[1].toWinxed(st) + " : " +
- this.children[2].toWinxed(st);
+ return this.children[0].wrapWinxed(st) + " ? " +
+ this.children[1].wrapWinxed(st) + " : " +
+ this.children[2].wrapWinxed(st);
+ }
+});
+
+def(wast, "TryStatement", {
+ setTryBlock : function(b) { this.children[0] = b; },
+ setCatchClause : function(c) { this.children[1] = c; },
+ toWinxed : function(st) {
+ return "try " + this.children[0].wrapWinxed(st) + this.children[1].wrapWinxed(st);
+ }
+});
+
+def(wast, "CatchClause", {
+ setExceptionVar : function(e) { this.children[0] = e; },
+ setCatchBlock : function(b) { this.children[1] = b; },
+ toWinxed : function(st) {
+ wx = " catch (";
+ var ex = null;
+ if (this.children[0] != null) {
+ ex = this.children[0].wrapWinxed(st);
+ wx += "__exception__";
+ }
+ wx += ") ";
+ if (ex == null) {
+ wx += this.children[1].wrapWinxed(st);
+ } else {
+ var st = new SymbolTable(st);
+ st.addLocal(ex);
+ wx += "{\n" +
+ BLCK_INDENT + "var " + ex + " = __exception__.payload;\n" +
+ BLCK_INDENT + "if (" + ex + " == null) " + ex + " = __exception__.message;\n" +
+ BLCK_INDENT + this.children[1].wrapWinxed(st) + "\n" +
+ STMT_INDENT + "}\n";
+ }
+ return wx;
}
});
+
+def(stmt, "ThrowStatement", {
+ setPayload : function(p) { this.children[0] = p; },
+ toWinxed : function(st) {
+ var wx = "__tmp = new 'Exception'; __tmp.payload = " + this.children[0].toWinxed(st) + "; throw(__tmp)";
+ return wx;
+ }
+});
View
20 t/stage0/try_catch.t
@@ -0,0 +1,20 @@
+// Test try/catch and throw
+var t = new TestObject();
+test_list([
+ function() {
+ try {
+ } catch (err) {
+ t.fail("No exception, should not catch");
+ }
+ },
+ function() {
+ var is_ok = 1;
+ try {
+ throw "exception message";
+ is_ok = 0;
+ } catch (err) {
+ t.equal(err, "exception message");
+ }
+ t.equal(is_ok, 1);
+ }
+]);

0 comments on commit 8478c3b

Please sign in to comment.
Something went wrong with that request. Please try again.