2024-10-29 03:59:50 +00:00
|
|
|
// an implementation of Ludus
|
|
|
|
|
|
|
|
// curently left undone (and not adding for a while yet):
|
|
|
|
// * sets
|
|
|
|
// * interpolated strings & string patterns
|
|
|
|
// * pkgs, namespaces, imports, `use` forms
|
|
|
|
// * with forms
|
|
|
|
// * test forms
|
|
|
|
// * ignored words
|
|
|
|
|
|
|
|
// todo:
|
2024-10-31 20:28:15 +00:00
|
|
|
// * [x] rewrite fn parser to use chumsky::Recursive::declare/define
|
|
|
|
// - [x] do this to extract/simplify/DRY things like tuple patterns, fn clauses, etc.
|
2024-10-31 19:38:55 +00:00
|
|
|
// * [x] Work around chumsky::Stream::from_iter().spanned disappearing in most recent version
|
2024-10-29 03:59:50 +00:00
|
|
|
// * [x] investigate using labels (which is behind a compiler flag, somehow)
|
2024-11-21 21:41:46 +00:00
|
|
|
// * [ ] write parsing errors
|
2024-10-29 03:59:50 +00:00
|
|
|
// * [ ] wire up Ariadne parsing errors
|
2024-11-21 21:41:46 +00:00
|
|
|
// * [ ] add stack traces and code locations to panics
|
2024-12-11 22:32:31 +00:00
|
|
|
// * [x] validation
|
2024-10-31 20:59:26 +00:00
|
|
|
// * [x] break this out into multiple files
|
2024-11-11 22:50:58 +00:00
|
|
|
// * [x] write a tree-walk VM
|
|
|
|
// - [x] learn how to deal with lifetimes
|
|
|
|
// - [x] with stack mechanics and refcounting
|
|
|
|
// - [ ] with tail-call optimization (nb: this may not be possible w/ a TW-VM)
|
|
|
|
// - [ ] with all the necessary forms for current Ludus
|
2024-11-21 01:10:17 +00:00
|
|
|
// * [x] guards in match clauses
|
2024-11-15 03:19:52 +00:00
|
|
|
// * [x] `as` patterns
|
2024-11-21 01:10:17 +00:00
|
|
|
// * [x] splat patterns in tuples, lists, dicts
|
2024-11-21 21:41:46 +00:00
|
|
|
// * [x] splats in list and dict literals
|
2024-11-21 22:02:54 +00:00
|
|
|
// * [x] `loop` and `recur`
|
2024-12-11 22:32:31 +00:00
|
|
|
// * [x] string patterns
|
2024-12-05 01:19:41 +00:00
|
|
|
// * [x] string interpolation
|
2024-11-22 03:36:57 +00:00
|
|
|
// * [x] docstrings
|
2024-12-11 22:32:31 +00:00
|
|
|
// * [x] write `base` in Rust
|
2024-10-29 03:59:50 +00:00
|
|
|
// * [ ] turn this into a library function
|
|
|
|
// * [ ] compile this into WASM
|
|
|
|
// * [ ] perf testing
|
|
|
|
|
2024-10-31 20:59:26 +00:00
|
|
|
use chumsky::{input::Stream, prelude::*};
|
2024-12-09 04:33:02 +00:00
|
|
|
use rust_embed::Embed;
|
2024-10-29 03:59:50 +00:00
|
|
|
|
2024-10-31 20:59:26 +00:00
|
|
|
mod spans;
|
2024-10-29 03:59:50 +00:00
|
|
|
|
2024-10-31 20:59:26 +00:00
|
|
|
mod lexer;
|
|
|
|
use crate::lexer::*;
|
2024-10-29 03:59:50 +00:00
|
|
|
|
2024-10-31 20:59:26 +00:00
|
|
|
mod value;
|
2024-12-09 04:33:02 +00:00
|
|
|
use crate::value::*;
|
2024-10-29 03:59:50 +00:00
|
|
|
|
2024-10-31 20:59:26 +00:00
|
|
|
mod parser;
|
|
|
|
use crate::parser::*;
|
2024-10-29 03:59:50 +00:00
|
|
|
|
2024-11-11 22:50:58 +00:00
|
|
|
mod base;
|
|
|
|
use crate::base::*;
|
|
|
|
|
2024-12-10 21:44:52 +00:00
|
|
|
mod validator;
|
|
|
|
use crate::validator::*;
|
|
|
|
|
2024-12-11 20:42:50 +00:00
|
|
|
mod process;
|
|
|
|
use crate::process::*;
|
2024-12-09 04:33:02 +00:00
|
|
|
|
2024-12-12 05:31:57 +00:00
|
|
|
mod errors;
|
|
|
|
use crate::errors::*;
|
|
|
|
|
2024-12-09 04:33:02 +00:00
|
|
|
#[derive(Embed)]
|
|
|
|
#[folder = "assets/"]
|
|
|
|
struct Asset;
|
|
|
|
|
2024-12-11 23:58:59 +00:00
|
|
|
pub fn prelude<'src>() -> (
|
|
|
|
Vec<(String, Value<'src>)>,
|
|
|
|
std::collections::HashMap<*const Ast, FnInfo>,
|
|
|
|
) {
|
|
|
|
let prelude = Asset::get("test_prelude.ld").unwrap().data.into_owned();
|
2024-12-09 04:33:02 +00:00
|
|
|
// we know for sure Prelude should live through the whole run of the program
|
|
|
|
let leaked = Box::leak(Box::new(prelude));
|
|
|
|
let prelude = std::str::from_utf8(leaked).unwrap();
|
|
|
|
|
|
|
|
let (ptoks, perrs) = lexer().parse(prelude).into_output_errors();
|
|
|
|
if !perrs.is_empty() {
|
|
|
|
println!("Errors lexing Prelude");
|
|
|
|
println!("{:?}", perrs);
|
|
|
|
panic!();
|
|
|
|
}
|
|
|
|
|
|
|
|
let ptoks = ptoks.unwrap();
|
|
|
|
|
|
|
|
let (p_ast, perrs) = parser()
|
|
|
|
.parse(Stream::from_iter(ptoks).map((0..prelude.len()).into(), |(t, s)| (t, s)))
|
|
|
|
.into_output_errors();
|
|
|
|
if !perrs.is_empty() {
|
|
|
|
println!("Errors parsing Prelude");
|
|
|
|
println!("{:?}", perrs);
|
|
|
|
panic!();
|
|
|
|
}
|
|
|
|
|
2024-12-11 23:58:59 +00:00
|
|
|
let prelude_parsed = Box::leak(Box::new(p_ast.unwrap()));
|
2024-12-09 04:33:02 +00:00
|
|
|
let base_pkg = base();
|
|
|
|
|
2024-12-13 00:01:51 +00:00
|
|
|
let mut v6or = Validator::new(
|
|
|
|
&prelude_parsed.0,
|
|
|
|
prelude_parsed.1,
|
|
|
|
"prelude",
|
|
|
|
prelude,
|
|
|
|
&base_pkg,
|
|
|
|
);
|
2024-12-11 21:43:13 +00:00
|
|
|
v6or.validate();
|
|
|
|
|
2024-12-13 00:01:51 +00:00
|
|
|
if !v6or.errors.is_empty() {
|
|
|
|
report_invalidation(v6or.errors);
|
|
|
|
panic!("interal Ludus error: invalid prelude")
|
|
|
|
}
|
2024-12-11 22:22:37 +00:00
|
|
|
|
2024-12-11 20:42:50 +00:00
|
|
|
let mut base_ctx = Process::<'src> {
|
2024-12-13 00:01:51 +00:00
|
|
|
input: "prelude",
|
|
|
|
src: prelude,
|
|
|
|
locals: base_pkg.clone(),
|
2024-12-11 23:58:59 +00:00
|
|
|
ast: &prelude_parsed.0,
|
|
|
|
span: prelude_parsed.1,
|
2024-12-11 22:22:37 +00:00
|
|
|
prelude: vec![],
|
2024-12-11 21:43:13 +00:00
|
|
|
fn_info: v6or.fn_info,
|
2024-12-09 04:33:02 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let prelude = base_ctx.eval();
|
|
|
|
|
|
|
|
let mut p_ctx = vec![];
|
|
|
|
|
|
|
|
match prelude {
|
|
|
|
Ok(Value::Dict(p_dict)) => {
|
|
|
|
for (key, value) in p_dict.iter() {
|
|
|
|
p_ctx.push((key.to_string(), value.clone()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(_) => {
|
|
|
|
println!("Bad Prelude export");
|
|
|
|
panic!();
|
|
|
|
}
|
|
|
|
Err(LErr { msg, .. }) => {
|
|
|
|
println!("Error running Prelude");
|
|
|
|
println!("{:?}", msg);
|
|
|
|
panic!();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-12-11 23:58:59 +00:00
|
|
|
(p_ctx, base_ctx.fn_info)
|
2024-12-09 04:33:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run(src: &'static str) {
|
2024-10-29 03:59:50 +00:00
|
|
|
let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
|
2024-11-21 23:50:13 +00:00
|
|
|
if !lex_errs.is_empty() {
|
2024-10-29 03:59:50 +00:00
|
|
|
println!("{:?}", lex_errs);
|
2024-11-21 23:50:13 +00:00
|
|
|
return;
|
2024-10-29 03:59:50 +00:00
|
|
|
}
|
|
|
|
let tokens = tokens.unwrap();
|
|
|
|
let to_parse = tokens.clone();
|
2024-12-09 04:33:02 +00:00
|
|
|
|
2024-12-10 22:14:26 +00:00
|
|
|
let (parse_result, parse_errors) = parser()
|
2024-10-31 19:38:55 +00:00
|
|
|
.parse(Stream::from_iter(to_parse).map((0..src.len()).into(), |(t, s)| (t, s)))
|
2024-12-09 04:33:02 +00:00
|
|
|
.into_output_errors();
|
|
|
|
if !parse_errors.is_empty() {
|
|
|
|
println!("{:?}", parse_errors);
|
|
|
|
return;
|
|
|
|
}
|
2024-11-01 03:53:48 +00:00
|
|
|
|
2024-12-11 23:58:59 +00:00
|
|
|
let parsed = parse_result.unwrap();
|
2024-11-01 03:53:48 +00:00
|
|
|
|
2024-12-13 00:01:51 +00:00
|
|
|
let (prelude_ctx, mut prelude_fn_info) = prelude();
|
2024-11-01 03:53:48 +00:00
|
|
|
|
2024-12-13 00:01:51 +00:00
|
|
|
let mut v6or = Validator::new(&parsed.0, parsed.1, "script", src, &prelude_ctx);
|
2024-11-21 23:50:13 +00:00
|
|
|
|
2024-12-11 04:42:05 +00:00
|
|
|
v6or.validate();
|
2024-12-10 22:14:26 +00:00
|
|
|
|
2024-12-11 23:58:59 +00:00
|
|
|
prelude_fn_info.extend(&mut v6or.fn_info.into_iter());
|
|
|
|
|
|
|
|
let mut proc = Process {
|
2024-12-13 00:01:51 +00:00
|
|
|
input: "script",
|
|
|
|
src,
|
2024-12-11 23:58:59 +00:00
|
|
|
locals: vec![],
|
|
|
|
prelude: prelude_ctx,
|
|
|
|
ast: &parsed.0,
|
|
|
|
span: parsed.1,
|
|
|
|
fn_info: prelude_fn_info,
|
|
|
|
};
|
2024-12-10 22:14:26 +00:00
|
|
|
|
2024-12-11 21:43:13 +00:00
|
|
|
let result = proc.eval();
|
2024-12-10 22:14:26 +00:00
|
|
|
|
2024-12-11 03:26:52 +00:00
|
|
|
match result {
|
|
|
|
Ok(result) => println!("{}", result),
|
2024-12-13 00:01:51 +00:00
|
|
|
Err(err) => report_panic(err),
|
2024-12-11 03:26:52 +00:00
|
|
|
}
|
2024-12-09 04:33:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn main() {
|
|
|
|
let src = "
|
2024-12-13 00:01:51 +00:00
|
|
|
fn foo () -> panics! ()
|
|
|
|
foo ()
|
2024-12-09 04:33:02 +00:00
|
|
|
";
|
|
|
|
run(src);
|
2024-11-21 23:50:13 +00:00
|
|
|
// struct_scalpel::print_dissection_info::<value::Value>()
|
|
|
|
// struct_scalpel::print_dissection_info::<parser::Ast>();
|
|
|
|
// println!("{}", std::mem::size_of::<parser::Ast>())
|
2024-10-29 03:59:50 +00:00
|
|
|
}
|