use chumsky::{input::Stream, prelude::*}; use std::env; 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 pattern; 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 = Box::leak(Box::new(parse_result.unwrap())); let mut compiler = Compiler::new(parsed, "test", src); compiler.compile(); if DEBUG_COMPILE { println!("=== source code ==="); println!("{src}"); compiler.disassemble(); println!("\n\n") } if DEBUG_RUN { println!("=== vm run: test ==="); } let mut vm = Vm::new(&compiler.chunk); let result = vm.run(); let output = match result { Ok(val) => val.show(&compiler.chunk), Err(panic) => format!("{:?}", panic), }; vm.print_stack(); println!("{output}"); } pub fn main() { env::set_var("RUST_BACKTRACE", "1"); let src = " let #{:a x} = #{:a 1} x "; run(src); }