use std::collections::HashMap;
use somni_parser::parser::parse;
use crate::{
codegen::Program,
error::CompileError,
types::VmTypeSet,
vm::{NativeFunction, SomniFn},
};
pub mod codegen;
pub mod error;
pub mod ir;
pub mod string_interner;
#[cfg(test)]
pub mod test;
pub mod transform_ir;
pub mod types;
pub mod variable_tracker;
pub mod vm;
pub struct Compiler<'ctx> {
functions: HashMap<&'ctx str, SomniFn<'ctx>>,
}
impl<'ctx> Compiler<'ctx> {
pub fn new() -> Self {
Self {
functions: HashMap::new(),
}
}
pub fn compile<'s>(&mut self, source: &'s str) -> Result<Program, CompileError<'s>> {
let ast = match parse::<VmTypeSet>(source) {
Ok(ast) => ast,
Err(parse_error) => {
return Err(CompileError {
source,
location: parse_error.location,
error: parse_error.error,
})
}
};
let ir = match ir::Program::compile(source, &ast) {
Ok(program) => program,
Err(parse_error) => {
return Err(CompileError {
source,
location: parse_error.location,
error: parse_error.error,
})
}
};
codegen::compile(source, ast, &ir, &self.functions)
}
pub fn add_function<F, A>(&mut self, name: &'ctx str, func: F)
where
F: NativeFunction<A> + 'ctx,
{
self.functions.insert(name, SomniFn::new(func));
}
}
#[test]
fn test_parser() {
test::run_parser_tests("tests/parser/");
}
fn strip_ansi(s: impl AsRef<str>) -> String {
use ansi_parser::AnsiParser;
fn text_block(output: ansi_parser::Output<'_>) -> Option<&str> {
match output {
ansi_parser::Output::TextBlock(text) => Some(text),
_ => None,
}
}
s.as_ref()
.ansi_parse()
.filter_map(text_block)
.collect::<String>()
}