Mercurial > repos > tabletprog
comparison cbackend.js @ 84:9811040704ac
Add support for llMessage:withVars:andCode and llProperty:withType for specifying low level code without having to stick C inside the compiler. Redo array built-in type to use this feature.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 21 Jul 2012 22:30:21 -0700 |
parents | 7f635666c73d |
children | 25bc8a5ab41e |
comparison
equal
deleted
inserted
replaced
83:fdb9785d2c93 | 84:9811040704ac |
---|---|
42 op.prototype.toC = function(isReceiver) { | 42 op.prototype.toC = function(isReceiver) { |
43 var optoMeth = {'+': 'ADD_', '-': 'SUB_', '*': 'MUL_', '/': 'DIV_', '%': 'MOD_', '=': 'EQ_', '!=': 'NEQ_', '<': 'LT_', '>': 'GT_', '>=': 'GEQ_', '<=': 'LEQ_', '.': 'CAT_'}; | 43 var optoMeth = {'+': 'ADD_', '-': 'SUB_', '*': 'MUL_', '/': 'DIV_', '%': 'MOD_', '=': 'EQ_', '!=': 'NEQ_', '<': 'LT_', '>': 'GT_', '>=': 'GEQ_', '<=': 'LEQ_', '.': 'CAT_'}; |
44 var method = optoMeth[this.op]; | 44 var method = optoMeth[this.op]; |
45 return 'mcall(' + getMethodId(method) + '/* ' + method + ' */, 2, (object *)' + this.left.toC() + ', ' + this.right.toC() + ')\n'; | 45 return 'mcall(' + getMethodId(method) + '/* ' + method + ' */, 2, (object *)' + this.left.toC() + ', ' + this.right.toC() + ')\n'; |
46 }; | 46 }; |
47 op.prototype.toCLLExpr = function(vars) { | |
48 return this.left.toCLLExpr(vars) + (this.op == '=' ? '==' : this.op) + this.right.toCLLExpr(vars); | |
49 }; | |
50 op.prototype.toCLines = function(vars, needsreturn) { | |
51 return [ (needsreturn ? 'return (object *)' : '' ) + this.toCLLExpr(vars) + ';']; | |
52 }; | |
53 | |
47 | 54 |
48 function escapeCName(name) | 55 function escapeCName(name) |
49 { | 56 { |
50 if (name == 'self') { | 57 if (name == 'self') { |
51 return name; | 58 return name; |
106 } | 113 } |
107 return 'mcall(' + getMethodId(name) + '/* ' + name + ' */, 1, ' + obj + ')'; | 114 return 'mcall(' + getMethodId(name) + '/* ' + name + ' */, 1, ' + obj + ')'; |
108 } | 115 } |
109 return getSymbolPrefix(info, this.symbols) + escapeCName(name); | 116 return getSymbolPrefix(info, this.symbols) + escapeCName(name); |
110 } | 117 } |
118 symbol.prototype.toCTypeName = function() { | |
119 return this.cleanName(); | |
120 }; | |
121 symbol.prototype.toCLLExpr = function(vars) { | |
122 var name = this.cleanName(); | |
123 if (name in vars) { | |
124 return name; | |
125 } | |
126 if (name == 'self') { | |
127 return 'self'; | |
128 } | |
129 var info = this.symbols.find(name, false, true); | |
130 var symbols = this.symbols; | |
131 while (info && info.type == 'local') { | |
132 symbols = symbols.parent; | |
133 info = symbols.find(name, false, true); | |
134 } | |
135 if (!info) { | |
136 return name; | |
137 } | |
138 if (info.type == 'toplevel') { | |
139 return toplevel.moduleVar(name); | |
140 } else if (info.type == 'self') { | |
141 if (info.isll || !(info.def instanceof lambda)) { | |
142 return 'self->' + name; | |
143 } else { | |
144 return 'mcall(' + getMethodId(name) + '/* ' + name + ' */, 1, ' + (new symbol('self', this.symbols)).toC() + ')'; | |
145 } | |
146 } | |
147 throw new Error('Unsupported reference type ' + info.type + ' for variable ' + name); | |
148 }; | |
149 symbol.prototype.toCLines = function(vars, needsreturn) { | |
150 return [ (needsreturn ? 'return (object *)' : '' ) + this.toCLLExpr(vars) + ';' ]; | |
151 }; | |
111 | 152 |
112 var declaredInts = {}; | 153 var declaredInts = {}; |
113 | 154 |
114 intlit.prototype.toC = function() { | 155 intlit.prototype.toC = function() { |
115 var str = this.val < 0 ? 'neg_' + (0-this.val).toString() : this.val.toString(); | 156 var str = this.val < 0 ? 'neg_' + (0-this.val).toString() : this.val.toString(); |
117 toplevelcode += 'obj_int32 int32_' + str + ' = {{&obj_int32_meta, NULL}, ' + this.val.toString() + '};\n'; | 158 toplevelcode += 'obj_int32 int32_' + str + ' = {{&obj_int32_meta, NULL}, ' + this.val.toString() + '};\n'; |
118 declaredInts[this.val] = true; | 159 declaredInts[this.val] = true; |
119 } | 160 } |
120 return '((object *)&int32_' + str + ')'; | 161 return '((object *)&int32_' + str + ')'; |
121 } | 162 } |
163 intlit.prototype.toCLLExpr = function(vars) { | |
164 return this.val.toString(); | |
165 }; | |
166 intlit.prototype.toCLines = function(vars, needsreturn) { | |
167 return [ (needsreturn ? 'return (object *)' : '' ) + this.toCLLExpr(vars) + ';' ]; | |
168 }; | |
122 | 169 |
123 floatlit.prototype.toC = function() { | 170 floatlit.prototype.toC = function() { |
124 return 'make_float(' + this.val.toString() + ')'; | 171 return 'make_float(' + this.val.toString() + ')'; |
125 } | 172 } |
173 floatlit.prototype.toCLLExpr = function(vars) { | |
174 return this.val.toString(); | |
175 }; | |
176 floatlit.prototype.toCLines = function(vars, needsreturn) { | |
177 return [ (needsreturn ? 'return (object *)' : '' ) + this.toCLLExpr(vars) + ';' ]; | |
178 }; | |
126 | 179 |
127 var declaredStrings = {}; | 180 var declaredStrings = {}; |
128 var nextStringId = 0; | 181 var nextStringId = 0; |
129 | 182 |
130 strlit.prototype.toC = function() { | 183 strlit.prototype.toC = function() { |
132 //TODO: get the proper byte length | 185 //TODO: get the proper byte length |
133 toplevelcode += 'string str_' + nextStringId + ' = {{&string_meta, NULL}, ' + this.val.length + ', ' + this.val.length + ', "' + this.val.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r') + '"};\n'; | 186 toplevelcode += 'string str_' + nextStringId + ' = {{&string_meta, NULL}, ' + this.val.length + ', ' + this.val.length + ', "' + this.val.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r') + '"};\n'; |
134 declaredStrings[this.val] = nextStringId++; | 187 declaredStrings[this.val] = nextStringId++; |
135 } | 188 } |
136 return '((object *)&str_' + declaredStrings[this.val] + ')'; | 189 return '((object *)&str_' + declaredStrings[this.val] + ')'; |
137 } | 190 }; |
191 strlit.prototype.toCLLExpr = function(vars) { | |
192 return '"' + this.val.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r') + '"'; | |
193 }; | |
194 strlit.prototype.toCLines = function(vars, needsreturn) { | |
195 return [ (needsreturn ? 'return (object *)' : '' ) + this.toCLLExpr(vars) +';' ]; | |
196 }; | |
138 | 197 |
139 listlit.prototype.toC = function() { | 198 listlit.prototype.toC = function() { |
140 var ret = 'make_list(' + this.val.length; | 199 var ret = 'make_list(' + this.val.length; |
141 for (var i = 0; i < this.val.length; i++) { | 200 for (var i = 0; i < this.val.length; i++) { |
142 ret += ', ' + this.val[i].toC(); | 201 ret += ', ' + this.val[i].toC(); |
160 } else if(this.args[0] instanceof symbol) { | 219 } else if(this.args[0] instanceof symbol) { |
161 return this.args[0].name; | 220 return this.args[0].name; |
162 } else { | 221 } else { |
163 throw new Error("Unexpected AST type for foreign:"); | 222 throw new Error("Unexpected AST type for foreign:"); |
164 } | 223 } |
224 } else if(name == 'llProperty:withType' || name == 'llProperty:withVars:andCode') { | |
225 return null; | |
165 } | 226 } |
166 var args = this.args.slice(0, this.args.length); | 227 var args = this.args.slice(0, this.args.length); |
167 if (this.receiver) { | 228 if (this.receiver) { |
168 args.splice(0, 0, this.receiver); | 229 args.splice(0, 0, this.receiver); |
169 } | 230 } |
205 callpart = 'mcall(' + getMethodId(name) + '/* ' + name + ' */'; | 266 callpart = 'mcall(' + getMethodId(name) + '/* ' + name + ' */'; |
206 } else { | 267 } else { |
207 callpart = 'ccall(' + (new symbol(name, this.symbols)).toC(); | 268 callpart = 'ccall(' + (new symbol(name, this.symbols)).toC(); |
208 } | 269 } |
209 return callpart + ', ' + args.length + args.join('') + ')'; | 270 return callpart + ', ' + args.length + args.join('') + ')'; |
210 } | 271 }; |
272 funcall.prototype.toCTypeName = function() { | |
273 switch(this.name) | |
274 { | |
275 case 'ptr:': | |
276 case 'ptr': | |
277 var receiver = this.receiver ? this.receiver : this.args[0]; | |
278 return receiver.toCTypeName() + ' *'; | |
279 break; | |
280 default: | |
281 throw new Error('invalid use of funcall expression where a C type name is expected'); | |
282 } | |
283 }; | |
284 funcall.prototype.toCLines = function(vars, needsreturn) { | |
285 var lines = []; | |
286 var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name; | |
287 var args = this.args.slice(0, this.args.length); | |
288 if (this.receiver) { | |
289 args.splice(0, 0, [this.receiver]); | |
290 } | |
291 switch(name) | |
292 { | |
293 case 'if': | |
294 lines.push('if (' + this.args[0].toCLLExpr(vars) + ') {'); | |
295 var blines = this.args[1].toCLines(vars, needsreturn); | |
296 for (var i in blines) { | |
297 lines.push('\t' + blines[i]); | |
298 } | |
299 if (needsreturn) { | |
300 lines.push('} else {'); | |
301 lines.push('\t return module_false;'); | |
302 lines.push('}'); | |
303 } else { | |
304 lines.push('}'); | |
305 } | |
306 break; | |
307 case 'if:else': | |
308 lines.push('if (' + this.args[0].toCLLExpr(vars) + ') {'); | |
309 var blines = this.args[1].toCLines(vars, needsreturn); | |
310 for (var i in blines) { | |
311 lines.push('\t' + blines[i]); | |
312 } | |
313 lines.push('} else {'); | |
314 blines = this.args[2].toCLines(vars, needsreturn); | |
315 for (var i in blines) { | |
316 lines.push('\t' + blines[i]); | |
317 } | |
318 lines.push('}'); | |
319 break; | |
320 case 'while:do': | |
321 if (needsreturn) { | |
322 throw new Error("while:do can't be last statement in llMessage code block"); | |
323 } | |
324 lines.push('while (' + this.args[0].toCLLExpr(vars) + ') {'); | |
325 var blines = this.args[1].toCLines(vars); | |
326 for (var i in blines) { | |
327 lines.push('\t' + blines[i]); | |
328 } | |
329 lines.push('}'); | |
330 break; | |
331 default: | |
332 lines.push( (needsreturn ? 'return (object *)' : '') + this.toCLLExpr(vars) + ';'); | |
333 } | |
334 return lines; | |
335 }; | |
336 | |
337 funcall.prototype.toCLLExpr = function(vars) { | |
338 var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name; | |
339 var args = this.args.slice(0, this.args.length); | |
340 if (this.receiver) { | |
341 if(this.args.length == 0) { | |
342 return this.receiver.toCLLExpr(vars) + '->' + this.name; | |
343 } else if (this.args.length == 1 && name[name.length-1] == '!') { | |
344 return this.receiver.toCLLExpr(vars) + '->' + this.name.substr(0, name.length-1) + ' = ' + args[0].toCLLExpr(vars); | |
345 } else { | |
346 args.splice(0, 0, this.receiver); | |
347 } | |
348 } | |
349 switch(name) | |
350 { | |
351 case 'if': | |
352 case 'if:else': | |
353 case 'while:do': | |
354 throw new Error('if, if:else and while:do not allow in expression context in llMessage block'); | |
355 case 'addr_of': | |
356 return '&(' + args[0].toCLLExpr(vars) + ')'; | |
357 case 'sizeof': | |
358 return 'sizeof(' + args[0].toCTypeName() + ')'; | |
359 case 'get': | |
360 return args[0].toCLLExpr(vars) + '[' + args[1].toCLLExpr(vars) + ']'; | |
361 case 'set': | |
362 return args[0].toCLLExpr(vars) + '[' + args[1].toCLLExpr(vars) + '] = ' + args[2].toCLLExpr(vars); | |
363 case 'not': | |
364 return '!(' + args[0].toCLLExpr(vars) + ')'; | |
365 default: | |
366 for (var i in args) { | |
367 args[i] = args[i].toCLLExpr(vars); | |
368 } | |
369 return name + '(' + args.join(', ') + ')'; | |
370 } | |
371 }; | |
211 | 372 |
212 function cObject(name) { | 373 function cObject(name) { |
213 this.name = name; | 374 this.name = name; |
214 this.slots = {}; | 375 this.slots = {}; |
215 this.properties = []; | 376 this.properties = []; |
353 return this.toCInstance(); | 514 return this.toCInstance(); |
354 } | 515 } |
355 | 516 |
356 var nextobject = 0; | 517 var nextobject = 0; |
357 | 518 |
358 object.prototype.toC = function() { | 519 |
520 object.prototype.toCObject = function() { | |
359 var messages = this.messages; | 521 var messages = this.messages; |
360 var values = []; | 522 var values = []; |
361 var imports = [] | 523 var imports = []; |
362 var me = new cObject('object_' + nextobject++); | 524 if (!this.name) { |
525 this.name = 'object_' + nextobject++; | |
526 } | |
527 var me = new cObject(this.name); | |
363 this.symbols.typename = me.name; | 528 this.symbols.typename = me.name; |
364 if (this.symbols.needsenv) { | 529 if (this.symbols.needsenv) { |
365 me.addProperty('env', this.symbols.envVar(), 'struct ' + this.symbols.getEnvType() + ' * '); | 530 me.addProperty('env', this.symbols.envVar(), 'struct ' + this.symbols.getEnvType() + ' * '); |
366 me.hasenv = true; | 531 me.hasenv = true; |
367 } | 532 } |
379 throw new Error('Names in import:from statement must be symbols'); | 544 throw new Error('Names in import:from statement must be symbols'); |
380 } | 545 } |
381 importsyms.push(new strlit(el.name)); | 546 importsyms.push(new strlit(el.name)); |
382 }); | 547 }); |
383 imports.push({symbols: new listlit(importsyms), src: messages[i].args[1]}); | 548 imports.push({symbols: new listlit(importsyms), src: messages[i].args[1]}); |
549 } else if(messages[i].name == 'llProperty:withType:' && messages[i].args.length == 2) { | |
550 me.addProperty(messages[i].args[0].name, null, messages[i].args[1].toCTypeName()) | |
551 } else if(messages[i].name == 'llMessage:withVars:andCode:' && messages[i].args.length == 3) { | |
552 var msgname = messages[i].args[0].name | |
553 var rawvars = messages[i].args[1].expressions; | |
554 var vars = {}; | |
555 for(var v in rawvars) { | |
556 vars[rawvars[v].symbol.name] = rawvars[v].expression.toCTypeName(); | |
557 } | |
558 me.addMessage(msgname, { | |
559 vars: vars, | |
560 lines: messages[i].args[2].toCLines(vars, true) | |
561 }); | |
384 } else { | 562 } else { |
385 throw new Error('Only import and import:from calls allowed in object context'); | 563 |
564 throw new Error('Only import and import:from calls allowed in object context. ' + messages[i].name + 'with ' + messages[i].args.length + ' arguments found instead.'); | |
386 } | 565 } |
387 } else { | 566 } else { |
388 messages[i].toCObject(me); | 567 messages[i].toCObject(me); |
389 } | 568 } |
390 } | 569 } |
391 | 570 |
392 return me.toC(); | 571 return me; |
393 } | 572 }; |
573 | |
574 object.prototype.toC = function() { | |
575 return this.toCObject().toC(); | |
576 }; | |
394 | 577 |
395 var toplevelcode; | 578 var toplevelcode; |
396 var forwarddec; | 579 var forwarddec; |
397 | 580 |
398 function addBinaryOp(cobject, opname, cop, objtype) | 581 function addBinaryOp(cobject, opname, cop, objtype) |
457 return int32; | 640 return int32; |
458 } | 641 } |
459 | 642 |
460 function makeArray() | 643 function makeArray() |
461 { | 644 { |
462 var array = new cObject('array'); | 645 var arrayfile = toplevel.names['array']; |
463 array.addProperty('size', null, 'uint32_t'); | 646 var ast = parseFile(arrayfile.path + '/' + arrayfile.file); |
464 array.addProperty('storage', null, 'uint32_t'); | 647 ast.name = 'array'; |
465 array.addProperty('data', null, 'object **'); | 648 ast.populateSymbols(toplevel); |
466 array.addMessage('get', { | 649 return ast.toCObject(); |
467 vars: {index: 'obj_int32 *'}, | |
468 lines: [ | |
469 'index = va_arg(args, obj_int32 *);', | |
470 'if (index->num >= 0 && index->num < self->size) {', | |
471 ' return self->data[index->num];', | |
472 '}', | |
473 'return ' + toplevel.moduleVar('false') + ';' | |
474 ] | |
475 }); | |
476 array.addMessage('set', { | |
477 vars: {index: 'obj_int32 *'}, | |
478 lines: [ | |
479 'index = va_arg(args, obj_int32 *);', | |
480 'if (index->num >= 0 && index->num < self->size) {', | |
481 ' self->data[index->num] = va_arg(args, object *);', | |
482 '}', | |
483 'return &(self->header);' | |
484 ] | |
485 }); | |
486 array.addMessage('foreach', { | |
487 vars: {index: 'obj_int32 *', i: 'int32_t', clos: 'lambda *'}, | |
488 lines: [ | |
489 'clos = va_arg(args, lambda *);', | |
490 'for (i = 0; i < self->size; i++) {', | |
491 ' index = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);', | |
492 ' index->num = i;', | |
493 ' ccall(clos, 2, index, self->data[i]);', | |
494 '}', | |
495 'return &(self->header);' | |
496 ] | |
497 }); | |
498 array.addMessage('append', { | |
499 vars: {tmp: 'object **'}, | |
500 lines: [ | |
501 'if (self->storage == self->size) {', | |
502 ' self->storage *= 2;', | |
503 ' tmp = GC_REALLOC(self->data, self->storage * sizeof(object *));', | |
504 ' if (!tmp) {', | |
505 ' fputs("Failed to increase array size\\n", stderr);', | |
506 ' exit(1);', | |
507 ' }', | |
508 ' self->data = tmp;', | |
509 '}', | |
510 'self->data[self->size++] = va_arg(args, object *);', | |
511 'return &(self->header);' | |
512 ] | |
513 }); | |
514 array.addMessage('length', { | |
515 vars: {intret: 'obj_int32 *'}, | |
516 lines: [ | |
517 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);', | |
518 'intret->num = self->size;', | |
519 'return &(intret->header);' | |
520 ] | |
521 }); | |
522 return array; | |
523 } | 650 } |
524 | 651 |
525 function makeString() | 652 function makeString() |
526 { | 653 { |
527 var string = new cObject('string'); | 654 var string = new cObject('string'); |
768 function processUsedToplevel(toplevel) | 895 function processUsedToplevel(toplevel) |
769 { | 896 { |
770 var alwaysused = ['true', 'false']; | 897 var alwaysused = ['true', 'false']; |
771 var ret = ''; | 898 var ret = ''; |
772 var modulenum = 0; | 899 var modulenum = 0; |
900 var visited = {}; | |
901 for (var i in alwaysused) { | |
902 toplevel.used[alwaysused[i]] = true; | |
903 } | |
773 var newused = Object.keys(toplevel.used); | 904 var newused = Object.keys(toplevel.used); |
774 var allused = newused; | 905 var allused = newused; |
775 var visited = {}; | |
776 for (var i in alwaysused) { | |
777 forwarddec += 'object * ' + toplevel.moduleVar(alwaysused[i]) + ';\n'; | |
778 toplevel.names[alwaysused[i]].populateSymbols(toplevel); | |
779 visited[alwaysused[i]] = true; | |
780 } | |
781 while (newused.length) { | 906 while (newused.length) { |
782 for (var i in newused) { | 907 for (var i in newused) { |
783 debugprint('//---module', newused[i], '--- populate symbols'); | 908 debugprint('//---module', newused[i], '--- populate symbols'); |
784 forwarddec += 'object * ' + toplevel.moduleVar(newused[i]) + ';\n'; | 909 forwarddec += 'object * ' + toplevel.moduleVar(newused[i]) + ';\n'; |
785 toplevel.names[newused[i]].populateSymbols(toplevel); | 910 toplevel.names[newused[i]].populateSymbols(toplevel); |
792 newused.push(symbol); | 917 newused.push(symbol); |
793 allused.push(symbol); | 918 allused.push(symbol); |
794 } | 919 } |
795 } | 920 } |
796 } | 921 } |
797 for (var i in alwaysused) { | |
798 allused.push(alwaysused[i]); | |
799 } | |
800 | 922 |
801 for (var i = allused.length-1; i >= 0; i--) { | 923 for (var i = allused.length-1; i >= 0; i--) { |
802 var symbol = allused[i]; | 924 var symbol = allused[i]; |
803 debugprint('//---module', symbol, '--- compile'); | 925 debugprint('//---module', symbol, '(' + i +')--- compile'); |
804 ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n'; | 926 ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n'; |
805 } | 927 } |
806 return ret; | 928 return ret; |
807 } | 929 } |
808 | 930 |
809 function makeCProg(obj) | 931 function makeCProg(obj) |
810 { | 932 { |
933 forwarddec = toplevelcode = ''; | |
811 var builtins = builtinTypes(); | 934 var builtins = builtinTypes(); |
812 forwarddec = toplevelcode = ''; | |
813 for (var i in builtins) { | 935 for (var i in builtins) { |
814 forwarddec += builtins[i].toEarlyCDef(); | 936 forwarddec += builtins[i].toEarlyCDef(); |
815 toplevelcode += builtins[i].toCDef(); | 937 toplevelcode += builtins[i].toCDef(); |
816 } | 938 } |
817 addBuiltinModules(toplevel); | 939 addBuiltinModules(toplevel); |
930 this.selftype = typename; | 1052 this.selftype = typename; |
931 return this.toC(); | 1053 return this.toC(); |
932 }; | 1054 }; |
933 lambda.prototype.toCModule = function() { | 1055 lambda.prototype.toCModule = function() { |
934 return makeCProg(this); | 1056 return makeCProg(this); |
1057 }; | |
1058 lambda.prototype.toCLines = function(vars, needsreturn) { | |
1059 var lines = []; | |
1060 for (var i in this.args) { | |
1061 var name = this.args[i].name; | |
1062 if (name[0] == ':') { | |
1063 name = name.substr(1); | |
1064 } | |
1065 if(name != 'self') { | |
1066 lines.push(name + ' = va_arg(args, ' + vars[name] + ');'); | |
1067 } | |
1068 } | |
1069 for (var i in this.expressions) { | |
1070 var exprlines = this.expressions[i].toCLines(vars, needsreturn && i == this.expressions.length - 1); | |
1071 for (var j in exprlines) { | |
1072 lines.push('\t' + exprlines[j]); | |
1073 } | |
1074 } | |
1075 return lines; | |
1076 } | |
1077 lambda.prototype.toCLLExpr = function(vars) { | |
1078 if (this.expressions.length != 1) { | |
1079 throw new Error('lambda in expression context must have a single statement in llMessage block'); | |
1080 } | |
1081 return this.expressions[0].toCLLExpr(vars); | |
935 } | 1082 } |
936 | 1083 |
937 assignment.prototype.toC = function() { | 1084 assignment.prototype.toC = function() { |
938 debugprint('//assignment', this.symbol.name); | 1085 debugprint('//assignment', this.symbol.name); |
939 var existing = this.symbols.find(this.symbol.name); | 1086 var existing = this.symbols.find(this.symbol.name); |
980 if (this.expression instanceof object && this.expression.symbols.needsparent) { | 1127 if (this.expression instanceof object && this.expression.symbols.needsparent) { |
981 cobj.addInit('self->' + escapeCName(this.symbol.name) + '->parent = (object *)self;'); | 1128 cobj.addInit('self->' + escapeCName(this.symbol.name) + '->parent = (object *)self;'); |
982 } | 1129 } |
983 } | 1130 } |
984 }; | 1131 }; |
1132 assignment.prototype.toCLines = function(vars, needsreturn) { | |
1133 return [(needsreturn ? 'return ' : '') + this.symbol.toCLLExpr(vars) + ' = ' + this.expression.toCLLExpr(vars) + ';'] | |
1134 }; |