diff --git a/.builds/ci.yml b/.builds/ci.yml index 7d3bf99..aba3a23 100644 --- a/.builds/ci.yml +++ b/.builds/ci.yml @@ -3,7 +3,7 @@ packages: - rust - node sources: - - https://git.sr.ht/~garritfra/sabre#master + - https://git.sr.ht/~garritfra/sabre tasks: - build: | cargo build diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bd39dac..0b36744 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - name: Install LLVM and Clang + uses: KyleMayes/install-llvm-action@v1 + with: + version: "10" + directory: ${{ runner.temp }}/llvm - uses: actions-rs/toolchain@v1 with: profile: minimal @@ -22,6 +27,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - name: Install LLVM and Clang + uses: KyleMayes/install-llvm-action@v1 + with: + version: "10" + directory: ${{ runner.temp }}/llvm - uses: actions-rs/toolchain@v1 with: profile: minimal @@ -36,6 +46,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - name: Install LLVM and Clang + uses: KyleMayes/install-llvm-action@v1 + with: + version: "10" + directory: ${{ runner.temp }}/llvm - uses: actions-rs/toolchain@v1 with: profile: minimal @@ -52,6 +67,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - name: Install LLVM and Clang + uses: KyleMayes/install-llvm-action@v1 + with: + version: "10" + directory: ${{ runner.temp }}/llvm - uses: actions-rs/toolchain@v1 with: profile: minimal diff --git a/.gitignore b/.gitignore index 09dbe4c..4a9063a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ target/ .vscode/ examples_out/ tests_out/ -book/ \ No newline at end of file +book/ +examples/playground.sb \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index da272ca..b38bcf4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,14 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + [[package]] name = "ansi_term" version = "0.11.0" @@ -26,12 +35,24 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "cc" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" + [[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" @@ -47,13 +68,19 @@ dependencies = [ "vec_map", ] +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + [[package]] name = "getrandom" version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "wasi", ] @@ -76,6 +103,41 @@ dependencies = [ "libc", ] +[[package]] +name = "inkwell" +version = "0.1.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fe0be1e47c0c0f3da4397693e08f5d78329ae095c25d529e12ade78420fb41" +dependencies = [ + "either", + "inkwell_internals", + "libc", + "llvm-sys", + "once_cell", + "parking_lot", + "regex", +] + +[[package]] +name = "inkwell_internals" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e1f71330ccec54ee62533ae88574c4169b67fb4b95cbb1196a1322582abd11" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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" @@ -88,6 +150,65 @@ version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" +[[package]] +name = "llvm-sys" +version = "100.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9109e19fbfac3458f2970189719fa19f1007c6fd4e08c44fdebf4be0ddbe261d" +dependencies = [ + "cc", + "lazy_static", + "libc", + "regex", + "semver", +] + +[[package]] +name = "lock_api" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] +name = "once_cell" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" + +[[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 = "ppv-lite86" version = "0.2.10" @@ -183,6 +304,24 @@ version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +[[package]] +name = "regex" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -228,6 +367,7 @@ dependencies = [ name = "sabre-lang" version = "0.2.1" dependencies = [ + "inkwell", "rust-embed", "structopt", "tempfile", @@ -242,6 +382,33 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[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" @@ -289,7 +456,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "rand", "redox_syscall", @@ -306,6 +473,15 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thread_local" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +dependencies = [ + "once_cell", +] + [[package]] name = "unicode-segmentation" version = "1.7.1" diff --git a/Cargo.toml b/Cargo.toml index c4d2e1e..abf3f0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,10 +17,15 @@ path = "src/main.rs" [features] backend_c = [] backend_node = [] +backend_llvm = ["inkwell"] +# To change, use the --featues flag: +# cargo run --features backend_llvm default = ["backend_node"] [dependencies] structopt = "0.3.21" rust-embed = "5.7.0" tempfile = "3.1.0" +inkwell = { version = "0.1.0-beta.2", features = ["llvm10-0"], optional = true } + diff --git a/docs/developers/backends.md b/docs/developers/backends.md index 4a16fb3..1ac62c2 100644 --- a/docs/developers/backends.md +++ b/docs/developers/backends.md @@ -10,9 +10,16 @@ The backend can be specified in the `Cargo.toml` file in the root of the project default = ["backend_c"] ``` +If you're working on an unstable backend, you can override the backend using the `--features` flag of the cargo CLI: + +``` +cargo run --features backend_llvm ... +``` + ## Available Backends | Target Language | Identifier | Stability notice | | :-------------- | :------------- | :--------------- | | Node.js | `backend_node` | mostly stable | +| LLVM | `backend_llvm` | unstable | | C | `backend_c` | unstable | diff --git a/examples/playground.sb b/examples/playground.sb deleted file mode 100644 index 3ed3f25..0000000 --- a/examples/playground.sb +++ /dev/null @@ -1,9 +0,0 @@ -fn main() { - my_print([1, 2, 3]) -} - -fn my_print(x: int[]) { - for i in x { - println(i) - } -} \ No newline at end of file diff --git a/src/generator/llvm.rs b/src/generator/llvm.rs new file mode 100644 index 0000000..afd5b57 --- /dev/null +++ b/src/generator/llvm.rs @@ -0,0 +1,33 @@ +use crate::generator::Generator; +use crate::parser::node_type::*; +use inkwell::builder::Builder; +use inkwell::context::Context; +use inkwell::module::Module; +use inkwell::targets::{InitializationConfig, Target}; + +pub struct LLVMGenerator<'ctx> { + ctx: &'ctx Context, + module: Module<'ctx>, +} + +impl<'ctx> Generator for LLVMGenerator<'ctx> { + fn generate(prog: Program) -> String { + let ctx = Context::create(); + let module = ctx.create_module("main"); + let mut generator = LLVMGenerator { + ctx: &ctx, + module: module, + }; + for func in prog.func { + generator.generate_function(func); + } + generator.module.print_to_string().to_string() + } +} + +impl<'ctx> LLVMGenerator<'ctx> { + fn generate_function(&mut self, func: Function) { + self.module + .add_function(&func.name, self.ctx.void_type().fn_type(&[], false), None); + } +} diff --git a/src/generator/mod.rs b/src/generator/mod.rs index 8f2f045..482009f 100644 --- a/src/generator/mod.rs +++ b/src/generator/mod.rs @@ -15,8 +15,12 @@ */ use crate::parser::node_type::*; +#[cfg(feature = "backend_c")] pub mod c; +#[cfg(feature = "backend_node")] pub mod js; +#[cfg(feature = "backend_llvm")] +pub mod llvm; #[cfg(test)] mod tests; pub mod x86; @@ -26,11 +30,14 @@ pub trait Generator { } pub fn generate(prog: Program) -> String { - if cfg!(feature = "backend_c") { - c::CGenerator::generate(prog) - } else if cfg!(feature = "backend_node") { - js::JsGenerator::generate(prog) - } else { - panic!("No backend specified") - } + #[cfg(feature = "backend_llvm")] + return llvm::LLVMGenerator::generate(prog); + + #[cfg(feature = "backend_c")] + return c::CGenerator::generate(prog); + + #[cfg(feature = "backend_node")] + return js::JsGenerator::generate(prog); + + panic!("No backend specified"); } diff --git a/src/generator/tests/mod.rs b/src/generator/tests/mod.rs index 8999cd3..4e807ca 100644 --- a/src/generator/tests/mod.rs +++ b/src/generator/tests/mod.rs @@ -1 +1,2 @@ +#[cfg(feature = "backend_c")] mod c_tests;