Skip to content

Commit

Permalink
Add magicport source to repo
Browse files Browse the repository at this point in the history
  • Loading branch information
yebblies committed Apr 5, 2015
1 parent 683ab81 commit 7e9398a
Show file tree
Hide file tree
Showing 9 changed files with 5,880 additions and 0 deletions.
781 changes: 781 additions & 0 deletions src/magicport/ast.d

Large diffs are not rendered by default.

1,719 changes: 1,719 additions & 0 deletions src/magicport/dprinter.d

Large diffs are not rendered by default.

316 changes: 316 additions & 0 deletions src/magicport/magicport2.d
@@ -0,0 +1,316 @@

import std.file;
import std.stdio;
import std.range;
import std.path;
import std.algorithm;
import std.json;

import tokens;
import parser;
import dprinter;
import scanner;
import ast;
import namer;
import typenames;

void main(string[] args)
{
Module[] asts;

auto srcdir = args[1];
auto destdir = args[2];

auto settings = parseJSON(readText("magicport.json")).object;
auto src = settings["src"].array.map!"a.str"().array;
auto mapping = settings["mapping"].array.loadMapping();
foreach(t; settings["basicTypes"].array.map!"a.str")
basicTypes[t] = false;
foreach(t; settings["structTypes"].array.map!"a.str")
structTypes[t] = false;
foreach(t; settings["rootclasses"].array.map!"a.str")
rootClasses[t] = false;
foreach(t; settings["overriddenfuncs"].array.map!(j => j.array.map!("a.str").array))
overridenFuncs ~= t;
foreach(t; settings["nonfinalclasses"].array.map!"a.str")
nonFinalClasses ~= t;

Token[][string] toks;
foreach(xfn; src)
{
auto fn = buildPath(srcdir, xfn);
writeln("loading -- ", fn);
assert(fn.exists(), fn ~ " does not exist");
auto pp = cast(string)read(fn);
pp = pp.replace("\"v\"\n#include \"verstr.h\"\n ;", "__IMPORT__;");
auto tx = Lexer(pp, fn).array;
toks[fn] = tx;
foreach(i, t; tx)
{
string[] matchSeq(string[] strs...)
{
string[] res;
foreach(j, s; strs)
{
if (i + j > tx.length)
return null;
if (s == null)
{
res ~= tx[i + j].text;
continue;
}
if (s != tx[i + j].text)
return null;
}
return res;
}
if (auto v = matchSeq("class", null, ";"))
classTypes[v[0]] = false;
if (auto v = matchSeq("class", null, "{"))
classTypes[v[0]] = false;
if (auto v = matchSeq("class", null, ":"))
classTypes[v[0]] = false;
if (auto v = matchSeq("struct", null, ";"))
structTypes[v[0]] = false;
if (auto v = matchSeq("struct", null, "{"))
structTypes[v[0]] = false;
if (auto v = matchSeq("union", null, "{"))
structTypes[v[0]] = false;
if (auto v = matchSeq("typedef", "Array", "<", "class", null, "*", ">", null, ";"))
{
structTypes[v[1]] = false;
}
if (auto v = matchSeq("typedef", "Array", "<", "struct", null, "*", ">", null, ";"))
{
structTypes[v[1]] = false;
}
}
}

auto scan = new Scanner();
foreach(fn, tx; toks)
{
asts ~= parse(tx, fn);
asts[$-1].visit(scan);
}

foreach(t, used; basicTypes)
if (!used)
writeln("type ", t, " not referenced");
foreach(t, used; structTypes)
if (!used)
writeln("type ", t, " not referenced");
foreach(t, used; classTypes)
if (!used)
writeln("type ", t, " not referenced");

writeln("collapsing ast...");
auto superast = collapse(asts, scan);
auto map = buildMap(superast);
auto longmap = buildLongMap(superast);

bool failed;
try { mkdir(destdir); } catch {}
foreach(m; mapping)
{
auto dir = buildPath(destdir, m.p);
if (m.p.length)
try { mkdir(dir); } catch {}

auto fn = buildPath(dir, m.m).setExtension(".d");
auto f = File(fn, "wb");
writeln("writing -- ", fn);

f.writeln(
"// Compiler implementation of the D programming language
// Copyright (c) 1999-2015 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt");

f.writeln();
if (m.p.length)
f.writefln("module ddmd.%s.%s;", m.p, m.m);
else
f.writefln("module ddmd.%s;", m.m);
f.writeln();

void importList(R)(R imports)
{
bool found;
foreach(i; imports)
{
if (!found)
f.writef("import %s", i);
else
f.writef(", %s", i);
found = true;
}
if (found)
f.writeln(";");
}
importList(m.imports.filter!(i => i.startsWith("core.")));
importList(m.imports.filter!(i => i.startsWith("root.")));
importList(m.imports.filter!(i => !i.startsWith("core.", "root.")));
if (m.imports.length)
f.writeln();

foreach(e; m.extra)
{
f.writeln(e);
}
if (m.extra.length)
f.writeln();

auto printer = new DPrinter((string s) { f.write(s); }, scan);
Declaration prev;
foreach(d; m.members)
{
if (auto p = d in map)
{
if (!p.d)
{
writeln(d, " needs mangled name");
foreach(id, x; longmap)
{
if (id.startsWith(d))
{
writeln(" - ", id);
}
}
}
else
{
if (prev)
{
if (cast(TypedefDeclaration)prev && cast(TypedefDeclaration)p.d)
{
}
else if (cast(VarDeclaration)prev && cast(VarDeclaration)p.d)
{
}
else
printer.println("");
}
prev = p.d;
printer.visitX(p.d);
p.count++;
}
}
else if (auto p = d in longmap)
{
assert(p.d);
map[p.d.getName].count++;
if (prev)
{
if (cast(TypedefDeclaration)prev && cast(TypedefDeclaration)p.d)
{
}
else if (cast(VarDeclaration)prev && cast(VarDeclaration)p.d)
{
}
else
printer.println("");
}
prev = p.d;
printer.visitX(p.d);
p.count++;
}
else
{
writeln("Not found: ", d);
failed = true;
}
}
}
foreach(id, d; map)
{
if (d.count == 0)
{
assert(d.d, id);
writeln("unreferenced: ", d.d.getName);
failed = true;
}
if (d.count > 1 && d.d)
{
writeln("duplicate: ", d.d.getName);
}
}
foreach(id, d; longmap)
{
if (d.count > 1)
{
assert(d.d);
writeln("duplicate: ", d.d.getName);
}
}
if (failed)
assert(0);
}

struct D
{
Declaration d;
int count;
}

D[string] buildMap(Module m)
{
D[string] map;
foreach(d; m.decls)
{
auto s = d.getName();
if (s in map)
map[s] = D(null, 0);
else
map[s] = D(d, 0);
}
return map;
}

D[string] buildLongMap(Module m)
{
D[string] map;
foreach(d; m.decls)
{
auto s = d.getLongName();
assert(s !in map, s);
map[s] = D(d, 0);
}
return map;
}

struct M
{
string m;
string p;
string[] imports;
string[] members;
string[] extra;
}

auto loadMapping(JSONValue[] modules)
{
M[] r;
foreach(j; modules)
{
auto imports = j.object["imports"].array.map!"a.str"().array;
sort(imports);
foreach(ref i; imports)
if (!i.startsWith("core"))
i = "ddmd." ~ i;
string[] extra;
if ("extra" in j.object)
extra = j.object["extra"].array.map!"a.str"().array;
r ~= M(
j.object["module"].str,
j.object["package"].str,
imports,
j.object["members"].array.map!"a.str"().array,
extra
);
}
return r;
}

0 comments on commit 7e9398a

Please sign in to comment.