diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/aatbe-lang.iml b/.idea/aatbe-lang.iml new file mode 100644 index 0000000..7c8cb7b --- /dev/null +++ b/.idea/aatbe-lang.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..2d2e2ea --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..495fd2e --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index a1f9da6..37f5221 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "aatboot" version = "0.1.0" @@ -7,12 +9,12 @@ dependencies = [ "clap", "comp-be", "dotenv", + "flexi_logger", "glob", "llvm-sys", "llvm-sys-wrapper", "log", "parser", - "simplelog", ] [[package]] @@ -37,18 +39,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - -[[package]] -name = "arrayvec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" - [[package]] name = "atty" version = "0.2.14" @@ -66,29 +56,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" -[[package]] -name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" - [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -[[package]] -name = "blake2b_simd" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" -dependencies = [ - "arrayref", - "arrayvec", - "constant_time_eq", -] - [[package]] name = "cc" version = "1.0.50" @@ -97,9 +70,9 @@ checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" [[package]] name = "cfg-if" -version = "0.1.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" @@ -131,50 +104,13 @@ dependencies = [ name = "comp-be" version = "0.0.1" dependencies = [ + "guard", "llvm-sys-wrapper", + "log", "parser", "tuple-combinator", ] -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "crossbeam-utils" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -dependencies = [ - "autocfg", - "cfg-if", - "lazy_static", -] - -[[package]] -name = "dirs" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" -dependencies = [ - "cfg-if", - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" -dependencies = [ - "cfg-if", - "libc", - "redox_users", - "winapi", -] - [[package]] name = "dotenv" version = "0.15.0" @@ -182,14 +118,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] -name = "getrandom" -version = "0.1.14" +name = "flexi_logger" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +checksum = "33ab94b6ac8eb69f1496a6993f26f785b5fd6d99b7416023eb2a6175c0b242b1" dependencies = [ - "cfg-if", - "libc", - "wasi", + "atty", + "chrono", + "glob", + "lazy_static", + "log", + "regex", + "thiserror", + "yansi", ] [[package]] @@ -198,6 +139,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "guard" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1f3d64ec55b293a2ddfee276c6d7733616925b55dd337ddc0dc83aba96fbbb1" + [[package]] name = "hermit-abi" version = "0.1.8" @@ -242,9 +189,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.8" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ "cfg-if", ] @@ -279,22 +226,29 @@ name = "parser" version = "0.1.0" [[package]] -name = "redox_syscall" -version = "0.1.56" +name = "proc-macro2" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid", +] [[package]] -name = "redox_users" -version = "0.3.4" +name = "quote" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ - "getrandom", - "redox_syscall", - "rust-argon2", + "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" + [[package]] name = "regex" version = "1.3.9" @@ -313,18 +267,6 @@ version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" -[[package]] -name = "rust-argon2" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" -dependencies = [ - "base64", - "blake2b_simd", - "constant_time_eq", - "crossbeam-utils", -] - [[package]] name = "semver" version = "0.9.0" @@ -340,17 +282,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -[[package]] -name = "simplelog" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05a3e303ace6adb0a60a9e9e2fbc6a33e1749d1e43587e2125f7efa9c5e107c5" -dependencies = [ - "chrono", - "log", - "term", -] - [[package]] name = "strsim" version = "0.8.0" @@ -358,13 +289,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] -name = "term" -version = "0.6.1" +name = "syn" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" +checksum = "ed22b90a0e734a23a7610f4283ac9e5acfb96cbb30dfefa540d66f866f1c09c5" dependencies = [ - "dirs", - "winapi", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] @@ -376,6 +308,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.0.1" @@ -409,16 +361,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" [[package]] -name = "vec_map" -version = "0.8.1" +name = "unicode-xid" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" +name = "vec_map" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" [[package]] name = "winapi" @@ -441,3 +393,9 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "yansi" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71" diff --git a/aatboot/Cargo.toml b/aatboot/Cargo.toml index ad12e32..538bdd8 100644 --- a/aatboot/Cargo.toml +++ b/aatboot/Cargo.toml @@ -12,7 +12,7 @@ comp-be = { path="../comp-be" } parser = { path="../parser" } clap = "^2.33.0" -simplelog = "^0.7.4" +flexi_logger = "0.17.1" log = "^0.4" glob = "^0.3.0" llvm-sys = "100.0" diff --git a/aatboot/src/main.rs b/aatboot/src/main.rs index 6ba7291..910247f 100644 --- a/aatboot/src/main.rs +++ b/aatboot/src/main.rs @@ -1,6 +1,7 @@ use comp_be::codegen::{comp_unit::CompilationUnit, AatbeModule, CompileError}; use clap::{clap_app, crate_authors, crate_description, crate_version}; +use flexi_logger::Logger; use std::{ env, ffi::CString, @@ -17,7 +18,6 @@ use glob::glob; use llvm_sys::support::LLVMLoadLibraryPermanently; use llvm_sys_wrapper::{CodegenLevel, CPU, LLVM}; use log::{error, warn}; -use simplelog::*; fn main() -> io::Result<()> { dotenv().ok(); @@ -34,10 +34,7 @@ fn main() -> io::Result<()> { (@arg LIB: -l ... +takes_value "Link with library without prefix or extension")) .get_matches(); - if let Err(_) = TermLogger::init(LevelFilter::Warn, Config::default(), TerminalMode::Mixed) { - SimpleLogger::init(LevelFilter::Warn, Config::default()) - .expect("No logger should be already set") - } + Logger::with_env_or_str("trace").start().unwrap(); let input_path = Path::new(matches.value_of_os("INPUT").unwrap()).to_path_buf(); let main_cu = CompilationUnit::new(input_path.clone())?; @@ -70,7 +67,7 @@ fn main() -> io::Result<()> { if let Some(libs) = matches.values_of("LIB") { for lib in libs { - let globs = glob(format!("/usr/lib/x86_64-linux-gnu/lib{}.so", lib).as_ref()) + let globs = glob(&format!("/usr/lib/x86_64-linux-gnu/lib{}.so", lib)) .unwrap() .filter_map(Result::ok) .collect::>(); @@ -80,11 +77,8 @@ fn main() -> io::Result<()> { error!("-l{} found too many matches, please be more specific", lib); } else { unsafe { - LLVMLoadLibraryPermanently( - CString::new(globs[0].to_str().unwrap()) - .expect("cstring failed") - .as_ptr(), - ); + let cs = CString::new(globs[0].to_str().unwrap()).expect("cstring failed"); + LLVMLoadLibraryPermanently(cs.as_ptr()); } } } @@ -230,6 +224,6 @@ fn main() -> io::Result<()> { } Ok(()) } - Err(err) => panic!(err), + Err(err) => panic!("{}", err), } } diff --git a/bench/fizzbuzz.aat b/bench/fizzbuzz.aat new file mode 100644 index 0000000..7c020f2 --- /dev/null +++ b/bench/fizzbuzz.aat @@ -0,0 +1,20 @@ +module libc { + public extern fn printf str, ... -> i32 +} + +@entry +fn main () = { + var i = 1 + + until i > 128 { + if i % 3 == 0 && i % 5 == 0 then + libc::printf "FizzBuzz\n" + else if i % 3 == 0 then + libc::printf "Fizz\n" + else if i % 5 == 0 then + libc::printf "Buzz\n" + else libc::printf "%d\n", i + + i = i + 1 + } +} \ No newline at end of file diff --git a/comp-be/Cargo.toml b/comp-be/Cargo.toml index 2b79400..4da0039 100644 --- a/comp-be/Cargo.toml +++ b/comp-be/Cargo.toml @@ -13,3 +13,5 @@ path = "src/lib.rs" llvm-sys-wrapper = { path = "../llvm-sys-wrapper" } tuple-combinator = "0.2.1" parser = { path = "../parser" } +log = "0.4.14" +guard = "0.5" diff --git a/comp-be/src/codegen/atom.rs b/comp-be/src/codegen/atom.rs index 69cd4c0..dad1cc4 100644 --- a/comp-be/src/codegen/atom.rs +++ b/comp-be/src/codegen/atom.rs @@ -1,7 +1,6 @@ use crate::{ codegen::{ - builder::{cast, core, op, ty}, - expr::const_expr::const_atom, + builder::{base, cast, op, ty}, unit::Slot, AatbeModule, CompileError, ValueTypePair, }, @@ -10,75 +9,76 @@ use crate::{ }; use super::builder::value; -use parser::ast::{AtomKind, Boolean, FloatSize, PrimitiveType}; +use parser::ast::{AtomKind, Boolean, FloatSize, Type}; impl AatbeModule { pub fn codegen_atom(&mut self, atom: &AtomKind) -> Option { - match atom { + todo!() + /*match atom { AtomKind::Cast(box val, ty) => { let val = self.codegen_atom(val)?; match (val.prim(), ty) { - (PrimitiveType::Char, PrimitiveType::UInt(_)) - | (PrimitiveType::Char, PrimitiveType::Int(_)) => { + (Type::Char, Type::UInt(_)) + | (Type::Char, Type::Int(_)) => { return Some(cast::zext(self, val, ty)) } - (PrimitiveType::Int(from), PrimitiveType::Int(to)) if from < to => { + (Type::Int(from), Type::Int(to)) if from < to => { return Some(cast::zext(self, val, ty)) } - (PrimitiveType::Int(from), PrimitiveType::Int(to)) if from > to => { + (Type::Int(from), Type::Int(to)) if from > to => { return Some(cast::trunc(self, val, ty)) } - (PrimitiveType::Int(from), PrimitiveType::UInt(to)) if from < to => { + (Type::Int(from), Type::UInt(to)) if from < to => { return Some(cast::zext(self, val, ty)) } - (PrimitiveType::Int(from), PrimitiveType::UInt(to)) if from > to => { + (Type::Int(from), Type::UInt(to)) if from > to => { return Some(cast::trunc(self, val, ty)) } - (PrimitiveType::UInt(from), PrimitiveType::Int(to)) if from < to => { + (Type::UInt(from), Type::Int(to)) if from < to => { return Some(cast::zext(self, val, ty)) } - (PrimitiveType::UInt(from), PrimitiveType::Int(to)) if from > to => { + (Type::UInt(from), Type::Int(to)) if from > to => { return Some(cast::trunc(self, val, ty)) } - (PrimitiveType::Int(_), PrimitiveType::Pointer(_)) => { + (Type::Int(_), Type::Pointer(_)) => { return Some(cast::itop(self, val, ty)) } - (PrimitiveType::Pointer(_), PrimitiveType::Int(_)) => { + (Type::Pointer(_), Type::Int(_)) => { return Some(cast::ptoi(self, val, ty)) } - (PrimitiveType::Str, PrimitiveType::Int(_)) => { + (Type::Str, Type::Int(_)) => { return Some(cast::ptoi(self, val, ty)) } - (PrimitiveType::Str, PrimitiveType::UInt(_)) => { + (Type::Str, Type::UInt(_)) => { return Some(cast::ptoi(self, val, ty)) } - (PrimitiveType::UInt(_), PrimitiveType::Pointer(_)) => { + (Type::UInt(_), Type::Pointer(_)) => { return Some(cast::itop(self, val, ty)) } - (PrimitiveType::Pointer(_), PrimitiveType::UInt(_)) => { + (Type::Pointer(_), Type::UInt(_)) => { return Some(cast::ptoi(self, val, ty)) } - (PrimitiveType::Int(_), PrimitiveType::Str) => { + (Type::Int(_), Type::Str) => { return Some(cast::itop(self, val, ty)) } - (PrimitiveType::Int(_), PrimitiveType::Float(_)) => { + (Type::Int(_), Type::Float(_)) => { return Some(cast::stof(self, val, ty)) } - (PrimitiveType::UInt(_), PrimitiveType::Float(_)) => { + (Type::UInt(_), Type::Float(_)) => { return Some(cast::utof(self, val, ty)) } ( - PrimitiveType::Float(FloatSize::Bits64), - PrimitiveType::Float(FloatSize::Bits32), + Type::Float(FloatSize::Bits64), + Type::Float(FloatSize::Bits32), ) => return Some(cast::ftrunc(self, val, ty)), - (PrimitiveType::Float(_), PrimitiveType::Int(_)) => { + (Type::Float(_), Type::Int(_)) => { return Some(cast::ftos(self, val, ty)) } - (PrimitiveType::Float(_), PrimitiveType::UInt(_)) => { + (Type::Float(_), Type::UInt(_)) => { return Some(cast::ftou(self, val, ty)) } // FIXME: Huge hack to work for llvm test - (PrimitiveType::Array { .. }, PrimitiveType::Slice { ty: box ty }) => { + (Type::Array { .. }, Type::Slice { ty: box ty }) => { return Some( ( self.llvm_builder_ref().build_inbounds_gep( @@ -88,7 +88,7 @@ impl AatbeModule { self.llvm_context_ref().SInt32(0), ], ), - PrimitiveType::Pointer(box ty.clone()), + Type::Pointer(box ty.clone()), ) .into(), ) @@ -109,15 +109,15 @@ impl AatbeModule { let mut arr = false; let ty = match ty { - TypeKind::Primitive(PrimitiveType::Str) => { - TypeKind::Primitive(PrimitiveType::Char) + TypeKind::Primitive(Type::Str) => { + TypeKind::Primitive(Type::Char) } - TypeKind::Primitive(PrimitiveType::Array { ty: box ty, .. }) => { + TypeKind::Primitive(Type::Array { ty: box ty, .. }) => { arr = true; TypeKind::Primitive(ty) } - TypeKind::Primitive(PrimitiveType::Slice { ty: box ty }) => { + TypeKind::Primitive(Type::Slice { ty: box ty }) => { arr = true; TypeKind::Primitive(ty) @@ -141,7 +141,7 @@ impl AatbeModule { AtomKind::Deref(path) => { let acc = self.codegen_atom(path)?; match acc.prim() { - PrimitiveType::Newtype(name) => { + Type::Newtype(name) => { let val = core::struct_gep(self, *acc, 0); match self.typectx_ref().get_type(name) { Some(TypeKind::Typedef(TypedefKind::Newtype(_, ty))) => { @@ -150,7 +150,7 @@ impl AatbeModule { _ => unimplemented!(), } } - PrimitiveType::Box(box ty) => Some(core::load_prim(self, *acc, ty.clone())), + Type::Box(box ty) => Some(core::load_prim(self, *acc, ty.clone())), _ => unimplemented!(), } } @@ -165,31 +165,15 @@ impl AatbeModule { .into(), ) } - AtomKind::Ident(name) => { - let var_ref = self.get_var(name)?; - - match var_ref.var_ty() { - ty @ PrimitiveType::Newtype(_) | ty @ PrimitiveType::VariantType(_) => { - let val: ValueTypePair = var_ref.into(); - Some((*val, ty).into()) - } - ty => Some((var_ref.load_var(self.llvm_builder_ref()), ty).into()), - } - } AtomKind::Ref(box AtomKind::Ident(name)) => { let var_ref = self.get_var(name)?; let var: ValueTypePair = var_ref.into(); - Some((*var, PrimitiveType::Ref(box var.prim().clone())).into()) - } - atom @ (AtomKind::StringLiteral(_) | AtomKind::CharLiteral(_)) => { - const_atom(self, atom) + Some((*var, Type::Ref(box var.prim().clone())).into()) } atom @ AtomKind::Integer(_, _) => const_atom(self, atom), atom @ AtomKind::Floating(_, _) => const_atom(self, atom), - AtomKind::Bool(Boolean::True) => Some(value::t(self)), - AtomKind::Bool(Boolean::False) => Some(value::f(self)), AtomKind::Expr(expr) => self.codegen_expr(expr), AtomKind::Unit => None, AtomKind::Unary(op, val) if op == &String::from("-") => { @@ -198,8 +182,8 @@ impl AatbeModule { .expect(format!("ICE Cannot negate {:?}", val).as_str()); match value.prim() { - PrimitiveType::Int(_) | PrimitiveType::UInt(_) => Some(op::neg(self, value)), - PrimitiveType::Float(_) => Some(op::fneg(self, value)), + Type::Int(_) | Type::UInt(_) => Some(op::neg(self, value)), + Type::Float(_) => Some(op::fneg(self, value)), _ => { self.add_error(CompileError::UnaryMismatch { op: op.clone(), @@ -216,10 +200,10 @@ impl AatbeModule { .codegen_atom(val) .expect(format!("ICE Cannot negate {:?}", val).as_str()); - if value.prim() != &PrimitiveType::Bool { + if value.prim() != &Type::Bool { self.add_error(CompileError::UnaryMismatch { op: op.clone(), - expected_ty: PrimitiveType::Bool.fmt(), + expected_ty: Type::Bool.fmt(), found_ty: value.prim().fmt(), value: val.fmt(), }) @@ -228,7 +212,7 @@ impl AatbeModule { Some(op::not(self, value)) } AtomKind::Parenthesized(expr) => self.codegen_expr(expr), - AtomKind::Array(exprs) => { + /*AtomKind::Array(exprs) => { let values = exprs .iter() .filter_map(|expr| self.codegen_expr(expr)) @@ -266,18 +250,18 @@ impl AatbeModule { &mut values.iter().map(|val| **val).collect::>(), len, ), - PrimitiveType::Array { + Type::Array { ty: box fst.clone(), len: len, }, ) .into(), ) - } + }*/ AtomKind::Is(box val, ty) => match val { AtomKind::Ident(val) => { let var_ref = self.get_var(val).expect("").clone(); - if let PrimitiveType::TypeRef(var) = var_ref.var_ty().clone() { + if let Type::TypeRef(var) = var_ref.var_ty().clone() { let variant_ty = self.typectx_ref().get_typedef(&var); match variant_ty { Ok(TypedefKind::VariantType(variant)) if variant.has_variant(ty) => { @@ -305,7 +289,7 @@ impl AatbeModule { Slot::Variable { mutable: var_ref.get_mutability().clone(), name: val.clone(), - ty: PrimitiveType::Variant { + ty: Type::Variant { parent: var, variant: ty.clone(), }, @@ -327,6 +311,6 @@ impl AatbeModule { ), }, _ => panic!("ICE codegen_atom {:?}", atom), - } + }*/ } } diff --git a/comp-be/src/codegen/builder/base.rs b/comp-be/src/codegen/builder/base.rs new file mode 100644 index 0000000..a9ace42 --- /dev/null +++ b/comp-be/src/codegen/builder/base.rs @@ -0,0 +1,154 @@ +use crate::{ + codegen::{ + unit::{function::Func, CompilerContext}, + ValueTypePair, + }, + ty::{LLVMTyInCtx, TypeKind}, +}; +use llvm_sys_wrapper::{LLVMBasicBlockRef, LLVMTypeRef, LLVMValueRef}; +use parser::ast::{IntSize, Type}; + +pub fn load(ctx: &CompilerContext, pointer: LLVMValueRef) -> LLVMValueRef { + ctx.llvm_builder.build_load(pointer) +} + +pub fn load_ty(ctx: &CompilerContext, pointer: LLVMValueRef, ty: TypeKind) -> ValueTypePair { + (ctx.llvm_builder.build_load(pointer), ty).into() +} + +pub fn load_prim(ctx: &CompilerContext, pointer: LLVMValueRef, ty: Type) -> ValueTypePair { + (ctx.llvm_builder.build_load(pointer), ty).into() +} + +pub fn store(ctx: &CompilerContext, value: LLVMValueRef, pointer: LLVMValueRef) -> LLVMValueRef { + ctx.llvm_builder.build_store(value, pointer) +} + +pub fn struct_gep(ctx: &CompilerContext, pointer: LLVMValueRef, index: u32) -> LLVMValueRef { + ctx.llvm_builder.build_struct_gep(pointer, index) +} + +pub fn struct_gep_with_name( + ctx: &CompilerContext, + pointer: LLVMValueRef, + index: u32, + name: &str, +) -> LLVMValueRef { + ctx.llvm_builder + .build_struct_gep_with_name(pointer, index, name) +} + +pub fn inbounds_gep( + ctx: &CompilerContext, + pointer: LLVMValueRef, + indices: &mut Vec, +) -> LLVMValueRef { + ctx.llvm_builder + .build_inbounds_gep(pointer, indices.as_mut_slice()) +} + +pub fn alloca(ctx: &CompilerContext, ty: LLVMTypeRef) -> LLVMValueRef { + ctx.llvm_builder.build_alloca(ty) +} + +pub fn alloca_with_name(ctx: &CompilerContext, ty: LLVMTypeRef, name: &str) -> LLVMValueRef { + ctx.llvm_builder.build_alloca_with_name(ty, name) +} + +pub fn alloca_ty(ctx: &CompilerContext, ty: &Type) -> LLVMValueRef { + ctx.llvm_builder.build_alloca(ty.llvm_ty_in_ctx(ctx)) +} + +pub fn alloca_with_name_ty(ctx: &CompilerContext, ty: &Type, name: &str) -> LLVMValueRef { + ctx.llvm_builder + .build_alloca_with_name(ty.llvm_ty_in_ctx(ctx), name) +} + +pub fn call( + ctx: &CompilerContext, + func: &Func, + call_args: &mut Vec, +) -> ValueTypePair { + ( + ctx.llvm_builder + .build_call(func.as_ref(), call_args.as_mut()), + func.ret_ty(), + ) + .into() +} + +pub fn extract_i8(ctx: &CompilerContext, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { + ( + ctx.llvm_builder.build_extract_value(agg_val, index), + Type::Int(IntSize::Bits8), + ) + .into() +} + +pub fn extract_i16(ctx: &CompilerContext, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { + ( + ctx.llvm_builder.build_extract_value(agg_val, index), + Type::Int(IntSize::Bits16), + ) + .into() +} + +pub fn extract_i32(ctx: &CompilerContext, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { + ( + ctx.llvm_builder.build_extract_value(agg_val, index), + Type::Int(IntSize::Bits32), + ) + .into() +} + +pub fn extract_i64(ctx: &CompilerContext, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { + ( + ctx.llvm_builder.build_extract_value(agg_val, index), + Type::Int(IntSize::Bits64), + ) + .into() +} + +pub fn extract_u8(ctx: &CompilerContext, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { + ( + ctx.llvm_builder.build_extract_value(agg_val, index), + Type::UInt(IntSize::Bits8), + ) + .into() +} + +pub fn extract_u16(ctx: &CompilerContext, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { + ( + ctx.llvm_builder.build_extract_value(agg_val, index), + Type::UInt(IntSize::Bits16), + ) + .into() +} + +pub fn extract_u32(ctx: &CompilerContext, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { + ( + ctx.llvm_builder.build_extract_value(agg_val, index), + Type::UInt(IntSize::Bits32), + ) + .into() +} + +pub fn extract_u64(ctx: &CompilerContext, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { + ( + ctx.llvm_builder.build_extract_value(agg_val, index), + Type::UInt(IntSize::Bits64), + ) + .into() +} + +pub fn ret(ctx: &CompilerContext, val: ValueTypePair) -> ValueTypePair { + (ctx.llvm_builder.build_ret(*val), val.prim()).into() +} + +pub fn ret_void(ctx: &CompilerContext) { + ctx.llvm_builder.build_ret_void(); +} + +pub fn pos_at_end(ctx: &CompilerContext, bb: LLVMBasicBlockRef) { + ctx.llvm_builder.position_at_end(bb); +} diff --git a/comp-be/src/codegen/builder/branch.rs b/comp-be/src/codegen/builder/branch.rs index acd75bb..2bfcf8b 100644 --- a/comp-be/src/codegen/builder/branch.rs +++ b/comp-be/src/codegen/builder/branch.rs @@ -1,17 +1,15 @@ -use crate::codegen::AatbeModule; +use crate::codegen::unit::CompilerContext; use llvm_sys_wrapper::{LLVMBasicBlockRef, LLVMValueRef}; -pub fn branch(module: &AatbeModule, block: LLVMBasicBlockRef) -> LLVMValueRef { - module.llvm_builder_ref().build_br(block) +pub fn branch(ctx: &CompilerContext, block: LLVMBasicBlockRef) -> LLVMValueRef { + ctx.llvm_builder.build_br(block) } pub fn cond_branch( - module: &AatbeModule, + ctx: &CompilerContext, cond: LLVMValueRef, then_block: LLVMBasicBlockRef, else_block: LLVMBasicBlockRef, ) -> LLVMValueRef { - module - .llvm_builder_ref() - .build_cond_br(cond, then_block, else_block) + ctx.llvm_builder.build_cond_br(cond, then_block, else_block) } diff --git a/comp-be/src/codegen/builder/cast.rs b/comp-be/src/codegen/builder/cast.rs index d368fa9..76c7efd 100644 --- a/comp-be/src/codegen/builder/cast.rs +++ b/comp-be/src/codegen/builder/cast.rs @@ -1,132 +1,113 @@ use crate::{ - codegen::{AatbeModule, ValueTypePair}, + codegen::{unit::CompilerContext, ValueTypePair}, ty::variant::VariantType, ty::LLVMTyInCtx, }; use llvm_sys_wrapper::{LLVMTypeRef, LLVMValueRef}; -use parser::ast::PrimitiveType; +use parser::ast::Type; -pub fn zext(module: &AatbeModule, val: ValueTypePair, ty: &PrimitiveType) -> ValueTypePair { +pub fn zext(ctx: &CompilerContext, val: ValueTypePair, ty: &Type) -> ValueTypePair { ( - module - .llvm_builder_ref() - .build_zext(*val, ty.llvm_ty_in_ctx(module)), + ctx.llvm_builder.build_zext(*val, ty.llvm_ty_in_ctx(ctx)), ty, ) .into() } -pub fn trunc(module: &AatbeModule, val: ValueTypePair, ty: &PrimitiveType) -> ValueTypePair { +pub fn trunc(ctx: &CompilerContext, val: ValueTypePair, ty: &Type) -> ValueTypePair { ( - module - .llvm_builder_ref() - .build_trunc(*val, ty.llvm_ty_in_ctx(module)), + ctx.llvm_builder.build_trunc(*val, ty.llvm_ty_in_ctx(ctx)), ty, ) .into() } -pub fn ftrunc(module: &AatbeModule, val: ValueTypePair, ty: &PrimitiveType) -> ValueTypePair { +pub fn ftrunc(ctx: &CompilerContext, val: ValueTypePair, ty: &Type) -> ValueTypePair { ( - module - .llvm_builder_ref() - .build_fp_trunc(*val, ty.llvm_ty_in_ctx(module)), + ctx.llvm_builder + .build_fp_trunc(*val, ty.llvm_ty_in_ctx(ctx)), ty, ) .into() } -pub fn itop(module: &AatbeModule, val: ValueTypePair, ty: &PrimitiveType) -> ValueTypePair { +pub fn itop(ctx: &CompilerContext, val: ValueTypePair, ty: &Type) -> ValueTypePair { ( - module - .llvm_builder_ref() - .build_int_to_ptr(*val, ty.llvm_ty_in_ctx(module)), + ctx.llvm_builder + .build_int_to_ptr(*val, ty.llvm_ty_in_ctx(ctx)), ty, ) .into() } -pub fn ptoi(module: &AatbeModule, val: ValueTypePair, ty: &PrimitiveType) -> ValueTypePair { +pub fn ptoi(ctx: &CompilerContext, val: ValueTypePair, ty: &Type) -> ValueTypePair { ( - module - .llvm_builder_ref() - .build_ptr_to_int(*val, ty.llvm_ty_in_ctx(module)), + ctx.llvm_builder + .build_ptr_to_int(*val, ty.llvm_ty_in_ctx(ctx)), ty, ) .into() } -pub fn stof(module: &AatbeModule, val: ValueTypePair, ty: &PrimitiveType) -> ValueTypePair { +pub fn stof(ctx: &CompilerContext, val: ValueTypePair, ty: &Type) -> ValueTypePair { ( - module - .llvm_builder_ref() - .build_si_to_fp(*val, ty.llvm_ty_in_ctx(module)), + ctx.llvm_builder + .build_si_to_fp(*val, ty.llvm_ty_in_ctx(ctx)), ty, ) .into() } -pub fn utof(module: &AatbeModule, val: ValueTypePair, ty: &PrimitiveType) -> ValueTypePair { +pub fn utof(ctx: &CompilerContext, val: ValueTypePair, ty: &Type) -> ValueTypePair { ( - module - .llvm_builder_ref() - .build_ui_to_fp(*val, ty.llvm_ty_in_ctx(module)), + ctx.llvm_builder + .build_ui_to_fp(*val, ty.llvm_ty_in_ctx(ctx)), ty, ) .into() } -pub fn ftos(module: &AatbeModule, val: ValueTypePair, ty: &PrimitiveType) -> ValueTypePair { +pub fn ftos(ctx: &CompilerContext, val: ValueTypePair, ty: &Type) -> ValueTypePair { ( - module - .llvm_builder_ref() - .build_fp_to_si(*val, ty.llvm_ty_in_ctx(module)), + ctx.llvm_builder + .build_fp_to_si(*val, ty.llvm_ty_in_ctx(ctx)), ty, ) .into() } -pub fn ftou(module: &AatbeModule, val: ValueTypePair, ty: &PrimitiveType) -> ValueTypePair { +pub fn ftou(ctx: &CompilerContext, val: ValueTypePair, ty: &Type) -> ValueTypePair { ( - module - .llvm_builder_ref() - .build_fp_to_ui(*val, ty.llvm_ty_in_ctx(module)), + ctx.llvm_builder + .build_fp_to_ui(*val, ty.llvm_ty_in_ctx(ctx)), ty, ) .into() } -pub fn bitcast(module: &AatbeModule, val: ValueTypePair, ty: &dyn LLVMTyInCtx) -> LLVMValueRef { - module - .llvm_builder_ref() - .build_bitcast(*val, ty.llvm_ty_in_ctx(module)) +pub fn bitcast(ctx: &CompilerContext, val: ValueTypePair, ty: &dyn LLVMTyInCtx) -> LLVMValueRef { + ctx.llvm_builder.build_bitcast(*val, ty.llvm_ty_in_ctx(ctx)) } -pub fn bitcast_ty(module: &AatbeModule, val: ValueTypePair, ty: &PrimitiveType) -> ValueTypePair { +pub fn bitcast_ty(ctx: &CompilerContext, val: ValueTypePair, ty: &Type) -> ValueTypePair { ( - module - .llvm_builder_ref() - .build_bitcast(*val, ty.llvm_ty_in_ctx(module)), + ctx.llvm_builder.build_bitcast(*val, ty.llvm_ty_in_ctx(ctx)), ty, ) .into() } pub fn child_to_parent( - module: &AatbeModule, + ctx: &CompilerContext, val: ValueTypePair, parent: &VariantType, ) -> LLVMValueRef { - module.llvm_builder_ref().build_load( - module.llvm_builder_ref().build_bitcast( - *val, - module - .llvm_context_ref() - .PointerType(parent.llvm_ty_in_ctx(module)), - ), - ) + ctx.llvm_builder.build_load(ctx.llvm_builder.build_bitcast( + *val, + ctx.llvm_context.PointerType(parent.llvm_ty_in_ctx(ctx)), + )) } -pub fn bitcast_to(module: &AatbeModule, val: LLVMValueRef, ty: LLVMTypeRef) -> LLVMValueRef { - module.llvm_builder_ref().build_bitcast(val, ty) +pub fn bitcast_to(ctx: &CompilerContext, val: LLVMValueRef, ty: LLVMTypeRef) -> LLVMValueRef { + ctx.llvm_builder.build_bitcast(val, ty) } diff --git a/comp-be/src/codegen/builder/core.rs b/comp-be/src/codegen/builder/core.rs deleted file mode 100644 index 3e66346..0000000 --- a/comp-be/src/codegen/builder/core.rs +++ /dev/null @@ -1,169 +0,0 @@ -use crate::{ - codegen::{unit::function::Func, AatbeModule, ValueTypePair}, - ty::{LLVMTyInCtx, TypeKind}, -}; -use llvm_sys_wrapper::{LLVMBasicBlockRef, LLVMTypeRef, LLVMValueRef}; -use parser::ast::{IntSize, PrimitiveType}; - -pub fn load(module: &AatbeModule, pointer: LLVMValueRef) -> LLVMValueRef { - module.llvm_builder_ref().build_load(pointer) -} - -pub fn load_ty(module: &AatbeModule, pointer: LLVMValueRef, ty: TypeKind) -> ValueTypePair { - (module.llvm_builder_ref().build_load(pointer), ty).into() -} - -pub fn load_prim(module: &AatbeModule, pointer: LLVMValueRef, ty: PrimitiveType) -> ValueTypePair { - (module.llvm_builder_ref().build_load(pointer), ty).into() -} - -pub fn store(module: &AatbeModule, value: LLVMValueRef, pointer: LLVMValueRef) -> LLVMValueRef { - module.llvm_builder_ref().build_store(value, pointer) -} - -pub fn struct_gep(module: &AatbeModule, pointer: LLVMValueRef, index: u32) -> LLVMValueRef { - module.llvm_builder_ref().build_struct_gep(pointer, index) -} - -pub fn struct_gep_with_name( - module: &AatbeModule, - pointer: LLVMValueRef, - index: u32, - name: &str, -) -> LLVMValueRef { - module - .llvm_builder_ref() - .build_struct_gep_with_name(pointer, index, name) -} - -pub fn inbounds_gep( - module: &AatbeModule, - pointer: LLVMValueRef, - indices: &mut Vec, -) -> LLVMValueRef { - module - .llvm_builder_ref() - .build_inbounds_gep(pointer, indices.as_mut_slice()) -} - -pub fn alloca(module: &AatbeModule, ty: LLVMTypeRef) -> LLVMValueRef { - module.llvm_builder_ref().build_alloca(ty) -} - -pub fn alloca_with_name(module: &AatbeModule, ty: LLVMTypeRef, name: &str) -> LLVMValueRef { - module.llvm_builder_ref().build_alloca_with_name(ty, name) -} - -pub fn alloca_ty(module: &AatbeModule, ty: &PrimitiveType) -> LLVMValueRef { - module - .llvm_builder_ref() - .build_alloca(ty.llvm_ty_in_ctx(module)) -} - -pub fn alloca_with_name_ty(module: &AatbeModule, ty: &PrimitiveType, name: &str) -> LLVMValueRef { - module - .llvm_builder_ref() - .build_alloca_with_name(ty.llvm_ty_in_ctx(module), name) -} - -pub fn call(module: &AatbeModule, func: &Func, call_args: &mut Vec) -> ValueTypePair { - ( - module - .llvm_builder_ref() - .build_call(func.as_ref(), call_args.as_mut()), - func.ret_ty(), - ) - .into() -} - -pub fn extract_i8(module: &AatbeModule, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { - ( - module - .llvm_builder_ref() - .build_extract_value(agg_val, index), - PrimitiveType::Int(IntSize::Bits8), - ) - .into() -} - -pub fn extract_i16(module: &AatbeModule, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { - ( - module - .llvm_builder_ref() - .build_extract_value(agg_val, index), - PrimitiveType::Int(IntSize::Bits16), - ) - .into() -} - -pub fn extract_i32(module: &AatbeModule, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { - ( - module - .llvm_builder_ref() - .build_extract_value(agg_val, index), - PrimitiveType::Int(IntSize::Bits32), - ) - .into() -} - -pub fn extract_i64(module: &AatbeModule, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { - ( - module - .llvm_builder_ref() - .build_extract_value(agg_val, index), - PrimitiveType::Int(IntSize::Bits64), - ) - .into() -} - -pub fn extract_u8(module: &AatbeModule, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { - ( - module - .llvm_builder_ref() - .build_extract_value(agg_val, index), - PrimitiveType::UInt(IntSize::Bits8), - ) - .into() -} - -pub fn extract_u16(module: &AatbeModule, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { - ( - module - .llvm_builder_ref() - .build_extract_value(agg_val, index), - PrimitiveType::UInt(IntSize::Bits16), - ) - .into() -} - -pub fn extract_u32(module: &AatbeModule, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { - ( - module - .llvm_builder_ref() - .build_extract_value(agg_val, index), - PrimitiveType::UInt(IntSize::Bits32), - ) - .into() -} - -pub fn extract_u64(module: &AatbeModule, agg_val: LLVMValueRef, index: u32) -> ValueTypePair { - ( - module - .llvm_builder_ref() - .build_extract_value(agg_val, index), - PrimitiveType::UInt(IntSize::Bits64), - ) - .into() -} - -pub fn ret(module: &AatbeModule, val: ValueTypePair) -> ValueTypePair { - (module.llvm_builder_ref().build_ret(*val), val.prim()).into() -} - -pub fn ret_void(module: &AatbeModule) { - module.llvm_builder_ref().build_ret_void(); -} - -pub fn pos_at_end(module: &AatbeModule, bb: LLVMBasicBlockRef) { - module.llvm_builder_ref().position_at_end(bb); -} diff --git a/comp-be/src/codegen/builder/mod.rs b/comp-be/src/codegen/builder/mod.rs index 9933d62..0845b08 100644 --- a/comp-be/src/codegen/builder/mod.rs +++ b/comp-be/src/codegen/builder/mod.rs @@ -1,6 +1,6 @@ +pub mod base; pub mod branch; pub mod cast; -pub mod core; pub mod op; pub mod ty; pub mod value; diff --git a/comp-be/src/codegen/builder/op.rs b/comp-be/src/codegen/builder/op.rs index 0f1d127..fa1594c 100644 --- a/comp-be/src/codegen/builder/op.rs +++ b/comp-be/src/codegen/builder/op.rs @@ -1,23 +1,23 @@ -use crate::codegen::{AatbeModule, ValueTypePair}; +use crate::codegen::{unit::CompilerContext, ValueTypePair}; use llvm_sys_wrapper::LLVMValueRef; -use parser::ast::PrimitiveType; +use parser::ast::Type; -pub fn neg(module: &AatbeModule, val: ValueTypePair) -> ValueTypePair { - (module.llvm_builder_ref().build_neg(*val), val.prim()).into() +pub fn neg(ctx: &CompilerContext, val: ValueTypePair) -> ValueTypePair { + (ctx.llvm_builder.build_neg(*val), val.prim()).into() } -pub fn fneg(module: &AatbeModule, val: ValueTypePair) -> ValueTypePair { - (module.llvm_builder_ref().build_fneg(*val), val.prim()).into() +pub fn fneg(ctx: &CompilerContext, val: ValueTypePair) -> ValueTypePair { + (ctx.llvm_builder.build_fneg(*val), val.prim()).into() } -pub fn not(module: &AatbeModule, val: ValueTypePair) -> ValueTypePair { - (module.llvm_builder_ref().build_not(*val), val.prim()).into() +pub fn not(ctx: &CompilerContext, val: ValueTypePair) -> ValueTypePair { + (ctx.llvm_builder.build_not(*val), val.prim()).into() } -pub fn ieq(module: &AatbeModule, lhs: LLVMValueRef, rhs: LLVMValueRef) -> ValueTypePair { +pub fn ieq(ctx: &CompilerContext, lhs: LLVMValueRef, rhs: LLVMValueRef) -> ValueTypePair { ( - module.llvm_builder_ref().build_icmp_eq(lhs, rhs), - PrimitiveType::Bool, + ctx.llvm_builder.build_icmp_eq(lhs, rhs), + Type::Bool, ) .into() } diff --git a/comp-be/src/codegen/builder/ty.rs b/comp-be/src/codegen/builder/ty.rs index dfcd94a..92db37e 100644 --- a/comp-be/src/codegen/builder/ty.rs +++ b/comp-be/src/codegen/builder/ty.rs @@ -1,51 +1,44 @@ -use crate::{codegen::AatbeModule, ty::LLVMTyInCtx}; +use crate::{codegen::unit::CompilerContext, ty::LLVMTyInCtx}; use llvm_sys_wrapper::LLVMTypeRef; -pub fn pointer(module: &AatbeModule, ty: &dyn LLVMTyInCtx) -> LLVMTypeRef { - module - .llvm_context_ref() - .PointerType(ty.llvm_ty_in_ctx(module)) +pub fn pointer(ctx: &CompilerContext, ty: &dyn LLVMTyInCtx) -> LLVMTypeRef { + ctx.llvm_context.PointerType(ty.llvm_ty_in_ctx(ctx)) } -pub fn slice_type(module: &AatbeModule, ty: &dyn LLVMTyInCtx) -> LLVMTypeRef { - module - .llvm_context_ref() - .StructType(&mut vec![slice_ptr(module, ty), i32(module)], false) +pub fn slice_type(ctx: &CompilerContext, ty: &dyn LLVMTyInCtx) -> LLVMTypeRef { + ctx.llvm_context + .StructType(&mut vec![slice_ptr(ctx, ty), i32(ctx)], false) .as_ref() } -pub fn pointer_to(module: &AatbeModule, ty: LLVMTypeRef) -> LLVMTypeRef { - module.llvm_context_ref().PointerType(ty) +pub fn pointer_to(ctx: &CompilerContext, ty: LLVMTypeRef) -> LLVMTypeRef { + ctx.llvm_context.PointerType(ty) } -pub fn array(module: &AatbeModule, ty: &dyn LLVMTyInCtx, count: u32) -> LLVMTypeRef { - module - .llvm_context_ref() - .ArrayType(ty.llvm_ty_in_ctx(module), count) +pub fn array(ctx: &CompilerContext, ty: &dyn LLVMTyInCtx, count: u32) -> LLVMTypeRef { + ctx.llvm_context.ArrayType(ty.llvm_ty_in_ctx(ctx), count) } -pub fn slice(module: &AatbeModule, ty: &dyn LLVMTyInCtx) -> LLVMTypeRef { - module - .llvm_context_ref() - .ArrayType(ty.llvm_ty_in_ctx(module), 0) +pub fn slice(ctx: &CompilerContext, ty: &dyn LLVMTyInCtx) -> LLVMTypeRef { + ctx.llvm_context.ArrayType(ty.llvm_ty_in_ctx(ctx), 0) } -pub fn slice_ptr(module: &AatbeModule, ty: &dyn LLVMTyInCtx) -> LLVMTypeRef { - pointer_to(module, slice(module, ty)) +pub fn slice_ptr(ctx: &CompilerContext, ty: &dyn LLVMTyInCtx) -> LLVMTypeRef { + pointer_to(ctx, slice(ctx, ty)) } -pub fn i8(module: &AatbeModule) -> LLVMTypeRef { - module.llvm_context_ref().Int8Type() +pub fn i8(ctx: &CompilerContext) -> LLVMTypeRef { + ctx.llvm_context.Int8Type() } -pub fn i16(module: &AatbeModule) -> LLVMTypeRef { - module.llvm_context_ref().Int16Type() +pub fn i16(ctx: &CompilerContext) -> LLVMTypeRef { + ctx.llvm_context.Int16Type() } -pub fn i32(module: &AatbeModule) -> LLVMTypeRef { - module.llvm_context_ref().Int32Type() +pub fn i32(ctx: &CompilerContext) -> LLVMTypeRef { + ctx.llvm_context.Int32Type() } -pub fn i64(module: &AatbeModule) -> LLVMTypeRef { - module.llvm_context_ref().Int64Type() +pub fn i64(ctx: &CompilerContext) -> LLVMTypeRef { + ctx.llvm_context.Int64Type() } diff --git a/comp-be/src/codegen/builder/value.rs b/comp-be/src/codegen/builder/value.rs index 11a0a30..8fa5b52 100644 --- a/comp-be/src/codegen/builder/value.rs +++ b/comp-be/src/codegen/builder/value.rs @@ -1,141 +1,132 @@ -use crate::codegen::{AatbeModule, ValueTypePair}; +use crate::codegen::{unit::CompilerContext, ValueTypePair}; use llvm_sys_wrapper::{LLVMValueRef, Struct}; -use parser::ast::{FloatSize, IntSize, PrimitiveType}; +use parser::ast::{FloatSize, IntSize, Type}; -pub fn t(module: &AatbeModule) -> ValueTypePair { - (module.llvm_context_ref().SInt1(1), PrimitiveType::Bool).into() +pub fn t(ctx: &CompilerContext) -> ValueTypePair { + (ctx.llvm_context.SInt1(1), Type::Bool).into() } -pub fn f(module: &AatbeModule) -> ValueTypePair { - (module.llvm_context_ref().SInt1(0), PrimitiveType::Bool).into() +pub fn f(ctx: &CompilerContext) -> ValueTypePair { + (ctx.llvm_context.SInt1(0), Type::Bool).into() } -pub fn char(module: &AatbeModule, c: char) -> ValueTypePair { - ( - module.llvm_context_ref().SInt8(c as u64), - PrimitiveType::Char, - ) - .into() +pub fn char(ctx: &CompilerContext, c: char) -> ValueTypePair { + (ctx.llvm_context.SInt8(c as u64), Type::Char).into() } -pub fn s8(module: &AatbeModule, value: i8) -> ValueTypePair { +pub fn s8(ctx: &CompilerContext, value: i8) -> ValueTypePair { ( - module.llvm_context_ref().SInt8(value as u64), - PrimitiveType::Int(IntSize::Bits8), + ctx.llvm_context.SInt8(value as u64), + Type::Int(IntSize::Bits8), ) .into() } -pub fn s16(module: &AatbeModule, value: i16) -> ValueTypePair { +pub fn s16(ctx: &CompilerContext, value: i16) -> ValueTypePair { ( - module.llvm_context_ref().SInt16(value as u64), - PrimitiveType::Int(IntSize::Bits16), + ctx.llvm_context.SInt16(value as u64), + Type::Int(IntSize::Bits16), ) .into() } -pub fn s32(module: &AatbeModule, value: i32) -> ValueTypePair { +pub fn s32(ctx: &CompilerContext, value: i32) -> ValueTypePair { ( - module.llvm_context_ref().SInt32(value as u64), - PrimitiveType::Int(IntSize::Bits32), + ctx.llvm_context.SInt32(value as u64), + Type::Int(IntSize::Bits32), ) .into() } -pub fn s64(module: &AatbeModule, value: i64) -> ValueTypePair { +pub fn s64(ctx: &CompilerContext, value: i64) -> ValueTypePair { ( - module.llvm_context_ref().SInt64(value as u64), - PrimitiveType::Int(IntSize::Bits64), + ctx.llvm_context.SInt64(value as u64), + Type::Int(IntSize::Bits64), ) .into() } -pub fn u8(module: &AatbeModule, value: u8) -> ValueTypePair { +pub fn u8(ctx: &CompilerContext, value: u8) -> ValueTypePair { ( - module.llvm_context_ref().UInt8(value as u64), - PrimitiveType::UInt(IntSize::Bits8), + ctx.llvm_context.UInt8(value as u64), + Type::UInt(IntSize::Bits8), ) .into() } -pub fn u16(module: &AatbeModule, value: u16) -> ValueTypePair { +pub fn u16(ctx: &CompilerContext, value: u16) -> ValueTypePair { ( - module.llvm_context_ref().UInt16(value as u64), - PrimitiveType::UInt(IntSize::Bits16), + ctx.llvm_context.UInt16(value as u64), + Type::UInt(IntSize::Bits16), ) .into() } -pub fn u32(module: &AatbeModule, value: u32) -> ValueTypePair { +pub fn u32(ctx: &CompilerContext, value: u32) -> ValueTypePair { ( - module.llvm_context_ref().UInt32(value as u64), - PrimitiveType::UInt(IntSize::Bits32), + ctx.llvm_context.UInt32(value as u64), + Type::UInt(IntSize::Bits32), ) .into() } -pub fn u64(module: &AatbeModule, value: u64) -> ValueTypePair { - ( - module.llvm_context_ref().UInt64(value), - PrimitiveType::UInt(IntSize::Bits64), - ) - .into() +pub fn u64(ctx: &CompilerContext, value: u64) -> ValueTypePair { + (ctx.llvm_context.UInt64(value), Type::UInt(IntSize::Bits64)).into() } -pub fn slice( - module: &AatbeModule, - pointer: LLVMValueRef, - ty: PrimitiveType, - len: u32, -) -> ValueTypePair { +pub fn slice(ctx: &CompilerContext, pointer: LLVMValueRef, ty: Type, len: u32) -> ValueTypePair { ( - Struct::new_const_struct(&mut [pointer, *u32(module, len)], false), - PrimitiveType::Slice { ty: box ty }, + Struct::new_const_struct(&mut [pointer, *u32(ctx, len)], false), + Type::Slice { ty: box ty }, ) .into() } -pub fn sint(module: &AatbeModule, size: IntSize, value: u64) -> ValueTypePair { +pub fn sint(ctx: &CompilerContext, size: IntSize, value: u64) -> ValueTypePair { ( match size { - IntSize::Bits8 => module.llvm_context_ref().SInt8(value), - IntSize::Bits16 => module.llvm_context_ref().SInt16(value), - IntSize::Bits32 => module.llvm_context_ref().SInt32(value), - IntSize::Bits64 => module.llvm_context_ref().SInt64(value), + IntSize::Bits8 => ctx.llvm_context.SInt8(value), + IntSize::Bits16 => ctx.llvm_context.SInt16(value), + IntSize::Bits32 => ctx.llvm_context.SInt32(value), + IntSize::Bits64 => ctx.llvm_context.SInt64(value), }, - PrimitiveType::Int(size), + Type::Int(size), ) .into() } -pub fn uint(module: &AatbeModule, size: IntSize, value: u64) -> ValueTypePair { +pub fn uint(ctx: &CompilerContext, size: IntSize, value: u64) -> ValueTypePair { ( match size { - IntSize::Bits8 => module.llvm_context_ref().UInt8(value), - IntSize::Bits16 => module.llvm_context_ref().UInt16(value), - IntSize::Bits32 => module.llvm_context_ref().UInt32(value), - IntSize::Bits64 => module.llvm_context_ref().UInt64(value), + IntSize::Bits8 => ctx.llvm_context.UInt8(value), + IntSize::Bits16 => ctx.llvm_context.UInt16(value), + IntSize::Bits32 => ctx.llvm_context.UInt32(value), + IntSize::Bits64 => ctx.llvm_context.UInt64(value), }, - PrimitiveType::UInt(size), + Type::UInt(size), ) .into() } -pub fn floating(module: &AatbeModule, size: FloatSize, value: f64) -> ValueTypePair { +pub fn floating(ctx: &CompilerContext, size: FloatSize, value: f64) -> ValueTypePair { ( match size { - FloatSize::Bits32 => module.llvm_context_ref().Float(value), - FloatSize::Bits64 => module.llvm_context_ref().Double(value), + FloatSize::Bits32 => ctx.llvm_context.Float(value), + FloatSize::Bits64 => ctx.llvm_context.Double(value), }, - PrimitiveType::Float(size), + Type::Float(size), ) .into() } -pub fn str(module: &AatbeModule, string: &str) -> ValueTypePair { +pub fn str(ctx: &CompilerContext, string: &str) -> ValueTypePair { + (ctx.llvm_builder.build_global_string_ptr(string), Type::Str).into() +} + +pub fn unit(ctx: &CompilerContext) -> ValueTypePair { ( - module.llvm_builder_ref().build_global_string_ptr(string), - PrimitiveType::Str, + ctx.llvm_context.Null(ctx.llvm_context.VoidType()), + Type::Unit, ) .into() } diff --git a/comp-be/src/codegen/call.rs b/comp-be/src/codegen/call.rs index b257eec..413fe0e 100644 --- a/comp-be/src/codegen/call.rs +++ b/comp-be/src/codegen/call.rs @@ -1,17 +1,18 @@ use crate::{ codegen::{ - builder::{cast, core, ty, value}, + builder::{base, cast, ty, value}, unit::function::find_function, AatbeModule, CompileError, ValueTypePair, }, fmt::AatbeFmt, ty::LLVMTyInCtx, }; -use parser::ast::{AtomKind, Expression, PrimitiveType}; +use parser::ast::{AtomKind, Expression, Type}; impl AatbeModule { pub fn codegen_call(&mut self, call_expr: &Expression) -> Option { - match call_expr { + todo!() + /*match call_expr { // TODO: generics Expression::Call { name, @@ -30,11 +31,11 @@ impl AatbeModule { .iter() .filter_map(|arg| match arg { Expression::Atom(AtomKind::SymbolLiteral(sym)) => { - call_types.push(PrimitiveType::Symbol(sym.clone())); + call_types.push(Type::Symbol(sym.clone())); None } Expression::Atom(AtomKind::Unit) => { - call_types.push(PrimitiveType::Unit); + call_types.push(Type::Unit); None } _ => { @@ -46,8 +47,8 @@ impl AatbeModule { None } else { expr.map_or(None, |arg| match arg.prim().clone() { - PrimitiveType::VariantType(name) => { - call_types.push(PrimitiveType::VariantType(name.clone())); + Type::VariantType(name) => { + call_types.push(Type::VariantType(name.clone())); let ty = self.typectx_ref().get_parent_for_variant(&name)?; Some(core::load( @@ -55,15 +56,15 @@ impl AatbeModule { cast::bitcast_to(self, *arg, ty::pointer(self, ty)), )) } - PrimitiveType::Array { ty: box ty, len } => { + Type::Array { ty: box ty, len } => { let arr = cast::bitcast_to(self, *arg, ty::slice_ptr(self, &ty)); let slice = value::slice(self, arr, ty.clone(), len); - call_types.push(PrimitiveType::Slice { ty: box ty }); + call_types.push(Type::Slice { ty: box ty }); Some(*slice) } - PrimitiveType::Ref(box PrimitiveType::Array { + Type::Ref(box Type::Array { ty: box ty, len, }) => { @@ -76,8 +77,8 @@ impl AatbeModule { core::store(self, arr, arr_ptr); core::store(self, *value::u32(self, len), len_ptr); - call_types.push(PrimitiveType::Ref( - box PrimitiveType::Slice { ty: box ty }, + call_types.push(Type::Ref( + box Type::Slice { ty: box ty }, )); Some(slice) } @@ -134,7 +135,7 @@ impl AatbeModule { Some(core::call(self, func.unwrap(), &mut call_args)) } _ => unreachable!(), - } + }*/ } pub fn internal_len( @@ -142,13 +143,14 @@ impl AatbeModule { values: &Vec, _name: String, ) -> Option { - if values.len() != 1 { + todo!() + /*if values.len() != 1 { return None; } let arr = module.codegen_expr(&values[0])?; match arr.prim() { - PrimitiveType::Array { len, .. } => Some(value::u32(module, *len)), - PrimitiveType::Slice { .. } => Some(core::extract_u32(module, *arr, 1)), + Type::Array { len, .. } => Some(value::u32(module, *len)), + Type::Slice { .. } => Some(core::extract_u32(module, *arr, 1)), _ => { module.add_error(CompileError::MismatchedArguments { function: String::from("len"), @@ -157,7 +159,7 @@ impl AatbeModule { }); None } - } + }*/ } pub fn internal_box( @@ -165,7 +167,8 @@ impl AatbeModule { values: &Vec, _name: String, ) -> Option { - if values.len() != 1 { + todo!("internal_box") + /*if values.len() != 1 { return None; } @@ -175,7 +178,7 @@ impl AatbeModule { .llvm_builder_ref() .build_malloc(val_ty.clone().llvm_ty_in_ctx(module)); - if let PrimitiveType::VariantType(_) = val_ty.inner() { + if let Type::VariantType(_) = val_ty.inner() { unimplemented!(); } @@ -184,6 +187,6 @@ impl AatbeModule { core::inbounds_gep(module, ptr, &mut vec![*value::s64(module, 0)]), ); - Some((ptr, PrimitiveType::Box(box val_ty.clone())).into()) + Some((ptr, Type::Box(box val_ty.clone())).into())*/ } } diff --git a/comp-be/src/codegen/comp_unit.rs b/comp-be/src/codegen/comp_unit.rs index ed351f0..18a1efc 100644 --- a/comp-be/src/codegen/comp_unit.rs +++ b/comp-be/src/codegen/comp_unit.rs @@ -26,7 +26,7 @@ impl CompilationUnit { path, ast: match Parser::new(Lexer::new(code.as_str()).lex()).parse() { Ok(ptree) => ptree, - Err(err) => panic!(format!("{:#?}", err)), + Err(err) => panic!("{:#?}", err), }, }) } diff --git a/comp-be/src/codegen/conditional.rs b/comp-be/src/codegen/conditional.rs index 3d7178e..7b20b0b 100644 --- a/comp-be/src/codegen/conditional.rs +++ b/comp-be/src/codegen/conditional.rs @@ -1,19 +1,20 @@ use crate::{ codegen::{ - builder::{branch, core}, + builder::{base, branch}, AatbeModule, CompileError, ValueTypePair, }, fmt::AatbeFmt, ty::LLVMTyInCtx, }; -use parser::ast::{Expression, LoopType, PrimitiveType}; +use parser::ast::{Expression, LoopType, Type}; use llvm_sys_wrapper::Phi; impl AatbeModule { pub fn codegen_if(&mut self, if_expr: &Expression) -> Option { - match if_expr { + todo!("{:?}", if_expr); + /*match if_expr { Expression::If { cond_expr, then_expr, @@ -31,9 +32,9 @@ impl AatbeModule { self.start_scope(); let cond = self.codegen_expr(cond_expr)?; - if *cond.prim().inner() != PrimitiveType::Bool { + if *cond.prim().inner() != Type::Bool { self.add_error(CompileError::ExpectedType { - expected_ty: PrimitiveType::Bool.fmt(), + expected_ty: Type::Bool.fmt(), found_ty: cond.prim().fmt(), value: cond_expr.fmt(), }); @@ -68,7 +69,7 @@ impl AatbeModule { if let Some(then_val) = then_val { let ty = then_val.prim().clone(); - if ty != PrimitiveType::Unit { + if ty != Type::Unit { if else_val.is_some() { let phi = Phi::new( self.llvm_builder_ref().as_ref(), @@ -101,11 +102,12 @@ impl AatbeModule { } } _ => unreachable!(), - } + }*/ } pub fn codegen_basic_loop(&mut self, basic_loop: &Expression) -> Option { - match basic_loop { + todo!() + /*match basic_loop { Expression::Loop { loop_type, cond_expr, @@ -119,9 +121,9 @@ impl AatbeModule { core::pos_at_end(self, cond_bb); let cond = self.codegen_expr(cond_expr)?; - if *cond.prim().inner() != PrimitiveType::Bool { + if *cond.prim().inner() != Type::Bool { self.add_error(CompileError::ExpectedType { - expected_ty: PrimitiveType::Bool.fmt(), + expected_ty: Type::Bool.fmt(), found_ty: cond.prim().fmt(), value: cond_expr.fmt(), }); @@ -141,6 +143,6 @@ impl AatbeModule { None } _ => unreachable!(), - } + }*/ } } diff --git a/comp-be/src/codegen/expr/compare.rs b/comp-be/src/codegen/expr/compare.rs deleted file mode 100644 index c68073e..0000000 --- a/comp-be/src/codegen/expr/compare.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::codegen::{AatbeModule, ValueTypePair}; -use parser::ast::PrimitiveType; - -use llvm_sys_wrapper::LLVMValueRef; - -pub fn codegen_compare_float( - module: &AatbeModule, - op: &String, - lhs: LLVMValueRef, - rhs: LLVMValueRef, -) -> ValueTypePair { - ( - match op.as_str() { - "<" => module.llvm_builder_ref().build_fcmp_ult(lhs, rhs), - ">" => module.llvm_builder_ref().build_fcmp_ugt(lhs, rhs), - "<=" => module.llvm_builder_ref().build_fcmp_ule(lhs, rhs), - ">=" => module.llvm_builder_ref().build_fcmp_uge(lhs, rhs), - _ => panic!("ICE codegen_compare_float unhandled op {}", op), - }, - PrimitiveType::Bool, - ) - .into() -} - -pub fn codegen_compare_signed( - module: &AatbeModule, - op: &String, - lhs: LLVMValueRef, - rhs: LLVMValueRef, -) -> ValueTypePair { - ( - match op.as_str() { - "<" => module.llvm_builder_ref().build_icmp_slt(lhs, rhs), - ">" => module.llvm_builder_ref().build_icmp_sgt(lhs, rhs), - "<=" => module.llvm_builder_ref().build_icmp_sle(lhs, rhs), - ">=" => module.llvm_builder_ref().build_icmp_sge(lhs, rhs), - _ => panic!("ICE codegen_compare_signed unhandled op {}", op), - }, - PrimitiveType::Bool, - ) - .into() -} - -pub fn codegen_compare_unsigned( - module: &AatbeModule, - op: &String, - lhs: LLVMValueRef, - rhs: LLVMValueRef, -) -> ValueTypePair { - ( - match op.as_str() { - "<" => module.llvm_builder_ref().build_icmp_ult(lhs, rhs), - ">" => module.llvm_builder_ref().build_icmp_ugt(lhs, rhs), - "<=" => module.llvm_builder_ref().build_icmp_ule(lhs, rhs), - ">=" => module.llvm_builder_ref().build_icmp_uge(lhs, rhs), - _ => panic!("ICE codegen_compare_unsigned unhandled op {}", op), - }, - PrimitiveType::Bool, - ) - .into() -} diff --git a/comp-be/src/codegen/expr/const_expr.rs b/comp-be/src/codegen/expr/const_expr.rs deleted file mode 100644 index f4840ae..0000000 --- a/comp-be/src/codegen/expr/const_expr.rs +++ /dev/null @@ -1,118 +0,0 @@ -use crate::{ - codegen::{ - builder::value, - unit::{Mutability, Slot}, - AatbeModule, CompileError, ValueTypePair, - }, - fmt::AatbeFmt, - ty::LLVMTyInCtx, -}; -use parser::ast::{AtomKind, Expression, PrimitiveType, AST}; - -pub fn const_atom(module: &AatbeModule, atom: &AtomKind) -> Option { - match atom { - AtomKind::StringLiteral(string) => Some(value::str(module, string.as_ref())), - AtomKind::CharLiteral(ch) => Some(value::char(module, *ch)), - AtomKind::Integer(val, PrimitiveType::Int(size)) => { - Some(value::sint(module, size.clone(), *val)) - } - AtomKind::Integer(val, PrimitiveType::UInt(size)) => { - Some(value::uint(module, size.clone(), *val)) - } - AtomKind::Floating(val, PrimitiveType::Float(size)) => { - Some(value::floating(module, size.clone(), *val)) - } - AtomKind::Cast(box AtomKind::Integer(val, _), PrimitiveType::Char) => { - Some(value::char(module, *val as u8 as char)) - } - AtomKind::Unary(op, box AtomKind::Integer(val, PrimitiveType::Int(size))) - if op == &String::from("-") => - { - Some(value::sint(module, size.clone(), (-(*val as i64)) as u64)) - } - AtomKind::Unary(op, box AtomKind::Integer(val, PrimitiveType::UInt(size))) - if op == &String::from("-") => - { - Some(value::uint(module, size.clone(), (-(*val as i64)) as u64)) - } - AtomKind::Parenthesized(box atom) => fold_expression(module, atom), - _ => panic!("ICE fold_atom {:?}", atom), - } -} - -fn fold_expression(module: &AatbeModule, expr: &Expression) -> Option { - match expr { - Expression::Atom(atom) => const_atom(module, atom), - _ => panic!("ICE fold_expression {:?}", expr), - } -} - -pub fn fold_constant(module: &mut AatbeModule, ast: &AST) -> Option { - match ast { - AST::Global { - ty: - PrimitiveType::NamedType { - name, - ty: Some(box ty), - }, - value, - export: _, - } => fold_expression(module, value) - .and_then(|val| { - if val.prim() != ty.inner() { - module.add_error(CompileError::AssignMismatch { - expected_ty: ty.fmt(), - found_ty: val.prim().fmt(), - value: value.fmt(), - var: name.clone(), - }); - - None - } else { - Some(val) - } - }) - .map(|val| { - let val_ref = module - .llvm_module_ref() - .add_global(ty.llvm_ty_in_ctx(module), name.as_ref()); - module.llvm_module_ref().set_initializer(val_ref, *val); - Slot::Variable { - mutable: Mutability::Global, - name: name.clone(), - ty: val.prim().clone(), - value: val_ref, - } - }), - AST::Constant { - ty: - PrimitiveType::NamedType { - name, - ty: Some(box ty), - }, - value, - export: _, - } => fold_expression(module, value) - .and_then(|val| { - if val.prim() != ty.inner() { - module.add_error(CompileError::AssignMismatch { - expected_ty: ty.fmt(), - found_ty: val.prim().fmt(), - value: value.fmt(), - var: name.clone(), - }); - - None - } else { - Some(val) - } - }) - .map(|val| Slot::Variable { - mutable: Mutability::Constant, - name: name.clone(), - ty: val.prim().clone(), - value: *val, - }), - _ => unreachable!(), - } -} diff --git a/comp-be/src/codegen/expr/eqne.rs b/comp-be/src/codegen/expr/eqne.rs deleted file mode 100644 index e16668e..0000000 --- a/comp-be/src/codegen/expr/eqne.rs +++ /dev/null @@ -1,55 +0,0 @@ -use crate::codegen::{AatbeModule, ValueTypePair}; -use parser::ast::PrimitiveType; - -use llvm_sys_wrapper::LLVMValueRef; - -pub fn codegen_eq_ne( - module: &AatbeModule, - op: &String, - lhs: LLVMValueRef, - rhs: LLVMValueRef, -) -> ValueTypePair { - ( - match op.as_str() { - "==" => module.llvm_builder_ref().build_icmp_eq(lhs, rhs), - "!=" => module.llvm_builder_ref().build_icmp_ne(lhs, rhs), - _ => panic!("ICE codegen_eq_ne unhandled op {}", op), - }, - PrimitiveType::Bool, - ) - .into() -} - -pub fn codegen_boolean( - module: &AatbeModule, - op: &String, - lhs: LLVMValueRef, - rhs: LLVMValueRef, -) -> ValueTypePair { - ( - match op.as_str() { - "&&" => module.llvm_builder_ref().build_and(lhs, rhs), - "||" => module.llvm_builder_ref().build_or(lhs, rhs), - _ => panic!("ICE codegen_eq_ne unhandled op {}", op), - }, - PrimitiveType::Bool, - ) - .into() -} - -pub fn codegen_eq_ne_float( - module: &AatbeModule, - op: &String, - lhs: LLVMValueRef, - rhs: LLVMValueRef, -) -> ValueTypePair { - ( - match op.as_str() { - "==" => module.llvm_builder_ref().build_fcmp_ueq(lhs, rhs), - "!=" => module.llvm_builder_ref().build_fcmp_une(lhs, rhs), - _ => panic!("ICE codegen_eq_ne_float unhandled op {}", op), - }, - PrimitiveType::Bool, - ) - .into() -} diff --git a/comp-be/src/codegen/expr/math.rs b/comp-be/src/codegen/expr/math.rs deleted file mode 100644 index e8ab19d..0000000 --- a/comp-be/src/codegen/expr/math.rs +++ /dev/null @@ -1,67 +0,0 @@ -use crate::codegen::{AatbeModule, ValueTypePair}; -use parser::ast::{FloatSize, IntSize, PrimitiveType}; - -use llvm_sys_wrapper::LLVMValueRef; - -pub fn codegen_float_ops( - module: &AatbeModule, - op: &String, - lhs: LLVMValueRef, - rhs: LLVMValueRef, - float_size: FloatSize, -) -> ValueTypePair { - ( - match op.as_str() { - "+" => module.llvm_builder_ref().build_fadd(lhs, rhs), - "-" => module.llvm_builder_ref().build_fsub(lhs, rhs), - "*" => module.llvm_builder_ref().build_fmul(lhs, rhs), - "/" => module.llvm_builder_ref().build_fdiv(lhs, rhs), - "%" => module.llvm_builder_ref().build_frem(lhs, rhs), - _ => panic!("ICE codegen_float_ops unhandled op {}", op), - }, - PrimitiveType::Float(float_size), - ) - .into() -} - -pub fn codegen_signed_ops( - module: &AatbeModule, - op: &String, - lhs: LLVMValueRef, - rhs: LLVMValueRef, - int_size: IntSize, -) -> ValueTypePair { - ( - match op.as_str() { - "+" => module.llvm_builder_ref().build_add(lhs, rhs), - "-" => module.llvm_builder_ref().build_sub(lhs, rhs), - "*" => module.llvm_builder_ref().build_mul(lhs, rhs), - "/" => module.llvm_builder_ref().build_sdiv(lhs, rhs), - "%" => module.llvm_builder_ref().build_srem(lhs, rhs), - _ => panic!("ICE codegen_unsigned_ops unhandled op {}", op), - }, - PrimitiveType::Int(int_size), - ) - .into() -} - -pub fn codegen_unsigned_ops( - module: &AatbeModule, - op: &String, - lhs: LLVMValueRef, - rhs: LLVMValueRef, - int_size: PrimitiveType, -) -> ValueTypePair { - ( - match op.as_str() { - "+" => module.llvm_builder_ref().build_add(lhs, rhs), - "-" => module.llvm_builder_ref().build_sub(lhs, rhs), - "*" => module.llvm_builder_ref().build_mul(lhs, rhs), - "/" => module.llvm_builder_ref().build_udiv(lhs, rhs), - "%" => module.llvm_builder_ref().build_urem(lhs, rhs), - _ => panic!("ICE codegen_unsigned_ops unhandled op {}", op), - }, - int_size, - ) - .into() -} diff --git a/comp-be/src/codegen/expr/mod.rs b/comp-be/src/codegen/expr/mod.rs index 7e672b2..8c94b08 100644 --- a/comp-be/src/codegen/expr/mod.rs +++ b/comp-be/src/codegen/expr/mod.rs @@ -1,142 +1,100 @@ -mod eqne; -use eqne::{codegen_boolean, codegen_eq_ne, codegen_eq_ne_float}; - -mod compare; -use compare::{codegen_compare_float, codegen_compare_signed, codegen_compare_unsigned}; - -mod math; -use math::{codegen_float_ops, codegen_signed_ops, codegen_unsigned_ops}; - -pub mod const_expr; - use crate::{ - codegen::{AatbeModule, CompileError, GenRes, ValueTypePair}, + codegen::{ + builder::value, + unit::{CompilerContext, Mutability, Slot}, + AatbeModule, CompileError, ValueTypePair, + }, fmt::AatbeFmt, + ty::LLVMTyInCtx, }; -use parser::ast::{Expression, FloatSize, IntSize, PrimitiveType}; - -use llvm_sys_wrapper::LLVMValueRef; +use parser::ast::{AtomKind, Expression, Type, AST}; -fn dispatch_bool( - module: &AatbeModule, - op: &String, - lhs: LLVMValueRef, - rhs: LLVMValueRef, -) -> Option { - match op.as_str() { - "==" | "!=" => Some(codegen_eq_ne(module, op, lhs, rhs)), - "&&" | "||" => Some(codegen_boolean(module, op, lhs, rhs)), - _ => None, +pub fn const_atom(ctx: &CompilerContext, atom: &AtomKind) -> Option { + match atom { + AtomKind::StringLiteral(string) => Some(value::str(ctx, &string)), + AtomKind::CharLiteral(ch) => Some(value::char(ctx, *ch)), + AtomKind::Cast(box AtomKind::Integer(val, _), Type::Char) => { + Some(value::char(ctx, *val as u8 as char)) + } + AtomKind::Parenthesized(box atom) => fold_expression(ctx, atom), + _ => panic!("ICE fold_atom {:?}", atom), } } -fn dispatch_signed( - module: &AatbeModule, - op: &String, - lhs: LLVMValueRef, - rhs: LLVMValueRef, - int_size: IntSize, -) -> Option { - match op.as_str() { - "+" | "-" | "*" | "/" | "%" => Some(codegen_signed_ops(module, op, lhs, rhs, int_size)), - ">" | "<" | ">=" | "<=" => Some(codegen_compare_signed(module, op, lhs, rhs)), - "==" | "!=" => Some(codegen_eq_ne(module, op, lhs, rhs)), - _ => None, +fn fold_expression(ctx: &CompilerContext, expr: &Expression) -> Option { + match expr { + Expression::Atom(atom) => const_atom(ctx, atom), + _ => panic!("ICE fold_expression {:?}", expr), } } -fn dispatch_float( - module: &AatbeModule, - op: &String, - lhs: LLVMValueRef, - rhs: LLVMValueRef, - float_size: FloatSize, -) -> Option { - match op.as_str() { - "+" | "-" | "*" | "/" | "%" => Some(codegen_float_ops(module, op, lhs, rhs, float_size)), - ">" | "<" | ">=" | "<=" => Some(codegen_compare_float(module, op, lhs, rhs)), - "==" | "!=" => Some(codegen_eq_ne_float(module, op, lhs, rhs)), - _ => None, - } -} +pub fn fold_constant(module: &mut AatbeModule, ast: &AST) -> Option { + /*match ast { + AST::Global { + ty: + Type::NamedType { + name, + ty: Some(box ty), + }, + value, + export: _, + } => fold_expression(module, value) + .and_then(|val| { + if val.prim() != ty.inner() { + module.add_error(CompileError::AssignMismatch { + expected_ty: ty.fmt(), + found_ty: val.prim().fmt(), + value: value.fmt(), + var: name.clone(), + }); -fn dispatch_unsigned( - module: &AatbeModule, - op: &String, - lhs: LLVMValueRef, - rhs: LLVMValueRef, - int_size: PrimitiveType, -) -> Option { - match op.as_str() { - "+" | "-" | "*" | "/" | "%" => Some(codegen_unsigned_ops(module, op, lhs, rhs, int_size)), - ">" | "<" | ">=" | "<=" => Some(codegen_compare_unsigned(module, op, lhs, rhs)), - "==" | "!=" => Some(codegen_eq_ne(module, op, lhs, rhs)), - _ => None, - } -} - -pub fn codegen_binary( - module: &mut AatbeModule, - op: &String, - lhs_expr: &Expression, - rhs_expr: &Expression, -) -> GenRes { - let lhs = module.codegen_expr(lhs_expr).ok_or(CompileError::Handled)?; - let rhs = module.codegen_expr(rhs_expr).ok_or(CompileError::Handled)?; + None + } else { + Some(val) + } + }) + .map(|val| { + let val_ref = module + .llvm_module_ref() + .add_global(ty.llvm_ty_in_ctx(module), name.as_ref()); + module.llvm_module_ref().set_initializer(val_ref, *val); + Slot::Variable { + mutable: Mutability::Global, + name: name.clone(), + ty: val.prim().clone(), + value: val_ref, + } + }), + AST::Constant { + ty: + Type::NamedType { + name, + ty: Some(box ty), + }, + value, + export: _, + } => fold_expression(module, value) + .and_then(|val| { + if val.prim() != ty.inner() { + module.add_error(CompileError::AssignMismatch { + expected_ty: ty.fmt(), + found_ty: val.prim().fmt(), + value: value.fmt(), + var: name.clone(), + }); - match (lhs.prim(), rhs.prim()) { - (PrimitiveType::Bool, PrimitiveType::Bool) => match dispatch_bool(module, op, *lhs, *rhs) { - Some(res) => Ok(res), - None => Err(CompileError::OpMismatch { - op: op.clone(), - types: (lhs.prim().fmt(), rhs.prim().fmt()), - values: (lhs_expr.fmt(), rhs_expr.fmt()), + None + } else { + Some(val) + } + }) + .map(|val| Slot::Variable { + mutable: Mutability::Constant, + name: name.clone(), + ty: val.prim().clone(), + value: *val, }), - }, - (PrimitiveType::Char, PrimitiveType::Char) => { - match dispatch_unsigned(module, op, *lhs, *rhs, PrimitiveType::Char) { - Some(res) => Ok(res), - None => Err(CompileError::OpMismatch { - op: op.clone(), - types: (lhs.prim().fmt(), rhs.prim().fmt()), - values: (lhs_expr.fmt(), rhs_expr.fmt()), - }), - } - } - (PrimitiveType::UInt(lsz), PrimitiveType::UInt(rsz)) if lsz == rsz => { - match dispatch_unsigned(module, op, *lhs, *rhs, PrimitiveType::UInt(lsz.clone())) { - Some(res) => Ok(res), - None => Err(CompileError::OpMismatch { - op: op.clone(), - types: (lhs.prim().fmt(), rhs.prim().fmt()), - values: (lhs_expr.fmt(), rhs_expr.fmt()), - }), - } - } - (PrimitiveType::Int(lsz), PrimitiveType::Int(rsz)) if lsz == rsz => { - match dispatch_signed(module, op, *lhs, *rhs, lsz.clone()) { - Some(res) => Ok(res), - None => Err(CompileError::OpMismatch { - op: op.clone(), - types: (lhs.prim().fmt(), rhs.prim().fmt()), - values: (lhs_expr.fmt(), rhs_expr.fmt()), - }), - } - } - (PrimitiveType::Float(lsz), PrimitiveType::Float(rsz)) if lsz == rsz => { - match dispatch_float(module, op, *lhs, *rhs, lsz.clone()) { - Some(res) => Ok(res), - None => Err(CompileError::OpMismatch { - op: op.clone(), - types: (lhs.prim().fmt(), rhs.prim().fmt()), - values: (lhs_expr.fmt(), rhs_expr.fmt()), - }), - } - } - _ => Err(CompileError::BinaryMismatch { - op: op.clone(), - types: (lhs.prim().fmt(), rhs.prim().fmt()), - values: (lhs_expr.fmt(), rhs_expr.fmt()), - }), - } + _ => unreachable!(), + }*/ + todo!("{:?}", ast) } diff --git a/comp-be/src/codegen/mangle_v1.rs b/comp-be/src/codegen/mangle_v1.rs index e6802a5..fc0fa36 100644 --- a/comp-be/src/codegen/mangle_v1.rs +++ b/comp-be/src/codegen/mangle_v1.rs @@ -1,13 +1,14 @@ -use crate::codegen::AatbeModule; +use parser::ast::{AtomKind, Expression, FloatSize, FunctionType, IntSize, Type}; -use parser::ast::{AtomKind, Expression, FloatSize, FunctionType, IntSize, PrimitiveType}; +use super::unit::CompilerContext; +use crate::prefix; pub trait NameMangler { - fn mangle(&self, module: &AatbeModule) -> String; + fn mangle(&self, ctx: &CompilerContext) -> String; } impl NameMangler for Expression { - fn mangle(&self, module: &AatbeModule) -> String { + fn mangle(&self, ctx: &CompilerContext) -> String { match self { Expression::Function { name, @@ -15,7 +16,7 @@ impl NameMangler for Expression { body: _, attributes, type_names, - export: _, + public: _, } => match ty { FunctionType { ext: false, @@ -25,13 +26,25 @@ impl NameMangler for Expression { if !attributes.contains(&String::from("entry")) { format!( "{}{}{}", - name, + { + let n = prefix!(ctx, name.clone()); + if n.len() == 1 { + n[0].clone() + } else { + format!( + "_{}", + n.iter().fold(String::default(), |prev, curr| { + format!("{}{}{}", prev, curr.len(), curr) + }) + ) + } + }, if type_names.len() > 0 { format!("G{}", type_names.len()) } else { String::default() }, - ty.mangle(module), + ty.mangle(ctx), ) } else { name.clone() @@ -49,27 +62,27 @@ impl NameMangler for Expression { } impl NameMangler for AtomKind { - fn mangle(&self, module: &AatbeModule) -> String { + fn mangle(&self, ctx: &CompilerContext) -> String { match self { AtomKind::StringLiteral(lit) => format!("{:?}", lit), AtomKind::Ident(id) => id.clone(), AtomKind::SymbolLiteral(sym) => format!(":{}", sym), - AtomKind::Floating(val, ty) => format!("{:?}{}", val, ty.mangle(module)), - AtomKind::Integer(val, ty) => format!("{:?}{}", val, ty.mangle(module)), + AtomKind::Floating(val, ty) => format!("{:?}{}", val, ty.mangle(ctx)), + AtomKind::Integer(val, ty) => format!("{:?}{}", val, ty.mangle(ctx)), AtomKind::Access(arr) => arr.join("."), - AtomKind::Parenthesized(val) => format!("{}", val.mangle(module)), - AtomKind::Ref(val) => format!("&{}", val.mangle(module)), + AtomKind::Parenthesized(val) => format!("{}", val.mangle(ctx)), + AtomKind::Ref(val) => format!("&{}", val.mangle(ctx)), _ => panic!("ICE mangle {:?}", self), } } } impl NameMangler for FunctionType { - fn mangle(&self, module: &AatbeModule) -> String { + fn mangle(&self, ctx: &CompilerContext) -> String { let params_mangled = self .params .iter() - .map(|p| p.mangle(module)) + .map(|p| p.mangle(ctx)) .filter(|m| !m.is_empty()) .collect::>() .join("."); @@ -81,44 +94,44 @@ impl NameMangler for FunctionType { } } -impl NameMangler for PrimitiveType { - fn mangle(&self, module: &AatbeModule) -> String { +impl NameMangler for Type { + fn mangle(&self, ctx: &CompilerContext) -> String { match self { - PrimitiveType::TypeRef(ty) => ty.clone(), - PrimitiveType::Function(ty) => ty.mangle(module), + Type::TypeRef(ty) => ty.clone(), + Type::Function(ty) => ty.mangle(ctx), // TODO: Handle Unit - PrimitiveType::Unit => String::new(), - PrimitiveType::NamedType { + Type::Unit => String::new(), + Type::NamedType { name: _, ty: Some(ty), - } => ty.mangle(module), - PrimitiveType::Str => String::from("s"), - PrimitiveType::Int(size) => format!("i{}", size.mangle(module)), - PrimitiveType::UInt(size) => format!("u{}", size.mangle(module)), - PrimitiveType::Float(size) => format!("f{}", size.mangle(module)), - PrimitiveType::Bool => String::from("b"), - PrimitiveType::Char => String::from("c"), - PrimitiveType::Ref(r) => format!("R{}", r.mangle(module)), - PrimitiveType::Pointer(p) => format!("P{}", p.mangle(module)), - PrimitiveType::Array { ty, len: _ } => format!("A{}", ty.mangle(module)), - PrimitiveType::Slice { ty } => format!("S{}", ty.mangle(module)), - PrimitiveType::Symbol(name) => format!("N{}", name), - PrimitiveType::VariantType(name) => format!( + } => ty.mangle(ctx), + Type::Str => String::from("s"), + Type::Int(size) => format!("i{}", size.mangle(ctx)), + Type::UInt(size) => format!("u{}", size.mangle(ctx)), + Type::Float(size) => format!("f{}", size.mangle(ctx)), + Type::Bool => String::from("b"), + Type::Char => String::from("c"), + Type::Ref(r) => format!("R{}", r.mangle(ctx)), + Type::Pointer(p) => format!("P{}", p.mangle(ctx)), + Type::Array { ty, len: _ } => format!("A{}", ty.mangle(ctx)), + Type::Slice { ty } => format!("S{}", ty.mangle(ctx)), + Type::Symbol(name) => format!("N{}", name), + /*Type::VariantType(name) => format!( "{}", module .typectx_ref() .get_variant(name) .expect(format!("Cannot find variant {}", name).as_str()) .parent_name - ), - PrimitiveType::Variant { parent, .. } => parent.clone(), + ),*/ + Type::Variant { parent, .. } => parent.clone(), _ => panic!("Cannot name mangle {:?}", self), } } } impl NameMangler for IntSize { - fn mangle(&self, _module: &AatbeModule) -> String { + fn mangle(&self, _ctx: &CompilerContext) -> String { match self { IntSize::Bits8 => String::from("8"), IntSize::Bits16 => String::from("16"), @@ -129,7 +142,7 @@ impl NameMangler for IntSize { } impl NameMangler for FloatSize { - fn mangle(&self, _module: &AatbeModule) -> String { + fn mangle(&self, _ctx: &CompilerContext) -> String { match self { FloatSize::Bits32 => String::from("32"), FloatSize::Bits64 => String::from("64"), diff --git a/comp-be/src/codegen/mod.rs b/comp-be/src/codegen/mod.rs index ce59a2c..e9666cc 100644 --- a/comp-be/src/codegen/mod.rs +++ b/comp-be/src/codegen/mod.rs @@ -93,7 +93,7 @@ pub enum CompileError { use crate::ty::TypeKind; use llvm_sys_wrapper::LLVMValueRef; -use parser::ast::PrimitiveType; +use parser::ast::Type; pub struct ValueTypePair(LLVMValueRef, TypeKind); @@ -103,14 +103,14 @@ impl From<(LLVMValueRef, TypeKind)> for ValueTypePair { } } -impl From<(LLVMValueRef, PrimitiveType)> for ValueTypePair { - fn from((val, ty): (LLVMValueRef, PrimitiveType)) -> ValueTypePair { +impl From<(LLVMValueRef, Type)> for ValueTypePair { + fn from((val, ty): (LLVMValueRef, Type)) -> ValueTypePair { ValueTypePair(val, TypeKind::Primitive(ty)) } } -impl From<(LLVMValueRef, &PrimitiveType)> for ValueTypePair { - fn from((val, ty): (LLVMValueRef, &PrimitiveType)) -> ValueTypePair { +impl From<(LLVMValueRef, &Type)> for ValueTypePair { + fn from((val, ty): (LLVMValueRef, &Type)) -> ValueTypePair { ValueTypePair(val, TypeKind::Primitive(ty.clone())) } } @@ -122,17 +122,17 @@ impl From for (LLVMValueRef, TypeKind) { } impl ValueTypePair { - pub fn prim(&self) -> &PrimitiveType { + pub fn prim(&self) -> &Type { match self { ValueTypePair( _, - TypeKind::Primitive(PrimitiveType::NamedType { + TypeKind::Primitive(Type::NamedType { name: _, ty: Some(ty), }), ) => ty, ValueTypePair(_, TypeKind::Primitive(prim)) => prim, - _ => panic!("ICE prim {:?}"), + _ => panic!("ICE prim"), } } @@ -141,19 +141,20 @@ impl ValueTypePair { } pub fn indexable(&self, module: &AatbeModule) -> Option { - match &self { + todo!() + /*match &self { ValueTypePair(val, TypeKind::Primitive(prim)) => match prim { - prim @ (PrimitiveType::Str | PrimitiveType::Array { .. }) => { + prim @ (Type::Str | Type::Array { .. }) => { Some((*val, prim).into()) } - PrimitiveType::Slice { .. } => { + Type::Slice { .. } => { Some((module.llvm_builder_ref().build_extract_value(*val, 0), prim).into()) } - PrimitiveType::Pointer(box ty) => Some((*val, ty).into()), + Type::Pointer(box ty) => Some((*val, ty).into()), _ => None, }, _ => None, - } + }*/ } } diff --git a/comp-be/src/codegen/module.rs b/comp-be/src/codegen/module.rs index 6508900..529c495 100644 --- a/comp-be/src/codegen/module.rs +++ b/comp-be/src/codegen/module.rs @@ -9,13 +9,11 @@ use std::{ use crate::{ codegen::{ - codegen_binary, comp_unit::CompilationUnit, - expr::const_expr::{const_atom, fold_constant}, mangle_v1::NameMangler, unit::{ alloc_variable, declare_and_compile_function, declare_function, init_record, - store_value, Slot, + store_value, CompilerUnit, Slot, }, CompileError, Scope, ValueTypePair, }, @@ -29,12 +27,12 @@ use crate::{ }; use super::{ - builder::{cast, core}, + builder::{base, cast}, unit::function::{find_func, FuncTyMap}, }; use parser::{ ast, - ast::{AtomKind, Expression, FunctionType, PrimitiveType, AST}, + ast::{AtomKind, Expression, FunctionType, Type, AST}, }; pub type InternalFunc = dyn Fn(&mut AatbeModule, &Vec, String) -> Option; @@ -44,8 +42,6 @@ pub struct AatbeModule { llvm_context: Context, llvm_module: Module, name: String, - scope_stack: Vec, - typectx: TypeContext, compile_errors: Vec, record_templates: HashMap, function_templates: HashMap, @@ -59,7 +55,7 @@ impl AatbeModule { LLVM::initialize(); let llvm_context = Context::new(); - let llvm_module = llvm_context.create_module(name.as_ref()); + let llvm_module = llvm_context.create_module(&name); let mut internal_functions: HashMap> = HashMap::new(); internal_functions.insert(String::from("len"), Rc::new(AatbeModule::internal_len)); @@ -69,11 +65,9 @@ impl AatbeModule { compilation_units.insert(name.clone(), base_cu); Self { - llvm_context, llvm_module, + llvm_context, name, - scope_stack: vec![], - typectx: TypeContext::new(), compile_errors: vec![], record_templates: HashMap::new(), function_templates: HashMap::new(), @@ -85,10 +79,6 @@ impl AatbeModule { pub fn compile(&mut self) { let base_cu = self.compilation_units.get(&self.name).unwrap(); - self.scope_stack.push(Scope::with_builder_and_fdir( - Builder::new_in_context(self.llvm_context.as_ref()), - base_cu.path().clone(), - )); let main_ast = self .compilation_units .get(&self.name.clone()) @@ -96,13 +86,23 @@ impl AatbeModule { .ast() .clone(); - self.decl_pass(&main_ast); - self.codegen_pass(&main_ast); - - self.exit_scope(); - } + let root_builder = Builder::new_in_context(self.llvm_context.as_ref()); - pub fn parse_import(&mut self, module: &String) -> io::Result { + CompilerUnit::new( + base_cu.path().clone(), + &self.llvm_context, + &self.llvm_module, + ) + .in_root_scope(|root_module| { + root_module.decl(&root_builder, &main_ast); + //root_module.generics(&root_builder, &main_ast); + //root_module.decl(&root_builder, &main_ast); + //root_module.codegen(&root_builder, &main_ast); + root_module.codegen(&root_builder, &main_ast); + }); + } + + /*pub fn parse_import(&mut self, module: &String) -> io::Result { let mut path = self.fdir().with_file_name(module); path.set_extension("aat"); if !path.exists() { @@ -115,24 +115,11 @@ impl AatbeModule { } CompilationUnit::new(path) - } + }*/ - pub fn decl_expr(&mut self, expr: &Expression) { - match expr { - Expression::Function { type_names, .. } if type_names.len() == 0 => { - declare_function(self, expr) - } - Expression::Function { name, .. } => { - if !self.function_templates.contains_key(name) { - self.function_templates.insert(name.clone(), expr.clone()); - } - } - _ => panic!("Top level {:?} unsupported", expr), - } - } + pub fn decl_pass(&mut self, root_module: &mut CompilerUnit) { - pub fn decl_pass(&mut self, ast: &AST) { - match ast { + /*match ast { AST::Constant { .. } | AST::Global { .. } => {} AST::Record(name, None, types) => { let rec = Record::new(self, name, types); @@ -184,13 +171,17 @@ impl AatbeModule { AST::Typedef { type_names: None, .. } => self.gen_newtype_ctors(&ast), + AST::Module(name, ast) => { + self.root_module.push(name, ModuleUnit::new(ast.clone())); + } _ => panic!("cannot decl {:?}", ast), - } + }*/ } #[allow(unused_unsafe)] pub fn gen_variants(&mut self, typedef: &AST) { - match typedef { + todo!() + /*match typedef { AST::Typedef { name, type_names: None, @@ -200,7 +191,7 @@ impl AatbeModule { let smallest = variants.iter().map(|vari| vari.smallest()).min().unwrap(); let size = max_size / smallest; - let smallest_ty = PrimitiveType::UInt(smallest.into()); + let smallest_ty = Type::UInt(smallest.into()); let td_struct = self.llvm_context_ref().StructTypeNamed(name.as_ref()); td_struct.set_body( @@ -316,7 +307,7 @@ impl AatbeModule { }); } Some( - (variant, PrimitiveType::VariantType(name.clone())) + (variant, Type::VariantType(name.clone())) .into(), ) } else { @@ -329,11 +320,12 @@ impl AatbeModule { }); } _ => unreachable!(), - } + }*/ } pub fn gen_newtype_ctors(&mut self, typedef: &AST) { - match typedef { + todo!() + /*match typedef { AST::Typedef { name, type_names: None, @@ -363,7 +355,7 @@ impl AatbeModule { val, module.llvm_builder_ref().build_struct_gep(res, 0), ); - Some((res, PrimitiveType::Newtype(name.clone())).into()) + Some((res, Type::Newtype(name.clone())).into()) }), ); self.typectx.push_type( @@ -381,10 +373,10 @@ impl AatbeModule { } } _ => unreachable!(), - } + }*/ } - pub fn get_interior_pointer(&self, parts: Vec) -> Option { + /*pub fn get_interior_pointer(&self, parts: Vec) -> Option { match parts.as_slice() { [field, access @ ..] => { let agg_bind = self.get_var(&field)?; @@ -400,7 +392,7 @@ impl AatbeModule { } [] => unreachable!(), } - } + }*/ pub fn has_ret(&self, expr: &Expression) -> bool { match expr { @@ -413,7 +405,8 @@ impl AatbeModule { } pub fn codegen_expr(&mut self, expr: &Expression) -> Option { - match expr { + todo!() + /*match expr { Expression::Ret(box _value) => { let val = self.codegen_expr(_value)?; @@ -423,12 +416,12 @@ impl AatbeModule { .ret_ty() .clone(); - if let PrimitiveType::VariantType(ty) = val.prim() { + if let Type::VariantType(ty) = val.prim() { let parent_ty = self .typectx_ref() .get_parent_for_variant(ty) .expect("ICE: Variant without parent"); - if let PrimitiveType::TypeRef(name) = &func_ret { + if let Type::TypeRef(name) = &func_ret { if &parent_ty.type_name == name { Some(core::ret( self, @@ -458,7 +451,7 @@ impl AatbeModule { Some(core::ret(self, val)) } } - Expression::RecordInit { + /*Expression::RecordInit { record, types, values, @@ -500,11 +493,11 @@ impl AatbeModule { Some( ( self.llvm_builder_ref().build_load(rec), - PrimitiveType::TypeRef(record.clone()), + Type::TypeRef(record.clone()), ) .into(), ) - } + }*/ Expression::Assign { lval, value } => match value { box Expression::RecordInit { record, @@ -521,44 +514,7 @@ impl AatbeModule { ), _ => store_value(self, lval, value), }, - Expression::Decl { - ty: PrimitiveType::NamedType { name, ty: Some(ty) }, - value: _, - exterior_bind: _, - } => { - alloc_variable(self, expr); - - Some( - ( - self.get_var(name).expect("Compiler crapped out.").into(), - *ty.clone(), - ) - .into(), - ) - } - Expression::Decl { - ty: PrimitiveType::NamedType { name, ty: None }, - value, - exterior_bind: _, - } => { - if value.is_none() { - self.add_error(CompileError::ExpectedValue { name: name.clone() }); - return None; - } - - alloc_variable(self, expr).and_then(|ty| { - Some( - ( - self.get_var(name).expect("Compiler crapped out.").into(), - ty, - ) - .into(), - ) - }) - } Expression::Loop { .. } => self.codegen_basic_loop(expr), - Expression::If { .. } => self.codegen_if(expr), - Expression::Call { .. } => self.codegen_call(expr), Expression::Binary(lhs, op, rhs) => match codegen_binary(self, op, lhs, rhs) { Ok(val) => Some(val), Err(_) => { @@ -570,14 +526,6 @@ impl AatbeModule { None } }, - Expression::Function { ty, type_names, .. } if type_names.len() == 0 => match ty { - FunctionType { - ret_ty: _, - params: _, - ext: true, - } => None, - _ => declare_and_compile_function(self, expr), - }, Expression::Function { .. } => None, Expression::Block(nodes) if nodes.len() == 0 => None, Expression::Block(nodes) => { @@ -592,20 +540,20 @@ impl AatbeModule { ret } - Expression::Atom(atom) => self.codegen_atom(atom), - _ => panic!(format!("ICE: codegen_expr {:?}", expr)), - } + _ => panic!("ICE: codegen_expr {:?}", expr), + }*/ } - pub fn codegen_pass(&mut self, ast: &AST) -> Option { - match ast { + pub fn codegen_pass(&mut self, root_module: &mut CompilerUnit) -> Option { + todo!() + /*match ast { AST::Constant { - ty: PrimitiveType::NamedType { name, ty: _ }, + ty: Type::NamedType { name, ty: _ }, export, value: _, } | AST::Global { - ty: PrimitiveType::NamedType { name, ty: _ }, + ty: Type::NamedType { name, ty: _ }, export, value: _, } => { @@ -626,11 +574,16 @@ impl AatbeModule { AST::Import(..) => None, AST::Record(..) => None, AST::Typedef { .. } => None, + AST::Module(name, _) => self + .root_module + .get_mut(name) + .expect(format!("ICE: Module codegen but none found").as_str()) + .codegen(), _ => panic!("cannot codegen {:?}", ast), - } + }*/ } - pub fn start_scope(&mut self) { + /*pub fn start_scope(&mut self) { self.scope_stack.push(Scope::new()); } @@ -638,14 +591,6 @@ impl AatbeModule { self.scope_stack.push(Scope::with_name(name)); } - pub fn start_scope_with_function(&mut self, func: (String, FunctionType), builder: Builder) { - self.scope_stack.push(Scope::with_function(func, builder)); - } - - pub fn exit_scope(&mut self) { - self.scope_stack.pop(); - } - pub fn get_in_scope(&self, name: &String) -> Option<&Slot> { for scope in self.scope_stack.iter().rev() { if let Some(sym) = scope.find_symbol(name) { @@ -682,19 +627,7 @@ impl AatbeModule { .add_symbol(name, unit); } - pub fn add_function(&mut self, name: &String, func: Func) { - self.scope_stack - .last_mut() - .expect("Compiler broke. Scope stack is corrupted.") - .add_function(name, func); - } - pub fn export_function(&mut self, name: &String, func: Func) { - self.scope_stack - .first_mut() - .expect("Compiler broke. Scope stack is corrupted.") - .add_function(name, func); - } pub fn export_global(&mut self, name: &String, unit: Slot) { self.scope_stack @@ -703,33 +636,15 @@ impl AatbeModule { .add_symbol(name, unit); } - pub fn get_func_group(&self, name: &String) -> Option<&FuncTyMap> { - for scope in self.scope_stack.iter().rev() { - if let Some(func) = scope.func_by_name(name) { - return Some(func); - } - } - - None - } - - pub fn get_func(&self, func: (String, FunctionType)) -> Option<&Func> { - for scope in self.scope_stack.iter().rev() { - if let Some(group) = scope.func_by_name(&func.0) { - return find_func(group, &func.1); - } - } - - None - } + */ pub fn propagate_generic_body( body: Box, - type_map: HashMap<&String, PrimitiveType>, + type_map: HashMap<&String, Type>, ) -> Box { box match body { box Expression::Atom(atom) => Expression::Atom(match atom { - AtomKind::Cast(box atom, PrimitiveType::TypeRef(ty_ref)) => { + AtomKind::Cast(box atom, Type::TypeRef(ty_ref)) => { AtomKind::Cast(box atom, type_map[&ty_ref].clone()) } AtomKind::Parenthesized(expr) => AtomKind::Parenthesized( @@ -745,8 +660,8 @@ impl AatbeModule { &mut self, template: &String, name: &String, - types: Vec, - ) -> Option> { + types: Vec, + ) -> Option> { self.get_params(name).or_else(|| { self.propagate_types_in_function(template, types.clone()) .and_then(|ty| match self.function_templates.get(template) { @@ -774,7 +689,7 @@ impl AatbeModule { params .iter() .map(|p| match p { - PrimitiveType::NamedType { + Type::NamedType { ty: Some(box ty), .. } => ty.clone(), _ => p.clone(), @@ -791,7 +706,7 @@ impl AatbeModule { }) }*/ - pub fn is_extern(&self, func: (String, FunctionType)) -> bool { + /*pub fn is_extern(&self, func: (String, FunctionType)) -> bool { let val_ref = self.get_func(func); if let Some(func) = val_ref { func.is_extern() @@ -812,12 +727,12 @@ impl AatbeModule { Some(Slot::FunctionArgument(_arg, _)) => val_ref, _ => None, } - } + }*/ - pub fn propagate_types_in_function( + /*pub fn propagate_types_in_function( &mut self, name: &String, - types: Vec, + types: Vec, ) -> Option { if types.len() == 0 { return None; @@ -854,11 +769,11 @@ impl AatbeModule { let type_map = type_names.iter().zip(types).collect::>(); let ret_ty = match ret_ty { - box PrimitiveType::TypeRef(ty) => { + box Type::TypeRef(ty) => { if type_map.contains_key(ty) { box type_map[ty].clone() } else { - box PrimitiveType::TypeRef(ty.clone()) + box Type::TypeRef(ty.clone()) } } _ => ret_ty.clone(), @@ -866,26 +781,26 @@ impl AatbeModule { let params = params .iter() .map(|param| match param { - PrimitiveType::TypeRef(ty) => { + Type::TypeRef(ty) => { if type_map.contains_key(ty) { type_map[ty].clone() } else { - PrimitiveType::TypeRef(ty.clone()) + Type::TypeRef(ty.clone()) } } - PrimitiveType::NamedType { + Type::NamedType { name, - ty: Some(box PrimitiveType::TypeRef(ty)), + ty: Some(box Type::TypeRef(ty)), } => { if type_map.contains_key(ty) { - PrimitiveType::NamedType { + Type::NamedType { name: name.clone(), ty: Some(box type_map[ty].clone()), } } else { - PrimitiveType::NamedType { + Type::NamedType { name: name.clone(), - ty: Some(box PrimitiveType::TypeRef(ty.clone())), + ty: Some(box Type::TypeRef(ty.clone())), } } } @@ -923,10 +838,11 @@ impl AatbeModule { } else { None } - } + }*/ - pub fn propagate_types_in_record(&mut self, name: &String, types: Vec) { - let rec = format!( + pub fn propagate_types_in_record(&mut self, name: &String, types: Vec) { + todo!() + /*let rec = format!( "{}[{}]", name, types @@ -949,10 +865,10 @@ impl AatbeModule { let fields = fields .iter() .map(|field| { - if let PrimitiveType::NamedType { name, ty } = field { - if let Some(box PrimitiveType::TypeRef(ty_name)) = ty { + if let Type::NamedType { name, ty } = field { + if let Some(box Type::TypeRef(ty_name)) = ty { if type_map.contains_key(ty_name) { - PrimitiveType::NamedType { + Type::NamedType { name: name.clone(), ty: Some(box type_map[ty_name].clone()), } @@ -973,10 +889,10 @@ impl AatbeModule { .get_record(&rec) .unwrap() .set_body(self, &fields); - } + }*/ } - pub fn fdir(&self) -> PathBuf { + /*pub fn fdir(&self) -> PathBuf { for scope in self.scope_stack.iter().rev() { if let Some(fdir) = scope.fdir() { return fdir.clone(); @@ -985,29 +901,24 @@ impl AatbeModule { unreachable!(); } - pub fn llvm_builder_ref(&self) -> &Builder { - for scope in self.scope_stack.iter().rev() { - if let Some(builder) = scope.builder() { - return builder; - } - } - unreachable!(); - } + */ pub fn llvm_module_ref(&self) -> &Module { &self.llvm_module } pub fn llvm_context_ref(&self) -> &Context { - &self.llvm_context + todo!() //&self.llvm_context } pub fn typectx_ref(&self) -> &TypeContext { - &self.typectx + todo!() + //&self.typectx } pub fn typectx_ref_mut(&mut self) -> &mut TypeContext { - &mut self.typectx + todo!() + //&mut self.typectx } pub fn add_error(&mut self, error: CompileError) { diff --git a/comp-be/src/codegen/scope.rs b/comp-be/src/codegen/scope.rs index 7b9a6d2..41f01f8 100644 --- a/comp-be/src/codegen/scope.rs +++ b/comp-be/src/codegen/scope.rs @@ -1,14 +1,11 @@ -use crate::codegen::{ - unit::{ - function::{find_func, Func, FuncTyMap, FunctionMap}, - Slot, - }, - AatbeModule, +use crate::codegen::unit::{ + function::{find_func, Func, FuncTyMap, FunctionMap}, + CompilerUnit, Slot, }; -use std::{collections::HashMap, path::PathBuf}; +use std::{cell::RefCell, collections::HashMap, path::PathBuf, rc::Rc}; use llvm_sys_wrapper::{Builder, LLVMBasicBlockRef}; -use parser::ast::FunctionType; +use parser::ast::{Expression, FunctionType}; #[derive(Debug)] pub struct Scope { @@ -16,8 +13,8 @@ pub struct Scope { functions: FunctionMap, name: String, function: Option<(String, FunctionType)>, - builder: Option, fdir: Option, + function_templates: HashMap, } impl Scope { @@ -27,8 +24,8 @@ impl Scope { functions: HashMap::new(), name: String::default(), function: None, - builder: None, fdir: None, + function_templates: HashMap::new(), } } pub fn with_name(name: &String) -> Self { @@ -37,8 +34,8 @@ impl Scope { functions: HashMap::new(), name: name.clone(), function: None, - builder: None, fdir: None, + function_templates: HashMap::new(), } } pub fn with_builder(builder: Builder) -> Self { @@ -47,41 +44,59 @@ impl Scope { functions: HashMap::new(), name: String::default(), function: None, - builder: Some(builder), fdir: None, + function_templates: HashMap::new(), } } - pub fn with_builder_and_fdir(builder: Builder, fdir: PathBuf) -> Self { + pub fn with_fdir

(fdir: P) -> Self + where + P: Into, + { Self { refs: HashMap::new(), functions: HashMap::new(), name: String::default(), function: None, - builder: Some(builder), - fdir: Some(fdir), + fdir: Some(fdir.into()), + function_templates: HashMap::new(), } } - pub fn with_function(func: (String, FunctionType), builder: Builder) -> Self { + pub fn with_function(func: (String, FunctionType)) -> Self { Self { refs: HashMap::new(), functions: HashMap::new(), name: func.0.clone(), function: Some(func), - builder: Some(builder), fdir: None, + function_templates: HashMap::new(), } } - pub fn func_by_name(&self, name: &String) -> Option<&FuncTyMap> { - self.functions.get(name) + pub fn func_by_name(&self, name: &String) -> Option> { + self.functions.get(name).cloned() + } + + pub fn get_template(&self, name: &String) -> Option { + self.function_templates.get(name).map(|expr| expr.clone()) + } + + pub fn add_template(&mut self, name: String, func: Expression) { + if self.function_templates.insert(name, func).is_some() { + // TODO: Error + panic!("ERROR"); + } } pub fn add_function(&mut self, name: &String, func: Func) { if !self.functions.contains_key(name) { - self.functions.insert(name.clone(), vec![]); + self.functions.insert(name.clone(), RefCell::new(vec![])); } - self.functions.get_mut(name).unwrap().push(func); + self.functions + .get_mut(name) + .unwrap() + .get_mut() + .push(Rc::new(func)); } pub fn find_symbol(&self, name: &String) -> Option<&Slot> { @@ -93,20 +108,23 @@ impl Scope { pub fn function(&self) -> Option<(String, FunctionType)> { self.function.clone() } - pub fn builder(&self) -> Option<&Builder> { - self.builder.as_ref() - } pub fn fdir(&self) -> Option { self.fdir.clone() } - pub fn bb(&self, module: &AatbeModule, name: &String) -> Option { - let func = self.function.as_ref()?; + pub fn name(&self) -> String { + self.name.clone() + } + + pub fn bb(&self, module: &CompilerUnit, name: &str) -> Option { + let (_, ty) = self.function.as_ref()?; Some( - find_func(module.get_func_group(&func.0)?, &func.1) + find_func(module.get_func_group(&module.get_prefix().join("::"))?, &ty) .unwrap() - .append_basic_block(name.as_ref()), + .upgrade() + .expect("ICE") + .append_basic_block(name), ) } } diff --git a/comp-be/src/codegen/unit/cg/assign.rs b/comp-be/src/codegen/unit/cg/assign.rs new file mode 100644 index 0000000..33fa065 --- /dev/null +++ b/comp-be/src/codegen/unit/cg/assign.rs @@ -0,0 +1,20 @@ +use guard::guard; +use parser::ast::Expression; + +use crate::codegen::{ + unit::{store_value, CompilerContext}, + ValueTypePair, +}; + +pub fn cg(expr: &Expression, ctx: &CompilerContext) -> Option { + guard!(let Expression::Assign { lval, value } = expr else { unreachable!() }); + + match value { + box Expression::RecordInit { + record, + types, + values, + } => todo!(), + _ => store_value(ctx, lval, value), + } +} diff --git a/comp-be/src/codegen/unit/cg/atom.rs b/comp-be/src/codegen/unit/cg/atom.rs new file mode 100644 index 0000000..094d19d --- /dev/null +++ b/comp-be/src/codegen/unit/cg/atom.rs @@ -0,0 +1,44 @@ +use parser::ast::{AtomKind, Boolean, Type}; + +use guard::guard; + +use crate::{ + codegen::{ + builder::value, + expr::const_atom, + unit::{ + cg::{consts, expr}, + CompilerContext, Query, QueryResponse, + }, + ValueTypePair, + }, + fmt::AatbeFmt, +}; + +pub fn cg(atom: &AtomKind, ctx: &CompilerContext) -> Option { + ctx.trace(format!("Atom {}", atom.fmt())); + match atom { + AtomKind::Parenthesized(expr) => expr::cg(expr, ctx), + AtomKind::Unit => Some(value::unit(ctx)), + AtomKind::Bool(Boolean::True) => Some(value::t(ctx)), + AtomKind::Bool(Boolean::False) => Some(value::f(ctx)), + atom + @ + (AtomKind::Integer(..) + | AtomKind::Floating(..) + | AtomKind::Unary(_, box AtomKind::Integer(..))) => consts::numeric::cg(atom, ctx), + atom @ (AtomKind::StringLiteral(..) | AtomKind::CharLiteral(..)) => const_atom(ctx, atom), + AtomKind::Ident(name) => { + guard!(let QueryResponse::Slot(slot) = ctx.query(Query::Slot(name)) else { unreachable!(); }); + let slot = slot?; + match slot.var_ty().clone() { + ty @ Type::Newtype(_) | ty @ Type::VariantType(_) => { + let val: ValueTypePair = slot.into(); + Some((*val, ty).into()) + } + ty => Some((slot.load_var(ctx.llvm_builder), ty).into()), + } + } + _ => todo!("{:?}", atom), + } +} diff --git a/comp-be/src/codegen/unit/cg/binary/bool.rs b/comp-be/src/codegen/unit/cg/binary/bool.rs new file mode 100644 index 0000000..5ebc6db --- /dev/null +++ b/comp-be/src/codegen/unit/cg/binary/bool.rs @@ -0,0 +1,21 @@ +use crate::codegen::{ + unit::{ + cg::binary::{comp, eqne}, + CompilerContext, + }, + ValueTypePair, +}; +use llvm_sys_wrapper::LLVMValueRef; + +pub fn cg( + lhs: LLVMValueRef, + op: &String, + rhs: LLVMValueRef, + ctx: &CompilerContext, +) -> Option { + match op.as_str() { + "==" | "!=" => Some(eqne::cg(lhs, op, rhs, ctx)), + "&&" | "||" => Some(comp::cg(lhs, op, rhs, ctx)), + _ => None, + } +} diff --git a/comp-be/src/codegen/unit/cg/binary/comp.rs b/comp-be/src/codegen/unit/cg/binary/comp.rs new file mode 100644 index 0000000..01a4389 --- /dev/null +++ b/comp-be/src/codegen/unit/cg/binary/comp.rs @@ -0,0 +1,20 @@ +use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair}; +use llvm_sys_wrapper::LLVMValueRef; +use parser::ast::Type; + +pub fn cg( + lhs: LLVMValueRef, + op: &String, + rhs: LLVMValueRef, + ctx: &CompilerContext, +) -> ValueTypePair { + ( + match op.as_str() { + "&&" => ctx.llvm_builder.build_and(lhs, rhs), + "||" => ctx.llvm_builder.build_or(lhs, rhs), + _ => panic!("ICE codegen_eq_ne unhandled op {}", op), + }, + Type::Bool, + ) + .into() +} diff --git a/comp-be/src/codegen/unit/cg/binary/eqne.rs b/comp-be/src/codegen/unit/cg/binary/eqne.rs new file mode 100644 index 0000000..51ecc98 --- /dev/null +++ b/comp-be/src/codegen/unit/cg/binary/eqne.rs @@ -0,0 +1,20 @@ +use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair}; +use llvm_sys_wrapper::LLVMValueRef; +use parser::ast::Type; + +pub fn cg( + lhs: LLVMValueRef, + op: &String, + rhs: LLVMValueRef, + ctx: &CompilerContext, +) -> ValueTypePair { + ( + match op.as_str() { + "==" => ctx.llvm_builder.build_icmp_eq(lhs, rhs), + "!=" => ctx.llvm_builder.build_icmp_ne(lhs, rhs), + _ => panic!("ICE codegen_eq_ne unhandled op {}", op), + }, + Type::Bool, + ) + .into() +} diff --git a/comp-be/src/codegen/unit/cg/binary/float/arith.rs b/comp-be/src/codegen/unit/cg/binary/float/arith.rs new file mode 100644 index 0000000..95be5db --- /dev/null +++ b/comp-be/src/codegen/unit/cg/binary/float/arith.rs @@ -0,0 +1,24 @@ +use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair}; +use llvm_sys_wrapper::LLVMValueRef; +use parser::ast::{FloatSize, Type}; + +pub fn cg( + lhs: LLVMValueRef, + op: &String, + rhs: LLVMValueRef, + float_size: FloatSize, + ctx: &CompilerContext, +) -> ValueTypePair { + ( + match op.as_str() { + "+" => ctx.llvm_builder.build_fadd(lhs, rhs), + "-" => ctx.llvm_builder.build_fsub(lhs, rhs), + "*" => ctx.llvm_builder.build_fmul(lhs, rhs), + "/" => ctx.llvm_builder.build_fdiv(lhs, rhs), + "%" => ctx.llvm_builder.build_frem(lhs, rhs), + _ => panic!("ICE codegen_float_ops unhandled op {}", op), + }, + Type::Float(float_size), + ) + .into() +} diff --git a/comp-be/src/codegen/unit/cg/binary/float/cmp.rs b/comp-be/src/codegen/unit/cg/binary/float/cmp.rs new file mode 100644 index 0000000..d66f726 --- /dev/null +++ b/comp-be/src/codegen/unit/cg/binary/float/cmp.rs @@ -0,0 +1,20 @@ +use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair}; +use llvm_sys_wrapper::LLVMValueRef; +use parser::ast::Type; + +pub fn cg( + lhs: LLVMValueRef, + op: &String, + rhs: LLVMValueRef, + ctx: &CompilerContext, +) -> ValueTypePair { + ( + match op.as_str() { + "==" => ctx.llvm_builder.build_fcmp_ueq(lhs, rhs), + "!=" => ctx.llvm_builder.build_fcmp_une(lhs, rhs), + _ => panic!("ICE codegen_eq_ne_float unhandled op {}", op), + }, + Type::Bool, + ) + .into() +} diff --git a/comp-be/src/codegen/unit/cg/binary/float/eqne.rs b/comp-be/src/codegen/unit/cg/binary/float/eqne.rs new file mode 100644 index 0000000..fdb3eed --- /dev/null +++ b/comp-be/src/codegen/unit/cg/binary/float/eqne.rs @@ -0,0 +1,22 @@ +use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair}; +use llvm_sys_wrapper::LLVMValueRef; +use parser::ast::Type; + +pub fn cg( + lhs: LLVMValueRef, + op: &String, + rhs: LLVMValueRef, + ctx: &CompilerContext, +) -> ValueTypePair { + ( + match op.as_str() { + "<" => ctx.llvm_builder.build_fcmp_ult(lhs, rhs), + ">" => ctx.llvm_builder.build_fcmp_ugt(lhs, rhs), + "<=" => ctx.llvm_builder.build_fcmp_ule(lhs, rhs), + ">=" => ctx.llvm_builder.build_fcmp_uge(lhs, rhs), + _ => panic!("ICE codegen_compare_float unhandled op {}", op), + }, + Type::Bool, + ) + .into() +} diff --git a/comp-be/src/codegen/unit/cg/binary/float/mod.rs b/comp-be/src/codegen/unit/cg/binary/float/mod.rs new file mode 100644 index 0000000..5f79704 --- /dev/null +++ b/comp-be/src/codegen/unit/cg/binary/float/mod.rs @@ -0,0 +1,22 @@ +mod arith; +mod cmp; +mod eqne; + +use crate::codegen::{unit::CompilerContext, ValueTypePair}; +use llvm_sys_wrapper::LLVMValueRef; +use parser::ast::FloatSize; + +pub fn cg( + lhs: LLVMValueRef, + op: &String, + rhs: LLVMValueRef, + float_size: FloatSize, + ctx: &CompilerContext, +) -> Option { + match op.as_str() { + "+" | "-" | "*" | "/" | "%" => Some(arith::cg(lhs, op, rhs, float_size, ctx)), + ">" | "<" | ">=" | "<=" => Some(cmp::cg(lhs, op, rhs, ctx)), + "==" | "!=" => Some(eqne::cg(lhs, op, rhs, ctx)), + _ => None, + } +} diff --git a/comp-be/src/codegen/unit/cg/binary/int/arith.rs b/comp-be/src/codegen/unit/cg/binary/int/arith.rs new file mode 100644 index 0000000..fcd1aae --- /dev/null +++ b/comp-be/src/codegen/unit/cg/binary/int/arith.rs @@ -0,0 +1,24 @@ +use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair}; +use llvm_sys_wrapper::LLVMValueRef; +use parser::ast::{IntSize, Type}; + +pub fn cg( + lhs: LLVMValueRef, + op: &String, + rhs: LLVMValueRef, + int_size: IntSize, + ctx: &CompilerContext, +) -> ValueTypePair { + ( + match op.as_str() { + "+" => ctx.llvm_builder.build_add(lhs, rhs), + "-" => ctx.llvm_builder.build_sub(lhs, rhs), + "*" => ctx.llvm_builder.build_mul(lhs, rhs), + "/" => ctx.llvm_builder.build_sdiv(lhs, rhs), + "%" => ctx.llvm_builder.build_srem(lhs, rhs), + _ => panic!("ICE codegen_unsigned_ops unhandled op {}", op), + }, + Type::Int(int_size), + ) + .into() +} diff --git a/comp-be/src/codegen/unit/cg/binary/int/cmp.rs b/comp-be/src/codegen/unit/cg/binary/int/cmp.rs new file mode 100644 index 0000000..b1d550d --- /dev/null +++ b/comp-be/src/codegen/unit/cg/binary/int/cmp.rs @@ -0,0 +1,22 @@ +use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair}; +use llvm_sys_wrapper::LLVMValueRef; +use parser::ast::Type; + +pub fn cg( + lhs: LLVMValueRef, + op: &String, + rhs: LLVMValueRef, + ctx: &CompilerContext, +) -> ValueTypePair { + ( + match op.as_str() { + "<" => ctx.llvm_builder.build_icmp_slt(lhs, rhs), + ">" => ctx.llvm_builder.build_icmp_sgt(lhs, rhs), + "<=" => ctx.llvm_builder.build_icmp_sle(lhs, rhs), + ">=" => ctx.llvm_builder.build_icmp_sge(lhs, rhs), + _ => panic!("ICE codegen_compare_signed unhandled op {}", op), + }, + Type::Bool, + ) + .into() +} diff --git a/comp-be/src/codegen/unit/cg/binary/int/mod.rs b/comp-be/src/codegen/unit/cg/binary/int/mod.rs new file mode 100644 index 0000000..d061784 --- /dev/null +++ b/comp-be/src/codegen/unit/cg/binary/int/mod.rs @@ -0,0 +1,24 @@ +mod arith; +mod cmp; + +use crate::codegen::{ + unit::{cg::binary::eqne, CompilerContext}, + ValueTypePair, +}; +use llvm_sys_wrapper::LLVMValueRef; +use parser::ast::IntSize; + +pub fn cg( + lhs: LLVMValueRef, + op: &String, + rhs: LLVMValueRef, + int_size: IntSize, + ctx: &CompilerContext, +) -> Option { + match op.as_str() { + "+" | "-" | "*" | "/" | "%" => Some(arith::cg(lhs, op, rhs, int_size, ctx)), + ">" | "<" | ">=" | "<=" => Some(cmp::cg(lhs, op, rhs, ctx)), + "==" | "!=" => Some(eqne::cg(lhs, op, rhs, ctx)), + _ => None, + } +} diff --git a/comp-be/src/codegen/unit/cg/binary/mod.rs b/comp-be/src/codegen/unit/cg/binary/mod.rs new file mode 100644 index 0000000..ceeef7a --- /dev/null +++ b/comp-be/src/codegen/unit/cg/binary/mod.rs @@ -0,0 +1,88 @@ +mod bool; +mod comp; +mod eqne; +mod float; +mod int; +mod uint; + +use parser::ast::{Expression, IntSize, Type}; + +use guard::guard; + +use crate::{ + codegen::{ + unit::{cg::expr, CompilerContext}, + CompileError, GenRes, + }, + fmt::AatbeFmt, +}; + +pub fn cg(expr: &Expression, ctx: &CompilerContext) -> GenRes { + guard!(let Expression::Binary(box lh, op, box rh) = expr else { unreachable!() }); + + let lhs = expr::cg(lh, ctx).ok_or(CompileError::Handled)?; + let rhs = expr::cg(rh, ctx).ok_or(CompileError::Handled)?; + + match (lhs.prim(), rhs.prim()) { + (Type::Bool, Type::Bool) => { + ctx.trace(format!("Binary {} {} {}", lh.fmt(), op, rh.fmt())); + match bool::cg(*lhs, op, *rhs, ctx) { + Some(res) => Ok(res), + None => Err(CompileError::OpMismatch { + op: op.clone(), + types: (lhs.prim().fmt(), rhs.prim().fmt()), + values: (lh.fmt(), rh.fmt()), + }), + } + } + (Type::Char, Type::Char) => { + ctx.trace(format!("Binary {} {} {}", lh.fmt(), op, rh.fmt())); + match uint::cg(*lhs, op, *rhs, IntSize::Bits8, ctx) { + Some(res) => Ok(res), + None => Err(CompileError::OpMismatch { + op: op.clone(), + types: (lhs.prim().fmt(), rhs.prim().fmt()), + values: (lh.fmt(), rh.fmt()), + }), + } + } + (Type::UInt(lsz), Type::UInt(rsz)) if lsz == rsz => { + ctx.trace(format!("Binary {} {} {}", lh.fmt(), op, rh.fmt())); + match uint::cg(*lhs, op, *rhs, lsz.clone(), ctx) { + Some(res) => Ok(res), + None => Err(CompileError::OpMismatch { + op: op.clone(), + types: (lhs.prim().fmt(), rhs.prim().fmt()), + values: (lh.fmt(), rh.fmt()), + }), + } + } + (Type::Int(lsz), Type::Int(rsz)) if lsz == rsz => { + ctx.trace(format!("Binary {} {} {}", lh.fmt(), op, rh.fmt())); + match int::cg(*lhs, op, *rhs, lsz.clone(), ctx) { + Some(res) => Ok(res), + None => Err(CompileError::OpMismatch { + op: op.clone(), + types: (lhs.prim().fmt(), rhs.prim().fmt()), + values: (lh.fmt(), rh.fmt()), + }), + } + } + (Type::Float(lsz), Type::Float(rsz)) if lsz == rsz => { + ctx.trace(format!("Binary {} {} {}", lh.fmt(), op, rh.fmt())); + match float::cg(*lhs, op, *rhs, lsz.clone(), ctx) { + Some(res) => Ok(res), + None => Err(CompileError::OpMismatch { + op: op.clone(), + types: (lhs.prim().fmt(), rhs.prim().fmt()), + values: (lh.fmt(), rh.fmt()), + }), + } + } + _ => Err(CompileError::BinaryMismatch { + op: op.clone(), + types: (lhs.prim().fmt(), rhs.prim().fmt()), + values: (lh.fmt(), rh.fmt()), + }), + } +} diff --git a/comp-be/src/codegen/unit/cg/binary/uint/arith.rs b/comp-be/src/codegen/unit/cg/binary/uint/arith.rs new file mode 100644 index 0000000..1873091 --- /dev/null +++ b/comp-be/src/codegen/unit/cg/binary/uint/arith.rs @@ -0,0 +1,24 @@ +use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair}; +use llvm_sys_wrapper::LLVMValueRef; +use parser::ast::{IntSize, Type}; + +pub fn cg( + lhs: LLVMValueRef, + op: &String, + rhs: LLVMValueRef, + ty: IntSize, + ctx: &CompilerContext, +) -> ValueTypePair { + ( + match op.as_str() { + "+" => ctx.llvm_builder.build_add(lhs, rhs), + "-" => ctx.llvm_builder.build_sub(lhs, rhs), + "*" => ctx.llvm_builder.build_mul(lhs, rhs), + "/" => ctx.llvm_builder.build_udiv(lhs, rhs), + "%" => ctx.llvm_builder.build_urem(lhs, rhs), + _ => panic!("ICE codegen_unsigned_ops unhandled op {}", op), + }, + Type::UInt(ty), + ) + .into() +} diff --git a/comp-be/src/codegen/unit/cg/binary/uint/cmp.rs b/comp-be/src/codegen/unit/cg/binary/uint/cmp.rs new file mode 100644 index 0000000..c03bd83 --- /dev/null +++ b/comp-be/src/codegen/unit/cg/binary/uint/cmp.rs @@ -0,0 +1,22 @@ +use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair}; +use llvm_sys_wrapper::LLVMValueRef; +use parser::ast::Type; + +pub fn cg( + lhs: LLVMValueRef, + op: &String, + rhs: LLVMValueRef, + ctx: &CompilerContext, +) -> ValueTypePair { + ( + match op.as_str() { + "<" => ctx.llvm_builder.build_icmp_ult(lhs, rhs), + ">" => ctx.llvm_builder.build_icmp_ugt(lhs, rhs), + "<=" => ctx.llvm_builder.build_icmp_ule(lhs, rhs), + ">=" => ctx.llvm_builder.build_icmp_uge(lhs, rhs), + _ => panic!("ICE codegen_compare_unsigned unhandled op {}", op), + }, + Type::Bool, + ) + .into() +} diff --git a/comp-be/src/codegen/unit/cg/binary/uint/mod.rs b/comp-be/src/codegen/unit/cg/binary/uint/mod.rs new file mode 100644 index 0000000..a127a3a --- /dev/null +++ b/comp-be/src/codegen/unit/cg/binary/uint/mod.rs @@ -0,0 +1,24 @@ +mod arith; +mod cmp; + +use crate::codegen::{ + unit::{cg::binary::eqne, CompilerContext}, + ValueTypePair, +}; +use llvm_sys_wrapper::LLVMValueRef; +use parser::ast::IntSize; + +pub fn cg( + lhs: LLVMValueRef, + op: &String, + rhs: LLVMValueRef, + ty: IntSize, + ctx: &CompilerContext, +) -> Option { + match op.as_str() { + "+" | "-" | "*" | "/" | "%" => Some(arith::cg(lhs, op, rhs, ty, ctx)), + ">" | "<" | ">=" | "<=" => Some(cmp::cg(lhs, op, rhs, ctx)), + "==" | "!=" => Some(eqne::cg(lhs, op, rhs, ctx)), + _ => None, + } +} diff --git a/comp-be/src/codegen/unit/cg/call.rs b/comp-be/src/codegen/unit/cg/call.rs new file mode 100644 index 0000000..33abc3e --- /dev/null +++ b/comp-be/src/codegen/unit/cg/call.rs @@ -0,0 +1,100 @@ +use std::borrow::Borrow; + +use parser::ast::{AtomKind, Expression, IdentPath, Type}; + +use llvm_sys_wrapper::LLVMValueRef; + +use crate::{ + codegen::{ + builder::base, + unit::{cg::expr, function::find_function, CompilerContext, Query, QueryResponse}, + ValueTypePair, + }, + fmt::AatbeFmt, + prefix, +}; + +use guard::guard; +use log::*; + +pub fn cg(expr: &Expression, ctx: &CompilerContext) -> Option { + guard!(let Expression::Call { + name, + types: _, + args, + } = expr else { unreachable!() }); + + ctx.trace(format!("Call {}", AatbeFmt::fmt(expr))); + + guard!(let Some((call_types, mut call_args)) = compute_arguments(args, ctx) else { + trace!("Got error"); + return None + }); + + let prefix = |path: &IdentPath| -> Vec { + match path { + IdentPath::Local(name) => prefix!(call ctx, name.clone()), + IdentPath::Module(name) => prefix!(call module ctx, name.clone()), + IdentPath::Root(name) => name.clone(), + } + }; + + find_function( + match ctx.query(Query::FunctionGroup(prefix(name).join("::"))) { + QueryResponse::FunctionGroup(Some(group)) => group, + QueryResponse::FunctionGroup(None) => todo!("no function found"), + _ => unreachable!(), + }, + &call_types, + ) + .map(|func| base::call(ctx, func.upgrade().expect("ICE").borrow(), &mut call_args)) +} + +fn compute_arguments( + args: &Vec, + ctx: &CompilerContext, +) -> Option<(Vec, Vec)> { + let mut call_types = vec![]; + let mut error = false; + + let call_args = args + .iter() + .filter_map(|arg| match arg { + Expression::Atom(AtomKind::SymbolLiteral(sym)) => { + call_types.push(Type::Symbol(sym.clone())); + None + } + Expression::Atom(AtomKind::Unit) => { + call_types.push(Type::Unit); + None + } + _ => { + let expr = expr::cg(&arg, ctx); + + if expr.is_none() { + error = true; + + None + } else { + expr.map_or(None, |arg| match arg.prim().clone() { + ref ty @ Type::VariantType(ref _name) => todo!("{:?}", ty), + ref ty @ Type::Array { .. } => todo!("{:?}", ty), + ref ty @ Type::Ref(box Type::Array { .. }) => { + todo!("{:?}", ty) + } + ref ty @ _ => { + call_types.push(ty.clone()); + Some(*arg) + } + }) + } + } + }) + .collect::>(); + + if error { + None + } else { + Some((call_types, call_args)) + } +} diff --git a/comp-be/src/codegen/unit/cg/conditional/ifelse.rs b/comp-be/src/codegen/unit/cg/conditional/ifelse.rs new file mode 100644 index 0000000..01739b1 --- /dev/null +++ b/comp-be/src/codegen/unit/cg/conditional/ifelse.rs @@ -0,0 +1,172 @@ +use crate::{ + codegen::{ + builder::{base, branch}, + unit::{cg::expr, CompilerContext, Message}, + ValueTypePair, + }, + fmt::AatbeFmt, + ty::LLVMTyInCtx, +}; +use llvm_sys_wrapper::{LLVMBasicBlockRef, Phi}; +use parser::ast::{Expression, Type}; + +use guard::guard; + +pub fn cg(expr: &Expression, ctx: &CompilerContext) -> Option { + guard!(let Expression::If { + cond_expr, + then_expr, + elseif_exprs, + else_expr + } = expr else { unreachable!() }); + + let then_bb = ctx.basic_block("then"); + let elseif_bbs = elseif_exprs + .iter() + .map(|e| { + ( + ( + ctx.basic_block("elseif_cond"), + ctx.basic_block("elseif_body"), + ), + e, + ) + }) + .collect::>(); + let else_bb = else_expr.as_ref().map(|_| ctx.basic_block("else")); + let end_bb = ctx.basic_block("if_end"); + + ctx.dispatch(Message::EnterIfScope(cond_expr.fmt())); + let cond = expr::cg(cond_expr, ctx)?; + + if *cond.prim().inner() != Type::Bool { + /* + self.add_error(CompileError::ExpectedType { + expected_ty: Type::Bool.fmt(), + found_ty: cond.prim().fmt(), + value: cond_expr.fmt(), + }); */ + todo!("NOT A BOOL"); + } + + let next_bb = |i: usize| -> LLVMBasicBlockRef { + elseif_bbs + .get(i) + .map(|e| e.0 .0) + .unwrap_or(else_bb.unwrap_or(end_bb)) + }; + + branch::cond_branch(ctx, *cond, then_bb, next_bb(0)); + + base::pos_at_end(ctx, then_bb); + let then_val = expr::cg(then_expr, ctx)?; + + ctx.dispatch(Message::ExitScope); + + let elseif_vals = elseif_bbs + .iter() + .enumerate() + .map(|(i, ((bb_cond, bb_body), (cond, expr)))| { + ctx.dispatch(Message::EnterElseIfScope(cond.fmt())); + base::pos_at_end(ctx, *bb_cond); + + let cond = expr::cg(cond, ctx)?; + + if *cond.prim().inner() != Type::Bool { + /* + self.add_error(CompileError::ExpectedType { + expected_ty: Type::Bool.fmt(), + found_ty: cond.prim().fmt(), + value: cond_expr.fmt(), + }); */ + todo!("NOT A BOOL"); + } + + branch::cond_branch(ctx, *cond, *bb_body, next_bb(i + 1)); + + base::pos_at_end(ctx, *bb_body); + let val = expr::cg(expr, ctx); + branch::branch(ctx, end_bb); + ctx.dispatch(Message::ExitScope); + + val + }) + .collect::>(); + + base::pos_at_end(ctx, then_bb); + + let else_val = else_bb + .map(|bb| { + ctx.dispatch(Message::EnterElseScope); + branch::branch(ctx, end_bb); + base::pos_at_end(ctx, bb); + + let res = else_expr.as_ref().and_then(|expr| expr::cg(&expr, ctx)); + ctx.dispatch(Message::ExitScope); + res + }) + .flatten(); + + branch::branch(ctx, end_bb); + + base::pos_at_end(ctx, end_bb); + + let ty = then_val.prim().inner().clone(); + let mut values = vec![*then_val]; + let mut blocks = vec![then_bb]; + + // Else If type failed to compile + if elseif_vals.len() != 0 && elseif_vals.iter().any(|v| v.is_none()) { + // TODO: Error + return None; + } else { + let velseif = elseif_vals + .iter() + .map(|e| e.as_ref().unwrap()) + .collect::>(); + + // Else If types do not match if type + if !velseif + .iter() + .fold(true, |a, b| a && b.prim().inner() == &ty) + { + // TODO: Error + return None; + } else { + for (i, val) in velseif.iter().enumerate() { + values.push(***val); + blocks.push(elseif_bbs[i].0 .1); + } + } + } + + // Else type does not match if type + if else_val + .as_ref() + .map(|v| v.prim().inner().clone()) + .unwrap_or(ty.clone()) + != ty + { + // TODO: Error + return None; + } else if let Some(velse) = else_val { + values.push(*velse); + blocks.push(else_bb.unwrap()); + } + + if ty == Type::Unit { + return None; + } + + match values.len() { + 0 => None, + 1 => Some(then_val), + _ => { + let phi = Phi::new(ctx.llvm_builder.as_ref(), ty.llvm_ty_in_ctx(ctx), ""); + + phi.add_incomings(&mut values, &mut blocks); + + Some((phi.as_ref(), ty).into()) + } + } +} diff --git a/comp-be/src/codegen/unit/cg/conditional/loops.rs b/comp-be/src/codegen/unit/cg/conditional/loops.rs new file mode 100644 index 0000000..1b89df0 --- /dev/null +++ b/comp-be/src/codegen/unit/cg/conditional/loops.rs @@ -0,0 +1,48 @@ +use parser::ast::{Expression, LoopType, Type}; + +use guard::guard; + +use crate::codegen::{ + builder::{base, branch}, + unit::{cg::expr, CompilerContext}, + ValueTypePair, +}; + +pub fn cg(expr: &Expression, ctx: &CompilerContext) -> Option { + guard!(let Expression::Loop { + loop_type, + cond_expr, + body + } = expr else { unreachable!() }); + + let cond_bb = ctx.basic_block("while_cond"); + let body_bb = ctx.basic_block("while_body"); + + branch::branch(ctx, cond_bb); + base::pos_at_end(ctx, cond_bb); + let cond = expr::cg(cond_expr, ctx)?; + + if *cond.prim().inner() != Type::Bool { + // TODO: Error + /*self.add_error(CompileError::ExpectedType { + expected_ty: Type::Bool.fmt(), + found_ty: cond.prim().fmt(), + value: cond_expr.fmt(), + });*/ + }; + + base::pos_at_end(ctx, body_bb); + expr::cg(body, ctx); + branch::branch(ctx, cond_bb); + + base::pos_at_end(ctx, cond_bb); + let end_bb = ctx.basic_block("while_end"); + match loop_type { + LoopType::While => branch::cond_branch(ctx, *cond, body_bb, end_bb), + LoopType::Until => branch::cond_branch(ctx, *cond, end_bb, body_bb), + }; + + base::pos_at_end(ctx, end_bb); + + None +} diff --git a/comp-be/src/codegen/unit/cg/conditional/mod.rs b/comp-be/src/codegen/unit/cg/conditional/mod.rs new file mode 100644 index 0000000..0ae47bc --- /dev/null +++ b/comp-be/src/codegen/unit/cg/conditional/mod.rs @@ -0,0 +1,2 @@ +pub mod ifelse; +pub mod loops; diff --git a/comp-be/src/codegen/unit/cg/consts/mod.rs b/comp-be/src/codegen/unit/cg/consts/mod.rs new file mode 100644 index 0000000..4375cad --- /dev/null +++ b/comp-be/src/codegen/unit/cg/consts/mod.rs @@ -0,0 +1 @@ +pub mod numeric; diff --git a/comp-be/src/codegen/unit/cg/consts/numeric.rs b/comp-be/src/codegen/unit/cg/consts/numeric.rs new file mode 100644 index 0000000..934e00a --- /dev/null +++ b/comp-be/src/codegen/unit/cg/consts/numeric.rs @@ -0,0 +1,28 @@ +use parser::ast::{AtomKind, Type}; + +use crate::codegen::{builder::value, unit::CompilerContext, ValueTypePair}; + +pub fn cg(atom: &AtomKind, ctx: &CompilerContext) -> Option { + match atom { + AtomKind::Integer(val, Type::Int(size)) => { + Some(value::sint(ctx, size.clone(), *val)) + } + AtomKind::Integer(val, Type::UInt(size)) => { + Some(value::uint(ctx, size.clone(), *val)) + } + AtomKind::Floating(val, Type::Float(size)) => { + Some(value::floating(ctx, size.clone(), *val)) + } + AtomKind::Unary(op, box AtomKind::Integer(val, Type::Int(size))) + if op == &String::from("-") => + { + Some(value::sint(ctx, size.clone(), (-(*val as i64)) as u64)) + } + AtomKind::Unary(op, box AtomKind::Integer(val, Type::UInt(size))) + if op == &String::from("-") => + { + Some(value::uint(ctx, size.clone(), (-(*val as i64)) as u64)) + } + _ => panic!("ICE Atom {:?}", atom), + } +} diff --git a/comp-be/src/codegen/unit/cg/decl.rs b/comp-be/src/codegen/unit/cg/decl.rs new file mode 100644 index 0000000..36bba7a --- /dev/null +++ b/comp-be/src/codegen/unit/cg/decl.rs @@ -0,0 +1,40 @@ +use parser::ast::{Expression, Type}; + +use guard::guard; + +use crate::codegen::{ + unit::{alloc_variable, CompilerContext, Query, QueryResponse}, + ValueTypePair, +}; + +pub fn cg(expr: &Expression, ctx: &CompilerContext) -> Option { + match expr { + Expression::Decl { + ty: Type::NamedType { name, ty: Some(ty) }, + value: _, + exterior_bind: _, + } => { + alloc_variable(expr, ctx); + + guard!(let QueryResponse::Slot(slot) = ctx.query(Query::Slot(name)) else { unreachable!() }); + let slot = slot?; + Some((slot.into(), *ty.clone()).into()) + } + Expression::Decl { + ty: Type::NamedType { name, ty: None }, + value, + exterior_bind: _, + } => { + if value.is_none() { + todo!("ERROR") + } + + alloc_variable(expr, ctx).and_then(|ty| { + guard!(let QueryResponse::Slot(slot) = ctx.query(Query::Slot(name)) else { unreachable!() }); + let slot = slot?; + Some((slot.into(), ty).into()) + }) + } + _ => unreachable!(), + } +} diff --git a/comp-be/src/codegen/unit/cg/expr.rs b/comp-be/src/codegen/unit/cg/expr.rs new file mode 100644 index 0000000..36006bb --- /dev/null +++ b/comp-be/src/codegen/unit/cg/expr.rs @@ -0,0 +1,44 @@ +use parser::ast::{Expression, FunctionType}; + +use crate::codegen::{ + unit::{ + cg::{assign, atom, binary, call, conditional, decl}, + declare_and_compile_function, CompilerContext, Message, + }, + ValueTypePair, +}; + +pub fn cg(expr: &Expression, ctx: &CompilerContext) -> Option { + match expr { + Expression::Assign { .. } => assign::cg(expr, ctx), + Expression::Decl { .. } => decl::cg(expr, ctx), + Expression::Loop { .. } => conditional::loops::cg(expr, ctx), + Expression::If { .. } => conditional::ifelse::cg(expr, ctx), + Expression::Binary(..) => Some(binary::cg(expr, ctx).ok().expect("todo")), + Expression::Call { .. } => call::cg(expr, ctx), + Expression::Atom(atom) => atom::cg(atom, ctx), + Expression::Function { ty, type_names, .. } if type_names.len() == 0 => match ty { + FunctionType { + ret_ty: _, + params: _, + ext: true, + } => None, + _ => declare_and_compile_function(ctx, expr), + }, + Expression::Function { .. } => None, + Expression::Block(body) if body.len() == 0 => None, + Expression::Block(body) => { + ctx.dispatch(Message::EnterAnonymousScope); + + let ret = body + .iter() + .fold(None, |_, expr| Some(cg(expr, ctx))) + .unwrap(); + + ctx.dispatch(Message::ExitScope); + + ret + } + _ => todo!("{:?}", expr), + } +} diff --git a/comp-be/src/codegen/unit/cg/mod.rs b/comp-be/src/codegen/unit/cg/mod.rs new file mode 100644 index 0000000..0ea5b69 --- /dev/null +++ b/comp-be/src/codegen/unit/cg/mod.rs @@ -0,0 +1,27 @@ +use llvm_sys_wrapper::LLVMValueRef; +use parser::ast::AST; + +use super::{CompilerContext, Message}; + +pub mod assign; +pub mod atom; +pub mod binary; +pub mod call; +pub mod conditional; +pub mod consts; +pub mod decl; +pub mod expr; + +pub fn cg(ast: &AST, ctx: &CompilerContext) -> Option { + match ast { + AST::Expr(expr) => expr::cg(expr, ctx).map(|e| *e), + AST::File(nodes) => nodes.iter().fold(None, |_, n| cg(n, ctx)), + AST::Module(name, ast) => { + ctx.dispatch(Message::RestoreModuleScope(name.clone())); + let ret = cg(ast, ctx); + ctx.dispatch(Message::ExitScope); + ret + } + _ => todo!("{:?}", ast), + } +} diff --git a/comp-be/src/codegen/unit/compiler.rs b/comp-be/src/codegen/unit/compiler.rs new file mode 100644 index 0000000..c27ffba --- /dev/null +++ b/comp-be/src/codegen/unit/compiler.rs @@ -0,0 +1,583 @@ +use std::{cell::RefCell, collections::HashMap, path::PathBuf, rc::Weak}; + +use llvm_sys_wrapper::{Builder, Context, LLVMBasicBlockRef, LLVMValueRef, Module}; +use parser::ast::{Expression, FunctionType, AST}; + +use crate::{ + codegen::{ + comp_unit::CompilationUnit, + unit::{cg, decl, function::find_func, generic}, + Scope, ValueTypePair, + }, + fmt::AatbeFmt, + ty::TypeContext, +}; + +use super::{ + function::{Func, FuncTyMap}, + Slot, +}; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum FunctionVisibility { + Local, + Public, +} + +pub enum Message { + PushFunctionTemplate(String, Expression), + PushInScope(String, Slot), + DeclareFunction(String, Func, FunctionVisibility), + EnterFunctionScope((String, FunctionType)), + EnterModuleScope(String), + ExitModuleScope(String), + RestoreModuleScope(String), + EnterIfScope(String), + EnterElseIfScope(String), + EnterElseScope, + EnterAnonymousScope, + ExitScope, +} + +impl std::fmt::Debug for Message { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match &self { + Message::PushFunctionTemplate(name, expr) => { + f.debug_tuple("PushFunctionTemplate").field(name).finish() + } + Message::PushInScope(name, slot) => f + .debug_tuple("PushInScope") + .field(name) + .field(slot) + .finish(), + Message::DeclareFunction(name, ty, vis) => f + .debug_tuple("DeclareFunction") + .field(name) + .field(&AatbeFmt::fmt(ty)) + .field(vis) + .finish(), + Message::EnterFunctionScope(func) => f + .debug_tuple("EnterFunctionScope") + .field(&func.0) + .field(&AatbeFmt::fmt(&func.1)) + .finish(), + Message::EnterModuleScope(name) => { + f.debug_tuple("EnterModuleScope").field(&name).finish() + } + Message::ExitModuleScope(name) => { + f.debug_tuple("ExitModuleScope").field(&name).finish() + } + Message::RestoreModuleScope(name) => { + f.debug_tuple("RestoreModuleScope").field(&name).finish() + } + Message::EnterIfScope(cond) => f.debug_tuple("EnterIfScope").field(cond).finish(), + Message::EnterElseIfScope(cond) => { + f.debug_tuple("EnterElseIfScope").field(cond).finish() + } + Message::EnterElseScope => write!(f, "EnterElseScope"), + Message::EnterAnonymousScope => write!(f, "EnterAnonymousScope"), + Message::ExitScope => write!(f, "ExitScope"), + } + } +} + +pub enum Query<'cmd> { + Slot(&'cmd String), + Function((String, &'cmd FunctionType)), + FunctionGroup(String), + Prefix, +} + +impl std::fmt::Debug for Query<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Query::Slot(name) => f.debug_tuple("Slot").field(name).finish(), + Query::Function(func) => f + .debug_tuple("Function") + .field(&func.0) + .field(&AatbeFmt::fmt(func.1)) + .finish(), + Query::FunctionGroup(name) => f.debug_tuple("FunctionGroup").field(name).finish(), + Query::Prefix => write!(f, "Prefix"), + } + } +} + +pub enum QueryResponse { + Slot(Option), + Function(Option>), + FunctionGroup(Option>), + Prefix(Vec), +} + +impl std::fmt::Debug for QueryResponse { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + QueryResponse::Slot(slot) => f.debug_tuple("Slot").field(slot).finish(), + QueryResponse::Function(ref func) => f + .debug_tuple("Function") + .field( + &func + .as_ref() + .map(|f| AatbeFmt::fmt(f.upgrade().expect("ICE").as_ref())), + ) + .finish(), + QueryResponse::FunctionGroup(group) => f + .debug_tuple("FunctionGroup") + .field(&format_args!( + "{}", + match &group { + None => String::from("[]"), + Some(gr) => format!("{:?}", gr.borrow().iter().collect::>()), + } + )) + .finish(), + QueryResponse::Prefix(prefix) => f + .debug_tuple("Prefix") + .field(&format_args!("{}", prefix.join("::"))) + .finish(), + } + } +} + +pub struct CompilerContext<'ctx> { + pub path: PathBuf, + pub llvm_context: &'ctx Context, + pub llvm_module: &'ctx Module, + pub llvm_builder: &'ctx Builder, + dispatch: &'ctx dyn Fn(Message) -> (), + query: &'ctx dyn Fn(Query) -> QueryResponse, + trace: &'ctx dyn Fn(String) -> (), + basic_block: &'ctx dyn Fn(&str) -> LLVMBasicBlockRef, +} + +impl<'ctx> CompilerContext<'ctx> { + pub fn new

( + path: P, + llvm_context: &'ctx Context, + llvm_module: &'ctx Module, + llvm_builder: &'ctx Builder, + dispatch: &'ctx dyn Fn(Message) -> (), + query: &'ctx dyn Fn(Query) -> QueryResponse, + trace: &'ctx dyn Fn(String) -> (), + basic_block: &'ctx dyn Fn(&str) -> LLVMBasicBlockRef, + ) -> Self + where + P: Into, + { + Self { + path: path.into(), + llvm_context, + llvm_module, + llvm_builder, + dispatch, + query, + trace, + basic_block, + } + } + + fn with_builder(&'ctx self, builder: &'ctx Builder) -> Self { + Self { + path: self.path.clone(), + llvm_context: self.llvm_context, + llvm_module: self.llvm_module, + llvm_builder: builder, + dispatch: self.dispatch, + query: self.query, + trace: self.trace, + basic_block: self.basic_block, + } + } + + pub fn basic_block(&self, name: &str) -> LLVMBasicBlockRef { + (self.basic_block)(name) + } + + pub fn trace(&self, message: String) { + (self.trace)(message) + } + + pub fn dispatch(&self, message: Message) { + (self.dispatch)(message) + } + + pub fn query(&self, query: Query) -> QueryResponse { + (self.query)(query) + } + + pub fn in_function_scope(&self, func: (String, FunctionType), f: F) -> Option + where + F: FnOnce(CompilerContext) -> Option, + { + self.dispatch(Message::EnterFunctionScope(func)); + let builder = Builder::new_in_context(self.llvm_context.as_ref()); + let ctx = self.with_builder(&builder); + let res = f(ctx); + self.dispatch(Message::ExitScope); + res + } +} + +pub struct CompilerUnit<'ctx> { + modules: HashMap>, + _typectx: TypeContext, + llvm_context: &'ctx Context, + llvm_module: &'ctx Module, + scope_stack: RefCell>, + module_scopes: RefCell>, + path: PathBuf, + ident: RefCell, + generic_processor: RefCell, +} + +impl<'ctx> CompilerUnit<'ctx> { + pub fn new

(path: P, llvm_context: &'ctx Context, llvm_module: &'ctx Module) -> Self + where + P: Into, + { + Self { + path: path.into(), + llvm_context, + llvm_module, + modules: HashMap::new(), + _typectx: TypeContext::new(), + scope_stack: RefCell::new(vec![]), + module_scopes: RefCell::new(HashMap::new()), + ident: RefCell::new(0), + generic_processor: RefCell::new(generic::Processor::new()), + } + } + + pub fn in_root_scope(&self, f: F) + where + F: FnOnce(&Self), + { + self.enter_root_scope(); + f(self); + println!("└── Exit Root Scope"); + self.exit_scope(); + } + + fn enter_root_scope(&self) { + println!("Enter Root Scope"); + self.scope_stack + .borrow_mut() + .push(Scope::with_fdir(self.path.clone())); + } + + fn enter_anonymous_scope(&self) { + self.scope_stack.borrow_mut().push(Scope::new()); + } + + fn enter_function_scope(&self, func: (String, FunctionType)) { + self.scope_stack + .borrow_mut() + .push(Scope::with_function((func.0, func.1))); + } + + fn enter_module_scope(&self, name: String) { + self.scope_stack.borrow_mut().push(Scope::with_name(&name)); + } + + fn exit_module_scope(&self, name: String) { + let scope = self + .scope_stack + .borrow_mut() + .pop() + .expect("ICE Scope stack broke"); + self.module_scopes.borrow_mut().insert(name, scope); + } + + fn restore_module_scope(&self, name: String) { + let scope = self + .module_scopes + .borrow_mut() + .remove(&name) + .expect("ICE Scope stack broke"); + self.scope_stack.borrow_mut().push(scope); + } + + pub fn push_in_scope(&self, name: &String, unit: Slot) { + self.scope_stack + .borrow_mut() + .last_mut() + .expect("Compiler broke. Scope stack is corrupted.") + .add_symbol(name, unit); + } + + pub fn push_function_template(&self, name: String, func: Expression) { + self.scope_stack + .borrow_mut() + .last_mut() + .expect("Compiler broke. Scope stack is corrupted.") + .add_template(name, func); + } + + pub fn get_from_scope(&self, name: &String) -> Option { + for scope in self.scope_stack.borrow().iter().rev() { + if let Some(sym) = scope.find_symbol(name) { + return Some(sym.clone()); + } + } + + None + } + + pub fn get_slot(&self, name: &String) -> Option { + if let Some(slot @ (Slot::Variable { .. } | Slot::FunctionArgument(..))) = + self.get_from_scope(name) + { + Some(slot) + } else { + None + } + } + + fn exit_scope(&self) { + self.scope_stack + .borrow_mut() + .pop() + .expect("ICE Scope Stack Broke"); + } + + fn dispatch(&self, message: Message) { + print!("{}", "│ ".repeat(*self.ident.borrow())); + println!("├── {:?}", message); + match message { + Message::PushFunctionTemplate(name, func) => { + self.push_function_template(name, func); + } + Message::PushInScope(ref name, unit) => { + self.push_in_scope(name, unit.clone()); + } + Message::DeclareFunction(name, func, ty) => { + let mut scope_stack = self.scope_stack.borrow_mut(); + if ty == FunctionVisibility::Local { + scope_stack.last_mut() + } else { + scope_stack.first_mut() + } + .expect("ICE: Scope stack is corrupted.") + .add_function(&name, func.clone()); + } + Message::EnterFunctionScope(func) => { + *self.ident.borrow_mut() += 1; + self.enter_function_scope(func.clone()); + } + Message::EnterModuleScope(name) => { + *self.ident.borrow_mut() += 1; + self.enter_module_scope(name.clone()) + } + Message::ExitModuleScope(name) => { + *self.ident.borrow_mut() -= 1; + self.exit_module_scope(name.clone()) + } + Message::RestoreModuleScope(name) => { + *self.ident.borrow_mut() += 1; + self.restore_module_scope(name.clone()) + } + Message::EnterIfScope(_) => { + *self.ident.borrow_mut() += 1; + self.enter_anonymous_scope() + } + Message::EnterElseIfScope(_) => { + *self.ident.borrow_mut() += 1; + self.enter_anonymous_scope() + } + Message::EnterElseScope => { + *self.ident.borrow_mut() += 1; + self.enter_anonymous_scope() + } + Message::EnterAnonymousScope => { + *self.ident.borrow_mut() += 1; + self.enter_anonymous_scope() + } + Message::ExitScope => { + *self.ident.borrow_mut() -= 1; + self.exit_scope() + } + } + } + + fn query(&self, query: Query) -> QueryResponse { + print!("{}", "│ ".repeat(*self.ident.borrow())); + println!("├── Query {:?}", query); + let response = match query { + Query::Function(func) => QueryResponse::Function(self.get_func(func)), + Query::FunctionGroup(name) => QueryResponse::FunctionGroup(self.get_func_group(&name)), + Query::Prefix => QueryResponse::Prefix(self.get_prefix()), + Query::Slot(name) => QueryResponse::Slot(self.get_slot(name)), + }; + print!("{}", "│ ".repeat(*self.ident.borrow())); + println!("├── Response {:?}", response); + response + } + + fn trace(&self, message: String) { + print!("{}", "│ ".repeat(*self.ident.borrow())); + println!("├── {}", message); + } + + pub fn push( + &mut self, + name: &String, + module: CompilerUnit<'ctx>, + ) -> Option> { + self.modules.insert(name.clone(), module) + } + + pub fn get_mut(&mut self, name: &String) -> Option<&mut Self> { + self.modules.get_mut(name) + } + + pub fn decl(&'ctx self, root_builder: &Builder, ast: &AST) { + let dispatch = &|command: Message| self.dispatch(command); + let query = &|query: Query| self.query(query); + let trace = &|message: String| self.trace(message); + let basic_block = &|name: &str| self.basic_block(name); + + decl::decl( + ast, + &mut CompilerContext::new( + self.path.clone(), + self.llvm_context, + self.llvm_module, + root_builder, + dispatch, + query, + trace, + basic_block, + ), + ); + } + + pub fn generics(&'ctx self, root_builder: &Builder, ast: &AST) { + let mut proc = self.generic_processor.borrow_mut(); + let ast = proc + .extract_function_calls(ast) + .extract_tree(ast) + .generate_tree() + .generated_tree + .as_ref() + .unwrap(); + + self.decl(root_builder, ast); + self.codegen(root_builder, ast); + } + + pub fn codegen(&'ctx self, root_builder: &Builder, ast: &AST) -> Option { + let dispatch = &|command: Message| self.dispatch(command); + let query = &|query: Query| self.query(query); + let trace = &|message: String| self.trace(message); + let basic_block = &|name: &str| self.basic_block(name); + + cg::cg( + ast, + &CompilerContext::new( + self.path.clone(), + self.llvm_context, + self.llvm_module, + root_builder, + dispatch, + query, + trace, + basic_block, + ), + ) + } + + pub fn get_func_group(&self, name: &String) -> Option> { + for scope in self.scope_stack.borrow().iter().rev() { + if let Some(func) = scope.func_by_name(&name) { + return Some(func); + } + } + + for scope in self.scope_stack.borrow().iter().rev() { + if let Some(func) = scope.get_template(&name) { + println!("Found template!"); + } + } + + None + } + + pub fn get_func(&self, func: (String, &FunctionType)) -> Option> { + for scope in self.scope_stack.borrow().iter().rev() { + if let Some(group) = scope.func_by_name(&func.0) { + return find_func(group, func.1); + } + } + + None + } + + pub fn llvm_module_ref(&self) -> &Module { + &self.llvm_module + } + + pub fn get_prefix(&self) -> Vec { + self.scope_stack + .borrow() + .iter() + .map(|s| s.name()) + .filter(|n| n != &String::default()) + .collect::>() + } + + pub fn basic_block(&self, name: &str) -> LLVMBasicBlockRef { + for scope in self.scope_stack.borrow().iter().rev() { + let bb = scope.bb(self, &name); + if let Some(bb) = bb { + return bb; + } + } + panic!("Compiler broke. Scope stack is corrupted."); + } +} + +#[macro_export] +macro_rules! prefix { + (call $ctx: expr, $name: expr) => {{ + if let crate::codegen::unit::compiler::QueryResponse::Prefix(mut prefix) = + $ctx.query(crate::codegen::unit::compiler::Query::Prefix) + { + prefix.pop(); + prefix.push($name); + prefix + } else { + panic!("PREFIX ICE") + } + }}; + (call module $ctx: expr, $name: expr) => {{ + if let crate::codegen::unit::compiler::QueryResponse::Prefix(mut prefix) = + $ctx.query(crate::codegen::unit::compiler::Query::Prefix) + { + prefix.pop(); + prefix.extend($name); + prefix + } else { + panic!("PREFIX ICE") + } + }}; + ($ctx: expr, $name: expr) => {{ + if let crate::codegen::unit::compiler::QueryResponse::Prefix(mut prefix) = + $ctx.query(crate::codegen::unit::compiler::Query::Prefix) + { + prefix.push($name); + prefix + } else { + panic!("PREFIX ICE") + } + }}; + ($ctx: expr) => {{ + if let crate::codegen::unit::compiler::QueryResponse::Prefix(prefix) = + $ctx.query(crate::codegen::unit::compiler::Query::Prefix) + { + prefix + } else { + panic!("PREFIX ICE") + } + }}; +} diff --git a/comp-be/src/codegen/unit/decl/expr.rs b/comp-be/src/codegen/unit/decl/expr.rs new file mode 100644 index 0000000..15370d0 --- /dev/null +++ b/comp-be/src/codegen/unit/decl/expr.rs @@ -0,0 +1,15 @@ +use parser::ast::Expression; + +use crate::codegen::unit::{declare_function, CompilerContext, Message}; + +pub fn decl(expr: &Expression, ctx: &mut CompilerContext) { + match expr { + Expression::Function { type_names, .. } if type_names.len() == 0 => { + declare_function(ctx, expr) + } + Expression::Function { name, .. } => { + ctx.dispatch(Message::PushFunctionTemplate(name.clone(), expr.clone())); + } + _ => panic!("Top level {:?} unsupported", expr), + } +} diff --git a/comp-be/src/codegen/unit/decl/mod.rs b/comp-be/src/codegen/unit/decl/mod.rs new file mode 100644 index 0000000..da48c01 --- /dev/null +++ b/comp-be/src/codegen/unit/decl/mod.rs @@ -0,0 +1,21 @@ +mod expr; + +use parser::ast::AST; + +use super::{CompilerContext, Message}; + +pub fn decl(ast: &AST, ctx: &mut CompilerContext) { + match ast { + AST::Expr(expr) => expr::decl(expr, ctx), + AST::Module(name, ast) => { + ctx.dispatch(Message::EnterModuleScope(name.clone())); + super::decl(ast, ctx); + ctx.dispatch(Message::ExitModuleScope(name.clone())); + } + AST::File(nodes) => nodes + .iter() + .fold(Some(()), |_, ast| Some(decl(ast, ctx))) + .unwrap(), + _ => todo!("{:?}", ast), + } +} diff --git a/comp-be/src/codegen/unit/function.rs b/comp-be/src/codegen/unit/function.rs index e0449a2..c473256 100644 --- a/comp-be/src/codegen/unit/function.rs +++ b/comp-be/src/codegen/unit/function.rs @@ -1,29 +1,45 @@ use crate::{ codegen::builder::cast, codegen::{ - builder::core, + builder::base, mangle_v1::NameMangler, - unit::{Mutability, Slot}, - AatbeModule, CompileError, ValueTypePair, + unit::{ + cg::expr, CompilerContext, FunctionVisibility, Message, Mutability, Query, + QueryResponse, Slot, + }, + CompileError, ValueTypePair, }, fmt::AatbeFmt, + prefix, ty::LLVMTyInCtx, }; use llvm_sys_wrapper::Function; -use std::collections::HashMap; -use std::ops::Deref; +use std::{ + cell::RefCell, + collections::HashMap, + ops::Deref, + rc::{Rc, Weak}, +}; + +use guard::guard; -use parser::ast::{Expression, FunctionType, PrimitiveType}; +use parser::ast::{Expression, FunctionType, Type}; use llvm_sys_wrapper::{Builder, LLVMBasicBlockRef}; -#[derive(Debug)] +#[derive(Clone)] pub struct Func { ty: FunctionType, - name: String, + ident: String, inner: Function, } +impl std::fmt::Debug for Func { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", AatbeFmt::fmt(self)) + } +} + impl AatbeFmt for &Func { fn fmt(self) -> String { format!( @@ -33,28 +49,28 @@ impl AatbeFmt for &Func { } else { String::default() }, - self.name, + self.ident, (&self.ty).fmt() ) } } -pub type FuncTyMap = Vec; -pub type FunctionMap = HashMap; +pub type FuncTyMap = Vec>; +pub type FunctionMap = HashMap>; -pub fn find_func<'a>(map: &'a FuncTyMap, ty: &FunctionType) -> Option<&'a Func> { - for func in map { +pub fn find_func<'a>(map: RefCell, ty: &FunctionType) -> Option> { + for func in map.borrow().iter() { if &func.ty == ty { - return Some(func); + return Some(Rc::downgrade(func)); } } return None; } -pub fn find_function<'a>(map: &'a FuncTyMap, args: &Vec) -> Option<&'a Func> { - for func in map { +pub fn find_function<'a>(map: RefCell, args: &Vec) -> Option> { + for func in map.borrow().iter() { if func.accepts(args) { - return Some(func); + return Some(Rc::downgrade(func)); } } return None; @@ -68,15 +84,15 @@ impl Deref for Func { } impl Func { - pub fn new(ty: FunctionType, name: String, inner: Function) -> Self { - Self { ty, name, inner } + pub fn new(ty: FunctionType, ident: String, inner: Function) -> Self { + Self { ty, ident, inner } } pub fn ty(&self) -> &FunctionType { &self.ty } - pub fn ret_ty(&self) -> &PrimitiveType { + pub fn ret_ty(&self) -> &Type { &self.ty.ret_ty } @@ -85,28 +101,28 @@ impl Func { } pub fn bb(&self, name: String) -> LLVMBasicBlockRef { - self.inner.append_basic_block(name.as_ref()) + self.inner.append_basic_block(&name) } - fn accepts(&self, args: &Vec) -> bool { + fn accepts(&self, args: &Vec) -> bool { let params = &self.ty.params; - if params.len() != args.len() && !(params.contains(&PrimitiveType::Varargs)) { + if params.len() != args.len() && !(params.contains(&Type::Varargs)) { return false; }; for (i, param) in params.iter().enumerate() { - if matches!(param, PrimitiveType::Varargs) { + if matches!(param, Type::Varargs) { continue; } let arg = &args[i]; match param { - PrimitiveType::Varargs => continue, - PrimitiveType::NamedType { + Type::Varargs => continue, + Type::NamedType { ty: Some(box t), .. } if t != arg => return false, - PrimitiveType::NamedType { + Type::NamedType { ty: Some(box t), .. } if t == arg => return true, t if t != arg => return false, @@ -118,32 +134,41 @@ impl Func { } } -pub fn declare_function(module: &mut AatbeModule, function: &Expression) { +pub fn declare_function(ctx: &CompilerContext, function: &Expression) { match function { Expression::Function { ty, - export, + public, type_names, name, .. } if type_names.len() == 0 => { - let func = module - .llvm_module_ref() - .get_or_add_function(&function.mangle(module), ty.llvm_ty_in_ctx(module)); + let func = ctx + .llvm_module + .get_or_add_function(&function.mangle(&ctx), ty.llvm_ty_in_ctx(&ctx)); + let name = prefix!(ctx, name.clone()).join("::"); let func = Func::new(ty.clone(), name.clone(), func); - if !export { - module.add_function(&name, func); + if !public { + ctx.dispatch(Message::DeclareFunction( + name, + func, + FunctionVisibility::Local, + )); } else { - module.export_function(&name, func); + ctx.dispatch(Message::DeclareFunction( + name, + func, + FunctionVisibility::Public, + )); } } _ => unimplemented!("{:?}", function), } } -pub fn declare_and_compile_function( - module: &mut AatbeModule, +pub fn declare_and_compile_function<'ctx>( + ctx: &CompilerContext, func: &Expression, ) -> Option { match func { @@ -154,53 +179,46 @@ pub fn declare_and_compile_function( ext: true, } => None, _ => { - let builder = Builder::new_in_context(module.llvm_context_ref().as_ref()); - module.start_scope_with_function((name.clone(), ty.clone()), builder); - codegen_function(module, func); - inject_function_in_scope(module, func); - let ret_val = module.codegen_expr( - &body - .as_ref() - .expect("ICE Function with no body but not external"), - ); - - // TODO: Typechecks - if has_return_type(ty) { - if let Some(val) = ret_val { - match val.prim() { - PrimitiveType::VariantType(variant) => { - let parent_ty = module - .typectx_ref() - .get_parent_for_variant(variant) - .expect("ICE: Variant without parent"); - let ret_ty = *ty.ret_ty.clone(); - core::ret( - module, - (cast::child_to_parent(module, val, parent_ty), ret_ty).into(), - ) - } - _ => core::ret(module, val), - }; + ctx.in_function_scope((name.clone(), ty.clone()), |ctx| { + inject_function_in_scope(&ctx, func); + + codegen_function(&ctx, func); + + let ret_val = expr::cg( + &body + .as_ref() + .expect("ICE Function with no body but not external"), + &ctx, + ); + + if !has_return_type(ty) { + base::ret_void(&ctx); } else { - module.add_error(CompileError::ExpectedReturn { - function: func.clone().fmt(), - ty: ty.fmt(), - }) + if let Some(val) = ret_val { + match val.prim() { + Type::VariantType(_variant) => todo!(), + _ => base::ret(&ctx, val), + }; + } else { + // TODO: Error + /* + module.add_error(CompileError::ExpectedReturn { + function: func.clone().fmt(), + ty: ty.fmt(), + }) */ + todo!() + } } - } else { - core::ret_void(module); - } - - module.exit_scope(); - None + None + }) } }, _ => unreachable!(), } } -pub fn codegen_function(module: &mut AatbeModule, function: &Expression) { +pub fn codegen_function(ctx: &CompilerContext, function: &Expression) { match function { Expression::Function { attributes, @@ -208,24 +226,27 @@ pub fn codegen_function(module: &mut AatbeModule, function: &Expression) { ty, .. } => { - let func = module.get_func((name.clone(), ty.clone())).unwrap(); + let func = ctx.query(Query::Function((prefix!(ctx).join("::"), ty))); + + guard!(let QueryResponse::Function(Some(func)) = func else { unreachable!(); }); + let func = func.upgrade().expect("ICE"); if !attributes.is_empty() { for attr in attributes { match attr.to_lowercase().as_ref() { - "entry" => core::pos_at_end(module, func.bb("entry".to_string())), + "entry" => base::pos_at_end(ctx, func.bb("entry".to_string())), _ => panic!("Cannot decorate function with {}", name), }; } } else { - core::pos_at_end(module, func.bb(String::default())); + base::pos_at_end(ctx, func.bb(String::default())); } } _ => unreachable!(), } } -pub fn inject_function_in_scope(module: &mut AatbeModule, function: &Expression) { +pub fn inject_function_in_scope(ctx: &CompilerContext, function: &Expression) { match function { Expression::Function { name: fname, ty, .. @@ -241,21 +262,17 @@ pub fn inject_function_in_scope(module: &mut AatbeModule, function: &Expression) for (pos, ty) in params .into_iter() .filter(|ty| match ty { - PrimitiveType::Symbol(_) => false, + Type::Symbol(_) => false, _ => true, }) .enumerate() { match ty { - PrimitiveType::NamedType { + Type::NamedType { name, - ty: - Some( - box PrimitiveType::TypeRef(_) - | box PrimitiveType::Array { .. }, - ), + ty: Some(box Type::TypeRef(_) | box Type::Array { .. }), } => { - let arg = module + /*let arg = module .get_func((fname.clone(), fty.clone())) .expect("Compiler borked. Functions borked") .get_param(pos as u32); @@ -265,9 +282,9 @@ pub fn inject_function_in_scope(module: &mut AatbeModule, function: &Expression) name, Slot::Variable { mutable: match ty { - PrimitiveType::Array { .. } - | PrimitiveType::NamedType { - ty: Some(box PrimitiveType::Array { .. }), + Type::Array { .. } + | Type::NamedType { + ty: Some(box Type::Array { .. }), .. } => Mutability::Mutable, _ => Mutability::Immutable, @@ -276,24 +293,24 @@ pub fn inject_function_in_scope(module: &mut AatbeModule, function: &Expression) ty: ty.clone(), value: ptr, }, - ); + );*/ + todo!() } - PrimitiveType::NamedType { + Type::NamedType { name, - ty: Some(box PrimitiveType::Ref(ty) | ty), + ty: Some(box Type::Ref(ty) | ty), } => { - module.push_in_scope( - name, - Slot::FunctionArgument( - module - .get_func((fname.clone(), fty.clone())) - .expect("Compiler borked. Functions borked") - .get_param(pos as u32), - *ty.clone(), - ), - ); + guard!(let QueryResponse::Function(Some(func)) = + ctx.query(Query::Function((prefix!(ctx).join("::"), fty))) + else { unreachable!() }); + + let func = func.upgrade().expect("ICE"); + ctx.dispatch(Message::PushInScope( + name.clone(), + Slot::FunctionArgument(func.get_param(pos as u32), *ty.clone()), + )) } - PrimitiveType::Unit | PrimitiveType::Symbol(_) => {} + Type::Unit | Type::Symbol(_) => {} _ => unimplemented!("{:?}", ty), } } @@ -307,7 +324,7 @@ pub fn inject_function_in_scope(module: &mut AatbeModule, function: &Expression) fn has_return_type(func: &FunctionType) -> bool { match func.ret_ty { - box PrimitiveType::Unit => false, + box Type::Unit => false, _ => true, } } diff --git a/comp-be/src/codegen/unit/generic/gen.rs b/comp-be/src/codegen/unit/generic/gen.rs new file mode 100644 index 0000000..3368a9a --- /dev/null +++ b/comp-be/src/codegen/unit/generic/gen.rs @@ -0,0 +1,103 @@ +use std::collections::HashMap; + +use parser::ast::{Expression, FunctionType, IdentPath, Type, AST}; + +use super::Processor; + +use guard::guard; + +pub fn gen(ast: &AST, proc: &Processor) -> Option { + match ast { + AST::Module(..) => { + // TODO: Module + None + } + AST::File(body) => Some(AST::File( + body.iter() + .filter_map(|ast| gen_tree(ast, proc)) + .flatten() + .collect::>(), + )), + _ => todo!("{:?}", ast), + } +} + +fn gen_tree(ast: &AST, proc: &Processor) -> Option> { + match ast { + AST::Module(..) => { + // TODO: Module + None + } + AST::Expr(expr) => gen_expr(expr, proc).and_then(|exprs| { + Some( + exprs + .iter() + .map(|expr| AST::Expr(expr.clone())) + .collect::>(), + ) + }), + _ => todo!("{:?}", ast), + } +} + +fn gen_expr(expr: &Expression, proc: &Processor) -> Option> { + match expr { + Expression::Function { + type_names, + name, + ty: + FunctionType { + ext, + ret_ty, + params, + }, + body, + attributes, + public, + } => { + guard!(let Some(types) = proc + .function_calls + .get(&IdentPath::Local(name.clone())) else { return None; }); + + Some( + types + .iter() + .map(|set| { + let map = type_names.iter().zip(set).collect::>(); + + Expression::Function { + type_names: vec![], + name: name.clone(), + ty: FunctionType { + ext: *ext, + ret_ty: box resolve_type(ret_ty, &map), + params: params + .iter() + .map(|ty| resolve_type(ty, &map)) + .collect::>(), + }, + body: body.clone(), + attributes: attributes.clone(), + public: *public, + } + }) + .collect(), + ) + } + _ => todo!("{:?}", expr), + } +} + +fn resolve_type(ty: &Type, map: &HashMap<&String, &Type>) -> Type { + match ty { + Type::NamedType { + name, + ty: Some(box ty), + } => Type::NamedType { + name: name.clone(), + ty: Some(box resolve_type(ty, map)), + }, + Type::TypeRef(name) => map.get(name).cloned().unwrap().clone(), + _ => ty.clone(), + } +} diff --git a/comp-be/src/codegen/unit/generic/mod.rs b/comp-be/src/codegen/unit/generic/mod.rs new file mode 100644 index 0000000..c1195ba --- /dev/null +++ b/comp-be/src/codegen/unit/generic/mod.rs @@ -0,0 +1,94 @@ +use std::collections::{HashMap, HashSet}; + +use parser::ast::{Expression, IdentPath, Type, AST}; + +mod gen; + +#[derive(Debug)] +pub struct Processor { + pub(super) function_calls: HashMap>>, + extracted_tree: Option, + pub generated_tree: Option, +} + +impl Processor { + pub fn new() -> Self { + Self { + function_calls: HashMap::new(), + extracted_tree: None, + generated_tree: None, + } + } + + pub fn extract_function_calls(&mut self, ast: &AST) -> &mut Self { + match ast { + AST::Module(..) => { + // TODO: Module + } + AST::File(body) => body.iter().for_each(|ast| { + self.extract_function_calls(ast); + }), + AST::Expr(expr) => self.from_expression(expr), + _ => todo!("{:?}", ast), + }; + + self + } + + fn from_expression(&mut self, expr: &Expression) { + match expr { + Expression::Function { + body: Some(box body), + .. + } => self.from_expression(body), + Expression::Call { name, types, .. } if types.len() > 0 => { + self.insert_function_call(name, types.clone()) + } + Expression::Block(body) => body.iter().for_each(|e| self.from_expression(e)), + _ => {} + } + } + + pub fn extract_tree(&mut self, ast: &AST) -> &mut Self { + println!("{:#?}", ast); + self.extracted_tree = extract_ast(ast); + println!("{:#?}", self.extracted_tree); + self + } + + pub fn generate_tree(&mut self) -> &mut Self { + let ast = self.extracted_tree.as_ref().unwrap(); + self.generated_tree = gen::gen(ast, &self); + println!("{:#?}", self.generated_tree); + self + } + + fn insert_function_call(&mut self, name: &IdentPath, types: Vec) { + if !self.function_calls.contains_key(name) { + self.function_calls.insert(name.clone(), HashSet::new()); + } + + self.function_calls.get_mut(name).unwrap().insert(types); + } +} + +fn extract_ast(ast: &AST) -> Option { + match ast { + AST::Module(..) => { + // TODO: Module + None + } + AST::File(body) => Some(AST::File( + body.iter().filter_map(extract_ast).collect::>(), + )), + AST::Expr(expr) => extract_expr(expr).and_then(|expr| Some(AST::Expr(expr))), + _ => todo!("{:?}", ast), + } +} + +fn extract_expr(expr: &Expression) -> Option { + match expr { + Expression::Function { type_names, .. } if type_names.len() > 0 => Some(expr.clone()), + _ => None, + } +} diff --git a/comp-be/src/codegen/unit/mod.rs b/comp-be/src/codegen/unit/mod.rs index fea2d57..f41e7cc 100644 --- a/comp-be/src/codegen/unit/mod.rs +++ b/comp-be/src/codegen/unit/mod.rs @@ -1,7 +1,7 @@ use llvm_sys_wrapper::{Builder, LLVMValueRef}; use crate::codegen::{AatbeModule, ValueTypePair}; -use parser::ast::{BindType, PrimitiveType}; +use parser::ast::{BindType, Type}; pub mod function; pub use function::{ @@ -11,6 +11,19 @@ pub use function::{ pub mod variable; pub use variable::{alloc_variable, init_record, store_value}; +pub mod compiler; +pub use compiler::{ + CompilerContext, CompilerUnit, FunctionVisibility, Message, Query, QueryResponse, +}; + +pub mod decl; +pub use decl::decl; + +pub mod cg; +pub use cg::cg; + +pub mod generic; + #[derive(Debug, Clone)] pub enum Mutability { Immutable, @@ -31,11 +44,11 @@ impl From<&BindType> for Mutability { #[derive(Debug, Clone)] pub enum Slot { - FunctionArgument(LLVMValueRef, PrimitiveType), + FunctionArgument(LLVMValueRef, Type), Variable { mutable: Mutability, name: String, - ty: PrimitiveType, + ty: Type, value: LLVMValueRef, }, } @@ -54,6 +67,20 @@ impl Into for &Slot { } } +impl Into for Slot { + fn into(self) -> ValueTypePair { + match self { + Slot::FunctionArgument(arg, ty) => (arg, ty).into(), + Slot::Variable { + mutable: _, + name: _, + ty, + value, + } => (value, ty).into(), + } + } +} + impl Into for &Slot { fn into(self) -> LLVMValueRef { match self { @@ -77,24 +104,24 @@ impl Slot { match self { Slot::Variable { ty: - PrimitiveType::TypeRef(rec) - | PrimitiveType::NamedType { + Type::TypeRef(rec) + | Type::NamedType { name: _, - ty: Some(box PrimitiveType::TypeRef(rec)), + ty: Some(box Type::TypeRef(rec)), }, .. } => Some(rec.clone()), Slot::FunctionArgument( _arg, - PrimitiveType::TypeRef(rec) - | PrimitiveType::Pointer(box PrimitiveType::TypeRef(rec)), + Type::TypeRef(rec) + | Type::Pointer(box Type::TypeRef(rec)), ) => Some(rec.clone()), Slot::Variable { ty: - PrimitiveType::VariantType(name) - | PrimitiveType::NamedType { + Type::VariantType(name) + | Type::NamedType { name: _, - ty: Some(box PrimitiveType::VariantType(name)), + ty: Some(box Type::VariantType(name)), }, .. } => Some(name.clone()), @@ -102,13 +129,13 @@ impl Slot { } } - pub fn get_index(&self, module: &AatbeModule, name: &String) -> Option<(u32, PrimitiveType)> { + pub fn get_index(&self, module: &AatbeModule, name: &String) -> Option<(u32, Type)> { match self { Slot::Variable { ty: - PrimitiveType::NamedType { + Type::NamedType { name: _, - ty: Some(box PrimitiveType::TypeRef(record)), + ty: Some(box Type::TypeRef(record)), }, .. } => match module.typectx_ref().get_record(record) { @@ -122,25 +149,25 @@ impl Slot { pub fn load_var(&self, builder: &Builder) -> LLVMValueRef { match self { Slot::Variable { - ty: PrimitiveType::Array { .. }, + ty: Type::Array { .. }, .. } | Slot::Variable { ty: - PrimitiveType::NamedType { - ty: Some(box PrimitiveType::Array { .. }), + Type::NamedType { + ty: Some(box Type::Array { .. }), .. }, .. } => self.into(), Slot::Variable { - ty: PrimitiveType::Slice { .. }, + ty: Type::Slice { .. }, .. } | Slot::Variable { ty: - PrimitiveType::NamedType { - ty: Some(box PrimitiveType::Slice { .. }), + Type::NamedType { + ty: Some(box Type::Slice { .. }), .. }, .. @@ -152,17 +179,17 @@ impl Slot { Mutability::Constant => self.into(), _ => builder.build_load(self.into()), }, - Slot::FunctionArgument(_, PrimitiveType::Slice { .. }) => { + Slot::FunctionArgument(_, Type::Slice { .. }) => { builder.build_load(self.into()) } Slot::FunctionArgument(_, _) => self.into(), } } - pub fn var_ty(&self) -> &PrimitiveType { + pub fn var_ty(&self) -> &Type { match self { Slot::Variable { ty, .. } => match ty { - PrimitiveType::NamedType { + Type::NamedType { name: _, ty: Some(ty), } => ty, @@ -175,8 +202,8 @@ impl Slot { pub fn get_mutability(&self) -> &Mutability { match self { Slot::Variable { mutable, .. } => mutable, - Slot::FunctionArgument(_, PrimitiveType::Array { .. }) => &Mutability::Mutable, - Slot::FunctionArgument(_, PrimitiveType::Slice { .. }) => &Mutability::Mutable, + Slot::FunctionArgument(_, Type::Array { .. }) => &Mutability::Mutable, + Slot::FunctionArgument(_, Type::Slice { .. }) => &Mutability::Mutable, _ => panic!("ICE get_mutability: Not a variable {:?}", self), } } diff --git a/comp-be/src/codegen/unit/variable.rs b/comp-be/src/codegen/unit/variable.rs index d5f3add..00c5702 100644 --- a/comp-be/src/codegen/unit/variable.rs +++ b/comp-be/src/codegen/unit/variable.rs @@ -1,14 +1,16 @@ use crate::ty::infer::infer_type; use crate::{ codegen::{ - unit::{Mutability, Slot}, + builder::{base, value}, + unit::{cg::expr, CompilerContext, Message, Mutability, Query, QueryResponse, Slot}, AatbeModule, CompileError, ValueTypePair, }, fmt::AatbeFmt, ty::{record::store_named_field, LLVMTyInCtx, TypeKind}, }; -use parser::ast::{AtomKind, Expression, LValue, PrimitiveType}; +use guard::guard; +use parser::ast::{AtomKind, Expression, LValue, Type}; macro_rules! rec_name { ($name:expr, $types:expr) => {{ @@ -31,25 +33,26 @@ macro_rules! rec_name { }}; } -pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option { +pub fn alloc_variable(variable: &Expression, ctx: &CompilerContext) -> Option { match variable { Expression::Decl { - ty: PrimitiveType::NamedType { name, ty }, + ty: Type::NamedType { name, ty }, value, exterior_bind, } => { - /*let mut vtp = None; + let mut vtp = None; let ty = match ty { Some(ty) => match ty { - box PrimitiveType::GenericTypeRef(name, types) => { - let rec = rec_name!(name.clone(), types); + box Type::GenericTypeRef(name, types) => { + /*let rec = rec_name!(name.clone(), types); if !module.typectx_ref().get_record(&rec).is_ok() { module.propagate_types_in_record(name, types.clone()); } - PrimitiveType::TypeRef(rec.clone()) + Type::TypeRef(rec.clone())*/ + todo!() } - box PrimitiveType::VariantType(_) => { - if let Some(e) = value { + box Type::VariantType(_) => { + /*if let Some(e) = value { let pair = module.codegen_expr(e)?; let ty = pair.prim().clone(); @@ -57,7 +60,8 @@ pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option ty } else { unreachable!(); - } + }*/ + todo!() } _ => *ty.clone(), }, @@ -69,18 +73,19 @@ pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option values: _, } = e { - let rec = rec_name!(record.clone(), types); + /*let rec = rec_name!(record.clone(), types); if types.len() == 0 { - PrimitiveType::TypeRef(rec.clone()) + Type::TypeRef(rec.clone()) } else { if !module.typectx_ref().get_record(&rec).is_ok() { module.propagate_types_in_record(record, types.clone()); } - PrimitiveType::TypeRef(rec.clone()) - } + Type::TypeRef(rec.clone()) + }*/ + todo!() } else { - let pair = module.codegen_expr(e)?; + let pair = expr::cg(e, ctx)?; let ty = pair.prim().clone(); vtp = Some(pair); @@ -90,10 +95,10 @@ pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option unreachable!(); } } - };*/ + }; - /*if let PrimitiveType::Newtype(..) | PrimitiveType::VariantType(..) = ty { - module.push_in_scope( + if let Type::Newtype(..) | Type::VariantType(..) = ty { + /*module.push_in_scope( name, Slot::Variable { mutable: Mutability::from(exterior_bind), @@ -102,52 +107,45 @@ pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option value: *vtp.unwrap(), }, ); - return Some(ty.clone()); - }*/ + return Some(ty.clone());*/ + todo!() + } if value.is_none() { - let ty = ty.as_ref().expect("ICE: Ty none for none value"); - let val_ref = module - .llvm_builder_ref() - .build_alloca_with_name(ty.llvm_ty_in_ctx(module), name.as_ref()); + let val_ref = base::alloca_with_name(ctx, ty.llvm_ty_in_ctx(ctx), &name); - module.push_in_scope( - name, + ctx.dispatch(Message::PushInScope( + name.clone(), Slot::Variable { mutable: Mutability::from(exterior_bind), name: name.clone(), - ty: *ty.clone(), + ty: ty.clone(), value: val_ref, }, - ); + )); - return Some(*ty.clone()); + return Some(ty); } // TODO: Variants, generic records - let ty = infer_type( - module, - &*(value.as_ref().expect("ICE: Value cannot be none")), - ); + let ty = infer_type(ctx, &*(value.as_ref().expect("ICE: Value cannot be none"))); if ty.is_none() { panic!("ICE: ty is none {:?} value", value); } let (ty, constant) = ty.unwrap(); - let var_ref = module - .llvm_builder_ref() - .build_alloca_with_name(ty.llvm_ty_in_ctx(module), name.as_ref()); + let var_ref = base::alloca_with_name(ctx, ty.llvm_ty_in_ctx(ctx), &name); - module.push_in_scope( - name, + ctx.dispatch(Message::PushInScope( + name.clone(), Slot::Variable { mutable: Mutability::from(exterior_bind), name: name.clone(), ty: ty.clone(), value: var_ref, }, - ); + )); if let Some(e) = value { if let box Expression::RecordInit { @@ -156,7 +154,7 @@ pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option values, } = e { - if ty.inner() != &PrimitiveType::TypeRef(rec_name!(record.clone(), types)) { + /*if ty.inner() != &Type::TypeRef(rec_name!(record.clone(), types)) { module.add_error(CompileError::ExpectedType { expected_ty: ty.inner().fmt(), found_ty: record.clone(), @@ -171,11 +169,12 @@ pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option types: types.clone(), values: values.to_vec(), }, - ); + );*/ + todo!() } else { match ty.clone() { - PrimitiveType::Array { ref ty, len } if !constant => { - if let box Expression::Atom(AtomKind::Array(exprs)) = e { + Type::Array { ref ty, len } if !constant => { + /*if let box Expression::Atom(AtomKind::Array(exprs)) = e { let vals = exprs .iter() .filter_map(|e| module.codegen_expr(e)) @@ -207,20 +206,22 @@ pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option }); } else { panic!("ICE: arr ty not arr val"); - } + }*/ + todo!() } _ => { - let val = module.codegen_expr(e)?; + let val = expr::cg(e, ctx)?; if val.prim() != ty.inner() { - module.add_error(CompileError::ExpectedType { + /*module.add_error(CompileError::ExpectedType { expected_ty: ty.inner().fmt(), found_ty: val.prim().fmt(), value: value.as_ref().unwrap().fmt(), - }); + });*/ + todo!("Error") }; - module.llvm_builder_ref().build_store(*val, var_ref); + base::store(ctx, *val, var_ref); } }; } @@ -236,7 +237,8 @@ pub fn init_record( lval: &LValue, rec: &Expression, ) -> Option { - fn get_lval(module: &mut AatbeModule, lvalue: &LValue) -> Option { + todo!() + /*fn get_lval(module: &mut AatbeModule, lvalue: &LValue) -> Option { match lvalue { LValue::Ident(name) => match module.get_var(name) { None => panic!("Cannot find variable {}", name), @@ -250,7 +252,7 @@ pub fn init_record( if let Some(val) = val { match val.ty() { - TypeKind::Primitive(PrimitiveType::Str) => { + TypeKind::Primitive(Type::Str) => { let gep = module .llvm_builder_ref() .build_inbounds_gep(*val, &mut [*index]); @@ -258,7 +260,7 @@ pub fn init_record( Some( ( module.llvm_builder_ref().build_load(gep), - PrimitiveType::Char, + Type::Char, ) .into(), ) @@ -325,64 +327,69 @@ pub fn init_record( } }), _ => unreachable!(), - } + }*/ } pub fn store_value( - module: &mut AatbeModule, + ctx: &CompilerContext, lval: &LValue, value: &Expression, ) -> Option { - fn get_lval(module: &mut AatbeModule, lvalue: &LValue) -> Option { + fn get_lval(ctx: &CompilerContext, lvalue: &LValue) -> Option { match lvalue { - LValue::Ident(name) => match module.get_var(name) { - None => panic!("Cannot find variable {}", name), - Some(var) => { - match var.get_mutability() { - Mutability::Mutable | Mutability::Global => {} - _ => panic!("Cannot reassign to immutable/constant {}", name), - }; - Some(var.into()) - } - }, - LValue::Accessor(parts) => Some(module.get_interior_pointer(parts.clone())?), + LValue::Ident(name) => { + guard!(let QueryResponse::Slot(Some(slot)) = ctx.query(Query::Slot(name)) else { panic!("Cannot find variable {}", name) }); + match slot.get_mutability() { + Mutability::Mutable | Mutability::Global => {} + _ => panic!("Cannot reassign to immutable/constant {}", name), + }; + Some(slot.into()) + } + LValue::Accessor(parts) => todo!(), //Some(module.get_interior_pointer(parts.clone())?), LValue::Deref(_) => unimplemented!("{:?}", lvalue), LValue::Index(lval, index) => { - let val = get_lval(module, lval); - let index = module.codegen_expr(index).expect("ICE store_value index"); + let val = get_lval(ctx, lval); + let index = expr::cg(index, ctx)?; if let Some(val) = val { match val.ty() { - TypeKind::Primitive(PrimitiveType::Str) => { - let load = module.llvm_builder_ref().build_load(*val); - let gep = module - .llvm_builder_ref() - .build_inbounds_gep(load, &mut [*index]); - - Some((gep, PrimitiveType::Char).into()) - } - TypeKind::Primitive(PrimitiveType::Array { ty: box ty, .. }) => { - let gep = module.llvm_builder_ref().build_inbounds_gep( - *val, - &mut [module.llvm_context_ref().SInt32(0), *index], - ); - - Some((gep, ty).into()) - } - TypeKind::Primitive(PrimitiveType::Slice { ty: box ty }) => { - let arr = module.llvm_builder_ref().build_struct_gep(*val, 0); - let gep = module.llvm_builder_ref().build_inbounds_gep( - module.llvm_builder_ref().build_load(arr), - &mut [module.llvm_context_ref().SInt32(0), *index], - ); - - Some((gep, ty).into()) - } + TypeKind::Primitive(Type::Str) => Some( + ( + base::inbounds_gep(ctx, base::load(ctx, *val), &mut vec![*index]), + Type::Char, + ) + .into(), + ), + TypeKind::Primitive(Type::Array { ty: box ty, .. }) => Some( + ( + base::inbounds_gep( + ctx, + *val, + &mut vec![*value::s32(ctx, 0), *index], + ), + ty, + ) + .into(), + ), + TypeKind::Primitive(Type::Slice { ty: box ty }) => Some( + ( + base::inbounds_gep( + ctx, + base::load(ctx, base::struct_gep(ctx, *val, 0)), + &mut vec![*value::s32(ctx, 0), *index], + ), + ty, + ) + .into(), + ), _ => { + // TODO: Error + /* module.add_error(CompileError::NotIndexable { ty: val.prim().fmt(), lval: lvalue.fmt(), - }); + });*/ + todo!(); None } } @@ -393,19 +400,21 @@ pub fn store_value( } } - get_lval(module, lval).and_then(|var| { - let val = module.codegen_expr(value)?; + get_lval(ctx, lval).and_then(|var| { + let val = expr::cg(value, ctx)?; if var.prim() != val.prim().inner() { - module.add_error(CompileError::AssignMismatch { + // TODO: Error + todo!("ERROR"); + /*module.add_error(CompileError::AssignMismatch { expected_ty: var.prim().fmt(), found_ty: val.prim().fmt(), value: value.fmt(), var: lval.fmt(), - }); + });*/ None } else { - Some((module.llvm_builder_ref().build_store(*val, *var), var.ty()).into()) + Some((base::store(ctx, *val, *var), var.ty()).into()) } }) } diff --git a/comp-be/src/fmt.rs b/comp-be/src/fmt.rs index ebd3873..279bf5c 100644 --- a/comp-be/src/fmt.rs +++ b/comp-be/src/fmt.rs @@ -1,12 +1,23 @@ use parser::ast::{ - AtomKind, Boolean, Expression, FloatSize, FunctionType, IntSize, LValue, PrimitiveType, + AtomKind, Boolean, Expression, FloatSize, FunctionType, IdentPath, IntSize, LValue, + Type, }; pub trait AatbeFmt { fn fmt(self) -> String; } -impl AatbeFmt for PrimitiveType { +impl AatbeFmt for &IdentPath { + fn fmt(self) -> String { + match self { + IdentPath::Local(path) => path.clone(), + IdentPath::Module(path) => path.join("::"), + IdentPath::Root(path) => format!("::{}", path.join("::")), + } + } +} + +impl AatbeFmt for Type { fn fmt(self) -> String { (&self).fmt() } @@ -20,7 +31,7 @@ impl AatbeFmt for FunctionType { impl AatbeFmt for &FunctionType { fn fmt(self) -> String { - let params = if self.params.len() == 1 && self.params[0] == PrimitiveType::Unit { + let params = if self.params.len() == 1 && self.params[0] == Type::Unit { String::from("()") } else { format!( @@ -39,43 +50,43 @@ impl AatbeFmt for &FunctionType { } } -impl AatbeFmt for &PrimitiveType { +impl AatbeFmt for &Type { fn fmt(self) -> String { match self { - PrimitiveType::Str => String::from("str"), - PrimitiveType::Bool => String::from("bool"), - PrimitiveType::Int(bits) => match bits { + Type::Str => String::from("str"), + Type::Bool => String::from("bool"), + Type::Int(bits) => match bits { IntSize::Bits8 => String::from("i8"), IntSize::Bits16 => String::from("i16"), IntSize::Bits32 => String::from("i32"), IntSize::Bits64 => String::from("i64"), }, - PrimitiveType::UInt(bits) => match bits { + Type::UInt(bits) => match bits { IntSize::Bits8 => String::from("u8"), IntSize::Bits16 => String::from("u16"), IntSize::Bits32 => String::from("u32"), IntSize::Bits64 => String::from("u64"), }, - PrimitiveType::Float(bits) => match bits { + Type::Float(bits) => match bits { FloatSize::Bits32 => String::from("f32"), FloatSize::Bits64 => String::from("f64"), }, - PrimitiveType::Varargs => String::from("..."), - PrimitiveType::NamedType { + Type::Varargs => String::from("..."), + Type::NamedType { name: _, ty: Some(ty), } => ty.clone().fmt(), - PrimitiveType::Pointer(ty) => format!("{}*", ty.clone().fmt()), - PrimitiveType::Char => String::from("char"), - PrimitiveType::TypeRef(ty) => ty.clone(), - PrimitiveType::Array { ty, len } => { + Type::Pointer(ty) => format!("{}*", ty.clone().fmt()), + Type::Char => String::from("char"), + Type::TypeRef(ty) => ty.clone(), + Type::Array { ty, len } => { format!("{}[{}]", ty.clone().fmt(), len.to_string()) } - PrimitiveType::Unit => String::from("()"), - PrimitiveType::Ref(ty) => format!("&{}", ty.clone().fmt()), - PrimitiveType::Function(func) => func.fmt(), - PrimitiveType::Slice { ty } => format!("{}[]", ty.clone().fmt()), - PrimitiveType::GenericTypeRef(name, types) => format!( + Type::Unit => String::from("()"), + Type::Ref(ty) => format!("&{}", ty.clone().fmt()), + Type::Function(func) => func.fmt(), + Type::Slice { ty } => format!("{}[]", ty.clone().fmt()), + Type::GenericTypeRef(name, types) => format!( "{}[{}]", name, types @@ -84,8 +95,8 @@ impl AatbeFmt for &PrimitiveType { .collect::>() .join(", ") ), - PrimitiveType::Newtype(name) => name.clone(), - PrimitiveType::VariantType(name) => name.clone(), + Type::Newtype(name) => name.clone(), + Type::VariantType(name) => name.clone(), _ => panic!("ICE fmt {:?}", self), } } @@ -94,8 +105,8 @@ impl AatbeFmt for &PrimitiveType { impl AatbeFmt for &AtomKind { fn fmt(self) -> String { match self { - AtomKind::StringLiteral(lit) => format!("\"{}\"", lit), - AtomKind::CharLiteral(lit) => format!("{}", lit), + AtomKind::StringLiteral(lit) => format!("{:?}", lit), + AtomKind::CharLiteral(lit) => format!("{:?}", lit), AtomKind::Integer(val, ty) => format!("{}{}", val, ty.fmt()), AtomKind::Floating(val, ty) => format!("{}{}", val, ty.fmt()), AtomKind::Bool(Boolean::True) => String::from("true"), @@ -155,7 +166,7 @@ impl AatbeFmt for &Expression { ), Expression::Call { name, types, args } => format!( "{}{} {}", - name, + name.fmt(), if types.len() > 0 { format!( "[{}]", @@ -175,16 +186,20 @@ impl AatbeFmt for &Expression { ), Expression::Function { name, - export, + public, ty: ty @ FunctionType { ext, .. }, .. } => format!( "{}{}fn {}{}", - if *export { "exp " } else { "" }, + if *public { "public " } else { "" }, if *ext { "ext " } else { "" }, name, ty.fmt(), ), + Expression::Assign { + lval, + value: box value, + } => format!("{} = {}", lval.fmt(), value.fmt()), _ => panic!("ICE fmt {:?}", self), } } diff --git a/comp-be/src/lib.rs b/comp-be/src/lib.rs index 8ffc12a..7972c04 100644 --- a/comp-be/src/lib.rs +++ b/comp-be/src/lib.rs @@ -2,11 +2,11 @@ box_syntax, box_patterns, type_ascription, - vec_remove_item, option_expect_none, or_patterns, bindings_after_at, - type_alias_impl_trait + type_alias_impl_trait, + in_band_lifetimes, )] pub mod codegen; diff --git a/comp-be/src/ty/aggregate.rs b/comp-be/src/ty/aggregate.rs index 5d20d0e..b027520 100644 --- a/comp-be/src/ty/aggregate.rs +++ b/comp-be/src/ty/aggregate.rs @@ -1,5 +1,5 @@ use crate::{ - codegen::{AatbeModule, ValueTypePair}, + codegen::{unit::CompilerContext, ValueTypePair}, ty::TypeResult, }; @@ -8,28 +8,28 @@ use llvm_sys_wrapper::LLVMValueRef; pub trait Aggregate { fn gep_indexed_field( &self, - module: &AatbeModule, + ctx: &CompilerContext, index: u32, aggregate_ref: LLVMValueRef, ) -> TypeResult; fn gep_named_field( &self, - module: &AatbeModule, + ctx: &CompilerContext, name: &String, aggregate_ref: LLVMValueRef, ) -> TypeResult; fn gep_field( &self, - module: &AatbeModule, + ctx: &CompilerContext, name: &String, aggregate_ref: LLVMValueRef, ) -> TypeResult { if let Ok(index) = name.parse::() { - self.gep_indexed_field(module, index, aggregate_ref) + self.gep_indexed_field(ctx, index, aggregate_ref) } else { - self.gep_named_field(module, name, aggregate_ref) + self.gep_named_field(ctx, name, aggregate_ref) } } } diff --git a/comp-be/src/ty/infer.rs b/comp-be/src/ty/infer.rs index 83eff39..bf0e95c 100644 --- a/comp-be/src/ty/infer.rs +++ b/comp-be/src/ty/infer.rs @@ -1,10 +1,15 @@ -use parser::ast::{AtomKind, Expression, PrimitiveType}; +use parser::ast::{AtomKind, Expression, IdentPath, Type}; -use crate::codegen::{unit::function::find_function, AatbeModule}; +use guard::guard; -pub fn infer_type(module: &AatbeModule, expr: &Expression) -> Option<(PrimitiveType, bool)> { +use crate::{ + codegen::unit::{function::find_function, CompilerContext, Query, QueryResponse}, + prefix, +}; + +pub fn infer_type(ctx: &CompilerContext, expr: &Expression) -> Option<(Type, bool)> { match expr { - Expression::Atom(atom) => infer_atom(module, &atom), + Expression::Atom(atom) => infer_atom(ctx, &atom), Expression::Call { name, args: call_args, @@ -12,7 +17,7 @@ pub fn infer_type(module: &AatbeModule, expr: &Expression) -> Option<(PrimitiveT } => { let args = call_args .iter() - .filter_map(|e| infer_type(module, e)) + .filter_map(|e| infer_type(ctx, e)) .map(|ty| ty.0) .collect::>(); @@ -20,37 +25,51 @@ pub fn infer_type(module: &AatbeModule, expr: &Expression) -> Option<(PrimitiveT return None; } - let group = module.get_func_group(name)?; - let func = find_function(group, &args)?; + let prefix = |path: &IdentPath| -> Vec { + match path { + IdentPath::Local(name) => prefix!(call ctx, name.clone()), + IdentPath::Module(name) => prefix!(call module ctx, name.clone()), + _ => todo!(), + } + }; - return Some((func.ret_ty().clone(), false)); + find_function( + match ctx.query(Query::FunctionGroup(prefix(name).join("::"))) { + QueryResponse::FunctionGroup(Some(group)) => group, + QueryResponse::FunctionGroup(None) => todo!("no function found"), + _ => unreachable!(), + }, + &args, + ) + .map(|func| Some((func.upgrade().expect("ICE").ret_ty().clone(), false))) + .flatten() } Expression::RecordInit { record, types, .. } if types.len() == 0 => { - Some((PrimitiveType::TypeRef(record.clone()), true)) + Some((Type::TypeRef(record.clone()), true)) } Expression::RecordInit { record, types, .. } => Some(( - PrimitiveType::GenericTypeRef(record.clone(), types.clone()), + Type::GenericTypeRef(record.clone(), types.clone()), true, )), _ => unimplemented!("{:?}", expr), } } -pub fn infer_atom(module: &AatbeModule, atom: &AtomKind) -> Option<(PrimitiveType, bool)> { +pub fn infer_atom(ctx: &CompilerContext, atom: &AtomKind) -> Option<(Type, bool)> { match atom { AtomKind::Integer(_, sz) => Some((sz.clone(), true)), - AtomKind::Unit => Some((PrimitiveType::Unit, true)), - AtomKind::StringLiteral(_) => Some((PrimitiveType::Str, true)), - AtomKind::CharLiteral(_) => Some((PrimitiveType::Char, true)), - AtomKind::Bool(_) => Some((PrimitiveType::Bool, true)), - AtomKind::SymbolLiteral(s) => Some((PrimitiveType::Symbol(s.clone()), true)), + AtomKind::Unit => Some((Type::Unit, true)), + AtomKind::StringLiteral(_) => Some((Type::Str, true)), + AtomKind::CharLiteral(_) => Some((Type::Char, true)), + AtomKind::Bool(_) => Some((Type::Bool, true)), + AtomKind::SymbolLiteral(s) => Some((Type::Symbol(s.clone()), true)), AtomKind::Array(vals) => { - let fst = vals.first().and_then(|v| infer_type(module, v)); - if !vals.iter().all(|v| infer_type(module, v) == fst) { + let fst = vals.first().and_then(|v| infer_type(ctx, v)); + if !vals.iter().all(|v| infer_type(ctx, v) == fst) { None } else if let Some((ty, constant)) = fst { Some(( - PrimitiveType::Array { + Type::Array { ty: box ty, len: vals.len() as u32, }, @@ -61,12 +80,12 @@ pub fn infer_atom(module: &AatbeModule, atom: &AtomKind) -> Option<(PrimitiveTyp } } AtomKind::Ident(name) => { - let var = module.get_var(name)?; - - Some((var.var_ty().clone(), false)) + guard!(let QueryResponse::Slot(slot) = ctx.query(Query::Slot(name)) else { unreachable!() }); + let slot = slot?; + Some((slot.var_ty().clone(), false).into()) } AtomKind::Cast(_, ty) => Some((ty.clone(), false)), - AtomKind::Parenthesized(box expr) => infer_type(module, expr), + AtomKind::Parenthesized(box expr) => infer_type(ctx, expr), _ => unimplemented!("{:?}", atom), } } diff --git a/comp-be/src/ty/mod.rs b/comp-be/src/ty/mod.rs index 3c35dbc..b817ead 100644 --- a/comp-be/src/ty/mod.rs +++ b/comp-be/src/ty/mod.rs @@ -1,9 +1,9 @@ use crate::{ - codegen::{AatbeModule, ValueTypePair}, + codegen::{unit::CompilerContext, AatbeModule, ValueTypePair}, fmt::AatbeFmt, ty::variant::{Variant, VariantType}, }; -use parser::ast::{FloatSize, FunctionType, IntSize, PrimitiveType}; +use parser::ast::{FloatSize, FunctionType, IntSize, Type}; use llvm_sys_wrapper::{LLVMFunctionType, LLVMTypeRef, LLVMValueRef}; @@ -21,7 +21,7 @@ pub use record::Record; #[derive(Debug)] pub enum TypeError { NotFound(String), - NotFoundPrim(PrimitiveType), + NotFoundPrim(Type), VariantOOB(String, u32), RecordIndexOOB(String, u32), NamedOnVariant(String, String), @@ -32,13 +32,13 @@ pub type TypeResult = Result; pub enum TypeKind { RecordType(Record), - Primitive(PrimitiveType), + Primitive(Type), Typedef(TypedefKind), } pub enum TypedefKind { Opaque(LLVMTypeRef), - Newtype(LLVMTypeRef, PrimitiveType), + Newtype(LLVMTypeRef, Type), VariantType(VariantType), } @@ -65,10 +65,10 @@ impl fmt::Debug for TypedefKind { } impl LLVMTyInCtx for TypeKind { - fn llvm_ty_in_ctx(&self, module: &AatbeModule) -> LLVMTypeRef { + fn llvm_ty_in_ctx(&self, ctx: &CompilerContext) -> LLVMTypeRef { match self { - TypeKind::RecordType(record) => record.llvm_ty_in_ctx(module), - TypeKind::Primitive(primitive) => primitive.llvm_ty_in_ctx(module), + TypeKind::RecordType(record) => record.llvm_ty_in_ctx(ctx), + TypeKind::Primitive(primitive) => primitive.llvm_ty_in_ctx(ctx), TypeKind::Typedef(TypedefKind::Opaque(ty)) => *ty, TypeKind::Typedef(TypedefKind::Newtype(ty, _)) => *ty, TypeKind::Typedef(TypedefKind::VariantType(VariantType { ty, .. })) => *ty, @@ -136,17 +136,17 @@ impl TypeContext { } } - pub fn get_aggregate_from_prim(&self, prim: &PrimitiveType) -> Option<&dyn Aggregate> { + pub fn get_aggregate_from_prim(&self, prim: &Type) -> Option<&dyn Aggregate> { match prim { - PrimitiveType::TypeRef(name) => match self.types.get(name) { + Type::TypeRef(name) => match self.types.get(name) { Some(TypeKind::RecordType(record)) => Some(record as &dyn Aggregate), _ => None, }, - PrimitiveType::VariantType(name) => match self.get_variant(name) { + Type::VariantType(name) => match self.get_variant(name) { Some(variant) => Some(variant as &dyn Aggregate), _ => None, }, - PrimitiveType::Variant { variant, .. } => match self.get_variant(variant) { + Type::Variant { variant, .. } => match self.get_variant(variant) { Some(variant) => Some(variant as &dyn Aggregate), _ => None, }, @@ -212,7 +212,8 @@ impl TypeContext { fields: Vec, reference: LLVMValueRef, ) -> TypeResult { - match fields.as_slice() { + todo!() + /*match fields.as_slice() { [field] => ty.gep_field(module, field, reference), [field, subfields @ ..] => { let field = ty.gep_field(module, field, reference)?; @@ -224,37 +225,37 @@ impl TypeContext { self.gep_fields(module, ty, subfields.to_vec(), *field) } [] => unreachable!(), - } + }*/ } } pub trait LLVMTyInCtx { - fn llvm_ty_in_ctx(&self, module: &AatbeModule) -> LLVMTypeRef; + fn llvm_ty_in_ctx(&self, ctx: &CompilerContext) -> LLVMTypeRef; } impl LLVMTyInCtx for FunctionType { - fn llvm_ty_in_ctx(&self, module: &AatbeModule) -> LLVMTypeRef { - let ret = self.ret_ty.llvm_ty_in_ctx(module); + fn llvm_ty_in_ctx(&self, ctx: &CompilerContext) -> LLVMTypeRef { + let ret = self.ret_ty.llvm_ty_in_ctx(ctx); let mut varargs = false; let ext = self.ext; let mut param_types = self .params .iter() .filter_map(|t| match t { - PrimitiveType::TypeRef(name) => { + /*Type::TypeRef(name) => { Some(module.typectx_ref().get_type(name)?.llvm_ty_in_ctx(module)) - } - PrimitiveType::Symbol(_) => None, - PrimitiveType::Unit => None, - PrimitiveType::Varargs => { + }*/ + Type::Symbol(_) => None, + Type::Unit => None, + Type::Varargs => { varargs = true; None } - PrimitiveType::NamedType { - ty: Some(box PrimitiveType::Slice { ty: box ty }), + /*Type::NamedType { + ty: Some(box Type::Slice { ty: box ty }), .. } - | PrimitiveType::Slice { ty: box ty } + | Type::Slice { ty: box ty } if ext => { Some( @@ -262,8 +263,8 @@ impl LLVMTyInCtx for FunctionType { .llvm_context_ref() .PointerType(ty.llvm_ty_in_ctx(module)), ) - } - _ => Some(t.llvm_ty_in_ctx(module)), + }*/ + _ => Some(t.llvm_ty_in_ctx(ctx)), }) .collect::>(); @@ -278,50 +279,50 @@ impl LLVMTyInCtx for FunctionType { } } -impl LLVMTyInCtx for PrimitiveType { - fn llvm_ty_in_ctx(&self, module: &AatbeModule) -> LLVMTypeRef { - let ctx = module.llvm_context_ref(); +impl LLVMTyInCtx for Type { + fn llvm_ty_in_ctx(&self, mctx: &CompilerContext) -> LLVMTypeRef { + let ctx = mctx.llvm_context; match self { - PrimitiveType::Slice { ty } => ctx + Type::Slice { ty } => ctx .StructType( &mut vec![ - ctx.PointerType(ctx.ArrayType(ty.llvm_ty_in_ctx(module), 0)), + ctx.PointerType(ctx.ArrayType(ty.llvm_ty_in_ctx(mctx), 0)), ctx.Int32Type(), ], false, ) .as_ref(), - PrimitiveType::Array { ty, len } => ctx.ArrayType(ty.llvm_ty_in_ctx(module), *len), - PrimitiveType::Ref(r) => ctx.PointerType(r.llvm_ty_in_ctx(module)), - PrimitiveType::Unit => ctx.VoidType(), - PrimitiveType::Bool => ctx.Int1Type(), - PrimitiveType::Int(IntSize::Bits8) | PrimitiveType::UInt(IntSize::Bits8) => { + Type::Array { ty, len } => ctx.ArrayType(ty.llvm_ty_in_ctx(mctx), *len), + Type::Ref(r) => ctx.PointerType(r.llvm_ty_in_ctx(mctx)), + Type::Unit => ctx.VoidType(), + Type::Bool => ctx.Int1Type(), + Type::Int(IntSize::Bits8) | Type::UInt(IntSize::Bits8) => { ctx.Int8Type() } - PrimitiveType::Int(IntSize::Bits16) | PrimitiveType::UInt(IntSize::Bits16) => { + Type::Int(IntSize::Bits16) | Type::UInt(IntSize::Bits16) => { ctx.Int16Type() } - PrimitiveType::Int(IntSize::Bits32) | PrimitiveType::UInt(IntSize::Bits32) => { + Type::Int(IntSize::Bits32) | Type::UInt(IntSize::Bits32) => { ctx.Int32Type() } - PrimitiveType::Int(IntSize::Bits64) | PrimitiveType::UInt(IntSize::Bits64) => { + Type::Int(IntSize::Bits64) | Type::UInt(IntSize::Bits64) => { ctx.Int64Type() } - PrimitiveType::Float(FloatSize::Bits32) => ctx.FloatType(), - PrimitiveType::Float(FloatSize::Bits64) => ctx.DoubleType(), - PrimitiveType::Str => ctx.CharPointerType(), - PrimitiveType::Char => ctx.Int8Type(), - PrimitiveType::NamedType { + Type::Float(FloatSize::Bits32) => ctx.FloatType(), + Type::Float(FloatSize::Bits64) => ctx.DoubleType(), + Type::Str => ctx.CharPointerType(), + Type::Char => ctx.Int8Type(), + Type::NamedType { name: _, ty: Some(ty), - } => ty.llvm_ty_in_ctx(module), - PrimitiveType::TypeRef(name) => module + } => ty.llvm_ty_in_ctx(mctx), + /*Type::TypeRef(name) => module .typectx_ref() .llvm_ty_in_ctx(name) .expect(format!("Type {} is not declared", name).as_str()) .llvm_ty_in_ctx(module), - PrimitiveType::GenericTypeRef(name, types) => { + Type::GenericTypeRef(name, types) => { let rec = format!( "{}[{}]", name, @@ -338,17 +339,17 @@ impl LLVMTyInCtx for PrimitiveType { .expect(format!("Type {} is not declared", rec).as_str()) .llvm_ty_in_ctx(module) } - PrimitiveType::Pointer(ty) => match ty { - box PrimitiveType::Char => ctx.CharPointerType(), - tr @ box PrimitiveType::TypeRef(_) => ctx.PointerType(tr.llvm_ty_in_ctx(module)), - tr @ box PrimitiveType::UInt(_) => ctx.PointerType(tr.llvm_ty_in_ctx(module)), - tr @ box PrimitiveType::Int(_) => ctx.PointerType(tr.llvm_ty_in_ctx(module)), - box PrimitiveType::Str => ctx.PointerType(ctx.Int8PointerType()), - box PrimitiveType::Pointer(box ty) => ctx.PointerType(ty.llvm_ty_in_ctx(module)), + Type::Pointer(ty) => match ty { + box Type::Char => ctx.CharPointerType(), + tr @ box Type::TypeRef(_) => ctx.PointerType(tr.llvm_ty_in_ctx(module)), + tr @ box Type::UInt(_) => ctx.PointerType(tr.llvm_ty_in_ctx(module)), + tr @ box Type::Int(_) => ctx.PointerType(tr.llvm_ty_in_ctx(module)), + box Type::Str => ctx.PointerType(ctx.Int8PointerType()), + box Type::Pointer(box ty) => ctx.PointerType(ty.llvm_ty_in_ctx(module)), _ => panic!("llvm_ty_in_ctx {:?}", ty), }, - PrimitiveType::Function(ty) => ty.llvm_ty_in_ctx(module), - PrimitiveType::Newtype(name) => module + Type::Function(ty) => ty.llvm_ty_in_ctx(module), + Type::Newtype(name) => module .typectx_ref() .get_type(&name) .map(|ty| match ty { @@ -356,19 +357,17 @@ impl LLVMTyInCtx for PrimitiveType { _ => unreachable!(), }) .expect(format!("Cannot find type for {:?}", self).as_ref()), - PrimitiveType::Variant { variant, .. } => { + Type::Variant { variant, .. } => { module.typectx_ref().get_variant(variant).expect("ICE").ty } - PrimitiveType::VariantType(variant) => { + Type::VariantType(variant) => { module .typectx_ref() .get_parent_for_variant(variant) .expect("ICE") .ty - } - PrimitiveType::Box(box val) => module - .llvm_context_ref() - .PointerType(val.llvm_ty_in_ctx(module)), + }*/ + Type::Box(box val) => ctx.PointerType(val.llvm_ty_in_ctx(mctx)), _ => panic!("ICE: llvm_ty_in_ctx {:?}", self), } } diff --git a/comp-be/src/ty/record.rs b/comp-be/src/ty/record.rs index 7534987..298ec76 100644 --- a/comp-be/src/ty/record.rs +++ b/comp-be/src/ty/record.rs @@ -1,8 +1,8 @@ use crate::{ - codegen::{builder::core, AatbeModule, ValueTypePair}, + codegen::{builder::base, unit::CompilerContext, AatbeModule, ValueTypePair}, ty::{Aggregate, LLVMTyInCtx, TypeError, TypeResult}, }; -use parser::ast::PrimitiveType; +use parser::ast::Type; use llvm_sys_wrapper::{LLVMTypeRef, LLVMValueRef, Struct}; use std::collections::HashMap; @@ -12,15 +12,15 @@ pub struct Record { name: String, inner: Struct, body: HashMap, - types: HashMap, + types: HashMap, } impl Record { - pub fn new(module: &AatbeModule, name: &String, types: &Vec) -> Self { + pub fn new(module: &AatbeModule, name: &String, types: &Vec) -> Self { let mut body = HashMap::new(); let mut types_map = HashMap::new(); types.iter().enumerate().for_each(|(index, ty)| match ty { - PrimitiveType::NamedType { name, ty: Some(ty) } => { + Type::NamedType { name, ty: Some(ty) } => { body.insert(name.clone(), index as u32); types_map.insert(index as u32, *ty.clone()); } @@ -29,22 +29,22 @@ impl Record { Self { name: name.clone(), - inner: Struct::new_with_name(module.llvm_context_ref().as_ref(), name.as_ref()), + inner: Struct::new_with_name(module.llvm_context_ref().as_ref(), &name), body, types: types_map, } } - pub fn set_body(&self, module: &AatbeModule, types: &Vec) { + pub fn set_body(&self, ctx: &CompilerContext, types: &Vec) { let mut types = types .iter() - .map(|ty| ty.llvm_ty_in_ctx(module)) + .map(|ty| ty.llvm_ty_in_ctx(ctx)) .collect::>(); self.inner.set_body(&mut types, false); } - pub fn get_field_index_ty(&self, name: &String) -> Option<(u32, PrimitiveType)> { + pub fn get_field_index_ty(&self, name: &String) -> Option<(u32, Type)> { let idx = self.body.get(name).map(|i| *i); (idx, self.types.get(&idx?).map(|i| i.clone())).transpose() } @@ -57,12 +57,12 @@ impl Record { impl Aggregate for Record { fn gep_indexed_field( &self, - module: &AatbeModule, + ctx: &CompilerContext, index: u32, aggregate_ref: LLVMValueRef, ) -> TypeResult { Ok(( - core::struct_gep(module, aggregate_ref, index), + base::struct_gep(ctx, aggregate_ref, index), self.types .get(&index) .ok_or(TypeError::RecordIndexOOB(self.name.clone(), index))? @@ -73,7 +73,7 @@ impl Aggregate for Record { fn gep_named_field( &self, - module: &AatbeModule, + ctx: &CompilerContext, name: &String, aggregate_ref: LLVMValueRef, ) -> TypeResult { @@ -84,7 +84,7 @@ impl Aggregate for Record { )), Some(index) => { let ty = self.types.get(index).cloned().unwrap(); - let gep = core::struct_gep(module, aggregate_ref, *index); + let gep = base::struct_gep(ctx, aggregate_ref, *index); Ok((gep, ty).into()) } } @@ -92,19 +92,19 @@ impl Aggregate for Record { } pub fn store_named_field( - module: &AatbeModule, + ctx: &CompilerContext, struct_ref: LLVMValueRef, rec_name: &String, rec: &Record, name: &String, value: ValueTypePair, -) -> Result<(), PrimitiveType> { +) -> Result<(), Type> { let index = rec .get_field_index_ty(name) .expect(format!("Cannot find field {:?} in {:?}\0", name, rec.name).as_str()); - let gep = core::struct_gep_with_name( - module, + let gep = base::struct_gep_with_name( + ctx, struct_ref, index.0, format!("{}.{}\0", rec_name, name).as_str(), @@ -113,13 +113,13 @@ pub fn store_named_field( if value.prim() != &index.1 { Err(index.1) } else { - module.llvm_builder_ref().build_store(*value, gep); + base::store(ctx, *value, gep); Ok(()) } } impl LLVMTyInCtx for &Record { - fn llvm_ty_in_ctx(&self, _module: &AatbeModule) -> LLVMTypeRef { + fn llvm_ty_in_ctx(&self, _ctx: &CompilerContext) -> LLVMTypeRef { self.inner.as_ref() } } diff --git a/comp-be/src/ty/size.rs b/comp-be/src/ty/size.rs index c32d663..69e861e 100644 --- a/comp-be/src/ty/size.rs +++ b/comp-be/src/ty/size.rs @@ -1,26 +1,26 @@ -use parser::ast::{IntSize, PrimitiveType, TypeKind}; +use parser::ast::{IntSize, Type, TypeKind}; pub trait AatbeSizeOf { fn size_of(&self) -> usize; fn smallest(&self) -> usize; } -impl AatbeSizeOf for PrimitiveType { +impl AatbeSizeOf for Type { fn size_of(&self) -> usize { match self { - PrimitiveType::UInt(IntSize::Bits8) => 1, - PrimitiveType::UInt(IntSize::Bits16) => 2, - PrimitiveType::UInt(IntSize::Bits32) => 4, - PrimitiveType::UInt(IntSize::Bits64) => 8, - PrimitiveType::Int(IntSize::Bits8) => 1, - PrimitiveType::Int(IntSize::Bits16) => 2, - PrimitiveType::Int(IntSize::Bits32) => 4, - PrimitiveType::Int(IntSize::Bits64) => 8, - PrimitiveType::Str => 8, // TODO: Platform specific pointer size - PrimitiveType::Pointer(_) => 8, // FIXME: Platform specific pointer size - PrimitiveType::Box(_) => 8, // FIXME: Platform specific pointer size - PrimitiveType::Bool => 1, - PrimitiveType::Char => 1, + Type::UInt(IntSize::Bits8) => 1, + Type::UInt(IntSize::Bits16) => 2, + Type::UInt(IntSize::Bits32) => 4, + Type::UInt(IntSize::Bits64) => 8, + Type::Int(IntSize::Bits8) => 1, + Type::Int(IntSize::Bits16) => 2, + Type::Int(IntSize::Bits32) => 4, + Type::Int(IntSize::Bits64) => 8, + Type::Str => 8, // TODO: Platform specific pointer size + Type::Pointer(_) => 8, // FIXME: Platform specific pointer size + Type::Box(_) => 8, // FIXME: Platform specific pointer size + Type::Bool => 1, + Type::Char => 1, _ => unimplemented!("{:?}", self), } } diff --git a/comp-be/src/ty/variant.rs b/comp-be/src/ty/variant.rs index 8467bc4..dbb1df4 100644 --- a/comp-be/src/ty/variant.rs +++ b/comp-be/src/ty/variant.rs @@ -1,16 +1,16 @@ use crate::{ - codegen::{builder::core, AatbeModule, ValueTypePair}, + codegen::{builder::base, unit::CompilerContext, ValueTypePair}, ty::{Aggregate, LLVMTyInCtx, TypeError, TypeResult}, }; use llvm_sys_wrapper::{LLVMTypeRef, LLVMValueRef}; -use parser::ast::PrimitiveType; +use parser::ast::Type; use std::{collections::HashMap, fmt}; pub struct VariantType { pub type_name: String, pub variants: HashMap, - pub discriminant_type: PrimitiveType, + pub discriminant_type: Type, pub ty: LLVMTypeRef, } @@ -21,7 +21,7 @@ impl VariantType { } impl LLVMTyInCtx for VariantType { - fn llvm_ty_in_ctx(&self, _: &AatbeModule) -> LLVMTypeRef { + fn llvm_ty_in_ctx(&self, _: &CompilerContext) -> LLVMTypeRef { self.ty } } @@ -30,13 +30,13 @@ impl LLVMTyInCtx for VariantType { pub struct Variant { pub parent_name: String, pub name: String, - pub types: Option>, + pub types: Option>, pub ty: LLVMTypeRef, pub discriminant: u32, } impl LLVMTyInCtx for Variant { - fn llvm_ty_in_ctx(&self, _: &AatbeModule) -> LLVMTypeRef { + fn llvm_ty_in_ctx(&self, _: &CompilerContext) -> LLVMTypeRef { self.ty } } @@ -54,7 +54,7 @@ impl VariantType { impl Aggregate for Variant { fn gep_indexed_field( &self, - module: &AatbeModule, + ctx: &CompilerContext, index: u32, aggregate_ref: LLVMValueRef, ) -> TypeResult { @@ -64,7 +64,7 @@ impl Aggregate for Variant { Err(TypeError::VariantOOB(self.name.clone(), index)) } Some(types) => Ok(( - core::struct_gep(module, aggregate_ref, index + 1), + base::struct_gep(ctx, aggregate_ref, index + 1), types[index as usize].clone(), ) .into()), @@ -73,7 +73,7 @@ impl Aggregate for Variant { fn gep_named_field( &self, - _module: &AatbeModule, + _ctx: &CompilerContext, name: &String, _aggregate_ref: LLVMValueRef, ) -> TypeResult { diff --git a/libc.aat b/libc.aat new file mode 100644 index 0000000..b20473c --- /dev/null +++ b/libc.aat @@ -0,0 +1 @@ +public extern fn printf str, ... -> i32 \ No newline at end of file diff --git a/main.aat b/main.aat index b8a2580..14715fd 100644 --- a/main.aat +++ b/main.aat @@ -1,9 +1,28 @@ -fn foo i: i32* -> () = {} +use libc -@entry -fn main() -> () = { - val i = 32 - val fa = [i] +module std { + public fn println s: str = ::libc::printf "%s\n", s + public fn println c: char = ::libc::printf "%c\n", c + + public fn println b: bool = + if b then println "true" + else println "false" - foo fa as [i32] + public fn println i: i8 = ::libc::printf "%hhi\n", i + public fn println i: i16 = ::libc::printf "%hi\n", i + public fn println i: i32 = ::libc::printf "%i\n", i + public fn println i: i64 = ::libc::printf "%li\n", i + public fn println u: u8 = ::libc::printf "%hhu\n", u + public fn println u: u16 = ::libc::printf "%hu\n", u + public fn println u: u32 = ::libc::printf "%u\n", u + public fn println u: u64 = ::libc::printf "%lu\n", u + public fn println f: f64 = ::libc::printf "%f\n", f + public fn println f: f64 = ::libc::printf "%f\n", f } + +@entry +fn main () = { + std::println false + std::println 128u16 + std::println 'A' +} \ No newline at end of file diff --git a/main.aat.bak b/main.aat.bak new file mode 100644 index 0000000..b13e9ff --- /dev/null +++ b/main.aat.bak @@ -0,0 +1,26 @@ +module libc { + public extern fn printf str, ... -> i32 +} + +module std { + public fn println s: str -> () = ::libc::printf "%s\n", s + public fn println c: char -> () = ::libc::printf "%c\n", c + + public fn println i: i8 -> () = ::libc::printf "%hhi\n", i + public fn println i: i16 -> () = ::libc::printf "%hi\n", i + public fn println i: i32 -> () = ::libc::printf "%i\n", i + public fn println i: i64 -> () = ::libc::printf "%li\n", i + public fn println u: u8 -> () = ::libc::printf "%hhu\n", u + public fn println u: u16 -> () = ::libc::printf "%hu\n", u + public fn println u: u32 -> () = ::libc::printf "%u\n", u + public fn println u: u64 -> () = ::libc::printf "%lu\n", u + public fn println f: f64 -> () = ::libc::printf "%f\n", f + public fn println f: f64 -> () = ::libc::printf "%f\n", f +} + +fn add[I] a: I, b: I -> I = a + b + +@entry +fn main () = { + libc::printf "%d\n", add[i32] 10, 8 +} \ No newline at end of file diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 09c063e..aae7a4a 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -1,33 +1,43 @@ use std::fmt; +type ModPath = Vec; + +#[derive(Debug, PartialEq, Clone, Eq, Hash)] +pub enum IdentPath { + Local(String), + Module(ModPath), + Root(ModPath), +} + #[derive(Debug, PartialEq, Clone)] pub enum AST { File(Vec), Error, Expr(Expression), - Import(String), - Record(String, Option>, Vec), + Import(IdentPath), + Record(String, Option>, Vec), Typedef { name: String, type_names: Option>, variants: Option>, }, Constant { - ty: PrimitiveType, + ty: Type, export: bool, value: Box, }, Global { - ty: PrimitiveType, + ty: Type, export: bool, value: Box, }, + Module(String, Box), } #[derive(Debug, PartialEq, Clone)] pub enum TypeKind { - Newtype(PrimitiveType), - Variant(String, Option>), + Newtype(Type), + Variant(String, Option>), } #[derive(Debug, PartialEq, Clone)] @@ -37,7 +47,7 @@ pub enum Expression { Block(Vec), Ret(Box), Decl { - ty: PrimitiveType, + ty: Type, value: Option>, exterior_bind: BindType, }, @@ -46,8 +56,8 @@ pub enum Expression { value: Box, }, Call { - name: String, - types: Vec, + name: IdentPath, + types: Vec, args: Vec, }, Function { @@ -56,17 +66,17 @@ pub enum Expression { body: Option>, attributes: Vec, type_names: Vec, - export: bool, + public: bool, }, If { cond_expr: Box, then_expr: Box, + elseif_exprs: Vec<(Expression, Expression)>, else_expr: Option>, - is_expr: bool, }, RecordInit { record: String, - types: Vec, + types: Vec, values: Vec, }, Loop { @@ -91,7 +101,7 @@ pub enum BindType { Constant, } -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum LoopType { While, Until, @@ -100,18 +110,18 @@ pub enum LoopType { #[derive(Debug, PartialEq, Eq, Clone, Hash)] pub struct FunctionType { pub ext: bool, - pub ret_ty: Box, - pub params: Vec, + pub ret_ty: Box, + pub params: Vec, } -impl From for PrimitiveType { +impl From for Type { fn from(func: FunctionType) -> Self { - PrimitiveType::Function(func) + Type::Function(func) } } #[derive(Debug, PartialEq, Eq, Clone, Hash)] -pub enum PrimitiveType { +pub enum Type { Unit, Str, Varargs, @@ -121,51 +131,41 @@ pub enum PrimitiveType { UInt(IntSize), Float(FloatSize), TypeRef(String), - GenericTypeRef(String, Vec), + GenericTypeRef(String, Vec), Newtype(String), VariantType(String), - Variant { - parent: String, - variant: String, - }, + Variant { parent: String, variant: String }, Function(FunctionType), - NamedType { - name: String, - ty: Option>, - }, - Ref(Box), - Pointer(Box), - Array { - ty: Box, - len: u32, - }, - Slice { - ty: Box, - }, + NamedType { name: String, ty: Option> }, + Ref(Box), + Pointer(Box), + Array { ty: Box, len: u32 }, + Slice { ty: Box }, Symbol(String), - Box(Box), + Box(Box), + Path(ModPath), } -impl PrimitiveType { - pub fn inner(&self) -> &PrimitiveType { +impl Type { + pub fn inner(&self) -> &Type { match self { - PrimitiveType::NamedType { + Type::NamedType { name: _, ty: Some(box ty), } => ty, - PrimitiveType::Function(..) => panic!("ICE primty inner {:?}", self), + Type::Function(..) => panic!("ICE primty inner {:?}", self), other => other, } } pub fn ext(&self) -> bool { match self { - PrimitiveType::Function(FunctionType { + Type::Function(FunctionType { ext, ret_ty: _, params: _, }) => ext.clone(), - _ => panic!("ICE PrimitiveType ext {:?}", self), + _ => panic!("ICE Type ext {:?}", self), } } } @@ -175,8 +175,8 @@ pub enum AtomKind { Unit, SymbolLiteral(String), Bool(Boolean), - Integer(u64, PrimitiveType), - Floating(f64, PrimitiveType), + Integer(u64, Type), + Floating(f64, Type), StringLiteral(String), CharLiteral(char), Expr(Box), @@ -187,7 +187,7 @@ pub enum AtomKind { Deref(Box), Ref(Box), Index(Box, Box), - Cast(Box, PrimitiveType), + Cast(Box, Type), Array(Vec), Is(Box, String), NamedValue { name: String, val: Box }, diff --git a/parser/src/lexer/mod.rs b/parser/src/lexer/mod.rs index 1a957b9..ecea1da 100644 --- a/parser/src/lexer/mod.rs +++ b/parser/src/lexer/mod.rs @@ -239,9 +239,13 @@ impl<'c> Lexer<'c> { ',' => { symbol!(tokens, Symbol::Comma, pos); } - ':' => { - symbol!(tokens, Symbol::Colon, pos); - } + ':' => match self.chars.peek() { + Some(':') => { + self.advance(); + symbol!(tokens, Symbol::Doubly, pos) + } + _ => symbol!(tokens, Symbol::Colon, pos), + }, '%' => { symbol!(tokens, Symbol::Modulo, pos); } @@ -316,9 +320,9 @@ impl<'c> Lexer<'c> { token!( tokens, - Token::keyword(buf.as_ref()).unwrap_or( - Token::boolean(buf.as_ref()).unwrap_or( - Token::r#type(buf.as_ref()).unwrap_or(TokenKind::Identifier(buf)), + Token::keyword(&buf).unwrap_or( + Token::boolean(&buf).unwrap_or( + Token::r#type(&buf).unwrap_or(TokenKind::Identifier(buf)), ), ), pos @@ -351,9 +355,10 @@ impl<'c> Lexer<'c> { }; } if buf.contains(".") { - TokenKind::FloatLiteral(f64::from_str(&buf).expect( - format!("{} is not a floating point literal", buf).as_ref(), - )) + TokenKind::FloatLiteral( + f64::from_str(&buf) + .expect(&format!("{} is not a floating point literal", buf)), + ) } else { TokenKind::IntLiteral( u64::from_str_radix(&buf, 10).expect("Lexer died @digits -> u64"), @@ -377,9 +382,10 @@ impl<'c> Lexer<'c> { token!( tokens, if buf.contains(".") { - TokenKind::FloatLiteral(f64::from_str(&buf).expect( - format!("{} is not a floating point literal", buf).as_ref(), - )) + TokenKind::FloatLiteral( + f64::from_str(&buf) + .expect(&format!("{} is not a floating point literal", buf)), + ) } else { TokenKind::IntLiteral( u64::from_str_radix(&buf, 10).expect("Lexer died @digits -> u64"), diff --git a/parser/src/lexer/tests.rs b/parser/src/lexer/tests.rs index 65a689a..230cd1f 100644 --- a/parser/src/lexer/tests.rs +++ b/parser/src/lexer/tests.rs @@ -1,7 +1,7 @@ #[cfg(test)] mod lexer_tests { use crate::lexer::{ - token::{Boolean, Keyword, Type}, + token::{Boolean, Keyword, TokenType}, Lexer, Symbol, TokenKind, }; #[test] @@ -150,7 +150,7 @@ mod lexer_tests { #[test] fn keyword_identifier() { let mut lexer = Lexer::new( - "fn extern var val if else use true false main record.test bool rec global ret while until type is exp", + "fn extern var val if else use true false main record.test bool rec global ret while until type is public module", ); let mut tokens = lexer.lex().into_iter(); @@ -194,11 +194,13 @@ mod lexer_tests { sep!(tokens); assert_eq!(tokens.next().unwrap().kw(), Some(Keyword::Until)); sep!(tokens); - assert_eq!(tokens.next().unwrap().kw(), Some(Keyword::Type)); + assert_eq!(tokens.next().unwrap().kw(), Some(Keyword::TokenType)); sep!(tokens); assert_eq!(tokens.next().unwrap().kw(), Some(Keyword::Is)); sep!(tokens); - assert_eq!(tokens.next().unwrap().kw(), Some(Keyword::Exp)); + assert_eq!(tokens.next().unwrap().kw(), Some(Keyword::Public)); + sep!(tokens); + assert_eq!(tokens.next().unwrap().kw(), Some(Keyword::Module)); } #[test] @@ -206,26 +208,26 @@ mod lexer_tests { let mut lexer = Lexer::new("str i8 i16 i32 i64 u8 u16 u32 u64 f32 f64"); let mut tokens = lexer.lex().into_iter(); - assert_eq!(tokens.next().unwrap().ty(), Some(Type::Str)); + assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::Str)); sep!(tokens); - assert_eq!(tokens.next().unwrap().ty(), Some(Type::I8)); + assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::I8)); sep!(tokens); - assert_eq!(tokens.next().unwrap().ty(), Some(Type::I16)); + assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::I16)); sep!(tokens); - assert_eq!(tokens.next().unwrap().ty(), Some(Type::I32)); + assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::I32)); sep!(tokens); - assert_eq!(tokens.next().unwrap().ty(), Some(Type::I64)); + assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::I64)); sep!(tokens); - assert_eq!(tokens.next().unwrap().ty(), Some(Type::U8)); + assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::U8)); sep!(tokens); - assert_eq!(tokens.next().unwrap().ty(), Some(Type::U16)); + assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::U16)); sep!(tokens); - assert_eq!(tokens.next().unwrap().ty(), Some(Type::U32)); + assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::U32)); sep!(tokens); - assert_eq!(tokens.next().unwrap().ty(), Some(Type::U64)); + assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::U64)); sep!(tokens); - assert_eq!(tokens.next().unwrap().ty(), Some(Type::F32)); + assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::F32)); sep!(tokens); - assert_eq!(tokens.next().unwrap().ty(), Some(Type::F64)); + assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::F64)); } } diff --git a/parser/src/lexer/token.rs b/parser/src/lexer/token.rs index 99b0711..f563987 100644 --- a/parser/src/lexer/token.rs +++ b/parser/src/lexer/token.rs @@ -18,7 +18,7 @@ pub enum TokenKind { BooleanLiteral(Boolean), Identifier(String), Keyword(Keyword), - Type(Type), + TokenType(TokenType), StringLiteral(String), CharLiteral(char), EOL, @@ -60,6 +60,7 @@ pub enum Symbol { Dot, DoDot, GoDot, + Doubly, } impl From for String { @@ -82,6 +83,7 @@ impl From for String { Symbol::And => String::from("&&"), Symbol::Xor => String::from("^"), Symbol::Modulo => String::from("%"), + Symbol::Doubly => String::from("::"), _ => panic!("Symbol to str {:?}", sym), } } @@ -111,13 +113,14 @@ pub enum Keyword { Ret, While, Until, - Type, + TokenType, Is, - Exp, + Public, + Module, } #[derive(Debug, Eq, PartialEq, Clone, Copy)] -pub enum Type { +pub enum TokenType { Char, Str, I8, @@ -160,7 +163,7 @@ impl Token { } to_tok!(keyword, Keyword, Keyword); to_tok!(boolean, BooleanLiteral, Boolean); - to_tok!(r#type, Type, Type); + to_tok!(r#type, TokenType, TokenType); pub fn op(&self) -> Option { if let TokenKind::Symbol(sym) = self.kind { return match sym { @@ -202,13 +205,13 @@ impl Token { from_tok!(int, IntLiteral, u64); from_tok!(float, FloatLiteral, f64); from_tok!(ident, Identifier, String); - from_tok!(ty, Type, Type); + from_tok!(ty, TokenType, TokenType); from_tok!(st, StringLiteral, String); from_tok!(comm, Comment, String); from_tok!(ch, CharLiteral, char); } -impl FromStr for Type { +impl FromStr for TokenType { type Err = (); fn from_str(s: &str) -> Result { match s { @@ -249,9 +252,10 @@ impl FromStr for Keyword { "ret" => Ok(Self::Ret), "while" => Ok(Self::While), "until" => Ok(Self::Until), - "type" => Ok(Self::Type), + "type" => Ok(Self::TokenType), "is" => Ok(Self::Is), - "exp" => Ok(Self::Exp), + "public" => Ok(Self::Public), + "module" => Ok(Self::Module), _ => Err(()), } } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 582947c..2486629 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -8,10 +8,10 @@ pub mod parser; mod tests; use crate::{ - ast::{Expression, FloatSize, IntSize, PrimitiveType, TypeKind, AST}, + ast::{Expression, FloatSize, IntSize, Type, TypeKind, AST}, lexer::{ token, - token::{Keyword, Symbol, Type}, + token::{Keyword, Symbol, TokenType}, }, parser::{ParseError, ParseResult, Parser}, }; @@ -20,19 +20,19 @@ use ast::FunctionType; use std::path::PathBuf; impl Parser { - fn parse_type(&mut self) -> ParseResult { + fn parse_type(&mut self) -> ParseResult { let token = self.next(); if let Some(tok) = token { match tok.sym() { - Some(Symbol::Colon) => Some(PrimitiveType::Symbol(ident!(res self)?)), - Some(Symbol::Unit) => Some(PrimitiveType::Unit), - Some(Symbol::GoDot) => Some(PrimitiveType::Varargs), + Some(Symbol::Colon) => Some(Type::Symbol(ident!(res self)?)), + Some(Symbol::Unit) => Some(Type::Unit), + Some(Symbol::GoDot) => Some(Type::Varargs), Some(Symbol::Ampersand) => capture!(res parse_type, self) .ok() - .and_then(|ty| Some(PrimitiveType::Ref(box ty))), + .and_then(|ty| Some(Type::Ref(box ty))), Some(Symbol::At) => capture!(res parse_type, self) .ok() - .and_then(|ty| Some(PrimitiveType::Box(box ty))), + .and_then(|ty| Some(Type::Box(box ty))), Some(Symbol::LBracket) => capture!(res parse_type, self).ok().and_then(|ty| { let len = if sym!(bool Comma, self) { self.peek().and_then(|tok| tok.int()).map(|len| len as u32) @@ -44,14 +44,14 @@ impl Parser { } sym!(RBracket, self); Some(match len { - None => PrimitiveType::Slice { ty: box ty }, - Some(len) => PrimitiveType::Array { ty: box ty, len }, + None => Type::Slice { ty: box ty }, + Some(len) => Type::Array { ty: box ty, len }, }) }), _ => None, } .or_else(|| match tok.kw() { - Some(Keyword::Bool) => Some(PrimitiveType::Bool), + Some(Keyword::Bool) => Some(Type::Bool), _ => None, }) .or_else(|| match tok.ident() { @@ -62,26 +62,44 @@ impl Parser { .parse_type_list() .expect(format!("Expected type list at {}", tyref).as_str()); sym!(RBracket, self); - Some(PrimitiveType::GenericTypeRef(tyref, types)) + Some(Type::GenericTypeRef(tyref, types)) } else { - Some(PrimitiveType::TypeRef(tyref)) + if matches!(self.peek_symbol(Symbol::Doubly), Some(true)) { + let mut res = vec![tyref]; + self.next(); + loop { + match self.peek_ident() { + None => break, + Some(ty) => { + self.next(); + res.push(ty); + if matches!(self.peek_symbol(Symbol::Doubly), Some(true)) { + self.next(); + } + } + } + } + Some(Type::Path(res)) + } else { + Some(Type::TypeRef(tyref)) + } } } None => None, }) .or_else(|| match tok.ty() { - Some(Type::Str) => Some(PrimitiveType::Str), - Some(Type::Char) => Some(PrimitiveType::Char), - Some(Type::I8) => Some(PrimitiveType::Int(IntSize::Bits8)), - Some(Type::I16) => Some(PrimitiveType::Int(IntSize::Bits16)), - Some(Type::I32) => Some(PrimitiveType::Int(IntSize::Bits32)), - Some(Type::I64) => Some(PrimitiveType::Int(IntSize::Bits64)), - Some(Type::U8) => Some(PrimitiveType::UInt(IntSize::Bits8)), - Some(Type::U16) => Some(PrimitiveType::UInt(IntSize::Bits16)), - Some(Type::U32) => Some(PrimitiveType::UInt(IntSize::Bits32)), - Some(Type::U64) => Some(PrimitiveType::UInt(IntSize::Bits64)), - Some(Type::F32) => Some(PrimitiveType::Float(FloatSize::Bits32)), - Some(Type::F64) => Some(PrimitiveType::Float(FloatSize::Bits64)), + Some(TokenType::Str) => Some(Type::Str), + Some(TokenType::Char) => Some(Type::Char), + Some(TokenType::I8) => Some(Type::Int(IntSize::Bits8)), + Some(TokenType::I16) => Some(Type::Int(IntSize::Bits16)), + Some(TokenType::I32) => Some(Type::Int(IntSize::Bits32)), + Some(TokenType::I64) => Some(Type::Int(IntSize::Bits64)), + Some(TokenType::U8) => Some(Type::UInt(IntSize::Bits8)), + Some(TokenType::U16) => Some(Type::UInt(IntSize::Bits16)), + Some(TokenType::U32) => Some(Type::UInt(IntSize::Bits32)), + Some(TokenType::U64) => Some(Type::UInt(IntSize::Bits64)), + Some(TokenType::F32) => Some(Type::Float(FloatSize::Bits32)), + Some(TokenType::F64) => Some(Type::Float(FloatSize::Bits64)), _ => None, }) } else { @@ -90,14 +108,14 @@ impl Parser { .and_then(|ty| { let mut ty = ty; while sym!(bool Star, self) { - ty = PrimitiveType::Pointer(box ty); + ty = Type::Pointer(box ty); } Some(ty) }) .ok_or(ParseError::ExpectedType) } - fn parse_named_type(&mut self) -> ParseResult { + fn parse_named_type(&mut self) -> ParseResult { let name = ident!(required self); if sym!(bool Comma, self) | sym!(bool Arrow, self) @@ -111,7 +129,7 @@ impl Parser { } else { None }; - Ok(PrimitiveType::NamedType { name, ty }) + Ok(Type::NamedType { name, ty }) } fn parse_attribute(&mut self) -> Option { @@ -121,20 +139,13 @@ impl Parser { fn parse_use(&mut self) -> ParseResult { kw!(Use, self); - if let Some(path) = self.peek_str() { - self.next(); - let pb = PathBuf::from(path); + let path = path!(module self); - Ok(AST::Import( - pb.to_str().expect("ICE parse_use pb.to_str").to_string(), - )) - } else { - Err(ParseError::ExpectedPath) - } + Ok(AST::Import(path)) } - fn parse_type_list(&mut self) -> ParseResult> { + fn parse_type_list(&mut self) -> ParseResult> { let mut params = vec![]; loop { @@ -151,7 +162,7 @@ impl Parser { Ok(params) } - fn parse_free_type_list(&mut self) -> ParseResult> { + fn parse_free_type_list(&mut self) -> ParseResult> { let mut params = vec![]; loop { @@ -190,7 +201,7 @@ impl Parser { }; let fields = if sym!(bool Unit, self) { - vec![PrimitiveType::Unit] + vec![Type::Unit] } else { sym!(required LParen, self); let fields = self @@ -204,7 +215,7 @@ impl Parser { } fn parse_const_global(&mut self) -> ParseResult { - let export = kw!(bool Exp, self); + let export = kw!(bool Public, self); let cons = kw!(bool Const, self); let glob = kw!(bool Global, self); @@ -225,7 +236,7 @@ impl Parser { } fn parse_typedef(&mut self) -> ParseResult { - kw!(Type, self); + kw!(TokenType, self); let name = ident!(res self)?; let type_names = if sym!(bool LBracket, self) { @@ -242,7 +253,7 @@ impl Parser { Some(if sym!(bool Pipe, self) { let mut variants = vec![]; - if let PrimitiveType::TypeRef(name) = ty { + if let Type::TypeRef(name) = ty { self.variants.push(name.clone()); variants.push(TypeKind::Variant(name, vars)); } else { @@ -264,7 +275,7 @@ impl Parser { variants } else { if vars.is_some() { - if let PrimitiveType::TypeRef(name) = ty { + if let Type::TypeRef(name) = ty { vec![TypeKind::Variant(name, vars)] } else { return Err(ParseError::ExpectedIdent); @@ -294,7 +305,7 @@ impl Parser { } } - let export = kw!(bool Exp, self); + let public = kw!(bool Public, self); let ext = kw!(bool Extern, self); kw!(Fn, self); let name = ident!(required self); @@ -314,7 +325,7 @@ impl Parser { let ret_ty = box if sym!(bool Arrow, self) { capture!(res parse_type, self)? } else { - PrimitiveType::Unit + Type::Unit }; let mut body = None; @@ -327,7 +338,7 @@ impl Parser { attributes, body, type_names, - export, + public, ty: FunctionType { ext, ret_ty, @@ -335,4 +346,20 @@ impl Parser { }, })) } + + fn parse_module(&mut self) -> ParseResult { + if kw!(bool Module, self) { + let name = ident!(required self); + sym!(required LCurly, self); + if sym!(bool RCurly, self) { + Ok(AST::Module(name, box AST::File(vec![]))) + } else { + let res = Ok(AST::Module(name, box self.parse()?)); + sym!(required RCurly, self); + res + } + } else { + Err(ParseError::Continue) + } + } } diff --git a/parser/src/parser/atom.rs b/parser/src/parser/atom.rs index 4d65fb7..22e898f 100644 --- a/parser/src/parser/atom.rs +++ b/parser/src/parser/atom.rs @@ -1,8 +1,8 @@ use crate::{ - ast::{AtomKind, Boolean, FloatSize, IntSize, PrimitiveType}, + ast::{AtomKind, Boolean, FloatSize, IntSize, Type}, parser::{ParseError, ParseResult, Parser}, token, - token::{Keyword, Symbol, Type}, + token::{Keyword, Symbol, TokenType}, }; impl Parser { @@ -21,22 +21,22 @@ impl Parser { } fn parse_number(&mut self) -> Option { - fn parse_number_type(parser: &mut Parser) -> Option { + fn parse_number_type(parser: &mut Parser) -> Option { let prev_ind = parser.index; let tok = parser.next(); if let Some(tok) = tok { match tok.ty() { - Some(Type::I8) => Some(PrimitiveType::Int(IntSize::Bits8)), - Some(Type::I16) => Some(PrimitiveType::Int(IntSize::Bits16)), - Some(Type::I32) => Some(PrimitiveType::Int(IntSize::Bits32)), - Some(Type::I64) => Some(PrimitiveType::Int(IntSize::Bits64)), - Some(Type::U8) => Some(PrimitiveType::UInt(IntSize::Bits8)), - Some(Type::U16) => Some(PrimitiveType::UInt(IntSize::Bits16)), - Some(Type::U32) => Some(PrimitiveType::UInt(IntSize::Bits32)), - Some(Type::U64) => Some(PrimitiveType::UInt(IntSize::Bits64)), - Some(Type::F32) => Some(PrimitiveType::Float(FloatSize::Bits32)), - Some(Type::F64) => Some(PrimitiveType::Float(FloatSize::Bits64)), + Some(TokenType::I8) => Some(Type::Int(IntSize::Bits8)), + Some(TokenType::I16) => Some(Type::Int(IntSize::Bits16)), + Some(TokenType::I32) => Some(Type::Int(IntSize::Bits32)), + Some(TokenType::I64) => Some(Type::Int(IntSize::Bits64)), + Some(TokenType::U8) => Some(Type::UInt(IntSize::Bits8)), + Some(TokenType::U16) => Some(Type::UInt(IntSize::Bits16)), + Some(TokenType::U32) => Some(Type::UInt(IntSize::Bits32)), + Some(TokenType::U64) => Some(Type::UInt(IntSize::Bits64)), + Some(TokenType::F32) => Some(Type::Float(FloatSize::Bits32)), + Some(TokenType::F64) => Some(Type::Float(FloatSize::Bits64)), _ => { parser.index = prev_ind; None @@ -52,11 +52,9 @@ impl Parser { if let Some(tok) = token { if let Some(val) = tok.int() { return Some(match parse_number_type(self) { - Some(ty @ (PrimitiveType::Int(_) | PrimitiveType::UInt(_))) => { - AtomKind::Integer(val, ty) - } - Some(ty @ PrimitiveType::Float(_)) => AtomKind::Floating(val as f64, ty), - None => AtomKind::Integer(val, PrimitiveType::Int(IntSize::Bits32)), + Some(ty @ (Type::Int(_) | Type::UInt(_))) => AtomKind::Integer(val, ty), + Some(ty @ Type::Float(_)) => AtomKind::Floating(val as f64, ty), + None => AtomKind::Integer(val, Type::Int(IntSize::Bits32)), _ => unreachable!(), }); } @@ -66,14 +64,14 @@ impl Parser { } fn parse_float(&mut self) -> Option { - fn parse_float_type(parser: &mut Parser) -> Option { + fn parse_float_type(parser: &mut Parser) -> Option { let prev_ind = parser.index; let tok = parser.next(); if let Some(tok) = tok { match tok.ty() { - Some(Type::F32) => Some(PrimitiveType::Float(FloatSize::Bits32)), - Some(Type::F64) => Some(PrimitiveType::Float(FloatSize::Bits64)), + Some(TokenType::F32) => Some(Type::Float(FloatSize::Bits32)), + Some(TokenType::F64) => Some(Type::Float(FloatSize::Bits64)), _ => { parser.index = prev_ind; None @@ -91,7 +89,7 @@ impl Parser { let ty = parse_float_type(self); return Some(AtomKind::Floating( val, - ty.unwrap_or(PrimitiveType::Float(FloatSize::Bits32)), + ty.unwrap_or(Type::Float(FloatSize::Bits32)), )); } } diff --git a/parser/src/parser/conditionals.rs b/parser/src/parser/conditionals.rs index 0126b43..d05a631 100644 --- a/parser/src/parser/conditionals.rs +++ b/parser/src/parser/conditionals.rs @@ -8,7 +8,6 @@ impl Parser { pub fn parse_if_else(&mut self) -> ParseResult { kw!(If, self); - let is_expr = kw!(bool Ret, self); let cond_expr = box capture!(self, parse_expression).ok_or(ParseError::ExpectedCondition)?; kw!(bool Then, self); @@ -16,7 +15,21 @@ impl Parser { box capture!(self, parse_expression).ok_or(ParseError::ExpectedThenExpression)?; let mut else_expr = None; - let has_else = kw!(bool Else, self); + let mut chain = vec![]; + + let mut has_else = false; + while kw!(bool Else, self) && { + has_else = !kw!(bool If, self); + !has_else + } { + let cond_expr = + capture!(self, parse_expression).ok_or(ParseError::ExpectedCondition)?; + kw!(bool Then, self); + let then_expr = + capture!(self, parse_expression).ok_or(ParseError::ExpectedThenExpression)?; + + chain.push((cond_expr, then_expr)); + } if has_else { else_expr = @@ -26,8 +39,8 @@ impl Parser { Ok(Expression::If { cond_expr, then_expr, + elseif_exprs: chain, else_expr, - is_expr, }) } diff --git a/parser/src/parser/expression.rs b/parser/src/parser/expression.rs index 0bfd529..7835cae 100644 --- a/parser/src/parser/expression.rs +++ b/parser/src/parser/expression.rs @@ -50,7 +50,7 @@ impl Parser { } fn parse_funcall(&mut self) -> ParseResult { - let name = ident!(required self); + let name = path!(required self); let types = if sym!(bool LBracket, self) { let types = self.parse_type_list()?; diff --git a/parser/src/parser/macros.rs b/parser/src/parser/macros.rs index e921072..7c00e1c 100644 --- a/parser/src/parser/macros.rs +++ b/parser/src/parser/macros.rs @@ -110,6 +110,119 @@ macro_rules! kw { }}; } +#[macro_export] +macro_rules! path { + (module $self:ident) => {{ + use crate::{ast::IdentPath, lexer::token::TokenKind}; + let prev_ind = $self.index; + let token = $self.next(); + if let Some(tok) = token { + match tok.kind { + TokenKind::Identifier(id) => { + let mut res = vec![id.clone()]; + + while matches!($self.peek_symbol(Symbol::Doubly), Some(true)) { + $self.next(); + if $self.peek_ident().is_some() { + $self.next().unwrap().ident().map(|id| res.push(id.clone())); + } + } + + if res.len() == 1 { + IdentPath::Local(id) + } else { + IdentPath::Module(res) + } + } + TokenKind::Symbol(Symbol::Doubly) => { + $self.index = prev_ind; + let mut res = vec![]; + + while matches!($self.peek_symbol(Symbol::Doubly), Some(true)) { + $self.next(); + if $self.peek_ident().is_some() { + $self.next().unwrap().ident().map(|id| res.push(id.clone())); + } + } + + IdentPath::Root(res) + } + _ => { + $self.index = prev_ind; + return Err(ParseError::ExpectedIdent); + } + } + } else { + $self.index = prev_ind; + return Err(ParseError::ExpectedIdent); + } + }}; + (required $self:ident) => {{ + use crate::{ + ast::IdentPath, + lexer::token::{Token, TokenKind}, + }; + let prev_ind = $self.index; + let token = $self.next(); + if let Some(tok) = token { + match tok.kind { + TokenKind::Identifier(id) => { + let mut res = vec![id.clone()]; + if let Some(Token { + kind: TokenKind::EOL, + .. + }) = $self.peek_rel(0) + { + $self.index = prev_ind; + return Err(ParseError::ExpectedIdent); + } + + while matches!($self.peek_symbol(Symbol::Doubly), Some(true)) { + $self.next(); + if $self.peek_ident().is_some() { + $self.next().unwrap().ident().map(|id| res.push(id.clone())); + } + } + + if !matches!($self.peek_symbol(Symbol::LBracket), Some(true)) { + $self.index -= 1; + } + + if res.len() == 1 { + IdentPath::Local(id) + } else { + IdentPath::Module(res) + } + } + TokenKind::Symbol(Symbol::Doubly) => { + $self.index = prev_ind; + let mut res = vec![]; + + while matches!($self.peek_symbol(Symbol::Doubly), Some(true)) { + $self.next(); + if $self.peek_ident().is_some() { + $self.next().unwrap().ident().map(|id| res.push(id.clone())); + } + } + + if !matches!($self.peek_symbol(Symbol::LBracket), Some(true)) { + $self.index -= 1; + } + + IdentPath::Root(res) + } + _ => { + $self.index = prev_ind; + return Err(ParseError::ExpectedIdent); + } + } + } else { + $self.index = prev_ind; + return Err(ParseError::ExpectedIdent); + } + }}; +} + #[macro_export] macro_rules! ident { (required $self:ident) => {{ diff --git a/parser/src/parser/mod.rs b/parser/src/parser/mod.rs index 659dc96..cb5db7a 100644 --- a/parser/src/parser/mod.rs +++ b/parser/src/parser/mod.rs @@ -133,14 +133,18 @@ impl Parser { None => break Err(ParseError::InvalidEOF), }; - res.push( - capture!(res parse_use, self) - .or_else(|_| capture!(res parse_function, self)) - .or_else(|_| capture!(res parse_record, self)) - .or_else(|_| capture!(res parse_const_global, self)) - .or_else(|_| capture!(res parse_typedef, self)) - .unwrap_or_else(|r| panic!("{:?} {:?}", r, self.peek())), - ); + let result = capture!(res parse_use, self) + .or_else(|_| capture!(res parse_function, self)) + .or_else(|_| capture!(res parse_record, self)) + .or_else(|_| capture!(res parse_const_global, self)) + .or_else(|_| capture!(res parse_typedef, self)) + .or_else(|_| capture!(res parse_module, self)); + + match result { + Err(ParseError::Continue) => break Ok(()), + Err(err) => panic!("{:?} {:?}", err, self.peek()), + Ok(ast) => res.push(ast), + }; }?; Ok(pass::type_resolution(&self.variants, &AST::File(res))) diff --git a/parser/src/parser/pass/type_resolution.rs b/parser/src/parser/pass/type_resolution.rs index 0c21eb3..5508b3e 100644 --- a/parser/src/parser/pass/type_resolution.rs +++ b/parser/src/parser/pass/type_resolution.rs @@ -1,4 +1,4 @@ -use crate::ast::{AtomKind, Expression, FunctionType, LValue, PrimitiveType, TypeKind, AST}; +use crate::ast::{AtomKind, Expression, FunctionType, LValue, Type, TypeKind, AST}; pub fn type_resolution(variants: &Vec, ast: &AST) -> AST { match ast { @@ -27,6 +27,7 @@ pub fn type_resolution(variants: &Vec, ast: &AST) -> AST { types.clone(), fields.iter().map(|f| resolve_prim(variants, f)).collect(), ), + AST::Module(_, _) => ast.clone(), _ => panic!("unhandled {:?}", ast), } } @@ -50,12 +51,12 @@ fn resolve_expr(variants: &Vec, ast: &Expression) -> Expression { name, body, ty, - export, + public, } => Expression::Function { name: name.clone(), attributes: attributes.clone(), type_names: type_names.clone(), - export: *export, + public: *public, ty: resolve_function_ty(variants, ty), body: body.as_ref().map(|body| box resolve_expr(variants, &body)), }, @@ -93,18 +94,30 @@ fn resolve_expr(variants: &Vec, ast: &Expression) -> Expression { value: box resolve_expr(variants, value), }, Expression::If { - is_expr, cond_expr: box cond_expr, + elseif_exprs, else_expr, then_expr: box then_expr, } => Expression::If { - is_expr: *is_expr, cond_expr: box resolve_expr(variants, cond_expr), + elseif_exprs: elseif_exprs + .iter() + .map(|(cond, block)| (resolve_expr(variants, cond), resolve_expr(variants, block))) + .collect(), else_expr: else_expr .as_ref() .map(|box ex| box resolve_expr(variants, &ex)), then_expr: box resolve_expr(variants, then_expr), }, + Expression::Loop { + loop_type, + cond_expr: box cond_expr, + body: box body, + } => Expression::Loop { + cond_expr: box resolve_expr(variants, cond_expr), + body: box resolve_expr(variants, body), + loop_type: *loop_type, + }, Expression::RecordInit { record, types, @@ -179,16 +192,16 @@ fn resolve_function_ty(variants: &Vec, ty: &FunctionType) -> FunctionTyp } } -fn resolve_prim(variants: &Vec, ty: &PrimitiveType) -> PrimitiveType { +fn resolve_prim(variants: &Vec, ty: &Type) -> Type { match ty { - PrimitiveType::TypeRef(ty) => { + Type::TypeRef(ty) => { if variants.contains(ty) { - PrimitiveType::VariantType(ty.clone()) + Type::VariantType(ty.clone()) } else { - PrimitiveType::TypeRef(ty.clone()) + Type::TypeRef(ty.clone()) } } - PrimitiveType::NamedType { name, ty } => PrimitiveType::NamedType { + Type::NamedType { name, ty } => Type::NamedType { name: name.clone(), ty: ty.as_ref().map(|ty| box resolve_prim(variants, &ty)), }, diff --git a/parser/src/tests.rs b/parser/src/tests.rs index 3372c2f..ba35247 100644 --- a/parser/src/tests.rs +++ b/parser/src/tests.rs @@ -1,10 +1,9 @@ #[cfg(test)] mod parser_tests { - use crate::ast::FunctionType; use crate::{ - ast::{AtomKind, BindType, Boolean, IntSize, LValue, TypeKind}, + ast::{AtomKind, BindType, Boolean, FunctionType, IdentPath, IntSize, LValue, TypeKind}, lexer::{token::Token, Lexer}, - Expression, ParseError, Parser, PrimitiveType, AST, + Expression, ParseError, Parser, Type, AST, }; fn tt(code: &'static str) -> Vec { @@ -47,7 +46,7 @@ mod parser_tests { #[test] fn unit_function() { - let pt = parse_test!("exp fn test () -> ()", "Unit Function"); + let pt = parse_test!("public fn test () -> ()", "Unit Function"); assert_eq!( pt, @@ -56,11 +55,11 @@ mod parser_tests { attributes: vec![], body: None, type_names: vec![], - export: true, + public: true, ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::Unit], + ret_ty: box Type::Unit, + params: vec![Type::Unit], } }),]) ); @@ -77,11 +76,11 @@ mod parser_tests { attributes: vec![], body: None, type_names: vec![], - export: false, + public: false, ty: FunctionType { ext: true, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::Unit], + ret_ty: box Type::Unit, + params: vec![Type::Unit], } }),]) ); @@ -103,12 +102,12 @@ fn main () -> () name: "main".to_string(), attributes: attr(vec!["entry"]), body: None, - export: false, + public: false, type_names: vec![], ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::Unit], + ret_ty: box Type::Unit, + params: vec![Type::Unit], } }),]) ); @@ -130,12 +129,12 @@ fn main () -> () = () name: "main".to_string(), attributes: attr(vec!["entry"]), type_names: vec![], - export: false, + public: false, body: Some(box Expression::Atom(AtomKind::Unit)), ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::Unit], + ret_ty: box Type::Unit, + params: vec![Type::Unit], } }),]) ); @@ -157,47 +156,35 @@ fn main () -> () = 1 + 2 * 3 + 4 || 1 == 2 & -foo name: "main".to_string(), attributes: attr(vec!["entry"]), type_names: vec![], - export: false, + public: false, body: Some(box Expression::Binary( box Expression::Binary( box Expression::Binary( - box Expression::Atom(AtomKind::Integer( - 1, - PrimitiveType::Int(IntSize::Bits32) - )), - String::from("+"), + box Expression::Atom(AtomKind::Integer(1, Type::Int(IntSize::Bits32))), + "+".to_string(), box Expression::Binary( box Expression::Atom(AtomKind::Integer( 2, - PrimitiveType::Int(IntSize::Bits32) + Type::Int(IntSize::Bits32) )), - String::from("*"), + "*".to_string(), box Expression::Atom(AtomKind::Integer( 3, - PrimitiveType::Int(IntSize::Bits32) + Type::Int(IntSize::Bits32) )), ), ), - String::from("+"), - box Expression::Atom(AtomKind::Integer( - 4, - PrimitiveType::Int(IntSize::Bits32) - )), + "+".to_string(), + box Expression::Atom(AtomKind::Integer(4, Type::Int(IntSize::Bits32))), ), - String::from("||"), + "||".to_string(), box Expression::Binary( box Expression::Binary( - box Expression::Atom(AtomKind::Integer( - 1, - PrimitiveType::Int(IntSize::Bits32) - )), - String::from("=="), - box Expression::Atom(AtomKind::Integer( - 2, - PrimitiveType::Int(IntSize::Bits32) - )), + box Expression::Atom(AtomKind::Integer(1, Type::Int(IntSize::Bits32))), + "==".to_string(), + box Expression::Atom(AtomKind::Integer(2, Type::Int(IntSize::Bits32))), ), - String::from("&"), + "&".to_string(), box Expression::Atom(AtomKind::Unary( "-".to_string(), box AtomKind::Ident("foo".to_string()), @@ -206,8 +193,8 @@ fn main () -> () = 1 + 2 * 3 + 4 || 1 == 2 & -foo ),), ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::Unit], + ret_ty: box Type::Unit, + params: vec![Type::Unit], } }),]) ); @@ -230,11 +217,11 @@ fn main () -> () = {} attributes: attr(vec!["entry"]), body: Some(box Expression::Block(vec![])), type_names: vec![], - export: false, + public: false, ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::Unit], + ret_ty: box Type::Unit, + params: vec![Type::Unit], } }),]) ); @@ -256,14 +243,14 @@ fn main () -> () = { () } name: "main".to_string(), attributes: attr(vec!["entry"]), type_names: vec![], - export: false, + public: false, body: Some(box Expression::Block(vec![Expression::Atom( AtomKind::Unit )])), ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::Unit], + ret_ty: box Type::Unit, + params: vec![Type::Unit], } }),]) ); @@ -295,11 +282,11 @@ fn main () -> () = { attributes: vec![], body: None, type_names: vec![], - export: false, + public: false, ty: FunctionType { ext: true, - ret_ty: box PrimitiveType::Int(IntSize::Bits32), - params: vec![PrimitiveType::Str], + ret_ty: box Type::Int(IntSize::Bits32), + params: vec![Type::Str], } }), AST::Expr(Expression::Function { @@ -307,17 +294,17 @@ fn main () -> () = { attributes: vec![], body: None, type_names: vec![], - export: false, + public: false, ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, + ret_ty: box Type::Unit, params: vec![ - PrimitiveType::NamedType { + Type::NamedType { name: "s".to_string(), - ty: Some(box PrimitiveType::Str) + ty: Some(box Type::Str) }, - PrimitiveType::Int(IntSize::Bits32), - PrimitiveType::Varargs, + Type::Int(IntSize::Bits32), + Type::Varargs, ], } }), @@ -325,36 +312,36 @@ fn main () -> () = { name: "main".to_string(), attributes: attr(vec!["entry"]), type_names: vec![], - export: false, + public: false, body: Some(box Expression::Block(vec![ Expression::Call { - name: "puts".to_string(), + name: IdentPath::Local("puts".to_string()), types: vec![], args: vec![Expression::Atom(AtomKind::StringLiteral( "Hello World".to_string() ))], }, Expression::Call { - name: "puts".to_string(), + name: IdentPath::Local("puts".to_string()), types: vec![], args: vec![Expression::Atom(AtomKind::StringLiteral( "Hallo".to_string() ))], }, Expression::Call { - name: "test".to_string(), + name: IdentPath::Local("test".to_string()), types: vec![], args: vec![ Expression::Atom(AtomKind::StringLiteral("Test".to_string())), Expression::Binary( box Expression::Atom(AtomKind::Integer( 1, - PrimitiveType::Int(IntSize::Bits32) + Type::Int(IntSize::Bits32) )), - String::from("+"), + "+".to_string(), box Expression::Atom(AtomKind::Integer( 2, - PrimitiveType::Int(IntSize::Bits32) + Type::Int(IntSize::Bits32) )), ) ] @@ -362,8 +349,8 @@ fn main () -> () = { ])), ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::Unit], + ret_ty: box Type::Unit, + params: vec![Type::Unit], } }), ]) @@ -391,28 +378,28 @@ fn main () -> () = { name: "main".to_string(), attributes: attr(vec!["entry"]), type_names: vec![], - export: false, + public: false, body: Some(box Expression::Block(vec![ Expression::Decl { - ty: PrimitiveType::NamedType { + ty: Type::NamedType { name: "var_t".to_string(), - ty: Some(box PrimitiveType::Str), + ty: Some(box Type::Str), }, - value: Some(box Expression::Atom(AtomKind::StringLiteral(String::from( - "Hello World" - )))), + value: Some(box Expression::Atom(AtomKind::StringLiteral( + "Hello World".to_string() + ))), exterior_bind: BindType::Mutable, }, Expression::Decl { - ty: PrimitiveType::NamedType { + ty: Type::NamedType { name: "val_t".to_string(), - ty: Some(box PrimitiveType::Str), + ty: Some(box Type::Str), }, value: None, exterior_bind: BindType::Immutable, }, Expression::Decl { - ty: PrimitiveType::NamedType { + ty: Type::NamedType { name: "infer".to_string(), ty: None, }, @@ -421,15 +408,64 @@ fn main () -> () = { }, Expression::Assign { lval: LValue::Ident("var_t".to_string()), - value: box Expression::Atom(AtomKind::StringLiteral(String::from( - "Aloha honua" - ))), + value: box Expression::Atom(AtomKind::StringLiteral( + "Aloha honua".to_string() + )), } ])), ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::Unit], + ret_ty: box Type::Unit, + params: vec![Type::Unit], + } + }),]) + ); + } + + #[test] + fn if_else_if() { + let pt = parse_test!( + " +@entry +fn main () = { + if true then false + else if false then true + else if !false then false + else false +} +", + "If Else If chain" + ); + + assert_eq!( + pt, + AST::File(vec![AST::Expr(Expression::Function { + name: "main".to_string(), + attributes: attr(vec!["entry"]), + type_names: vec![], + public: false, + body: Some(box Expression::Block(vec![Expression::If { + cond_expr: box Expression::Atom(AtomKind::Bool(Boolean::True)), + then_expr: box Expression::Atom(AtomKind::Bool(Boolean::False)), + elseif_exprs: vec![ + ( + Expression::Atom(AtomKind::Bool(Boolean::False)), + Expression::Atom(AtomKind::Bool(Boolean::True)) + ), + ( + Expression::Atom(AtomKind::Unary( + "!".to_string(), + box AtomKind::Bool(Boolean::False) + ),), + Expression::Atom(AtomKind::Bool(Boolean::False)) + ) + ], + else_expr: Some(box Expression::Atom(AtomKind::Bool(Boolean::False))), + }])), + ty: FunctionType { + ext: false, + ret_ty: box Type::Unit, + params: vec![Type::Unit], } }),]) ); @@ -460,35 +496,29 @@ fn main () -> () = { name: "main".to_string(), attributes: attr(vec!["entry"]), type_names: vec![], - export: false, + public: false, body: Some(box Expression::Block(vec![ Expression::If { cond_expr: box Expression::Binary( - box Expression::Atom(AtomKind::Integer( - 1, - PrimitiveType::Int(IntSize::Bits32) - )), + box Expression::Atom(AtomKind::Integer(1, Type::Int(IntSize::Bits32))), "==".to_string(), - box Expression::Atom(AtomKind::Integer( - 2, - PrimitiveType::Int(IntSize::Bits32) - )), + box Expression::Atom(AtomKind::Integer(2, Type::Int(IntSize::Bits32))), ), then_expr: box Expression::Block(vec![Expression::Call { - name: "foo".to_string(), + name: IdentPath::Local("foo".to_string()), types: vec![], args: vec![Expression::Atom(AtomKind::StringLiteral( "bar".to_string() ))] }]), + elseif_exprs: vec![], else_expr: Some(box Expression::Block(vec![Expression::Call { - name: "bar".to_string(), + name: IdentPath::Local("bar".to_string()), types: vec![], args: vec![Expression::Atom(AtomKind::StringLiteral( "foo".to_string() ))] }])), - is_expr: false, }, Expression::If { cond_expr: box Expression::Atom(AtomKind::Unary( @@ -500,12 +530,12 @@ fn main () -> () = { )), )), then_expr: box Expression::Call { - name: "baz".to_string(), + name: IdentPath::Local("baz".to_string()), types: vec![], args: vec![Expression::Atom(AtomKind::Bool(Boolean::True))] }, + elseif_exprs: vec![], else_expr: None, - is_expr: false, }, Expression::If { cond_expr: box Expression::Atom(AtomKind::Unary( @@ -513,14 +543,14 @@ fn main () -> () = { box AtomKind::Bool(Boolean::True) )), then_expr: box Expression::Atom(AtomKind::Bool(Boolean::False)), + elseif_exprs: vec![], else_expr: Some(box Expression::Atom(AtomKind::Bool(Boolean::True))), - is_expr: false, }, ])), ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::Unit], + ret_ty: box Type::Unit, + params: vec![Type::Unit], } }),]) ); @@ -531,7 +561,9 @@ fn main () -> () = { let pt = parse_test!( " // test comment -use \"lib.aat\" +use lib +use mod::lib +use ::lib @entry fn main () -> () @@ -542,17 +574,22 @@ fn main () -> () assert_eq!( pt, AST::File(vec![ - AST::Import(String::from("lib.aat")), + AST::Import(IdentPath::Local("lib".to_string())), + AST::Import(IdentPath::Module(vec![ + "mod".to_string(), + "lib".to_string() + ])), + AST::Import(IdentPath::Root(vec!["lib".to_string()])), AST::Expr(Expression::Function { name: "main".to_string(), attributes: attr(vec!["entry"]), body: None, type_names: vec![], - export: false, + public: false, ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::Unit], + ret_ty: box Type::Unit, + params: vec![Type::Unit], } }), ]) @@ -577,25 +614,25 @@ rec Unit() "Record".to_string(), None, vec![ - PrimitiveType::NamedType { + Type::NamedType { name: "msg".to_string(), - ty: Some(box PrimitiveType::Str), + ty: Some(box Type::Str), }, - PrimitiveType::NamedType { + Type::NamedType { name: "time".to_string(), - ty: Some(box PrimitiveType::Int(IntSize::Bits64)), + ty: Some(box Type::Int(IntSize::Bits64)), } ] ), AST::Record( "Generic".to_string(), - Some(vec![String::from("T")]), - vec![PrimitiveType::NamedType { + Some(vec!["T".to_string()]), + vec![Type::NamedType { name: "value".to_string(), - ty: Some(box PrimitiveType::TypeRef(String::from("T"))), + ty: Some(box Type::TypeRef("T".to_string())), },] ), - AST::Record("Unit".to_string(), None, vec![PrimitiveType::Unit],) + AST::Record("Unit".to_string(), None, vec![Type::Unit],) ]) ); } @@ -620,29 +657,29 @@ fn generic_test () = Generic[str] { value: \"Aloha\" } "Record".to_string(), None, vec![ - PrimitiveType::NamedType { + Type::NamedType { name: "msg".to_string(), - ty: Some(box PrimitiveType::Str), + ty: Some(box Type::Str), }, - PrimitiveType::NamedType { + Type::NamedType { name: "time".to_string(), - ty: Some(box PrimitiveType::Int(IntSize::Bits32)), + ty: Some(box Type::Int(IntSize::Bits32)), } ] ), AST::Record( "Generic".to_string(), - Some(vec![String::from("T")]), - vec![PrimitiveType::NamedType { + Some(vec!["T".to_string()]), + vec![Type::NamedType { name: "value".to_string(), - ty: Some(box PrimitiveType::TypeRef(String::from("T"))), + ty: Some(box Type::TypeRef("T".to_string())), },] ), AST::Expr(Expression::Function { name: "rec_test".to_string(), attributes: vec![], type_names: vec![], - export: false, + public: false, body: Some(box Expression::RecordInit { record: "Record".to_string(), types: vec![], @@ -657,7 +694,7 @@ fn generic_test () = Generic[str] { value: \"Aloha\" } name: "time".to_string(), val: box Expression::Atom(AtomKind::Integer( 42, - PrimitiveType::Int(IntSize::Bits32) + Type::Int(IntSize::Bits32) )) }, AtomKind::NamedValue { @@ -671,18 +708,18 @@ fn generic_test () = Generic[str] { value: \"Aloha\" } }), ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::Unit], + ret_ty: box Type::Unit, + params: vec![Type::Unit], } }), AST::Expr(Expression::Function { name: "generic_test".to_string(), attributes: vec![], type_names: vec![], - export: false, + public: false, body: Some(box Expression::RecordInit { record: "Generic".to_string(), - types: vec![PrimitiveType::Str], + types: vec![Type::Str], values: vec![AtomKind::NamedValue { name: "value".to_string(), val: box Expression::Atom(AtomKind::StringLiteral("Aloha".to_string())) @@ -690,8 +727,8 @@ fn generic_test () = Generic[str] { value: \"Aloha\" } }), ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::Unit], + ret_ty: box Type::Unit, + params: vec![Type::Unit], } }), ]) @@ -715,39 +752,39 @@ fn generic_test[T] value: T AST::File(vec![ AST::Record( "Generic".to_string(), - Some(vec![String::from("T")]), - vec![PrimitiveType::NamedType { + Some(vec!["T".to_string()]), + vec![Type::NamedType { name: "value".to_string(), - ty: Some(box PrimitiveType::TypeRef(String::from("T"))), + ty: Some(box Type::TypeRef("T".to_string())), },] ), AST::Expr(Expression::Function { name: "generic_record_test".to_string(), attributes: vec![], - type_names: vec![String::from("T")], + type_names: vec!["T".to_string()], body: None, - export: false, + public: false, ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::GenericTypeRef( - String::from("Generic"), - vec![PrimitiveType::TypeRef(String::from("T"))] + ret_ty: box Type::Unit, + params: vec![Type::GenericTypeRef( + "Generic".to_string(), + vec![Type::TypeRef("T".to_string())] )], } }), AST::Expr(Expression::Function { name: "generic_test".to_string(), attributes: vec![], - type_names: vec![String::from("T")], + type_names: vec!["T".to_string()], body: None, - export: false, + public: false, ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::NamedType { - name: String::from("value"), - ty: Some(box PrimitiveType::TypeRef(String::from("T"))) + ret_ty: box Type::Unit, + params: vec![Type::NamedType { + name: "value".to_string(), + ty: Some(box Type::TypeRef("T".to_string())) }], } }), @@ -771,15 +808,15 @@ fn test () = generic_test[i32] 64 AST::Expr(Expression::Function { name: "generic_test".to_string(), attributes: vec![], - type_names: vec![String::from("T")], + type_names: vec!["T".to_string()], body: None, - export: false, + public: false, ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::NamedType { - name: String::from("value"), - ty: Some(box PrimitiveType::TypeRef(String::from("T"))) + ret_ty: box Type::Unit, + params: vec![Type::NamedType { + name: "value".to_string(), + ty: Some(box Type::TypeRef("T".to_string())) }], } }), @@ -787,19 +824,19 @@ fn test () = generic_test[i32] 64 name: "test".to_string(), attributes: vec![], type_names: vec![], - export: false, + public: false, body: Some(box Expression::Call { - name: String::from("generic_test"), - types: vec![PrimitiveType::Int(IntSize::Bits32)], + name: IdentPath::Local("generic_test".to_string()), + types: vec![Type::Int(IntSize::Bits32)], args: vec![Expression::Atom(AtomKind::Integer( 64, - PrimitiveType::Int(IntSize::Bits32) + Type::Int(IntSize::Bits32) ))] }), ty: FunctionType { ext: false, - ret_ty: box PrimitiveType::Unit, - params: vec![PrimitiveType::Unit], + ret_ty: box Type::Unit, + params: vec![Type::Unit], } }), ]) @@ -824,54 +861,160 @@ type Complex = u8 | u16 | Comp @str pt, AST::File(vec![ AST::Typedef { - name: String::from("Opaque"), + name: "Opaque".to_string(), type_names: None, variants: None, }, AST::Typedef { - name: String::from("Generic"), - type_names: Some(vec![String::from("T")]), + name: "Generic".to_string(), + type_names: Some(vec!["T".to_string()]), variants: None, }, AST::Typedef { - name: String::from("Newtype"), + name: "Newtype".to_string(), type_names: None, - variants: Some(vec![TypeKind::Newtype(PrimitiveType::UInt( - IntSize::Bits32 - ))]), + variants: Some(vec![TypeKind::Newtype(Type::UInt(IntSize::Bits32))]), }, AST::Typedef { - name: String::from("Option"), - type_names: Some(vec![String::from("T")]), + name: "Option".to_string(), + type_names: Some(vec!["T".to_string()]), variants: Some(vec![ - TypeKind::Variant(String::from("None"), None), + TypeKind::Variant("None".to_string(), None), TypeKind::Variant( - String::from("Some"), - Some(vec![PrimitiveType::TypeRef(String::from("T"))]) + "Some".to_string(), + Some(vec![Type::TypeRef("T".to_string())]) ) ]), }, AST::Typedef { - name: String::from("Number"), + name: "Number".to_string(), type_names: None, variants: Some(vec![ - TypeKind::Newtype(PrimitiveType::UInt(IntSize::Bits8)), - TypeKind::Newtype(PrimitiveType::UInt(IntSize::Bits16)), + TypeKind::Newtype(Type::UInt(IntSize::Bits8)), + TypeKind::Newtype(Type::UInt(IntSize::Bits16)), ]), }, AST::Typedef { - name: String::from("Complex"), + name: "Complex".to_string(), type_names: None, variants: Some(vec![ - TypeKind::Newtype(PrimitiveType::UInt(IntSize::Bits8)), - TypeKind::Newtype(PrimitiveType::UInt(IntSize::Bits16)), - TypeKind::Variant( - String::from("Comp"), - Some(vec![PrimitiveType::Box(box PrimitiveType::Str)]) - ) + TypeKind::Newtype(Type::UInt(IntSize::Bits8)), + TypeKind::Newtype(Type::UInt(IntSize::Bits16)), + TypeKind::Variant("Comp".to_string(), Some(vec![Type::Box(box Type::Str)])) ]), }, ]) ); } + + #[test] + fn empty_module() { + let pt = parse_test!( + " +module mod { + +}", + "Parse Empty Module" + ); + + assert_eq!( + pt, + AST::File(vec![AST::Module("mod".to_string(), box AST::File(vec![]))]) + ); + } + + #[test] + fn module() { + let pt = parse_test!( + " +module mod { + + type Opaque + +}", + "Parse Module" + ); + + assert_eq!( + pt, + AST::File(vec![AST::Module( + "mod".to_string(), + box AST::File(vec![AST::Typedef { + name: "Opaque".to_string(), + type_names: None, + variants: None, + }]) + )]) + ); + } + + #[test] + fn module_path() { + let pt = parse_test!( + " +type Newtype = mod::test::next +", + "Module Typedef tests" + ); + + assert_eq!( + pt, + AST::File(vec![AST::Typedef { + name: "Newtype".to_string(), + type_names: None, + variants: Some(vec![TypeKind::Newtype(Type::Path(vec![ + "mod".to_string(), + "test".to_string(), + "next".to_string(), + ]))]), + },]) + ); + } + + #[test] + fn module_call() { + let pt = parse_test!( + " +@entry +fn main () = { + func () + mod::func () + ::func () +} +", + "Module call tests" + ); + + assert_eq!( + pt, + AST::File(vec![AST::Expr(Expression::Function { + name: "main".to_string(), + attributes: attr(vec!["entry"]), + type_names: vec![], + public: false, + body: Some(box Expression::Block(vec![ + Expression::Call { + name: IdentPath::Local("func".to_string()), + types: vec![], + args: vec![Expression::Atom(AtomKind::Unit)] + }, + Expression::Call { + name: IdentPath::Module(vec!["mod".to_string(), "func".to_string()]), + types: vec![], + args: vec![Expression::Atom(AtomKind::Unit)] + }, + Expression::Call { + name: IdentPath::Root(vec!["func".to_string()]), + types: vec![], + args: vec![Expression::Atom(AtomKind::Unit)] + } + ])), + ty: FunctionType { + ext: false, + ret_ty: box Type::Unit, + params: vec![Type::Unit], + } + })]) + ); + } } diff --git a/spec/compiler/020_if_expression.aat b/spec/compiler/020_if_expression.aat index 0f93d5d..a4f178e 100644 --- a/spec/compiler/020_if_expression.aat +++ b/spec/compiler/020_if_expression.aat @@ -1,9 +1,9 @@ -// spector:name If/Else expressions using `if ret` +// spector:name If/Else expressions extern fn puts str -> i32 fn should_return b: bool -> str = - if ret b then "true" + if b then "true" else "false" @entry