mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-18 19:16:35 +00:00
everything
This commit is contained in:
parent
f3523e486b
commit
072e44eaa8
@ -42,6 +42,7 @@ export const Builtins = {
|
|||||||
StringEqual: 0x11,
|
StringEqual: 0x11,
|
||||||
ArraySet: 0x20,
|
ArraySet: 0x20,
|
||||||
StructSet: 0x30,
|
StructSet: 0x30,
|
||||||
|
Print: 0x40,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export function opToString(op: number): string {
|
export function opToString(op: number): string {
|
||||||
@ -119,6 +120,8 @@ export function builtinToString(builtin: number): string {
|
|||||||
return "ArraySet";
|
return "ArraySet";
|
||||||
case Builtins.StructSet:
|
case Builtins.StructSet:
|
||||||
return "StructSet";
|
return "StructSet";
|
||||||
|
case Builtins.Print:
|
||||||
|
return "Print";
|
||||||
default:
|
default:
|
||||||
return `<unknown Builtin ${builtin}>`;
|
return `<unknown Builtin ${builtin}>`;
|
||||||
}
|
}
|
||||||
|
@ -49,17 +49,10 @@ export class Assembler {
|
|||||||
const locs: { [key: string]: number } = {};
|
const locs: { [key: string]: number } = {};
|
||||||
const refs: { [key: number]: string } = {};
|
const refs: { [key: number]: string } = {};
|
||||||
|
|
||||||
const debugLines: {
|
|
||||||
startIp: number;
|
|
||||||
endIp: number;
|
|
||||||
insString: string;
|
|
||||||
}[] = [];
|
|
||||||
|
|
||||||
for (const line of this.lines) {
|
for (const line of this.lines) {
|
||||||
for (const label of line.labels ?? []) {
|
for (const label of line.labels ?? []) {
|
||||||
locs[label] = ip;
|
locs[label] = ip;
|
||||||
}
|
}
|
||||||
const startIp = ip;
|
|
||||||
for (const lit of line.ins as Lit[]) {
|
for (const lit of line.ins as Lit[]) {
|
||||||
if (typeof lit === "number") {
|
if (typeof lit === "number") {
|
||||||
output.push(lit);
|
output.push(lit);
|
||||||
@ -68,6 +61,8 @@ export class Assembler {
|
|||||||
output.push(lit ? 1 : 0);
|
output.push(lit ? 1 : 0);
|
||||||
ip += 1;
|
ip += 1;
|
||||||
} else if (typeof lit === "string") {
|
} else if (typeof lit === "string") {
|
||||||
|
output.push(lit.length);
|
||||||
|
ip += 1;
|
||||||
for (let i = 0; i < lit.length; ++i) {
|
for (let i = 0; i < lit.length; ++i) {
|
||||||
output.push(lit.charCodeAt(i));
|
output.push(lit.charCodeAt(i));
|
||||||
ip += 1;
|
ip += 1;
|
||||||
@ -78,11 +73,6 @@ export class Assembler {
|
|||||||
ip += 1;
|
ip += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debugLines.push({
|
|
||||||
startIp,
|
|
||||||
endIp: ip,
|
|
||||||
insString: this.insToString(line.ins),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
for (let i = 0; i < output.length; ++i) {
|
for (let i = 0; i < output.length; ++i) {
|
||||||
if (!(i in refs)) {
|
if (!(i in refs)) {
|
||||||
@ -96,21 +86,14 @@ export class Assembler {
|
|||||||
}
|
}
|
||||||
output[i] = locs[refs[i]];
|
output[i] = locs[refs[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const line of debugLines) {
|
|
||||||
console.log(
|
|
||||||
line.startIp.toString().padStart(3, " ") + " " +
|
|
||||||
output.slice(line.startIp, line.endIp).join(", ") + "\n" +
|
|
||||||
line.insString + "\n",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public printProgram() {
|
public printProgram() {
|
||||||
|
let ip = 0;
|
||||||
for (const line of this.lines) {
|
for (const line of this.lines) {
|
||||||
for (const label of line.labels ?? []) {
|
for (const label of line.labels ?? []) {
|
||||||
console.log(`${label}:`);
|
console.log(` ${label}:`);
|
||||||
}
|
}
|
||||||
const op = opToString(line.ins[0] as number)
|
const op = opToString(line.ins[0] as number)
|
||||||
.padEnd(13, " ");
|
.padEnd(13, " ");
|
||||||
@ -129,28 +112,10 @@ export class Assembler {
|
|||||||
return lit.label;
|
return lit.label;
|
||||||
}
|
}
|
||||||
}).join(", ");
|
}).join(", ");
|
||||||
console.log(` ${op} ${args}`);
|
console.log(`${ip.toString().padStart(8, " ")}: ${op} ${args}`);
|
||||||
|
ip += line.ins.map((lit) =>
|
||||||
|
typeof lit === "string" ? lit.length : 1
|
||||||
|
).reduce((acc, curr) => acc + curr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private insToString(ins: Ins): string {
|
|
||||||
const op = opToString(ins[0] as number)
|
|
||||||
.padEnd(13, " ");
|
|
||||||
const args = (ins.slice(1) as Lit[]).map((lit) => {
|
|
||||||
if (typeof lit === "number") {
|
|
||||||
return lit;
|
|
||||||
} else if (typeof lit === "boolean") {
|
|
||||||
return lit.toString();
|
|
||||||
} else if (typeof lit === "string") {
|
|
||||||
return '"' +
|
|
||||||
lit.replaceAll("\\", "\\\\").replaceAll("\0", "\\0")
|
|
||||||
.replaceAll("\n", "\\n").replaceAll("\t", "\\t")
|
|
||||||
.replaceAll("\r", "\\r") +
|
|
||||||
'"';
|
|
||||||
} else {
|
|
||||||
return lit.label;
|
|
||||||
}
|
|
||||||
}).join(", ");
|
|
||||||
return ` ${op} ${args}`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ export type StmtKind =
|
|||||||
params: Param[];
|
params: Param[];
|
||||||
returnType?: EType;
|
returnType?: EType;
|
||||||
body: Expr;
|
body: Expr;
|
||||||
|
annos?: Anno[];
|
||||||
vtype?: VType;
|
vtype?: VType;
|
||||||
}
|
}
|
||||||
| { type: "let"; param: Param; value: Expr }
|
| { type: "let"; param: Param; value: Expr }
|
||||||
@ -85,7 +86,7 @@ export type SymKind =
|
|||||||
| { type: "fn"; stmt: Stmt }
|
| { type: "fn"; stmt: Stmt }
|
||||||
| { type: "fn_param"; param: Param }
|
| { type: "fn_param"; param: Param }
|
||||||
| { type: "closure"; inner: Sym }
|
| { type: "closure"; inner: Sym }
|
||||||
| { type: "builtin" };
|
| { type: "builtin"; builtinId: number };
|
||||||
|
|
||||||
export type EType = {
|
export type EType = {
|
||||||
kind: ETypeKind;
|
kind: ETypeKind;
|
||||||
@ -98,3 +99,9 @@ export type ETypeKind =
|
|||||||
| { type: "ident"; value: string }
|
| { type: "ident"; value: string }
|
||||||
| { type: "array"; inner: EType }
|
| { type: "array"; inner: EType }
|
||||||
| { type: "struct"; fields: Param[] };
|
| { type: "struct"; fields: Param[] };
|
||||||
|
|
||||||
|
export type Anno = {
|
||||||
|
ident: string;
|
||||||
|
values: Expr[];
|
||||||
|
pos: Pos;
|
||||||
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { StmtKind } from "./ast.ts";
|
import { Builtins } from "./arch.ts";
|
||||||
import { EType, Expr, Stmt } from "./ast.ts";
|
import { EType, Expr, Stmt } from "./ast.ts";
|
||||||
import { printStackTrace, Reporter } from "./info.ts";
|
import { printStackTrace, Reporter } from "./info.ts";
|
||||||
import { Pos } from "./token.ts";
|
import { Pos } from "./token.ts";
|
||||||
@ -356,6 +356,7 @@ export class Checker {
|
|||||||
}
|
}
|
||||||
const pos = expr.pos;
|
const pos = expr.pos;
|
||||||
const subject = this.checkExpr(expr.kind.subject);
|
const subject = this.checkExpr(expr.kind.subject);
|
||||||
|
console.log(expr);
|
||||||
if (subject.type !== "fn") {
|
if (subject.type !== "fn") {
|
||||||
this.report("cannot call non-fn", pos);
|
this.report("cannot call non-fn", pos);
|
||||||
return { type: "error" };
|
return { type: "error" };
|
||||||
|
@ -91,7 +91,7 @@ export class Lexer {
|
|||||||
this.step();
|
this.step();
|
||||||
return { ...this.token("string", pos), stringValue: value };
|
return { ...this.token("string", pos), stringValue: value };
|
||||||
}
|
}
|
||||||
if (this.test(/[\+\{\};=\-\*\(\)\.,:;\[\]><!0]/)) {
|
if (this.test(/[\+\{\};=\-\*\(\)\.,:;\[\]><!0#]/)) {
|
||||||
const first = this.current();
|
const first = this.current();
|
||||||
this.step();
|
this.step();
|
||||||
if (first === "=" && !this.done() && this.test("=")) {
|
if (first === "=" && !this.done() && this.test("=")) {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Builtins } from "./arch.ts";
|
import { Builtins } from "./arch.ts";
|
||||||
import { BinaryType, Expr, Stmt } from "./ast.ts";
|
import { Expr, Stmt } from "./ast.ts";
|
||||||
import { LocalLeaf, Locals, LocalsFnRoot } from "./lowerer_locals.ts";
|
import { LocalLeaf, Locals, LocalsFnRoot } from "./lowerer_locals.ts";
|
||||||
import { Ops } from "./mod.ts";
|
import { Ops } from "./mod.ts";
|
||||||
import { Assembler, Label } from "./assembler.ts";
|
import { Assembler, Label } from "./assembler.ts";
|
||||||
import { VType, vtypeToString } from "./vtype.ts";
|
import { vtypeToString } from "./vtype.ts";
|
||||||
|
|
||||||
export class Lowerer {
|
export class Lowerer {
|
||||||
private program = new Assembler();
|
private program = new Assembler();
|
||||||
@ -134,25 +134,13 @@ export class Lowerer {
|
|||||||
for (const { ident } of stmt.kind.params) {
|
for (const { ident } of stmt.kind.params) {
|
||||||
this.locals.allocSym(ident);
|
this.locals.allocSym(ident);
|
||||||
}
|
}
|
||||||
this.locals.allocSym("::return");
|
|
||||||
this.program.add(Ops.PushNull);
|
|
||||||
this.lowerExpr(stmt.kind.body);
|
this.lowerExpr(stmt.kind.body);
|
||||||
this.program.add(Ops.StoreLocal, this.locals.symId("::return"));
|
|
||||||
this.locals = outerLocals;
|
this.locals = outerLocals;
|
||||||
|
|
||||||
for (
|
const localAmount = fnRoot.stackReserved() -
|
||||||
let i = 0;
|
stmt.kind.params.length;
|
||||||
i < fnRoot.stackReserved() - 1 - stmt.kind.params.length;
|
for (let i = 0; i < localAmount; ++i) {
|
||||||
++i
|
|
||||||
) {
|
|
||||||
outerProgram.add(Ops.PushNull);
|
outerProgram.add(Ops.PushNull);
|
||||||
this.program.add(Ops.Pop);
|
|
||||||
}
|
|
||||||
if (stmt.kind.params.length >= 1) {
|
|
||||||
this.program.add(Ops.StoreLocal, 0);
|
|
||||||
}
|
|
||||||
for (let i = 0; i < stmt.kind.params.length - 1; ++i) {
|
|
||||||
this.program.add(Ops.Pop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.program.add(Ops.Return);
|
this.program.add(Ops.Return);
|
||||||
@ -334,6 +322,8 @@ export class Lowerer {
|
|||||||
|
|
||||||
if (expr.kind.falsy) {
|
if (expr.kind.falsy) {
|
||||||
this.lowerExpr(expr.kind.falsy!);
|
this.lowerExpr(expr.kind.falsy!);
|
||||||
|
} else {
|
||||||
|
this.program.add(Ops.PushNull);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.program.setLabel(doneLabel);
|
this.program.setLabel(doneLabel);
|
||||||
|
@ -1,14 +1,5 @@
|
|||||||
import { Stmt } from "./ast.ts";
|
|
||||||
import { Lexer } from "./lexer.ts";
|
|
||||||
import { Parser } from "./parser.ts";
|
|
||||||
|
|
||||||
export * from "./parser.ts";
|
export * from "./parser.ts";
|
||||||
export * from "./ast.ts";
|
export * from "./ast.ts";
|
||||||
export * from "./arch.ts";
|
export * from "./arch.ts";
|
||||||
export * from "./lexer.ts";
|
export * from "./lexer.ts";
|
||||||
export * from "./token.ts";
|
export * from "./token.ts";
|
||||||
|
|
||||||
export async function compileWithDebug(filepath: string): Promise<Stmt[]> {
|
|
||||||
const text = await Deno.readTextFile(filepath);
|
|
||||||
return new Parser(new Lexer(text)).parseStmts();
|
|
||||||
}
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
Anno,
|
||||||
BinaryType,
|
BinaryType,
|
||||||
EType,
|
EType,
|
||||||
ETypeKind,
|
ETypeKind,
|
||||||
@ -203,6 +204,11 @@ export class Parser {
|
|||||||
this.step();
|
this.step();
|
||||||
returnType = this.parseEType();
|
returnType = this.parseEType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let annos: Anno[] | null = null;
|
||||||
|
if (this.test("#")) {
|
||||||
|
annos = this.parseAnnoArgs();
|
||||||
|
}
|
||||||
if (!this.test("{")) {
|
if (!this.test("{")) {
|
||||||
this.report("expected block");
|
this.report("expected block");
|
||||||
return this.stmt({ type: "error" }, pos);
|
return this.stmt({ type: "error" }, pos);
|
||||||
@ -214,6 +220,62 @@ export class Parser {
|
|||||||
return this.stmt({ type: "fn", ident, params, returnType, body }, pos);
|
return this.stmt({ type: "fn", ident, params, returnType, body }, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public parseAnnoArgs(): Expr[] {
|
||||||
|
this.step();
|
||||||
|
if (!this.test("(")) {
|
||||||
|
this.report("expected '('");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
this.step();
|
||||||
|
const annoArgs: Expr[] = [];
|
||||||
|
if (!this.test(")")) {
|
||||||
|
annoArgs.push(this.parseExpr());
|
||||||
|
while (this.test(",")) {
|
||||||
|
this.step();
|
||||||
|
if (this.test(")")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
annoArgs.push(this.parseExpr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.test(")")) {
|
||||||
|
this.report("expected ')'");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
this.step();
|
||||||
|
return annoArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public parseAnnos(): Anno[] {
|
||||||
|
this.step();
|
||||||
|
if (!this.test("[")) {
|
||||||
|
this.report("expected '['");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
this.step();
|
||||||
|
const annoArgs: Expr[] = [];
|
||||||
|
if (!this.test(")")) {
|
||||||
|
if (!this.test("ident")) {
|
||||||
|
this.report("expected identifier");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
annoArgs.push(this.parseExpr());
|
||||||
|
while (this.test(",")) {
|
||||||
|
this.step();
|
||||||
|
if (this.test(")")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
annoArgs.push(this.parseExpr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.test(")")) {
|
||||||
|
this.report("expected ')'");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
this.step();
|
||||||
|
return annoArgs;
|
||||||
|
}
|
||||||
|
|
||||||
public parseFnParams(): Param[] {
|
public parseFnParams(): Param[] {
|
||||||
this.step();
|
this.step();
|
||||||
if (this.test(")")) {
|
if (this.test(")")) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
import { Builtins } from "./arch.ts";
|
||||||
import { Expr, Stmt } from "./ast.ts";
|
import { Expr, Stmt } from "./ast.ts";
|
||||||
import { Reporter } from "./info.ts";
|
import { printStackTrace, Reporter } from "./info.ts";
|
||||||
import {
|
import {
|
||||||
FnSyms,
|
FnSyms,
|
||||||
GlobalSyms,
|
GlobalSyms,
|
||||||
@ -12,7 +13,13 @@ import { Pos } from "./token.ts";
|
|||||||
export class Resolver {
|
export class Resolver {
|
||||||
private root = new GlobalSyms();
|
private root = new GlobalSyms();
|
||||||
|
|
||||||
public constructor(private reporter: Reporter) {}
|
public constructor(private reporter: Reporter) {
|
||||||
|
this.root.define("print", {
|
||||||
|
type: "builtin",
|
||||||
|
ident: "print",
|
||||||
|
builtinId: Builtins.Print,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public resolve(stmts: Stmt[]) {
|
public resolve(stmts: Stmt[]) {
|
||||||
const scopeSyms = new StaticSyms(this.root);
|
const scopeSyms = new StaticSyms(this.root);
|
||||||
@ -208,6 +215,7 @@ export class Resolver {
|
|||||||
msg: `use of undefined symbol '${ident}'`,
|
msg: `use of undefined symbol '${ident}'`,
|
||||||
pos,
|
pos,
|
||||||
});
|
});
|
||||||
|
printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
private reportAlreadyDefined(ident: string, pos: Pos, syms: Syms) {
|
private reportAlreadyDefined(ident: string, pos: Pos, syms: Syms) {
|
||||||
@ -228,5 +236,6 @@ export class Resolver {
|
|||||||
msg: `previous definition of '${ident}'`,
|
msg: `previous definition of '${ident}'`,
|
||||||
pos: prev.sym.pos,
|
pos: prev.sym.pos,
|
||||||
});
|
});
|
||||||
|
printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
|
|
||||||
|
|
||||||
fn main() -> int {
|
fn main() -> int {
|
||||||
add(1, 2)
|
add(1, 2)
|
||||||
}
|
}
|
||||||
@ -11,5 +10,5 @@ fn add(a: int, b: int) -> int {
|
|||||||
let a = c;
|
let a = c;
|
||||||
+ a d
|
+ a d
|
||||||
}
|
}
|
||||||
//+ a b
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
|
fn print(msg: string) #[builtin(print)] {}
|
||||||
fn println(str: string) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sum(a: int, b: int) -> int {
|
fn sum(a: int, b: int) -> int {
|
||||||
+ a b
|
+ a b
|
||||||
@ -13,13 +11,13 @@ fn main() {
|
|||||||
|
|
||||||
let b = "world";
|
let b = "world";
|
||||||
|
|
||||||
println(+ + + a " " b "!"); // -> "Hello world!"
|
print(+ + + a " " b "!\n"); // -> "Hello world!"
|
||||||
|
|
||||||
if == a b {
|
if == a b {
|
||||||
println("whaaaat");
|
print("whaaaat\n");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println(":o");
|
print(":o\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
fn add(a, b) {
|
fn add(a: int, b: int) -> int {
|
||||||
+ a b
|
+ a b
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = 0;
|
fn main() -> int {
|
||||||
let i = 0;
|
let result = 0;
|
||||||
loop {
|
let i = 0;
|
||||||
if >= i 10 {
|
loop {
|
||||||
break;
|
if >= i 10 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result = add(result, 5);
|
||||||
|
i = + i 1;
|
||||||
}
|
}
|
||||||
result = add(result, 5);
|
result
|
||||||
i = + i 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,30 @@
|
|||||||
|
|
||||||
namespace sliger {
|
namespace sliger {
|
||||||
|
|
||||||
|
inline auto escape_string(std::string str) -> std::string
|
||||||
|
{
|
||||||
|
auto result = std::string();
|
||||||
|
for (auto ch : str) {
|
||||||
|
switch (ch) {
|
||||||
|
case '\n':
|
||||||
|
result += "\\n";
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
result += "\\t";
|
||||||
|
break;
|
||||||
|
case '\0':
|
||||||
|
result += "\\0";
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
result += "\\\\";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result += ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
enum class ValueType {
|
enum class ValueType {
|
||||||
Null,
|
Null,
|
||||||
Int,
|
Int,
|
||||||
@ -137,7 +161,7 @@ public:
|
|||||||
case ValueType::Bool:
|
case ValueType::Bool:
|
||||||
return as_bool().value ? "true" : "false";
|
return as_bool().value ? "true" : "false";
|
||||||
case ValueType::String:
|
case ValueType::String:
|
||||||
return std::format("\"{}\"", as_string().value);
|
return std::format("\"{}\"", escape_string(as_string().value));
|
||||||
case ValueType::Ptr:
|
case ValueType::Ptr:
|
||||||
return std::to_string(as_ptr().value);
|
return std::to_string(as_ptr().value);
|
||||||
}
|
}
|
||||||
|
@ -13,56 +13,37 @@ using namespace sliger;
|
|||||||
inline auto maybe_op_to_string(uint32_t value) -> std::string
|
inline auto maybe_op_to_string(uint32_t value) -> std::string
|
||||||
{
|
{
|
||||||
switch (static_cast<Op>(value)) {
|
switch (static_cast<Op>(value)) {
|
||||||
case Op::Nop:
|
/* clang-format off */
|
||||||
return "Nop";
|
case Op::Nop: return "Nop";
|
||||||
case Op::PushNull:
|
case Op::PushNull: return "PushNull";
|
||||||
return "PushNull";
|
case Op::PushInt: return "PushInt";
|
||||||
case Op::PushInt:
|
case Op::PushBool: return "PushBool";
|
||||||
return "PushInt";
|
case Op::PushString: return "PushString";
|
||||||
case Op::PushBool:
|
case Op::PushPtr: return "PushPtr";
|
||||||
return "PushBool";
|
case Op::Pop: return "Pop";
|
||||||
case Op::PushString:
|
case Op::ReserveStatic: return "ReserveStatic";
|
||||||
return "PushString";
|
case Op::LoadStatic: return "LoadStatic";
|
||||||
case Op::PushPtr:
|
case Op::StoreStatic: return "StoreStatic";
|
||||||
return "PushPtr";
|
case Op::LoadLocal: return "LoadLocal";
|
||||||
case Op::Pop:
|
case Op::StoreLocal: return "StoreLocal";
|
||||||
return "Pop";
|
case Op::Call: return "Call";
|
||||||
case Op::LoadLocal:
|
case Op::Return: return "Return";
|
||||||
return "LoadLocal";
|
case Op::Jump: return "Jump";
|
||||||
case Op::StoreLocal:
|
case Op::JumpIfTrue: return "JumpIfTrue";
|
||||||
return "StoreLocal";
|
case Op::Builtin: return "Builtin";
|
||||||
case Op::Call:
|
case Op::Add: return "Add";
|
||||||
return "Call";
|
case Op::Subtract: return "Subtract";
|
||||||
case Op::Return:
|
case Op::Multiply: return "Multiply";
|
||||||
return "Return";
|
case Op::Divide: return "Divide";
|
||||||
case Op::Jump:
|
case Op::Remainder: return "Remainder";
|
||||||
return "Jump";
|
case Op::Equal: return "Equal";
|
||||||
case Op::JumpIfTrue:
|
case Op::LessThan: return "LessThan";
|
||||||
return "JumpIfTrue";
|
case Op::And: return "And";
|
||||||
case Op::Add:
|
case Op::Or: return "Or";
|
||||||
return "Add";
|
case Op::Xor: return "Xor";
|
||||||
case Op::Subtract:
|
case Op::Not: return "Not";
|
||||||
return "Subtract";
|
case Op::SourceMap: return "SourceMap";
|
||||||
case Op::Multiply:
|
/* clang-format on */
|
||||||
return "Multiply";
|
|
||||||
case Op::Divide:
|
|
||||||
return "Divide";
|
|
||||||
case Op::Remainder:
|
|
||||||
return "Remainder";
|
|
||||||
case Op::Equal:
|
|
||||||
return "Equal";
|
|
||||||
case Op::LessThan:
|
|
||||||
return "LessThan";
|
|
||||||
case Op::And:
|
|
||||||
return "And";
|
|
||||||
case Op::Or:
|
|
||||||
return "Or";
|
|
||||||
case Op::Xor:
|
|
||||||
return "Xor";
|
|
||||||
case Op::Not:
|
|
||||||
return "Not";
|
|
||||||
case Op::SourceMap:
|
|
||||||
return "SourceMap";
|
|
||||||
default:
|
default:
|
||||||
return std::to_string(value);
|
return std::to_string(value);
|
||||||
}
|
}
|
||||||
@ -88,7 +69,7 @@ void VM::run_n_instructions(size_t amount)
|
|||||||
void VM::run_instruction()
|
void VM::run_instruction()
|
||||||
{
|
{
|
||||||
std::cout << std::format(" {:>4}: {:<12}{}\n", this->pc,
|
std::cout << std::format(" {:>4}: {:<12}{}\n", this->pc,
|
||||||
maybe_op_to_string(this->program[this->pc]), stack_repr_string(6));
|
maybe_op_to_string(this->program[this->pc]), stack_repr_string(8));
|
||||||
auto op = eat_op();
|
auto op = eat_op();
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Op::Nop:
|
case Op::Nop:
|
||||||
@ -179,12 +160,11 @@ void VM::run_instruction()
|
|||||||
}
|
}
|
||||||
stack_push(Ptr { .value = this->pc });
|
stack_push(Ptr { .value = this->pc });
|
||||||
stack_push(Ptr { .value = this->bp });
|
stack_push(Ptr { .value = this->bp });
|
||||||
|
this->pc = fn_ptr.as_ptr().value;
|
||||||
|
this->bp = static_cast<uint32_t>(this->stack.size());
|
||||||
for (size_t i = arguments.size(); i > 0; --i) {
|
for (size_t i = arguments.size(); i > 0; --i) {
|
||||||
stack_push(std::move(arguments.at(i - 1)));
|
stack_push(std::move(arguments.at(i - 1)));
|
||||||
}
|
}
|
||||||
this->pc = fn_ptr.as_ptr().value;
|
|
||||||
this->bp
|
|
||||||
= static_cast<uint32_t>(this->stack.size() - arguments.size());
|
|
||||||
if (this->opts.flame_graph) {
|
if (this->opts.flame_graph) {
|
||||||
this->flame_graph.report_call(
|
this->flame_graph.report_call(
|
||||||
fn_ptr.as_ptr().value, this->instruction_counter);
|
fn_ptr.as_ptr().value, this->instruction_counter);
|
||||||
@ -194,6 +174,9 @@ void VM::run_instruction()
|
|||||||
case Op::Return: {
|
case Op::Return: {
|
||||||
assert_stack_has(3);
|
assert_stack_has(3);
|
||||||
auto ret_val = stack_pop();
|
auto ret_val = stack_pop();
|
||||||
|
while (this->stack.size() > this->bp) {
|
||||||
|
stack_pop();
|
||||||
|
}
|
||||||
auto bp_val = stack_pop();
|
auto bp_val = stack_pop();
|
||||||
auto pc_val = stack_pop();
|
auto pc_val = stack_pop();
|
||||||
this->bp = bp_val.as_ptr().value;
|
this->bp = bp_val.as_ptr().value;
|
||||||
@ -331,16 +314,16 @@ void VM::run_builtin(Builtin builtin_id)
|
|||||||
switch (builtin_id) {
|
switch (builtin_id) {
|
||||||
case Builtin::StringConcat: {
|
case Builtin::StringConcat: {
|
||||||
assert_stack_has(2);
|
assert_stack_has(2);
|
||||||
auto right = stack_pop();
|
|
||||||
auto left = stack_pop();
|
auto left = stack_pop();
|
||||||
|
auto right = stack_pop();
|
||||||
stack_push(
|
stack_push(
|
||||||
String(right.as_string().value + left.as_string().value));
|
String(right.as_string().value + left.as_string().value));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Builtin::StringEqual: {
|
case Builtin::StringEqual: {
|
||||||
assert_stack_has(2);
|
assert_stack_has(2);
|
||||||
auto right = stack_pop();
|
|
||||||
auto left = stack_pop();
|
auto left = stack_pop();
|
||||||
|
auto right = stack_pop();
|
||||||
stack_push(Bool(right.as_string().value == left.as_string().value));
|
stack_push(Bool(right.as_string().value == left.as_string().value));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
echo Text:
|
||||||
|
cat $1
|
||||||
|
|
||||||
echo Compiling $1...
|
echo Compiling $1...
|
||||||
|
|
||||||
deno run --allow-read --allow-write compiler/main.ts $1
|
deno run --allow-read --allow-write compiler/main.ts $1
|
||||||
|
|
||||||
echo "Running out.slgbc..."
|
echo Running out.slgbc...
|
||||||
|
|
||||||
./runtime/build/sliger run out.slgbc
|
./runtime/build/sliger run out.slgbc
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user