Skip to content

Commit ded5a1f

Browse files
committed
Initial typing
1 parent d1cb515 commit ded5a1f

File tree

11 files changed

+415
-53
lines changed

11 files changed

+415
-53
lines changed

src/main/scala/plus/meow/MeowRust/Main.scala

+37-12
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import scala.io.Source
55
import plus.meow.MeowRust.parser.Parser
66
import com.codecommit.gll.Success
77
import com.codecommit.gll.Failure
8+
import plus.meow.MeowRust.grammar.Node
9+
import plus.meow.MeowRust.resolve.TypeResolvable
10+
import plus.meow.MeowRust.resolve.TypeResolutionContext
11+
import plus.meow.MeowRust.resolve.ResolvedType
12+
import scala.collection.immutable.HashMap
813

914
/**
1015
* MeowRust compiler
@@ -25,21 +30,41 @@ import com.codecommit.gll.Failure
2530

2631

2732
object Main extends App {
33+
def parse(file: String): Node = {
34+
println("Parsing file: " + file)
35+
36+
val stream = LineStream(Source fromFile file)
37+
38+
// First successful parsing-tree is with the intended precedence
39+
for(i <- Parser.parse(stream)) {
40+
i match {
41+
case Success(tree, _) => {
42+
println("Parser tree:\n" + tree.fmt)
43+
return tree
44+
}
45+
case Failure(f, t) => println("Failed: " + f + ", " + t.mkString)
46+
}
47+
}
48+
49+
throw new Error("No applicable parsing tree")
50+
}
51+
52+
def typing(root: Node): ResolvedType = {
53+
if(root.isInstanceOf[TypeResolvable]) {
54+
val ctx = TypeResolutionContext(HashMap(), None, None)
55+
val t = root.asInstanceOf[TypeResolvable].resolve(ctx, None)
56+
println("Root type: " + t.toString)
57+
t
58+
} else {
59+
throw new Error("Root not type-resolvable")
60+
}
61+
}
62+
2863
override def main(args: Array[String]) {
2964
for(file <- args) {
3065
println("Processing file " + file)
31-
val stream = LineStream(Source fromFile file)
32-
33-
// First parse-tree / error is with the intended precedence
34-
for(i <- Parser.parse(stream)) {
35-
i match {
36-
case Success(tree, _) => {
37-
println("Parser tree:\n" + tree.fmt)
38-
return
39-
}
40-
case Failure(f, t) => println("Failed: " + f + ", " + t.mkString)
41-
}
42-
}
66+
val tree = parse(file)
67+
val resolvedType = typing(tree)
4368
}
4469
}
4570
}

src/main/scala/plus/meow/MeowRust/grammar/expr.scala

+204-23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package plus.meow.MeowRust.grammar
22

3+
import plus.meow.MeowRust.resolve._
4+
35
abstract class UnaryOp
46
case class Neg() extends UnaryOp
57
case class LogicalNot() extends UnaryOp
@@ -43,38 +45,217 @@ case class Return() extends FlowCtrl
4345
case class Continue() extends FlowCtrl
4446
case class Break() extends FlowCtrl
4547

46-
abstract class Expr extends Node
47-
case class LiteralExpr(lit: Literal) extends Expr
48-
// TODO: statements
49-
case class BlockExpr(body: List[Any]) extends Expr
50-
case class TupleExpr(exprs: List[Expr]) extends Expr
51-
case class ArrayExpr(elems: List[Expr]) extends Expr
52-
case class ArrayFillExpr(elem: Expr, count: Expr) extends Expr
53-
case class CallExpr(recv: Expr, method: Option[String], params: List[Expr]) extends Expr
48+
abstract class Expr extends Node with TypeResolvable with ConstEvaluable
49+
50+
// TODO: impl constEval for types other thant literal expr
51+
52+
case class LiteralExpr(lit: Literal) extends Expr {
53+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = lit.resolve(ctx, hint)
54+
override def constEval: ConstEvalResult = lit.constEval
55+
}
56+
57+
case class BlockExpr(body: List[Stmt], implicitRet: Option[Expr]) extends Expr {
58+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = {
59+
// TODO: check all ret values are the same?
60+
for(s <- body) s.resolve(ctx, None)
61+
implicitRet match {
62+
case None => plus.meow.MeowRust.resolve.TupleType(List())
63+
case Some(expr) => expr.resolve(ctx, None)
64+
}
65+
}
66+
}
67+
case class TupleExpr(exprs: List[Expr]) extends Expr {
68+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = {
69+
val types = for(e <- exprs) yield e.resolve(ctx, None)
70+
plus.meow.MeowRust.resolve.TupleType(types)
71+
}
72+
}
73+
case class ArrayExpr(elems: List[Expr]) extends Expr {
74+
// TODO: check all elems are of the same type?
75+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = {
76+
// TODO: error if hint doesn't match
77+
var base = hint.flatMap(_.t match {
78+
case plus.meow.MeowRust.resolve.ArrayType(t, len) => Some(t)
79+
case _ => None
80+
})
81+
82+
// TODO: apply type hints
83+
for(e <- elems) {
84+
val self = e.resolve(ctx, None)
85+
if(base.isEmpty) base = Some(self)
86+
}
87+
plus.meow.MeowRust.resolve.ArrayType(base.get, elems.length)
88+
}
89+
}
90+
case class ArrayFillExpr(elem: Expr, count: Expr) extends Expr {
91+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = {
92+
// TODO: error if hint doesn't match
93+
val base = elem.resolve(ctx, None)
94+
val countType = count.resolve(ctx, None)
95+
val countEvaluated = count.constEval.asInstanceOf[ConstEvalValue]
96+
// TODO: error if count cannot be const-evaluated, or is not evaluated to ints
97+
plus.meow.MeowRust.resolve.ArrayType(base, countEvaluated.value.asInstanceOf[BigInt])
98+
}
99+
}
100+
case class CallExpr(recv: Expr, method: Option[String], params: List[Expr]) extends Expr {
101+
// TODO: resolve functions
102+
}
54103
case class FieldExpr(owner: Expr, field: Expr) extends Expr
55-
case class ArrayIndexExpr(owner: Expr, index: Expr) extends Expr
56-
case class TupleIndexExpr(owner: Expr, index: BigInt) extends Expr
57-
case class ClosureExpr(params: List[Pattern], body: Expr) extends Expr
58-
case class FlowCtrlExpr(ctrl: FlowCtrl, label: Option[String], param: Option[Expr]) extends Expr
59-
case class RangeExpr(from: Option[Expr], to: Option[Expr], includeTo: Boolean) extends Expr
104+
case class ArrayIndexExpr(owner: Expr, index: Expr) extends Expr {
105+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = {
106+
owner.resolve(ctx, None) match {
107+
case plus.meow.MeowRust.resolve.ArrayType(b, _) => b
108+
case _ => {
109+
// TODO: convert to Index / IndexMut calls
110+
ResolutionErrorType("Unimplemented: Index/IndexMut override")
111+
}
112+
}
113+
}
114+
}
115+
case class TupleIndexExpr(owner: Expr, index: BigInt) extends Expr {
116+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = {
117+
owner.resolve(ctx, None) match {
118+
case plus.meow.MeowRust.resolve.TupleType(l) => {
119+
if(l.length <= index) {
120+
ResolutionErrorType("Tuple with length " + l.length + " indexed with " + index)
121+
} else {
122+
l(index toInt)
123+
}
124+
}
125+
case t => {
126+
ResolutionErrorType("Cannot use tuple index on " + t.toString)
127+
}
128+
}
129+
}
130+
}
131+
case class ClosureExpr(params: List[Pattern], body: Expr) extends Expr {
132+
// TODO: typing patterns
133+
}
134+
case class FlowCtrlExpr(ctrl: FlowCtrl, label: Option[String], param: Option[Expr]) extends Expr {
135+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = {
136+
val ptype = param.map(_.resolve(ctx, None)) getOrElse plus.meow.MeowRust.resolve.TupleType(List()) // Unit
137+
138+
// TODO: reverse typehint
139+
val around = ctrl match {
140+
case Break() => ctx.getBreakable(label)
141+
case Return() => ctx.func
142+
}
143+
144+
if(around.isDefined) {
145+
around.get.apply(ptype)
146+
}
147+
148+
plus.meow.MeowRust.resolve.NeverType()
149+
}
150+
}
151+
case class RangeExpr(from: Option[Expr], to: Option[Expr], includeTo: Boolean) extends Expr {
152+
// TODO: impl range class
153+
}
60154

61155
// Operator expressions
62-
case class BorrowExpr(content: Expr, mut: Boolean) extends Expr
63-
case class DerefExpr(from: Expr) extends Expr
64-
case class QuestionExpr(unwrapped: Expr) extends Expr
156+
case class BorrowExpr(content: Expr, mut: Boolean) extends Expr {
157+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = {
158+
// TODO: deref hint
159+
val inner = content.resolve(ctx, None)
160+
plus.meow.MeowRust.resolve.RefType(inner, mut)
161+
}
162+
}
163+
164+
case class DerefExpr(from: Expr) extends Expr {
165+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = {
166+
// TODO: deref hint
167+
from.resolve(ctx, None) match {
168+
case plus.meow.MeowRust.resolve.RefType(inner, _) => inner
169+
case t => ResolutionErrorType("Cannot deref " + t.toString)
170+
}
171+
}
172+
}
173+
case class QuestionExpr(unwrapped: Expr) extends Expr {
174+
// TODO: check surrounding function ret type
175+
// TODO: impl result type
176+
}
177+
178+
// TODO: desuger into function calls
65179
case class UnaryOpExpr(op: UnaryOp, operand: Expr) extends Expr
66180
case class BinaryOpExpr(op: BinaryOp, lhs: Expr, rhs: Expr) extends Expr
67181

68182
// Loops
69-
case class InftyLoopExpr(label: Option[String], body: Expr) extends Expr
70-
case class ForLoopExpr(label: Option[String], pat: Pattern, collection: Expr, body: Expr) extends Expr
71-
case class WhileExpr(label: Option[String], cond: Expr, body: Expr) extends Expr
72-
case class WhileLetExpr(label: Option[String], pat: List[Pattern], unwrapped: Expr, body: Expr) extends Expr
183+
abstract class LoopExpr extends Expr {
184+
val label: Option[String]
185+
val body: Expr
186+
187+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = {
188+
var selfType: Option[ResolvedType] = None
189+
val newCtx = ctx.withBreakable(label, t => {
190+
selfType = Some(t)
191+
true
192+
})
193+
// TODO: check if the end of the loop is reachable
194+
val bodyType = body.resolve(newCtx, None)
195+
196+
// TODO: check if bodyType is unit
197+
selfType getOrElse plus.meow.MeowRust.resolve.NeverType()
198+
}
199+
}
200+
case class InftyLoopExpr(label: Option[String], body: Expr) extends LoopExpr
201+
case class ForLoopExpr(label: Option[String], pat: Pattern, collection: Expr, body: Expr) extends LoopExpr {
202+
// TODO: apply pattern type into ctx when resolving types
203+
}
204+
case class WhileExpr(label: Option[String], cond: Expr, body: Expr) extends LoopExpr {
205+
// TODO: apply pattern type into ctx when resolving types
206+
}
207+
case class WhileLetExpr(label: Option[String], pat: List[Pattern], unwrapped: Expr, body: Expr) extends LoopExpr {
208+
// TODO: apply pattern type into ctx when resolving types
209+
}
73210

74211
// Conditionals
75-
case class IfExpr(cond: Expr, body: Expr, otherwise: Option[Expr]) extends Expr
76-
case class IfLetExpr(pat: List[Pattern], unwrapped: Expr, body: Expr, otherwise: Option[Expr]) extends Expr
212+
case class IfExpr(cond: Expr, body: Expr, otherwise: Option[Expr]) extends Expr {
213+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = {
214+
val condType = cond.resolve(ctx, None)
215+
if(condType != ResolvedType.bool)
216+
return ResolutionErrorType("Cannot use as condition: " + condType.toString)
217+
218+
val trueArmType = body.resolve(ctx, None)
219+
val falseArmType = otherwise map { _.resolve(ctx, None) } getOrElse plus.meow.MeowRust.resolve.TupleType(List()) // Unit
220+
if(falseArmType != trueArmType)
221+
return ResolutionErrorType("Cannot use different types on if arms: " + trueArmType.toString + ", " + falseArmType.toString)
222+
223+
trueArmType
224+
}
225+
}
226+
case class IfLetExpr(pat: List[Pattern], unwrapped: Expr, body: Expr, otherwise: Option[Expr]) extends Expr {
227+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = {
228+
// TODO: apply binding
229+
val trueArmType = body.resolve(ctx, hint)
230+
if(otherwise.isDefined) {
231+
val inner = otherwise.get
232+
val falseArmType = inner.resolve(ctx, hint)
233+
if(falseArmType != trueArmType)
234+
return ResolutionErrorType("Cannot use different types on if arms: " + trueArmType.toString + ", " + falseArmType.toString)
235+
}
236+
237+
trueArmType
238+
}
239+
}
77240

78241
// Matches
79242
case class MatchArm(pat: List[Pattern], guardCond: Option[Expr], body: Expr)
80-
case class MatchExpr(input: Expr, arms: List[MatchArm]) extends Expr
243+
case class MatchExpr(input: Expr, arms: List[MatchArm]) extends Expr {
244+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = {
245+
val inputType = input.resolve(ctx, None)
246+
// TODO: check match arm pattern
247+
var store: Option[ResolvedType] = None
248+
for(arm <- arms) arm match {
249+
case MatchArm(pat, _, body) => {
250+
val t = body.resolve(ctx, hint)
251+
252+
if(store.isEmpty) store = Some(t)
253+
else if(store.get != t) {
254+
return ResolutionErrorType("Match arm typing errored: Expected " + store.get.toString + ", got " + t.toString)
255+
}
256+
}
257+
}
258+
259+
store getOrElse plus.meow.MeowRust.resolve.NeverType()
260+
}
261+
}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,38 @@
11
package plus.meow.MeowRust.grammar
2+
import plus.meow.MeowRust.resolve._
3+
import plus.meow.MeowRust
24

3-
abstract class Literal extends Node
4-
case class CharLiteral(val value: Char) extends Literal
5-
case class IntLiteral(val value: BigInt, val container: Option[String]) extends Literal
6-
case class FloatLiteral(val value: BigDecimal, val container: Option[String]) extends Literal
7-
case class StrLiteral(val value: String) extends Literal
8-
case class BoolLiteral(val value: Boolean) extends Literal
5+
abstract class Literal extends Node with TypeResolvable with ConstEvaluable {
6+
lazy val solidType: ResolvedType = ResolutionErrorType("ICE: Literal resolution not overrided")
7+
override def resolve(
8+
ctx: TypeResolutionContext,
9+
hint: Option[TypeHint]
10+
): ResolvedType = solidType
11+
12+
type LitRepr
13+
val value: LitRepr
14+
override def constEval: ConstEvalResult = ConstEvalValue(value)
15+
}
16+
17+
case class CharLiteral(val value: Char) extends Literal {
18+
override type LitRepr = Char
19+
override lazy val solidType: ResolvedType = PrimitiveType("char")
20+
}
21+
case class IntLiteral(val value: BigInt, val container: Option[String]) extends Literal {
22+
override type LitRepr = BigInt
23+
override lazy val solidType: ResolvedType = PrimitiveType(container getOrElse "isize") // TODO: infer length
24+
}
25+
case class FloatLiteral(val value: BigDecimal, val container: Option[String]) extends Literal {
26+
override type LitRepr = BigDecimal
27+
override lazy val solidType: ResolvedType = PrimitiveType(container getOrElse "f128") // TODO: infer length
28+
}
29+
case class StrLiteral(val value: String) extends Literal {
30+
override type LitRepr = String
31+
override lazy val solidType: ResolvedType = MeowRust.resolve.RefType(PrimitiveType("str"), false)
32+
}
33+
case class BoolLiteral(val value: Boolean) extends Literal {
34+
override type LitRepr = Boolean
35+
override lazy val solidType: ResolvedType = PrimitiveType("bool")
36+
}
37+
38+
// TODO: array, tuple, struct, enum literals
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
package plus.meow.MeowRust.grammar
2+
import plus.meow.MeowRust.resolve._
23

3-
abstract class Stmt
4+
abstract class Stmt extends TypeResolvable {
5+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType
6+
= plus.meow.MeowRust.resolve.TupleType(List()) // Unit
7+
}
48

5-
case class LetStmt(store: Pattern, value: Option[Expr]) extends Stmt
6-
case class ExprStmt(expr: Expr) extends Stmt
9+
case class LetStmt(store: Pattern, value: Option[Expr]) extends Stmt {
10+
// TODO: assign type to the pattern
11+
// TODO: assign type hint to value
12+
}
13+
case class ExprStmt(expr: Expr) extends Stmt {
14+
override def resolve(ctx: TypeResolutionContext, hint: Option[TypeHint]): ResolvedType = {
15+
expr.resolve(ctx, None)
16+
plus.meow.MeowRust.resolve.TupleType(List()) // Unit
17+
}
18+
}
719
case class EmptyStmt() extends Stmt

src/main/scala/plus/meow/MeowRust/parser/common.scala

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ trait SeparatedParsers extends RegexParsers {
1010
override val skipWhitespace: Boolean = false
1111

1212
val delimStart = Set('+', '-', '*', '/', '%', '^', '!', '&', '|',
13-
'>', '<', '=', '@', '_', '.', ',', ';', ':', '#', '$', '?')
13+
'>', '<', '=', '@', '_', '.', ',', ';', ':', '#', '$', '?',
14+
'(', '[', '{', ')', ']', '{'
15+
)
1416

1517
class SeparatorParser extends RegexParser("""[\n\t ]+""".r) {
1618
override def computeFirst(seen: Set[Parser[Any]])

0 commit comments

Comments
 (0)