forked from hkust-taco/mlscript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBlock.mls
More file actions
163 lines (132 loc) · 4.9 KB
/
Block.mls
File metadata and controls
163 lines (132 loc) · 4.9 KB
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import "./Predef.mls"
import "./Option.mls"
import "./Term.mls"
import "./StrOps.mls"
open StrOps
open Predef
open Option
module Block with...
type Opt[A] = Option[A]
// dependancies referenced in Block classes, referencing implementation in Term.mls
type Ident = Symbol
type Literal = null | undefined | Str | Int | Num | Bool
class Arg(val spread: Opt[Bool], val value: Path) // unused
type ParamList = Array[Symbol]
// Classes defined in Block.scala
class Path with
constructor
Select(val qual: Path, val name: Ident)
DynSelect(val qual: Path, val fld: Path, arrayIdx: Bool)
ValueRef(val l: Symbol)
ValueLit(val lit: Literal)
// Match pattern for staged code
class Case with
constructor
Lit(val lit: Literal)
Cls(val cls: Symbol, val path: Path)
Tup(val len: Int, val inf: Bool) // TODO: remove inf?
Field(val name: Ident)
Wildcard
class Result with
constructor
// unused?
TrivialResult(val path: Path) // only Path extends TrivialResult
Call(val _fun: Path, val args: Array[Arg])
Instantiate(val cls: Path, val args: Array[Arg]) // assume immutable
Tuple(val elems: Array[Arg]) // assume immutable
class Defn with
constructor
ValDefn(val sym: Symbol, val rhs: Path)
ClsLikeDefn(val sym: Symbol, val paramsOpt: Opt[ParamList], val companion: Opt[ClsLikeBody]) // unused
FunDefn(val sym: Symbol, val params: Array[ParamList], val body: Block)
class ClsLikeBody(val isym: Symbol, val methods: Array[FunDefn], val publicFields: Array[Symbol -> Symbol]) // unused
class Block with
constructor
Match(val scrut: Path, val arms: Array[Case -> Block], val dflt: Opt[Block], val rest: Block)
Return(val res: Result, val implct: Bool)
Assign(val lhs: Symbol, val rhs: Result, val rest: Block)
Define(val defn: Defn, val rest: Block)
End()
fun showBool(b: Bool) = if b then "true" else "false"
fun showLiteral(l: Literal) =
if l is
null => "null"
| undefined => "undefined"
| s: Str => "\"" + s + "\""
| i: Int => str(i)
| n: Num => str(n)
| b: Bool => showBool(b)
fun showSymbol(s: Symbol) = "Symbol(" + "\"" + s.name + "\"" + ")"
fun showIdent(i: Ident) = showSymbol(i)
// Path
fun showPath(p: Path): Str =
if p is
Select(qual, name) =>
"Select(" + showPath(qual) + ", " + showIdent(name) + ")"
| DynSelect(qual, fld, arrayIdx) =>
"DynSelect(" + showPath(qual) + ", " + showPath(fld) + ", " + showBool(arrayIdx) + ")"
| ValueRef(l) =>
// match Term/Quasiquotes style: Ref(Symbol("x"))
"Ref(" + showSymbol(l) + ")"
| ValueLit(lit) =>
// match Term/Quasiquotes style: Lit(42)
"Lit(" + showLiteral(lit) + ")"
// Arg (used in Result.Call/Tuple/etc.)
fun showArg(a: Arg) =
if a.spread is
Some(true) => "..." + showPath(a.value)
| _ => showPath(a.value)
fun showArgs(as: Array[Arg]) =
"[" + as.map(showArg).joinWith(", ") + "]"
// Case (match arm patterns)
fun showCase(c: Case): Str =
if c is
Lit(lit) => "Lit(" + showLiteral(lit) + ")"
| Cls(cls, path) => "Cls(" + showSymbol(cls) + ", " + showPath(path) + ")"
| Tup(len, inf) => "Tup(" + str(len) + ", " + showBool(inf) + ")"
| Field(name) => "Field(" + showIdent(name) + ")"
| Wildcard => "Wildcard"
// Result
fun showResult(r: Result): Str =
if r is
TrivialResult(path) => showPath(path)
| Call(fun, args) => "Call(" + showPath(fun) + ", " + showArgs(args) + ")"
| Instantiate(cls, args) => "Instantiate(" + showPath(cls) + ", " + showArgs(args) + ")"
| Tuple(elems) => "Tuple(" + showArgs(elems) + ")"
// Defn
fun showParamList(ps: ParamList) =
"[" + ps.map(showSymbol).joinWith(", ") + "]"
fun showDefn(d: Defn): Str =
if d is
ValDefn(sym, rhs) =>
"ValDefn(" + showSymbol(sym) + ", " + showPath(rhs) + ")"
| FunDefn(sym, params, body) =>
"FunDefn(" + showSymbol(sym) + ", " +
"[" + params.map(showParamList).joinWith(", ") + "], " +
showBlock(body) + ")"
| ClsLikeDefn(sym, paramsOpt, companion) =>
// minimal, since this is unused in your staged Block for now
"ClsLikeDefn(" + showSymbol(sym) + ")"
// Block
fun showOptBlock(ob: Opt[Block]) =
if ob is Some(b) then showBlock(b) else "None"
fun showArm(pair: Case -> Block) =
if pair is cse -> body then showCase(cse) + " -> " + showBlock(body) else "<bad-arm>"
fun showBlock(b: Block): Str =
if b is
Match(scrut, arms, dflt, rest) =>
"Match(" +
showPath(scrut) + ", " +
"[" + arms.map(showArm).joinWith(", ") + "], " +
showOptBlock(dflt) + ", " +
showBlock(rest) + ")"
| Return(res, implct) =>
"Return(" + showResult(res) + ", " + showBool(implct) + ")"
| Assign(lhs, rhs, rest) =>
"Assign(" + showSymbol(lhs) + ", " + showResult(rhs) + ", " + showBlock(rest) + ")"
| Define(defn, rest) =>
"Define(" + showDefn(defn) + ", " + showBlock(rest) + ")"
| End() => "End"
// Public entry
fun printCode(p: Block): Str = console.log(showBlock(p))
fun compile(p: Block) = ???