# HG changeset patch # User Michael Pavone # Date 1405840363 25200 # Node ID 0dc7322590dae0f23b3d731c498232c1de1aa0c3 # Parent bb2b4613fdc8a5dc3522bff3f5c2e32ca5a98712 Make import:from actually work. Fix some macro bugs. Add a cpointer primitive type for storing an opaque pointer to a C object. diff -r bb2b4613fdc8 -r 0dc7322590da cbackend.js --- a/cbackend.js Sat Jul 19 20:18:34 2014 -0700 +++ b/cbackend.js Sun Jul 20 00:12:43 2014 -0700 @@ -106,6 +106,13 @@ symbol.prototype.toCTypeName = function() { return this.cleanName(); }; +symbol.prototype.cSafeName = function() { + var name = this.cleanName(); + if (name[0] >= "0" && name[0] <= "9") { + name = '_tp_' + name; + } + return name; +}; symbol.prototype.toCLLExpr = function(vars) { var name = this.cleanName(); if (name in vars) { @@ -121,13 +128,13 @@ info = symbols.find(name, false, true); } if (!info) { - return name; + return this.cSafeName(); } if (info.type == 'toplevel') { return toplevel.moduleVar(name); } else if (info.type == 'self') { if (info.isll || !(info.def instanceof lambda)) { - return 'self->' + name; + return 'self->' + this.cSafeName(); } else { return 'mcall(' + getMethodId(name) + '/* ' + name + ' */, 1, self)'; } @@ -417,6 +424,7 @@ this.parent = 'NULL'; this.init = []; this.initmsgadded = false; + this.imported = []; } cObject.prototype.addInclude = function(includefile) { @@ -467,14 +475,19 @@ }; cObject.prototype.addImport = function(symbols, source) { - this.imported.push(source); - var importNum = imported.length - 1; + var importNum = this.imported.indexOf(source); + if (importNum < 0) { + var importNum = this.imported.length; + this.imported.push(source); + this.addInit('self->import_' + importNum + ' = ' + source.toC() + ';'); + } if (symbols) { + var self = this; each(symbols, function(i, sym) { - this.addMessage(sym.name, { + self.addMessage(sym.name, { vars: {}, lines: [ - 'return self->import_' + importNum + '->meta->meth_lookup[method_id & 0xF](method_id, num_args, self->import_' + importNum + ', args);' + 'return self->import_' + importNum + '->meta->meth_lookup[method_id & 0xF](method_id, num_params, self->import_' + importNum + ', args);' ] }); }); @@ -515,6 +528,9 @@ objdef += '\tobject * ' + this.properties[i] + ';\n' } } + for (var i in this.imported) { + objdef += '\tobject * import_' + i + ';\n'; + } objdef += '} ' + this.name + ';\nobj_meta ' + this.name + '_meta;\n'; return includes + objdef; } @@ -604,9 +620,13 @@ } for (var i in messages) { if (messages[i] instanceof funcall) { - if (messages[i].name == 'import:' && messages[i].args.length == 1) { + var msgname = messages[i].name; + if (msgname[msgname.length-1] == ':') { + msgname = msgname.substr(0, msgname.length-1); + } + if (msgname == 'import' && messages[i].args.length == 1) { me.addImport(false, messages[i].args[0]); - } else if(messages[i].name == 'import:from:' && messages[i].args.length == 2) { + } else if(msgname == 'import:from' && messages[i].args.length == 2) { var importsyms = []; each(messages[i].args[0].val, function(i, el) { if (!(el instanceof symbol)) { @@ -615,9 +635,9 @@ importsyms.push(el); }); me.addImport(importsyms, messages[i].args[1]); - } else if(messages[i].name == 'llProperty:withType:' && messages[i].args.length == 2) { + } else if(msgname == 'llProperty:withType' && messages[i].args.length == 2) { me.addProperty(messages[i].args[0].name, null, messages[i].args[1].toCTypeName()); - } else if(messages[i].name == 'llMessage:withVars:andCode:' && messages[i].args.length == 3) { + } else if(msgname == 'llMessage:withVars:andCode' && messages[i].args.length == 3) { if (messages[i].args[0] instanceof symbol) { var msgname = messages[i].args[0].name; } else if (messages[i].args[0] instanceof strlit) { @@ -628,13 +648,13 @@ var rawvars = messages[i].args[1].expressions; var vars = {}; for(var v in rawvars) { - vars[rawvars[v].symbol.name] = rawvars[v].expression.toCTypeName(); + vars[rawvars[v].symbol.cSafeName()] = rawvars[v].expression.toCTypeName(); } me.addMessage(msgname, { vars: vars, lines: messages[i].args[2].toCLines(vars, true) }); - } else if(messages[i].name == 'includeSystemHeader:' && messages[i].args.length == 1) { + } else if(msgname == 'includeSystemHeader' && messages[i].args.length == 1) { me.addInclude("<" + messages[i].args[0].val + ">"); } else { @@ -786,6 +806,29 @@ return intObj; } +function makeCPointer() +{ + var cptr = new cObject('cpointer'); + cptr.addProperty('val', null, 'void *'); + //cpointer: + //1234567890 + cptr.addMessage('string', { + vars: {ret: 'string *'}, + lines: [ + 'ret = make_object(&string_meta, NULL, 0);', + //22 digits for worst case sensible representation + //10 chars for prefix + //4 for slop + //1 for null terminator + 'ret->data = GC_MALLOC_ATOMIC(22+10+4+1);', + 'snprintf(ret->data, 22+10+4, "cpointer: %p", self->val);', + 'ret->data[22+10+4] = 0;', + 'return (object *)ret;' + ] + }); + return cptr; +} + function makeArray() { var arrayfile = toplevel.names['array']; @@ -827,7 +870,7 @@ { return [makeInt(64, false), makeInt(32, false), makeInt(16, false), makeInt(8, false), makeInt(64, true) , makeInt(32, true), makeInt(16, true), makeInt(8, true), - makeArray(), makeString(), makelambda()]; + makeArray(), makeString(), makelambda(), makeCPointer()]; } function addBuiltinModules(toplevel) diff -r bb2b4613fdc8 -r 0dc7322590da compiler.js --- a/compiler.js Sat Jul 19 20:18:34 2014 -0700 +++ b/compiler.js Sun Jul 20 00:12:43 2014 -0700 @@ -380,6 +380,13 @@ } else { throw new Error("Unexpected AST type for foreign:"); } + } else if (this.name == 'import:from:' && symbols instanceof osymbols && this.args.length == 2) { + each(this.args[0].val, function(i, el) { + if (!(el instanceof symbol)) { + throw new Error('Names in import:from statement must be symbols'); + } + symbols.defineMsg(el.name, new lambda([], [])); + }); } else if (this.name == 'llProperty:withType:') { if (this.args[0] instanceof symbol) { if ((this.args[1] instanceof symbol) || (this.args[1] instanceof funcall)) { @@ -391,10 +398,11 @@ } else { throw new Error("First argument to llProperty:withType: must be a symbol or string"); } - } else if (this.name == 'llMessage:withVars:andCode:') { + } else if (this.name == 'llMessage:withVars:andCode:' && symbols instanceof osymbols) { if (this.args[0] instanceof symbol || this.args[0] instanceof strlit) { if (this.args[1] instanceof lambda) { if (this.args[2] instanceof lambda) { + symbols.defineMsg(this.args[0].name, this.args[2]); isll = true; } else { diff -r bb2b4613fdc8 -r 0dc7322590da interp.js --- a/interp.js Sat Jul 19 20:18:34 2014 -0700 +++ b/interp.js Sun Jul 20 00:12:43 2014 -0700 @@ -757,14 +757,15 @@ for (var i = 0; i < this.args.length; i++) { env.syms[this.args[i].cleanName()] = {}; } + var outexprs = [] for (var i = 0; i < this.expressions.length; i++) { var expr = this.expressions[i]; if (expr instanceof assignment) { if (expr.expression instanceof funcall && expr.expression.name == 'macro:') { - env.defMacro(expr.symbol.name, exp.expression.args[0].eval(env)); + env.defMacro(expr.symbol.name, expr.expression.args[0].eval(env)); } else { env.syms[expr.symbol.cleanName()] = {}; - this.expressions[i] = expr.macroexpand(env); + outexprs.push(expr.macroexpand(env)); try { if (this.expressions[i].expression.isconstant()) { env.syms[expr.symbol.cleanName()] = this.expressions[i].expression.eval(env); @@ -780,9 +781,10 @@ } } } else { - this.expressions[i] = expr.macroexpand(env); + outexprs.push(expr.macroexpand(env)); } } + this.expressions = outexprs; return this; };