diff --git a/.gitignore b/.gitignore index ea8c4bf..b0c52a5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +/a.out +/*.o diff --git a/Cargo.lock b/Cargo.lock index 8c5ed02..697958d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,534 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "byteorder" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "2.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "cranelift" +version = "0.69.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "910322bd748b9b2450947659a48a928f35b8ba7212d80d719ff85e4b7cde62b7" +dependencies = [ + "cranelift-codegen", + "cranelift-frontend", +] + +[[package]] +name = "cranelift-bforest" +version = "0.69.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4066fd63b502d73eb8c5fa6bcab9c7962b05cd580f6b149ee83a8e730d8ce7fb" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-codegen" +version = "0.69.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a54e4beb833a3c873a18a8fe735d73d732044004c7539a072c8faa35ccb0c60" +dependencies = [ + "byteorder", + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-entity", + "log", + "regalloc", + "smallvec", + "target-lexicon", + "thiserror", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.69.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c54cac7cacb443658d8f0ff36a3545822613fa202c946c0891897843bc933810" +dependencies = [ + "cranelift-codegen-shared", + "cranelift-entity", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.69.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a109760aff76788b2cdaeefad6875a73c2b450be13906524f6c2a81e05b8d83c" + +[[package]] +name = "cranelift-entity" +version = "0.69.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b044234aa32531f89a08b487630ddc6744696ec04c8123a1ad388de837f5de3" + +[[package]] +name = "cranelift-frontend" +version = "0.69.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5452b3e4e97538ee5ef2cc071301c69a86c7adf2770916b9d04e9727096abd93" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-module" +version = "0.69.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b17bc01cb9f176156d5cbd47ece19292e04e05a91a837dcf0ef69cc1e0e97a5a" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-entity", + "log", + "thiserror", +] + +[[package]] +name = "cranelift-object" +version = "0.69.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b25cdfa0f692f9d17626fb6ee1ecae545585f97c7a998c90423576d588ea7825" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-module", + "log", + "object", + "target-lexicon", +] + +[[package]] +name = "crc32fast" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "gust" version = "0.1.0" +dependencies = [ + "anyhow", + "cranelift", + "cranelift-module", + "cranelift-object", + "lazy_static", + "parking_lot", + "peg", + "structopt", + "target-lexicon", +] + +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" + +[[package]] +name = "heck" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +dependencies = [ + "libc", +] + +[[package]] +name = "indexmap" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" + +[[package]] +name = "lock_api" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2" +dependencies = [ + "cfg-if 0.1.10", +] + +[[package]] +name = "object" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" +dependencies = [ + "crc32fast", + "indexmap", +] + +[[package]] +name = "parking_lot" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272" +dependencies = [ + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "peg" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f76678828272f177ac33b7e2ac2e3e73cc6c1cd1e3e387928aa69562fa51367" +dependencies = [ + "peg-macros", + "peg-runtime", +] + +[[package]] +name = "peg-macros" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "636d60acf97633e48d266d7415a9355d4389cea327a193f87df395d88cd2b14d" +dependencies = [ + "peg-runtime", + "proc-macro2", + "quote", +] + +[[package]] +name = "peg-runtime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555b1514d2d99d78150d3c799d4c357a3e2c2a8062cd108e93a06d9057629c5" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "regalloc" +version = "0.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5" +dependencies = [ + "log", + "rustc-hash", + "smallvec", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "smallvec" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "structopt" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c" +dependencies = [ + "clap", + "lazy_static", + "structopt-derive", +] + +[[package]] +name = "structopt-derive" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07cb8b1b4ebf86a89ee88cbd201b022b94138c623644d035185c84d3f41b7e66" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "target-lexicon" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee5a98e506fb7231a304c3a1bd7c132a55016cf65001e0282480665870dfcb9" + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-segmentation" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" + +[[package]] +name = "unicode-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 319f87a..ea92902 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,13 @@ version = "0.1.0" authors = ["Michael Zhang "] edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] +anyhow = "1.0.38" +cranelift = "0.69.0" +cranelift-module = "0.69.0" +cranelift-object = "0.69.0" +lazy_static = "1.4.0" +parking_lot = "0.11.1" +peg = "0.6.3" +structopt = "0.3.21" +target-lexicon = "0.11.1" diff --git a/example b/example new file mode 100644 index 0000000..3b4499e --- /dev/null +++ b/example @@ -0,0 +1,7 @@ +fn main +{ +urmom(); + 5 +} + +fn urmom { 12 } diff --git a/src/ast.rs b/src/ast.rs index 7e07a2c..61c2ade 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,80 +1,41 @@ -use std::collections::HashMap; - -#[derive(Debug, Hash, PartialEq, Eq)] -pub struct Id(pub u32); +#[derive(Debug)] +pub struct Program { + pub decls: Vec, +} #[derive(Debug)] pub enum Decl { - Iface(Iface), - Impl(Impl), - Struct(Struct), - Enum(Enum), Func(Func), } -#[derive(Debug)] -pub struct Iface { - -} - -#[derive(Debug)] -pub struct Impl { - -} - -#[derive(Debug)] -pub struct Struct { - -} - -#[derive(Debug)] -pub struct Enum { - -} - #[derive(Debug)] pub struct Func { + pub name: Ident, + pub body: Expr, +} +#[derive(Debug)] +pub enum Stmt { + Expr(Expr), + Return(Expr), } #[derive(Debug)] pub enum Expr { - + Seq(Vec, Box), + FuncCall(Ident), + Lit(Lit), } -#[derive(Default, Debug)] -pub struct TypeChecker<'a> { - gen: u32, - enums: HashMap, - funcs: HashMap, +#[derive(Debug)] +pub enum Lit { + Int(i64), } -impl<'a> TypeChecker<'a> { - pub fn new() -> Self { - Self::default() - } - - fn new_id(&mut self) -> u32 { - let id = self.gen; - self.gen += 1; - id - } - - pub fn process(&mut self, decls: &'a [Decl]) { - for decl in decls.iter() { - match decl { - Decl::Enum(v) => { - let id = self.new_id(); - self.enums.insert(id, v); - } - Decl::Func(v) => { - let id = self.new_id(); - self.funcs.insert(id, v); - } - _ => {} - } - } - - println!("self: {:?}", self); - } +#[derive(Debug)] +pub enum Type { + } + +#[derive(Clone, Debug, Hash, PartialEq, Eq)] +pub struct Ident(pub String); diff --git a/src/codegen.rs b/src/codegen.rs new file mode 100644 index 0000000..c0caa55 --- /dev/null +++ b/src/codegen.rs @@ -0,0 +1,46 @@ +use anyhow::Result; +use cranelift::prelude::*; +use cranelift_module::{Linkage, Module}; + +use super::{Decl, Program}; + +impl Program { + pub fn codegen(&self, mut module: impl Module) -> Result<()> { + let mut ctx = module.make_context(); + + for decl in self.decls.iter() { + match decl { + Decl::Func(func) => { + let mut builder_ctx = FunctionBuilderContext::new(); + let mut builder = FunctionBuilder::new(&mut ctx.func, &mut builder_ctx); + let entry_block = builder.create_block(); + builder.append_block_params_for_function_params(entry_block); + builder.switch_to_block(entry_block); + builder.seal_block(entry_block); + + let int = module.target_config().pointer_type(); + let val = builder.ins().iconst(int, 12345); + builder.ins().return_(&[val]); + + builder.finalize(); + ctx.func.signature.returns.push(AbiParam::new(int)); + + let func_id = module.declare_function( + &func.name, + Linkage::Export, + &ctx.func.signature, + )?; + module.define_function( + func_id, + &mut ctx, + &mut codegen::binemit::NullTrapSink {}, + )?; + module.clear_context(&mut ctx); + } + _ => {} + } + } + + Ok(()) + } +} diff --git a/src/hir.rs b/src/hir.rs index 8b13789..3133adc 100644 --- a/src/hir.rs +++ b/src/hir.rs @@ -1 +1,34 @@ +use std::collections::HashMap; +use crate::ast::{Program, Decl, Func, Type, Ident}; +use crate::utils::Id; + +#[derive(Debug)] +pub struct Namespaces { + funcs: HashMap, + types: HashMap, + + func_names: HashMap, + type_names: HashMap, +} + +impl Namespaces { + pub fn create(program: Program) -> Self { + let mut funcs = HashMap::new(); + let mut types = HashMap::new(); + let mut func_names = HashMap::new(); + let mut type_names = HashMap::new(); + + for decl in program.decls { + match decl { + Decl::Func(func) => { + let id = Id::default(); + func_names.insert(func.name.clone(), id); + funcs.insert(id, func); + } + } + } + + Namespaces { funcs, types, func_names, type_names } + } +} diff --git a/src/main.rs b/src/main.rs index 772c83f..fda5a09 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,68 @@ mod ast; +mod parser; mod hir; +mod utils; -fn main() { - let ast = vec![ - ast::Decl::Enum(ast::Enum { }), - ]; +use std::fs::{File, OpenOptions}; +use std::io::{Read, Write}; +use std::path::PathBuf; - let mut tc = ast::TypeChecker::new(); - tc.process(&ast); +use anyhow::Result; +use cranelift::prelude::*; +use structopt::StructOpt; - println!("Hello, world!"); +use crate::hir::Namespaces; + +#[derive(StructOpt)] +struct Opt { + file: PathBuf, + #[structopt(name = "out", short = "o", default_value = "a.out")] + out: PathBuf, +} + +fn main() -> Result<()> { + let opt = Opt::from_args(); + + let contents = { + let mut file = File::open(&opt.file)?; + let mut contents = String::new(); + file.read_to_string(&mut contents)?; + contents + }; + + let parsed = parser::program(&contents)?; + println!("parsed: {:?}", parsed); + + let namespaces = Namespaces::create(parsed); + println!("namespaces: {:?}", namespaces); + + let isa = { + use std::str::FromStr; + use target_lexicon::triple; + let builder = settings::builder(); + let flags = settings::Flags::new(builder); + isa::lookup(triple!("x86_64-unknown-linux-gnu"))?.finish(flags) + }; + use cranelift_object::{ObjectBuilder, ObjectModule}; + let libcall_names = cranelift_module::default_libcall_names(); + let builder = ObjectBuilder::new(isa, "OSU", libcall_names)?; + let mut module = ObjectModule::new(builder); + + // parsed.codegen(&mut module)?; + + let product = module.finish(); + let out = product.emit()?; + { + let mut open_opt = OpenOptions::new(); + #[cfg(target_os = "linux")] + { + use std::os::unix::fs::OpenOptionsExt; + // open_opt.mode(0o755); + } + open_opt.create(true).write(true); + let mut file = open_opt.open(&opt.out)?; + file.write_all(&out)?; + } + + Ok(()) } diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..cfad11f --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,50 @@ +use crate::ast::*; + +peg::parser! { + grammar parser() for str { + pub rule program() -> Program + = decls:decls() _? ![_] { Program { decls } } + + rule decls() -> Vec + = hd:decl() _? tl:decls() { let mut tl = tl; tl.insert(0, hd); tl } + / { vec![] } + + rule decl() -> Decl + = d:func() { Decl::Func(d) } + + rule func() -> Func + = "fn" _ name:ident() _? "{" _? body:expr() _? "}" { Func { name, body } } + / "fn" _ name:ident() _? body:blockexpr() { Func { name, body } } + + rule stmts() -> Vec + = hd:stmt() _? tl:stmts() { let mut tl = tl; tl.insert(0, hd); tl } + / { vec![] } + + rule stmt() -> Stmt + = "return" _ v:expr() _? ";" { Stmt::Return(v) } + / v:expr() _? ";" { Stmt::Expr(v) } + + rule blockexpr() -> Expr + = "{" _? s:stmts() _? e:expr() "}" { Expr::Seq(s, Box::new(e)) } + + rule expr() -> Expr + = blockexpr() + / func:ident() _? "(" _? ")" { Expr::FuncCall(func) } + / v:lit() { Expr::Lit(v) } + + rule lit() -> Lit + = v:int() { Lit::Int(v) } + + rule int() -> i64 + = s:$(['0'..='9']+) { s.parse::().unwrap() } + + rule ident() -> Ident + = s:$([ 'a'..='z' | 'A'..='Z'] ['a'..='z' | 'A'..='Z' | '0'..='9' ]*) { Ident(s.to_string()) } + / s:$("_" ['a'..='z' | 'A'..='Z' | '0'..='9' ]+) { Ident(s.to_string()) } + / expected!("identifier") + + rule _() = [' ' | '\n' | '\t']+ + } +} + +pub use self::parser::*; diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..14ddedd --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,25 @@ +use std::sync::Arc; + +use parking_lot::Mutex; + +use lazy_static::lazy_static; + +lazy_static! { + static ref N: Arc> = Arc::new(Mutex::new(0)); +} + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Id(usize); + +impl Default for Id { + fn default() -> Self { + Id(gen_int()) + } +} + +pub fn gen_int() -> usize { + let mut n = N.lock(); + let res = *n; + *n += 1; + res +}