|
1 | 1 | package plus.meow.MeowRust.grammar
|
2 | 2 |
|
| 3 | +import plus.meow.MeowRust.resolve._ |
| 4 | + |
3 | 5 | abstract class UnaryOp
|
4 | 6 | case class Neg() extends UnaryOp
|
5 | 7 | case class LogicalNot() extends UnaryOp
|
@@ -43,38 +45,217 @@ case class Return() extends FlowCtrl
|
43 | 45 | case class Continue() extends FlowCtrl
|
44 | 46 | case class Break() extends FlowCtrl
|
45 | 47 |
|
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 | +} |
54 | 103 | 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 | +} |
60 | 154 |
|
61 | 155 | // 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 |
65 | 179 | case class UnaryOpExpr(op: UnaryOp, operand: Expr) extends Expr
|
66 | 180 | case class BinaryOpExpr(op: BinaryOp, lhs: Expr, rhs: Expr) extends Expr
|
67 | 181 |
|
68 | 182 | // 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 | +} |
73 | 210 |
|
74 | 211 | // 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 | +} |
77 | 240 |
|
78 | 241 | // Matches
|
79 | 242 | 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 | +} |
0 commit comments