🤔 Add a type inference engine, along with typed literals. #4

Merged
acw merged 25 commits from acw/type-checker into develop 2023-09-19 20:40:05 -07:00
4 changed files with 88 additions and 0 deletions
Showing only changes of commit 7efd2fb796 - Show all commits

View File

@@ -1,5 +1,84 @@
extern crate lalrpop; extern crate lalrpop;
use std::env;
use std::fs::{self, File};
use std::io::Write;
use std::path::{Path, PathBuf};
fn main() { fn main() {
lalrpop::process_root().unwrap(); lalrpop::process_root().unwrap();
if let Err(e) = generate_example_tests() {
eprintln!("Failure building example tests: {}", e);
std::process::exit(3);
}
}
fn generate_example_tests() -> std::io::Result<()> {
let out_dir = env::var_os("OUT_DIR").expect("OUT_DIR");
let dest_path = Path::new(&out_dir).join("examples.rs");
let mut output = File::create(dest_path)?;
generate_tests(&mut output, PathBuf::from("examples"))?;
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=example.rs");
Ok(())
}
fn generate_tests(f: &mut File, path_so_far: PathBuf) -> std::io::Result<()> {
for entry in fs::read_dir(path_so_far)? {
let entry = entry?;
let file_name = entry
.file_name()
.into_string()
.expect("reasonable file name");
let name = file_name.trim_end_matches(".ngr");
if entry.file_type()?.is_dir() {
writeln!(f, "mod {} {{", name)?;
writeln!(f, " use super::*;")?;
generate_tests(f, entry.path())?;
writeln!(f, "}}")?;
} else {
writeln!(f, "#[test]")?;
writeln!(f, "fn {}() {{", name)?;
writeln!(f, " let mut file_database = SimpleFiles::new();")?;
writeln!(
f,
" let syntax = Syntax::parse_file(&mut file_database, {:?});",
entry.path().display()
)?;
if entry.path().to_string_lossy().contains("broken") {
writeln!(f, " if syntax.is_err() {{")?;
writeln!(f, " return;")?;
writeln!(f, " }}")?;
writeln!(f, " let (errors, _) = syntax.unwrap().validate();")?;
writeln!(
f,
" assert_ne!(errors.len(), 0, \"should have seen an error\");"
)?;
} else {
writeln!(
f,
" let syntax = syntax.expect(\"file should have parsed\");"
)?;
writeln!(f, " let (errors, _) = syntax.validate();")?;
writeln!(
f,
" assert_eq!(errors.len(), 0, \"file should have no validation errors\");"
)?;
writeln!(f, " let syntax_result = syntax.eval();")?;
writeln!(f, " let ir = IR::from(syntax);")?;
writeln!(
f,
" assert_eq!(syntax_result, ir.eval(), \"syntax equivalent to IR\");"
)?;
writeln!(f, " let compiled_result = Backend::<JITModule>::eval(ir);")?;
writeln!(f, " assert_eq!(syntax_result, compiled_result);")?;
}
writeln!(f, "}}")?;
}
}
Ok(())
} }

7
src/examples.rs Normal file
View File

@@ -0,0 +1,7 @@
use codespan_reporting::files::SimpleFiles;
use crate::backend::Backend;
use crate::ir::Program as IR;
use crate::syntax::Program as Syntax;
use cranelift_jit::JITModule;
include!(concat!(env!("OUT_DIR"), "/examples.rs"));

View File

@@ -63,6 +63,8 @@
//! //!
pub mod backend; pub mod backend;
pub mod eval; pub mod eval;
#[cfg(test)]
mod examples;
pub mod ir; pub mod ir;
pub mod syntax; pub mod syntax;