mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-27 08:24:05 +02:00
compiler: match expr mir
This commit is contained in:
parent
f4fbda226a
commit
9a6d570a8a
@ -222,11 +222,13 @@ export type PatKind =
|
||||
| { tag: "error" }
|
||||
| { tag: "bind" } & BindPat
|
||||
| { tag: "path" } & PathPat
|
||||
| { tag: "bool" } & BoolPat
|
||||
| { tag: "tuple" } & TuplePat
|
||||
| { tag: "struct" } & StructPat;
|
||||
|
||||
export type BindPat = { ident: Ident; mut: boolean };
|
||||
export type PathPat = { qty?: Ty; path: Path };
|
||||
export type BoolPat = { value: boolean };
|
||||
export type TuplePat = { path?: Path; elems: Pat[] };
|
||||
export type StructPat = { path?: Path; fields: PatField[] };
|
||||
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
Block,
|
||||
BlockExpr,
|
||||
BoolExpr,
|
||||
BoolPat,
|
||||
BreakStmt,
|
||||
CallExpr,
|
||||
CForExpr,
|
||||
@ -132,6 +133,7 @@ export interface Visitor<
|
||||
visitErrorPat?(pat: Pat, ...p: P): R;
|
||||
visitBindPat?(pat: Pat, kind: BindPat, ...p: P): R;
|
||||
visitPathPat?(pat: Pat, kind: PathPat, ...p: P): R;
|
||||
visitBoolPat?(pat: Pat, kind: BoolPat, ...p: P): R;
|
||||
visitTuplePat?(pat: Pat, kind: TuplePat, ...p: P): R;
|
||||
visitStructPat?(pat: Pat, kind: StructPat, ...p: P): R;
|
||||
|
||||
@ -532,6 +534,9 @@ export function visitPat<
|
||||
if (v.visitPathPat?.(pat, kind, ...p) === "stop") return;
|
||||
visitPath(v, kind.path, ...p);
|
||||
return;
|
||||
case "bool":
|
||||
if (v.visitBoolPat?.(pat, kind, ...p) === "stop") return;
|
||||
return;
|
||||
case "tuple":
|
||||
if (v.visitTuplePat?.(pat, kind, ...p) === "stop") return;
|
||||
kind.path && visitPath(v, kind.path, ...p);
|
||||
|
@ -91,6 +91,8 @@ export class Checker {
|
||||
return Ok(undefined);
|
||||
case "path":
|
||||
return todo();
|
||||
case "bool":
|
||||
return Ok(undefined);
|
||||
case "tuple": {
|
||||
if (k.path) {
|
||||
const re = this.re.pathRes(k.path.id);
|
||||
@ -133,6 +135,35 @@ export class Checker {
|
||||
}
|
||||
return Res.Ok(undefined);
|
||||
}
|
||||
if (re.kind.tag === "struct") {
|
||||
const data = re.kind.kind.data;
|
||||
if (
|
||||
data.kind.tag !== "tuple" ||
|
||||
ty.kind.tag !== "struct" ||
|
||||
ty.kind.data.tag !== "tuple"
|
||||
) {
|
||||
return Res.Err({
|
||||
msg: "type/pattern mismatch",
|
||||
span: pat.span,
|
||||
});
|
||||
}
|
||||
if (k.elems.length !== data.kind.elems.length) {
|
||||
return Res.Err({
|
||||
msg: `incorrect amount of elements, expected ${data.kind.elems.length} got ${k.elems.length}`,
|
||||
span: pat.span,
|
||||
});
|
||||
}
|
||||
for (const i of data.kind.elems.keys()) {
|
||||
const res = this.assignPatTy(
|
||||
k.elems[i],
|
||||
ty.kind.data.elems[i].ty,
|
||||
);
|
||||
if (!res.ok) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return Res.Ok(undefined);
|
||||
}
|
||||
}
|
||||
return todo();
|
||||
}
|
||||
@ -995,6 +1026,7 @@ export class Checker {
|
||||
case "int":
|
||||
return Ty({ tag: "int" });
|
||||
case "bool":
|
||||
return Ty({ tag: "bool" });
|
||||
case "str":
|
||||
return todo(k.tag);
|
||||
case "path": {
|
||||
@ -1073,6 +1105,10 @@ export class Checker {
|
||||
return todo();
|
||||
}
|
||||
case "path":
|
||||
return todo();
|
||||
case "bool": {
|
||||
return this.patTy(pat);
|
||||
}
|
||||
case "tuple":
|
||||
case "struct":
|
||||
return todo();
|
||||
|
@ -164,6 +164,9 @@ export class FnLowerer {
|
||||
return;
|
||||
}
|
||||
case "path":
|
||||
return todo();
|
||||
case "bool":
|
||||
return;
|
||||
case "tuple":
|
||||
case "struct":
|
||||
return todo();
|
||||
@ -186,6 +189,9 @@ export class FnLowerer {
|
||||
return;
|
||||
}
|
||||
case "path":
|
||||
return todo();
|
||||
case "bool":
|
||||
return;
|
||||
case "tuple":
|
||||
case "struct":
|
||||
return todo();
|
||||
@ -569,6 +575,7 @@ export class FnLowerer {
|
||||
nextArmBlock,
|
||||
);
|
||||
this.pushCreatedBlock(exprBlock);
|
||||
this.lowerMatchArmPatternBindings(discr, arm.pat);
|
||||
const rval = this.lowerExpr(arm.expr);
|
||||
this.addStmt({
|
||||
tag: "assign",
|
||||
@ -588,6 +595,102 @@ export class FnLowerer {
|
||||
pat: ast.Pat,
|
||||
truthyBlock: Block,
|
||||
falsyBlock: Block,
|
||||
) {
|
||||
const discrOperand = this.lowerMatchArmPatternCondition(discr, pat);
|
||||
this.setTer({
|
||||
tag: "switch",
|
||||
discr: discrOperand,
|
||||
targets: [{ value: 1, target: truthyBlock.id }],
|
||||
otherwise: falsyBlock.id,
|
||||
});
|
||||
}
|
||||
|
||||
private lowerMatchArmPatternCondition(
|
||||
discr: RVal,
|
||||
pat: ast.Pat,
|
||||
): Operand {
|
||||
const k = pat.kind;
|
||||
switch (k.tag) {
|
||||
case "error":
|
||||
return { tag: "error" };
|
||||
case "bind": {
|
||||
return { tag: "const", val: { tag: "int", value: 1 } };
|
||||
}
|
||||
case "path":
|
||||
return todo();
|
||||
case "bool": {
|
||||
const ty = this.ch.patTy(pat);
|
||||
if (ty.kind.tag !== "bool") {
|
||||
throw new Error();
|
||||
}
|
||||
const discrLocal = this.local(ty);
|
||||
this.addStmt({
|
||||
tag: "assign",
|
||||
place: { local: discrLocal, proj: [] },
|
||||
rval: discr,
|
||||
});
|
||||
const local = this.local(ty);
|
||||
this.addStmt({
|
||||
tag: "assign",
|
||||
place: { local, proj: [] },
|
||||
rval: {
|
||||
tag: "binary",
|
||||
binaryType: "eq",
|
||||
left: this.copyOrMoveLocal(discrLocal, ty),
|
||||
right: { tag: "const", val: { tag: "int", value: 1 } },
|
||||
},
|
||||
});
|
||||
return this.copyOrMoveLocal(local, ty);
|
||||
}
|
||||
case "tuple": {
|
||||
const ty = this.ch.patTy(pat);
|
||||
if (ty.kind.tag === "struct") {
|
||||
const discrLocal = this.local(ty);
|
||||
this.addStmt({
|
||||
tag: "assign",
|
||||
place: { local: discrLocal, proj: [] },
|
||||
rval: discr,
|
||||
});
|
||||
const condLocals: LocalId[] = [];
|
||||
for (const [fieldIdx, pat] of k.elems.entries()) {
|
||||
if (ty.kind.data.tag !== "tuple") {
|
||||
throw new Error();
|
||||
}
|
||||
const elemTy = ty.kind.data.elems[fieldIdx].ty;
|
||||
const condOperand = this.lowerMatchArmPatternCondition({
|
||||
tag: "use",
|
||||
operand: {
|
||||
tag: "move",
|
||||
place: {
|
||||
local: discrLocal,
|
||||
proj: [{ tag: "field", fieldIdx }],
|
||||
},
|
||||
},
|
||||
}, pat);
|
||||
const condLocal = this.local(Ty({ tag: "int" }));
|
||||
this.addStmt({
|
||||
tag: "assign",
|
||||
place: { local: condLocal, proj: [] },
|
||||
rval: { tag: "use", operand: condOperand },
|
||||
});
|
||||
condLocals.push(condLocal);
|
||||
}
|
||||
const condRVal = condLocals
|
||||
.reduce((condRVal, condLocal) => {
|
||||
const local = this.local(Ty({ tag: "int" }));
|
||||
});
|
||||
}
|
||||
return todo();
|
||||
}
|
||||
case "struct":
|
||||
return todo();
|
||||
}
|
||||
exhausted(k);
|
||||
}
|
||||
|
||||
private lowerMatchArmPatternBindings(
|
||||
discr: RVal,
|
||||
pat: ast.Pat,
|
||||
) {
|
||||
const k = pat.kind;
|
||||
switch (k.tag) {
|
||||
@ -601,14 +704,14 @@ export class FnLowerer {
|
||||
place: { local, proj: [] },
|
||||
rval: discr,
|
||||
});
|
||||
this.setTer({ tag: "goto", target: truthyBlock.id });
|
||||
return;
|
||||
}
|
||||
case "path":
|
||||
return;
|
||||
case "bool":
|
||||
return;
|
||||
case "tuple":
|
||||
return todo();
|
||||
case "tuple": {
|
||||
return todo();
|
||||
}
|
||||
case "struct":
|
||||
return todo();
|
||||
}
|
||||
|
@ -1222,6 +1222,14 @@ export class Parser {
|
||||
const ident = this.parseIdent();
|
||||
return this.pat({ tag: "bind", ident, mut: true }, begin);
|
||||
}
|
||||
if (this.test("false")) {
|
||||
this.step();
|
||||
return this.pat({ tag: "bool", value: false }, begin);
|
||||
}
|
||||
if (this.test("true")) {
|
||||
this.step();
|
||||
return this.pat({ tag: "bool", value: true }, begin);
|
||||
}
|
||||
this.report(`expected pattern, got '${this.current().type}'`, begin);
|
||||
this.step();
|
||||
return this.pat({ tag: "error" }, begin);
|
||||
|
@ -2,14 +2,25 @@
|
||||
// #[builtin(Hello)]
|
||||
// fn c_hello() -> int {}
|
||||
|
||||
fn main() {
|
||||
let mut a = 2;
|
||||
if true {
|
||||
a = 3;
|
||||
} else {
|
||||
struct A(bool, bool);
|
||||
|
||||
fn main() {
|
||||
//let mut a = 2;
|
||||
//if true {
|
||||
// a = 3;
|
||||
//} else {
|
||||
//
|
||||
//}
|
||||
//let b = a;
|
||||
|
||||
let a = A(true, false);
|
||||
|
||||
match a {
|
||||
A(false, false) => {}
|
||||
A(false, true) => {}
|
||||
A(true, false) => {}
|
||||
A(true, true) => {}
|
||||
}
|
||||
let b = a;
|
||||
}
|
||||
|
||||
|
||||
|
@ -180,6 +180,8 @@ export class HirStringifyer {
|
||||
}`;
|
||||
case "path":
|
||||
return this.path(k.path);
|
||||
case "bool":
|
||||
return k.value ? "true" : "false";
|
||||
case "tuple":
|
||||
return `${k.path && this.path(k.path) || ""}(${
|
||||
k.elems.map((pat) => this.pat(pat, d)).join(", ")
|
||||
|
Loading…
x
Reference in New Issue
Block a user