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
|
||||
isImplicit:boolean;
|
||||
isOptional:boolean;
|
||||
allLocals: JLocalDef[];
|
||||
capturedLocals: JLocalDef[];
|
||||
}
|
||||
|
||||
export interface JOptionalParameter extends JNode
|
||||
|
@ -377,6 +379,7 @@ module TDev.AST.Json
|
|||
{
|
||||
name:string;
|
||||
type:JTypeRef;
|
||||
isByRef: boolean;
|
||||
}
|
||||
|
||||
// Response to:
|
||||
|
|
|
@ -88,8 +88,11 @@ module TDev {
|
|||
|
||||
public visitExprHolder(env: H.Env, locals: J.JLocalDef[], expr: J.JExprHolder) {
|
||||
var decls = locals.map(d => {
|
||||
var x = H.defaultValueForType(this.libraryMap, d.type);
|
||||
return this.visit(env, d) + (x ? " = " + x : "") + ";";
|
||||
// Side-effect: marks [d] as promoted, if needed.
|
||||
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) +
|
||||
(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)
|
||||
// - arrays, strings, user-defined objects, which are in fact of type
|
||||
// "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) {
|
||||
return H.mkType(env, this.libraryMap, type)+" "+H.resolveLocal(env, name, id);
|
||||
public visitLocalDef(env: H.Env, name: string, id: string, type: J.JTypeRef, isByRef: boolean) {
|
||||
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.
|
||||
|
|
|
@ -140,6 +140,10 @@ module TDev {
|
|||
libName: 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 {
|
||||
|
@ -149,9 +153,18 @@ module TDev {
|
|||
globalNameMap: e.globalNameMap,
|
||||
libName: e.libName,
|
||||
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 {
|
||||
var usedNames: StringMap<boolean> = {};
|
||||
var m = libName ? g.libraries[libName] : g.program;
|
||||
|
@ -165,6 +178,7 @@ module TDev {
|
|||
globalNameMap: g,
|
||||
libName: libName,
|
||||
indent: "",
|
||||
promotedIds: {},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -240,6 +254,10 @@ module TDev {
|
|||
return n;
|
||||
}
|
||||
|
||||
export function shouldPromoteToRef(e: Env, t: J.JTypeRef, isByRef: boolean) {
|
||||
return typeof t == "string" && isByRef;
|
||||
}
|
||||
|
||||
|
||||
// --- Helper functions.
|
||||
// For constructing / modifying AST nodes.
|
||||
|
@ -325,7 +343,7 @@ module TDev {
|
|||
var retType = outParams.length ? mkType(env, libMap, outParams[0].type) : "void";
|
||||
var args = "(" + inParams.map(p => mkParam(env, libMap, p)).join(", ") + ")";
|
||||
if (isLambda)
|
||||
return "[=] "+args+" -> "+retType;
|
||||
return "[=] "+args+" mutable -> "+retType;
|
||||
else
|
||||
return retType + " " + name + args;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ module TDev {
|
|||
return this.visitGlobalDef(env, n13.name, n13.type, n13.comment);
|
||||
case "localDef":
|
||||
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":
|
||||
var n11 = <J.JLocalRef> n;
|
||||
return this.visitLocalRef(env, n11.name, <any> n11.localId);
|
||||
|
@ -115,7 +115,8 @@ module TDev {
|
|||
env: T,
|
||||
name: 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 visitExprHolder(
|
||||
env: T,
|
||||
|
|
|
@ -4,7 +4,7 @@ module TDev.Cloud {
|
|||
export var lite = false;
|
||||
export var fullTD = true;
|
||||
export var litePermissions:StringMap<boolean> = {};
|
||||
var microbitGitTag = "v12";
|
||||
var microbitGitTag = "v13";
|
||||
|
||||
export var useEmbeddedGcc = true;
|
||||
export var useNativeCompilation = false;
|
||||
|
|
Загрузка…
Ссылка в новой задаче