keep working on panics: tracebacks sort of work?
This commit is contained in:
parent
050a0f987d
commit
9228e060bb
|
@ -34,6 +34,7 @@ async function handle_messages (e) {
|
||||||
}
|
}
|
||||||
case "Error": {
|
case "Error": {
|
||||||
console.log("Main: ludus errored with => ", msg.data)
|
console.log("Main: ludus errored with => ", msg.data)
|
||||||
|
ludus_result = msg.data
|
||||||
running = false
|
running = false
|
||||||
ready = false
|
ready = false
|
||||||
outbox = []
|
outbox = []
|
||||||
|
|
4
pkg/rudus.d.ts
vendored
4
pkg/rudus.d.ts
vendored
|
@ -14,8 +14,8 @@ export interface InitOutput {
|
||||||
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
||||||
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||||
readonly __wbindgen_export_6: WebAssembly.Table;
|
readonly __wbindgen_export_6: WebAssembly.Table;
|
||||||
readonly closure352_externref_shim: (a: number, b: number, c: any) => void;
|
readonly closure353_externref_shim: (a: number, b: number, c: any) => void;
|
||||||
readonly closure375_externref_shim: (a: number, b: number, c: any, d: any) => void;
|
readonly closure376_externref_shim: (a: number, b: number, c: any, d: any) => void;
|
||||||
readonly __wbindgen_start: () => void;
|
readonly __wbindgen_start: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
36
pkg/rudus.js
36
pkg/rudus.js
|
@ -240,13 +240,13 @@ function _assertNum(n) {
|
||||||
function __wbg_adapter_20(arg0, arg1, arg2) {
|
function __wbg_adapter_20(arg0, arg1, arg2) {
|
||||||
_assertNum(arg0);
|
_assertNum(arg0);
|
||||||
_assertNum(arg1);
|
_assertNum(arg1);
|
||||||
wasm.closure352_externref_shim(arg0, arg1, arg2);
|
wasm.closure353_externref_shim(arg0, arg1, arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function __wbg_adapter_50(arg0, arg1, arg2, arg3) {
|
function __wbg_adapter_46(arg0, arg1, arg2, arg3) {
|
||||||
_assertNum(arg0);
|
_assertNum(arg0);
|
||||||
_assertNum(arg1);
|
_assertNum(arg1);
|
||||||
wasm.closure375_externref_shim(arg0, arg1, arg2, arg3);
|
wasm.closure376_externref_shim(arg0, arg1, arg2, arg3);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function __wbg_load(module, imports) {
|
async function __wbg_load(module, imports) {
|
||||||
|
@ -314,30 +314,8 @@ function __wbg_get_imports() {
|
||||||
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
|
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
|
||||||
}
|
}
|
||||||
}, arguments) };
|
}, arguments) };
|
||||||
imports.wbg.__wbg_log_86d603e98cc11395 = function() { return logError(function (arg0, arg1) {
|
imports.wbg.__wbg_log_11652c6a56eeddfb = function() { return logError(function (arg0, arg1) {
|
||||||
let deferred0_0;
|
|
||||||
let deferred0_1;
|
|
||||||
try {
|
|
||||||
deferred0_0 = arg0;
|
|
||||||
deferred0_1 = arg1;
|
|
||||||
console.log(getStringFromWasm0(arg0, arg1));
|
console.log(getStringFromWasm0(arg0, arg1));
|
||||||
} finally {
|
|
||||||
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
|
|
||||||
}
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_log_9e426f8e841e42d3 = function() { return logError(function (arg0, arg1) {
|
|
||||||
console.log(getStringFromWasm0(arg0, arg1));
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_log_edeb598b620f1ba2 = function() { return logError(function (arg0, arg1) {
|
|
||||||
let deferred0_0;
|
|
||||||
let deferred0_1;
|
|
||||||
try {
|
|
||||||
deferred0_0 = arg0;
|
|
||||||
deferred0_1 = arg1;
|
|
||||||
console.log(getStringFromWasm0(arg0, arg1));
|
|
||||||
} finally {
|
|
||||||
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
|
|
||||||
}
|
|
||||||
}, arguments) };
|
}, arguments) };
|
||||||
imports.wbg.__wbg_new_23a2665fac83c611 = function() { return logError(function (arg0, arg1) {
|
imports.wbg.__wbg_new_23a2665fac83c611 = function() { return logError(function (arg0, arg1) {
|
||||||
try {
|
try {
|
||||||
|
@ -346,7 +324,7 @@ function __wbg_get_imports() {
|
||||||
const a = state0.a;
|
const a = state0.a;
|
||||||
state0.a = 0;
|
state0.a = 0;
|
||||||
try {
|
try {
|
||||||
return __wbg_adapter_50(a, state0.b, arg0, arg1);
|
return __wbg_adapter_46(a, state0.b, arg0, arg1);
|
||||||
} finally {
|
} finally {
|
||||||
state0.a = a;
|
state0.a = a;
|
||||||
}
|
}
|
||||||
|
@ -425,8 +403,8 @@ function __wbg_get_imports() {
|
||||||
_assertBoolean(ret);
|
_assertBoolean(ret);
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
imports.wbg.__wbindgen_closure_wrapper8059 = function() { return logError(function (arg0, arg1, arg2) {
|
imports.wbg.__wbindgen_closure_wrapper8065 = function() { return logError(function (arg0, arg1, arg2) {
|
||||||
const ret = makeMutClosure(arg0, arg1, 353, __wbg_adapter_20);
|
const ret = makeMutClosure(arg0, arg1, 354, __wbg_adapter_20);
|
||||||
return ret;
|
return ret;
|
||||||
}, arguments) };
|
}, arguments) };
|
||||||
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
||||||
|
|
Binary file not shown.
4
pkg/rudus_bg.wasm.d.ts
vendored
4
pkg/rudus_bg.wasm.d.ts
vendored
|
@ -9,6 +9,6 @@ export const __wbindgen_free: (a: number, b: number, c: number) => void;
|
||||||
export const __wbindgen_malloc: (a: number, b: number) => number;
|
export const __wbindgen_malloc: (a: number, b: number) => number;
|
||||||
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||||
export const __wbindgen_export_6: WebAssembly.Table;
|
export const __wbindgen_export_6: WebAssembly.Table;
|
||||||
export const closure352_externref_shim: (a: number, b: number, c: any) => void;
|
export const closure353_externref_shim: (a: number, b: number, c: any) => void;
|
||||||
export const closure375_externref_shim: (a: number, b: number, c: any, d: any) => void;
|
export const closure376_externref_shim: (a: number, b: number, c: any, d: any) => void;
|
||||||
export const __wbindgen_start: () => void;
|
export const __wbindgen_start: () => void;
|
||||||
|
|
16
src/base.rs
16
src/base.rs
|
@ -1,7 +1,7 @@
|
||||||
|
use crate::js::*;
|
||||||
use crate::value::*;
|
use crate::value::*;
|
||||||
use imbl::*;
|
use imbl::*;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wasm_bindgen::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum BaseFn {
|
pub enum BaseFn {
|
||||||
|
@ -268,12 +268,6 @@ pub fn last(ordered: &Value) -> Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern "C" {
|
|
||||||
#[wasm_bindgen(js_namespace = console)]
|
|
||||||
fn log(msg: String);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print(x: &Value) -> Value {
|
pub fn print(x: &Value) -> Value {
|
||||||
let Value::List(args) = x else {
|
let Value::List(args) = x else {
|
||||||
unreachable!("internal Ludus error")
|
unreachable!("internal Ludus error")
|
||||||
|
@ -284,7 +278,7 @@ pub fn print(x: &Value) -> Value {
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(" ");
|
.join(" ");
|
||||||
// println!("{out}");
|
// println!("{out}");
|
||||||
log(out);
|
console_log!("{out}");
|
||||||
Value::Keyword("ok")
|
Value::Keyword("ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,12 +507,6 @@ pub fn floor(x: &Value) -> Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern "C" {
|
|
||||||
#[wasm_bindgen(js_namespace = Math)]
|
|
||||||
fn random() -> f64;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn base_random() -> Value {
|
pub fn base_random() -> Value {
|
||||||
Value::Number(random())
|
Value::Number(random())
|
||||||
}
|
}
|
||||||
|
|
21
src/chunk.rs
21
src/chunk.rs
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::js::*;
|
||||||
use crate::op::Op;
|
use crate::op::Op;
|
||||||
use crate::value::{Key, Value};
|
use crate::value::{Key, Value};
|
||||||
use chumsky::prelude::SimpleSpan;
|
use chumsky::prelude::SimpleSpan;
|
||||||
|
@ -43,20 +44,20 @@ impl Chunk {
|
||||||
| UnconditionalMatch | Print | AppendList | ConcatList | PushList | PushDict
|
| UnconditionalMatch | Print | AppendList | ConcatList | PushList | PushDict
|
||||||
| AppendDict | ConcatDict | Nothing | PushGlobal | SetUpvalue | LoadMessage
|
| AppendDict | ConcatDict | Nothing | PushGlobal | SetUpvalue | LoadMessage
|
||||||
| NextMessage | MatchMessage | ClearMessage | SendMethod | LoadScrutinee => {
|
| NextMessage | MatchMessage | ClearMessage | SendMethod | LoadScrutinee => {
|
||||||
println!("{i:04}: {op}")
|
console_log!("{i:04}: {op}")
|
||||||
}
|
}
|
||||||
Constant | MatchConstant => {
|
Constant | MatchConstant => {
|
||||||
let high = self.bytecode[*i + 1];
|
let high = self.bytecode[*i + 1];
|
||||||
let low = self.bytecode[*i + 2];
|
let low = self.bytecode[*i + 2];
|
||||||
let idx = ((high as usize) << 8) + low as usize;
|
let idx = ((high as usize) << 8) + low as usize;
|
||||||
let value = &self.constants[idx].show();
|
let value = &self.constants[idx].show();
|
||||||
println!("{i:04}: {:16} {idx:05}: {value}", op.to_string());
|
console_log!("{i:04}: {:16} {idx:05}: {value}", op.to_string());
|
||||||
*i += 2;
|
*i += 2;
|
||||||
}
|
}
|
||||||
Msg => {
|
Msg => {
|
||||||
let msg_idx = self.bytecode[*i + 1];
|
let msg_idx = self.bytecode[*i + 1];
|
||||||
let msg = &self.msgs[msg_idx as usize];
|
let msg = &self.msgs[msg_idx as usize];
|
||||||
println!("{i:04}: {msg}");
|
console_log!("{i:04}: {msg}");
|
||||||
*i += 1;
|
*i += 1;
|
||||||
}
|
}
|
||||||
PushBinding | MatchTuple | MatchSplattedTuple | LoadSplattedTuple | MatchList
|
PushBinding | MatchTuple | MatchSplattedTuple | LoadSplattedTuple | MatchList
|
||||||
|
@ -64,7 +65,7 @@ impl Chunk {
|
||||||
| DropDictEntry | LoadDictValue | PushTuple | PushBox | MatchDepth | PopN | StoreN
|
| DropDictEntry | LoadDictValue | PushTuple | PushBox | MatchDepth | PopN | StoreN
|
||||||
| Call | GetUpvalue | Partial | MatchString | PushStringMatches | TailCall | LoadN => {
|
| Call | GetUpvalue | Partial | MatchString | PushStringMatches | TailCall | LoadN => {
|
||||||
let next = self.bytecode[*i + 1];
|
let next = self.bytecode[*i + 1];
|
||||||
println!("{i:04}: {:16} {next:03}", op.to_string());
|
console_log!("{i:04}: {:16} {next:03}", op.to_string());
|
||||||
*i += 1;
|
*i += 1;
|
||||||
}
|
}
|
||||||
Jump | JumpIfFalse | JumpIfTrue | JumpIfNoMatch | JumpIfMatch | JumpBack
|
Jump | JumpIfFalse | JumpIfTrue | JumpIfNoMatch | JumpIfMatch | JumpBack
|
||||||
|
@ -72,26 +73,18 @@ impl Chunk {
|
||||||
let high = self.bytecode[*i + 1];
|
let high = self.bytecode[*i + 1];
|
||||||
let low = self.bytecode[*i + 2];
|
let low = self.bytecode[*i + 2];
|
||||||
let len = ((high as u16) << 8) + low as u16;
|
let len = ((high as u16) << 8) + low as u16;
|
||||||
println!("{i:04}: {:16} {len:05}", op.to_string());
|
console_log!("{i:04}: {:16} {len:05}", op.to_string());
|
||||||
*i += 2;
|
*i += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dissasemble(&self) {
|
pub fn dissasemble(&self) {
|
||||||
println!("IDX | CODE | INFO");
|
console_log!("IDX | CODE | INFO");
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < self.bytecode.len() {
|
while i < self.bytecode.len() {
|
||||||
self.dissasemble_instr(&mut i);
|
self.dissasemble_instr(&mut i);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn kw_from(&self, kw: &str) -> Option<Value> {
|
|
||||||
// self.kw_index_from(kw).map(Value::Keyword)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn kw_index_from(&self, kw: &str) -> Option<usize> {
|
|
||||||
// self.keywords.iter().position(|s| *s == kw)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,12 +68,10 @@ pub struct Compiler {
|
||||||
pub scope_depth: isize,
|
pub scope_depth: isize,
|
||||||
pub match_depth: usize,
|
pub match_depth: usize,
|
||||||
pub stack_depth: usize,
|
pub stack_depth: usize,
|
||||||
pub spans: Vec<SimpleSpan>,
|
|
||||||
pub nodes: Vec<&'static Ast>,
|
|
||||||
pub ast: &'static Ast,
|
pub ast: &'static Ast,
|
||||||
pub span: SimpleSpan,
|
pub span: SimpleSpan,
|
||||||
pub src: &'static str,
|
pub src: &'static str,
|
||||||
pub name: &'static str,
|
pub input: &'static str,
|
||||||
pub depth: usize,
|
pub depth: usize,
|
||||||
pub upvalues: Vec<&'static str>,
|
pub upvalues: Vec<&'static str>,
|
||||||
loop_info: Vec<LoopInfo>,
|
loop_info: Vec<LoopInfo>,
|
||||||
|
@ -98,7 +96,7 @@ fn has_placeholder(args: &[Spanned<Ast>]) -> bool {
|
||||||
impl Compiler {
|
impl Compiler {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
ast: &'static Spanned<Ast>,
|
ast: &'static Spanned<Ast>,
|
||||||
name: &'static str,
|
input: &'static str,
|
||||||
src: &'static str,
|
src: &'static str,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
env: imbl::HashMap<Key, Value>,
|
env: imbl::HashMap<Key, Value>,
|
||||||
|
@ -111,6 +109,9 @@ impl Compiler {
|
||||||
string_patterns: vec![],
|
string_patterns: vec![],
|
||||||
env,
|
env,
|
||||||
msgs: vec![],
|
msgs: vec![],
|
||||||
|
src,
|
||||||
|
input,
|
||||||
|
spans: vec![],
|
||||||
};
|
};
|
||||||
Compiler {
|
Compiler {
|
||||||
chunk,
|
chunk,
|
||||||
|
@ -119,14 +120,12 @@ impl Compiler {
|
||||||
scope_depth: -1,
|
scope_depth: -1,
|
||||||
match_depth: 0,
|
match_depth: 0,
|
||||||
stack_depth: 0,
|
stack_depth: 0,
|
||||||
spans: vec![],
|
|
||||||
nodes: vec![],
|
|
||||||
ast: &ast.0,
|
ast: &ast.0,
|
||||||
span: ast.1,
|
span: ast.1,
|
||||||
loop_info: vec![],
|
loop_info: vec![],
|
||||||
upvalues: vec![],
|
upvalues: vec![],
|
||||||
src,
|
src,
|
||||||
name,
|
input,
|
||||||
tail_pos: false,
|
tail_pos: false,
|
||||||
debug,
|
debug,
|
||||||
}
|
}
|
||||||
|
@ -147,8 +146,8 @@ impl Compiler {
|
||||||
let low = len as u8;
|
let low = len as u8;
|
||||||
let high = (len >> 8) as u8;
|
let high = (len >> 8) as u8;
|
||||||
self.emit_op(op);
|
self.emit_op(op);
|
||||||
self.chunk.bytecode.push(high);
|
self.emit_byte(high as usize);
|
||||||
self.chunk.bytecode.push(low);
|
self.emit_byte(low as usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stub_jump(&mut self, op: Op) -> usize {
|
fn stub_jump(&mut self, op: Op) -> usize {
|
||||||
|
@ -188,8 +187,8 @@ impl Compiler {
|
||||||
self.emit_op(Op::Constant);
|
self.emit_op(Op::Constant);
|
||||||
let low = const_idx as u8;
|
let low = const_idx as u8;
|
||||||
let high = (const_idx >> 8) as u8;
|
let high = (const_idx >> 8) as u8;
|
||||||
self.chunk.bytecode.push(high);
|
self.emit_byte(high as usize);
|
||||||
self.chunk.bytecode.push(low);
|
self.emit_byte(low as usize);
|
||||||
self.stack_depth += 1;
|
self.stack_depth += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,18 +214,18 @@ impl Compiler {
|
||||||
self.emit_op(Op::MatchConstant);
|
self.emit_op(Op::MatchConstant);
|
||||||
let low = const_idx as u8;
|
let low = const_idx as u8;
|
||||||
let high = (const_idx >> 8) as u8;
|
let high = (const_idx >> 8) as u8;
|
||||||
self.chunk.bytecode.push(high);
|
self.emit_byte(high as usize);
|
||||||
self.chunk.bytecode.push(low);
|
self.emit_byte(low as usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_op(&mut self, op: Op) {
|
fn emit_op(&mut self, op: Op) {
|
||||||
self.chunk.bytecode.push(op as u8);
|
self.chunk.bytecode.push(op as u8);
|
||||||
self.spans.push(self.span);
|
self.chunk.spans.push(self.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_byte(&mut self, byte: usize) {
|
fn emit_byte(&mut self, byte: usize) {
|
||||||
self.chunk.bytecode.push(byte as u8);
|
self.chunk.bytecode.push(byte as u8);
|
||||||
self.spans.push(self.span);
|
self.chunk.spans.push(self.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
|
@ -234,7 +233,7 @@ impl Compiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bind(&mut self, name: &'static str) {
|
pub fn bind(&mut self, name: &'static str) {
|
||||||
self.msg(format!("binding `{name}` in {}", self.name));
|
self.msg(format!("binding `{name}` in {}", self.input));
|
||||||
self.msg(format!(
|
self.msg(format!(
|
||||||
"stack depth: {}; match depth: {}",
|
"stack depth: {}; match depth: {}",
|
||||||
self.stack_depth, self.match_depth
|
self.stack_depth, self.match_depth
|
||||||
|
@ -275,7 +274,7 @@ impl Compiler {
|
||||||
fn resolve_binding(&mut self, name: &'static str) {
|
fn resolve_binding(&mut self, name: &'static str) {
|
||||||
self.msg(format!(
|
self.msg(format!(
|
||||||
"resolving binding `{name}` in {}\nlocals: {}",
|
"resolving binding `{name}` in {}\nlocals: {}",
|
||||||
self.name,
|
self.input,
|
||||||
self.bindings
|
self.bindings
|
||||||
.iter()
|
.iter()
|
||||||
.map(|binding| format!("{binding}"))
|
.map(|binding| format!("{binding}"))
|
||||||
|
@ -1161,7 +1160,7 @@ impl Compiler {
|
||||||
None => {
|
None => {
|
||||||
let mut compiler = Compiler::new(
|
let mut compiler = Compiler::new(
|
||||||
clause,
|
clause,
|
||||||
name,
|
self.input,
|
||||||
self.src,
|
self.src,
|
||||||
self.depth + 1,
|
self.depth + 1,
|
||||||
self.chunk.env.clone(),
|
self.chunk.env.clone(),
|
||||||
|
@ -1502,7 +1501,7 @@ impl Compiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disassemble(&self) {
|
pub fn disassemble(&self) {
|
||||||
println!("=== chunk: {} ===", self.name);
|
println!("=== chunk: {} ===", self.input);
|
||||||
self.chunk.dissasemble();
|
self.chunk.dissasemble();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
// use crate::process::{LErr, Trace};
|
use crate::js::*;
|
||||||
use crate::lexer::Token;
|
use crate::lexer::Token;
|
||||||
use crate::validator::VErr;
|
|
||||||
use crate::panic::{Panic, PanicMsg};
|
use crate::panic::{Panic, PanicMsg};
|
||||||
|
use crate::validator::VErr;
|
||||||
use crate::vm::CallFrame;
|
use crate::vm::CallFrame;
|
||||||
use chumsky::error::RichPattern;
|
use chumsky::error::RichPattern;
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
|
|
||||||
|
|
||||||
const SEPARATOR: &str = "\n\n";
|
const SEPARATOR: &str = "\n\n";
|
||||||
|
|
||||||
fn line_number(src: &'static str, span: SimpleSpan) -> usize {
|
fn line_number(src: &'static str, span: SimpleSpan) -> usize {
|
||||||
|
@ -94,30 +93,46 @@ fn parsing_message(err: Rich<'static, Token>) -> String {
|
||||||
format!("Ludus did not expect to see: {found}\n expected: {expecteds}")
|
format!("Ludus did not expect to see: {found}\n expected: {expecteds}")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn panic(panic: Panic, src: &'static str, input: &'static str) -> String {
|
pub fn panic(panic: Panic) -> String {
|
||||||
let msgs = vec!["Ludus panicked!".to_string()];
|
// console_log!("Ludus panicked!: {panic}");
|
||||||
|
// panic.call_stack.last().unwrap().chunk().dissasemble();
|
||||||
|
// console_log!("{:?}", panic.call_stack.last().unwrap().chunk().spans);
|
||||||
|
let mut msgs = vec!["Ludus panicked!".to_string()];
|
||||||
let msg = match panic.msg {
|
let msg = match panic.msg {
|
||||||
PanicMsg::Generic(s) => s,
|
PanicMsg::Generic(ref s) => s,
|
||||||
_ => "no match".to_string(),
|
_ => &"no match".to_string(),
|
||||||
|
};
|
||||||
|
msgs.push(msg.clone());
|
||||||
|
msgs.push(traceback(&panic));
|
||||||
|
|
||||||
|
msgs.join("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn traceback(panic: &Panic) -> String {
|
||||||
|
let mut traceback = vec![];
|
||||||
|
for frame in panic.call_stack.iter().rev() {
|
||||||
|
traceback.push(frame_info(frame));
|
||||||
}
|
}
|
||||||
|
traceback.join("\n")
|
||||||
todo!()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn traceback(_panic: Panic) -> String {
|
fn frame_info(frame: &CallFrame) -> String {
|
||||||
todo!()
|
let span = frame.chunk().spans[if frame.ip == 0 {
|
||||||
|
frame.ip
|
||||||
|
} else {
|
||||||
|
frame.ip - 1
|
||||||
|
}];
|
||||||
|
let line_number = line_number(frame.chunk().src, span);
|
||||||
|
let line = get_line(frame.chunk().src, line_number);
|
||||||
|
let line = line.trim_start();
|
||||||
|
let name = frame.function.as_fn().name();
|
||||||
|
let input = frame.chunk().input;
|
||||||
|
format!(
|
||||||
|
" in {name} on line {} in {input}\n >>> {line}",
|
||||||
|
line_number + 1
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame_info(frame: CallFrame) -> String {
|
|
||||||
let chunk = frame.chunk();
|
|
||||||
let CallFrame{function, arity, ip, ..} = frame;
|
|
||||||
|
|
||||||
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/////// Some thoughts
|
/////// Some thoughts
|
||||||
// We're putting the information we need on the function and the chunk.
|
// We're putting the information we need on the function and the chunk.
|
||||||
// In the compiler, on functions, build up a vec of strings that are the patterns the function can match against
|
// In the compiler, on functions, build up a vec of strings that are the patterns the function can match against
|
||||||
|
@ -126,4 +141,3 @@ fn frame_info(frame: CallFrame) -> String {
|
||||||
// Let no match is no problem, either. We should have no concerns pulling the line with the span start and string
|
// Let no match is no problem, either. We should have no concerns pulling the line with the span start and string
|
||||||
// We don't need to reproduce the pattern, since it will be right there in the code
|
// We don't need to reproduce the pattern, since it will be right there in the code
|
||||||
// As for match forms, we'll just use "no match" and print the value
|
// As for match forms, we'll just use "no match" and print the value
|
||||||
|
|
||||||
|
|
13
src/io.rs
13
src/io.rs
|
@ -1,6 +1,7 @@
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
|
use crate::js::*;
|
||||||
use imbl::Vector;
|
use imbl::Vector;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
@ -13,12 +14,6 @@ extern "C" {
|
||||||
async fn io (output: String) -> Result<JsValue, JsValue>;
|
async fn io (output: String) -> Result<JsValue, JsValue>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern "C" {
|
|
||||||
#[wasm_bindgen(js_namespace = console)]
|
|
||||||
fn log(s: String);
|
|
||||||
}
|
|
||||||
|
|
||||||
type Url = Value; // expect a string
|
type Url = Value; // expect a string
|
||||||
type Commands = Value; // expect a list of command tuples
|
type Commands = Value; // expect a list of command tuples
|
||||||
|
|
||||||
|
@ -81,7 +76,7 @@ impl MsgIn {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_err_to_ludus_console(msg: String) {
|
pub async fn send_err_to_ludus_console(msg: String) {
|
||||||
log(msg.clone());
|
console_log!("{msg}");
|
||||||
do_io(vec![MsgOut::Ready, MsgOut::Error(msg)]).await;
|
do_io(vec![MsgOut::Ready, MsgOut::Error(msg)]).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,9 +90,9 @@ pub async fn do_io (msgs: Vec<MsgOut>) -> Vec<MsgIn> {
|
||||||
let inbox = inbox.as_string().expect("response should be a string");
|
let inbox = inbox.as_string().expect("response should be a string");
|
||||||
let inbox: Vec<MsgIn> = serde_json::from_str(inbox.as_str()).expect("response from js should be valid");
|
let inbox: Vec<MsgIn> = serde_json::from_str(inbox.as_str()).expect("response from js should be valid");
|
||||||
if !inbox.is_empty() {
|
if !inbox.is_empty() {
|
||||||
log("ludus received messages".to_string());
|
console_log!("ludus received messages");
|
||||||
for msg in inbox.iter() {
|
for msg in inbox.iter() {
|
||||||
log(format!("{}", msg));
|
console_log!("{}", msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inbox
|
inbox
|
||||||
|
|
21
src/lib.rs
21
src/lib.rs
|
@ -42,6 +42,9 @@ use crate::errors::{lexing, parsing, validation};
|
||||||
|
|
||||||
mod panic;
|
mod panic;
|
||||||
|
|
||||||
|
mod js;
|
||||||
|
use crate::js::*;
|
||||||
|
|
||||||
mod chunk;
|
mod chunk;
|
||||||
mod op;
|
mod op;
|
||||||
|
|
||||||
|
@ -63,8 +66,8 @@ fn prelude() -> HashMap<Key, Value> {
|
||||||
.into_output_errors();
|
.into_output_errors();
|
||||||
|
|
||||||
if !parse_errors.is_empty() {
|
if !parse_errors.is_empty() {
|
||||||
log("ERROR PARSING PRELUDE:");
|
console_log!("ERROR PARSING PRELUDE:");
|
||||||
log(format!("{:?}", parse_errors).as_str());
|
console_log!("{:?}", parse_errors);
|
||||||
panic!("parsing errors in prelude");
|
panic!("parsing errors in prelude");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,9 +83,9 @@ fn prelude() -> HashMap<Key, Value> {
|
||||||
validator.validate();
|
validator.validate();
|
||||||
|
|
||||||
if !validator.errors.is_empty() {
|
if !validator.errors.is_empty() {
|
||||||
log("VALIDATION ERRORS IN PRLUDE:");
|
console_log!("VALIDATION ERRORS IN PRLUDE:");
|
||||||
// report_invalidation(validator.errors);
|
// report_invalidation(validator.errors);
|
||||||
log(format!("{:?}", validator.errors).as_str());
|
console_log!("{:?}", validator.errors);
|
||||||
panic!("validator errors in prelude");
|
panic!("validator errors in prelude");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,13 +113,6 @@ fn prelude() -> HashMap<Key, Value> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern "C" {
|
|
||||||
#[wasm_bindgen(js_namespace = console)]
|
|
||||||
fn log(s: &str);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub async fn ludus(src: String) {
|
pub async fn ludus(src: String) {
|
||||||
// instrument wasm to report rust panics
|
// instrument wasm to report rust panics
|
||||||
|
@ -157,7 +153,7 @@ pub async fn ludus(src: String) {
|
||||||
|
|
||||||
let mut compiler = Compiler::new(
|
let mut compiler = Compiler::new(
|
||||||
parsed,
|
parsed,
|
||||||
"ludus script",
|
"user script",
|
||||||
src,
|
src,
|
||||||
0,
|
0,
|
||||||
prelude.clone(),
|
prelude.clone(),
|
||||||
|
@ -181,7 +177,6 @@ pub async fn ludus(src: String) {
|
||||||
|
|
||||||
let mut world = World::new(vm_chunk, prelude.clone(), DEBUG_SCRIPT_RUN);
|
let mut world = World::new(vm_chunk, prelude.clone(), DEBUG_SCRIPT_RUN);
|
||||||
world.run().await;
|
world.run().await;
|
||||||
// let result = world.result.clone();
|
|
||||||
|
|
||||||
// TODO: actually do something useful on a panic
|
// TODO: actually do something useful on a panic
|
||||||
// match result {
|
// match result {
|
||||||
|
|
32
src/panic.rs
32
src/panic.rs
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::errors::panic;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::vm::CallFrame;
|
use crate::vm::CallFrame;
|
||||||
|
|
||||||
|
@ -9,11 +10,38 @@ pub enum PanicMsg {
|
||||||
Generic(String),
|
Generic(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for PanicMsg {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
use PanicMsg::*;
|
||||||
|
match self {
|
||||||
|
NoLetMatch => write!(f, "no match in `let`"),
|
||||||
|
NoFnMatch => write!(f, "no match calling fn"),
|
||||||
|
NoMatch => write!(f, "no match in `match` form"),
|
||||||
|
Generic(s) => write!(f, "{s}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Panic {
|
pub struct Panic {
|
||||||
pub msg: PanicMsg,
|
pub msg: PanicMsg,
|
||||||
pub frame: CallFrame,
|
|
||||||
pub scrutinee: Option<Value>,
|
pub scrutinee: Option<Value>,
|
||||||
pub ip: usize,
|
|
||||||
pub call_stack: Vec<CallFrame>,
|
pub call_stack: Vec<CallFrame>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn frame_dump(frame: &CallFrame) -> String {
|
||||||
|
let dump = format!("stack name: {}\nspans: {:?}", frame, frame.chunk().spans);
|
||||||
|
dump
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Panic {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
let stub_trace = self
|
||||||
|
.call_stack
|
||||||
|
.iter()
|
||||||
|
.map(frame_dump)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n");
|
||||||
|
write!(f, "Panic: {}\n{stub_trace}", self.msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
51
src/vm.rs
51
src/vm.rs
|
@ -1,5 +1,6 @@
|
||||||
use crate::base::BaseFn;
|
use crate::base::BaseFn;
|
||||||
use crate::chunk::Chunk;
|
use crate::chunk::Chunk;
|
||||||
|
use crate::js::*;
|
||||||
use crate::op::Op;
|
use crate::op::Op;
|
||||||
use crate::panic::{Panic, PanicMsg};
|
use crate::panic::{Panic, PanicMsg};
|
||||||
use crate::value::{Key, LFn, Value};
|
use crate::value::{Key, LFn, Value};
|
||||||
|
@ -83,7 +84,7 @@ impl std::fmt::Display for Creature {
|
||||||
impl Creature {
|
impl Creature {
|
||||||
pub fn new(chunk: Chunk, zoo: Rc<RefCell<Zoo>>, debug: bool) -> Creature {
|
pub fn new(chunk: Chunk, zoo: Rc<RefCell<Zoo>>, debug: bool) -> Creature {
|
||||||
let lfn = LFn::Defined {
|
let lfn = LFn::Defined {
|
||||||
name: "user script",
|
name: "toplevel",
|
||||||
doc: None,
|
doc: None,
|
||||||
chunks: vec![chunk],
|
chunks: vec![chunk],
|
||||||
arities: vec![0],
|
arities: vec![0],
|
||||||
|
@ -185,42 +186,28 @@ impl Creature {
|
||||||
self.chunk().dissasemble_instr(&mut ip);
|
self.chunk().dissasemble_instr(&mut ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn call_stack(&mut self) -> String {
|
|
||||||
// let mut stack = format!(" calling {}", self.frame.function.show());
|
|
||||||
// for frame in self.call_stack.iter().rev() {
|
|
||||||
// let mut name = frame.function.show();
|
|
||||||
// name = if name == "fn user script" {
|
|
||||||
// "user script".to_string()
|
|
||||||
// } else {
|
|
||||||
// name
|
|
||||||
// };
|
|
||||||
// stack = format!("{stack}\n from {name}");
|
|
||||||
// }
|
|
||||||
// stack
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn panic(&mut self, msg: &'static str) {
|
|
||||||
// let msg = format!("{msg}\nPanic traceback:\n{}", self.call_stack());
|
|
||||||
// println!("process {} panicked!\n{msg}", self.pid);
|
|
||||||
// self.result = Some(Err(Panic::String(msg)));
|
|
||||||
// self.r#yield = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn panic_with(&mut self, msg: String) {
|
|
||||||
// let msg = format!("{msg}\nPanic traceback:\n{}", self.call_stack());
|
|
||||||
// println!("process {} panicked!\n{msg}", self.pid);
|
|
||||||
// self.result = Some(Err(Panic::String(msg)));
|
|
||||||
// self.r#yield = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn panic(&mut self, msg: PanicMsg) {
|
fn panic(&mut self, msg: PanicMsg) {
|
||||||
|
// first prep the current frame for parsing
|
||||||
|
let mut frame = self.frame.clone();
|
||||||
|
frame.ip = self.last_code;
|
||||||
|
// add it to our cloned stack
|
||||||
|
let mut call_stack = self.call_stack.clone();
|
||||||
|
call_stack.push(frame);
|
||||||
|
// console_log!(
|
||||||
|
// "{}",
|
||||||
|
// call_stack
|
||||||
|
// .iter()
|
||||||
|
// .map(|s| s.to_string())
|
||||||
|
// .collect::<Vec<_>>()
|
||||||
|
// .join("\n")
|
||||||
|
// );
|
||||||
|
//make a panic
|
||||||
let panic = Panic {
|
let panic = Panic {
|
||||||
msg,
|
msg,
|
||||||
frame: self.frame.clone(),
|
|
||||||
scrutinee: self.scrutinee.clone(),
|
scrutinee: self.scrutinee.clone(),
|
||||||
ip: self.ip,
|
call_stack,
|
||||||
call_stack: self.call_stack.clone(),
|
|
||||||
};
|
};
|
||||||
|
// and gtfo
|
||||||
self.result = Some(Err(panic));
|
self.result = Some(Err(panic));
|
||||||
self.r#yield = true;
|
self.r#yield = true;
|
||||||
}
|
}
|
||||||
|
|
18
src/world.rs
18
src/world.rs
|
@ -2,25 +2,13 @@ use crate::chunk::Chunk;
|
||||||
use crate::value::{Value, Key};
|
use crate::value::{Value, Key};
|
||||||
use crate::vm::Creature;
|
use crate::vm::Creature;
|
||||||
use crate::panic::Panic;
|
use crate::panic::Panic;
|
||||||
|
use crate::errors::panic;
|
||||||
|
use crate::js::{random, now};
|
||||||
use crate::io::{MsgOut, MsgIn, do_io};
|
use crate::io::{MsgOut, MsgIn, do_io};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::mem::swap;
|
use std::mem::swap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wasm_bindgen::prelude::*;
|
|
||||||
|
|
||||||
// Grab some JS stuff
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern "C" {
|
|
||||||
#[wasm_bindgen(js_namespace = console)]
|
|
||||||
fn log(s: &str);
|
|
||||||
|
|
||||||
#[wasm_bindgen(js_namespace = Math)]
|
|
||||||
fn random() -> f64;
|
|
||||||
|
|
||||||
#[wasm_bindgen(js_namespace = Date)]
|
|
||||||
fn now() -> f64;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ANIMALS: [&str; 32] = [
|
const ANIMALS: [&str; 32] = [
|
||||||
"tortoise",
|
"tortoise",
|
||||||
|
@ -420,7 +408,7 @@ impl World {
|
||||||
self.result = Some(result.clone());
|
self.result = Some(result.clone());
|
||||||
let result_msg = match result {
|
let result_msg = match result {
|
||||||
Ok(value) => MsgOut::Complete(Value::string(value.show())),
|
Ok(value) => MsgOut::Complete(Value::string(value.show())),
|
||||||
Err(_msg) => MsgOut::Error("Ludus panicked!".to_string())
|
Err(p) => MsgOut::Error(panic(p))
|
||||||
};
|
};
|
||||||
outbox.push(result_msg);
|
outbox.push(result_msg);
|
||||||
outbox
|
outbox
|
||||||
|
|
Loading…
Reference in New Issue
Block a user