Skip to content

Commit 78a97fb

Browse files
committed
Add frontend module and example
1 parent da4ea18 commit 78a97fb

3 files changed

Lines changed: 164 additions & 0 deletions

File tree

dub.sdl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ subPackage {
9999
"src/ddmd/escape.d" \
100100
"src/ddmd/expression.d" \
101101
"src/ddmd/expressionsem.d" \
102+
"src/ddmd/frontend.d" \
102103
"src/ddmd/func.d" \
103104
"src/ddmd/hdrgen.d" \
104105
"src/ddmd/id.d" \

src/ddmd/frontend.d

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Compiler implementation of the
3+
* $(LINK2 http://www.dlang.org, D programming language).
4+
*
5+
* This module contains the high-level interfaces for interacting with DMD
6+
* 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.globals : global;
23+
import ddmd.dmodule : Module;
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+
Type._init();
32+
Id.initialize();
33+
Module._init();
34+
Target._init();
35+
Expression._init();
36+
Objc._init();
37+
builtin_init();
38+
}
39+

test/dub_package/frontend.d

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

0 commit comments

Comments
 (0)