mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-28 00:34:06 +02:00
compiler: if-else + copyMove + more
This commit is contained in:
parent
c5e42844af
commit
21c737d06a
@ -45,7 +45,9 @@ export class PackCompiler {
|
|||||||
const resols = new Resolver(this.ctx, entryFileAst).resolve();
|
const resols = new Resolver(this.ctx, entryFileAst).resolve();
|
||||||
const checker = new Checker(this.ctx, entryFileAst, resols);
|
const checker = new Checker(this.ctx, entryFileAst, resols);
|
||||||
console.log(
|
console.log(
|
||||||
"=== HIR ===\n" + new HirStringifyer(checker).file(entryFileAst),
|
"=== HIR ===\n" +
|
||||||
|
new HirStringifyer(this.ctx, checker)
|
||||||
|
.file(entryFileAst),
|
||||||
);
|
);
|
||||||
const astLowerer = new AstLowerer(
|
const astLowerer = new AstLowerer(
|
||||||
this.ctx,
|
this.ctx,
|
||||||
|
@ -178,7 +178,10 @@ export class FnLowerer {
|
|||||||
place: { local: patLocal, proj: [] },
|
place: { local: patLocal, proj: [] },
|
||||||
rval: {
|
rval: {
|
||||||
tag: "use",
|
tag: "use",
|
||||||
operand: { tag: "move", place: { local, proj } },
|
operand: this.copyOrMoveLocal(
|
||||||
|
local,
|
||||||
|
this.locals.get(local)!.ty,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@ -290,10 +293,40 @@ export class FnLowerer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private lowerIfExpr(expr: ast.Expr, kind: ast.IfExpr): RVal {
|
private lowerIfExpr(expr: ast.Expr, kind: ast.IfExpr): RVal {
|
||||||
const cond = this.lowerExprToOperand(kind.cond);
|
const ty = this.ch.exprTy(expr);
|
||||||
|
const discr = this.lowerExprToOperand(kind.cond);
|
||||||
const condBlock = this.currentBlock!;
|
const condBlock = this.currentBlock!;
|
||||||
if (kind.falsy) {
|
if (kind.falsy) {
|
||||||
return todo();
|
const local = this.local(ty);
|
||||||
|
|
||||||
|
const truthBlock = this.pushBlock();
|
||||||
|
const truthy = this.lowerExpr(kind.truthy);
|
||||||
|
this.addStmt({
|
||||||
|
tag: "assign",
|
||||||
|
place: { local, proj: [] },
|
||||||
|
rval: truthy,
|
||||||
|
});
|
||||||
|
|
||||||
|
const falsyBlock = this.pushBlock();
|
||||||
|
const falsy = this.lowerExpr(kind.falsy);
|
||||||
|
this.addStmt({
|
||||||
|
tag: "assign",
|
||||||
|
place: { local, proj: [] },
|
||||||
|
rval: falsy,
|
||||||
|
});
|
||||||
|
|
||||||
|
const exit = this.pushBlock();
|
||||||
|
this.setTer({ tag: "goto", target: exit.id }, truthBlock);
|
||||||
|
this.setTer({ tag: "goto", target: exit.id }, falsyBlock);
|
||||||
|
|
||||||
|
this.setTer({
|
||||||
|
tag: "switch",
|
||||||
|
discr,
|
||||||
|
targets: [{ value: 1, target: truthBlock.id }],
|
||||||
|
otherwise: falsyBlock.id,
|
||||||
|
}, condBlock);
|
||||||
|
|
||||||
|
return { tag: "use", operand: this.copyOrMoveLocal(local, ty) };
|
||||||
} else {
|
} else {
|
||||||
if (this.ch.exprTy(expr).kind.tag !== "null") {
|
if (this.ch.exprTy(expr).kind.tag !== "null") {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
@ -304,7 +337,7 @@ export class FnLowerer {
|
|||||||
this.setTer({ tag: "goto", target: exit.id }, truthBlock);
|
this.setTer({ tag: "goto", target: exit.id }, truthBlock);
|
||||||
this.setTer({
|
this.setTer({
|
||||||
tag: "switch",
|
tag: "switch",
|
||||||
discr: cond,
|
discr,
|
||||||
targets: [{ value: 1, target: truthBlock.id }],
|
targets: [{ value: 1, target: truthBlock.id }],
|
||||||
otherwise: exit.id,
|
otherwise: exit.id,
|
||||||
}, condBlock);
|
}, condBlock);
|
||||||
@ -361,7 +394,7 @@ export class FnLowerer {
|
|||||||
place: { local, proj: [] },
|
place: { local, proj: [] },
|
||||||
rval,
|
rval,
|
||||||
});
|
});
|
||||||
return { tag: "move", place: { local, proj: [] } };
|
return this.copyOrMoveLocal(local, ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exhausted(k);
|
exhausted(k);
|
||||||
@ -388,24 +421,7 @@ export class FnLowerer {
|
|||||||
if (patRes.kind.tag === "fn_param") {
|
if (patRes.kind.tag === "fn_param") {
|
||||||
this.paramLocals.set(local, patRes.kind.paramIdx);
|
this.paramLocals.set(local, patRes.kind.paramIdx);
|
||||||
}
|
}
|
||||||
const isCopyable = (() => {
|
return this.copyOrMoveLocal(local, ty);
|
||||||
switch (ty.kind.tag) {
|
|
||||||
case "error":
|
|
||||||
case "unknown":
|
|
||||||
return false;
|
|
||||||
case "null":
|
|
||||||
case "int":
|
|
||||||
case "bool":
|
|
||||||
return true;
|
|
||||||
case "fn":
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
exhausted(ty.kind);
|
|
||||||
})();
|
|
||||||
return {
|
|
||||||
tag: isCopyable ? "copy" : "move",
|
|
||||||
place: { local, proj: [] },
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
case "fn": {
|
case "fn": {
|
||||||
const { item, kind } = re.kind;
|
const { item, kind } = re.kind;
|
||||||
@ -415,6 +431,27 @@ export class FnLowerer {
|
|||||||
exhausted(re.kind);
|
exhausted(re.kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private copyOrMoveLocal(local: LocalId, ty: Ty): Operand {
|
||||||
|
const isCopyable = (() => {
|
||||||
|
switch (ty.kind.tag) {
|
||||||
|
case "error":
|
||||||
|
case "unknown":
|
||||||
|
return false;
|
||||||
|
case "null":
|
||||||
|
case "int":
|
||||||
|
case "bool":
|
||||||
|
return true;
|
||||||
|
case "fn":
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
exhausted(ty.kind);
|
||||||
|
})();
|
||||||
|
return {
|
||||||
|
tag: isCopyable ? "copy" : "move",
|
||||||
|
place: { local, proj: [] },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private local(ty: Ty, ident?: ast.Ident): LocalId {
|
private local(ty: Ty, ident?: ast.Ident): LocalId {
|
||||||
const id = this.localIds.nextThenStep();
|
const id = this.localIds.nextThenStep();
|
||||||
this.locals.set(id, { id, ty, ident });
|
this.locals.set(id, { id, ty, ident });
|
||||||
|
@ -134,8 +134,8 @@ export class Parser {
|
|||||||
this.step();
|
this.step();
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseExpr(): Expr {
|
private parseExpr(rs: ExprRestricts = 0): Expr {
|
||||||
return this.parseBinary();
|
return this.parseBinary(rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseBlock(): ParseRes<Block, undefined> {
|
private parseBlock(): ParseRes<Block, undefined> {
|
||||||
@ -698,12 +698,12 @@ export class Parser {
|
|||||||
private parseIf(): Expr {
|
private parseIf(): Expr {
|
||||||
const pos = this.span();
|
const pos = this.span();
|
||||||
this.step();
|
this.step();
|
||||||
const cond = this.parseExpr();
|
const cond = this.parseExpr(ExprRestricts.NoStructs);
|
||||||
if (!this.test("{")) {
|
if (!this.test("{")) {
|
||||||
this.report("expected block");
|
this.report("expected block");
|
||||||
return this.expr({ tag: "error" }, pos);
|
return this.expr({ tag: "error" }, pos);
|
||||||
}
|
}
|
||||||
const truthy = this.parseExpr();
|
const truthy = this.parseBlockExpr();
|
||||||
if (!this.test("else")) {
|
if (!this.test("else")) {
|
||||||
return this.expr({ tag: "if", cond, truthy }, pos);
|
return this.expr({ tag: "if", cond, truthy }, pos);
|
||||||
}
|
}
|
||||||
@ -721,16 +721,16 @@ export class Parser {
|
|||||||
return this.expr({ tag: "if", cond, truthy, falsy }, pos);
|
return this.expr({ tag: "if", cond, truthy, falsy }, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseBinary(): Expr {
|
private parseBinary(rs: ExprRestricts): Expr {
|
||||||
return this.parseOr();
|
return this.parseOr(rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseOr(): Expr {
|
private parseOr(rs: ExprRestricts): Expr {
|
||||||
const pos = this.span();
|
const pos = this.span();
|
||||||
let left = this.parseAnd();
|
let left = this.parseAnd(rs);
|
||||||
while (true) {
|
while (true) {
|
||||||
if (this.test("or")) {
|
if (this.test("or")) {
|
||||||
left = this.parBinTail(left, pos, this.parseAnd, "or");
|
left = this.parBinTail(left, pos, rs, this.parseAnd, "or");
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -738,12 +738,12 @@ export class Parser {
|
|||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseAnd(): Expr {
|
private parseAnd(rs: ExprRestricts): Expr {
|
||||||
const pos = this.span();
|
const pos = this.span();
|
||||||
let left = this.parseEquality();
|
let left = this.parseEq(rs);
|
||||||
while (true) {
|
while (true) {
|
||||||
if (this.test("and")) {
|
if (this.test("and")) {
|
||||||
left = this.parBinTail(left, pos, this.parseEquality, "and");
|
left = this.parBinTail(left, pos, rs, this.parseEq, "and");
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -751,46 +751,36 @@ export class Parser {
|
|||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseEquality(): Expr {
|
private parseEq(rs: ExprRestricts): Expr {
|
||||||
const pos = this.span();
|
const pos = this.span();
|
||||||
const left = this.parseComparison();
|
const left = this.parseComparison(rs);
|
||||||
if (this.test("==")) {
|
if (this.test("==") || this.test("!=")) {
|
||||||
return this.parBinTail(left, pos, this.parseComparison, "==");
|
const op = this.current().type as BinaryType;
|
||||||
}
|
return this.parBinTail(left, pos, rs, this.parseComparison, op);
|
||||||
if (this.test("!=")) {
|
|
||||||
return this.parBinTail(left, pos, this.parseComparison, "!=");
|
|
||||||
}
|
}
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseComparison(): Expr {
|
private parseComparison(rs: ExprRestricts): Expr {
|
||||||
const pos = this.span();
|
const pos = this.span();
|
||||||
const left = this.parseAddSub();
|
const left = this.parseAddSub(rs);
|
||||||
if (this.test("<")) {
|
if (
|
||||||
return this.parBinTail(left, pos, this.parseAddSub, "<");
|
this.test("<") || this.test(">") || this.test("<=") ||
|
||||||
}
|
this.test(">=")
|
||||||
if (this.test(">")) {
|
) {
|
||||||
return this.parBinTail(left, pos, this.parseAddSub, ">");
|
const op = this.current().type as BinaryType;
|
||||||
}
|
return this.parBinTail(left, pos, rs, this.parseAddSub, op);
|
||||||
if (this.test("<=")) {
|
|
||||||
return this.parBinTail(left, pos, this.parseAddSub, "<=");
|
|
||||||
}
|
|
||||||
if (this.test(">=")) {
|
|
||||||
return this.parBinTail(left, pos, this.parseAddSub, ">=");
|
|
||||||
}
|
}
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseAddSub(): Expr {
|
private parseAddSub(rs: ExprRestricts): Expr {
|
||||||
const pos = this.span();
|
const pos = this.span();
|
||||||
let left = this.parseMulDiv();
|
let left = this.parseMulDiv(rs);
|
||||||
while (true) {
|
while (true) {
|
||||||
if (this.test("+")) {
|
if (this.test("+") || this.test("-")) {
|
||||||
left = this.parBinTail(left, pos, this.parseMulDiv, "+");
|
const op = this.current().type as BinaryType;
|
||||||
continue;
|
left = this.parBinTail(left, pos, rs, this.parseMulDiv, op);
|
||||||
}
|
|
||||||
if (this.test("-")) {
|
|
||||||
left = this.parBinTail(left, pos, this.parseMulDiv, "-");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -798,16 +788,13 @@ export class Parser {
|
|||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseMulDiv(): Expr {
|
private parseMulDiv(rs: ExprRestricts): Expr {
|
||||||
const pos = this.span();
|
const pos = this.span();
|
||||||
let left = this.parsePrefix();
|
let left = this.parsePrefix(rs);
|
||||||
while (true) {
|
while (true) {
|
||||||
if (this.test("*")) {
|
if (this.test("*") || this.test("/")) {
|
||||||
left = this.parBinTail(left, pos, this.parsePrefix, "*");
|
const op = this.current().type as BinaryType;
|
||||||
continue;
|
left = this.parBinTail(left, pos, rs, this.parsePrefix, op);
|
||||||
}
|
|
||||||
if (this.test("/")) {
|
|
||||||
left = this.parBinTail(left, pos, this.parsePrefix, "/");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -818,23 +805,24 @@ export class Parser {
|
|||||||
private parBinTail(
|
private parBinTail(
|
||||||
left: Expr,
|
left: Expr,
|
||||||
span: Span,
|
span: Span,
|
||||||
parseRight: (this: Parser) => Expr,
|
rs: ExprRestricts,
|
||||||
|
parseRight: (this: Parser, rs: ExprRestricts) => Expr,
|
||||||
binaryType: BinaryType,
|
binaryType: BinaryType,
|
||||||
): Expr {
|
): Expr {
|
||||||
this.step();
|
this.step();
|
||||||
const right = parseRight.call(this);
|
const right = parseRight.call(this, rs);
|
||||||
return this.expr(
|
return this.expr(
|
||||||
{ tag: "binary", binaryType, left, right },
|
{ tag: "binary", binaryType, left, right },
|
||||||
span,
|
span,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private parsePrefix(): Expr {
|
private parsePrefix(rs: ExprRestricts): Expr {
|
||||||
const pos = this.span();
|
const pos = this.span();
|
||||||
if (this.test("not") || this.test("-")) {
|
if (this.test("not") || this.test("-")) {
|
||||||
const unaryType = this.current().type as UnaryType;
|
const unaryType = this.current().type as UnaryType;
|
||||||
this.step();
|
this.step();
|
||||||
const expr = this.parsePrefix();
|
const expr = this.parsePrefix(rs);
|
||||||
return this.expr({ tag: "unary", unaryType, expr }, pos);
|
return this.expr({ tag: "unary", unaryType, expr }, pos);
|
||||||
}
|
}
|
||||||
if (this.test("&")) {
|
if (this.test("&")) {
|
||||||
@ -849,19 +837,19 @@ export class Parser {
|
|||||||
this.step();
|
this.step();
|
||||||
mut = true;
|
mut = true;
|
||||||
}
|
}
|
||||||
const expr = this.parsePrefix();
|
const expr = this.parsePrefix(rs);
|
||||||
return this.expr({ tag: "ref", expr, mut, refType }, pos);
|
return this.expr({ tag: "ref", expr, mut, refType }, pos);
|
||||||
}
|
}
|
||||||
if (this.test("*")) {
|
if (this.test("*")) {
|
||||||
this.step();
|
this.step();
|
||||||
const expr = this.parsePrefix();
|
const expr = this.parsePrefix(rs);
|
||||||
return this.expr({ tag: "deref", expr }, pos);
|
return this.expr({ tag: "deref", expr }, pos);
|
||||||
}
|
}
|
||||||
return this.parsePostfix();
|
return this.parsePostfix(rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private parsePostfix(): Expr {
|
private parsePostfix(rs: ExprRestricts): Expr {
|
||||||
let subject = this.parseOperand();
|
let subject = this.parseOperand(rs);
|
||||||
while (true) {
|
while (true) {
|
||||||
if (this.test(".")) {
|
if (this.test(".")) {
|
||||||
subject = this.parseFieldTail(subject);
|
subject = this.parseFieldTail(subject);
|
||||||
@ -917,14 +905,14 @@ export class Parser {
|
|||||||
return Res.Ok(this.parseExpr());
|
return Res.Ok(this.parseExpr());
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseOperand(): Expr {
|
private parseOperand(rs: ExprRestricts): Expr {
|
||||||
const pos = this.span();
|
const pos = this.span();
|
||||||
if (this.test("ident")) {
|
if (this.test("ident")) {
|
||||||
const pathRes = this.parsePath();
|
const pathRes = this.parsePath();
|
||||||
if (!pathRes.ok) {
|
if (!pathRes.ok) {
|
||||||
return this.expr({ tag: "error" }, pos);
|
return this.expr({ tag: "error" }, pos);
|
||||||
}
|
}
|
||||||
if (this.test("{")) {
|
if (this.test("{") && !(rs & ExprRestricts.NoStructs)) {
|
||||||
this.step();
|
this.step();
|
||||||
const fields = this.parseDelimitedList(
|
const fields = this.parseDelimitedList(
|
||||||
this.parseExprField,
|
this.parseExprField,
|
||||||
@ -1264,3 +1252,9 @@ export class Parser {
|
|||||||
return this.cx.ty(kind, span);
|
return this.cx.ty(kind, span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ExprRestricts = {
|
||||||
|
NoStructs: 1 << 0,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
type ExprRestricts = (typeof ExprRestricts)[keyof typeof ExprRestricts];
|
||||||
|
@ -4,12 +4,12 @@ fn add(lhs: int, rhs: int) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let a = 5;
|
let foo = 5;
|
||||||
let b = 7 + a;
|
let bar = 7 + foo;
|
||||||
|
|
||||||
if true {}
|
if foo {} else {}
|
||||||
|
|
||||||
let c = add(a, b);
|
let c = add(foo, bar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import * as ast from "@slige/ast";
|
import * as ast from "@slige/ast";
|
||||||
import { exhausted, todo } from "@slige/common";
|
import { Ctx, exhausted, todo } from "@slige/common";
|
||||||
import { Checker } from "@slige/check";
|
import { Checker } from "@slige/check";
|
||||||
import { Ty } from "@slige/ty";
|
import { Ty, tyToString } from "@slige/ty";
|
||||||
|
|
||||||
export class HirStringifyer {
|
export class HirStringifyer {
|
||||||
public constructor(
|
public constructor(
|
||||||
|
private ctx: Ctx,
|
||||||
private ch: Checker,
|
private ch: Checker,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ export class HirStringifyer {
|
|||||||
).join("\n");
|
).join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public stmt(stmt: ast.Stmt, depth = 0): string {
|
public stmt(stmt: ast.Stmt, d = 0): string {
|
||||||
const k = stmt.kind;
|
const k = stmt.kind;
|
||||||
switch (k.tag) {
|
switch (k.tag) {
|
||||||
case "error":
|
case "error":
|
||||||
@ -23,18 +24,18 @@ export class HirStringifyer {
|
|||||||
return this.item(k.item);
|
return this.item(k.item);
|
||||||
case "let":
|
case "let":
|
||||||
return `let ${this.pat(k.pat)}${
|
return `let ${this.pat(k.pat)}${
|
||||||
k.expr && ` = ${this.expr(k.expr)}` || ""
|
k.expr && ` = ${this.expr(k.expr, d)}` || ""
|
||||||
};`;
|
};`;
|
||||||
case "return":
|
case "return":
|
||||||
return `return${k.expr && ` ${this.expr(k.expr)}` || ""};`;
|
return `return${k.expr && ` ${this.expr(k.expr, d)}` || ""};`;
|
||||||
case "break":
|
case "break":
|
||||||
return `break${k.expr && ` ${this.expr(k.expr)}` || ""};`;
|
return `break${k.expr && ` ${this.expr(k.expr, d)}` || ""};`;
|
||||||
case "continue":
|
case "continue":
|
||||||
return `continue;`;
|
return `continue;`;
|
||||||
case "assign":
|
case "assign":
|
||||||
return `${this.expr(k.subject)} = ${this.expr(k.value)};`;
|
return `${this.expr(k.subject, d)} = ${this.expr(k.value, d)};`;
|
||||||
case "expr":
|
case "expr":
|
||||||
return `${this.expr(k.expr)};`;
|
return `${this.expr(k.expr, d)};`;
|
||||||
}
|
}
|
||||||
exhausted(k);
|
exhausted(k);
|
||||||
}
|
}
|
||||||
@ -76,7 +77,7 @@ export class HirStringifyer {
|
|||||||
exhausted(k);
|
exhausted(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
public expr(expr: ast.Expr, depth = 0): string {
|
public expr(expr: ast.Expr, d: number): string {
|
||||||
const k = expr.kind;
|
const k = expr.kind;
|
||||||
switch (k.tag) {
|
switch (k.tag) {
|
||||||
case "error":
|
case "error":
|
||||||
@ -102,19 +103,21 @@ export class HirStringifyer {
|
|||||||
case "index":
|
case "index":
|
||||||
return todo(k.tag);
|
return todo(k.tag);
|
||||||
case "call":
|
case "call":
|
||||||
return `${this.expr(k.expr)}(${
|
return `${this.expr(k.expr, d)}(${
|
||||||
k.args.map((arg) => this.expr(arg)).join(", ")
|
k.args.map((arg) => this.expr(arg, d)).join(", ")
|
||||||
})`;
|
})`;
|
||||||
case "unary":
|
case "unary":
|
||||||
return todo(k.tag);
|
return todo(k.tag);
|
||||||
case "binary":
|
case "binary":
|
||||||
return `${this.expr(k.left)} ${k.binaryType} ${
|
return `${this.expr(k.left, d)} ${k.binaryType} ${
|
||||||
this.expr(k.right)
|
this.expr(k.right, d)
|
||||||
}`;
|
}`;
|
||||||
case "block":
|
case "block":
|
||||||
return todo(k.tag);
|
return this.block(k.block, d);
|
||||||
case "if":
|
case "if":
|
||||||
return `if ${this.expr(k.cond)}`;
|
return `if ${this.expr(k.cond, d)} ${this.expr(k.truthy, d)}${
|
||||||
|
k.falsy && ` else ${this.expr(k.falsy, d)}` || ""
|
||||||
|
}`;
|
||||||
case "loop":
|
case "loop":
|
||||||
case "while":
|
case "while":
|
||||||
case "for":
|
case "for":
|
||||||
@ -124,7 +127,7 @@ export class HirStringifyer {
|
|||||||
exhausted(k);
|
exhausted(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
public pat(pat: ast.Pat, depth = 0): string {
|
public pat(pat: ast.Pat): string {
|
||||||
const k = pat.kind;
|
const k = pat.kind;
|
||||||
switch (k.tag) {
|
switch (k.tag) {
|
||||||
case "error":
|
case "error":
|
||||||
@ -139,41 +142,29 @@ export class HirStringifyer {
|
|||||||
exhausted(k);
|
exhausted(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
public block(block: ast.Block, depth = 0): string {
|
public block(block: ast.Block, d: number): string {
|
||||||
|
if (block.stmts.length === 0 && !block.expr) {
|
||||||
|
return "{}";
|
||||||
|
}
|
||||||
return `{\n${
|
return `{\n${
|
||||||
[
|
[
|
||||||
...block.stmts
|
...block.stmts
|
||||||
.map((stmt) => this.stmt(stmt, depth + 1)),
|
.map((stmt) => this.stmt(stmt, d + 1)),
|
||||||
...(block.expr ? [this.expr(block.expr)] : []),
|
...(block.expr ? [this.expr(block.expr, d + 1)] : []),
|
||||||
]
|
]
|
||||||
.map((str) => indent(depth + 1) + str)
|
.map((str) => indent(d + 1) + str)
|
||||||
.join("\n")
|
.join("\n")
|
||||||
}\n${indent(depth)}}`;
|
}\n${indent(d)}}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public path(path: ast.Path): string {
|
public path(path: ast.Path): string {
|
||||||
return path.segments.map((seg) => seg.ident.text).join("::");
|
return path.segments
|
||||||
|
.map((seg) => seg.ident.text)
|
||||||
|
.join("::");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ty(ty: Ty): string {
|
public ty(ty: Ty): string {
|
||||||
const k = ty.kind;
|
return tyToString(this.ctx, ty);
|
||||||
switch (k.tag) {
|
|
||||||
case "error":
|
|
||||||
return "<error>";
|
|
||||||
case "unknown":
|
|
||||||
return "<unknown>";
|
|
||||||
case "null":
|
|
||||||
return "null";
|
|
||||||
case "int":
|
|
||||||
return "int";
|
|
||||||
case "bool":
|
|
||||||
return "bool";
|
|
||||||
case "fn":
|
|
||||||
return `fn ${k.item.ident}(${
|
|
||||||
k.params.map((param) => this.ty(param)).join(", ")
|
|
||||||
}) -> ${this.ty(k.returnTy)}`;
|
|
||||||
}
|
|
||||||
exhausted(k);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,11 +10,9 @@ import {
|
|||||||
ProjElem,
|
ProjElem,
|
||||||
RVal,
|
RVal,
|
||||||
Stmt,
|
Stmt,
|
||||||
StmtKind,
|
|
||||||
Ter,
|
Ter,
|
||||||
} from "@slige/middle";
|
} from "@slige/middle";
|
||||||
import { Ctx, exhausted, IdMap, todo } from "@slige/common";
|
import { Ctx, exhausted, IdMap, todo } from "@slige/common";
|
||||||
import { Checker } from "@slige/check";
|
|
||||||
import { Ty, tyToString } from "@slige/ty";
|
import { Ty, tyToString } from "@slige/ty";
|
||||||
|
|
||||||
export class MirFnStringifyer {
|
export class MirFnStringifyer {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user