work on errors
This commit is contained in:
parent
2ffff9edd9
commit
d334e483a5
2
pkg/rudus.d.ts
vendored
2
pkg/rudus.d.ts
vendored
|
@ -1,6 +1,6 @@
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
export function ludus(src: string): Promise<string>;
|
export function ludus(src: string): Promise<void>;
|
||||||
|
|
||||||
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||||
|
|
||||||
|
|
16
pkg/rudus.js
16
pkg/rudus.js
|
@ -225,7 +225,7 @@ function debugString(val) {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @param {string} src
|
* @param {string} src
|
||||||
* @returns {Promise<string>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
export function ludus(src) {
|
export function ludus(src) {
|
||||||
const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||||
|
@ -237,13 +237,13 @@ export function ludus(src) {
|
||||||
function _assertNum(n) {
|
function _assertNum(n) {
|
||||||
if (typeof(n) !== 'number') throw new Error(`expected a number argument, found ${typeof(n)}`);
|
if (typeof(n) !== 'number') throw new Error(`expected a number argument, found ${typeof(n)}`);
|
||||||
}
|
}
|
||||||
function __wbg_adapter_22(arg0, arg1, arg2) {
|
function __wbg_adapter_20(arg0, arg1, arg2) {
|
||||||
_assertNum(arg0);
|
_assertNum(arg0);
|
||||||
_assertNum(arg1);
|
_assertNum(arg1);
|
||||||
wasm.closure346_externref_shim(arg0, arg1, arg2);
|
wasm.closure346_externref_shim(arg0, arg1, arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function __wbg_adapter_52(arg0, arg1, arg2, arg3) {
|
function __wbg_adapter_50(arg0, arg1, arg2, arg3) {
|
||||||
_assertNum(arg0);
|
_assertNum(arg0);
|
||||||
_assertNum(arg1);
|
_assertNum(arg1);
|
||||||
wasm.closure370_externref_shim(arg0, arg1, arg2, arg3);
|
wasm.closure370_externref_shim(arg0, arg1, arg2, arg3);
|
||||||
|
@ -346,7 +346,7 @@ function __wbg_get_imports() {
|
||||||
const a = state0.a;
|
const a = state0.a;
|
||||||
state0.a = 0;
|
state0.a = 0;
|
||||||
try {
|
try {
|
||||||
return __wbg_adapter_52(a, state0.b, arg0, arg1);
|
return __wbg_adapter_50(a, state0.b, arg0, arg1);
|
||||||
} finally {
|
} finally {
|
||||||
state0.a = a;
|
state0.a = a;
|
||||||
}
|
}
|
||||||
|
@ -425,8 +425,8 @@ function __wbg_get_imports() {
|
||||||
_assertBoolean(ret);
|
_assertBoolean(ret);
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
imports.wbg.__wbindgen_closure_wrapper7787 = function() { return logError(function (arg0, arg1, arg2) {
|
imports.wbg.__wbindgen_closure_wrapper7819 = function() { return logError(function (arg0, arg1, arg2) {
|
||||||
const ret = makeMutClosure(arg0, arg1, 347, __wbg_adapter_22);
|
const ret = makeMutClosure(arg0, arg1, 347, __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) {
|
||||||
|
@ -464,10 +464,6 @@ function __wbg_get_imports() {
|
||||||
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||||
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||||
};
|
};
|
||||||
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
|
|
||||||
const ret = getStringFromWasm0(arg0, arg1);
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||||
throw new Error(getStringFromWasm0(arg0, arg1));
|
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||||
};
|
};
|
||||||
|
|
Binary file not shown.
|
@ -1,52 +1,44 @@
|
||||||
// use crate::process::{LErr, Trace};
|
// use crate::process::{LErr, Trace};
|
||||||
|
use crate::lexer::Token;
|
||||||
use crate::validator::VErr;
|
use crate::validator::VErr;
|
||||||
|
use chumsky::prelude::*;
|
||||||
|
|
||||||
// pub fn report_panic(err: LErr) {
|
const SEPARATOR: &str = "\n\n***\n";
|
||||||
// let mut srcs = HashSet::new();
|
|
||||||
// let mut stack = vec![];
|
|
||||||
// let mut order = 1;
|
|
||||||
// for entry in err.trace.iter().rev() {
|
|
||||||
// let Trace {
|
|
||||||
// callee,
|
|
||||||
// caller,
|
|
||||||
// function,
|
|
||||||
// arguments,
|
|
||||||
// input,
|
|
||||||
// src,
|
|
||||||
// } = entry;
|
|
||||||
// let (_, first_span) = callee;
|
|
||||||
// let (_, second_span) = caller;
|
|
||||||
// let Value::Fn(f) = function else {
|
|
||||||
// unreachable!()
|
|
||||||
// };
|
|
||||||
// let fn_name = f.borrow().name.clone();
|
|
||||||
// let i = first_span.start;
|
|
||||||
// let j = second_span.end;
|
|
||||||
// let label = Label::new((entry.input, i..j))
|
|
||||||
// .with_color(Color::Yellow)
|
|
||||||
// .with_message(format!("({order}) calling `{fn_name}` with `{arguments}`"));
|
|
||||||
// order += 1;
|
|
||||||
// stack.push(label);
|
|
||||||
// srcs.insert((*input, *src));
|
|
||||||
// }
|
|
||||||
// Report::build(ReportKind::Error, (err.input, err.span.into_range()))
|
|
||||||
// .with_message(format!("Ludus panicked! {}", err.msg))
|
|
||||||
// .with_label(Label::new((err.input, err.span.into_range())).with_color(Color::Red))
|
|
||||||
// .with_labels(stack)
|
|
||||||
// .with_note(err.extra)
|
|
||||||
// .finish()
|
|
||||||
// .print(sources(srcs.iter().copied()))
|
|
||||||
// .unwrap();
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn report_invalidation(errs: Vec<VErr>) {
|
fn line_number(src: &'static str, span: SimpleSpan) -> usize {
|
||||||
for err in errs {
|
src.chars().take(span.start).filter(|c| *c == '\n').count()
|
||||||
// Report::build(ReportKind::Error, (err.input, err.span.into_range()))
|
}
|
||||||
// .with_message(err.msg.to_string())
|
|
||||||
// .with_label(Label::new((err.input, err.span.into_range())).with_color(Color::Cyan))
|
fn get_line(src: &'static str, line: usize) -> String {
|
||||||
// .finish()
|
src.split("\n").nth(line).unwrap().to_string()
|
||||||
// .print(sources(vec![(err.input, err.src)]))
|
}
|
||||||
// .unwrap();
|
|
||||||
println!("{}", err.msg);
|
pub fn lexing(errs: Vec<Rich<'static, char>>) -> String {
|
||||||
}
|
let mut msg = "Syntax errors".to_string();
|
||||||
|
for err in errs {
|
||||||
|
msg = format!("{msg}\n{:#?}", err);
|
||||||
|
}
|
||||||
|
msg
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn validation(errs: Vec<VErr>) -> String {
|
||||||
|
let mut msgs = vec![];
|
||||||
|
for err in errs {
|
||||||
|
let mut msg = vec![];
|
||||||
|
let line_number = line_number(err.src, *err.span);
|
||||||
|
let line = get_line(err.src, line_number);
|
||||||
|
msg.push(format!("Validation error: {}", err.msg));
|
||||||
|
msg.push(format!(" on line {} in {}", line_number + 1, err.input));
|
||||||
|
msg.push(format!(" >>> {line}"));
|
||||||
|
msgs.push(msg.join("\n"));
|
||||||
|
}
|
||||||
|
msgs.join(SEPARATOR)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parsing(errs: Vec<Rich<'static, Token>>) -> String {
|
||||||
|
let mut msg = "Syntax errors".to_string();
|
||||||
|
for err in errs {
|
||||||
|
msg = format!("{msg}\n{:#?}", err);
|
||||||
|
}
|
||||||
|
msg
|
||||||
}
|
}
|
||||||
|
|
16
src/io.rs
16
src/io.rs
|
@ -18,7 +18,6 @@ extern "C" {
|
||||||
fn log(s: String);
|
fn log(s: String);
|
||||||
}
|
}
|
||||||
|
|
||||||
type Lines = Value; // expect a list of values
|
|
||||||
type Commands = Value; // expect a list of values
|
type Commands = Value; // expect a list of values
|
||||||
type Url = Value; // expect a string representing a URL
|
type Url = Value; // expect a string representing a URL
|
||||||
type FinalValue = Result<Value, Panic>;
|
type FinalValue = Result<Value, Panic>;
|
||||||
|
@ -29,7 +28,7 @@ fn make_json_payload(verb: &'static str, data: String) -> String {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum MsgOut {
|
pub enum MsgOut {
|
||||||
Console(Lines),
|
Console(Value),
|
||||||
Commands(Commands),
|
Commands(Commands),
|
||||||
Fetch(Url),
|
Fetch(Url),
|
||||||
Complete(FinalValue),
|
Complete(FinalValue),
|
||||||
|
@ -65,7 +64,7 @@ impl MsgOut {
|
||||||
}
|
}
|
||||||
MsgOut::Console(lines) => {
|
MsgOut::Console(lines) => {
|
||||||
let lines = lines.as_list();
|
let lines = lines.as_list();
|
||||||
let json_lines = lines.iter().map(|line| line.stringify()).collect::<Vec<_>>().join("\\n");
|
let json_lines = lines.iter().map(|line| line.to_json().unwrap()).collect::<Vec<_>>().join("\\n");
|
||||||
let json_lines = format!("\"{json_lines}\"");
|
let json_lines = format!("\"{json_lines}\"");
|
||||||
make_json_payload("Console", json_lines)
|
make_json_payload("Console", json_lines)
|
||||||
}
|
}
|
||||||
|
@ -123,6 +122,17 @@ impl MsgIn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn send_err_to_ludus_console(msg: String) {
|
||||||
|
log(msg.clone());
|
||||||
|
let console_msg = Value::string(msg);
|
||||||
|
let mut console_vector = Vector::new();
|
||||||
|
console_vector.push_back(console_msg);
|
||||||
|
let console_list = Value::list(console_vector);
|
||||||
|
let console = MsgOut::Console(console_list);
|
||||||
|
let completion = MsgOut::Complete(Err(Panic::Str("")));
|
||||||
|
do_io(vec![MsgOut::Ready, console, completion]).await;
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn do_io (msgs: Vec<MsgOut>) -> Vec<MsgIn> {
|
pub async fn do_io (msgs: Vec<MsgOut>) -> Vec<MsgIn> {
|
||||||
let outbox = format!("[{}]", msgs.iter().map(|msg| msg.to_json()).collect::<Vec<_>>().join(","));
|
let outbox = format!("[{}]", msgs.iter().map(|msg| msg.to_json()).collect::<Vec<_>>().join(","));
|
||||||
let inbox = io (outbox).await;
|
let inbox = io (outbox).await;
|
||||||
|
|
|
@ -70,8 +70,8 @@ pub fn lexer(
|
||||||
|
|
||||||
let escape = just('\\')
|
let escape = just('\\')
|
||||||
.then(choice((
|
.then(choice((
|
||||||
just('\\'),
|
just('\\').to('\\'),
|
||||||
just('"'),
|
just('"').to('"'),
|
||||||
just('n').to('\n'),
|
just('n').to('\n'),
|
||||||
just('t').to('\t'),
|
just('t').to('\t'),
|
||||||
just('r').to('\r'),
|
just('r').to('\r'),
|
||||||
|
|
24
src/lib.rs
24
src/lib.rs
|
@ -15,6 +15,7 @@ const DEBUG_PRELUDE_RUN: bool = false;
|
||||||
// static ALLOCATOR: talc::TalckWasm = unsafe { talc::TalckWasm::new_global() };
|
// static ALLOCATOR: talc::TalckWasm = unsafe { talc::TalckWasm::new_global() };
|
||||||
|
|
||||||
mod io;
|
mod io;
|
||||||
|
use io::send_err_to_ludus_console;
|
||||||
|
|
||||||
mod ast;
|
mod ast;
|
||||||
use crate::ast::Ast;
|
use crate::ast::Ast;
|
||||||
|
@ -37,7 +38,7 @@ mod validator;
|
||||||
use crate::validator::Validator;
|
use crate::validator::Validator;
|
||||||
|
|
||||||
mod errors;
|
mod errors;
|
||||||
use crate::errors::report_invalidation;
|
use crate::errors::{lexing, parsing, validation};
|
||||||
|
|
||||||
mod chunk;
|
mod chunk;
|
||||||
mod op;
|
mod op;
|
||||||
|
@ -113,13 +114,19 @@ extern "C" {
|
||||||
fn log(s: &str);
|
fn log(s: &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub async fn ludus(src: String) -> String {
|
pub async fn ludus(src: String) {
|
||||||
|
// instrument wasm to report rust panics
|
||||||
console_error_panic_hook::set_once();
|
console_error_panic_hook::set_once();
|
||||||
|
// leak the source so it lives FOREVER
|
||||||
let src = src.to_string().leak();
|
let src = src.to_string().leak();
|
||||||
|
|
||||||
|
// lex the source
|
||||||
let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
|
let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
|
||||||
if !lex_errs.is_empty() {
|
if !lex_errs.is_empty() {
|
||||||
return format!("{:?}", lex_errs);
|
send_err_to_ludus_console(lexing(lex_errs)).await;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let tokens = tokens.unwrap();
|
let tokens = tokens.unwrap();
|
||||||
|
@ -128,7 +135,8 @@ pub async fn ludus(src: String) -> String {
|
||||||
.parse(Stream::from_iter(tokens).map((0..src.len()).into(), |(t, s)| (t, s)))
|
.parse(Stream::from_iter(tokens).map((0..src.len()).into(), |(t, s)| (t, s)))
|
||||||
.into_output_errors();
|
.into_output_errors();
|
||||||
if !parse_errors.is_empty() {
|
if !parse_errors.is_empty() {
|
||||||
return format!("{:?}", parse_errors);
|
send_err_to_ludus_console(parsing(parse_errors)).await;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let parsed: &'static Spanned<Ast> = Box::leak(Box::new(parse_result.unwrap()));
|
let parsed: &'static Spanned<Ast> = Box::leak(Box::new(parse_result.unwrap()));
|
||||||
|
@ -141,8 +149,8 @@ pub async fn ludus(src: String) -> String {
|
||||||
|
|
||||||
// TODO: validator should generate a string, not print to the console
|
// TODO: validator should generate a string, not print to the console
|
||||||
if !validator.errors.is_empty() {
|
if !validator.errors.is_empty() {
|
||||||
report_invalidation(validator.errors);
|
send_err_to_ludus_console(validation(validator.errors)).await;
|
||||||
return "Ludus found some validation errors.".to_string();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut compiler = Compiler::new(
|
let mut compiler = Compiler::new(
|
||||||
|
@ -173,7 +181,8 @@ pub async fn ludus(src: String) -> String {
|
||||||
world.run().await;
|
world.run().await;
|
||||||
let result = world.result.clone();
|
let result = world.result.clone();
|
||||||
|
|
||||||
let output = match result {
|
// TODO: actually do something useful on a panic
|
||||||
|
match result {
|
||||||
Some(Ok(val)) => val.show(),
|
Some(Ok(val)) => val.show(),
|
||||||
Some(Err(panic)) => format!("Ludus panicked! {panic}"),
|
Some(Err(panic)) => format!("Ludus panicked! {panic}"),
|
||||||
None => "Ludus run terminated by user".to_string()
|
None => "Ludus run terminated by user".to_string()
|
||||||
|
@ -182,5 +191,4 @@ pub async fn ludus(src: String) -> String {
|
||||||
// vm.print_stack();
|
// vm.print_stack();
|
||||||
}
|
}
|
||||||
|
|
||||||
output
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,8 +260,8 @@ impl Value {
|
||||||
use Value::*;
|
use Value::*;
|
||||||
match self {
|
match self {
|
||||||
True | False | Number(..) => Some(self.show()),
|
True | False | Number(..) => Some(self.show()),
|
||||||
String(string) => Some(serde_json::to_string(string.as_ref()).unwrap()),
|
String(string) => Some(string.escape_default().to_string()),
|
||||||
Interned(str) => Some(serde_json::to_string(str).unwrap()),
|
Interned(str) => Some(str.escape_default().to_string()),
|
||||||
Keyword(str) => Some(format!("\"{str}\"")),
|
Keyword(str) => Some(format!("\"{str}\"")),
|
||||||
List(members) => {
|
List(members) => {
|
||||||
let mut joined = "".to_string();
|
let mut joined = "".to_string();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user