Skip to content

Commit 8602a88

Browse files
committed
start with writing some language definitions
Also sketch out how the pass definition macros could look like.
1 parent 35c1eae commit 8602a88

File tree

1 file changed

+184
-0
lines changed

1 file changed

+184
-0
lines changed

passes/passes.nim

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
## The home of all intermediate languages and passes, representing the core of
2+
## the compiler.
3+
4+
import
5+
nanopass/nanopass,
6+
experimental/sexp_parse
7+
8+
defineLanguage Lsrc:
9+
n(int)
10+
fl(float)
11+
str(string)
12+
# TODO: only allow a type being used as a terminal once
13+
x(string) # identifier
14+
15+
rec_field(rf) ::= Field(x, e)
16+
field_decl(f) ::= Field(x, t)
17+
18+
pattern(p) ::= As(x, t)
19+
mrule(mr) ::= Rule(p, e)
20+
expr(e) ::= n | fl | x |
21+
ArrayCons(...e) |
22+
TupleCons(...e) |
23+
RecordCons(rf0, ...rf1) |
24+
Seq(t, ...e) |
25+
Seq(str) |
26+
Call(e, ...e) |
27+
FieldAccess(e, n) |
28+
FieldAccess(e, x) |
29+
At(e0, e1) |
30+
As(e, t) |
31+
And(e0, e1) |
32+
Or(e0, e1) |
33+
If(e0, e1) |
34+
If(e0, e1, e2) |
35+
While(e0, e1) |
36+
Return(e) |
37+
Unreachable() |
38+
Exprs(...e0, e1) |
39+
Asgn(e0, e1) |
40+
Decl(x, e) |
41+
Match(e, mr0, ...mr1)
42+
typ(t) ::= x | VoidTy() | UnitTy() | BoolTy() | IntTy() | FloatTy() |
43+
ArrayTy(n, t) |
44+
SeqTy(t) |
45+
TupleTy(t0, ...t1) |
46+
RecordTy(f0, ...f1) |
47+
UnionTy(t0, ...t1) |
48+
ProcTy(t0, ...t1)
49+
50+
param_decl(pd) ::= ParamDecl(x, t)
51+
params(pa) ::= Params(...pd)
52+
decl(d) ::= ProcDecl(x, t, pa, e) | TypeDecl(x, t)
53+
module(m) ::= Module(...d)
54+
55+
defineLanguage L1, Lsrc:
56+
## Language without And and Or.
57+
expr(e) ::= -And(e, e) | -Or(e, e)
58+
59+
defineLanguage L2, L1:
60+
## Language without single-branch `If`.
61+
expr(e) ::= -If(e, e)
62+
63+
defineLanguage L3, L2:
64+
## Language that replaces Decl with Let.
65+
expr(e) ::= -Decl(x, e) | +Let(x, e, e)
66+
67+
defineLanguage L4, L3:
68+
## Removes the `Match` form.
69+
pattern(p) ::= -As(x, t)
70+
mrule(mr) ::= -Rule(p, e)
71+
expr(e) ::= -Match(e, mr, ...mr)
72+
73+
defineLanguage L5, L4:
74+
## Removes the While form and adds the Loop and Break form.
75+
expr(e) ::= -While(e, e) | +Loop(e) | +Break(n)
76+
77+
defineLanguage L6, L5:
78+
## Requires explicit copies.
79+
root(ro) ::= +lv | +e
80+
lvalue(lv) ::=
81+
+At(ro, e) |
82+
+FieldAccess(ro, n)
83+
expr(e) ::=
84+
-At(e, e) |
85+
-FieldAccess(e, n) |
86+
+Copy(lv)
87+
88+
proc parse(s: var SexpParser): Lsrc {.inpass.} =
89+
## Parses the source language from an S-expression stream.
90+
proc ident(s: var SexpParser): dst.x {.transform.} =
91+
s.space()
92+
s.expect(tkIdent)
93+
build x(s.eatString())
94+
95+
proc call(s: var SexpParser): dst.e {.transform.} =
96+
let callee = expr(s)
97+
var x = @[expr(s)]
98+
s.space()
99+
while s.currToken != tkParensRi:
100+
expr(s)
101+
s.space()
102+
103+
s.eat(tkParensRi)
104+
build Call(callee, x)
105+
106+
proc expr(s: var SexpParser): dst.e {.transform.} =
107+
s.space()
108+
case s.currToken
109+
of tkParsensLe:
110+
let k = s.getTok()
111+
if k == tkIdent:
112+
case s.currString
113+
of "if":
114+
build If(expr(s), expr(s), expr(s))
115+
of "while":
116+
build While(expr(s), expr(s))
117+
of "decl":
118+
build Decl(ident(s), expr(s))
119+
of "and":
120+
build And(expr(s), expr(s))
121+
of "or":
122+
build Or(expr(s), expr(s))
123+
else:
124+
# TODO: implement the remaining keywords
125+
call(s)
126+
else:
127+
call(s)
128+
129+
of tkString:
130+
build str(s.eatString())
131+
of tkIdent:
132+
build x(s.eatString())
133+
of tkInt:
134+
build n(parseInt(s.eatString()))
135+
of tkFloat:
136+
build fl(parseFloat(s.eatString()))
137+
else:
138+
syntaxError(s)
139+
140+
proc typ(s: var SexpParser): dst.t {.transform.} =
141+
s.space()
142+
# TODO: implement
143+
144+
proc params(s: var SexprParser): dst.pa {.transform.} =
145+
s.space()
146+
# TODO: implement
147+
148+
proc top(s: var SexpParser): dst.d {.transform.} =
149+
s.eat(tkParensLe)
150+
s.expect(tkIdent)
151+
case s.currToken
152+
of "proc":
153+
build ProcDecl(ident(s), typ(s), params(s), expr(s))
154+
of "type":
155+
build TypeDecl(ident(s), typ(s))
156+
else:
157+
syntaxError()
158+
159+
proc removeAndOr(_: Lsrc): L1 {.pass.} =
160+
proc expr(_: src.e): dst.e {.transform.} =
161+
And([a], [b]) -> build If(a, b, x("false"))
162+
Or([a], [b]) -> build If(a, x("true"), b)
163+
164+
proc removeSingleIf(_: L1): L2 {.pass.} =
165+
proc expr(_: src.e): dst.e {.transform.} =
166+
If([a], [b]) -> build If(a, b, TupleCons())
167+
168+
proc declToLet(_: L2): L3 {.pass.} =
169+
proc expr(_: src.e): dst.e {.transform.} =
170+
Decl(`x`, `e`) -> build Let(x, e, TupleCons())
171+
Exprs(`e0`, [last]):
172+
var r = last
173+
var got: seq[dst.e]
174+
for i in countdown(e0.high, 0):
175+
match e0[i]:
176+
Decl(`x`, `e`):
177+
r =
178+
if got.len == 0: build Let(x, e, r)
179+
else: build Let(x, e, Exprs(got, r))
180+
else:
181+
got.insert expr(e0[i])
182+
183+
if got.len == 0: build Exprs(got, r)
184+
else: r

0 commit comments

Comments
 (0)