2024-12-16 04:50:12 +00:00
|
|
|
use chumsky::{input::Stream, prelude::*};
|
2025-06-20 18:29:31 +00:00
|
|
|
use imbl::HashMap;
|
2025-05-23 04:09:35 +00:00
|
|
|
use std::env;
|
2024-12-16 04:50:12 +00:00
|
|
|
|
2024-12-18 06:28:23 +00:00
|
|
|
const DEBUG_COMPILE: bool = true;
|
|
|
|
const DEBUG_RUN: bool = true;
|
|
|
|
|
2025-06-03 22:54:33 +00:00
|
|
|
mod base;
|
2024-12-18 04:45:39 +00:00
|
|
|
|
2024-12-16 04:50:12 +00:00
|
|
|
mod spans;
|
2024-12-23 00:51:02 +00:00
|
|
|
use crate::spans::Spanned;
|
2024-12-16 04:50:12 +00:00
|
|
|
|
|
|
|
mod lexer;
|
|
|
|
use crate::lexer::lexer;
|
|
|
|
|
|
|
|
mod parser;
|
2024-12-23 00:51:02 +00:00
|
|
|
use crate::parser::{parser, Ast};
|
2024-12-16 04:50:12 +00:00
|
|
|
|
|
|
|
mod validator;
|
|
|
|
|
|
|
|
mod compiler;
|
2024-12-27 00:03:09 +00:00
|
|
|
use crate::compiler::Compiler;
|
2024-12-16 04:50:12 +00:00
|
|
|
|
|
|
|
mod value;
|
2025-06-20 18:29:31 +00:00
|
|
|
use value::Value;
|
2024-12-16 04:50:12 +00:00
|
|
|
|
|
|
|
mod vm;
|
|
|
|
use vm::Vm;
|
|
|
|
|
2025-06-20 18:29:31 +00:00
|
|
|
const PRELUDE: &str = "
|
|
|
|
fn print! (...args) -> base :print! (args)
|
|
|
|
fn inc (x) -> base :inc (x)
|
|
|
|
fn dec (x) -> base :dec (x)
|
|
|
|
fn eq? (x, y) -> base :eq? (x, y)
|
|
|
|
|
|
|
|
#{print!, inc, dec, eq?}
|
|
|
|
";
|
|
|
|
|
|
|
|
pub fn prelude() -> HashMap<&'static str, Value> {
|
|
|
|
let tokens = lexer().parse(PRELUDE).into_output_errors().0.unwrap();
|
|
|
|
let parsed = parser()
|
|
|
|
.parse(Stream::from_iter(tokens).map((0..PRELUDE.len()).into(), |(t, s)| (t, s)))
|
|
|
|
.into_output_errors()
|
|
|
|
.0
|
|
|
|
.unwrap();
|
|
|
|
let parsed: &'static Spanned<Ast> = Box::leak(Box::new(parsed));
|
|
|
|
let mut compiler = Compiler::new(parsed, "prelude", PRELUDE, None, HashMap::new());
|
|
|
|
let base = base::make_base();
|
|
|
|
compiler.emit_constant(base);
|
|
|
|
compiler.bind("base");
|
|
|
|
compiler.compile();
|
|
|
|
|
|
|
|
let chunk = compiler.chunk;
|
|
|
|
let mut vm = Vm::new(chunk);
|
|
|
|
let prelude = vm.run().clone().unwrap();
|
|
|
|
match prelude {
|
|
|
|
Value::Dict(hashmap) => *hashmap,
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-12-16 04:50:12 +00:00
|
|
|
pub fn run(src: &'static str) {
|
|
|
|
let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
|
|
|
|
if !lex_errs.is_empty() {
|
|
|
|
println!("{:?}", lex_errs);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let tokens = tokens.unwrap();
|
|
|
|
|
|
|
|
let (parse_result, parse_errors) = parser()
|
|
|
|
.parse(Stream::from_iter(tokens).map((0..src.len()).into(), |(t, s)| (t, s)))
|
|
|
|
.into_output_errors();
|
|
|
|
if !parse_errors.is_empty() {
|
|
|
|
println!("{:?}", parse_errors);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-12-23 15:55:28 +00:00
|
|
|
// ::sigh:: The AST should be 'static
|
|
|
|
// This simplifies lifetimes, and
|
|
|
|
// in any event, the AST should live forever
|
2024-12-23 00:51:02 +00:00
|
|
|
let parsed: &'static Spanned<Ast> = Box::leak(Box::new(parse_result.unwrap()));
|
2024-12-16 04:50:12 +00:00
|
|
|
|
2025-06-20 18:29:31 +00:00
|
|
|
let prelude = prelude();
|
2025-06-20 16:49:31 +00:00
|
|
|
|
2025-06-20 18:29:31 +00:00
|
|
|
let mut compiler = Compiler::new(parsed, "test", src, None, prelude);
|
2025-06-20 16:49:31 +00:00
|
|
|
|
2024-12-27 00:03:09 +00:00
|
|
|
compiler.compile();
|
2024-12-18 06:28:23 +00:00
|
|
|
if DEBUG_COMPILE {
|
2025-05-23 04:09:35 +00:00
|
|
|
println!("=== source code ===");
|
|
|
|
println!("{src}");
|
2024-12-27 00:03:09 +00:00
|
|
|
compiler.disassemble();
|
2024-12-18 06:28:23 +00:00
|
|
|
println!("\n\n")
|
|
|
|
}
|
|
|
|
|
2025-06-05 16:15:49 +00:00
|
|
|
if DEBUG_RUN {
|
|
|
|
println!("=== vm run: test ===");
|
|
|
|
}
|
|
|
|
|
|
|
|
let vm_chunk = compiler.chunk;
|
|
|
|
|
|
|
|
let mut vm = Vm::new(vm_chunk);
|
|
|
|
let result = vm.run();
|
|
|
|
let output = match result {
|
|
|
|
Ok(val) => val.show(),
|
|
|
|
Err(panic) => format!("Ludus panicked! {panic}"),
|
|
|
|
};
|
|
|
|
vm.print_stack();
|
|
|
|
println!("{output}");
|
2024-12-16 04:50:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn main() {
|
2025-06-18 21:50:30 +00:00
|
|
|
env::set_var("RUST_BACKTRACE", "1");
|
2025-06-18 18:12:54 +00:00
|
|
|
let src = "
|
2025-06-20 18:29:31 +00:00
|
|
|
[
|
|
|
|
eq? (1, 2)
|
|
|
|
eq? (:foo, :foo)
|
|
|
|
inc (3)
|
2025-06-20 18:30:39 +00:00
|
|
|
dec (0)
|
2025-06-20 18:29:31 +00:00
|
|
|
]
|
2025-06-19 15:54:26 +00:00
|
|
|
";
|
2025-06-18 18:12:54 +00:00
|
|
|
run(src);
|
2024-12-16 04:50:12 +00:00
|
|
|
}
|