rudus/src/main.rs

132 lines
3.0 KiB
Rust
Raw Normal View History

use chumsky::{input::Stream, prelude::*};
use imbl::HashMap;
use std::env;
2024-12-18 06:28:23 +00:00
const DEBUG_COMPILE: bool = true;
const DEBUG_RUN: bool = true;
mod base;
2024-12-18 04:45:39 +00:00
mod spans;
use crate::spans::Spanned;
mod lexer;
use crate::lexer::lexer;
mod parser;
use crate::parser::{parser, Ast};
mod validator;
mod compiler;
2024-12-27 00:03:09 +00:00
use crate::compiler::Compiler;
mod value;
use value::Value;
mod vm;
use vm::Vm;
2025-06-20 19:35:09 +00:00
const PRELUDE: &str = include_str!("../assets/prelude.ld");
pub fn prelude() -> HashMap<&'static str, Value> {
let tokens = lexer().parse(PRELUDE).into_output_errors().0.unwrap();
2025-06-20 19:35:09 +00:00
let (parsed, parse_errors) = parser()
.parse(Stream::from_iter(tokens).map((0..PRELUDE.len()).into(), |(t, s)| (t, s)))
2025-06-20 19:35:09 +00:00
.into_output_errors();
if !parse_errors.is_empty() {
println!("ERROR PARSING PRELUDE:");
println!("{:?}", parse_errors);
panic!();
}
let parsed: &'static Spanned<Ast> = Box::leak(Box::new(parsed.unwrap()));
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!(),
}
}
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
let parsed: &'static Spanned<Ast> = Box::leak(Box::new(parse_result.unwrap()));
2025-06-20 19:35:09 +00:00
// let prelude = prelude();
let prelude = imbl::HashMap::new();
2025-06-20 16:49:31 +00:00
let mut compiler = Compiler::new(parsed, "test", src, None, prelude);
2025-06-20 19:35:09 +00:00
// let base = base::make_base();
// compiler.emit_constant(base);
// compiler.bind("base");
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 {
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}");
}
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 19:35:09 +00:00
fn one {
(x as :number) -> {
fn two () -> :number
two
}
(x as :bool) -> {
fn two () -> :bool
two
}
}
one (true) ()
2025-06-19 15:54:26 +00:00
";
2025-06-18 18:12:54 +00:00
run(src);
}