diff --git a/slige/compiler/check/checker.ts b/slige/compiler/check/checker.ts index a58f41d..ce23c1c 100644 --- a/slige/compiler/check/checker.ts +++ b/slige/compiler/check/checker.ts @@ -436,7 +436,7 @@ export class Checker { notCovered .keys() .toArray() - .map((field) => `'${field}'`) + .map((field) => `'${this.ctx.identText(field.ident)}'`) .join(", ") } not covered`, expr.span, diff --git a/slige/compiler/middle/ast_lower.ts b/slige/compiler/middle/ast_lower.ts index 66cda75..144141e 100644 --- a/slige/compiler/middle/ast_lower.ts +++ b/slige/compiler/middle/ast_lower.ts @@ -273,7 +273,9 @@ export class FnLowerer { case "group": case "array": case "repeat": + return todo(k.tag); case "struct": + return this.lowerStructExpr(expr, k); case "ref": case "deref": case "elem": @@ -322,6 +324,13 @@ export class FnLowerer { exhausted(re.kind); } + private lowerStructExpr(expr: ast.Expr, kind: ast.StructExpr): RVal { + const ty = this.ch.exprTy(expr); + const fields = kind.fields + .map((field) => this.lowerExprToOperand(field.expr)); + return { tag: "struct", ty, fields }; + } + private lowerCallExpr(expr: ast.Expr, kind: ast.CallExpr): RVal { const args = kind.args.map((arg) => this.lowerExprToOperand(arg)); const func = this.lowerExprToOperand(kind.expr); diff --git a/slige/compiler/middle/mir.ts b/slige/compiler/middle/mir.ts index 057f20c..7efd559 100644 --- a/slige/compiler/middle/mir.ts +++ b/slige/compiler/middle/mir.ts @@ -85,6 +85,7 @@ export type RVal = | { tag: "ptr"; place: Place; mut: boolean } | { tag: "binary"; binaryType: BinaryType; left: Operand; right: Operand } | { tag: "unary"; unaryType: UnaryType; operand: Operand } + | { tag: "struct"; ty: Ty; fields: Operand[] } | { tag: "call"; func: Operand; args: Operand[] }; export type BinaryType = diff --git a/slige/compiler/stringify/mir.ts b/slige/compiler/stringify/mir.ts index e5aa5a9..380a0cd 100644 --- a/slige/compiler/stringify/mir.ts +++ b/slige/compiler/stringify/mir.ts @@ -165,6 +165,26 @@ export class MirFnStringifyer { } case "unary": return todo(rval.tag); + case "struct": { + const tyk = rval.ty.kind; + if (tyk.tag === "struct") { + const datak = tyk.kind.data.kind; + if (datak.tag !== "struct") { + throw new Error(); + } + const name = tyk.item.ident.text; + const fields = rval.fields + .map((field, idx) => + `${datak.fields[idx].ident!.text}: ${ + this.operand(field) + }` + ) + .join(", "); + return `${name} { ${fields} }`; + } else { + return todo(); + } + } case "call": return `call ${this.operand(rval.func)}(${ rval.args.map((arg) => this.operand(arg)).join(", ")