rudus/src/main.rs

186 lines
4.8 KiB
Rust
Raw Normal View History

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:
// * [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
// * [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
// * [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
mod base;
use crate::base::*;
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
#[derive(Embed)]
#[folder = "assets/"]
struct Asset;
2024-12-11 20:42:50 +00:00
pub fn prelude<'src>() -> Process<'src> {
2024-12-11 22:32:31 +00:00
let prelude = Asset::get("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 21:43:13 +00:00
let (p_ast, p_span) = Box::leak(Box::new(p_ast.unwrap()));
2024-12-09 04:33:02 +00:00
let base_pkg = base();
2024-12-11 21:43:13 +00:00
let base_names = base_pkg.iter().map(|binding| binding.0.clone()).collect();
let mut v6or = Validator::new(p_ast, *p_span, &base_names);
v6or.validate();
// dbg!(&v6or);
2024-12-11 20:42:50 +00:00
let mut base_ctx = Process::<'src> {
locals: base_pkg,
2024-12-09 04:33:02 +00:00
ast: p_ast,
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 20:42:50 +00:00
Process {
2024-12-09 04:33:02 +00:00
locals: vec![],
ast: &Ast::Nil,
prelude: p_ctx,
2024-12-11 21:43:13 +00:00
fn_info: 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-12-10 22:14:26 +00:00
let (ast, span) = parse_result.unwrap();
2024-12-10 22:14:26 +00:00
let dummy_prelude = vec![];
2024-12-11 21:43:13 +00:00
let mut v6or = Validator::new(&ast, span, &dummy_prelude);
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
// dbg!(&v6or);
// dbg!(&v6or.fn_info);
2024-12-10 22:14:26 +00:00
2024-12-11 21:43:13 +00:00
let mut proc = prelude();
proc.ast = &ast;
// dbg!(&proc.fn_info);
2024-12-11 21:43:13 +00:00
proc.fn_info.extend(&mut v6or.fn_info.into_iter());
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),
Err(LErr { msg, .. }) => println!("Ludus panicked!\n{}", msg),
2024-12-11 03:26:52 +00:00
}
2024-12-09 04:33:02 +00:00
}
pub fn main() {
let src = "
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
}