progress on arrays and slices
All checks were successful
Check / Explore-Gitea-Actions (push) Successful in 8s
All checks were successful
Check / Explore-Gitea-Actions (push) Successful in 8s
This commit is contained in:
parent
8b10163805
commit
54ee879b45
@ -93,9 +93,9 @@ export class Node {
|
||||
case "ArrayExpr":
|
||||
return visit(...k.values);
|
||||
case "IndexExpr":
|
||||
return visit(k.expr, k.arg);
|
||||
return visit(k.value, k.arg);
|
||||
case "CallExpr":
|
||||
return visit(k.expr, ...k.args);
|
||||
return visit(k.value, ...k.args);
|
||||
case "UnaryExpr":
|
||||
return visit(k.expr);
|
||||
case "BinaryExpr":
|
||||
@ -136,8 +136,8 @@ export type NodeKind =
|
||||
| { tag: "IdentExpr"; ident: string }
|
||||
| { tag: "IntExpr"; value: number }
|
||||
| { tag: "ArrayExpr"; values: Node[] }
|
||||
| { tag: "IndexExpr"; expr: Node; arg: Node }
|
||||
| { tag: "CallExpr"; expr: Node; args: Node[] }
|
||||
| { tag: "IndexExpr"; value: Node; arg: Node }
|
||||
| { tag: "CallExpr"; value: Node; args: Node[] }
|
||||
| { tag: "UnaryExpr"; op: UnaryOp; expr: Node; tok: string }
|
||||
| { tag: "BinaryExpr"; op: BinaryOp; left: Node; right: Node; tok: string }
|
||||
| {
|
||||
|
||||
@ -15,6 +15,24 @@ export class Tys {
|
||||
this.checker = new Checker(this, this.syms, this.reporter);
|
||||
}
|
||||
|
||||
fnStmt(node: ast.NodeWithKind<"FnStmt">): Ty {
|
||||
if (this.nodeTys.has(node.id)) {
|
||||
return this.nodeTys.get(node.id)!;
|
||||
}
|
||||
const ty = this.checker.checkFnStmt(node);
|
||||
this.nodeTys.set(node.id, ty);
|
||||
return ty;
|
||||
}
|
||||
|
||||
place(node: ast.Node): Ty {
|
||||
if (this.nodeTys.has(node.id)) {
|
||||
return this.nodeTys.get(node.id)!;
|
||||
}
|
||||
const ty = this.checker.checkExpr(node);
|
||||
this.nodeTys.set(node.id, ty);
|
||||
return ty;
|
||||
}
|
||||
|
||||
expr(node: ast.Node): Ty {
|
||||
if (this.nodeTys.has(node.id)) {
|
||||
return this.nodeTys.get(node.id)!;
|
||||
@ -32,13 +50,44 @@ class Checker {
|
||||
private reporter: FileReporter,
|
||||
) {}
|
||||
|
||||
checkFnStmt(stmt: ast.NodeWithKind<"FnStmt">): Ty {
|
||||
const k = stmt.kind;
|
||||
|
||||
const params = k.params.map((param) => this.tys.expr(param));
|
||||
const retTy = k.retTy ? this.tys.expr(k.retTy) : Ty.Void;
|
||||
|
||||
k.body.visit({
|
||||
visit: (node) => {
|
||||
if (node.is("ReturnStmt")) {
|
||||
const ty = node.kind.expr
|
||||
? this.tys.expr(node.kind.expr)
|
||||
: Ty.Void;
|
||||
if (!ty.compatibleWith(retTy)) {
|
||||
this.error(
|
||||
node.loc,
|
||||
`type '${ty.pretty()}' not compatible with return type '${retTy.pretty()}'`,
|
||||
);
|
||||
this.info(
|
||||
stmt.kind.retTy?.loc ?? stmt.loc,
|
||||
`return type '${retTy}' defined here`,
|
||||
);
|
||||
this.fail();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const ty = Ty.create("Fn", { params, retTy });
|
||||
return Ty.create("FnStmt", { stmt, ty });
|
||||
}
|
||||
|
||||
checkPlace(node: ast.Node): Ty {
|
||||
return this.checkExpr(node);
|
||||
}
|
||||
|
||||
checkExpr(node: ast.Node): Ty {
|
||||
const k = node.kind;
|
||||
|
||||
if (node.is("FnStmt")) {
|
||||
return this.checkFnStmt(node);
|
||||
}
|
||||
|
||||
if (node.is("Param")) {
|
||||
const sym = this.syms.get(node);
|
||||
|
||||
@ -68,7 +117,7 @@ class Checker {
|
||||
if (node.is("IdentExpr")) {
|
||||
const sym = this.syms.get(node);
|
||||
if (sym.tag === "Fn") {
|
||||
return this.tys.expr(sym.stmt);
|
||||
return this.tys.fnStmt(sym.stmt);
|
||||
}
|
||||
if (sym.tag === "Bool") {
|
||||
return Ty.Bool;
|
||||
@ -108,7 +157,7 @@ class Checker {
|
||||
}
|
||||
|
||||
if (node.is("IndexExpr")) {
|
||||
const exprTy = this.tys.expr(node.kind.expr);
|
||||
const exprTy = this.tys.expr(node.kind.value);
|
||||
const argTy = this.tys.expr(node.kind.arg);
|
||||
if (
|
||||
(exprTy.is("Array") || exprTy.is("Slice")) &&
|
||||
@ -243,39 +292,8 @@ class Checker {
|
||||
throw new Error(`'${k.tag}' not unhandled`);
|
||||
}
|
||||
|
||||
private checkFnStmt(stmt: ast.NodeWithKind<"FnStmt">): Ty {
|
||||
const k = stmt.kind;
|
||||
|
||||
const params = k.params.map((param) => this.tys.expr(param));
|
||||
const retTy = k.retTy ? this.tys.expr(k.retTy) : Ty.Void;
|
||||
|
||||
k.body.visit({
|
||||
visit: (node) => {
|
||||
if (node.is("ReturnStmt")) {
|
||||
const ty = node.kind.expr
|
||||
? this.tys.expr(node.kind.expr)
|
||||
: Ty.Void;
|
||||
if (!ty.compatibleWith(retTy)) {
|
||||
this.error(
|
||||
node.loc,
|
||||
`type '${ty.pretty()}' not compatible with return type '${retTy.pretty()}'`,
|
||||
);
|
||||
this.info(
|
||||
stmt.kind.retTy?.loc ?? stmt.loc,
|
||||
`return type '${retTy}' defined here`,
|
||||
);
|
||||
this.fail();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const ty = Ty.create("Fn", { params, retTy });
|
||||
return Ty.create("FnStmt", { stmt, ty });
|
||||
}
|
||||
|
||||
private checkCall(node: ast.NodeWithKind<"CallExpr">): Ty {
|
||||
const calleeTy = this.tys.expr(node.kind.expr);
|
||||
const calleeTy = this.tys.expr(node.kind.value);
|
||||
|
||||
const callableTy = calleeTy.is("Fn")
|
||||
? calleeTy
|
||||
|
||||
@ -239,7 +239,7 @@ export class Parser {
|
||||
} else if (this.eat("[")) {
|
||||
const arg = this.parseExpr();
|
||||
this.mustEat("]");
|
||||
expr = ast.Node.create(loc, "IndexExpr", { expr, arg });
|
||||
expr = ast.Node.create(loc, "IndexExpr", { value: expr, arg });
|
||||
} else if (this.eat("(")) {
|
||||
const args: ast.Node[] = [];
|
||||
if (!this.test(")")) {
|
||||
@ -252,7 +252,7 @@ export class Parser {
|
||||
}
|
||||
}
|
||||
this.mustEat(")");
|
||||
expr = ast.Node.create(loc, "CallExpr", { expr, args });
|
||||
expr = ast.Node.create(loc, "CallExpr", { value: expr, args });
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4,14 +4,14 @@ import { builtins } from "./builtins.ts";
|
||||
|
||||
export class Syms {
|
||||
constructor(
|
||||
private resols: Map<number, Sym>,
|
||||
private symMap: Map<number, Sym>,
|
||||
) {}
|
||||
|
||||
get(node: ast.Node): Sym {
|
||||
if (!this.resols.has(node.id)) {
|
||||
if (!this.symMap.has(node.id)) {
|
||||
throw new Error(`'${node.kind.tag}' not resolved`);
|
||||
}
|
||||
return this.resols.get(node.id)!;
|
||||
return this.symMap.get(node.id)!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ export class MiddleLowerer {
|
||||
private fns = new Map<number, Fn>();
|
||||
|
||||
constructor(
|
||||
private resols: Syms,
|
||||
private syms: Syms,
|
||||
private tys: Tys,
|
||||
) {}
|
||||
|
||||
@ -15,7 +15,7 @@ export class MiddleLowerer {
|
||||
if (this.fns.has(stmt.id)) {
|
||||
return this.fns.get(stmt.id)!;
|
||||
}
|
||||
const fn = new FnLowerer(this, this.resols, this.tys, stmt).lower();
|
||||
const fn = new FnLowerer(this, this.syms, this.tys, stmt).lower();
|
||||
this.fns.set(stmt.id, fn);
|
||||
return fn;
|
||||
}
|
||||
@ -28,13 +28,13 @@ class FnLowerer {
|
||||
|
||||
constructor(
|
||||
private lowerer: MiddleLowerer,
|
||||
private resols: Syms,
|
||||
private syms: Syms,
|
||||
private tys: Tys,
|
||||
private stmt: ast.FnStmt,
|
||||
) {}
|
||||
|
||||
lower(): Fn {
|
||||
const ty = this.tys.expr(this.stmt);
|
||||
const ty = this.tys.fnStmt(this.stmt);
|
||||
this.lowerBlock(this.stmt.kind.body.as("Block"));
|
||||
this.pushInst(Ty.Void, "Return", { source: this.makeVoid() });
|
||||
this.bbs[0].insts.unshift(...this.allocs);
|
||||
@ -51,7 +51,10 @@ class FnLowerer {
|
||||
if (stmt.is("LetStmt")) {
|
||||
const ty = this.tys.expr(stmt.kind.param);
|
||||
const expr = this.lowerExpr(stmt.kind.expr);
|
||||
const local = new Inst(Ty.create("Ptr", { ty }), { tag: "Alloca" });
|
||||
const local = new Inst(
|
||||
Ty.create("PtrMut", { ty }),
|
||||
{ tag: "Alloca" },
|
||||
);
|
||||
this.allocs.push(local);
|
||||
this.pushInst(Ty.Void, "Store", {
|
||||
target: local,
|
||||
@ -119,8 +122,9 @@ class FnLowerer {
|
||||
}
|
||||
|
||||
private lowerPlace(place: ast.Node): Inst {
|
||||
const ty = this.tys.place(place);
|
||||
if (place.is("IdentExpr")) {
|
||||
const sym = this.resols.get(place);
|
||||
const sym = this.syms.get(place);
|
||||
if (sym.tag === "Let") {
|
||||
const local = this.localMap.get(sym.param.id);
|
||||
if (!local) {
|
||||
@ -128,27 +132,36 @@ class FnLowerer {
|
||||
}
|
||||
return local;
|
||||
}
|
||||
if (sym.tag === "FnParam") {
|
||||
return this.lowerExpr(place);
|
||||
}
|
||||
throw new Error(`'${sym.tag}' not handled`);
|
||||
}
|
||||
|
||||
if (place.is("UnaryExpr") && place.kind.op === "Deref") {
|
||||
return this.lowerExpr(place.kind.expr);
|
||||
const source = this.lowerPlace(place.kind.expr);
|
||||
return this.pushInst(
|
||||
Ty.create("PtrMut", { ty }),
|
||||
"Load",
|
||||
{ source },
|
||||
);
|
||||
}
|
||||
|
||||
if (place.is("IndexExpr")) {
|
||||
const exprTy = this.tys.expr(place.kind.expr);
|
||||
if (!exprTy.is("Array") && !exprTy.is("Slice")) {
|
||||
throw new Error(exprTy.pretty());
|
||||
}
|
||||
const value = place.kind.value;
|
||||
const valueTy = this.tys.expr(value);
|
||||
const arg = place.kind.arg;
|
||||
const argTy = this.tys.expr(arg);
|
||||
const exprInst = this.lowerExpr(place.kind.expr);
|
||||
if (!valueTy.is("Array") && !valueTy.is("Slice")) {
|
||||
throw new Error();
|
||||
}
|
||||
const valueInst = this.lowerPlace(place.kind.value);
|
||||
if (argTy.is("Int")) {
|
||||
const argInst = this.lowerExpr(arg);
|
||||
return this.pushInst(
|
||||
Ty.create("PtrMut", { ty: exprTy.kind.ty }),
|
||||
Ty.create("PtrMut", { ty: valueTy.kind.ty }),
|
||||
"Index",
|
||||
{ value: exprInst, arg: argInst },
|
||||
{ base: valueInst, offset: argInst },
|
||||
);
|
||||
}
|
||||
if (argTy.is("Range")) {
|
||||
@ -161,10 +174,10 @@ class FnLowerer {
|
||||
this.lowerExpr(arg.kind.end);
|
||||
return this.pushInst(
|
||||
Ty.create("PtrMut", {
|
||||
ty: Ty.create("Slice", { ty: exprTy.kind.ty }),
|
||||
ty: Ty.create("Slice", { ty: valueTy.kind.ty }),
|
||||
}),
|
||||
"Slice",
|
||||
{ value: exprInst, begin, end },
|
||||
{ value: valueInst, begin, end },
|
||||
);
|
||||
}
|
||||
throw new Error(
|
||||
@ -176,8 +189,9 @@ class FnLowerer {
|
||||
}
|
||||
|
||||
private lowerExpr(expr: ast.Node): Inst {
|
||||
const ty = this.tys.expr(expr);
|
||||
if (expr.is("IdentExpr")) {
|
||||
const sym = this.resols.get(expr);
|
||||
const sym = this.syms.get(expr);
|
||||
if (sym.tag === "Fn") {
|
||||
const fn = this.lowerer.lowerFn(sym.stmt);
|
||||
return this.pushInst(fn.ty, "Fn", { fn });
|
||||
@ -190,11 +204,8 @@ class FnLowerer {
|
||||
throw new Error("handle elsewhere");
|
||||
}
|
||||
if (sym.tag === "Let") {
|
||||
const local = this.localMap.get(sym.param.id);
|
||||
if (!local) {
|
||||
throw new Error();
|
||||
}
|
||||
return this.pushInst(local.ty, "Load", { source: local });
|
||||
const source = this.lowerPlace(expr);
|
||||
return this.pushInst(ty, "Load", { source });
|
||||
}
|
||||
if (sym.tag === "Bool") {
|
||||
return this.pushInst(Ty.Bool, "Bool", { value: sym.value });
|
||||
@ -211,18 +222,16 @@ class FnLowerer {
|
||||
return this.pushInst(ty, "Array", { values });
|
||||
}
|
||||
if (expr.is("IndexExpr")) {
|
||||
const ty = this.tys.expr(expr.kind.expr);
|
||||
const arg = this.lowerExpr(expr.kind.arg);
|
||||
const value = this.lowerExpr(expr.kind.expr);
|
||||
return this.pushInst(ty, "Index", { value, arg });
|
||||
const source = this.lowerPlace(expr);
|
||||
return this.pushInst(ty, "Load", { source });
|
||||
}
|
||||
if (expr.is("CallExpr")) {
|
||||
const ty = this.tys.expr(expr);
|
||||
const args = expr.kind.args
|
||||
.map((arg) => this.lowerExpr(arg));
|
||||
|
||||
if (expr.kind.expr.is("IdentExpr")) {
|
||||
const sym = this.resols.get(expr.kind.expr);
|
||||
if (expr.kind.value.is("IdentExpr")) {
|
||||
const sym = this.syms.get(expr.kind.value);
|
||||
if (sym.tag === "Builtin") {
|
||||
if (sym.id === "__add") {
|
||||
const [left, right] = args;
|
||||
@ -235,7 +244,7 @@ class FnLowerer {
|
||||
}
|
||||
}
|
||||
|
||||
const callee = this.lowerExpr(expr.kind.expr);
|
||||
const callee = this.lowerExpr(expr.kind.value);
|
||||
return this.pushInst(ty, "Call", { callee, args });
|
||||
}
|
||||
if (expr.is("UnaryExpr")) {
|
||||
@ -260,7 +269,7 @@ class FnLowerer {
|
||||
if (expr.kind.op === "Ref" || expr.kind.op === "RefMut") {
|
||||
const place = expr.kind.expr;
|
||||
if (place.is("IdentExpr")) {
|
||||
const sym = this.resols.get(place);
|
||||
const sym = this.syms.get(place);
|
||||
if (sym.tag === "Let") {
|
||||
const local = this.localMap.get(sym.param.id);
|
||||
if (!local) {
|
||||
|
||||
@ -128,7 +128,7 @@ export class Inst {
|
||||
case "Param":
|
||||
return `${k.idx}`;
|
||||
case "Index":
|
||||
return `${r(k.value)} [${r(k.arg)}]`;
|
||||
return `${r(k.base)} &[${r(k.offset)}]`;
|
||||
case "Slice":
|
||||
return `${r(k.value)} [${k.begin ? r(k.begin) : ""}..${
|
||||
k.end ? r(k.end) : ""
|
||||
@ -144,7 +144,7 @@ export class Inst {
|
||||
case "Jump":
|
||||
return `bb${cx.bbId(k.target)}`;
|
||||
case "Branch":
|
||||
return `if ${r(k.cond)} then bb${cx.bbId(k.truthy)} else bb${
|
||||
return `if ${r(k.cond)}: bb${cx.bbId(k.truthy)}, else: bb${
|
||||
cx.bbId(k.falsy)
|
||||
}`;
|
||||
case "Return":
|
||||
@ -184,7 +184,7 @@ export type InstKind =
|
||||
| { tag: "Array"; values: Inst[] }
|
||||
| { tag: "Fn"; fn: Fn }
|
||||
| { tag: "Param"; idx: number }
|
||||
| { tag: "Index"; value: Inst; arg: Inst }
|
||||
| { tag: "Index"; base: Inst; offset: Inst }
|
||||
| { tag: "Slice"; value: Inst; begin: Inst | null; end: Inst | null }
|
||||
| { tag: "Call"; callee: Inst; args: Inst[] }
|
||||
| { tag: "Alloca" }
|
||||
|
||||
@ -13,13 +13,14 @@ export class FnInterpreter {
|
||||
}
|
||||
|
||||
eval(): Val {
|
||||
const cx = new mir.PrettyCx();
|
||||
while (this.instIdx < this.bb.insts.length) {
|
||||
const inst = this.bb.insts[this.instIdx];
|
||||
this.instIdx += 1;
|
||||
|
||||
// console.log(
|
||||
// console.log(poin
|
||||
// `[${this.instIdx.toString().padStart(2, " ")}] ${
|
||||
// inst.pretty(new mir.PrettyCx())
|
||||
// inst.pretty(cx)
|
||||
// }`,
|
||||
// );
|
||||
|
||||
@ -49,39 +50,70 @@ export class FnInterpreter {
|
||||
case "Param":
|
||||
this.regs.set(inst, this.args[k.idx]);
|
||||
break;
|
||||
// case "Index": {
|
||||
// const idx = this.regs.get(k.arg)!;
|
||||
// if (idx.kind.tag !== "Int") {
|
||||
// throw new Error();
|
||||
// }
|
||||
// const value = this.regs.get(k.value)!;
|
||||
// if (value.kind.tag === "Array") {
|
||||
// if (idx.kind.value >= value.kind.values.length) {
|
||||
// throw new Error();
|
||||
// }
|
||||
// this.regs.set(inst, value.kind.values[idx.kind.value]);
|
||||
// } else if (value.kind.tag === "Slice") {
|
||||
// if (value.kind.value.kind.tag !== "Array") {
|
||||
// throw new Error();
|
||||
// }
|
||||
// const values = value.kind.value.kind.values;
|
||||
// const begin = value.kind.value;
|
||||
// const end = value.kind.end;
|
||||
// if (
|
||||
// begin.kind.tag !== "Int" || end.kind.tag !== "Int"
|
||||
// ) {
|
||||
// throw new Error();
|
||||
// }
|
||||
// if (
|
||||
// begin.kind.value + idx.kind.value < 0 ||
|
||||
// end.kind.value + idx.kind.value >= values.length
|
||||
// ) {
|
||||
// throw new Error();
|
||||
// }
|
||||
// this.regs.set(
|
||||
// inst,
|
||||
// values[begin.kind.value + idx.kind.value],
|
||||
// );
|
||||
// } else {
|
||||
// throw new Error();
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
case "Index": {
|
||||
const idx = this.regs.get(k.arg)!;
|
||||
if (idx.kind.tag !== "Int") {
|
||||
const offset = this.regs.get(k.offset)!;
|
||||
if (offset.kind.tag !== "Int") {
|
||||
throw new Error();
|
||||
}
|
||||
const value = this.regs.get(k.value)!;
|
||||
if (value.kind.tag === "Array") {
|
||||
if (idx.kind.value >= value.kind.values.length) {
|
||||
const base = this.regs.get(k.base)!;
|
||||
if (base.kind.tag === "Ptr") {
|
||||
const array = base.kind.value;
|
||||
if (array.kind.tag !== "Array") {
|
||||
console.log({ array });
|
||||
throw new Error();
|
||||
}
|
||||
this.regs.set(inst, value.kind.values[idx.kind.value]);
|
||||
} else if (value.kind.tag === "Slice") {
|
||||
if (value.kind.value.kind.tag !== "Array") {
|
||||
throw new Error();
|
||||
}
|
||||
const values = value.kind.value.kind.values;
|
||||
const begin = value.kind.value;
|
||||
const end = value.kind.end;
|
||||
if (
|
||||
begin.kind.tag !== "Int" || end.kind.tag !== "Int"
|
||||
) {
|
||||
throw new Error();
|
||||
}
|
||||
if (
|
||||
begin.kind.value + idx.kind.value < 0 ||
|
||||
end.kind.value + idx.kind.value >= values.length
|
||||
) {
|
||||
if (offset.kind.value >= array.kind.values.length) {
|
||||
throw new Error();
|
||||
}
|
||||
this.regs.set(
|
||||
inst,
|
||||
values[begin.kind.value + idx.kind.value],
|
||||
new Val({
|
||||
tag: "ArrayElemPtr",
|
||||
values: array.kind.values,
|
||||
idx: offset.kind.value,
|
||||
mutable: base.kind.mutable,
|
||||
}),
|
||||
);
|
||||
} else if (base.kind.tag === "Slice") {
|
||||
throw new Error();
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
@ -96,7 +128,11 @@ export class FnInterpreter {
|
||||
) {
|
||||
throw new Error();
|
||||
}
|
||||
const value = this.regs.get(k.value)!;
|
||||
const ptr = this.regs.get(k.value)!;
|
||||
if (ptr.kind.tag !== "Ptr") {
|
||||
throw new Error();
|
||||
}
|
||||
const value = ptr.kind.value;
|
||||
if (value.kind.tag !== "Array") {
|
||||
throw new Error();
|
||||
}
|
||||
@ -150,19 +186,29 @@ export class FnInterpreter {
|
||||
}
|
||||
case "Load": {
|
||||
const source = this.regs.get(k.source)!;
|
||||
if (source.kind.tag !== "Ptr") {
|
||||
if (source.kind.tag === "Ptr") {
|
||||
this.regs.set(inst, source.kind.value);
|
||||
} else if (source.kind.tag === "ArrayElemPtr") {
|
||||
this.regs.set(
|
||||
inst,
|
||||
source.kind.values[source.kind.idx],
|
||||
);
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
this.regs.set(inst, source.kind.value);
|
||||
break;
|
||||
}
|
||||
case "Store": {
|
||||
const target = this.regs.get(k.target)!;
|
||||
if (target.kind.tag !== "Ptr") {
|
||||
if (target.kind.tag === "Ptr") {
|
||||
const source = this.regs.get(k.source)!;
|
||||
target.kind.value = source;
|
||||
} else if (target.kind.tag === "ArrayElemPtr") {
|
||||
const source = this.regs.get(k.source)!;
|
||||
target.kind.values[target.kind.idx] = source;
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
const source = this.regs.get(k.source)!;
|
||||
target.kind.value = source;
|
||||
break;
|
||||
}
|
||||
case "Jump": {
|
||||
@ -309,6 +355,7 @@ class Val {
|
||||
case "Bool":
|
||||
return `${k.value}`;
|
||||
case "Ptr":
|
||||
case "ArrayElemPtr":
|
||||
return `<pointer>`;
|
||||
case "Slice":
|
||||
if (k.value.kind.tag !== "Array") {
|
||||
@ -340,6 +387,7 @@ type ValKind =
|
||||
| { tag: "Int"; value: number }
|
||||
| { tag: "Bool"; value: boolean }
|
||||
| { tag: "Ptr"; mutable: boolean; value: Val }
|
||||
| { tag: "ArrayElemPtr"; mutable: boolean; values: Val[]; idx: number }
|
||||
| { tag: "Slice"; value: Val; begin: Val; end: Val }
|
||||
| { tag: "Array"; values: Val[] }
|
||||
| { tag: "Fn"; fn: mir.Fn };
|
||||
|
||||
@ -3,25 +3,20 @@ fn main()
|
||||
{
|
||||
let array: [int; 3] = [1, 2, 3];
|
||||
|
||||
// let a = 4;
|
||||
// let b = a;
|
||||
// array[0] = a;
|
||||
// print_int(array[0]);
|
||||
let elem: int = array[0];
|
||||
// expect: 1
|
||||
print_int(elem);
|
||||
|
||||
// let elem: int = array[0];
|
||||
// // e xpect: 1
|
||||
// print_int(elem);
|
||||
//
|
||||
// let ptr_to_array: *[int; 3] = &array;
|
||||
let ptr_to_array: *[int; 3] = &array;
|
||||
// expect: 2
|
||||
print_int(ptr_to_array.*[1]);
|
||||
|
||||
let slice: *[int] = &array[..];
|
||||
// // e xpect: 2
|
||||
// print_int(ptr_to_array.*[1]);
|
||||
|
||||
// let slice: *[int] = &array[..];
|
||||
// e xpect: 2
|
||||
// print_int(slice.*[2]);
|
||||
|
||||
// let slice_1: *mut [int] = &mut array[1..3];
|
||||
// slice_1.*[0] = 4;
|
||||
// let slice_mut: *mut [int] = &mut array[1..3];
|
||||
// slice_mut.*[0] = 4;
|
||||
// // e xpect: 4
|
||||
// print_int(array[1]);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user