Straigthen out the story of the gigantic mutual recursion between all libraries
in a program, and clean up the code. Now allows compiling a library to correct,
albeit useless, C++.
This commit is contained in:
Jonathan Protzenko 2015-06-15 15:26:59 -07:00
Родитель 15d46ff89e
Коммит 60ba6878be
2 изменённых файлов: 30 добавлений и 25 удалений

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

@ -14,17 +14,12 @@ module TDev {
// Assuming all library references have been resolved, compile either the
// main app or one of said libraries.
function compile1(libs: J.JApp[], a: J.JApp): { prototypes: string; code: string; prelude: string; libName: string } {
var i = libs.indexOf(a);
var libRef: J.JCall = null;
if (i >= 0) {
libRef = H.mkLibraryRef(libs[i].name);
}
try {
lift(a);
var libName = i >= 0 ? H.mangleName(libs[i].name) : null;
var libRef: J.JCall = a.isLibrary ? H.mkLibraryRef(a.name) : null;
var libName = a.isLibrary ? H.mangleName(a.name) : null;
var e = new Emitter(libRef, libName, libs);
e.visit(i >= 0 ? indent(emptyEnv()) : emptyEnv(), a);
e.visit(emptyEnv(), a);
return e;
} catch (e) {
console.error("Compilation error", e);
@ -45,24 +40,20 @@ module TDev {
return Promise.as(J.dump(s));
});
});
return Promise.join(textPromises).then((libs: J.JApp[]) => {
var compiled = libs.concat([a]).map((a: J.JApp) => compile1(libs, a));
var wrapNamespaceIf = (x: { libName: string }, s: string) => {
if (x.libName != null)
return "namespace "+x.libName+" {\n"+
" // Disclaimer: some of these declarations/definitions may be useless.\n"+
" // TODO: prune unused variable declarations and function definitions.\n"+
s+
"\n}";
else
return s;
};
textPromises.push(Promise.as(a));
return Promise.join(textPromises).then((everything: J.JApp[]) => {
var compiled = everything.map((a: J.JApp) => compile1(everything, a));
return Promise.as(
compiled.map(x => x.prelude)
.concat(compiled.map(x => wrapNamespaceIf(x, x.prototypes)))
.concat(compiled.map(x => wrapNamespaceIf(x, x.code)))
.concat(compiled.map(x => x.prototypes))
.concat(compiled.map(x => x.code))
.filter(x => x != "")
.join("\n")
.join("\n") +
(a.isLibrary
? "\nvoid app_main() {\n"+
" uBit.display.scrollString(\"Error: trying to run a library\");\n"+
"}\n"
: "")
);
});
}

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

@ -377,9 +377,23 @@ module TDev {
e.indent + "}\n\n";
}
private wrapNamespaceIf (s: string) {
if (this.libName != null)
return "namespace "+this.libName+" {\n"+
" // Disclaimer: some of these declarations/definitions may be useless.\n"+
" // TODO: prune unused variable declarations and function definitions.\n"+
s+
"\n}";
else
return s;
}
// This function runs over all declarations. After execution, the three
// member fields [prelude], [prototypes] and [code] are filled accordingly.
public visitApp(e: EmitterEnv, decls: J.JDecl[]) {
if (this.libName)
e = indent(e);
// Some parts of the emitter need to lookup library names by their id
decls.forEach((x: J.JDecl) => {
if (x.nodeType == "library") {
@ -432,8 +446,8 @@ module TDev {
// By convention, because we're forced to return a string, write the
// output parameters in the member variables. Image literals are scoped
// within our namespace.
this.prototypes = globalsCode + forwardDeclarations.join("\n");
this.code = this.compileImageLiterals(e) + userFunctions.join("\n");
this.prototypes = this.wrapNamespaceIf(globalsCode + forwardDeclarations.join("\n"));
this.code = this.wrapNamespaceIf(this.compileImageLiterals(e) + userFunctions.join("\n"));
// [embedded.ts] now reads the three member fields separately and
// ignores this return value.