aboutsummaryrefslogtreecommitdiff
path: root/lib/ast.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ast.js')
-rw-r--r--lib/ast.js53
1 files changed, 47 insertions, 6 deletions
diff --git a/lib/ast.js b/lib/ast.js
index 5187b5ad..1a792861 100644
--- a/lib/ast.js
+++ b/lib/ast.js
@@ -70,7 +70,11 @@ function DEFNODE(type, props, methods, base) {
ctor.prototype.TYPE = ctor.TYPE = type;
}
if (methods) for (i in methods) if (HOP(methods, i)) {
- ctor.prototype[i] = methods[i];
+ if (/^\$/.test(i)) {
+ ctor[i.substr(1)] = methods[i];
+ } else {
+ ctor.prototype[i] = methods[i];
+ }
}
ctor.DEFMETHOD = function(name, method) {
this.prototype[name] = method;
@@ -429,12 +433,45 @@ var AST_New = DEFNODE("New", null, {
$documentation: "An object instantiation. Derives from a function call since it has exactly the same properties."
}, AST_Call);
-var AST_Seq = DEFNODE("Seq", "first second", {
+var AST_Seq = DEFNODE("Seq", "car cdr", {
$documentation: "A sequence expression (two comma-separated expressions)",
+ $cons: function(x, y) {
+ var seq = new AST_Seq(x);
+ seq.car = x;
+ seq.cdr = y;
+ return seq;
+ },
+ $from_array: function(array) {
+ if (array.length == 0) return null;
+ if (array.length == 1) return array[0].clone();
+ var list = null;
+ for (var i = array.length; --i >= 0;) {
+ list = AST_Seq.cons(array[i], list);
+ }
+ var p = list;
+ while (p) {
+ if (p.cdr && !p.cdr.cdr) {
+ p.cdr = p.cdr.car;
+ break;
+ }
+ p = p.cdr;
+ }
+ return list;
+ },
+ add: function(node) {
+ var p = this;
+ while (p) {
+ if (!(p.cdr instanceof AST_Seq)) {
+ var cell = AST_Seq.cons(p.cdr, node);
+ return p.cdr = cell;
+ }
+ p = p.cdr;
+ }
+ },
_walk: function(visitor) {
return visitor._visit(this, function(){
- this.first._walk(visitor);
- this.second._walk(visitor);
+ this.car._walk(visitor);
+ if (this.cdr) this.cdr._walk(visitor);
});
}
});
@@ -629,15 +666,19 @@ var AST_Undefined = DEFNODE("Undefined", null, {
value: (function(){}())
}, AST_Atom);
+var AST_Boolean = DEFNODE("Boolean", null, {
+ $documentation: "Base class for booleans",
+}, AST_Atom);
+
var AST_False = DEFNODE("False", null, {
$documentation: "The `false` atom",
value: false
-}, AST_Atom);
+}, AST_Boolean);
var AST_True = DEFNODE("True", null, {
$documentation: "The `true` atom",
value: true
-}, AST_Atom);
+}, AST_Boolean);
/* -----[ TreeWalker ]----- */