-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNodes.scala
131 lines (107 loc) · 4.23 KB
/
Nodes.scala
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
package bisquit
package nodes
import errors._
import input._
import runtime._
import scope._
import typechecker._
sealed trait Token extends Positioned
case class Eof() extends Token
case class Comma() extends Token
case class OpenParen() extends Token
case class CloseParen() extends Token
case class OpenCurlyBraket() extends Token
case class CloseCurlyBraket() extends Token
case class OpenSquareBraket() extends Token
case class CloseSquareBraket() extends Token
case class Colon() extends Token
case class Equal() extends Token
case class Dot() extends Token
sealed trait Expression extends Positioned with Typing
case class Binop(op: Expression, left: Expression, right: Expression) extends Expression
case class Uniop(op: Expression, subject: Expression) extends Expression
sealed trait IR extends Typing with Positioned
case class Id(lexeme: String) extends IR with Expression with Token
case class App(fn: Expression, args: List[Expression]) extends IR with Expression
case class Let(bindings: Map[Id, Expression], body: Expression) extends IR with Expression
case class Cond(cond: Expression, pass: Expression, fail: Expression) extends IR with Expression
case class RecordLookup(rec: Expression, field: Id) extends IR with Expression
sealed trait Value extends Expression
case class Int(value: Integer) extends IR with Value with Token
case class Real(value: Double) extends IR with Value with Token
case class Str(value: String) extends IR with Value with Token
case class Bool(value: Boolean) extends IR with Value with Token
case class Tuple(fields: List[Expression]) extends IR with Value
case class Lista(items: List[Expression]) extends IR with Value
case class RefCell(var value: Value) extends IR with Value
case class Record(fields: Map[Id, Expression] = Map()) extends IR with Value
trait Callable {
def apply(args: List[IR], scope: Scope):
Either[RuntimeError, Value]
}
type BuiltinFunc = (List[IR], Scope) => Either[RuntimeError, Value]
case class Builtin(sig: LambdaType, fn: BuiltinFunc)
extends IR with Value with Typed(sig) with Callable {
def apply(args: List[IR], scope: Scope) =
fn(args, scope)
}
case class Lambda(
params: List[Id],
body: Expression,
boundScope: Option[Scope],
) extends IR with Value with Callable {
def apply(args: List[IR], scope: Scope): Either[RuntimeError, Value] =
for
vals <- eval(args, scope)
ret <- evalIt(vals, scope)
yield ret
def evalIt(vals: List[Value], scope: Scope) =
val argScope = params.zip(vals).toMap
val lexScope = scope ++ boundScope.getOrElse(Map()) ++ argScope
if params.size != vals.size
then Right(curryIt(vals, lexScope))
else eval(pass1(body), lexScope)
def curryIt(bindings: List[Value], lexScope: Scope) =
Lambda(params = params.drop(bindings.size),
body = App(fn = Lambda(params = params.take(bindings.size),
body = body,
boundScope = boundScope),
args = bindings),
boundScope = Some(lexScope))
}
sealed trait Statement
case class Definition(name: Id, value: Expression) extends Statement
case class Import(name: Id, exposing: List[Id], all: Boolean = false) extends Statement
case class Module(name: Id, exposes: Set[Id], scope: Scope) extends Statement {
def expose(
lexScope: Scope,
modules: Modules,
exposing: List[Id],
all: Boolean,
): Either[RuntimeError, Scope] =
(
exposing.isEmpty,
all,
exposing.diff(exposing.distinct).distinct,
exposing.diff(exposes.toList),
) match {
case (_, true, _, _) =>
val fields = scope.filter { (name, _) =>
exposes.contains(name)
}
Right(lexScope ++ fields)
case (true, false, _, _) =>
val fields = scope.filter { (name, _) => exposes.contains(name) }
val record = Record(fields)
Right(lexScope ++ Map(name -> record))
case (_, _, Nil, Nil) =>
val fields = scope.filter { (name, _) =>
exposing.contains(name) && exposes.contains(name)
}
Right(lexScope ++ fields)
case (_, _, Nil, missing) =>
Left(ModuleValueNotExposed(missing.head, this))
case (_, _, dups, _) =>
Left(DuplicateExposeName(dups.head))
}
}