mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-27 16:24:07 +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: "error" }
|
||||||
| { tag: "bind" } & BindPat
|
| { tag: "bind" } & BindPat
|
||||||
| { tag: "path" } & PathPat
|
| { tag: "path" } & PathPat
|
||||||
|
| { tag: "bool" } & BoolPat
|
||||||
| { tag: "tuple" } & TuplePat
|
| { tag: "tuple" } & TuplePat
|
||||||
| { tag: "struct" } & StructPat;
|
| { tag: "struct" } & StructPat;
|
||||||
|
|
||||||
export type BindPat = { ident: Ident; mut: boolean };
|
export type BindPat = { ident: Ident; mut: boolean };
|
||||||
export type PathPat = { qty?: Ty; path: Path };
|
export type PathPat = { qty?: Ty; path: Path };
|
||||||
|
export type BoolPat = { value: boolean };
|
||||||
export type TuplePat = { path?: Path; elems: Pat[] };
|
export type TuplePat = { path?: Path; elems: Pat[] };
|
||||||
export type StructPat = { path?: Path; fields: PatField[] };
|
export type StructPat = { path?: Path; fields: PatField[] };
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
Block,
|
Block,
|
||||||
BlockExpr,
|
BlockExpr,
|
||||||
BoolExpr,
|
BoolExpr,
|
||||||
|
BoolPat,
|
||||||
BreakStmt,
|
BreakStmt,
|
||||||
CallExpr,
|
CallExpr,
|
||||||
CForExpr,
|
CForExpr,
|
||||||
@ -132,6 +133,7 @@ export interface Visitor<
|
|||||||
visitErrorPat?(pat: Pat, ...p: P): R;
|
visitErrorPat?(pat: Pat, ...p: P): R;
|
||||||
visitBindPat?(pat: Pat, kind: BindPat, ...p: P): R;
|
visitBindPat?(pat: Pat, kind: BindPat, ...p: P): R;
|
||||||
visitPathPat?(pat: Pat, kind: PathPat, ...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;
|
visitTuplePat?(pat: Pat, kind: TuplePat, ...p: P): R;
|
||||||
visitStructPat?(pat: Pat, kind: StructPat, ...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;
|
if (v.visitPathPat?.(pat, kind, ...p) === "stop") return;
|
||||||
visitPath(v, kind.path, ...p);
|
visitPath(v, kind.path, ...p);
|
||||||
return;
|
return;
|
||||||
|
case "bool":
|
||||||
|
if (v.visitBoolPat?.(pat, kind, ...p) === "stop") return;
|
||||||
|
return;
|
||||||
case "tuple":
|
case "tuple":
|
||||||
if (v.visitTuplePat?.(pat, kind, ...p) === "stop") return;
|
if (v.visitTuplePat?.(pat, kind, ...p) === "stop") return;
|
||||||
kind.path && visitPath(v, kind.path, ...p);
|
kind.path && visitPath(v, kind.path, ...p);
|
||||||
|
@ -91,6 +91,8 @@ export class Checker {
|
|||||||
return Ok(undefined);
|
return Ok(undefined);
|
||||||
case "path":
|
case "path":
|
||||||
return todo();
|
return todo();
|
||||||
|
case "bool":
|
||||||
|
return Ok(undefined);
|
||||||
case "tuple": {
|
case "tuple": {
|
||||||
if (k.path) {
|
if (k.path) {
|
||||||
const re = this.re.pathRes(k.path.id);
|
const re = this.re.pathRes(k.path.id);
|
||||||
@ -133,6 +135,35 @@ export class Checker {
|
|||||||
}
|
}
|
||||||
return Res.Ok(undefined);
|
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();
|
return todo();
|
||||||
}
|
}
|
||||||
@ -995,6 +1026,7 @@ export class Checker {
|
|||||||
case "int":
|
case "int":
|
||||||
return Ty({ tag: "int" });
|
return Ty({ tag: "int" });
|
||||||
case "bool":
|
case "bool":
|
||||||
|
return Ty({ tag: "bool" });
|
||||||
case "str":
|
case "str":
|
||||||
return todo(k.tag);
|
return todo(k.tag);
|
||||||
case "path": {
|
case "path": {
|
||||||
@ -1073,6 +1105,10 @@ export class Checker {
|
|||||||
return todo();
|
return todo();
|
||||||
}
|
}
|
||||||
case "path":
|
case "path":
|
||||||
|
return todo();
|
||||||
|
case "bool": {
|
||||||
|
return this.patTy(pat);
|
||||||
|
}
|
||||||
case "tuple":
|
case "tuple":
|
||||||
case "struct":
|
case "struct":
|
||||||
return todo();
|
return todo();
|
||||||
|
@ -164,6 +164,9 @@ export class FnLowerer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case "path":
|
case "path":
|
||||||
|
return todo();
|
||||||
|
case "bool":
|
||||||
|
return;
|
||||||
case "tuple":
|
case "tuple":
|
||||||
case "struct":
|
case "struct":
|
||||||
return todo();
|
return todo();
|
||||||
@ -186,6 +189,9 @@ export class FnLowerer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case "path":
|
case "path":
|
||||||
|
return todo();
|
||||||
|
case "bool":
|
||||||
|
return;
|
||||||
case "tuple":
|
case "tuple":
|
||||||
case "struct":
|
case "struct":
|
||||||
return todo();
|
return todo();
|
||||||
@ -569,6 +575,7 @@ export class FnLowerer {
|
|||||||
nextArmBlock,
|
nextArmBlock,
|
||||||
);
|
);
|
||||||
this.pushCreatedBlock(exprBlock);
|
this.pushCreatedBlock(exprBlock);
|
||||||
|
this.lowerMatchArmPatternBindings(discr, arm.pat);
|
||||||
const rval = this.lowerExpr(arm.expr);
|
const rval = this.lowerExpr(arm.expr);
|
||||||
this.addStmt({
|
this.addStmt({
|
||||||
tag: "assign",
|
tag: "assign",
|
||||||
@ -588,6 +595,102 @@ export class FnLowerer {
|
|||||||
pat: ast.Pat,
|
pat: ast.Pat,
|
||||||
truthyBlock: Block,
|
truthyBlock: Block,
|
||||||
falsyBlock: 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;
|
const k = pat.kind;
|
||||||
switch (k.tag) {
|
switch (k.tag) {
|
||||||
@ -601,14 +704,14 @@ export class FnLowerer {
|
|||||||
place: { local, proj: [] },
|
place: { local, proj: [] },
|
||||||
rval: discr,
|
rval: discr,
|
||||||
});
|
});
|
||||||
this.setTer({ tag: "goto", target: truthyBlock.id });
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case "path":
|
case "path":
|
||||||
|
return;
|
||||||
|
case "bool":
|
||||||
|
return;
|
||||||
|
case "tuple":
|
||||||
return todo();
|
return todo();
|
||||||
case "tuple": {
|
|
||||||
return todo();
|
|
||||||
}
|
|
||||||
case "struct":
|
case "struct":
|
||||||
return todo();
|
return todo();
|
||||||
}
|
}
|
||||||
|
@ -1222,6 +1222,14 @@ export class Parser {
|
|||||||
const ident = this.parseIdent();
|
const ident = this.parseIdent();
|
||||||
return this.pat({ tag: "bind", ident, mut: true }, begin);
|
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.report(`expected pattern, got '${this.current().type}'`, begin);
|
||||||
this.step();
|
this.step();
|
||||||
return this.pat({ tag: "error" }, begin);
|
return this.pat({ tag: "error" }, begin);
|
||||||
|
@ -2,14 +2,25 @@
|
|||||||
// #[builtin(Hello)]
|
// #[builtin(Hello)]
|
||||||
// fn c_hello() -> int {}
|
// fn c_hello() -> int {}
|
||||||
|
|
||||||
fn main() {
|
struct A(bool, bool);
|
||||||
let mut a = 2;
|
|
||||||
if true {
|
|
||||||
a = 3;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
|
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":
|
case "path":
|
||||||
return this.path(k.path);
|
return this.path(k.path);
|
||||||
|
case "bool":
|
||||||
|
return k.value ? "true" : "false";
|
||||||
case "tuple":
|
case "tuple":
|
||||||
return `${k.path && this.path(k.path) || ""}(${
|
return `${k.path && this.path(k.path) || ""}(${
|
||||||
k.elems.map((pat) => this.pat(pat, d)).join(", ")
|
k.elems.map((pat) => this.pat(pat, d)).join(", ")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user