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 */
|
||||
/* 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;
|
||||
|
||||
|
|
16
pkg/rudus.js
16
pkg/rudus.js
|
@ -225,7 +225,7 @@ function debugString(val) {
|
|||
}
|
||||
/**
|
||||
* @param {string} src
|
||||
* @returns {Promise<string>}
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export function ludus(src) {
|
||||
const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
|
@ -237,13 +237,13 @@ export function ludus(src) {
|
|||
function _assertNum(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(arg1);
|
||||
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(arg1);
|
||||
wasm.closure370_externref_shim(arg0, arg1, arg2, arg3);
|
||||
|
@ -346,7 +346,7 @@ function __wbg_get_imports() {
|
|||
const a = state0.a;
|
||||
state0.a = 0;
|
||||
try {
|
||||
return __wbg_adapter_52(a, state0.b, arg0, arg1);
|
||||
return __wbg_adapter_50(a, state0.b, arg0, arg1);
|
||||
} finally {
|
||||
state0.a = a;
|
||||
}
|
||||
|
@ -425,8 +425,8 @@ function __wbg_get_imports() {
|
|||
_assertBoolean(ret);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper7787 = function() { return logError(function (arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 347, __wbg_adapter_22);
|
||||
imports.wbg.__wbindgen_closure_wrapper7819 = function() { return logError(function (arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 347, __wbg_adapter_20);
|
||||
return ret;
|
||||
}, arguments) };
|
||||
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 * 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) {
|
||||
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||
};
|
||||
|
|
Binary file not shown.
|
@ -1,52 +1,44 @@
|
|||
// use crate::process::{LErr, Trace};
|
||||
use crate::lexer::Token;
|
||||
use crate::validator::VErr;
|
||||
use chumsky::prelude::*;
|
||||
|
||||
// pub fn report_panic(err: LErr) {
|
||||
// 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();
|
||||
// }
|
||||
const SEPARATOR: &str = "\n\n***\n";
|
||||
|
||||
pub fn report_invalidation(errs: Vec<VErr>) {
|
||||
for err in errs {
|
||||
// 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))
|
||||
// .finish()
|
||||
// .print(sources(vec![(err.input, err.src)]))
|
||||
// .unwrap();
|
||||
println!("{}", err.msg);
|
||||
}
|
||||
fn line_number(src: &'static str, span: SimpleSpan) -> usize {
|
||||
src.chars().take(span.start).filter(|c| *c == '\n').count()
|
||||
}
|
||||
|
||||
fn get_line(src: &'static str, line: usize) -> String {
|
||||
src.split("\n").nth(line).unwrap().to_string()
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
type Lines = Value; // expect a list of values
|
||||
type Commands = Value; // expect a list of values
|
||||
type Url = Value; // expect a string representing a URL
|
||||
type FinalValue = Result<Value, Panic>;
|
||||
|
@ -29,7 +28,7 @@ fn make_json_payload(verb: &'static str, data: String) -> String {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum MsgOut {
|
||||
Console(Lines),
|
||||
Console(Value),
|
||||
Commands(Commands),
|
||||
Fetch(Url),
|
||||
Complete(FinalValue),
|
||||
|
@ -65,7 +64,7 @@ impl MsgOut {
|
|||
}
|
||||
MsgOut::Console(lines) => {
|
||||
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}\"");
|
||||
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> {
|
||||
let outbox = format!("[{}]", msgs.iter().map(|msg| msg.to_json()).collect::<Vec<_>>().join(","));
|
||||
let inbox = io (outbox).await;
|
||||
|
|
|
@ -70,8 +70,8 @@ pub fn lexer(
|
|||
|
||||
let escape = just('\\')
|
||||
.then(choice((
|
||||
just('\\'),
|
||||
just('"'),
|
||||
just('\\').to('\\'),
|
||||
just('"').to('"'),
|
||||
just('n').to('\n'),
|
||||
just('t').to('\t'),
|
||||
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() };
|
||||
|
||||
mod io;
|
||||
use io::send_err_to_ludus_console;
|
||||
|
||||
mod ast;
|
||||
use crate::ast::Ast;
|
||||
|
@ -37,7 +38,7 @@ mod validator;
|
|||
use crate::validator::Validator;
|
||||
|
||||
mod errors;
|
||||
use crate::errors::report_invalidation;
|
||||
use crate::errors::{lexing, parsing, validation};
|
||||
|
||||
mod chunk;
|
||||
mod op;
|
||||
|
@ -113,13 +114,19 @@ extern "C" {
|
|||
fn log(s: &str);
|
||||
}
|
||||
|
||||
|
||||
#[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();
|
||||
// leak the source so it lives FOREVER
|
||||
let src = src.to_string().leak();
|
||||
|
||||
// lex the source
|
||||
let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
|
||||
if !lex_errs.is_empty() {
|
||||
return format!("{:?}", lex_errs);
|
||||
send_err_to_ludus_console(lexing(lex_errs)).await;
|
||||
return;
|
||||
}
|
||||
|
||||
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)))
|
||||
.into_output_errors();
|
||||
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()));
|
||||
|
@ -141,8 +149,8 @@ pub async fn ludus(src: String) -> String {
|
|||
|
||||
// TODO: validator should generate a string, not print to the console
|
||||
if !validator.errors.is_empty() {
|
||||
report_invalidation(validator.errors);
|
||||
return "Ludus found some validation errors.".to_string();
|
||||
send_err_to_ludus_console(validation(validator.errors)).await;
|
||||
return;
|
||||
}
|
||||
|
||||
let mut compiler = Compiler::new(
|
||||
|
@ -173,7 +181,8 @@ pub async fn ludus(src: String) -> String {
|
|||
world.run().await;
|
||||
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(Err(panic)) => format!("Ludus panicked! {panic}"),
|
||||
None => "Ludus run terminated by user".to_string()
|
||||
|
@ -182,5 +191,4 @@ pub async fn ludus(src: String) -> String {
|
|||
// vm.print_stack();
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
|
|
|
@ -260,8 +260,8 @@ impl Value {
|
|||
use Value::*;
|
||||
match self {
|
||||
True | False | Number(..) => Some(self.show()),
|
||||
String(string) => Some(serde_json::to_string(string.as_ref()).unwrap()),
|
||||
Interned(str) => Some(serde_json::to_string(str).unwrap()),
|
||||
String(string) => Some(string.escape_default().to_string()),
|
||||
Interned(str) => Some(str.escape_default().to_string()),
|
||||
Keyword(str) => Some(format!("\"{str}\"")),
|
||||
List(members) => {
|
||||
let mut joined = "".to_string();
|
||||
|
|
Loading…
Reference in New Issue
Block a user