pointers and arrays work
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
d2a49f3be0
commit
9691fc38cb
@ -28,7 +28,7 @@ export class Tys {
|
|||||||
if (this.nodeTys.has(node.id)) {
|
if (this.nodeTys.has(node.id)) {
|
||||||
return this.nodeTys.get(node.id)!;
|
return this.nodeTys.get(node.id)!;
|
||||||
}
|
}
|
||||||
const ty = this.checker.checkExpr(node);
|
const ty = this.checker.checkPlace(node);
|
||||||
this.nodeTys.set(node.id, ty);
|
this.nodeTys.set(node.id, ty);
|
||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
@ -82,6 +82,14 @@ class Checker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkPlace(node: ast.Node): Ty {
|
checkPlace(node: ast.Node): Ty {
|
||||||
|
if (node.is("UnaryExpr")) {
|
||||||
|
if (node.kind.op === "Deref") {
|
||||||
|
const exprTy = this.checkPlace(node.kind.expr);
|
||||||
|
if (exprTy.is("Ptr") || exprTy.is("PtrMut")) {
|
||||||
|
return exprTy.kind.ty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return this.checkExpr(node);
|
return this.checkExpr(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +165,7 @@ class Checker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (node.is("IndexExpr")) {
|
if (node.is("IndexExpr")) {
|
||||||
const exprTy = this.tys.expr(node.kind.value);
|
const exprTy = this.tys.place(node.kind.value);
|
||||||
const argTy = this.tys.expr(node.kind.arg);
|
const argTy = this.tys.expr(node.kind.arg);
|
||||||
if (
|
if (
|
||||||
(exprTy.is("Array") || exprTy.is("Slice")) &&
|
(exprTy.is("Array") || exprTy.is("Slice")) &&
|
||||||
@ -198,6 +206,13 @@ class Checker {
|
|||||||
}
|
}
|
||||||
if (node.kind.op === "Deref") {
|
if (node.kind.op === "Deref") {
|
||||||
if (exprTy.is("Ptr") || exprTy.is("PtrMut")) {
|
if (exprTy.is("Ptr") || exprTy.is("PtrMut")) {
|
||||||
|
if (!exprTy.kind.ty.isSized()) {
|
||||||
|
this.error(
|
||||||
|
node.loc,
|
||||||
|
`cannot dereference unsized type '${exprTy.kind.ty.pretty()}' in an expression`,
|
||||||
|
);
|
||||||
|
this.fail();
|
||||||
|
}
|
||||||
return exprTy.kind.ty;
|
return exprTy.kind.ty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export class Parser {
|
|||||||
private text: string,
|
private text: string,
|
||||||
private reporter: FileReporter,
|
private reporter: FileReporter,
|
||||||
) {
|
) {
|
||||||
this.toks = tokenize(text);
|
this.toks = tokenize(this.text, this.reporter);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseFile(): ast.Node {
|
parseFile(): ast.Node {
|
||||||
@ -402,7 +402,7 @@ const keywordPattern =
|
|||||||
const operatorPattern2 =
|
const operatorPattern2 =
|
||||||
/((?:\->)|(?:==)|(?:!=)|(?:<=)|(?:>=)|(?:<<)|(?:>>)|(?:\.\*)|(?:\.\.)|(?:\.\.=)|[\n\(\)\{\}\[\]\,\.\;\:\!\=\<\>\&\^\|\+\-\*\/\%])/g;
|
/((?:\->)|(?:==)|(?:!=)|(?:<=)|(?:>=)|(?:<<)|(?:>>)|(?:\.\*)|(?:\.\.)|(?:\.\.=)|[\n\(\)\{\}\[\]\,\.\;\:\!\=\<\>\&\^\|\+\-\*\/\%])/g;
|
||||||
|
|
||||||
export function tokenize(text: string): Tok[] {
|
export function tokenize(text: string, reporter: FileReporter): Tok[] {
|
||||||
return new Lexer()
|
return new Lexer()
|
||||||
.add(/[ \t\r\n]+/, (_) => null)
|
.add(/[ \t\r\n]+/, (_) => null)
|
||||||
.add(/\/\/[^\n]*/, (_) => null)
|
.add(/\/\/[^\n]*/, (_) => null)
|
||||||
@ -415,6 +415,8 @@ export function tokenize(text: string): Tok[] {
|
|||||||
return { type: "int", value, loc };
|
return { type: "int", value, loc };
|
||||||
})
|
})
|
||||||
.add(/./, (loc, value) => {
|
.add(/./, (loc, value) => {
|
||||||
|
const escapedChar = JSON.stringify(value[0]).slice(1, -1);
|
||||||
|
reporter.error(loc, `illegal character '${escapedChar}'`);
|
||||||
return null;
|
return null;
|
||||||
})
|
})
|
||||||
.lex(text);
|
.lex(text);
|
||||||
|
|||||||
53
src/main.ts
53
src/main.ts
@ -2,6 +2,7 @@ import * as ast from "./ast.ts";
|
|||||||
import { Reporter } from "./diagnostics.ts";
|
import { Reporter } from "./diagnostics.ts";
|
||||||
import * as front from "./front/mod.ts";
|
import * as front from "./front/mod.ts";
|
||||||
import * as middle from "./middle.ts";
|
import * as middle from "./middle.ts";
|
||||||
|
import * as mir from "./mir.ts";
|
||||||
import { FnInterpreter } from "./mir_interpreter.ts";
|
import { FnInterpreter } from "./mir_interpreter.ts";
|
||||||
|
|
||||||
const reporter = new Reporter();
|
const reporter = new Reporter();
|
||||||
@ -39,8 +40,56 @@ if (!mainFn) {
|
|||||||
const m = new middle.MiddleLowerer(syms, tys);
|
const m = new middle.MiddleLowerer(syms, tys);
|
||||||
const mainMiddleFn = m.lowerFn(mainFn);
|
const mainMiddleFn = m.lowerFn(mainFn);
|
||||||
|
|
||||||
if (!Deno.args.includes("--test")) {
|
function printMirFn(fn: mir.Fn) {
|
||||||
console.log(mainMiddleFn.pretty());
|
const pretty = fn.pretty();
|
||||||
|
const [lines, colors] = pretty
|
||||||
|
.split("\n")
|
||||||
|
.map<[string, string[]]>((line) => [line, []])
|
||||||
|
.map<[string, string[]]>(([line, colors]) => {
|
||||||
|
line = line.replace(/%(\d+)/g, "__%$1__");
|
||||||
|
if (/^\s*__%\d+__ \(.*?\) =/.test(line)) {
|
||||||
|
line = line.replace(
|
||||||
|
/__%(\d+)__ \((.*?)\) =/g,
|
||||||
|
"%c%$1 %c($2)%c =",
|
||||||
|
);
|
||||||
|
colors.push("color: lightblue;", "color: gray;", "");
|
||||||
|
}
|
||||||
|
if (/[A-Z][a-zA-Z]+/.test(line)) {
|
||||||
|
line = line.replace(/([A-Z][a-zA-Z]+)/, "%c$1%c");
|
||||||
|
colors.push("color: red;", "");
|
||||||
|
}
|
||||||
|
if (/\bptr\b/.test(line)) {
|
||||||
|
line = line.replace(/\b(ptr)\b/, "%c$1%c");
|
||||||
|
colors.push("color: gray;", "");
|
||||||
|
}
|
||||||
|
while (/__%\d+__/.test(line)) {
|
||||||
|
line = line.replace(/__%(\d+)__/, "%c%$1%c");
|
||||||
|
colors.push("color: lightblue;", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
return [line, colors];
|
||||||
|
})
|
||||||
|
.reduce<[string[], string[]]>(
|
||||||
|
([linesAcc, colorsAcc], [line, colors]) => {
|
||||||
|
linesAcc.push(line);
|
||||||
|
colorsAcc.push(...colors);
|
||||||
|
return [linesAcc, colorsAcc];
|
||||||
|
},
|
||||||
|
[[], []],
|
||||||
|
);
|
||||||
|
const text = lines.join("\n");
|
||||||
|
console.log(text + "%c", ...colors, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Deno.args.includes("--print-mir")) {
|
||||||
|
for (const fn of m.allFns()) {
|
||||||
|
printMirFn(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reporter.ok()) {
|
||||||
|
reporter.printAll();
|
||||||
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
new FnInterpreter(mainMiddleFn, []).eval();
|
new FnInterpreter(mainMiddleFn, []).eval();
|
||||||
|
|||||||
@ -19,6 +19,10 @@ export class MiddleLowerer {
|
|||||||
this.fns.set(stmt.id, fn);
|
this.fns.set(stmt.id, fn);
|
||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allFns(): Fn[] {
|
||||||
|
return this.fns.values().toArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FnLowerer {
|
class FnLowerer {
|
||||||
@ -50,19 +54,7 @@ class FnLowerer {
|
|||||||
|
|
||||||
private lowerStmt(stmt: ast.Node) {
|
private lowerStmt(stmt: ast.Node) {
|
||||||
if (stmt.is("LetStmt")) {
|
if (stmt.is("LetStmt")) {
|
||||||
const ty = this.tys.expr(stmt.kind.param);
|
return this.lowerLetStmt(stmt);
|
||||||
const expr = this.lowerExpr(stmt.kind.expr);
|
|
||||||
const local = new Inst(
|
|
||||||
Ty.create("PtrMut", { ty }),
|
|
||||||
{ tag: "Alloca" },
|
|
||||||
);
|
|
||||||
this.allocs.push(local);
|
|
||||||
this.pushInst(Ty.Void, "Store", {
|
|
||||||
target: local,
|
|
||||||
source: expr,
|
|
||||||
});
|
|
||||||
this.localMap.set(stmt.kind.param.id, local);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (stmt.is("ReturnStmt")) {
|
if (stmt.is("ReturnStmt")) {
|
||||||
const source = stmt.kind.expr
|
const source = stmt.kind.expr
|
||||||
@ -159,10 +151,7 @@ class FnLowerer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (stmt.is("AssignStmt")) {
|
if (stmt.is("AssignStmt")) {
|
||||||
const source = this.lowerExpr(stmt.kind.expr);
|
return this.lowerAssignStmt(stmt);
|
||||||
const target = this.lowerPlace(stmt.kind.place);
|
|
||||||
this.pushInst(Ty.Void, "Store", { target, source });
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (stmt.is("ExprStmt")) {
|
if (stmt.is("ExprStmt")) {
|
||||||
this.lowerExpr(stmt.kind.expr);
|
this.lowerExpr(stmt.kind.expr);
|
||||||
@ -171,7 +160,30 @@ class FnLowerer {
|
|||||||
throw new Error(`'${stmt.kind.tag}' not handled`);
|
throw new Error(`'${stmt.kind.tag}' not handled`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private lowerLetStmt(stmt: ast.NodeWithKind<"LetStmt">) {
|
||||||
|
const ty = this.tys.expr(stmt.kind.param);
|
||||||
|
const expr = this.lowerExpr(stmt.kind.expr);
|
||||||
|
const local = new Inst(
|
||||||
|
Ty.create("PtrMut", { ty }),
|
||||||
|
{ tag: "Alloca" },
|
||||||
|
);
|
||||||
|
this.allocs.push(local);
|
||||||
|
this.pushInst(Ty.Void, "Store", {
|
||||||
|
target: local,
|
||||||
|
source: expr,
|
||||||
|
});
|
||||||
|
this.localMap.set(stmt.kind.param.id, local);
|
||||||
|
}
|
||||||
|
|
||||||
|
private lowerAssignStmt(stmt: ast.NodeWithKind<"AssignStmt">) {
|
||||||
|
const source = this.lowerExpr(stmt.kind.expr);
|
||||||
|
const target = this.lowerPlace(stmt.kind.place);
|
||||||
|
this.pushInst(Ty.Void, "Store", { target, source });
|
||||||
|
}
|
||||||
|
|
||||||
private lowerPlace(place: ast.Node): Inst {
|
private lowerPlace(place: ast.Node): Inst {
|
||||||
|
// evaluate to most direct pointer
|
||||||
|
|
||||||
const ty = this.tys.place(place);
|
const ty = this.tys.place(place);
|
||||||
if (place.is("IdentExpr")) {
|
if (place.is("IdentExpr")) {
|
||||||
const sym = this.syms.get(place);
|
const sym = this.syms.get(place);
|
||||||
@ -189,17 +201,18 @@ class FnLowerer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (place.is("UnaryExpr") && place.kind.op === "Deref") {
|
if (place.is("UnaryExpr") && place.kind.op === "Deref") {
|
||||||
const source = this.lowerPlace(place.kind.expr);
|
const source = this.lowerExpr(place.kind.expr);
|
||||||
return this.pushInst(
|
// return this.pushInst(
|
||||||
Ty.create("PtrMut", { ty }),
|
// Ty.create("PtrMut", { ty }),
|
||||||
"Load",
|
// "Load",
|
||||||
{ source },
|
// { source },
|
||||||
);
|
// );
|
||||||
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (place.is("IndexExpr")) {
|
if (place.is("IndexExpr")) {
|
||||||
const value = place.kind.value;
|
const value = place.kind.value;
|
||||||
const valueTy = this.tys.expr(value);
|
const valueTy = this.tys.place(value);
|
||||||
const arg = place.kind.arg;
|
const arg = place.kind.arg;
|
||||||
const argTy = this.tys.expr(arg);
|
const argTy = this.tys.expr(arg);
|
||||||
if (!valueTy.is("Array") && !valueTy.is("Slice")) {
|
if (!valueTy.is("Array") && !valueTy.is("Slice")) {
|
||||||
@ -210,7 +223,7 @@ class FnLowerer {
|
|||||||
const argInst = this.lowerExpr(arg);
|
const argInst = this.lowerExpr(arg);
|
||||||
return this.pushInst(
|
return this.pushInst(
|
||||||
Ty.create("PtrMut", { ty: valueTy.kind.ty }),
|
Ty.create("PtrMut", { ty: valueTy.kind.ty }),
|
||||||
"Index",
|
"GetElemPtr",
|
||||||
{ base: valueInst, offset: argInst },
|
{ base: valueInst, offset: argInst },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/mir.ts
14
src/mir.ts
@ -100,7 +100,7 @@ export class Inst {
|
|||||||
|
|
||||||
pretty(cx: PrettyCx): string {
|
pretty(cx: PrettyCx): string {
|
||||||
const valueless = ["Store", "Jump", "Branch", "Return", "DebugPrint"];
|
const valueless = ["Store", "Jump", "Branch", "Return", "DebugPrint"];
|
||||||
const valueType = `%${cx.regId(this)} = ${this.ty.pretty()} `;
|
const valueType = `%${cx.regId(this)} (${this.ty.pretty()}) = `;
|
||||||
return `${
|
return `${
|
||||||
!valueless.includes(this.kind.tag) ? valueType : ""
|
!valueless.includes(this.kind.tag) ? valueType : ""
|
||||||
}${this.kind.tag} ${this.prettyArgs(cx)}`;
|
}${this.kind.tag} ${this.prettyArgs(cx)}`;
|
||||||
@ -127,10 +127,10 @@ export class Inst {
|
|||||||
return `${k.fn.stmt.kind.ident}`;
|
return `${k.fn.stmt.kind.ident}`;
|
||||||
case "Param":
|
case "Param":
|
||||||
return `${k.idx}`;
|
return `${k.idx}`;
|
||||||
case "Index":
|
case "GetElemPtr":
|
||||||
return `${r(k.base)} &[${r(k.offset)}]`;
|
return `&[ptr ${r(k.base)}][${r(k.offset)}]`;
|
||||||
case "Slice":
|
case "Slice":
|
||||||
return `${r(k.value)} [${k.begin ? r(k.begin) : ""}..${
|
return `&[ptr ${r(k.value)}][${k.begin ? r(k.begin) : ""}..${
|
||||||
k.end ? r(k.end) : ""
|
k.end ? r(k.end) : ""
|
||||||
}]`;
|
}]`;
|
||||||
case "Call":
|
case "Call":
|
||||||
@ -138,9 +138,9 @@ export class Inst {
|
|||||||
case "Alloca":
|
case "Alloca":
|
||||||
return "";
|
return "";
|
||||||
case "Load":
|
case "Load":
|
||||||
return `${r(k.source)}`;
|
return `[ptr ${r(k.source)}]`;
|
||||||
case "Store":
|
case "Store":
|
||||||
return `${r(k.target)} = ${r(k.source)}`;
|
return `[ptr ${r(k.target)}] = ${r(k.source)}`;
|
||||||
case "Jump":
|
case "Jump":
|
||||||
return `bb${cx.bbId(k.target)}`;
|
return `bb${cx.bbId(k.target)}`;
|
||||||
case "Branch":
|
case "Branch":
|
||||||
@ -184,7 +184,7 @@ export type InstKind =
|
|||||||
| { tag: "Array"; values: Inst[] }
|
| { tag: "Array"; values: Inst[] }
|
||||||
| { tag: "Fn"; fn: Fn }
|
| { tag: "Fn"; fn: Fn }
|
||||||
| { tag: "Param"; idx: number }
|
| { tag: "Param"; idx: number }
|
||||||
| { tag: "Index"; base: Inst; offset: Inst }
|
| { tag: "GetElemPtr"; base: Inst; offset: Inst }
|
||||||
| { tag: "Slice"; value: Inst; begin: Inst | null; end: Inst | null }
|
| { tag: "Slice"; value: Inst; begin: Inst | null; end: Inst | null }
|
||||||
| { tag: "Call"; callee: Inst; args: Inst[] }
|
| { tag: "Call"; callee: Inst; args: Inst[] }
|
||||||
| { tag: "Alloca" }
|
| { tag: "Alloca" }
|
||||||
|
|||||||
@ -13,12 +13,12 @@ export class FnInterpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
eval(): Val {
|
eval(): Val {
|
||||||
const cx = new mir.PrettyCx();
|
// const cx = new mir.PrettyCx();
|
||||||
while (this.instIdx < this.bb.insts.length) {
|
while (this.instIdx < this.bb.insts.length) {
|
||||||
const inst = this.bb.insts[this.instIdx];
|
const inst = this.bb.insts[this.instIdx];
|
||||||
this.instIdx += 1;
|
this.instIdx += 1;
|
||||||
|
|
||||||
// console.log(poin
|
// console.log(
|
||||||
// `[${this.instIdx.toString().padStart(2, " ")}] ${
|
// `[${this.instIdx.toString().padStart(2, " ")}] ${
|
||||||
// inst.pretty(cx)
|
// inst.pretty(cx)
|
||||||
// }`,
|
// }`,
|
||||||
@ -50,45 +50,7 @@ export class FnInterpreter {
|
|||||||
case "Param":
|
case "Param":
|
||||||
this.regs.set(inst, this.args[k.idx]);
|
this.regs.set(inst, this.args[k.idx]);
|
||||||
break;
|
break;
|
||||||
// case "Index": {
|
case "GetElemPtr": {
|
||||||
// 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 offset = this.regs.get(k.offset)!;
|
const offset = this.regs.get(k.offset)!;
|
||||||
if (offset.kind.tag !== "Int") {
|
if (offset.kind.tag !== "Int") {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
@ -100,7 +62,10 @@ export class FnInterpreter {
|
|||||||
console.log({ array });
|
console.log({ array });
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
if (offset.kind.value >= array.kind.values.length) {
|
if (
|
||||||
|
offset.kind.value < 0 ||
|
||||||
|
offset.kind.value >= array.kind.values.length
|
||||||
|
) {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
this.regs.set(
|
this.regs.set(
|
||||||
@ -112,8 +77,20 @@ export class FnInterpreter {
|
|||||||
mutable: base.kind.mutable,
|
mutable: base.kind.mutable,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
} else if (base.kind.tag === "Slice") {
|
} else if (base.kind.tag === "ArraySlice") {
|
||||||
|
const idx = offset.kind.value + base.kind.begin;
|
||||||
|
if (idx < 0 || idx >= base.kind.end) {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
|
}
|
||||||
|
this.regs.set(
|
||||||
|
inst,
|
||||||
|
new Val({
|
||||||
|
tag: "ArrayElemPtr",
|
||||||
|
values: base.kind.values,
|
||||||
|
idx,
|
||||||
|
mutable: base.kind.mutable,
|
||||||
|
}),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
@ -136,29 +113,31 @@ export class FnInterpreter {
|
|||||||
if (value.kind.tag !== "Array") {
|
if (value.kind.tag !== "Array") {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
if (
|
let beginIdx = 0;
|
||||||
begin && begin.kind.tag === "Int" &&
|
if (begin) {
|
||||||
begin.kind.value < 0
|
if (begin.kind.tag !== "Int") {
|
||||||
) {
|
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
if (
|
beginIdx = begin.kind.value;
|
||||||
end && end.kind.tag === "Int" &&
|
}
|
||||||
end.kind.value >= value.kind.values.length
|
let endIdx = value.kind.values.length;
|
||||||
) {
|
if (end) {
|
||||||
|
if (end.kind.tag !== "Int") {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
endIdx = end.kind.value;
|
||||||
|
}
|
||||||
|
if (beginIdx < 0 || endIdx > value.kind.values.length) {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
this.regs.set(
|
this.regs.set(
|
||||||
inst,
|
inst,
|
||||||
new Val({
|
new Val({
|
||||||
tag: "Slice",
|
tag: "ArraySlice",
|
||||||
value,
|
mutable: false,
|
||||||
begin: begin ?? new Val({ tag: "Int", value: 0 }),
|
values: value.kind.values,
|
||||||
end: end ??
|
begin: beginIdx,
|
||||||
new Val({
|
end: endIdx,
|
||||||
tag: "Int",
|
|
||||||
value: value.kind.values.length,
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -194,6 +173,7 @@ export class FnInterpreter {
|
|||||||
source.kind.values[source.kind.idx],
|
source.kind.values[source.kind.idx],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
console.log({ source });
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -207,6 +187,7 @@ export class FnInterpreter {
|
|||||||
const source = this.regs.get(k.source)!;
|
const source = this.regs.get(k.source)!;
|
||||||
target.kind.values[target.kind.idx] = source;
|
target.kind.values[target.kind.idx] = source;
|
||||||
} else {
|
} else {
|
||||||
|
console.log({ target });
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -357,18 +338,12 @@ class Val {
|
|||||||
case "Ptr":
|
case "Ptr":
|
||||||
case "ArrayElemPtr":
|
case "ArrayElemPtr":
|
||||||
return `<pointer>`;
|
return `<pointer>`;
|
||||||
case "Slice":
|
case "ArraySlice":
|
||||||
if (k.value.kind.tag !== "Array") {
|
|
||||||
throw new Error();
|
|
||||||
}
|
|
||||||
if (k.begin.kind.tag !== "Int" || k.end.kind.tag !== "Int") {
|
|
||||||
throw new Error();
|
|
||||||
}
|
|
||||||
return `[${
|
return `[${
|
||||||
k.value.kind.values.slice(
|
k.values
|
||||||
k.begin.kind.value,
|
.slice(k.begin, k.end)
|
||||||
k.end.kind.value,
|
.map((v) => v.pretty())
|
||||||
).map((v) => v.pretty()).join(", ")
|
.join(", ")
|
||||||
}]`;
|
}]`;
|
||||||
case "Array":
|
case "Array":
|
||||||
return `[${k.values.map((v) => v.pretty()).join(", ")}]`;
|
return `[${k.values.map((v) => v.pretty()).join(", ")}]`;
|
||||||
@ -388,6 +363,12 @@ type ValKind =
|
|||||||
| { tag: "Bool"; value: boolean }
|
| { tag: "Bool"; value: boolean }
|
||||||
| { tag: "Ptr"; mutable: boolean; value: Val }
|
| { tag: "Ptr"; mutable: boolean; value: Val }
|
||||||
| { tag: "ArrayElemPtr"; mutable: boolean; values: Val[]; idx: number }
|
| { tag: "ArrayElemPtr"; mutable: boolean; values: Val[]; idx: number }
|
||||||
| { tag: "Slice"; value: Val; begin: Val; end: Val }
|
| {
|
||||||
|
tag: "ArraySlice";
|
||||||
|
mutable: boolean;
|
||||||
|
values: Val[];
|
||||||
|
begin: number;
|
||||||
|
end: number;
|
||||||
|
}
|
||||||
| { tag: "Array"; values: Val[] }
|
| { tag: "Array"; values: Val[] }
|
||||||
| { tag: "Fn"; fn: mir.Fn };
|
| { tag: "Fn"; fn: mir.Fn };
|
||||||
|
|||||||
@ -122,6 +122,13 @@ export class Ty {
|
|||||||
throw new Error(`'${this.kind.tag}' not handled`);
|
throw new Error(`'${this.kind.tag}' not handled`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isSized(): boolean {
|
||||||
|
if (this.is("Slice")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
pretty(): string {
|
pretty(): string {
|
||||||
switch (this.kind.tag) {
|
switch (this.kind.tag) {
|
||||||
case "Error":
|
case "Error":
|
||||||
|
|||||||
@ -12,13 +12,13 @@ fn main()
|
|||||||
print_int(ptr_to_array.*[1]);
|
print_int(ptr_to_array.*[1]);
|
||||||
|
|
||||||
let slice: *[int] = &array[..];
|
let slice: *[int] = &array[..];
|
||||||
// // e xpect: 2
|
// expect: 3
|
||||||
// print_int(slice.*[2]);
|
print_int(slice.*[2]);
|
||||||
|
|
||||||
// let slice_mut: *mut [int] = &mut array[1..3];
|
let slice_mut: *mut [int] = &mut array[1..3];
|
||||||
// slice_mut.*[0] = 4;
|
slice_mut.*[0] = 4;
|
||||||
// // e xpect: 4
|
// expect: 4
|
||||||
// print_int(array[1]);
|
print_int(array[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// vim: syntax=rust commentstring=//\ %s
|
// vim: syntax=rust commentstring=//\ %s
|
||||||
|
|||||||
@ -8,25 +8,21 @@ fn main()
|
|||||||
{
|
{
|
||||||
let a = 1;
|
let a = 1;
|
||||||
let b: *int = &a;
|
let b: *int = &a;
|
||||||
|
|
||||||
// expect: 1
|
// expect: 1
|
||||||
print_int(*b);
|
print_int(*b);
|
||||||
|
|
||||||
a = 2;
|
a = 2;
|
||||||
|
|
||||||
// expect: 2
|
// expect: 2
|
||||||
print_int(*b);
|
print_int(*b);
|
||||||
|
|
||||||
let c: *mut int = &mut a;
|
let c: *mut int = &mut a;
|
||||||
*c = 3;
|
*c = 3;
|
||||||
|
|
||||||
// expect: 3
|
// expect: 3
|
||||||
print_int(a);
|
print_int(a);
|
||||||
// expect: 3
|
// expect: 3
|
||||||
print_int(*c);
|
print_int(*c);
|
||||||
|
|
||||||
change_to(&mut a, 4);
|
change_to(&mut a, 4);
|
||||||
|
|
||||||
// expect: 4
|
// expect: 4
|
||||||
print_int(a);
|
print_int(a);
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user