comparison jsbackend.js @ 8:04ae32e91598

Move compiler and test page related code out of parser.js
author Mike Pavone <pavone@retrodev.com>
date Wed, 21 Mar 2012 20:33:39 -0700
parents
children 37d7f60a8ea1
comparison
equal deleted inserted replaced
7:8af72f11714e 8:04ae32e91598
1 var mainModule;
2
3 function toobj(val)
4 {
5 switch(typeof val)
6 {
7 case 'boolean':
8 if(val) {
9 return mainModule.strue;
10 } else {
11 return mainModule.sfalse;
12 }
13 case 'number':
14 return mainModule.snumber(val);
15 }
16 throw new Error("can't make val into object");
17 }
18
19 op.prototype.toJS = function(symbols, isReceiver) {
20 var ret = '(' + this.left.toJS(symbols) +' '+ (this.op == '=' ? '==' : this.op) +' '+ this.right.toJS(symbols) + ')';
21 if (isReceiver) {
22 ret = 'toobj' + ret;
23 }
24 return ret;
25 };
26
27 symbol.prototype.toJS = function(symbols) {
28 var name = this.cleanName();
29 if (name == 'self') {
30 return symbols.selfVar();
31 }
32 name = name.replace("_", "UN_").replace(":", "CN_").replace("!", "EX_").replace('?', 'QS_').replace('@', 'AT_');
33 var reserved = {'true': true, 'false': true, 'this': true, 'if': true, 'else': true, 'NaN': true};
34 if (name in reserved) {
35 name = 's' + name;
36 }
37 return name;
38 }
39
40 intlit.prototype.toJS = function(symbols) {
41 return this.val.toString();
42 }
43
44 floatlit.prototype.toJS = function(symbols) {
45 return this.val.toString();
46 }
47
48 strlit.prototype.toJS = function(symbols) {
49 console.log('string:', this.val);
50 return '"' + this.val.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r') + '"';
51 }
52
53 funcall.prototype.toJS = function(symbols) {
54 var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name;
55 var args = this.args.slice(0, this.args.length);
56 if (this.receiver) {
57 args.splice(0, 0, this.receiver);
58 }
59 var funinfo = symbols.find(name);
60 if (!funinfo) {
61 var receiver = args[0];
62 args.splice(0, 1);
63 for (var i in args) {
64 args[i] = args[i].toJS(symbols);
65 }
66 return receiver.toJS(symbols, true) + '.' + (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')';
67 }
68 switch(funinfo.type)
69 {
70 case 'self':
71 if (args.length < funinfo.def.args.length || funinfo.def.args[0].name != 'self') {
72 var receiver = new symbol('self');
73 } else {
74 var receiver = args[0];
75 args.splice(0, 1);
76 }
77 for (var i in args) {
78 args[i] = args[i].toJS(symbols);
79 }
80 return receiver.toJS(symbols, true) + '.' + (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')';
81 case 'parent':
82 var ret = 'this';
83 for (var i = 0; i < funinfo.depth; ++i) {
84 ret += '.parent';
85 }
86 for (var i in args) {
87 args[i] = args[i].toJS(symbols);
88 }
89 ret += (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')';
90 return ret;
91 case 'local':
92 case 'upvar':
93 case 'foreign':
94 for (var i in args) {
95 args[i] = args[i].toJS(symbols);
96 }
97 return (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')';
98 }
99 }
100
101 object.prototype.toJS = function(symbols) {
102 var messages = this.messages;
103 symbols = new osymbols(symbols);
104 var compiled = []
105 for (var i in messages) {
106 var js = messages[i].toJSObject(symbols);
107 if (js) {
108 compiled.push(indent(js));
109 }
110 }
111 return '{\n\tparent: ' + symbols.parentObject() + ',\n\t' + compiled.join(',\n\t') + '\n}';
112 }
113
114 object.prototype.toJSModule = function() {
115 return '(function () {\n\tvar module = ' + indent(this.toJS(null)) + ';\n\treturn module;\n})'
116 }
117
118 lambda.prototype.toJS = function(symbols) {
119 var args = this.args ? this.args.slice(0, this.args.length) : [];
120 if (args.length && args[0].cleanName() == 'self') {
121 args.splice(0, 1);
122 }
123 var exprs = this.expressions;
124 symbols = new lsymbols(symbols);
125 for (var i in args) {
126 symbols.defineVar(args[i].cleanName(), null);
127 args[i] = args[i].toJS(symbols);
128 }
129 var compiled = []
130 for (var i in exprs) {
131 var js = exprs[i].toJS(symbols);
132 if (js) {
133 compiled.push(indent(js));
134 }
135 }
136 exprs = compiled;
137 if (exprs.length) {
138 exprs[exprs.length-1] = 'return ' + exprs[exprs.length-1] + ';';
139 }
140 return 'function (' + args.join(', ') + ') {\n\t' + (symbols.needsSelfVar ? 'var self = this;\n\t' : '') + exprs.join(';\n\t') + '\n}'
141 };
142 lambda.prototype.toJSModule = lambda.prototype.toJS
143
144 assignment.prototype.toJS = function(symbols) {
145 var existing = symbols.find(this.symbol.name);
146 var prefix = '';
147 if (!existing) {
148 symbols.defineVar(this.symbol.name, this.expression);
149 prefix = 'var ';
150 } else {
151 switch (existing.type)
152 {
153 case 'self':
154 prefix = 'this.';
155 break;
156 case 'parent':
157 prefix = 'this.';
158 for (var i = 0; i < existing.depth; ++i) {
159 prefix += 'parent.';
160 }
161 break;
162 }
163 }
164 if (this.expression instanceof funcall && this.expression.name == 'foreign:') {
165 return null;
166 }
167 return prefix + this.symbol.toJS(symbols) + ' = ' + this.expression.toJS(symbols);
168 };
169 assignment.prototype.toJSObject = function(symbols) {
170 symbols.defineMsg(this.symbol.name, this.expression);
171 if (this.expression instanceof funcall && this.expression.name == 'foreign:') {
172 return null;
173 }
174 return this.symbol.toJS(symbols) + ': ' + this.expression.toJS(symbols);
175 };