Generate proper C++ for capture by-reference.
This commit is contained in:
Родитель
2a575e029c
Коммит
75c3f42594
|
@ -250,6 +250,8 @@ module TDev.AST.Json
|
||||||
locals?:JLocalDef[]; // this contains the reference in short mode; it never contains anything else
|
locals?:JLocalDef[]; // this contains the reference in short mode; it never contains anything else
|
||||||
isImplicit:boolean;
|
isImplicit:boolean;
|
||||||
isOptional:boolean;
|
isOptional:boolean;
|
||||||
|
allLocals: JLocalDef[];
|
||||||
|
capturedLocals: JLocalDef[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface JOptionalParameter extends JNode
|
export interface JOptionalParameter extends JNode
|
||||||
|
@ -377,6 +379,7 @@ module TDev.AST.Json
|
||||||
{
|
{
|
||||||
name:string;
|
name:string;
|
||||||
type:JTypeRef;
|
type:JTypeRef;
|
||||||
|
isByRef: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response to:
|
// Response to:
|
||||||
|
|
|
@ -88,8 +88,11 @@ module TDev {
|
||||||
|
|
||||||
public visitExprHolder(env: H.Env, locals: J.JLocalDef[], expr: J.JExprHolder) {
|
public visitExprHolder(env: H.Env, locals: J.JLocalDef[], expr: J.JExprHolder) {
|
||||||
var decls = locals.map(d => {
|
var decls = locals.map(d => {
|
||||||
var x = H.defaultValueForType(this.libraryMap, d.type);
|
// Side-effect: marks [d] as promoted, if needed.
|
||||||
return this.visit(env, d) + (x ? " = " + x : "") + ";";
|
var decl = this.visit(env, d);
|
||||||
|
var defaultValue = H.defaultValueForType(this.libraryMap, d.type);
|
||||||
|
var initialValue = !H.isPromoted(env, d.id) && defaultValue ? " = " + defaultValue : "";
|
||||||
|
return decl + initialValue + ";";
|
||||||
});
|
});
|
||||||
return decls.join("\n"+env.indent) +
|
return decls.join("\n"+env.indent) +
|
||||||
(decls.length ? "\n" + env.indent : "") +
|
(decls.length ? "\n" + env.indent : "") +
|
||||||
|
@ -104,11 +107,23 @@ module TDev {
|
||||||
// which C and C++ accept both "f" and "&f" (we hence use the former)
|
// which C and C++ accept both "f" and "&f" (we hence use the former)
|
||||||
// - arrays, strings, user-defined objects, which are in fact of type
|
// - arrays, strings, user-defined objects, which are in fact of type
|
||||||
// "ManagedType<T>", no "&" operator here.
|
// "ManagedType<T>", no "&" operator here.
|
||||||
return H.resolveLocal(env, name, id);
|
// However, we now support capture-by-reference. This means that the
|
||||||
|
// data is ref-counted (so as to be shared), but assignment and
|
||||||
|
// reference operate on the ref-counted data (not on the pointer), so we
|
||||||
|
// must add a dereference there.
|
||||||
|
var prefix = H.isPromoted(env, id) ? "*" : "";
|
||||||
|
return prefix+H.resolveLocal(env, name, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public visitLocalDef(env: H.Env, name: string, id: string, type: J.JTypeRef) {
|
public visitLocalDef(env: H.Env, name: string, id: string, type: J.JTypeRef, isByRef: boolean) {
|
||||||
return H.mkType(env, this.libraryMap, type)+" "+H.resolveLocal(env, name, id);
|
var t = H.mkType(env, this.libraryMap, type);
|
||||||
|
var l = H.resolveLocal(env, name, id);
|
||||||
|
if (H.shouldPromoteToRef(env, type, isByRef)) {
|
||||||
|
H.markPromoted(env, id);
|
||||||
|
return "ManagedType<"+ t + "> " + l + "(new "+t+")";
|
||||||
|
} else {
|
||||||
|
return t + " " + l;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allows the target to redefine their own string type.
|
// Allows the target to redefine their own string type.
|
||||||
|
|
|
@ -140,6 +140,10 @@ module TDev {
|
||||||
libName: string;
|
libName: string;
|
||||||
|
|
||||||
indent: string;
|
indent: string;
|
||||||
|
|
||||||
|
// A table of id's that have been promoted to ref-counted types (because
|
||||||
|
// they were captured by a closure). Modified in an imperative manner.
|
||||||
|
promotedIds: StringMap<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function indent(e: Env): Env {
|
export function indent(e: Env): Env {
|
||||||
|
@ -149,9 +153,18 @@ module TDev {
|
||||||
globalNameMap: e.globalNameMap,
|
globalNameMap: e.globalNameMap,
|
||||||
libName: e.libName,
|
libName: e.libName,
|
||||||
indent: e.indent + " ",
|
indent: e.indent + " ",
|
||||||
|
promotedIds: e.promotedIds,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function markPromoted(e: Env, id: string) {
|
||||||
|
e.promotedIds[id] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isPromoted(e: Env, id: string) {
|
||||||
|
return e.promotedIds[id];
|
||||||
|
}
|
||||||
|
|
||||||
export function emptyEnv(g: GlobalNameMap, libName: string): Env {
|
export function emptyEnv(g: GlobalNameMap, libName: string): Env {
|
||||||
var usedNames: StringMap<boolean> = {};
|
var usedNames: StringMap<boolean> = {};
|
||||||
var m = libName ? g.libraries[libName] : g.program;
|
var m = libName ? g.libraries[libName] : g.program;
|
||||||
|
@ -165,6 +178,7 @@ module TDev {
|
||||||
globalNameMap: g,
|
globalNameMap: g,
|
||||||
libName: libName,
|
libName: libName,
|
||||||
indent: "",
|
indent: "",
|
||||||
|
promotedIds: {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,6 +254,10 @@ module TDev {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function shouldPromoteToRef(e: Env, t: J.JTypeRef, isByRef: boolean) {
|
||||||
|
return typeof t == "string" && isByRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// --- Helper functions.
|
// --- Helper functions.
|
||||||
// For constructing / modifying AST nodes.
|
// For constructing / modifying AST nodes.
|
||||||
|
@ -325,7 +343,7 @@ module TDev {
|
||||||
var retType = outParams.length ? mkType(env, libMap, outParams[0].type) : "void";
|
var retType = outParams.length ? mkType(env, libMap, outParams[0].type) : "void";
|
||||||
var args = "(" + inParams.map(p => mkParam(env, libMap, p)).join(", ") + ")";
|
var args = "(" + inParams.map(p => mkParam(env, libMap, p)).join(", ") + ")";
|
||||||
if (isLambda)
|
if (isLambda)
|
||||||
return "[=] "+args+" -> "+retType;
|
return "[=] "+args+" mutable -> "+retType;
|
||||||
else
|
else
|
||||||
return retType + " " + name + args;
|
return retType + " " + name + args;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ module TDev {
|
||||||
return this.visitGlobalDef(env, n13.name, n13.type, n13.comment);
|
return this.visitGlobalDef(env, n13.name, n13.type, n13.comment);
|
||||||
case "localDef":
|
case "localDef":
|
||||||
var n1 = <J.JLocalDef> n;
|
var n1 = <J.JLocalDef> n;
|
||||||
return this.visitLocalDef(env, n1.name, n1.id, n1.type);
|
return this.visitLocalDef(env, n1.name, n1.id, n1.type, n1.isByRef);
|
||||||
case "localRef":
|
case "localRef":
|
||||||
var n11 = <J.JLocalRef> n;
|
var n11 = <J.JLocalRef> n;
|
||||||
return this.visitLocalRef(env, n11.name, <any> n11.localId);
|
return this.visitLocalRef(env, n11.name, <any> n11.localId);
|
||||||
|
@ -115,7 +115,8 @@ module TDev {
|
||||||
env: T,
|
env: T,
|
||||||
name: string,
|
name: string,
|
||||||
id: string,
|
id: string,
|
||||||
type: J.JTypeRef): U { throw new Error("Not implemented"); }
|
type: J.JTypeRef,
|
||||||
|
isByRef: boolean): U { throw new Error("Not implemented"); }
|
||||||
public visitLocalRef(env: T, name: string, id: string): U { throw new Error("Not implemented"); }
|
public visitLocalRef(env: T, name: string, id: string): U { throw new Error("Not implemented"); }
|
||||||
public visitExprHolder(
|
public visitExprHolder(
|
||||||
env: T,
|
env: T,
|
||||||
|
|
|
@ -4,7 +4,7 @@ module TDev.Cloud {
|
||||||
export var lite = false;
|
export var lite = false;
|
||||||
export var fullTD = true;
|
export var fullTD = true;
|
||||||
export var litePermissions:StringMap<boolean> = {};
|
export var litePermissions:StringMap<boolean> = {};
|
||||||
var microbitGitTag = "v12";
|
var microbitGitTag = "v13";
|
||||||
|
|
||||||
export var useEmbeddedGcc = true;
|
export var useEmbeddedGcc = true;
|
||||||
export var useNativeCompilation = false;
|
export var useNativeCompilation = false;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче