From b17164b68b2729ada1b2d4cbe7b8f9f6a5bc1fce Mon Sep 17 00:00:00 2001 From: John Date: Mon, 29 Jul 2024 15:42:05 -0500 Subject: [PATCH] cl-interpret: Write an example for driving the interpreter --- compiler/cl-interpret/examples/conlang-run.rs | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 compiler/cl-interpret/examples/conlang-run.rs diff --git a/compiler/cl-interpret/examples/conlang-run.rs b/compiler/cl-interpret/examples/conlang-run.rs new file mode 100644 index 0000000..90d5812 --- /dev/null +++ b/compiler/cl-interpret/examples/conlang-run.rs @@ -0,0 +1,55 @@ +//! A bare-minimum harness to evaluate a Conlang program + +use std::{error::Error, path::PathBuf}; + +use cl_interpret::{convalue::ConValue, env::Environment}; +use cl_lexer::Lexer; +use cl_parser::{inliner::ModuleInliner, Parser}; + +fn main() -> Result<(), Box> { + let mut args = std::env::args(); + + let prog = args.next().unwrap(); + let Some(path) = args.next().map(PathBuf::from) else { + println!("Usage: {prog} `file.cl` [ args... ]"); + return Ok(()); + }; + + let parent = path.parent().unwrap_or("".as_ref()); + + let code = std::fs::read_to_string(&path)?; + let code = Parser::new(Lexer::new(&code)).file()?; + let code = match ModuleInliner::new(parent).inline(code) { + Ok(code) => code, + Err((code, ioerrs, perrs)) => { + for (p, err) in ioerrs { + eprintln!("{}:{err}", p.display()); + } + for (p, err) in perrs { + eprintln!("{}:{err}", p.display()); + } + code + } + }; + + let mut env = Environment::new(); + env.eval(&code)?; + + let main = "main".into(); + if env.get(main).is_ok() { + let args = args + .flat_map(|arg| { + Parser::new(Lexer::new(&arg)) + .expr() + .map(|arg| env.eval(&arg)) + }) + .collect::, _>>()?; + + match env.call(main, &args)? { + ConValue::Empty => {} + retval => println!("{retval}"), + } + } + + Ok(()) +}