cl-interpret: Write an example for driving the interpreter
This commit is contained in:
parent
ecebefe218
commit
b17164b68b
55
compiler/cl-interpret/examples/conlang-run.rs
Normal file
55
compiler/cl-interpret/examples/conlang-run.rs
Normal file
@ -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<dyn Error>> {
|
||||
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::<Result<Vec<_>, _>>()?;
|
||||
|
||||
match env.call(main, &args)? {
|
||||
ConValue::Empty => {}
|
||||
retval => println!("{retval}"),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue
Block a user