@@ -8,6 +8,8 @@ sealed trait Grammar[AT:Type,T:Type,ET:Type] {
8
8
val tType = implicitly[Type [T ]]
9
9
val eType = implicitly[Type [ET ]]
10
10
val aType = implicitly[Type [AT ]]
11
+ type t = T
12
+ type at = AT
11
13
}
12
14
13
15
private case class Terminal [T : Type : Liftable ](val v : T ) extends Grammar [Unit ,T ,T ] {
@@ -17,7 +19,7 @@ private case class ArgumentTerminal[T:Type]() extends Grammar[T,T,T]
17
19
private case class ArgToVal [T : Type ]() extends Grammar [T ,T ,Any ]
18
20
private case class ReadPos () extends Grammar [Unit ,Int ,Any ]
19
21
private case class Call [AT1 : Type ,AT2 : Type ,T : Type ,ET : Type ](val arg : Grammar [AT1 ,AT2 ,ET ], val fn : Grammar [AT2 ,T ,ET ]) extends Grammar [AT1 ,T ,ET ]
20
- private case class Sequence [LAT : Type ,RAT : Type , LT : Type ,RT : Type ,ET : Type ](val left : Grammar [LAT ,LT ,ET ], val right : Grammar [RAT ,RT ,ET ]) extends Grammar [( LAT , RAT ) ,(LT ,RT ),ET ]
22
+ private case class Sequence [AT : Type ,LT : Type ,RT : Type ,ET : Type ](val left : Grammar [AT ,LT ,ET ], val right : Grammar [AT ,RT ,ET ]) extends Grammar [AT ,(LT ,RT ),ET ]
21
23
private case class Check [AT : Type ,ET : Type ](val g : Grammar [AT ,Any ,ET ]) extends Grammar [AT ,Unit ,ET ]
22
24
private case class Disjunction [AT : Type ,T : Type ,ET : Type ](val left : Grammar [AT ,T ,ET ], val right : Grammar [AT ,T ,ET ]) extends Grammar [AT ,T ,ET ]
23
25
private case class Condition [AT : Type ,T : Type ,ET : Type ](val g : Grammar [AT ,T ,ET ], val cond : Expr [T ] => Expr [Boolean ]) extends Grammar [AT ,T ,ET ]
@@ -27,6 +29,34 @@ private class Recursion[AT:Type,T:Type,ET:Type](_g : =>Grammar[AT,T,ET]) extends
27
29
lazy val g = _g
28
30
}
29
31
32
+ sealed trait BlockIR [In : Type ,Out : Type ] {
33
+ val tIn = implicitly[Type [In ]]
34
+ val tOut = implicitly[Type [Out ]]
35
+ }
36
+
37
+ trait BlockContext [In : Type ,- Out : Type ] {
38
+ def fail : Expr [Unit ]
39
+ def arg : Expr [In ]
40
+ def succeed (v : Expr [Out ]) : Expr [Unit ]
41
+ }
42
+
43
+ case class BranchIR [In : Type ,Out : Type ](val condition : BlockContext [In ,Out ] => Expr [Boolean ], val yes : BlockIR [In ,Out ], val no : BlockIR [In ,Out ]) extends BlockIR [In ,Out ]
44
+ case class PreserveArgIR [In : Type ,Out : Type ](val g : BlockIR [In ,Out ]) extends BlockIR [In ,(In ,Out )] // produces a tuple of original arg and g's result
45
+ case class SeqIR [In : Type ,Mid : Type ,Out : Type ](val from : BlockIR [In ,Mid ], val to : BlockIR [Mid ,Out ]) extends BlockIR [In ,Out ] // makes result of from arg of to
46
+ case class CallIR [In : Type ,Out : Type ](val key : AnyRef ) extends BlockIR [In ,Out ]
47
+ case class RecoverIR [In : Type ,Out : Type ](val first : BlockIR [In ,Out ], val second : BlockIR [In ,Out ]) extends BlockIR [In ,Out ]
48
+ case class SimpleIR [In : Type ,Out : Type ](val fn : BlockContext [In ,Out ] => Expr [Unit ]) extends BlockIR [In ,Out ]
49
+
50
+ sealed trait BlockIR2 [In : Type ] {
51
+ val tIn = implicitly[Type [In ]]
52
+ type in = In
53
+ }
54
+
55
+ case class BranchIR2 [In : Type ](val condition : BlockContext [In ,Any ] => Expr [Boolean ], val yes : BlockIR2 [In ], val no : BlockIR2 [In ]) extends BlockIR2 [In ]
56
+ case class BeforeIR2 [In : Type ,In2 : Type ](val map : BlockContext [In ,In2 ] => Expr [Unit ], val next : BlockIR2 [In2 ]) extends BlockIR2 [In ]
57
+ case class JumpIR2 [In : Type ](val key : AnyRef , val ret : AnyRef ) extends BlockIR2 [In ]
58
+ case class ReturnIR2 [In : Type ]() extends BlockIR2 [In ]
59
+
30
60
trait SequenceContext [ET : Type ] {
31
61
type Mark
32
62
def mark : Expr [Mark ]
@@ -57,68 +87,121 @@ trait MakeSequenceContext[Seq[_]] {
57
87
def makeCtx [ET : Type ,Result : Type ](fn : SequenceContext [ET ] => Expr [Result ]) : Expr [Seq [ET ] => Result ]
58
88
}
59
89
60
- case class BlockCompiler [ET : Type ,Result ](seqCtx : SequenceContext [ET ], flowCtx : ControlFlowContext [Option [Result ]],
61
- recursions : Set [Grammar [_,_,_]], recMap : Map [AnyRef ,flowCtx.Label ]) {
62
- def handleRec [AT : Type ,T : Type ](g : Grammar [AT ,T ,ET ], arg : Expr [AT ], yes : Expr [T ]=> Expr [Unit ], no : Expr [Unit ]) : Expr [Unit ] = {
63
- if recursions.contains(g) then {
64
- val recLabel = flowCtx.block(recLabel => {
65
- this .copy(recMap= recMap.+ ((g, recLabel))).computeValue(g, flowCtx.callReg[AT ], flowCtx.ret(_), flowCtx.end(' {None }))
66
- })
67
- val retLabel = flowCtx.block(yes(flowCtx.retReg[T ]))
68
- flowCtx.call(recLabel, retLabel, arg)
69
- } else {
70
- computeValue(g, arg, yes, no)
71
- }
72
- }
73
- def computeValue [AT : Type ,T : Type ](g : Grammar [AT ,T ,ET ], arg : Expr [AT ], yes : Expr [T ]=> Expr [Unit ], no : Expr [Unit ]) : Expr [Unit ] = g match {
74
- case t@ Terminal (v) => {
75
- implicit val _ = t.liftable
76
- ' {
77
- if $ {seqCtx.isEOF} then $no else {
78
- val curr = $ {seqCtx.peek}
79
- if curr == $ {v.toExpr}
80
- then {
81
- $ {seqCtx.next}
82
- $ {yes(' {curr})}
83
- } else $no
84
- }
85
- }
86
- }
87
- case Disjunction (l,r) => {
88
- val lv = computeValue(l, arg, yes, no)
89
- val rv = computeValue(r, arg, yes, no)
90
- ' { // this is eager disjunction, TODO "correct" backtracking disjunction option
91
- if $ {speculateReachable(l, arg)}
92
- then $ {lv}
93
- else $ {rv}
94
- }
95
- }
96
- case r : Recursion [AT ,T ,ET ] => {
97
- val retLabel = flowCtx.block(yes(flowCtx.retReg[T ]))
98
- flowCtx.call(recMap.get(r.g).get, retLabel, arg)
99
- }
100
- case _ => ???
101
- }
90
+ case class BlockCompiler [ET : Type ,Result ](seqCtx : SequenceContext [ET ]) {
102
91
def speculateReachable [AT : Type ,T : Type ](g : Grammar [AT ,T ,ET ], arg : Expr [AT ]) : Expr [Boolean ] = g match {
103
92
case t@ Terminal (v) => {
104
93
implicit val _ = t.liftable
105
94
' { ! $ {seqCtx.isEOF} && $ {seqCtx.peek} == $ {v.toExpr}}
106
95
}
107
96
case Disjunction (l,r) => ' { $ {speculateReachable(l, arg)} || $ {speculateReachable(r, arg)} }
97
+ case Sequence (l,r) => {
98
+ implicit val _ = l.tType
99
+ speculateReachable(l, arg)
100
+ }
101
+ case ArgumentTerminal () => ' { ! $ {seqCtx.isEOF} && $ {seqCtx.peek} == $arg }
102
+ case Call (l,_) => {
103
+ implicit val _ = l.tType
104
+ speculateReachable(l, arg)
105
+ }
106
+ case Condition (gg,cond) => speculateReachable(gg, arg)
107
+ case MapArg (to,fn) => {
108
+ implicit val _ = to.aType
109
+ speculateReachable(to, fn(arg))
110
+ }
111
+ case MapVal (gg,_) => {
112
+ implicit val _ = gg.tType
113
+ speculateReachable(gg, arg)
114
+ }
115
+ case Check (gg) => speculateReachable(gg, arg)
108
116
case r : Recursion [AT ,T ,ET ] => speculateReachable(r.g, arg) // speculate past calls to avoid redundantly calling parser we know will fail
109
117
// note: this only works if the parser terminates :) ... maybe catch obvious
110
118
// non-termination later
111
119
case _ => ???
112
120
}
121
+ def computeBlocks [AT : Type ,T : Type ](g : Grammar [AT ,T ,ET ]) : Seq [(AnyRef , BlockIR [_,_])] = g match {
122
+ case t@ Terminal (v) => Seq (
123
+ (t, SimpleIR [AT ,T ](ctx => {
124
+ implicit val _ = t.liftable
125
+ ' {
126
+ if ! $ {seqCtx.isEOF} && $ {seqCtx.peek} == $ {v.toExpr}
127
+ then $ {ctx.succeed(v.toExpr)}
128
+ else $ {ctx.fail}
129
+ }
130
+ }))
131
+ )
132
+ case Disjunction (l, r) => Seq (
133
+ (g, BranchIR [AT ,T ](
134
+ condition= ctx => speculateReachable(l, ctx.arg),
135
+ yes= CallIR [AT ,T ](l),
136
+ no= CallIR [AT ,T ](r),
137
+ ))
138
+ ) ++ computeBlocks(l) ++ computeBlocks(r)
139
+ case Sequence (l, r) => {
140
+ implicit val _ = l.tType
141
+ implicit val _1 = r.tType
142
+ type LT = l.t
143
+ type RT = r.t
144
+ Seq (
145
+ (g, SeqIR (
146
+ PreserveArgIR (CallIR [AT ,LT ](l)),
147
+ SeqIR (
148
+ PreserveArgIR (SeqIR (
149
+ SimpleIR [(AT ,LT ),AT ](ctx => ctx.succeed(' {$ {ctx.arg} match { case (in,_) => in }})),
150
+ CallIR [AT ,RT ](r)
151
+ )),
152
+ SimpleIR [((AT ,LT ),RT ),(LT ,RT )](ctx => ctx.succeed(' {$ {ctx.arg} match { case ((_,res1),res2) => (res1,res2) }}))
153
+ )
154
+ )),
155
+ ) ++ computeBlocks(l) ++ computeBlocks(r)
156
+ }
157
+ case Call (arg, fn) => {
158
+ implicit val _ = arg.tType
159
+ type AAT = arg.t
160
+ Seq (
161
+ (g, SeqIR (CallIR [AT ,AAT ](arg), CallIR [AAT ,T ](fn)))
162
+ ) ++ computeBlocks(arg) ++ computeBlocks(fn)
163
+ }
164
+ case ArgumentTerminal () => Seq (
165
+ (g, SimpleIR (ctx => ' {
166
+ if ! $ {seqCtx.isEOF} && $ {seqCtx.peek} == $ {ctx.arg}
167
+ then $ {ctx.succeed(ctx.arg)}
168
+ else $ {ctx.fail}
169
+ }))
170
+ )
171
+ case Condition (gg, cond) => Seq (
172
+ (g, SeqIR (CallIR [AT ,T ](gg), SimpleIR [T ,T ](ctx => ' {
173
+ if $ {cond(ctx.arg)}
174
+ then $ {ctx.succeed(ctx.arg)}
175
+ else $ {ctx.fail}
176
+ })))
177
+ ) ++ computeBlocks(gg)
178
+ case MapArg (to,fn) => {
179
+ implicit val _ = to.aType
180
+ type TAT = to.at
181
+ Seq (
182
+ (g, SeqIR (SimpleIR [AT ,TAT ](ctx => ctx.succeed(fn(ctx.arg))), CallIR [TAT ,T ](to)))
183
+ ) ++ computeBlocks(to)
184
+ }
185
+ case MapVal (from,fn) => {
186
+ implicit val _ = from.tType
187
+ type FT = from.t
188
+ Seq (
189
+ (g, SeqIR (CallIR [AT ,FT ](from), SimpleIR [FT ,T ](ctx => ctx.succeed(fn(ctx.arg)))))
190
+ ) ++ computeBlocks(from)
191
+ }
192
+ case r : Recursion [AT ,T ,ET ] => Seq ((g, CallIR [AT ,T ](r.g)))
193
+ case _ => ???
194
+ }
113
195
}
114
196
115
197
object PolyParse {
116
198
117
199
private def maybeRecurse [AT : Type ,T : Type ,ET : Type ](g : => Grammar [AT ,T ,ET ]) : Grammar [AT ,T ,ET ] = if g == null then new Recursion (g) else g
118
200
119
- implicit class MaybeRecursion [AT1 : Type ,T : Type ,ET : Type ](g : => Grammar [AT1 ,T ,ET ]) {
120
- def <|> (other : => Grammar [AT1 ,T ,ET ]) : Grammar [AT1 ,T ,ET ] = Disjunction (maybeRecurse(g), maybeRecurse(other))
121
- def ++ [AT2 : Type ,Other : Type ](other : => Grammar [AT2 ,Other ,ET ]) : Grammar [(AT1 ,AT2 ),(T ,Other ),ET ] = Sequence (maybeRecurse(g), maybeRecurse(other))
201
+
202
+ implicit class MaybeRecursion [AT : Type ,T : Type ,ET : Type ](g : => Grammar [AT ,T ,ET ]) {
203
+ def <|> (other : => Grammar [AT ,T ,ET ]) : Grammar [AT ,T ,ET ] = Disjunction (maybeRecurse(g), maybeRecurse(other))
204
+ def ++ [Other : Type ](other : => Grammar [AT ,Other ,ET ]) : Grammar [AT ,(T ,Other ),ET ] = Sequence (maybeRecurse(g), maybeRecurse(other))
122
205
// def map[T2:Type](fn : Expr[T] => Expr[T2]) : Grammar[T2,ET] = Mapping(maybeRecurse(g), fn)
123
206
// def ??(cond : Expr[T] => Expr[Boolean]) : Grammar[T,ET] = Condition(maybeRecurse(g), cond)
124
207
}
@@ -141,6 +224,7 @@ object PolyParse {
141
224
}}
142
225
}
143
226
227
+
144
228
def makeControlFlowContext [Result : Type ](fn : ControlFlowContext [Result ] => Unit ) : Expr [Result ] = ' {
145
229
import collection .mutable .ArrayStack
146
230
val stackPC : ArrayStack [Int ] = new ArrayStack
@@ -189,6 +273,29 @@ object PolyParse {
189
273
retReg_.asInstanceOf [Result ]
190
274
}
191
275
276
+ def performInlining (blocks : Seq [(AnyRef ,BlockIR [_,_])]) : Seq [(AnyRef ,BlockIR [_,_])] = blocks // FIXME: actually do it
277
+
278
+ def splitBasicBlocks [In : Type ,Out : Type ](b : BlockIR [In ,Out ], rest : BlockIR2 [Out ]) : (BlockIR2 [In ],Seq [(AnyRef ,BlockIR2 [_])]) = b match {
279
+ case BranchIR (condition,yes,no) => {
280
+ val (yBlock, yBlocks) = splitBasicBlocks(yes,rest)
281
+ val (nBlock, nBlocks) = splitBasicBlocks(no,rest)
282
+ (BranchIR2 [In ](condition,yBlock,nBlock), yBlocks ++ nBlocks)
283
+ }
284
+ case SeqIR (left,right) => {
285
+ implicit val _ = left.tOut
286
+ val (rBlock, rBlocks) = splitBasicBlocks(right,rest)
287
+ val (lBlock, lBlocks) = splitBasicBlocks(left, rBlock)
288
+ (lBlock, lBlocks ++ rBlocks)
289
+ }
290
+ case CallIR (key) => {
291
+ (JumpIR2 (key,(key,rest)), Seq (((key,rest),rest)))
292
+ }
293
+ case SimpleIR (fn) => {
294
+ (BeforeIR2 [In ,Out ](fn, rest), Seq ())
295
+ }
296
+ case _ => ???
297
+ }
298
+
192
299
def compile [T : Type ,ET : Type ,Seq [_]: MakeSequenceContext ](g : Grammar [Unit ,T ,ET ])(implicit seqT : Type [Seq [T ]]) : Expr [Seq [ET ] => Option [T ]] = {
193
300
def findRecursions [AT ,T ,ET ](g : Grammar [AT ,T ,ET ]) : Set [Grammar [_,_,_]] = g match {
194
301
case Terminal (_) => Set .empty
@@ -203,8 +310,18 @@ object PolyParse {
203
310
implicitly[MakeSequenceContext [Seq ]].makeCtx(seqCtx => {
204
311
makeControlFlowContext[Option [T ]](flowCtx => {
205
312
flowCtx.block(root => {
206
- val compiler = BlockCompiler (seqCtx, flowCtx, recursions, Map .empty.+ ((g, root)))
207
- compiler.handleRec(g, ' {()}, res => flowCtx.end(' {Some ($res)}), flowCtx.end(' {None }))
313
+ val compiler = BlockCompiler (seqCtx)
314
+ val blocks = compiler.computeBlocks(g)
315
+ val inlinedBlocks = performInlining(blocks)
316
+ val basicBlocks = inlinedBlocks.flatMap(block => {
317
+ val (key,b) = block
318
+ implicit val _ = b.tIn
319
+ implicit val _1 = b.tOut
320
+ val root, blocks = splitBasicBlocks(b, ReturnIR2 ())
321
+ Seq ((key,root),blocks)
322
+ })
323
+ println(basicBlocks)
324
+ ' {()}
208
325
})
209
326
})
210
327
})
@@ -214,7 +331,7 @@ object PolyParse {
214
331
import scala .quoted .Toolbox .Default ._
215
332
object vv {
216
333
val v : Grammar [Unit ,Int ,Int ] = term(1 ) <|> term(2 ) <|> v
217
- val v2 : Grammar [( Unit , Unit ) ,(Int ,Int ),Int ] = (term(1 ) ++ term(2 )) <|> v2
334
+ val v2 : Grammar [Unit ,(Int ,Int ),Int ] = (term(1 ) ++ term(2 )) <|> v2
218
335
}
219
336
println(compile[Int ,Int ,List ](vv.v).show)
220
337
}
0 commit comments