1pub mod ast;
19pub mod cargo_runner;
20pub mod interpreter;
21pub mod lexer;
22pub mod parser;
23pub mod token;
24
25use interpreter::Interpreter;
26use lexer::Lexer;
27use parser::Parser;
28
29fn compile(source: &str) -> Result<Vec<ast::Expr>, String> {
31 let tokens = Lexer::new(source).tokenize().map_err(|e| format!("{e}"))?;
32
33 Parser::new(tokens)
34 .parse_program()
35 .map_err(|e| format!("{e}"))
36}
37
38fn has_main(program: &[ast::Expr]) -> bool {
40 program
41 .iter()
42 .any(|expr| matches!(expr, ast::Expr::FnDef { name, .. } if name == "main"))
43}
44
45fn execute(
47 interpreter: &mut Interpreter,
48 program: &[ast::Expr],
49) -> Result<interpreter::Value, String> {
50 let mut result = interpreter::Value::Unit;
51 for expr in program {
52 result = interpreter.eval(expr).map_err(|e| format!("{e}"))?;
53 }
54
55 if has_main(program) {
56 result = interpreter
57 .eval(&ast::Expr::FnCall {
58 name: "main".to_string(),
59 args: vec![],
60 })
61 .map_err(|e| format!("{e}"))?;
62 }
63
64 Ok(result)
65}
66
67pub fn run_source(source: &str) -> Result<(), String> {
71 let program = compile(source)?;
72 let mut interpreter = Interpreter::new();
73 execute(&mut interpreter, &program)?;
74 Ok(())
75}
76
77pub fn eval_source(source: &str) -> Result<String, String> {
81 let program = compile(source)?;
82 let mut interpreter = Interpreter::new();
83 let result = execute(&mut interpreter, &program)?;
84 Ok(format!("{result}"))
85}