Experimental support for compiling closures using GCC.

This commit is contained in:
Jonathan Protzenko 2015-08-21 15:52:57 -07:00
Родитель 7f0c4a6ed8
Коммит 23182abe5d
4 изменённых файлов: 29 добавлений и 11 удалений

Просмотреть файл

@ -1370,7 +1370,7 @@ module TDev.AST
}
}
if (!this.inShim && this.invisibleLocals.indexOf(l) >= 0) {
if (!this.inShim && this.invisibleLocals.indexOf(l) >= 0 && !document.location.href.match(/usegcc=1/)) {
this.markError(t, lf("TD208: inline functions cannot access locals from outside; try 'promote to data' on '{0}'", l.getName()))
}

Просмотреть файл

@ -92,6 +92,23 @@ module TDev {
return env.indent + this.visit(env, expr)+";";
}
public visitInlineActions(env: EmitterEnv, expr: J.JExprHolder, actions: J.JInlineAction[]) {
var map = {};
expr.locals.forEach((l: J.JLocalDef) => { map[l.id] = l.name });
var lambdas = actions.map((a: J.JInlineAction) => {
var n = H.mangleUnique(env, map[a.reference.id], a.reference.id);
return (
env.indent + "auto "+n+"_ = "+
this.visitAction(env, "", n, a.inParameters, a.outParameters, a.body, true)+";\n" +
env.indent + "auto "+n+" = new std::function<"+
H.mkSignature(env, this.libraryMap, "", a.inParameters, a.outParameters)+
">("+n+"_);"
);
});
return (lambdas.join("\n")+"\n"+
env.indent + this.visit(env, expr.tree) + ";");
}
public visitExprHolder(env: EmitterEnv, locals: J.JLocalDef[], expr: J.JExprHolder) {
var decls = locals.map(d => {
var x = H.defaultValueForType(this.libraryMap, d.type);
@ -387,7 +404,8 @@ module TDev {
id: string,
inParams: J.JLocalDef[],
outParams: J.JLocalDef[],
body: J.JStmt[])
body: J.JStmt[],
isLambda=false)
{
// This function is always called with H.willCompile == true, meaning
// it's not a shim.
@ -402,8 +420,8 @@ module TDev {
].filter(x => x != "").join("\n");
// The name of a function is unique per library, so don't go through
// [mangleUnique].
var head = H.mkSignature(env, this.libraryMap, H.mangleName(name), inParams, outParams);
return env.indent + head + " {\n" + bodyText + "\n"+env.indent+"}";
var head = H.mkSignature(env, this.libraryMap, H.mangleName(name), inParams, outParams, isLambda);
return (isLambda ? "" : env.indent) + head + " {\n" + bodyText + "\n"+env.indent+"}";
}
private compileImageLiterals(e: EmitterEnv) {

Просмотреть файл

@ -263,17 +263,17 @@ module TDev {
return mkType(env, libMap, p.type)+" "+mangleDef(env, p);
}
export function mkSignature(env: Env, libMap: LibMap, name: string, inParams: J.JLocalDef[], outParams: J.JLocalDef[]) {
export function mkSignature(env: Env, libMap: LibMap, name: string, inParams: J.JLocalDef[], outParams: J.JLocalDef[], isLambda=false) {
if (outParams.length > 1)
throw new Error("Not supported (multiple return parameters)");
var retType = outParams.length ? mkType(env, libMap, outParams[0].type) : "void";
if (name == "main")
name = "app_main";
return [
retType, " ", name, "(",
inParams.map(p => mkParam(env, libMap, p)).join(", "),
")",
].join("");
var args = "(" + inParams.map(p => mkParam(env, libMap, p)).join(", ") + ")";
if (isLambda)
return "[=] "+args+" -> "+retType;
else
return retType + " " + name + args;
}
// Generate the return instruction for the function.

Просмотреть файл

@ -129,7 +129,7 @@ module TDev {
public visitContinue(env: T): U { throw new Error("Not implemented"); }
public visitInlineActions(
env: T,
expr: J.JExpr,
expr: J.JExprHolder,
actions: J.JInlineAction[]): U { throw new Error("Not implemented"); }
public visitWhile(env: T, cond: J.JExprHolder, body: J.JStmt[]): U { throw new Error("Not implemented"); }
public visitFor(