use chumsky::{input::Stream, prelude::*}; const DEBUG_COMPILE: bool = true; const DEBUG_RUN: bool = true; mod memory_sandbox; mod spans; use crate::spans::Spanned; mod lexer; use crate::lexer::lexer; mod parser; use crate::parser::{parser, Ast}; mod validator; mod compiler; use crate::compiler::Compiler; mod value; mod vm; use vm::Vm; 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; } // ::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())); let mut compiler = Compiler::new(parsed, "test", src); compiler.compile(); if DEBUG_COMPILE { compiler.disassemble(); println!("\n\n") } if DEBUG_RUN { println!("=== vm run: test ==="); } let mut vm = Vm::new(&compiler.chunk); let result = vm.interpret(); let output = match result { Ok(val) => val.show(&compiler.chunk), Err(panic) => format!("{:?}", panic), }; println!("{output}"); } pub fn main() { let src = " let foo = 42 match foo with { :foo -> { 1 2 x } 2 -> :two 42 -> :everything _ -> :something_else } "; run(src); }