# HG changeset patch # User Mike Pavone # Date 1342149255 25200 # Node ID 4e983fe32047cce4dc6e9a509d71dcf541b0260a # Parent 0558dad9d061ce23f12a3cb06c1ff31f9e1bc1a2 Fix closures as methods so that private vars work diff -r 0558dad9d061 -r 4e983fe32047 cbackend.js --- a/cbackend.js Wed Jul 11 21:57:38 2012 -0700 +++ b/cbackend.js Thu Jul 12 20:14:15 2012 -0700 @@ -55,12 +55,8 @@ return name; } -symbol.prototype.toC = function() { - var name = this.cleanName(); - var info = this.symbols.find(name); - if (!info) { - throw new Error('symbol ' + name + ' not found'); - } +function getSymbolPrefix(info) +{ var pre = ''; switch(info.type) { case 'self': @@ -78,6 +74,13 @@ pre += 'parent->'; } break; + case 'recupvar': + if (info.subtype == 'object') { + pre = 'self->env->'; + } else { + //TODO: fill this case in if necessary + } + pre += getSymbolPrefix(info.parent); case 'toplevel': pre = 'modules.'; modules[name] = false; @@ -85,7 +88,17 @@ case 'closedover': pre = 'myenv->'; } - return pre + escapeCName(name); + return pre; +} + +symbol.prototype.toC = function() { + var name = this.cleanName(); + var info = this.symbols.find(name); + if (!info) { + throw new Error('symbol ' + name + ' not found'); + } + + return getSymbolPrefix(info) + escapeCName(name); } var declaredInts = {}; @@ -146,7 +159,7 @@ if (this.receiver) { args.splice(0, 0, this.receiver); } - var method = false; + var method = false; var funinfo = this.symbols.find(name); if (!funinfo || funinfo.def instanceof setter) { method = true; @@ -154,7 +167,8 @@ switch(funinfo.type) { case 'self': - if (args.length < funinfo.def.args.length || funinfo.def.args[0].name != 'self') { + + if (args.length < funinfo.def.args.length || !funinfo.def.args.length || funinfo.def.args[0].name != 'self') { args.splice(0, 0, new symbol('self', this.symbols)); } else { args.splice(0, 1); @@ -207,6 +221,9 @@ cObject.prototype.addProperty = function(propname, value, type) { if (type != undefined) { this.properties.push([propname, type]); + if (value !== null) { + this.values.push(value); + } } else { var escaped = escapeCName(propname); this.addMessage(propname, { @@ -288,6 +305,10 @@ var values = []; var imports = [] var me = new cObject('object_' + nextobject++); + if (this.symbols.needsenv) { + me.addProperty('env', this.symbols.envVar(), 'struct ' + this.symbols.getEnvType() + ' * '); + me.hasenv = true; + } for (var i in messages) { if (messages[i] instanceof funcall) { if (messages[i].name == 'import:' && messages[i].args.length == 1) { @@ -308,6 +329,7 @@ messages[i].toCObject(me); } } + forwarddec += me.toEarlyCDef(); toplevelcode += me.toCDef(); return me.toCInstance(); @@ -491,7 +513,7 @@ } if (Object.keys(this.symbols.closedover).length) { - forwarddec += 'typedef struct {\n'; + forwarddec += 'typedef struct lambda_' + mynum + '_env {\n'; for (var varname in this.symbols.closedover) { forwarddec += '\tobject * ' + escapeCName(varname) + ';\n'; } @@ -515,16 +537,20 @@ } toplevelcode += args.join('') + '\tva_end(args);\n' + exprs.join(';\n\t') + '\n}\n'; - if (this.symbols.parentEnvType() != 'void') { - if (this.symbols.passthruenv) { - var envvar = 'env'; - } else { - var envvar = 'myenv'; + if (this.selftype) { + return 'lambda_' + mynum; + } else { + if (this.symbols.parentEnvType() != 'void') { + if (this.symbols.passthruenv) { + var envvar = 'env'; + } else { + var envvar = 'myenv'; + } + return 'make_closure(' + envvar + ', lambda_' + mynum + ')'; + } else { + toplevelcode += 'closure lambda_obj_' + mynum + ' = {{&lambda_meta, NULL}, NULL, lambda_' + mynum + '};\n'; + return '((object *)&lambda_obj_' + mynum + ')'; } - return 'make_closure(' + envvar + ', lambda_' + mynum + ')'; - } else { - toplevelcode += 'closure lambda_obj_' + mynum + ' = {{&lambda_meta, NULL}, NULL, lambda_' + mynum + '};\n'; - return '((object *)&lambda_obj_' + mynum + ')'; } }; lambda.prototype.toCObject = function(typename) { @@ -571,7 +597,7 @@ } cobj.addMessage(this.symbol.name, { vars: messagevars, - lines: [paramget + 'return ccall(' + val + ', ' + params.length + (params.length ? ', ' : '') + params.join(', ') + ');'] + lines: [paramget + 'return ' + val + '(' + (cobj.hasenv ? 'self->env' : 'NULL') + ', ' + params.length + (params.length ? ', ' : '') + params.join(', ') + ');'] }); } else { cobj.addProperty(this.symbol.name, val); diff -r 0558dad9d061 -r 4e983fe32047 compiler.js --- a/compiler.js Wed Jul 11 21:57:38 2012 -0700 +++ b/compiler.js Thu Jul 12 20:14:15 2012 -0700 @@ -45,8 +45,9 @@ { this.parent = parent; this.names = {}; + this.needsenv = false; } -osymbols.prototype.find = function(name) { +osymbols.prototype.find = function(name, nestedcall) { if (name in this.names) { if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') { return { @@ -59,13 +60,15 @@ def: this.names[name], }; } else if(this.parent) { - var ret = this.parent.find(name); + var ret = this.parent.find(name, nestedcall); if (ret) { if(ret.type == 'self') { ret.type = 'parent'; ret.depth = 1; } else if(ret.type == 'parent') { ret.depth++; + } else if(ret.type == 'closedover' || ret.type == 'upvar') { + this.needsenv = true; } } return ret; @@ -101,6 +104,9 @@ osymbols.prototype.getEnvType = function() { return this.parent.getEnvType(); } +osymbols.prototype.envVar = function() { + return this.parent.envVar(); +} function lsymbols(parent) { @@ -187,6 +193,14 @@ return this.envtype; } } +lsymbols.prototype.envVar = function() { + if (Object.keys(this.closedover).length) { + return 'myenv'; + } else if(this.passthruenv) { + return 'env'; + } + return null; +} var mainModule; diff -r 0558dad9d061 -r 4e983fe32047 parser.js --- a/parser.js Wed Jul 11 21:57:38 2012 -0700 +++ b/parser.js Thu Jul 12 20:14:15 2012 -0700 @@ -54,7 +54,7 @@ function lambda(args, expressions) { - this.args = args; + this.args = args ? args : []; this.expressions = expressions; } diff -r 0558dad9d061 -r 4e983fe32047 samples/private Binary file samples/private has changed