Skip to content

Commit 0c91dab

Browse files
committed
Add frontend module and example
1 parent a323c4e commit 0c91dab

3 files changed

Lines changed: 180 additions & 0 deletions

File tree

dub.sdl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ subPackage {
100100
"src/dmd/escape.d" \
101101
"src/dmd/expression.d" \
102102
"src/dmd/expressionsem.d" \
103+
"src/dmd/frontend.d" \
103104
"src/dmd/func.d" \
104105
"src/dmd/gluelayer.d" \
105106
"src/dmd/hdrgen.d" \

src/ddmd/frontend.d

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* Compiler implementation of the
3+
* $(LINK2 http://www.dlang.org, D programming language).
4+
*
5+
* This module contains high-level interfaces for interacting
6+
with DMD as a library.
7+
*
8+
* Copyright: Copyright (c) 1999-2017 by The D Language Foundation, All Rights Reserved
9+
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
10+
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
11+
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/ddmd/id.d, _id.d)
12+
*/
13+
module ddmd.frontend;
14+
15+
// Online documentation: https://dlang.org/phobos/ddmd_frontend.html
16+
17+
/**
18+
Initializes the DMD compiler
19+
*/
20+
void initDMD()
21+
{
22+
import ddmd.dmodule : Module;
23+
import ddmd.globals : global;
24+
import ddmd.id : Id;
25+
import ddmd.mtype : Type;
26+
import ddmd.target : Target;
27+
import ddmd.expression : Expression;
28+
import ddmd.objc : Objc;
29+
import ddmd.builtin : builtin_init;
30+
31+
global._init;
32+
33+
version(linux)
34+
global.params.isLinux = 1;
35+
else version(OSX)
36+
global.params.isOSX = 1;
37+
else version(FreeBSD)
38+
global.params.isFreeBSD = 1;
39+
else version(Windows)
40+
global.params.isWindows = 1;
41+
else version(Solaris)
42+
global.params.isSolaris = 1;
43+
else version(OpenBSD)
44+
global.params.isOpenBSD = 1;
45+
else
46+
static assert(0, "OS not supported yet.");
47+
48+
Type._init();
49+
Id.initialize();
50+
Module._init();
51+
Target._init();
52+
Expression._init();
53+
Objc._init();
54+
builtin_init();
55+
}
56+

test/dub_package/frontend.d

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#!/usr/bin/env dub
2+
/+dub.sdl:
3+
dependency "dmd" path="../.."
4+
+/
5+
import std.stdio;
6+
7+
// add import paths
8+
void addImports(T)(T path)
9+
{
10+
import dmd.globals : global;
11+
import dmd.arraytypes : Strings;
12+
13+
stderr.writefln("addImport: %s", path);
14+
15+
Strings* res = new Strings();
16+
foreach (p; path)
17+
{
18+
import std.string : toStringz;
19+
Strings* a = new Strings();
20+
a.push(p.toStringz);
21+
res.append(a);
22+
}
23+
global.path = res;
24+
}
25+
26+
// finds a dmd.conf and parses it for import paths
27+
auto findImportPaths()
28+
{
29+
import std.string : fromStringz, toStringz;
30+
import std.path : buildPath, buildNormalizedPath, dirName;
31+
import std.process : env = environment;
32+
import dmd.dinifile : findConfFile;
33+
34+
auto dmdFilePath = env.get("DMD");
35+
auto iniFile = findConfFile(dmdFilePath.toStringz, "dmd.conf");
36+
37+
import std.algorithm, std.range, std.regex;
38+
return File(iniFile.fromStringz, "r")
39+
.byLineCopy
40+
.dropOne
41+
.front
42+
.matchAll("-I[^ ]+".regex)
43+
.joiner
44+
.map!(a => a.drop(2).replace("%@P%", dmdFilePath.dirName))
45+
.map!buildNormalizedPath;
46+
}
47+
48+
// test frontend
49+
void main()
50+
{
51+
import dmd.astcodegen : ASTCodegen;
52+
import dmd.dmodule : Module;
53+
import dmd.globals : global, Loc;
54+
import dmd.frontend : initDMD;
55+
import dmd.parse : Parser;
56+
import dmd.statement : Identifier;
57+
import dmd.tokens : TOKeof;
58+
import dmd.id : Id;
59+
60+
initDMD;
61+
findImportPaths.addImports;
62+
63+
auto parse(Module m, string code)
64+
{
65+
scope p = new Parser!ASTCodegen(m, code, false);
66+
p.nextToken; // skip the initial token
67+
auto members = p.parseModule;
68+
assert(!p.errors, "Parsing error occurred.");
69+
return members;
70+
}
71+
72+
Identifier id = Identifier.idPool("test");
73+
auto m = new Module("test.d", id, 0, 0);
74+
m.members = parse(m, q{
75+
void foo()
76+
{
77+
foreach (i; 0..10) {}
78+
}
79+
});
80+
81+
void semantic()
82+
{
83+
import dmd.dsymbolsem : dsymbolSemantic;
84+
import dmd.semantic : semantic2, semantic3;
85+
86+
m.importedFrom = m;
87+
m.importAll(null);
88+
m.dsymbolSemantic(null);
89+
m.semantic2(null);
90+
m.semantic3(null);
91+
}
92+
semantic();
93+
94+
auto prettyPrint()
95+
{
96+
import dmd.root.outbuffer: OutBuffer;
97+
import dmd.hdrgen : HdrGenState, PrettyPrintVisitor;
98+
99+
OutBuffer buf = { doindent: 1 };
100+
HdrGenState hgs = { fullDump: 1 };
101+
scope PrettyPrintVisitor ppv = new PrettyPrintVisitor(&buf, &hgs);
102+
m.accept(ppv);
103+
return buf;
104+
}
105+
auto buf = prettyPrint();
106+
107+
auto expected =q{import object;
108+
void foo()
109+
{
110+
{
111+
int __key3 = 0;
112+
int __limit4 = 10;
113+
for (; __key3 < __limit4; __key3 += 1)
114+
{
115+
int i = __key3;
116+
}
117+
}
118+
}
119+
};
120+
import std.string : replace, fromStringz;
121+
auto generated = buf.extractData.fromStringz.replace("\t", " ");
122+
assert(expected == generated, generated);
123+
}

0 commit comments

Comments
 (0)