comparison cbackend.js @ 92:6abbf2454657

merge
author William Morgan <bill@mrgn.org>
date Mon, 23 Jul 2012 01:07:52 -0700
parents 25bc8a5ab41e
children f23ecd4e22af
comparison
equal deleted inserted replaced
91:3bf57ace3e0b 92:6abbf2454657
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 var opmap = {'=': '==', 'xor': '^'};
49 return this.left.toCLLExpr(vars) + (this.op in opmap ? opmap[this.op] : this.op) + this.right.toCLLExpr(vars);
50 };
51 op.prototype.toCLines = function(vars, needsreturn) {
52 return [ (needsreturn ? 'return (object *)' : '' ) + this.toCLLExpr(vars) + ';'];
53 };
54
47 55
48 function escapeCName(name) 56 function escapeCName(name)
49 { 57 {
50 if (name == 'self') { 58 if (name == 'self') {
51 return name; 59 return name;
106 } 114 }
107 return 'mcall(' + getMethodId(name) + '/* ' + name + ' */, 1, ' + obj + ')'; 115 return 'mcall(' + getMethodId(name) + '/* ' + name + ' */, 1, ' + obj + ')';
108 } 116 }
109 return getSymbolPrefix(info, this.symbols) + escapeCName(name); 117 return getSymbolPrefix(info, this.symbols) + escapeCName(name);
110 } 118 }
119 symbol.prototype.toCTypeName = function() {
120 return this.cleanName();
121 };
122 symbol.prototype.toCLLExpr = function(vars) {
123 var name = this.cleanName();
124 if (name in vars) {
125 return name;
126 }
127 if (name == 'self') {
128 return 'self';
129 }
130 var info = this.symbols.find(name, false, true);
131 var symbols = this.symbols;
132 while (info && info.type == 'local') {
133 symbols = symbols.parent;
134 info = symbols.find(name, false, true);
135 }
136 if (!info) {
137 return name;
138 }
139 if (info.type == 'toplevel') {
140 return toplevel.moduleVar(name);
141 } else if (info.type == 'self') {
142 if (info.isll || !(info.def instanceof lambda)) {
143 return 'self->' + name;
144 } else {
145 return 'mcall(' + getMethodId(name) + '/* ' + name + ' */, 1, self)';
146 }
147 }
148 throw new Error('Unsupported reference type ' + info.type + ' for variable ' + name);
149 };
150 symbol.prototype.toCLines = function(vars, needsreturn) {
151 return [ (needsreturn ? 'return (object *)' : '' ) + this.toCLLExpr(vars) + ';' ];
152 };
111 153
112 var declaredInts = {}; 154 var declaredInts = {};
113 155
114 intlit.prototype.toC = function() { 156 intlit.prototype.toC = function() {
115 var str = this.val < 0 ? 'neg_' + (0-this.val).toString() : this.val.toString(); 157 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'; 159 toplevelcode += 'obj_int32 int32_' + str + ' = {{&obj_int32_meta, NULL}, ' + this.val.toString() + '};\n';
118 declaredInts[this.val] = true; 160 declaredInts[this.val] = true;
119 } 161 }
120 return '((object *)&int32_' + str + ')'; 162 return '((object *)&int32_' + str + ')';
121 } 163 }
164 intlit.prototype.toCLLExpr = function(vars) {
165 return this.val.toString();
166 };
167 intlit.prototype.toCLines = function(vars, needsreturn) {
168 return [ (needsreturn ? 'return (object *)' : '' ) + this.toCLLExpr(vars) + ';' ];
169 };
122 170
123 floatlit.prototype.toC = function() { 171 floatlit.prototype.toC = function() {
124 return 'make_float(' + this.val.toString() + ')'; 172 return 'make_float(' + this.val.toString() + ')';
125 } 173 }
174 floatlit.prototype.toCLLExpr = function(vars) {
175 return this.val.toString();
176 };
177 floatlit.prototype.toCLines = function(vars, needsreturn) {
178 return [ (needsreturn ? 'return (object *)' : '' ) + this.toCLLExpr(vars) + ';' ];
179 };
126 180
127 var declaredStrings = {}; 181 var declaredStrings = {};
128 var nextStringId = 0; 182 var nextStringId = 0;
129 183
130 strlit.prototype.toC = function() { 184 strlit.prototype.toC = function() {
132 //TODO: get the proper byte length 186 //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'; 187 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++; 188 declaredStrings[this.val] = nextStringId++;
135 } 189 }
136 return '((object *)&str_' + declaredStrings[this.val] + ')'; 190 return '((object *)&str_' + declaredStrings[this.val] + ')';
137 } 191 };
192 strlit.prototype.toCLLExpr = function(vars) {
193 return '"' + this.val.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r') + '"';
194 };
195 strlit.prototype.toCLines = function(vars, needsreturn) {
196 return [ (needsreturn ? 'return (object *)' : '' ) + this.toCLLExpr(vars) +';' ];
197 };
138 198
139 listlit.prototype.toC = function() { 199 listlit.prototype.toC = function() {
140 var ret = 'make_list(' + this.val.length; 200 var ret = 'make_list(' + this.val.length;
141 for (var i = 0; i < this.val.length; i++) { 201 for (var i = 0; i < this.val.length; i++) {
142 ret += ', ' + this.val[i].toC(); 202 ret += ', ' + this.val[i].toC();
160 } else if(this.args[0] instanceof symbol) { 220 } else if(this.args[0] instanceof symbol) {
161 return this.args[0].name; 221 return this.args[0].name;
162 } else { 222 } else {
163 throw new Error("Unexpected AST type for foreign:"); 223 throw new Error("Unexpected AST type for foreign:");
164 } 224 }
225 } else if(name == 'llProperty:withType' || name == 'llProperty:withVars:andCode') {
226 return null;
165 } 227 }
166 var args = this.args.slice(0, this.args.length); 228 var args = this.args.slice(0, this.args.length);
167 if (this.receiver) { 229 if (this.receiver) {
168 args.splice(0, 0, this.receiver); 230 args.splice(0, 0, this.receiver);
169 } 231 }
170 var method = false; 232 var method = false;
171 var funinfo = this.symbols.find(name); 233 var funinfo = this.symbols.find(name);
172 var start = 0; 234 var start = 0;
173 if (!funinfo || funinfo.def instanceof setter) { 235 if (!funinfo || funinfo.def instanceof setter || funinfo.type == 'toplevel') {
174 method = true; 236 method = true;
175 } else { 237 } else {
176 switch(funinfo.type) 238 switch(funinfo.type)
177 { 239 {
178 case 'self': 240 case 'self':
205 callpart = 'mcall(' + getMethodId(name) + '/* ' + name + ' */'; 267 callpart = 'mcall(' + getMethodId(name) + '/* ' + name + ' */';
206 } else { 268 } else {
207 callpart = 'ccall(' + (new symbol(name, this.symbols)).toC(); 269 callpart = 'ccall(' + (new symbol(name, this.symbols)).toC();
208 } 270 }
209 return callpart + ', ' + args.length + args.join('') + ')'; 271 return callpart + ', ' + args.length + args.join('') + ')';
210 } 272 };
273 funcall.prototype.toCTypeName = function() {
274 switch(this.name)
275 {
276 case 'ptr:':
277 case 'ptr':
278 var receiver = this.receiver ? this.receiver : this.args[0];
279 return receiver.toCTypeName() + ' *';
280 break;
281 default:
282 throw new Error('invalid use of funcall expression where a C type name is expected');
283 }
284 };
285 funcall.prototype.toCLines = function(vars, needsreturn) {
286 var lines = [];
287 var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name;
288 var args = this.args.slice(0, this.args.length);
289 if (this.receiver) {
290 args.splice(0, 0, [this.receiver]);
291 }
292 switch(name)
293 {
294 case 'if':
295 lines.push('if (' + this.args[0].toCLLExpr(vars) + ') {');
296 var blines = this.args[1].toCLines(vars, needsreturn);
297 for (var i in blines) {
298 lines.push('\t' + blines[i]);
299 }
300 if (needsreturn) {
301 lines.push('} else {');
302 lines.push('\t return module_false;');
303 lines.push('}');
304 } else {
305 lines.push('}');
306 }
307 break;
308 case 'if:else':
309 lines.push('if (' + this.args[0].toCLLExpr(vars) + ') {');
310 var blines = this.args[1].toCLines(vars, needsreturn);
311 for (var i in blines) {
312 lines.push('\t' + blines[i]);
313 }
314 lines.push('} else {');
315 blines = this.args[2].toCLines(vars, needsreturn);
316 for (var i in blines) {
317 lines.push('\t' + blines[i]);
318 }
319 lines.push('}');
320 break;
321 case 'while:do':
322 if (needsreturn) {
323 throw new Error("while:do can't be last statement in llMessage code block");
324 }
325 lines.push('while (' + this.args[0].toCLLExpr(vars) + ') {');
326 var blines = this.args[1].toCLines(vars);
327 for (var i in blines) {
328 lines.push('\t' + blines[i]);
329 }
330 lines.push('}');
331 break;
332 default:
333 lines.push( (needsreturn ? 'return (object *)' : '') + this.toCLLExpr(vars) + ';');
334 }
335 return lines;
336 };
337
338 funcall.prototype.toCLLExpr = function(vars) {
339 var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name;
340 var args = this.args.slice(0, this.args.length);
341 if (this.receiver) {
342 if(this.args.length == 0) {
343 return this.receiver.toCLLExpr(vars) + '->' + this.name;
344 } else if (this.args.length == 1 && name[name.length-1] == '!') {
345 return this.receiver.toCLLExpr(vars) + '->' + this.name.substr(0, name.length-1) + ' = ' + args[0].toCLLExpr(vars);
346 } else {
347 args.splice(0, 0, this.receiver);
348 }
349 }
350 switch(name)
351 {
352 case 'if':
353 return '((' + args[0].toCLLExpr(vars) + ') ? (' + args[1].toCLLExpr(vars) + ') : 0)';
354 case 'if:else':
355 return '((' + args[0].toCLLExpr(vars) + ') ? (' + args[1].toCLLExpr(vars) + ') : (' + args[2].toCLLExpr(vars) + '))';
356 case 'while:do':
357 throw new Error('while:do not allowed in expression context in llMessage block');
358 case 'addr_of':
359 return '&(' + args[0].toCLLExpr(vars) + ')';
360 case 'sizeof':
361 return 'sizeof(' + args[0].toCTypeName() + ')';
362 case 'get':
363 return args[0].toCLLExpr(vars) + '[' + args[1].toCLLExpr(vars) + ']';
364 case 'set':
365 return args[0].toCLLExpr(vars) + '[' + args[1].toCLLExpr(vars) + '] = ' + args[2].toCLLExpr(vars);
366 case 'not':
367 return '!(' + args[0].toCLLExpr(vars) + ')';
368 case 'mcall':
369 if (args[0] instanceof symbol) {
370 args[0] = new intlit(getMethodId(args[0].name));
371 }
372 default:
373 for (var i in args) {
374 args[i] = args[i].toCLLExpr(vars);
375 }
376 return name + '(' + args.join(', ') + ')';
377 }
378 };
211 379
212 function cObject(name) { 380 function cObject(name) {
213 this.name = name; 381 this.name = name;
214 this.slots = {}; 382 this.slots = {};
215 this.properties = []; 383 this.properties = [];
353 return this.toCInstance(); 521 return this.toCInstance();
354 } 522 }
355 523
356 var nextobject = 0; 524 var nextobject = 0;
357 525
358 object.prototype.toC = function() { 526
527 object.prototype.toCObject = function() {
359 var messages = this.messages; 528 var messages = this.messages;
360 var values = []; 529 var values = [];
361 var imports = [] 530 var imports = [];
362 var me = new cObject('object_' + nextobject++); 531 if (!this.name) {
532 this.name = 'object_' + nextobject++;
533 }
534 var me = new cObject(this.name);
363 this.symbols.typename = me.name; 535 this.symbols.typename = me.name;
364 if (this.symbols.needsenv) { 536 if (this.symbols.needsenv) {
365 me.addProperty('env', this.symbols.envVar(), 'struct ' + this.symbols.getEnvType() + ' * '); 537 me.addProperty('env', this.symbols.envVar(), 'struct ' + this.symbols.getEnvType() + ' * ');
366 me.hasenv = true; 538 me.hasenv = true;
367 } 539 }
379 throw new Error('Names in import:from statement must be symbols'); 551 throw new Error('Names in import:from statement must be symbols');
380 } 552 }
381 importsyms.push(new strlit(el.name)); 553 importsyms.push(new strlit(el.name));
382 }); 554 });
383 imports.push({symbols: new listlit(importsyms), src: messages[i].args[1]}); 555 imports.push({symbols: new listlit(importsyms), src: messages[i].args[1]});
556 } else if(messages[i].name == 'llProperty:withType:' && messages[i].args.length == 2) {
557 me.addProperty(messages[i].args[0].name, null, messages[i].args[1].toCTypeName())
558 } else if(messages[i].name == 'llMessage:withVars:andCode:' && messages[i].args.length == 3) {
559 var msgname = messages[i].args[0].name
560 var rawvars = messages[i].args[1].expressions;
561 var vars = {};
562 for(var v in rawvars) {
563 vars[rawvars[v].symbol.name] = rawvars[v].expression.toCTypeName();
564 }
565 me.addMessage(msgname, {
566 vars: vars,
567 lines: messages[i].args[2].toCLines(vars, true)
568 });
384 } else { 569 } else {
385 throw new Error('Only import and import:from calls allowed in object context'); 570
571 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 } 572 }
387 } else { 573 } else {
388 messages[i].toCObject(me); 574 messages[i].toCObject(me);
389 } 575 }
390 } 576 }
391 577
392 return me.toC(); 578 return me;
393 } 579 };
580
581 object.prototype.toC = function() {
582 return this.toCObject().toC();
583 };
394 584
395 var toplevelcode; 585 var toplevelcode;
396 var forwarddec; 586 var forwarddec;
397 587
398 function addBinaryOp(cobject, opname, cop, objtype) 588 function addBinaryOp(cobject, opname, cop, objtype)
442 vars: {str: 'string *'}, 632 vars: {str: 'string *'},
443 lines: [ 633 lines: [
444 'str = (string *)make_object(&string_meta, NULL, 0);', 634 'str = (string *)make_object(&string_meta, NULL, 0);',
445 'str->data = GC_MALLOC(12);', 635 'str->data = GC_MALLOC(12);',
446 'sprintf(str->data, "%d", self->num);', 636 'sprintf(str->data, "%d", self->num);',
447 'str->length = str->bytes = strlen(str->data);', 637 'str->len = str->bytes = strlen(str->data);',
448 'return &(str->header);' 638 'return &(str->header);'
449 ] 639 ]
450 }); 640 });
451 int32.addMessage('hash', { 641 int32.addMessage('hash', {
452 vars: {}, 642 vars: {},
457 return int32; 647 return int32;
458 } 648 }
459 649
460 function makeArray() 650 function makeArray()
461 { 651 {
462 var array = new cObject('array'); 652 var arrayfile = toplevel.names['array'];
463 array.addProperty('size', null, 'uint32_t'); 653 var ast = parseFile(arrayfile.path + '/' + arrayfile.file);
464 array.addProperty('storage', null, 'uint32_t'); 654 ast.name = 'array';
465 array.addProperty('data', null, 'object **'); 655 ast.populateSymbols(toplevel);
466 array.addMessage('get', { 656 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 } 657 }
524 658
525 function makeString() 659 function makeString()
526 { 660 {
527 var string = new cObject('string'); 661 var arrayfile = toplevel.names['string'];
528 string.addProperty('length', null, 'uint32_t'); 662 var ast = parseFile(arrayfile.path + '/' + arrayfile.file);
529 string.addProperty('bytes', null, 'uint32_t'); 663 ast.name = 'string';
530 string.addProperty('data', null, 'char *'); 664 ast.populateSymbols(toplevel);
531 string.addMessage('length', { 665 return ast.toCObject();
532 vars: {intret: 'obj_int32 *'},
533 lines: [
534 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
535 'intret->num = self->length;',
536 'return &(intret->header);'
537 ]
538 });
539 string.addMessage('byte_length', {
540 vars: {intret: 'obj_int32 *'},
541 lines: [
542 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
543 'intret->num = self->bytes;',
544 'return &(intret->header);'
545 ]
546 });
547 string.addMessage('EQ_', {
548 vars: {argb: 'string *'},
549 lines: [
550 'argb = va_arg(args, string *);',
551 'if (self->length == argb->length && self->bytes == argb->bytes && !memcmp(self->data, argb->data, self->bytes)) {',
552 ' return ' + toplevel.moduleVar('true') + ';',
553 '}',
554 'return ' + toplevel.moduleVar('false') + ';',
555 ]
556 });
557 string.addMessage('NEQ_', {
558 vars: {argb: 'string *'},
559 lines: [
560 'argb = va_arg(args, string *);',
561 'if (self->length != argb->length || self->bytes != argb->bytes || memcmp(self->data, argb->data, self->bytes)) {',
562 ' return ' + toplevel.moduleVar('true') + ';',
563 '}',
564 'return ' + toplevel.moduleVar('false') + ';',
565 ]
566 });
567 string.addMessage('print', {
568 vars: {},
569 lines: [
570 'fwrite(self->data, 1, self->bytes, stdout);',
571 'return &(self->header);'
572 ]
573 });
574 string.addMessage('string', {
575 vars: {},
576 lines: [ 'return &(self->header);' ]
577 });
578 string.addMessage('CAT_', {
579 vars: {argbo: 'object *', argb: 'string *', out: 'string *'},
580 lines: [
581 'argbo = va_arg(args, object *);',
582 'argb = (string *)mcall(' + getMethodId('string') + ', 1, argbo);',
583 'out = (string *)make_object(&string_meta, NULL, 0);',
584 'out->bytes = self->bytes + argb->bytes;',
585 'out->length = self->length + argb->length;',
586 'out->data = GC_MALLOC_ATOMIC(out->bytes+1);',
587 'memcpy(out->data, self->data, self->bytes);',
588 'memcpy(out->data + self->bytes, argb->data, argb->bytes + 1);',
589 'return &(out->header);'
590 ]
591 });
592 string.addMessage('byte', {
593 vars: {index: 'obj_int32 *', intret: 'obj_int32 *'},
594 lines: [
595 'index = va_arg(args, obj_int32 *);',
596 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
597 'intret->num = index->num < self->bytes ? self->data[index->num] : 0;',
598 'return &(intret->header);'
599 ]
600 });
601 string.addMessage('int32', {
602 vars: {intret: 'obj_int32 *'},
603 lines: [
604 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
605 'intret->num = atoi(self->data);',
606 'return &(intret->header);'
607 ]
608 });
609 string.addMessage('hash', {
610 vars: {intret: 'obj_int32 *', i: 'uint32_t'},
611 lines: [
612 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
613 'intret->num = 0;',
614 'if (self->bytes) {',
615 ' intret->num = self->data[0] << 7;',
616 ' for (i = 0; i < self->bytes; i++) {',
617 ' intret->num = (1000003 * intret->num) ^ self->data[i];',
618 ' }',
619 ' intret->num = intret->num ^ self->bytes;',
620 '}',
621 'return &(intret->header);'
622 ]
623 });
624 return string;
625 } 666 }
626 667
627 function makelambda() 668 function makelambda()
628 { 669 {
629 var clos = new cObject('lambda'); 670 var clos = new cObject('lambda');
768 function processUsedToplevel(toplevel) 809 function processUsedToplevel(toplevel)
769 { 810 {
770 var alwaysused = ['true', 'false']; 811 var alwaysused = ['true', 'false'];
771 var ret = ''; 812 var ret = '';
772 var modulenum = 0; 813 var modulenum = 0;
814 var visited = {};
815 for (var i in alwaysused) {
816 toplevel.used[alwaysused[i]] = true;
817 }
773 var newused = Object.keys(toplevel.used); 818 var newused = Object.keys(toplevel.used);
774 var allused = newused; 819 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) { 820 while (newused.length) {
782 for (var i in newused) { 821 for (var i in newused) {
783 debugprint('//---module', newused[i], '--- populate symbols'); 822 debugprint('//---module', newused[i], '--- populate symbols');
784 forwarddec += 'object * ' + toplevel.moduleVar(newused[i]) + ';\n'; 823 forwarddec += 'object * ' + toplevel.moduleVar(newused[i]) + ';\n';
785 toplevel.names[newused[i]].populateSymbols(toplevel); 824 toplevel.names[newused[i]].populateSymbols(toplevel);
792 newused.push(symbol); 831 newused.push(symbol);
793 allused.push(symbol); 832 allused.push(symbol);
794 } 833 }
795 } 834 }
796 } 835 }
797 for (var i in alwaysused) {
798 allused.push(alwaysused[i]);
799 }
800 836
801 for (var i = allused.length-1; i >= 0; i--) { 837 for (var i = allused.length-1; i >= 0; i--) {
802 var symbol = allused[i]; 838 var symbol = allused[i];
803 debugprint('//---module', symbol, '--- compile'); 839 debugprint('//---module', symbol, '(' + i +')--- compile');
804 ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n'; 840 ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n';
805 } 841 }
806 return ret; 842 return ret;
807 } 843 }
808 844
809 function makeCProg(obj) 845 function makeCProg(obj)
810 { 846 {
847 forwarddec = toplevelcode = '';
811 var builtins = builtinTypes(); 848 var builtins = builtinTypes();
812 forwarddec = toplevelcode = '';
813 for (var i in builtins) { 849 for (var i in builtins) {
814 forwarddec += builtins[i].toEarlyCDef(); 850 forwarddec += builtins[i].toEarlyCDef();
815 toplevelcode += builtins[i].toCDef(); 851 toplevelcode += builtins[i].toCDef();
816 } 852 }
817 addBuiltinModules(toplevel); 853 addBuiltinModules(toplevel);
930 this.selftype = typename; 966 this.selftype = typename;
931 return this.toC(); 967 return this.toC();
932 }; 968 };
933 lambda.prototype.toCModule = function() { 969 lambda.prototype.toCModule = function() {
934 return makeCProg(this); 970 return makeCProg(this);
971 };
972 lambda.prototype.toCLines = function(vars, needsreturn) {
973 var lines = [];
974 for (var i in this.args) {
975 var name = this.args[i].name;
976 if (name[0] == ':') {
977 name = name.substr(1);
978 }
979 if(name != 'self') {
980 lines.push(name + ' = va_arg(args, ' + vars[name] + ');');
981 }
982 }
983 for (var i in this.expressions) {
984 var exprlines = this.expressions[i].toCLines(vars, needsreturn && i == this.expressions.length - 1);
985 for (var j in exprlines) {
986 lines.push('\t' + exprlines[j]);
987 }
988 }
989 return lines;
990 }
991 lambda.prototype.toCLLExpr = function(vars) {
992 if (this.expressions.length != 1) {
993 throw new Error('lambda in expression context must have a single statement in llMessage block');
994 }
995 return this.expressions[0].toCLLExpr(vars);
935 } 996 }
936 997
937 assignment.prototype.toC = function() { 998 assignment.prototype.toC = function() {
938 debugprint('//assignment', this.symbol.name); 999 debugprint('//assignment', this.symbol.name);
939 var existing = this.symbols.find(this.symbol.name); 1000 var existing = this.symbols.find(this.symbol.name);
980 if (this.expression instanceof object && this.expression.symbols.needsparent) { 1041 if (this.expression instanceof object && this.expression.symbols.needsparent) {
981 cobj.addInit('self->' + escapeCName(this.symbol.name) + '->parent = (object *)self;'); 1042 cobj.addInit('self->' + escapeCName(this.symbol.name) + '->parent = (object *)self;');
982 } 1043 }
983 } 1044 }
984 }; 1045 };
1046 assignment.prototype.toCLines = function(vars, needsreturn) {
1047 return [(needsreturn ? 'return ' : '') + this.symbol.toCLLExpr(vars) + ' = ' + this.expression.toCLLExpr(vars) + ';']
1048 };