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": {
|
||||
console.log("Main: ludus errored with => ", msg.data)
|
||||
ludus_result = msg.data
|
||||
running = false
|
||||
ready = false
|
||||
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_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||
readonly __wbindgen_export_6: WebAssembly.Table;
|
||||
readonly closure352_externref_shim: (a: number, b: number, c: any) => void;
|
||||
readonly closure375_externref_shim: (a: number, b: number, c: any, d: any) => void;
|
||||
readonly closure353_externref_shim: (a: number, b: number, c: any) => void;
|
||||
readonly closure376_externref_shim: (a: number, b: number, c: any, d: any) => 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) {
|
||||
_assertNum(arg0);
|
||||
_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(arg1);
|
||||
wasm.closure375_externref_shim(arg0, arg1, arg2, arg3);
|
||||
wasm.closure376_externref_shim(arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
async function __wbg_load(module, imports) {
|
||||
|
@ -314,31 +314,9 @@ function __wbg_get_imports() {
|
|||
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
|
||||
}
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_log_86d603e98cc11395 = 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) };
|
||||
imports.wbg.__wbg_log_9e426f8e841e42d3 = function() { return logError(function (arg0, arg1) {
|
||||
imports.wbg.__wbg_log_11652c6a56eeddfb = 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) };
|
||||
imports.wbg.__wbg_new_23a2665fac83c611 = function() { return logError(function (arg0, arg1) {
|
||||
try {
|
||||
var state0 = {a: arg0, b: arg1};
|
||||
|
@ -346,7 +324,7 @@ function __wbg_get_imports() {
|
|||
const a = state0.a;
|
||||
state0.a = 0;
|
||||
try {
|
||||
return __wbg_adapter_50(a, state0.b, arg0, arg1);
|
||||
return __wbg_adapter_46(a, state0.b, arg0, arg1);
|
||||
} finally {
|
||||
state0.a = a;
|
||||
}
|
||||
|
@ -425,8 +403,8 @@ function __wbg_get_imports() {
|
|||
_assertBoolean(ret);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper8059 = function() { return logError(function (arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 353, __wbg_adapter_20);
|
||||
imports.wbg.__wbindgen_closure_wrapper8065 = function() { return logError(function (arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 354, __wbg_adapter_20);
|
||||
return ret;
|
||||
}, arguments) };
|
||||
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_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||
export const __wbindgen_export_6: WebAssembly.Table;
|
||||
export const closure352_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 closure353_externref_shim: (a: number, b: number, c: any) => void;
|
||||
export const closure376_externref_shim: (a: number, b: number, c: any, d: any) => 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 imbl::*;
|
||||
use std::rc::Rc;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
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 {
|
||||
let Value::List(args) = x else {
|
||||
unreachable!("internal Ludus error")
|
||||
|
@ -284,7 +278,7 @@ pub fn print(x: &Value) -> Value {
|
|||
.collect::<Vec<_>>()
|
||||
.join(" ");
|
||||
// println!("{out}");
|
||||
log(out);
|
||||
console_log!("{out}");
|
||||
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 {
|
||||
Value::Number(random())
|
||||
}
|
||||
|
|
21
src/chunk.rs
21
src/chunk.rs
|
@ -1,3 +1,4 @@
|
|||
use crate::js::*;
|
||||
use crate::op::Op;
|
||||
use crate::value::{Key, Value};
|
||||
use chumsky::prelude::SimpleSpan;
|
||||
|
@ -43,20 +44,20 @@ impl Chunk {
|
|||
| UnconditionalMatch | Print | AppendList | ConcatList | PushList | PushDict
|
||||
| AppendDict | ConcatDict | Nothing | PushGlobal | SetUpvalue | LoadMessage
|
||||
| NextMessage | MatchMessage | ClearMessage | SendMethod | LoadScrutinee => {
|
||||
println!("{i:04}: {op}")
|
||||
console_log!("{i:04}: {op}")
|
||||
}
|
||||
Constant | MatchConstant => {
|
||||
let high = self.bytecode[*i + 1];
|
||||
let low = self.bytecode[*i + 2];
|
||||
let idx = ((high as usize) << 8) + low as usize;
|
||||
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;
|
||||
}
|
||||
Msg => {
|
||||
let msg_idx = self.bytecode[*i + 1];
|
||||
let msg = &self.msgs[msg_idx as usize];
|
||||
println!("{i:04}: {msg}");
|
||||
console_log!("{i:04}: {msg}");
|
||||
*i += 1;
|
||||
}
|
||||
PushBinding | MatchTuple | MatchSplattedTuple | LoadSplattedTuple | MatchList
|
||||
|
@ -64,7 +65,7 @@ impl Chunk {
|
|||
| DropDictEntry | LoadDictValue | PushTuple | PushBox | MatchDepth | PopN | StoreN
|
||||
| Call | GetUpvalue | Partial | MatchString | PushStringMatches | TailCall | LoadN => {
|
||||
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;
|
||||
}
|
||||
Jump | JumpIfFalse | JumpIfTrue | JumpIfNoMatch | JumpIfMatch | JumpBack
|
||||
|
@ -72,26 +73,18 @@ impl Chunk {
|
|||
let high = self.bytecode[*i + 1];
|
||||
let low = self.bytecode[*i + 2];
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dissasemble(&self) {
|
||||
println!("IDX | CODE | INFO");
|
||||
console_log!("IDX | CODE | INFO");
|
||||
let mut i = 0;
|
||||
while i < self.bytecode.len() {
|
||||
self.dissasemble_instr(&mut i);
|
||||
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 match_depth: usize,
|
||||
pub stack_depth: usize,
|
||||
pub spans: Vec<SimpleSpan>,
|
||||
pub nodes: Vec<&'static Ast>,
|
||||
pub ast: &'static Ast,
|
||||
pub span: SimpleSpan,
|
||||
pub src: &'static str,
|
||||
pub name: &'static str,
|
||||
pub input: &'static str,
|
||||
pub depth: usize,
|
||||
pub upvalues: Vec<&'static str>,
|
||||
loop_info: Vec<LoopInfo>,
|
||||
|
@ -98,7 +96,7 @@ fn has_placeholder(args: &[Spanned<Ast>]) -> bool {
|
|||
impl Compiler {
|
||||
pub fn new(
|
||||
ast: &'static Spanned<Ast>,
|
||||
name: &'static str,
|
||||
input: &'static str,
|
||||
src: &'static str,
|
||||
depth: usize,
|
||||
env: imbl::HashMap<Key, Value>,
|
||||
|
@ -111,6 +109,9 @@ impl Compiler {
|
|||
string_patterns: vec![],
|
||||
env,
|
||||
msgs: vec![],
|
||||
src,
|
||||
input,
|
||||
spans: vec![],
|
||||
};
|
||||
Compiler {
|
||||
chunk,
|
||||
|
@ -119,14 +120,12 @@ impl Compiler {
|
|||
scope_depth: -1,
|
||||
match_depth: 0,
|
||||
stack_depth: 0,
|
||||
spans: vec![],
|
||||
nodes: vec![],
|
||||
ast: &ast.0,
|
||||
span: ast.1,
|
||||
loop_info: vec![],
|
||||
upvalues: vec![],
|
||||
src,
|
||||
name,
|
||||
input,
|
||||
tail_pos: false,
|
||||
debug,
|
||||
}
|
||||
|
@ -147,8 +146,8 @@ impl Compiler {
|
|||
let low = len as u8;
|
||||
let high = (len >> 8) as u8;
|
||||
self.emit_op(op);
|
||||
self.chunk.bytecode.push(high);
|
||||
self.chunk.bytecode.push(low);
|
||||
self.emit_byte(high as usize);
|
||||
self.emit_byte(low as usize);
|
||||
}
|
||||
|
||||
fn stub_jump(&mut self, op: Op) -> usize {
|
||||
|
@ -188,8 +187,8 @@ impl Compiler {
|
|||
self.emit_op(Op::Constant);
|
||||
let low = const_idx as u8;
|
||||
let high = (const_idx >> 8) as u8;
|
||||
self.chunk.bytecode.push(high);
|
||||
self.chunk.bytecode.push(low);
|
||||
self.emit_byte(high as usize);
|
||||
self.emit_byte(low as usize);
|
||||
self.stack_depth += 1;
|
||||
}
|
||||
|
||||
|
@ -215,18 +214,18 @@ impl Compiler {
|
|||
self.emit_op(Op::MatchConstant);
|
||||
let low = const_idx as u8;
|
||||
let high = (const_idx >> 8) as u8;
|
||||
self.chunk.bytecode.push(high);
|
||||
self.chunk.bytecode.push(low);
|
||||
self.emit_byte(high as usize);
|
||||
self.emit_byte(low as usize);
|
||||
}
|
||||
|
||||
fn emit_op(&mut self, op: Op) {
|
||||
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) {
|
||||
self.chunk.bytecode.push(byte as u8);
|
||||
self.spans.push(self.span);
|
||||
self.chunk.spans.push(self.span);
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
|
@ -234,7 +233,7 @@ impl Compiler {
|
|||
}
|
||||
|
||||
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!(
|
||||
"stack depth: {}; match depth: {}",
|
||||
self.stack_depth, self.match_depth
|
||||
|
@ -275,7 +274,7 @@ impl Compiler {
|
|||
fn resolve_binding(&mut self, name: &'static str) {
|
||||
self.msg(format!(
|
||||
"resolving binding `{name}` in {}\nlocals: {}",
|
||||
self.name,
|
||||
self.input,
|
||||
self.bindings
|
||||
.iter()
|
||||
.map(|binding| format!("{binding}"))
|
||||
|
@ -1161,7 +1160,7 @@ impl Compiler {
|
|||
None => {
|
||||
let mut compiler = Compiler::new(
|
||||
clause,
|
||||
name,
|
||||
self.input,
|
||||
self.src,
|
||||
self.depth + 1,
|
||||
self.chunk.env.clone(),
|
||||
|
@ -1502,7 +1501,7 @@ impl Compiler {
|
|||
}
|
||||
|
||||
pub fn disassemble(&self) {
|
||||
println!("=== chunk: {} ===", self.name);
|
||||
println!("=== chunk: {} ===", self.input);
|
||||
self.chunk.dissasemble();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
// use crate::process::{LErr, Trace};
|
||||
use crate::js::*;
|
||||
use crate::lexer::Token;
|
||||
use crate::validator::VErr;
|
||||
use crate::panic::{Panic, PanicMsg};
|
||||
use crate::validator::VErr;
|
||||
use crate::vm::CallFrame;
|
||||
use chumsky::error::RichPattern;
|
||||
use chumsky::prelude::*;
|
||||
|
||||
|
||||
const SEPARATOR: &str = "\n\n";
|
||||
|
||||
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}")
|
||||
}
|
||||
|
||||
pub fn panic(panic: Panic, src: &'static str, input: &'static str) -> String {
|
||||
let msgs = vec!["Ludus panicked!".to_string()];
|
||||
pub fn panic(panic: Panic) -> 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 {
|
||||
PanicMsg::Generic(s) => s,
|
||||
_ => "no match".to_string(),
|
||||
PanicMsg::Generic(ref s) => s,
|
||||
_ => &"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));
|
||||
}
|
||||
|
||||
todo!()
|
||||
|
||||
traceback.join("\n")
|
||||
}
|
||||
|
||||
fn traceback(_panic: Panic) -> String {
|
||||
todo!()
|
||||
fn frame_info(frame: &CallFrame) -> String {
|
||||
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
|
||||
// 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
|
||||
|
@ -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
|
||||
// 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
|
||||
|
||||
|
|
13
src/io.rs
13
src/io.rs
|
@ -1,6 +1,7 @@
|
|||
use wasm_bindgen::prelude::*;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use crate::value::Value;
|
||||
use crate::js::*;
|
||||
use imbl::Vector;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -13,12 +14,6 @@ extern "C" {
|
|||
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 Commands = Value; // expect a list of command tuples
|
||||
|
||||
|
@ -81,7 +76,7 @@ impl MsgIn {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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: Vec<MsgIn> = serde_json::from_str(inbox.as_str()).expect("response from js should be valid");
|
||||
if !inbox.is_empty() {
|
||||
log("ludus received messages".to_string());
|
||||
console_log!("ludus received messages");
|
||||
for msg in inbox.iter() {
|
||||
log(format!("{}", msg));
|
||||
console_log!("{}", msg);
|
||||
}
|
||||
}
|
||||
inbox
|
||||
|
|
21
src/lib.rs
21
src/lib.rs
|
@ -42,6 +42,9 @@ use crate::errors::{lexing, parsing, validation};
|
|||
|
||||
mod panic;
|
||||
|
||||
mod js;
|
||||
use crate::js::*;
|
||||
|
||||
mod chunk;
|
||||
mod op;
|
||||
|
||||
|
@ -63,8 +66,8 @@ fn prelude() -> HashMap<Key, Value> {
|
|||
.into_output_errors();
|
||||
|
||||
if !parse_errors.is_empty() {
|
||||
log("ERROR PARSING PRELUDE:");
|
||||
log(format!("{:?}", parse_errors).as_str());
|
||||
console_log!("ERROR PARSING PRELUDE:");
|
||||
console_log!("{:?}", parse_errors);
|
||||
panic!("parsing errors in prelude");
|
||||
}
|
||||
|
||||
|
@ -80,9 +83,9 @@ fn prelude() -> HashMap<Key, Value> {
|
|||
validator.validate();
|
||||
|
||||
if !validator.errors.is_empty() {
|
||||
log("VALIDATION ERRORS IN PRLUDE:");
|
||||
console_log!("VALIDATION ERRORS IN PRLUDE:");
|
||||
// report_invalidation(validator.errors);
|
||||
log(format!("{:?}", validator.errors).as_str());
|
||||
console_log!("{:?}", validator.errors);
|
||||
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]
|
||||
pub async fn ludus(src: String) {
|
||||
// instrument wasm to report rust panics
|
||||
|
@ -157,7 +153,7 @@ pub async fn ludus(src: String) {
|
|||
|
||||
let mut compiler = Compiler::new(
|
||||
parsed,
|
||||
"ludus script",
|
||||
"user script",
|
||||
src,
|
||||
0,
|
||||
prelude.clone(),
|
||||
|
@ -181,7 +177,6 @@ pub async fn ludus(src: String) {
|
|||
|
||||
let mut world = World::new(vm_chunk, prelude.clone(), DEBUG_SCRIPT_RUN);
|
||||
world.run().await;
|
||||
// let result = world.result.clone();
|
||||
|
||||
// TODO: actually do something useful on a panic
|
||||
// match result {
|
||||
|
|
32
src/panic.rs
32
src/panic.rs
|
@ -1,3 +1,4 @@
|
|||
use crate::errors::panic;
|
||||
use crate::value::Value;
|
||||
use crate::vm::CallFrame;
|
||||
|
||||
|
@ -9,11 +10,38 @@ pub enum PanicMsg {
|
|||
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)]
|
||||
pub struct Panic {
|
||||
pub msg: PanicMsg,
|
||||
pub frame: CallFrame,
|
||||
pub scrutinee: Option<Value>,
|
||||
pub ip: usize,
|
||||
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::chunk::Chunk;
|
||||
use crate::js::*;
|
||||
use crate::op::Op;
|
||||
use crate::panic::{Panic, PanicMsg};
|
||||
use crate::value::{Key, LFn, Value};
|
||||
|
@ -83,7 +84,7 @@ impl std::fmt::Display for Creature {
|
|||
impl Creature {
|
||||
pub fn new(chunk: Chunk, zoo: Rc<RefCell<Zoo>>, debug: bool) -> Creature {
|
||||
let lfn = LFn::Defined {
|
||||
name: "user script",
|
||||
name: "toplevel",
|
||||
doc: None,
|
||||
chunks: vec![chunk],
|
||||
arities: vec![0],
|
||||
|
@ -185,42 +186,28 @@ impl Creature {
|
|||
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) {
|
||||
// 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 {
|
||||
msg,
|
||||
frame: self.frame.clone(),
|
||||
scrutinee: self.scrutinee.clone(),
|
||||
ip: self.ip,
|
||||
call_stack: self.call_stack.clone(),
|
||||
call_stack,
|
||||
};
|
||||
// and gtfo
|
||||
self.result = Some(Err(panic));
|
||||
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::vm::Creature;
|
||||
use crate::panic::Panic;
|
||||
use crate::errors::panic;
|
||||
use crate::js::{random, now};
|
||||
use crate::io::{MsgOut, MsgIn, do_io};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::mem::swap;
|
||||
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] = [
|
||||
"tortoise",
|
||||
|
@ -420,7 +408,7 @@ impl World {
|
|||
self.result = Some(result.clone());
|
||||
let result_msg = match result {
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue
Block a user