-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathcompiler.grace
128 lines (110 loc) · 4.15 KB
/
compiler.grace
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
dialect "standard"
import "ast" as ast
import "buildinfo" as buildinfo
import "genjs" as genjs
import "identifierresolution" as identifierresolution
import "errormessages" as errormessages
import "io" as io
import "lexer" as lexer
import "parser" as parser
import "sys" as sys
import "unicode" as unicode
import "util" as util
import "xmodule" as xmodule
import "mirror" as mirror
if (mirror.initialModuleName == "compiler") then { compileInputFile }
method compileInputFile {
util.parseargs(buildinfo)
util.log_verbose "starting compilation"
try {
var tokens := lexer.lexfile(util.infile)
if (util.target == "lex") then {
// Print the lexed tokens and quit.
for (tokens) do { v ->
def val = if ("\n" == v.value) then { "\\n" } else { v.value }
if (util.verbosity > 30) then {
util.outprint "{v.kind}: {val} [pos: {v.line}:{v.column} size: {v.size} indent: {v.indent}]"
} else {
util.outprint "{v.kind}: {val}"
}
}
util.outfile.close
sys.exit(0)
}
var moduleObject := parser.parse(tokens)
tokens := false // release the memory
var values := moduleObject.value
if (util.target == "parse") then {
// Parse mode pretty-prints the parse tree and quits.
// util.log 60 verbose "target = parse, outfile = {util.outfile}."
util.outprint(moduleObject.pretty(0))
// util.log 60 verbose "done writing {util.outfile}."
util.outfile.close
sys.exit(0)
}
if (util.target == "grace") then {
for (values) do { v ->
util.outprint(v.toGrace(0))
}
util.outfile.close
sys.exit(0)
}
if (util.target == "imports") then {
def imps = set.empty
def vis = object {
inherit ast.baseVisitor
method visitImport(o) -> Boolean {
imps.add(o.path)
false
}
}
moduleObject.accept(vis)
list.withAll(imps).sort.do { im ->
util.outprint(im)
}
util.outfile.close
sys.exit(0)
}
moduleObject := identifierresolution.resolve(moduleObject)
// Perform the actual compilation
match(util.target)
case { == "js" ->
genjs.compile(moduleObject, util.outfile, util.buildtype, util.gracelibPath)
} else {
io.error.write("minigrace: no such target '" ++ util.target ++ "'\n")
sys.exit(1)
}
} catch { se:errormessages.SyntaxError ->
util.generalError("Syntax error: {se.message}", se.data.line, se.data.column, se.data.arrow, se.data.sugg)
} catch { se:errormessages.ReuseError ->
util.generalError("Reuse error: {se.message}", se.data.line, se.data.column, se.data.arrow, se.data.sugg)
} catch { se:errormessages.CompilationError ->
util.generalError("Compilation error: {se.message}", se.data.line, se.data.column, se.data.arrow, se.data.sugg)
}
}
////////////////////////////////////////////////////
//
// methods used when writing unit tests
//
////////////////////////////////////////////////////
method lexLines(input) {
// input is a Collection of Strings, each representing a line
// answers a linked list of tokens
util.lines.clear
util.lines.addAll(input)
xmodule.externalModules.clear
lexer.lexLines (input)
}
method lexString(inputString) { lexLines(inputString.split "\n") }
method parseLines(input) {
// input is a Collection of Strings, each representing a line
// answers the moduleNode at the top of the parse tree
parser.parse (lexLines (input))
}
method parseString(inputString) { parseLines(inputString.split "\n") }
method astFromLines(input) {
// input is a Collection of Strings, each representing a line
// answers the moduleNode at the top of the AST
identifierresolution.resolve (parseLines(input))
}
method astFromString(inputString) { astFromLines(inputString.split "\n") }