├── .cargo └── config.toml ├── .github └── workflows │ └── test.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── README.md ├── crates ├── aqua │ ├── Cargo.toml │ ├── build.rs │ ├── src │ │ ├── input.rs │ │ ├── logging.rs │ │ ├── main.rs │ │ └── version.rs │ └── x.aqua ├── compiler │ ├── Cargo.lock │ ├── Cargo.toml │ ├── benches │ │ └── benchmarks.rs │ ├── fuzz │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── fuzz_targets │ │ │ ├── fuzz_lexer.rs │ │ │ └── fuzz_parser.rs │ ├── src │ │ ├── analysis │ │ │ ├── check.rs │ │ │ ├── declare.rs │ │ │ ├── lookup.rs │ │ │ ├── mod.rs │ │ │ └── reachable.rs │ │ ├── ast │ │ │ ├── display.rs │ │ │ ├── mod.rs │ │ │ ├── passes │ │ │ │ ├── capture.rs │ │ │ │ ├── desugar.rs │ │ │ │ ├── expand.rs │ │ │ │ ├── flatten.rs │ │ │ │ ├── infer │ │ │ │ │ ├── annotate.rs │ │ │ │ │ ├── apply.rs │ │ │ │ │ ├── canonicalize.rs │ │ │ │ │ ├── defaults.rs │ │ │ │ │ ├── expand.rs │ │ │ │ │ ├── gather_goals.rs │ │ │ │ │ ├── impl_var.rs │ │ │ │ │ ├── instantiate.rs │ │ │ │ │ ├── local.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── primitives.rs │ │ │ │ │ ├── solver.rs │ │ │ │ │ ├── type_var.rs │ │ │ │ │ └── unify.rs │ │ │ │ ├── lift.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── monomorphise │ │ │ │ │ ├── mangle.rs │ │ │ │ │ └── mod.rs │ │ │ │ ├── query_desugar.rs │ │ │ │ └── resolve.rs │ │ │ └── utils │ │ │ │ ├── constructors.rs │ │ │ │ ├── downcasts.rs │ │ │ │ ├── get_loans.rs │ │ │ │ ├── get_span.rs │ │ │ │ ├── get_type.rs │ │ │ │ ├── key.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── upcasts.rs │ │ │ │ ├── utils.rs │ │ │ │ ├── with_span.rs │ │ │ │ └── with_type.rs │ │ ├── backend │ │ │ ├── codegen.rs │ │ │ ├── host │ │ │ │ ├── cpp.rs │ │ │ │ ├── java.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── profile.log │ │ │ │ └── rust.rs │ │ │ ├── mod.rs │ │ │ ├── name_generator │ │ │ │ ├── adjectives.rs │ │ │ │ ├── mod.rs │ │ │ │ └── nouns.rs │ │ │ └── runtime │ │ │ │ ├── flink │ │ │ │ ├── mod.rs │ │ │ │ ├── package.rs │ │ │ │ └── pom-template.xml │ │ │ │ ├── mod.rs │ │ │ │ └── native │ │ │ │ ├── mod.rs │ │ │ │ └── package.rs │ │ ├── builtins │ │ │ ├── conv.rs │ │ │ ├── functions │ │ │ │ └── io.rs │ │ │ ├── mod.rs │ │ │ ├── traits │ │ │ │ ├── add.rs │ │ │ │ ├── clone.rs │ │ │ │ ├── copy.rs │ │ │ │ ├── data.rs │ │ │ │ ├── debug.rs │ │ │ │ ├── deep_clone.rs │ │ │ │ ├── default.rs │ │ │ │ ├── display.rs │ │ │ │ ├── div.rs │ │ │ │ ├── eq.rs │ │ │ │ ├── fun.rs │ │ │ │ ├── hash.rs │ │ │ │ ├── into_iterator.rs │ │ │ │ ├── iterator.rs │ │ │ │ ├── mul.rs │ │ │ │ ├── neg.rs │ │ │ │ ├── not.rs │ │ │ │ ├── ord.rs │ │ │ │ ├── partial_eq.rs │ │ │ │ ├── partial_ord.rs │ │ │ │ ├── serde.rs │ │ │ │ └── sub.rs │ │ │ ├── types │ │ │ │ ├── array.rs │ │ │ │ ├── backend.rs │ │ │ │ ├── bag.rs │ │ │ │ ├── blob.rs │ │ │ │ ├── bool.rs │ │ │ │ ├── char.rs │ │ │ │ ├── dataflow.rs │ │ │ │ ├── dict.rs │ │ │ │ ├── duration.rs │ │ │ │ ├── f32.rs │ │ │ │ ├── f64.rs │ │ │ │ ├── file.rs │ │ │ │ ├── format.rs │ │ │ │ ├── function.rs │ │ │ │ ├── i128.rs │ │ │ │ ├── i16.rs │ │ │ │ ├── i32.rs │ │ │ │ ├── i64.rs │ │ │ │ ├── i8.rs │ │ │ │ ├── image.rs │ │ │ │ ├── instance.rs │ │ │ │ ├── iterator.rs │ │ │ │ ├── keyed_stream.rs │ │ │ │ ├── matrix.rs │ │ │ │ ├── model.rs │ │ │ │ ├── never.rs │ │ │ │ ├── option.rs │ │ │ │ ├── ordering.rs │ │ │ │ ├── path.rs │ │ │ │ ├── range.rs │ │ │ │ ├── reader.rs │ │ │ │ ├── record.rs │ │ │ │ ├── result.rs │ │ │ │ ├── set.rs │ │ │ │ ├── socket.rs │ │ │ │ ├── storage.rs │ │ │ │ ├── stream.rs │ │ │ │ ├── string.rs │ │ │ │ ├── time.rs │ │ │ │ ├── tuple.rs │ │ │ │ ├── u128.rs │ │ │ │ ├── u16.rs │ │ │ │ ├── u32.rs │ │ │ │ ├── u64.rs │ │ │ │ ├── u8.rs │ │ │ │ ├── unit.rs │ │ │ │ ├── url.rs │ │ │ │ ├── usize.rs │ │ │ │ ├── variant.rs │ │ │ │ ├── vec.rs │ │ │ │ ├── window.rs │ │ │ │ └── writer.rs │ │ │ └── value.rs │ │ ├── collections │ │ │ ├── concurrent.rs │ │ │ ├── keyvec.rs │ │ │ ├── map.rs │ │ │ ├── mod.rs │ │ │ ├── ordmap.rs │ │ │ └── set.rs │ │ ├── ffi.rs │ │ ├── interpret.rs │ │ ├── lib.rs │ │ ├── mir │ │ │ ├── display.rs │ │ │ ├── mod.rs │ │ │ ├── passes │ │ │ │ ├── borrowck.rs │ │ │ │ ├── constant_propagation.rs │ │ │ │ ├── dominators.rs │ │ │ │ ├── lexer.rs │ │ │ │ ├── liveness.rs │ │ │ │ ├── merge_blocks.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── remove_unreachable.rs │ │ │ │ └── remove_unused.rs │ │ │ └── utils │ │ │ │ ├── constructors.rs │ │ │ │ └── mod.rs │ │ ├── opt │ │ │ ├── free.egg │ │ │ ├── from_egg.rs │ │ │ ├── into_egg.rs │ │ │ ├── lib.egg │ │ │ ├── mod.rs │ │ │ ├── sugar.egg │ │ │ └── typeof.egg │ │ ├── print.rs │ │ ├── report.rs │ │ ├── syntax │ │ │ ├── lexer.rs │ │ │ ├── lookahead.rs │ │ │ ├── mod.rs │ │ │ ├── parser.rs │ │ │ ├── precedence.rs │ │ │ ├── source.rs │ │ │ ├── span.rs │ │ │ ├── spanned.rs │ │ │ ├── splice.rs │ │ │ ├── symbol.rs │ │ │ └── token.rs │ │ ├── transforms │ │ │ ├── ast_to_mir.rs │ │ │ ├── mir_to_ast.rs │ │ │ └── mod.rs │ │ └── traversal │ │ │ ├── mappable.rs │ │ │ ├── mapper.rs │ │ │ ├── mod.rs │ │ │ ├── visitable.rs │ │ │ └── visitor.rs │ └── tests │ │ ├── ast_to_mir.rs │ │ ├── capture.rs │ │ ├── codegen.rs │ │ ├── common │ │ ├── check.rs │ │ ├── dsl.rs │ │ ├── mod.rs │ │ └── passes.rs │ │ ├── controlflow.rs │ │ ├── desugar.rs │ │ ├── display.rs │ │ ├── egglog.rs │ │ ├── expand.rs │ │ ├── flatten.rs │ │ ├── infer.rs │ │ ├── interpret.rs │ │ ├── lexer.rs │ │ ├── lift.rs │ │ ├── monomorphise.rs │ │ ├── opt.egg │ │ ├── optimiser.egg │ │ ├── optimiser.rs │ │ ├── parser.rs │ │ ├── querycomp.rs │ │ ├── resolve.rs │ │ ├── serde.rs │ │ ├── source.rs │ │ ├── splice.rs │ │ ├── traits.rs │ │ └── unify.rs ├── config │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── lsp │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── macros │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ ├── proc_macro_attrs.rs │ │ ├── proc_macro_attrs │ │ ├── export │ │ │ ├── functions.rs │ │ │ └── impls.rs │ │ └── rewrite │ │ │ ├── enums.rs │ │ │ ├── externs.rs │ │ │ ├── functions.rs │ │ │ ├── main.rs │ │ │ └── structs.rs │ │ ├── proc_macro_derives.rs │ │ ├── proc_macros.rs │ │ └── utils.rs ├── repl │ ├── Cargo.toml │ └── src │ │ ├── config.rs │ │ ├── helper │ │ ├── completer.rs │ │ ├── highlighter.rs │ │ ├── hinter.rs │ │ ├── mod.rs │ │ └── validator.rs │ │ └── lib.rs └── runtime │ ├── .cargo │ └── config.toml │ ├── Cargo.toml │ ├── benches │ ├── iter.rs │ └── vec.rs │ ├── src │ ├── builtins │ │ ├── array.rs │ │ ├── bag.rs │ │ ├── blob.rs │ │ ├── cell.rs │ │ ├── channel.rs │ │ ├── channel │ │ │ └── spsc.rs │ │ ├── cow.rs │ │ ├── dataflow.rs │ │ ├── dataframe.rs │ │ ├── dict.rs │ │ ├── duration.rs │ │ ├── file.rs │ │ ├── format.rs │ │ ├── im_string.rs │ │ ├── image.rs │ │ ├── keyed_stream.rs │ │ ├── keyed_stream │ │ │ ├── drain.rs │ │ │ ├── filter.rs │ │ │ ├── flat_map.rs │ │ │ ├── fork.rs │ │ │ ├── incr_window.rs │ │ │ ├── join.rs │ │ │ ├── keyby.rs │ │ │ ├── map.rs │ │ │ ├── merge.rs │ │ │ ├── scan.rs │ │ │ ├── sink.rs │ │ │ ├── unkey.rs │ │ │ ├── window.rs │ │ │ └── window │ │ │ │ ├── count_sliding_holistic.rs │ │ │ │ ├── time_sliding_aligned_commutative_associative.rs │ │ │ │ ├── time_sliding_aligned_holistic.rs │ │ │ │ ├── time_tumbling_holistic.rs │ │ │ │ └── time_tumbling_holistic_vec.rs │ │ ├── matrix.rs │ │ ├── mod.rs │ │ ├── model.rs │ │ ├── option.rs │ │ ├── path.rs │ │ ├── range.rs │ │ ├── reader.rs │ │ ├── result.rs │ │ ├── set.rs │ │ ├── socket.rs │ │ ├── stream.rs │ │ ├── stream │ │ │ ├── assert.rs │ │ │ ├── batch.rs │ │ │ ├── collect.rs │ │ │ ├── drain.rs │ │ │ ├── dyn_source.rs │ │ │ ├── filter.rs │ │ │ ├── filter_map.rs │ │ │ ├── flat_map.rs │ │ │ ├── fork.rs │ │ │ ├── join.rs │ │ │ ├── join │ │ │ │ ├── interval_join.rs │ │ │ │ ├── interval_join_forward.rs │ │ │ │ ├── tumbling_window_join.rs │ │ │ │ └── tumbling_window_join_distinct.rs │ │ │ ├── keyby.rs │ │ │ ├── map.rs │ │ │ ├── merge.rs │ │ │ ├── operator.rs │ │ │ ├── scan.rs │ │ │ ├── sink.rs │ │ │ ├── source.rs │ │ │ ├── take.rs │ │ │ ├── window.rs │ │ │ └── window │ │ │ │ ├── count_sliding_aligned_commutative_associative.rs │ │ │ │ ├── count_sliding_holistic.rs │ │ │ │ ├── count_sliding_invertible.rs │ │ │ │ ├── count_tumbling_holistic.rs │ │ │ │ ├── time_sliding_aligned_commutative_associative.rs │ │ │ │ ├── time_sliding_aligned_holistic.rs │ │ │ │ ├── time_sliding_aligned_holistic_vec.rs │ │ │ │ ├── time_sliding_commutative_invertible.rs │ │ │ │ ├── time_sliding_invertible.rs │ │ │ │ └── time_tumbling_holistic.rs │ │ ├── string.rs │ │ ├── time.rs │ │ ├── unchecked_cell.rs │ │ ├── url.rs │ │ ├── vec.rs │ │ ├── window.rs │ │ └── writer.rs │ ├── formats │ │ ├── csv │ │ │ ├── de.rs │ │ │ └── ser.rs │ │ ├── json │ │ │ ├── de.rs │ │ │ └── ser.rs │ │ └── mod.rs │ ├── lib.rs │ ├── logging │ │ └── mod.rs │ ├── runner │ │ ├── context.rs │ │ ├── current_thread.rs │ │ ├── data_parallel.rs │ │ ├── env.rs │ │ ├── mod.rs │ │ ├── pinned_data_parallel.rs │ │ ├── single_thread.rs │ │ ├── task_parallel.rs │ │ └── threadpool.rs │ ├── state │ │ └── mod.rs │ └── traits │ │ └── mod.rs │ └── tests │ ├── basic.rs │ ├── data.csv │ ├── output.csv │ └── window.rs └── examples ├── fail.aqua ├── from-where-limit-into.aqua ├── generate-data.py └── http-server.aqua /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | rustflags = ["--cfg", "tokio_unstable"] 3 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | test: 6 | name: cargo test 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | - uses: dtolnay/rust-toolchain@stable 11 | - run: cargo test 12 | 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | output/ 3 | **/__pycache__/ 4 | **/*.wasm 5 | **/.DS_Store 6 | node_modules/ 7 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["crates/*", "crates/compiler/fuzz"] 3 | default-members = ["crates/aqua"] 4 | resolver = "2" 5 | 6 | [workspace.package] 7 | version = "0.0.0" 8 | edition = "2021" 9 | authors = ["Aqua Team"] 10 | readme = "README.md" 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest 2 | 3 | # Set the noninteractive timezone (prevents configuration prompts) 4 | ARG DEBIAN_FRONTEND=noninteractive 5 | ENV TZ=Europe/London 6 | 7 | # Set a working directory 8 | WORKDIR /aqua 9 | 10 | # Install apt packages 11 | RUN apt-get update && apt-get install -y \ 12 | curl wget software-properties-common 13 | 14 | # Install Rust 15 | RUN curl https://sh.rustup.rs -sSf | sh -s -- -y 16 | ENV PATH="/root/.cargo/bin:${PATH}" 17 | 18 | # Cleanup 19 | RUN apt-get clean 20 | 21 | # Copy the Rust code into the image 22 | COPY Cargo.toml /aqua/ 23 | COPY Cargo.lock /aqua/ 24 | COPY .cargo /aqua/.cargo 25 | COPY crates /aqua/crates 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Aqua 2 | 3 | Aqua is a programming language for data stream analytics. 4 | 5 | ## Installation 6 | 7 | Install [Rust](https://www.rust-lang.org/) and then: 8 | 9 | ```bash 10 | cargo install aqua --git=https://github.com/aqua-language/aqua 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```bash 16 | aqua 17 | >> 1 + 1; 18 | 2 19 | ``` 20 | 21 | ## Links 22 | 23 | - [Website](https://aqua-language.github.io) 24 | - [Manual](https://aqua-language.github.io/Manual.pdf) 25 | - [Research](https://aqua-language.github.io/research) 26 | 27 | ## Editor Plugins 28 | 29 | If you are using Neovim, you can use the [aqua-nvim](https://github.com/aqua-language/aqua-nvim) plugin for syntax highlighting. 30 | -------------------------------------------------------------------------------- /crates/aqua/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aqua" 3 | version.workspace = true 4 | edition.workspace = true 5 | build = "build.rs" 6 | 7 | [[bin]] 8 | name = "aqua" 9 | path = "src/main.rs" 10 | 11 | [features] 12 | default = ["repl", "lsp"] 13 | 14 | [dependencies] 15 | compiler = { path = "../compiler" } 16 | repl = { path = "../repl", optional = true } 17 | lsp = { path = "../lsp", optional = true } 18 | config = { path = "../config", features = ["clap"] } 19 | colored = "2.1.0" 20 | 21 | anyhow = { version = "1.0.79" } 22 | tracing = { version = "0.1.40", features = ["release_max_level_warn"] } 23 | tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } 24 | 25 | [build-dependencies] 26 | built = { version = "0.7.1", features = ["chrono"] } 27 | -------------------------------------------------------------------------------- /crates/aqua/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | built::write_built_file().expect("Failed to acquire build-time information") 3 | } 4 | -------------------------------------------------------------------------------- /crates/aqua/src/input.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use std::io::Read; 3 | use std::path::Path; 4 | 5 | pub fn read_file(path: &Path) -> Result<(String, String)> { 6 | let name = path.display().to_string(); 7 | let source = std::fs::read_to_string(path)?; 8 | if path.is_absolute() { 9 | std::env::set_current_dir(path.parent().unwrap())?; 10 | } else { 11 | let mut relative_path = std::env::current_dir()?; 12 | relative_path.push(path); 13 | std::env::set_current_dir(relative_path.parent().unwrap())?; 14 | } 15 | tracing::info!("Updated cwd to: {}", std::env::current_dir()?.display()); 16 | Ok((name, source)) 17 | } 18 | 19 | pub fn read_stdin() -> Result<(String, String)> { 20 | let mut source = String::new(); 21 | let mut stdin = std::io::stdin(); 22 | stdin.read_to_string(&mut source)?; 23 | Ok(("stdin".to_string(), source)) 24 | } 25 | -------------------------------------------------------------------------------- /crates/aqua/src/logging.rs: -------------------------------------------------------------------------------- 1 | use std::str::FromStr; 2 | 3 | use tracing_subscriber::prelude::*; 4 | 5 | #[cfg(debug_assertions)] 6 | pub const FILTER: &str = "info,librdkafka=off,rdkafka::client=off"; 7 | 8 | #[cfg(not(debug_assertions))] 9 | pub const FILTER: &str = "warn,librdkafka=off,rdkafka::client=off"; 10 | 11 | pub fn init() { 12 | let fmt = tracing_subscriber::fmt::layer() 13 | .with_file(false) 14 | .with_line_number(false) 15 | .compact() 16 | .with_writer(std::io::stderr) 17 | .with_filter(tracing_subscriber::filter::EnvFilter::from_str(FILTER).unwrap()); 18 | tracing_subscriber::registry().with(fmt).init(); 19 | } 20 | -------------------------------------------------------------------------------- /crates/aqua/src/version.rs: -------------------------------------------------------------------------------- 1 | pub fn print() { 2 | mod build { 3 | include!(concat!(env!("OUT_DIR"), "/built.rs")); 4 | } 5 | println!(" version: {}", build::PKG_VERSION); 6 | println!(" target: {}", build::TARGET); 7 | println!(" profile: {}", build::PROFILE); 8 | println!("compiler: {}", build::RUSTC_VERSION); 9 | println!(" time: {}", build::BUILT_TIME_UTC); 10 | } 11 | -------------------------------------------------------------------------------- /crates/aqua/x.aqua: -------------------------------------------------------------------------------- 1 | def main(): i32 = 1; 2 | -------------------------------------------------------------------------------- /crates/compiler/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "compiler" 3 | version.workspace = true 4 | edition.workspace = true 5 | 6 | [features] 7 | default = [] 8 | optimiser = ["egglog", "symbol_table"] 9 | explicit = [] 10 | 11 | [dependencies] 12 | config = { path = "../config", default-features = false } 13 | runtime = { path = "../runtime", default-features = false } 14 | serde = { version = "1.0.197", features = ["derive"] } 15 | 16 | ariadne = "0.5.0" 17 | bitmask-enum = "2.2.3" 18 | append-only-vec = "0.1.3" 19 | smol_str = { version = "0.3.1", features = ["std"] } 20 | ena = "0.14.3" 21 | directories = "5.0.1" 22 | indoc = "2.0.5" 23 | tracing = "0.1.40" 24 | anyhow = "1.0.41" 25 | linkme = "0.3.28" 26 | rand = { version = "0.8.5", features = ["std"] } 27 | # libffi = { version = "3.2.0" } 28 | 29 | egglog = { git = "https://github.com/egraphs-good/egglog", rev="77ffa1f7", optional = true } 30 | symbol_table = { version = "0.3.0", optional = true } 31 | ordered-float = "3.7.0" 32 | 33 | [dev-dependencies] 34 | indoc = "2.0.5" 35 | similar = "2.5.0" 36 | serde_json = "1.0.115" 37 | divan = "0.1.15" 38 | 39 | [[test]] 40 | name = "serde" 41 | 42 | [[test]] 43 | name = "optimiser" 44 | required-features = ["optimiser"] 45 | 46 | [[bench]] 47 | name = "benchmarks" 48 | harness = false 49 | -------------------------------------------------------------------------------- /crates/compiler/fuzz/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | corpus 3 | artifacts 4 | coverage 5 | -------------------------------------------------------------------------------- /crates/compiler/fuzz/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "compiler-fuzz" 3 | version = "0.0.0" 4 | publish = false 5 | edition = "2021" 6 | 7 | [package.metadata] 8 | cargo-fuzz = true 9 | 10 | [dependencies] 11 | libfuzzer-sys = "0.4" 12 | compiler = { path = ".." } 13 | 14 | [[bin]] 15 | name = "fuzz_lexer" 16 | path = "fuzz_targets/fuzz_lexer.rs" 17 | test = false 18 | doc = false 19 | bench = false 20 | 21 | [[bin]] 22 | name = "fuzz_parser" 23 | path = "fuzz_targets/fuzz_parser.rs" 24 | test = false 25 | doc = false 26 | bench = false 27 | -------------------------------------------------------------------------------- /crates/compiler/fuzz/fuzz_targets/fuzz_lexer.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | use std::rc::Rc; 4 | 5 | use compiler::syntax::lexer::Lexer; 6 | use compiler::syntax::source::Cache; 7 | use libfuzzer_sys::fuzz_target; 8 | 9 | fuzz_target!(|data: &[u8]| { 10 | if let Ok(s) = std::str::from_utf8(data) { 11 | let mut cache = Cache::new(); 12 | let s: Rc = s.into(); 13 | let id = cache.add("test", s.clone()); 14 | for _ in Lexer::new(id, &s) {} 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /crates/compiler/fuzz/fuzz_targets/fuzz_parser.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | use std::rc::Rc; 4 | 5 | use compiler::syntax::lexer::Lexer; 6 | use compiler::syntax::parser::Parser; 7 | use compiler::syntax::source::Cache; 8 | use libfuzzer_sys::fuzz_target; 9 | 10 | fuzz_target!(|data: &[u8]| { 11 | if let Ok(s) = std::str::from_utf8(data) { 12 | let mut cache = Cache::new(); 13 | let s: Rc = s.into(); 14 | let id = cache.add("", s.clone()); 15 | let lexer = Lexer::new(id, &s); 16 | let mut parser = Parser::new(&s, lexer); 17 | parser.parse(Parser::program).unwrap(); 18 | } 19 | }); 20 | -------------------------------------------------------------------------------- /crates/compiler/src/analysis/declare.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | 3 | use runtime::prelude::Send; 4 | use runtime::prelude::Sync; 5 | 6 | use crate::ast::Impl; 7 | use crate::ast::Map; 8 | use crate::ast::Name; 9 | use crate::ast::Stmt; 10 | use crate::ast::StmtDef; 11 | use crate::ast::StmtEnum; 12 | use crate::ast::StmtImpl; 13 | use crate::ast::StmtStruct; 14 | use crate::ast::StmtTrait; 15 | use crate::ast::StmtType; 16 | use crate::traversal::visitor::Visitor; 17 | 18 | #[derive(Debug, Default, Clone, Send, Sync)] 19 | pub struct Context { 20 | pub defs: Map>, 21 | pub structs: Map>, 22 | pub enums: Map>, 23 | pub traits: Map>, 24 | pub types: Map>, 25 | pub trait_impls: Map>>, 26 | pub type_impls: Vec>, 27 | } 28 | 29 | impl Context { 30 | pub fn new() -> Context { 31 | Context::default() 32 | } 33 | } 34 | 35 | impl Visitor for Context { 36 | fn visit_stmt(&mut self, s: &Stmt) { 37 | match s { 38 | Stmt::Local(_) => {} 39 | Stmt::Def(s) => { 40 | self.defs.insert(s.name, s.clone()); 41 | } 42 | Stmt::Impl(s) => match &s.head { 43 | Impl::Trait(tr) => { 44 | self.trait_impls 45 | .entry(tr.x) 46 | .or_insert_with(Vec::new) 47 | .push(s.clone()); 48 | } 49 | Impl::Type(_) => { 50 | self.type_impls.push(s.clone()); 51 | } 52 | Impl::Path(..) => {} 53 | Impl::Err => {} 54 | Impl::Var(..) => {} 55 | Impl::Unknown => {} 56 | }, 57 | Stmt::Expr(_) => {} 58 | Stmt::Struct(s) => { 59 | self.structs.insert(s.name, s.clone()); 60 | } 61 | Stmt::Enum(s) => { 62 | self.enums.insert(s.name, s.clone()); 63 | } 64 | Stmt::Type(s) => { 65 | self.types.insert(s.name, s.clone()); 66 | } 67 | Stmt::Trait(s) => { 68 | self.traits.insert(s.name, s.clone()); 69 | } 70 | Stmt::Err(_) => {} 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /crates/compiler/src/analysis/lookup.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::Expr; 2 | use crate::ast::Ast; 3 | use crate::ast::Stmt; 4 | use crate::syntax::span::Span; 5 | use crate::traversal::visitor::Visitor; 6 | 7 | pub struct Context { 8 | span: Span, 9 | output: Option, 10 | } 11 | 12 | pub enum Output { 13 | Expr(Expr), 14 | Stmt(Stmt), 15 | } 16 | 17 | impl Context { 18 | pub fn lookup(program: &Ast, span: Span) -> Option { 19 | let mut this = Self { span, output: None }; 20 | this.visit_program(program); 21 | this.output 22 | } 23 | } 24 | 25 | impl Visitor for Context { 26 | fn visit_expr(&mut self, e: &Expr) { 27 | if self.output.is_none() && e.span().contains(&self.span) { 28 | self._visit_expr(e); 29 | if self.output.is_none() { 30 | self.output = Some(Output::Expr(e.clone())); 31 | } 32 | } 33 | } 34 | 35 | fn visit_stmt(&mut self, s: &Stmt) { 36 | if self.output.is_none() && s.span().contains(&self.span) { 37 | self._visit_stmt(s); 38 | if self.output.is_none() { 39 | self.output = Some(Output::Stmt(s.clone())); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /crates/compiler/src/analysis/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod check; 2 | pub mod declare; 3 | pub mod lookup; 4 | pub mod reachable; 5 | -------------------------------------------------------------------------------- /crates/compiler/src/analysis/reachable.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::Expr; 2 | use crate::ast::Type; 3 | use crate::builtins::value::Dataflow; 4 | use crate::analysis::declare; 5 | use crate::traversal::visitor::Visitor; 6 | 7 | pub struct Context<'a> { 8 | pub reachable: declare::Context, 9 | pub decls: &'a declare::Context, 10 | } 11 | 12 | impl declare::Context { 13 | pub fn reachable(&self, dataflow: &Dataflow) -> Self { 14 | let mut ctx = Context { 15 | reachable: declare::Context::default(), 16 | decls: self, 17 | }; 18 | ctx._visit_value_dataflow(dataflow); 19 | ctx.reachable 20 | } 21 | } 22 | 23 | impl Visitor for Context<'_> { 24 | fn visit_expr(&mut self, expr: &Expr) { 25 | if let Expr::Def(_, _, x, _) = expr { 26 | if self.reachable.defs.contains_key(x) { 27 | return; 28 | } else { 29 | let stmt = self.decls.defs.get(x).unwrap(); 30 | self.reachable.defs.insert(*x, stmt.clone()); 31 | self.visit_stmt_def(stmt); 32 | } 33 | } 34 | self._visit_expr(expr); 35 | } 36 | 37 | fn visit_type(&mut self, ty: &Type) { 38 | if let Type::Builtin(x, _) = ty { 39 | if let Some(stmt) = self.decls.enums.get(x) { 40 | if self.reachable.enums.contains_key(x) { 41 | return; 42 | } else { 43 | self.reachable.enums.insert(*x, stmt.clone()); 44 | self.visit_stmt_enum(stmt); 45 | } 46 | } 47 | if let Some(stmt) = self.decls.structs.get(x) { 48 | if self.reachable.structs.contains_key(x) { 49 | return; 50 | } else { 51 | self.reachable.structs.insert(*x, stmt.clone()); 52 | self.visit_stmt_struct(stmt); 53 | } 54 | } 55 | } 56 | self._visit_type(ty); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /crates/compiler/src/ast/passes/infer/canonicalize.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::Impl; 2 | use crate::ast::Type; 3 | use crate::traversal::mappable::Mappable; 4 | use crate::traversal::mapper::Mapper; 5 | 6 | use super::Constraint; 7 | use super::Context; 8 | 9 | pub struct Canonicalize<'a>(&'a mut Context); 10 | 11 | impl<'a> Canonicalize<'a> { 12 | pub fn new(ctx: &'a mut Context) -> Canonicalize<'a> { 13 | Canonicalize(ctx) 14 | } 15 | } 16 | 17 | impl<'a> Mapper for Canonicalize<'a> { 18 | fn map_type(&mut self, t: &Type) -> Type { 19 | if let Type::Var(x) = t { 20 | Type::Var(self.0.type_ctx().type_union_find.find(*x)) 21 | } else { 22 | self._map_type(t) 23 | } 24 | } 25 | } 26 | 27 | impl Impl { 28 | pub fn canonicalize(&self, ctx: &mut Context) -> Impl { 29 | self.map(&mut Canonicalize::new(ctx)) 30 | } 31 | } 32 | 33 | impl Constraint { 34 | pub fn canonicalize(&self, ctx: &mut Context) -> Constraint { 35 | self.map(&mut Canonicalize::new(ctx)) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /crates/compiler/src/ast/passes/infer/defaults.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::passes::infer::primitives::default_float; 2 | use crate::ast::passes::infer::primitives::default_int; 3 | use crate::ast::passes::infer::type_var::TypeVarKind; 4 | use crate::ast::passes::infer::type_var::TypeVarValue; 5 | use crate::ast::passes::infer::Context; 6 | use crate::ast::Ast; 7 | use crate::ast::Impl; 8 | use crate::ast::StmtDef; 9 | use crate::ast::Type; 10 | use crate::traversal::visitor::Visitor; 11 | 12 | use super::Constraint; 13 | 14 | #[derive(Debug)] 15 | pub struct Defaults<'a>(&'a mut Context); 16 | 17 | impl Defaults<'_> { 18 | pub fn new<'a>(ctx: &'a mut Context) -> Defaults<'a> { 19 | Defaults(ctx) 20 | } 21 | } 22 | 23 | impl<'a> Visitor for Defaults<'a> { 24 | fn visit_type(&mut self, ty: &Type) { 25 | match ty { 26 | Type::Var(x) => { 27 | if let TypeVarValue::Unknown(k) = self.0.get_type_value(*x) { 28 | match k { 29 | TypeVarKind::Int => self.0.union_type_value(*x, default_int()), 30 | TypeVarKind::Float => self.0.union_type_value(*x, default_float()), 31 | _ => self._visit_type(ty), 32 | } 33 | } 34 | } 35 | _ => self._visit_type(ty), 36 | } 37 | } 38 | } 39 | 40 | impl Impl { 41 | /// Set default values for all type variables in a trait. 42 | pub fn defaults(&self, ctx: &mut Context) { 43 | Defaults::new(ctx).visit_impl(self); 44 | } 45 | } 46 | 47 | impl Ast { 48 | /// Set default values for all type variables in a program. 49 | pub fn defaults(&self, ctx: &mut Context) { 50 | Defaults::new(ctx).visit_program(self); 51 | } 52 | } 53 | 54 | impl StmtDef { 55 | /// Set default values for all type variables in a statement definition. 56 | pub fn defaults(&self, ctx: &mut Context) { 57 | Defaults::new(ctx).visit_stmt_def(self); 58 | } 59 | } 60 | 61 | impl Constraint { 62 | /// Set default values for all type variables in a constraint. 63 | pub fn defaults(&self, ctx: &mut Context) { 64 | Defaults::new(ctx).visit_constraint(self); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /crates/compiler/src/ast/passes/infer/expand.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | 3 | use crate::ast::Ast; 4 | use crate::ast::Stmt; 5 | use crate::ast::Impl; 6 | use crate::ast::Type; 7 | use crate::traversal::mappable::Mappable; 8 | use crate::traversal::mapper::Mapper; 9 | 10 | use super::Constraint; 11 | 12 | pub struct Expand; 13 | 14 | impl Expand { 15 | pub fn new() -> Expand { 16 | Expand 17 | } 18 | } 19 | 20 | impl Mapper for Expand { 21 | fn map_type(&mut self, t0: &Type) -> Type { 22 | if let Type::Assoc(_b, _x, _) = t0 { 23 | todo!() 24 | // if let Some(t1) = b.as_trait().unwrap().xts.get(x) { 25 | // t1.map(self) 26 | // } else { 27 | // t0.clone() 28 | // } 29 | } else { 30 | self._map_type(t0) 31 | } 32 | } 33 | 34 | fn map_stmt(&mut self, s: &Stmt) -> Stmt { 35 | match s { 36 | Stmt::Local(s) => Stmt::Local(Rc::new(self.map_stmt_local(s))), 37 | Stmt::Expr(s) => Stmt::Expr(Rc::new(self.map_expr(s))), 38 | _ => s.clone(), 39 | } 40 | } 41 | } 42 | 43 | impl Impl { 44 | /// Expand all associated types in a trait. 45 | pub fn expand(&self) -> Impl { 46 | self.map(&mut Expand::new()) 47 | } 48 | } 49 | 50 | impl Ast { 51 | /// Expand all associated types in a program. 52 | pub fn expand(&self) -> Ast { 53 | self.map(&mut Expand::new()) 54 | } 55 | } 56 | 57 | impl Type { 58 | /// Expand all associated types in a type. 59 | pub fn expand(&self) -> Type { 60 | self.map(&mut Expand::new()) 61 | } 62 | } 63 | 64 | impl Constraint { 65 | /// Expand all associated types in a constraint. 66 | pub fn expand(&self) -> Constraint { 67 | self.map(&mut Expand::new()) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /crates/compiler/src/ast/passes/infer/gather_goals.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::Expr; 2 | use crate::ast::Ast; 3 | use crate::ast::Stmt; 4 | use crate::ast::Type; 5 | use crate::syntax::span::Span; 6 | use crate::traversal::visitable::Visitable; 7 | use crate::traversal::visitor::Visitor; 8 | 9 | use super::Constraint; 10 | use super::Context; 11 | 12 | struct GatherConstraints<'a> { 13 | ctx: &'a mut Context, 14 | span: Span, 15 | } 16 | 17 | impl GatherConstraints<'_> { 18 | pub fn new<'a>(ctx: &'a mut Context, span: Span) -> GatherConstraints<'a> { 19 | GatherConstraints { ctx, span } 20 | } 21 | } 22 | 23 | impl Visitor for GatherConstraints<'_> { 24 | fn visit_type(&mut self, t: &Type) { 25 | self._visit_type(t); 26 | if let Type::Assoc(i, x, ts) = t { 27 | self.ctx.add_constraint(Constraint::AssocType( 28 | self.span, 29 | t.clone(), 30 | i.clone(), 31 | *x, 32 | ts.clone(), 33 | )) 34 | } 35 | } 36 | 37 | fn visit_expr(&mut self, e: &Expr) { 38 | self.span = e.span(); 39 | self._visit_expr(e); 40 | if let Expr::Assoc(s, t, i, x, ts) = e { 41 | self.ctx.add_constraint(Constraint::AssocDef( 42 | *s, 43 | t.clone(), 44 | i.clone(), 45 | *x, 46 | ts.clone(), 47 | )) 48 | } 49 | } 50 | 51 | fn visit_stmt(&mut self, s: &Stmt) { 52 | self.span = s.span(); 53 | match s { 54 | Stmt::Local(s) => self.visit_stmt_var(s), 55 | Stmt::Expr(s) => self.visit_expr(s), 56 | _ => {} 57 | } 58 | } 59 | } 60 | 61 | impl Ast { 62 | pub fn gather_constraints(&self, ctx: &mut Context) { 63 | self.visit(&mut GatherConstraints::new(ctx, self.span)); 64 | } 65 | } 66 | 67 | impl Type { 68 | pub fn gather_constraints(&self, ctx: &mut Context) { 69 | self.visit(&mut GatherConstraints::new(ctx, Span::default())); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /crates/compiler/src/ast/passes/infer/impl_var.rs: -------------------------------------------------------------------------------- 1 | use ena::unify::NoError; 2 | use ena::unify::UnifyKey; 3 | use ena::unify::UnifyValue; 4 | 5 | use crate::ast::Impl; 6 | use crate::ast::ImplVar; 7 | 8 | impl UnifyKey for ImplVar { 9 | type Value = ImplVarValue; 10 | 11 | fn index(&self) -> u32 { 12 | self.0 13 | } 14 | 15 | fn from_index(i: u32) -> Self { 16 | ImplVar(i) 17 | } 18 | 19 | fn tag() -> &'static str { 20 | "ImplVar" 21 | } 22 | } 23 | 24 | #[derive(Debug, Clone)] 25 | pub enum ImplVarValue { 26 | Known(Impl), 27 | Unknown, 28 | } 29 | 30 | impl ImplVarValue { 31 | pub fn known(self) -> Option { 32 | match self { 33 | ImplVarValue::Known(t) => Some(t), 34 | ImplVarValue::Unknown => None, 35 | } 36 | } 37 | 38 | pub fn is_unknown(self) -> bool { 39 | match self { 40 | ImplVarValue::Known(_) => false, 41 | ImplVarValue::Unknown => true, 42 | } 43 | } 44 | } 45 | 46 | impl std::fmt::Display for ImplVarValue { 47 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 48 | match self { 49 | ImplVarValue::Known(t) => write!(f, "{}", t), 50 | ImplVarValue::Unknown => write!(f, ""), 51 | } 52 | } 53 | } 54 | 55 | impl UnifyValue for ImplVarValue { 56 | type Error = NoError; 57 | 58 | fn unify_values(t0: &ImplVarValue, t1: &ImplVarValue) -> Result { 59 | use ImplVarValue::*; 60 | match (t0, t1) { 61 | (Unknown, Unknown) => Ok(Unknown), 62 | (Unknown, t) | (t, Unknown) => Ok(t.clone()), 63 | (Known(_), Known(_)) => unreachable!(), 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /crates/compiler/src/ast/passes/infer/local.rs: -------------------------------------------------------------------------------- 1 | // #[derive(Debug)] 2 | // pub struct InferContext { 3 | // pub table: InPlaceUnificationTable, 4 | // pub goals: Vec, 5 | // pub where_clause: Vec, 6 | // } 7 | -------------------------------------------------------------------------------- /crates/compiler/src/ast/passes/infer/primitives.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::Name; 2 | use crate::ast::Type; 3 | 4 | pub fn ints() -> impl Iterator { 5 | [ 6 | "i8".into(), 7 | "i32".into(), 8 | "i64".into(), 9 | "i128".into(), 10 | "u8".into(), 11 | "u32".into(), 12 | "u64".into(), 13 | "u128".into(), 14 | ] 15 | .into_iter() 16 | } 17 | 18 | pub fn floats() -> impl Iterator { 19 | ["f32".into(), "f64".into()].into_iter() 20 | } 21 | 22 | pub fn bool() -> Type { 23 | Type::Builtin("bool".into(), vec![]) 24 | } 25 | 26 | pub fn char() -> Type { 27 | Type::Builtin("char".into(), vec![]) 28 | } 29 | 30 | pub fn string() -> Type { 31 | Type::Builtin("String".into(), vec![]) 32 | } 33 | 34 | pub fn default_int() -> Type { 35 | Type::Builtin("i32".into(), vec![]) 36 | } 37 | 38 | pub fn default_float() -> Type { 39 | Type::Builtin("f64".into(), vec![]) 40 | } 41 | -------------------------------------------------------------------------------- /crates/compiler/src/ast/passes/infer/unify.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aqua-language/aqua/4e71a025d373e3284d17b4475af5dba33aba95ea/crates/compiler/src/ast/passes/infer/unify.rs -------------------------------------------------------------------------------- /crates/compiler/src/ast/passes/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::Ast; 2 | use crate::report::Report; 3 | 4 | pub mod capture; 5 | pub mod desugar; 6 | pub mod expand; 7 | pub mod flatten; 8 | pub mod infer; 9 | pub mod lift; 10 | pub mod monomorphise; 11 | pub mod query_desugar; 12 | pub mod resolve; 13 | 14 | pub trait Pass: std::fmt::Debug { 15 | fn run(&mut self, program: &Ast) -> Ast; 16 | fn report(&mut self) -> &mut Report; 17 | } 18 | -------------------------------------------------------------------------------- /crates/compiler/src/ast/utils/get_loans.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::Loan; 2 | use crate::ast::Type; 3 | use crate::traversal::visitor::Visitor; 4 | 5 | struct GetLoans { 6 | loans: Vec, 7 | } 8 | 9 | impl Type { 10 | pub fn loans(&self) -> Vec { 11 | let mut get_loans = GetLoans::new(); 12 | get_loans.visit_type(self); 13 | get_loans.loans 14 | } 15 | } 16 | 17 | impl GetLoans { 18 | pub fn new() -> GetLoans { 19 | GetLoans { loans: Vec::new() } 20 | } 21 | } 22 | 23 | impl Visitor for GetLoans { 24 | fn visit_type(&mut self, t: &Type) { 25 | if let Type::Ref(loans, _, _) = t { 26 | self.loans.extend(loans.iter().cloned()); 27 | } 28 | self._visit_type(t); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /crates/compiler/src/ast/utils/key.rs: -------------------------------------------------------------------------------- 1 | use crate::collections::keyvec::Key; 2 | 3 | use crate::ast::Local; 4 | use crate::ast::Name; 5 | use crate::ast::StmtDef; 6 | use crate::ast::StmtEnum; 7 | use crate::ast::StmtStruct; 8 | use crate::ast::StmtTrait; 9 | use crate::ast::StmtTraitDef; 10 | use crate::ast::StmtTraitType; 11 | use crate::ast::StmtType; 12 | use crate::ast::StmtLocal; 13 | 14 | impl Key for StmtDef { 15 | type K = Name; 16 | fn key(&self) -> &Self::K { 17 | &self.name 18 | } 19 | } 20 | 21 | impl Key for StmtLocal { 22 | type K = Name; 23 | fn key(&self) -> &Self::K { 24 | &self.local.name 25 | } 26 | } 27 | 28 | impl Key for StmtEnum { 29 | type K = Name; 30 | fn key(&self) -> &Self::K { 31 | &self.name 32 | } 33 | } 34 | 35 | impl Key for StmtType { 36 | type K = Name; 37 | fn key(&self) -> &Self::K { 38 | &self.name 39 | } 40 | } 41 | 42 | impl Key for StmtTrait { 43 | type K = Name; 44 | fn key(&self) -> &Self::K { 45 | &self.name 46 | } 47 | } 48 | 49 | impl Key for StmtStruct { 50 | type K = Name; 51 | fn key(&self) -> &Self::K { 52 | &self.name 53 | } 54 | } 55 | 56 | impl Key for StmtTraitDef { 57 | type K = Name; 58 | fn key(&self) -> &Self::K { 59 | &self.name 60 | } 61 | } 62 | 63 | impl Key for StmtTraitType { 64 | type K = Name; 65 | fn key(&self) -> &Self::K { 66 | &self.name 67 | } 68 | } 69 | 70 | impl Key for Local { 71 | type K = Name; 72 | fn key(&self) -> &Self::K { 73 | &self.name 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /crates/compiler/src/ast/utils/mod.rs: -------------------------------------------------------------------------------- 1 | mod constructors; 2 | mod downcasts; 3 | mod get_span; 4 | mod get_type; 5 | pub mod key; 6 | mod upcasts; 7 | mod utils; 8 | mod with_span; 9 | mod with_type; 10 | pub mod get_loans; 11 | -------------------------------------------------------------------------------- /crates/compiler/src/backend/codegen.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::Block; 2 | use crate::ast::Expr; 3 | use crate::ast::Local; 4 | use crate::ast::Name; 5 | use crate::ast::Ast; 6 | use crate::ast::Stmt; 7 | use crate::ast::StmtDef; 8 | use crate::ast::StmtEnum; 9 | use crate::ast::StmtStruct; 10 | use crate::ast::StmtType; 11 | use crate::ast::StmtLocal; 12 | use crate::ast::Type; 13 | use crate::builtins::value::Function; 14 | use crate::print::Print; 15 | 16 | pub trait Codegen<'a>: Print<'a> { 17 | fn program(&mut self, p: &Ast) -> std::fmt::Result; 18 | 19 | fn local(&mut self, l: &Local) -> std::fmt::Result; 20 | 21 | fn stmt(&mut self, s: &Stmt) -> std::fmt::Result; 22 | 23 | fn stmt_var(&mut self, s: &StmtLocal) -> std::fmt::Result; 24 | 25 | fn stmt_def(&mut self, s: &StmtDef) -> std::fmt::Result; 26 | 27 | fn stmt_expr(&mut self, s: &Expr) -> std::fmt::Result; 28 | 29 | fn stmt_struct(&mut self, s: &StmtStruct) -> std::fmt::Result; 30 | 31 | fn stmt_enum(&mut self, s: &StmtEnum) -> std::fmt::Result; 32 | 33 | fn stmt_type(&mut self, s: &StmtType) -> std::fmt::Result; 34 | 35 | fn expr(&mut self, e: &Expr) -> std::fmt::Result; 36 | 37 | fn block(&mut self, b: &Block) -> std::fmt::Result; 38 | 39 | fn field_expr(&mut self, xt: &(Name, Expr)) -> std::fmt::Result; 40 | 41 | fn field(&mut self, xt: &(Name, Type)) -> std::fmt::Result; 42 | 43 | fn ty(&mut self, t: &Type) -> std::fmt::Result; 44 | 45 | fn label(&mut self, l: &Option) -> std::fmt::Result; 46 | 47 | fn fun(&mut self, f: &Function) -> std::fmt::Result; 48 | 49 | fn fields( 50 | &mut self, 51 | items: &[T], 52 | f: impl Fn(&mut Self, &T) -> std::fmt::Result, 53 | ) -> std::fmt::Result; 54 | } 55 | -------------------------------------------------------------------------------- /crates/compiler/src/backend/host/cpp.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aqua-language/aqua/4e71a025d373e3284d17b4475af5dba33aba95ea/crates/compiler/src/backend/host/cpp.rs -------------------------------------------------------------------------------- /crates/compiler/src/backend/host/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod rust; 2 | pub mod java; 3 | pub mod cpp; 4 | -------------------------------------------------------------------------------- /crates/compiler/src/backend/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod host; 2 | pub mod name_generator; 3 | pub mod runtime; 4 | pub mod codegen; 5 | -------------------------------------------------------------------------------- /crates/compiler/src/backend/name_generator/mod.rs: -------------------------------------------------------------------------------- 1 | use std::sync::LazyLock; 2 | use std::sync::Mutex; 3 | 4 | use adjectives::ADJECTIVES; 5 | use nouns::NOUNS; 6 | use rand::rngs::OsRng; 7 | use rand::Rng; 8 | mod adjectives; 9 | mod nouns; 10 | 11 | pub static NAME_GENERATOR: LazyLock> = 12 | LazyLock::new(|| Mutex::new(NameGenerator::new())); 13 | 14 | pub struct NameGenerator(OsRng); 15 | 16 | impl NameGenerator { 17 | pub fn new() -> NameGenerator { 18 | NameGenerator(OsRng::default()) 19 | } 20 | 21 | pub fn generate(&mut self) -> String { 22 | let adjective = ADJECTIVES[self.0.gen_range(0..ADJECTIVES.len())]; 23 | let noun = NOUNS[self.0.gen_range(0..NOUNS.len())]; 24 | let time = std::time::SystemTime::now() 25 | .duration_since(std::time::UNIX_EPOCH) 26 | .expect("Time went backwards") 27 | .as_secs(); 28 | format!("{}-{}-{}", adjective, noun, time) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /crates/compiler/src/backend/runtime/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod flink; 2 | pub mod native; 3 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/functions/io.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::value::Tuple; 2 | use crate::builtins::Context; 3 | use crate::builtins::Decl; 4 | 5 | use linkme::distributed_slice; 6 | 7 | use crate::builtins::DECLS; 8 | 9 | #[distributed_slice(DECLS)] 10 | fn declare(ctx: &mut Context) { 11 | ctx.declare(Decl::Def { 12 | docs: "", 13 | aqua: "def print[T](v: T): () where Display[T];", 14 | codegen: None, 15 | fun: |_ctx, v| { 16 | let v0 = &v[0]; 17 | eprintln!("{}", v0); 18 | Tuple(vec![]).into() 19 | }, 20 | }); 21 | 22 | ctx.declare(Decl::Def { 23 | docs: "", 24 | aqua: "def debug[T](v: T): () where Debug[T];", 25 | codegen: None, 26 | fun: |_ctx, v| { 27 | let v0 = &v[0]; 28 | eprintln!("{:?}", v0); 29 | Tuple(vec![]).into() 30 | }, 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/add.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::builtins::value::Value; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::DECLS; 7 | 8 | #[distributed_slice(DECLS)] 9 | fn declare(ctx: &mut Context) { 10 | ctx.declare(Decl::Trait { 11 | docs: "", 12 | aqua: indoc::indoc! { 13 | "trait Add[A,B] { 14 | type Output; 15 | def add(a:A, b:B): Add[A,B]::Output; 16 | }" 17 | }, 18 | }); 19 | } 20 | 21 | impl std::ops::Add for Value { 22 | type Output = Value; 23 | fn add(self, other: Value) -> Value { 24 | match (self, other) { 25 | (Value::I32(a), Value::I32(b)) => Value::I32(a + b), 26 | (Value::F32(a), Value::F32(b)) => Value::F32(a + b), 27 | (Value::Tuple(a), Value::Tuple(b)) => Value::Tuple(a + b), 28 | _ => unreachable!(), 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/clone.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::builtins::Context; 4 | use crate::builtins::Decl; 5 | use crate::builtins::DECLS; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn declare(ctx: &mut Context) { 9 | ctx.declare(Decl::Trait { 10 | docs: "", 11 | aqua: "trait Clone[T] { 12 | def clone(v:T): T; 13 | }", 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/copy.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::builtins::Context; 4 | use crate::builtins::Decl; 5 | use crate::builtins::DECLS; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn decl(ctx: &mut Context) { 9 | ctx.declare(Decl::Trait { 10 | docs: "", 11 | aqua: "trait Copy[T] {}", 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/data.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aqua-language/aqua/4e71a025d373e3284d17b4475af5dba33aba95ea/crates/compiler/src/builtins/traits/data.rs -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/debug.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::aqua; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::DECLS; 7 | 8 | #[distributed_slice(DECLS)] 9 | fn decl(ctx: &mut Context) { 10 | ctx.declare(Decl::Trait { 11 | docs: "", 12 | aqua: aqua! { 13 | "trait Debug[T] { 14 | def debug(v: T): String; 15 | }" 16 | }, 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/default.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::builtins::Context; 4 | use crate::builtins::Decl; 5 | use crate::builtins::DECLS; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn declare(ctx: &mut Context) { 9 | ctx.declare(Decl::Trait { 10 | docs: "", 11 | aqua: "trait Default[T] { 12 | def default(): T; 13 | }", 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/div.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::value::Value; 2 | use crate::builtins::Context; 3 | use crate::builtins::Decl; 4 | use crate::builtins::DECLS; 5 | use linkme::distributed_slice; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn declare(ctx: &mut Context) { 9 | ctx.declare(Decl::Trait { 10 | docs: "", 11 | aqua: "trait Div[A,B] { 12 | type Output; 13 | def div(a:A, b:B): Div[A,B]::Output; 14 | }", 15 | }); 16 | } 17 | 18 | impl std::ops::Div for Value { 19 | type Output = Value; 20 | fn div(self, other: Value) -> Value { 21 | match (self, other) { 22 | (Value::I32(a), Value::I32(b)) => Value::I32(a / b), 23 | (Value::F32(a), Value::F32(b)) => Value::F32(a / b), 24 | _ => unreachable!(), 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/fun.rs: -------------------------------------------------------------------------------- 1 | // use crate::builtins::value::Value; 2 | 3 | // impl Fn<(Value)> for Value { 4 | // fn call(&self, args: Args) -> Self::Output { 5 | // todo!() 6 | // } 7 | // } 8 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/into_iterator.rs: -------------------------------------------------------------------------------- 1 | use crate::aqua; 2 | use crate::builtins::Context; 3 | use crate::builtins::Decl; 4 | use crate::builtins::DECLS; 5 | use linkme::distributed_slice; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn declare(ctx: &mut Context) { 9 | ctx.declare(Decl::Trait { 10 | docs: "", 11 | aqua: aqua! { 12 | "trait IntoIterator[T] 13 | where Iterator[IntoIterator[T]::IntoIter, 14 | Item = IntoIterator[T]::Item] { 15 | type Item; 16 | type IntoIter; 17 | def into_iter(data: T): IntoIterator[T]::IntoIter; 18 | }" 19 | }, 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/iterator.rs: -------------------------------------------------------------------------------- 1 | use crate::aqua; 2 | use crate::builtins::Context; 3 | use crate::builtins::Decl; 4 | use crate::builtins::DECLS; 5 | use linkme::distributed_slice; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn declare(ctx: &mut Context) { 9 | ctx.declare(Decl::Trait { 10 | docs: "", 11 | aqua: aqua! { 12 | "trait Iterator[T] { 13 | type Item; 14 | def next(v: T): Option[Iterator[T]::Item]; 15 | }" 16 | }, 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/mul.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::value::Value; 2 | use crate::builtins::Context; 3 | use crate::builtins::Decl; 4 | use crate::builtins::DECLS; 5 | use linkme::distributed_slice; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn declare(ctx: &mut Context) { 9 | ctx.declare(Decl::Trait { 10 | docs: "", 11 | aqua: "trait Mul[A,B] { 12 | type Output; 13 | def mul(a:A, b:B): Mul[A,B]::Output; 14 | }", 15 | }); 16 | } 17 | 18 | impl std::ops::Mul for Value { 19 | type Output = Value; 20 | fn mul(self, other: Value) -> Value { 21 | match (self, other) { 22 | (Value::I32(a), Value::I32(b)) => Value::I32(a * b), 23 | (Value::F32(a), Value::F32(b)) => Value::F32(a * b), 24 | _ => unreachable!(), 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/neg.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::value::Value; 2 | use crate::builtins::Context; 3 | use crate::builtins::Decl; 4 | use crate::builtins::DECLS; 5 | use linkme::distributed_slice; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn declare(ctx: &mut Context) { 9 | ctx.declare(Decl::Trait { 10 | docs: "", 11 | aqua: "trait Neg[T] { 12 | type Output; 13 | def neg(v:T): Neg[T]::Output; 14 | }", 15 | }); 16 | } 17 | 18 | impl std::ops::Neg for Value { 19 | type Output = Value; 20 | fn neg(self) -> Value { 21 | match self { 22 | Value::I32(a) => Value::I32(-a), 23 | Value::F32(a) => Value::F32(-a), 24 | _ => unreachable!(), 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/not.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::value::Value; 2 | use crate::builtins::Context; 3 | use crate::builtins::Decl; 4 | use crate::builtins::DECLS; 5 | use linkme::distributed_slice; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn declare(ctx: &mut Context) { 9 | ctx.declare(Decl::Trait { 10 | docs: "", 11 | aqua: "trait Not[T] { 12 | type Output; 13 | def not(v:T): Not[T]::Output; 14 | }", 15 | }); 16 | } 17 | 18 | impl std::ops::Not for Value { 19 | type Output = Value; 20 | fn not(self) -> Value { 21 | match self { 22 | Value::Bool(a) => Value::Bool(!a), 23 | _ => unreachable!(), 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/partial_eq.rs: -------------------------------------------------------------------------------- 1 | use crate::aqua; 2 | use crate::builtins::Context; 3 | use crate::builtins::Decl; 4 | use crate::builtins::DECLS; 5 | use linkme::distributed_slice; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn declare(ctx: &mut Context) { 9 | ctx.declare(Decl::Trait { 10 | docs: "", 11 | aqua: aqua! { 12 | "trait PartialEq[T] { 13 | def eq(a: T, b: T): bool; 14 | def ne(a: T, b: T): bool; 15 | }" 16 | }, 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/partial_ord.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::Context; 2 | use crate::builtins::Decl; 3 | use crate::builtins::DECLS; 4 | use linkme::distributed_slice; 5 | 6 | #[distributed_slice(DECLS)] 7 | fn declare(ctx: &mut Context) { 8 | ctx.declare(Decl::Trait { 9 | docs: "", 10 | aqua: "trait PartialOrd[T] where PartialEq[T] { 11 | def partial_cmp(a:T, b:T): Option[Ordering]; 12 | def lt(a:T, b:T): bool; 13 | def le(a:T, b:T): bool; 14 | def gt(a:T, b:T): bool; 15 | def ge(a:T, b:T): bool; 16 | }", 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/traits/sub.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::value::Value; 2 | use crate::builtins::Context; 3 | use crate::builtins::Decl; 4 | use crate::builtins::DECLS; 5 | use linkme::distributed_slice; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn declare(ctx: &mut Context) { 9 | ctx.declare(Decl::Trait { 10 | docs: "", 11 | aqua: "trait Sub[A,B] { 12 | type Output; 13 | def sub(a:A, b:B): Sub[A,B]::Output; 14 | }", 15 | }); 16 | } 17 | 18 | impl std::ops::Sub for Value { 19 | type Output = Value; 20 | fn sub(self, other: Value) -> Value { 21 | match (self, other) { 22 | (Value::I32(a), Value::I32(b)) => Value::I32(a - b), 23 | (Value::F32(a), Value::F32(b)) => Value::F32(a - b), 24 | _ => unreachable!(), 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/backend.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | use serde::Deserialize; 3 | use serde::Serialize; 4 | 5 | use crate::builtins::Context; 6 | use crate::builtins::Decl; 7 | use crate::builtins::ImplDecl; 8 | use crate::builtins::DECLS; 9 | 10 | #[distributed_slice(DECLS)] 11 | fn declare(ctx: &mut Context) { 12 | ctx.declare(Decl::Type { 13 | docs: "", 14 | aqua: "type Backend;", 15 | codegen: None, 16 | }); 17 | ctx.declare(Decl::Impl { 18 | aqua: "impl Backend", 19 | decls: &[ 20 | ImplDecl::Def { 21 | docs: "", 22 | aqua: "def native(): Backend;", 23 | codegen: None, 24 | eval: |_ctx, _v| Backend::native().into(), 25 | }, 26 | ImplDecl::Def { 27 | docs: "", 28 | aqua: "def flink(): Backend;", 29 | codegen: None, 30 | eval: |_ctx, _v| Backend::flink().into(), 31 | }, 32 | ], 33 | }); 34 | } 35 | 36 | #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)] 37 | pub enum Backend { 38 | Native, 39 | Flink, 40 | } 41 | 42 | impl std::fmt::Display for Backend { 43 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 44 | match self { 45 | Backend::Native => write!(f, "Native"), 46 | Backend::Flink => write!(f, "Flink"), 47 | } 48 | } 49 | } 50 | 51 | impl Backend { 52 | pub fn native() -> Self { 53 | Self::Native 54 | } 55 | pub fn flink() -> Self { 56 | Self::Flink 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/bag.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | 3 | use runtime::prelude::Bag; 4 | use runtime::prelude::Duration; 5 | use runtime::prelude::Format; 6 | use runtime::prelude::Reader; 7 | 8 | use crate::ast::Codegen; 9 | use crate::builtins::Context; 10 | use crate::builtins::Decl; 11 | use crate::builtins::ImplDecl; 12 | use crate::builtins::DECLS; 13 | use linkme::distributed_slice; 14 | 15 | use super::function::Function; 16 | 17 | #[derive(Debug, Clone, Eq, PartialEq)] 18 | pub struct LazyBag(pub Rc); 19 | 20 | #[derive(Debug, Clone, Eq, PartialEq)] 21 | pub enum Operator { 22 | Source(Reader, Format, Function, Duration, Duration), 23 | Take(LazyBag, i32), 24 | Map(LazyBag, Function), 25 | Filter(LazyBag, Function), 26 | Flatten(LazyBag), 27 | FlatMap(LazyBag, Function), 28 | Keyby(LazyBag, Function), 29 | Window(LazyBag, LazyBag, Function), 30 | IncrWindow(LazyBag, LazyBag, Function, Function, Function), 31 | Merge(LazyBag, LazyBag), 32 | } 33 | 34 | #[distributed_slice(DECLS)] 35 | fn declare(ctx: &mut Context) { 36 | ctx.declare(Decl::Type { 37 | docs: "", 38 | aqua: "type Bag[T];", 39 | codegen: None, 40 | }); 41 | 42 | ctx.declare(Decl::Impl { 43 | aqua: "impl[T] Serde[Bag[T]] where Serde[T]", 44 | decls: &[], 45 | }); 46 | 47 | ctx.declare(Decl::Impl { 48 | aqua: "impl[T] Bag[T]", 49 | decls: &[ImplDecl::Def { 50 | docs: "", 51 | aqua: "def new(): Bag[T];", 52 | codegen: Some(Codegen { 53 | rust: "Bag::new", 54 | java: "Bag.new", 55 | egglog: None, 56 | }), 57 | eval: |_ctx, _v| Bag::new().into(), 58 | }], 59 | }); 60 | } 61 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/blob.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::Codegen; 2 | use crate::builtins::Context; 3 | use crate::builtins::Decl; 4 | use crate::builtins::DECLS; 5 | use linkme::distributed_slice; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn declare(ctx: &mut Context) { 9 | ctx.declare(Decl::Type { 10 | docs: "", 11 | aqua: "type Blob;", 12 | codegen: Some(Codegen { 13 | rust: "Blob", 14 | java: "Blob", 15 | egglog: None, 16 | }), 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/bool.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::Codegen; 2 | use crate::builtins::Context; 3 | use crate::builtins::Decl; 4 | use crate::builtins::ImplDecl; 5 | use crate::builtins::DECLS; 6 | use linkme::distributed_slice; 7 | 8 | // `and` and `or` desugar to `if` expressions instead of functions, so we don't implement them. 9 | #[distributed_slice(DECLS)] 10 | fn declare(ctx: &mut Context) { 11 | ctx.declare(Decl::Type { 12 | docs: "", 13 | aqua: "type bool;", 14 | codegen: Some(Codegen { 15 | rust: "bool", 16 | java: "boolean", 17 | egglog: None, 18 | }), 19 | }); 20 | 21 | ctx.declare(Decl::Impl { 22 | aqua: "impl Serde[bool]", 23 | decls: &[], 24 | }); 25 | 26 | ctx.declare(Decl::Impl { 27 | aqua: "impl Not[bool]", 28 | decls: &[ 29 | ImplDecl::Type { 30 | docs: "", 31 | aqua: "type Output = bool;", 32 | }, 33 | ImplDecl::Def { 34 | docs: "", 35 | aqua: "def not(a:bool): bool;", 36 | codegen: Some(Codegen { 37 | rust: "(|a| !a)", 38 | java: "(a) -> !a", 39 | egglog: None, 40 | }), 41 | eval: |_ctx, v| { 42 | let v0 = v[0].as_bool(); 43 | (!v0).into() 44 | }, 45 | }, 46 | ], 47 | }); 48 | } 49 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/char.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::ast::Codegen; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::DECLS; 7 | 8 | #[distributed_slice(DECLS)] 9 | fn declare(ctx: &mut Context) { 10 | ctx.declare(Decl::Type { 11 | docs: "", 12 | aqua: "type char;", 13 | codegen: Some(Codegen { 14 | rust: "char", 15 | java: "char", 16 | egglog: None, 17 | }), 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/f32.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::ast::Codegen; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::DECLS; 7 | 8 | #[distributed_slice(DECLS)] 9 | fn declare(ctx: &mut Context) { 10 | ctx.declare(Decl::Type { 11 | docs: "", 12 | aqua: "type f32;", 13 | codegen: Some(Codegen { 14 | rust: "f32", 15 | java: "float", 16 | egglog: None, 17 | }), 18 | }); 19 | 20 | ctx.declare(Decl::Impl { 21 | aqua: "impl Serde[f32]", 22 | decls: &[], 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/file.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | use runtime::builtins::file::File; 3 | 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::ImplDecl; 7 | use crate::builtins::DECLS; 8 | 9 | #[distributed_slice(DECLS)] 10 | fn declare(ctx: &mut Context) { 11 | ctx.declare(Decl::Type { 12 | docs: "", 13 | aqua: "type File;", 14 | codegen: None, 15 | }); 16 | 17 | ctx.declare(Decl::Impl { 18 | aqua: "impl File", 19 | decls: &[ 20 | ImplDecl::Def { 21 | docs: "", 22 | aqua: "def open(path:Path): File;", 23 | codegen: None, 24 | eval: |_ctx, v| { 25 | let v0 = v[0].as_path(); 26 | File::open(v0).into() 27 | }, 28 | }, 29 | ImplDecl::Def { 30 | docs: "", 31 | aqua: "def read_to_string(file:File): String;", 32 | codegen: None, 33 | eval: |_ctx, _v| { 34 | todo!() 35 | // let v0 = v[0].as_file(); 36 | // v0.read_to_string().into() 37 | }, 38 | }, 39 | ImplDecl::Def { 40 | docs: "", 41 | aqua: "def read_to_bytes(file:File): Blob;", 42 | codegen: None, 43 | eval: |_ctx, v| { 44 | let v0 = v[0].as_file(); 45 | v0.read_to_bytes().into() 46 | }, 47 | }, 48 | ImplDecl::Def { 49 | docs: "", 50 | aqua: "def inspect(file:File): ();", 51 | codegen: None, 52 | eval: |_ctx, _v| { 53 | todo!() 54 | // let v0 = v[0].as_file(); 55 | // v0.inspect().into() 56 | }, 57 | }, 58 | ], 59 | }); 60 | } 61 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/format.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | use runtime::builtins::format::Format; 3 | 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::ImplDecl; 7 | use crate::builtins::DECLS; 8 | 9 | #[distributed_slice(DECLS)] 10 | fn declare(ctx: &mut Context) { 11 | ctx.declare(Decl::Type { 12 | docs: "", 13 | aqua: "type Format;", 14 | codegen: None, 15 | }); 16 | 17 | ctx.declare(Decl::Impl { 18 | aqua: "impl Format", 19 | decls: &[ 20 | ImplDecl::Def { 21 | docs: "", 22 | aqua: "def csv(sep: char): Format;", 23 | codegen: None, 24 | eval: |_ctx, v| { 25 | let v0 = v[0].as_char(); 26 | Format::csv(v0).into() 27 | }, 28 | }, 29 | ImplDecl::Def { 30 | docs: "", 31 | aqua: "def json(): Format;", 32 | codegen: None, 33 | eval: |_ctx, _v| Format::json().into(), 34 | }, 35 | ], 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/function.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | use runtime::prelude::Send; 3 | use runtime::prelude::Sync; 4 | 5 | use crate::ast::ExprBody; 6 | use crate::ast::Local; 7 | use crate::builtins::value::Value; 8 | 9 | use crate::builtins::Context; 10 | use crate::builtins::DECLS; 11 | 12 | #[distributed_slice(DECLS)] 13 | fn declare(_ctx: &mut Context) {} 14 | 15 | #[derive(Debug, Clone, Eq, PartialEq, Send, Sync)] 16 | pub struct Function { 17 | pub params: Vec, 18 | pub body: ExprBody, 19 | } 20 | 21 | impl std::fmt::Display for Function { 22 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 23 | write!(f, "(")?; 24 | let mut iter = self.params.iter(); 25 | if let Some(l) = iter.next() { 26 | write!(f, "{l}")?; 27 | for l in iter { 28 | write!(f, ", {l}")?; 29 | } 30 | } 31 | write!(f, ") => {}", self.body) 32 | } 33 | } 34 | 35 | impl Function { 36 | pub fn new(ls: Vec, body: ExprBody) -> Self { 37 | Self { params: ls, body } 38 | } 39 | 40 | pub fn call(&self, ctx: &mut crate::interpret::Context, args: &[Value]) -> Value { 41 | match &self.body { 42 | ExprBody::UserDefined(e) => ctx.scoped(|ctx| { 43 | for (l, v) in self.params.iter().zip(args) { 44 | ctx.stack.bind(l.name, v.clone()) 45 | } 46 | ctx.eval_expr(&e) 47 | }), 48 | ExprBody::Builtin(b) => (b.fun)(ctx, args), 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/i128.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::ast::Codegen; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::DECLS; 7 | 8 | #[distributed_slice(DECLS)] 9 | fn declare(ctx: &mut Context) { 10 | ctx.declare(Decl::Type { 11 | docs: "", 12 | aqua: "type i128;", 13 | codegen: Some(Codegen { 14 | rust: "i128", 15 | java: "long", 16 | egglog: None, 17 | }), 18 | }); 19 | 20 | ctx.declare(Decl::Impl { 21 | aqua: "impl Serde[i128]", 22 | decls: &[], 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/i16.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::ast::Codegen; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::DECLS; 7 | 8 | #[distributed_slice(DECLS)] 9 | fn declare(ctx: &mut Context) { 10 | ctx.declare(Decl::Type { 11 | docs: "", 12 | aqua: "type i16;", 13 | codegen: Some(Codegen { 14 | rust: "i16", 15 | java: "short", 16 | egglog: None, 17 | }), 18 | }); 19 | 20 | ctx.declare(Decl::Impl { 21 | aqua: "impl Serde[i16]", 22 | decls: &[], 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/i64.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::ast::Codegen; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::DECLS; 7 | 8 | #[distributed_slice(DECLS)] 9 | fn declare(ctx: &mut Context) { 10 | ctx.declare(Decl::Type { 11 | docs: "", 12 | aqua: "type i64;", 13 | codegen: Some(Codegen { 14 | rust: "i64", 15 | java: "long", 16 | egglog: None, 17 | }), 18 | }); 19 | 20 | ctx.declare(Decl::Impl { 21 | aqua: "impl Serde[i64]", 22 | decls: &[], 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/i8.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::ast::Codegen; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::DECLS; 7 | 8 | #[distributed_slice(DECLS)] 9 | fn declare(ctx: &mut Context) { 10 | ctx.declare(Decl::Type { 11 | docs: "", 12 | aqua: "type i8;", 13 | codegen: Some(Codegen { 14 | rust: "i8", 15 | java: "byte", 16 | egglog: None, 17 | }), 18 | }); 19 | 20 | ctx.declare(Decl::Impl { 21 | aqua: "impl Serde[i8]", 22 | decls: &[], 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/never.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::builtins::Context; 4 | use crate::builtins::Decl; 5 | use crate::builtins::DECLS; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn declare(ctx: &mut Context) { 9 | ctx.declare(Decl::Def { 10 | docs: "", 11 | aqua: "def unreachable(): !;", 12 | codegen: None, 13 | fun: |_ctx, _v| unreachable!(), 14 | }); 15 | 16 | ctx.declare(Decl::Def { 17 | docs: "", 18 | aqua: "def panic(msg: String): !;", 19 | codegen: None, 20 | fun: |_ctx, v| { 21 | let v0 = v[0].as_string(); 22 | panic!("{}", v0); 23 | }, 24 | }); 25 | 26 | ctx.declare(Decl::Def { 27 | docs: "", 28 | aqua: "def exit(): !;", 29 | codegen: None, 30 | fun: |_ctx, _v| { 31 | std::process::exit(0); 32 | }, 33 | }); 34 | } 35 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/path.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::Codegen; 2 | use crate::builtins::Context; 3 | use crate::builtins::Decl; 4 | use crate::builtins::ImplDecl; 5 | use crate::builtins::DECLS; 6 | use linkme::distributed_slice; 7 | use runtime::prelude::Path; 8 | 9 | #[distributed_slice(DECLS)] 10 | fn declare(ctx: &mut Context) { 11 | ctx.declare(Decl::Type { 12 | docs: "", 13 | aqua: "type Path;", 14 | codegen: Some(Codegen { 15 | rust: "Path", 16 | java: "Path", 17 | egglog: None, 18 | }), 19 | }); 20 | 21 | ctx.declare(Decl::Impl { 22 | aqua: "impl Path", 23 | decls: &[ 24 | ImplDecl::Def { 25 | docs: "", 26 | aqua: "def new(s: String): Path;", 27 | codegen: Some(Codegen { 28 | rust: "Path::new", 29 | java: "Path.new", 30 | egglog: None, 31 | }), 32 | eval: |_ctx, v| { 33 | let a0 = v[0].as_string(); 34 | Path::new(a0.to_string()).into() 35 | }, 36 | }, 37 | ImplDecl::Def { 38 | docs: "", 39 | aqua: "def extend(a0: Path, a1: String): Path;", 40 | codegen: Some(Codegen { 41 | rust: "Path::join", 42 | java: "Path.join", 43 | egglog: None, 44 | }), 45 | eval: |_ctx, _v| { 46 | todo!() 47 | // let a0 = v[0].as_path(); 48 | // let a1 = v[0].as_string(); 49 | // a0.join(a1).into() 50 | }, 51 | }, 52 | ], 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/range.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::Codegen; 2 | use crate::builtins::Context; 3 | use crate::builtins::Decl; 4 | use crate::builtins::DECLS; 5 | use linkme::distributed_slice; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn declare(ctx: &mut Context) { 9 | ctx.declare(Decl::Type { 10 | docs: "", 11 | aqua: "type Range[T];", 12 | codegen: Some(Codegen { 13 | rust: "Range", 14 | java: "Range", 15 | egglog: None, 16 | }), 17 | }); 18 | 19 | ctx.declare(Decl::Impl { 20 | aqua: "impl[T] Serde[Range[T]] where Serde[T]", 21 | decls: &[], 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/record.rs: -------------------------------------------------------------------------------- 1 | use runtime::prelude::DeepClone; 2 | use serde::ser::SerializeMap; 3 | use serde::Serialize; 4 | 5 | use crate::ast::Map; 6 | use crate::ast::Name; 7 | use crate::builtins::value::Value; 8 | 9 | use crate::builtins::Context; 10 | use crate::builtins::DECLS; 11 | use linkme::distributed_slice; 12 | 13 | #[distributed_slice(DECLS)] 14 | fn declare(_ctx: &mut Context) {} 15 | 16 | #[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] 17 | pub struct Record(pub Map); 18 | 19 | impl DeepClone for Record { 20 | fn deep_clone(&self) -> Self { 21 | let map = self 22 | .0 23 | .iter() 24 | .map(|(k, v)| (k.clone(), v.deep_clone())) 25 | .collect(); 26 | Record(map) 27 | } 28 | } 29 | 30 | impl std::fmt::Display for Record { 31 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 32 | write!(f, "{{")?; 33 | let mut iter = self.0.iter(); 34 | if let Some((k, v)) = iter.next() { 35 | write!(f, "{}: {}", k, v)?; 36 | for (k, v) in iter { 37 | write!(f, ", {}: {}", k, v)?; 38 | } 39 | } 40 | write!(f, "}}") 41 | } 42 | } 43 | 44 | impl Record { 45 | pub fn new(fields: Map) -> Record { 46 | Record(fields) 47 | } 48 | } 49 | 50 | impl std::ops::Index<&Name> for Record { 51 | type Output = Value; 52 | 53 | fn index(&self, name: &Name) -> &Value { 54 | self.0 55 | .iter() 56 | .find(|(n, _)| n == name) 57 | .map(|(_, v)| v) 58 | .unwrap() 59 | } 60 | } 61 | 62 | impl Serialize for Record { 63 | fn serialize(&self, serializer: S) -> Result 64 | where 65 | S: serde::Serializer, 66 | { 67 | let mut map = serializer.serialize_map(Some(self.0.len()))?; 68 | for (name, value) in &self.0 { 69 | map.serialize_entry(name, value)?; 70 | } 71 | map.end() 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/set.rs: -------------------------------------------------------------------------------- 1 | use runtime::builtins::set::Set; 2 | 3 | use crate::ast::Codegen; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::ImplDecl; 7 | use crate::builtins::DECLS; 8 | use linkme::distributed_slice; 9 | 10 | #[distributed_slice(DECLS)] 11 | fn declare(ctx: &mut Context) { 12 | ctx.declare(Decl::Type { 13 | docs: "", 14 | aqua: "type Set[T];", 15 | codegen: Some(Codegen { 16 | rust: "Set", 17 | java: "Set", 18 | egglog: None, 19 | }), 20 | }); 21 | 22 | 23 | ctx.declare(Decl::Impl { 24 | aqua: "impl[T] Serde[Set[T]] where Serde[T]", 25 | decls: &[], 26 | }); 27 | 28 | ctx.declare(Decl::Impl { 29 | aqua: "impl[T] Set[T]", 30 | decls: &[ImplDecl::Def { 31 | docs: "", 32 | aqua: "def new(): Set[T];", 33 | codegen: Some(Codegen { 34 | rust: "Set::new", 35 | java: "Set.new", 36 | egglog: None, 37 | }), 38 | eval: |_ctx, _v| Set::new().into(), 39 | }], 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/socket.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::Context; 2 | use crate::builtins::Decl; 3 | use crate::builtins::ImplDecl; 4 | use crate::builtins::DECLS; 5 | use linkme::distributed_slice; 6 | 7 | #[distributed_slice(DECLS)] 8 | fn declare(ctx: &mut Context) { 9 | ctx.declare(Decl::Type { 10 | docs: "", 11 | aqua: "type SocketAddr;", 12 | codegen: None, 13 | }); 14 | ctx.declare(Decl::Impl { 15 | aqua: "impl SocketAddr", 16 | decls: &[ImplDecl::Def { 17 | docs: "", 18 | aqua: "def new(s: String): SocketAddr;", 19 | codegen: None, 20 | eval: |_ctx, _v| { 21 | todo!() 22 | // let v0 = v[0].as_string(); 23 | // SocketAddr::parse(v0).into() 24 | }, 25 | }], 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/storage.rs: -------------------------------------------------------------------------------- 1 | use runtime::prelude::DeepClone; 2 | use serde::Serialize; 3 | 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::ImplDecl; 7 | use crate::builtins::DECLS; 8 | use linkme::distributed_slice; 9 | 10 | #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, DeepClone)] 11 | pub enum Storage { 12 | // Ephemeral 13 | Memory, 14 | // Local Persistent 15 | Sled, 16 | // Remote Persistent 17 | S3, 18 | AzBlob, 19 | Gcs, 20 | } 21 | 22 | #[distributed_slice(DECLS)] 23 | fn declare(ctx: &mut Context) { 24 | ctx.declare(Decl::Type { 25 | docs: "Storage backend.", 26 | aqua: "type Storage;", 27 | codegen: None, 28 | }); 29 | 30 | ctx.declare(Decl::Impl { 31 | aqua: "impl Storage", 32 | decls: &[ 33 | ImplDecl::Def { 34 | docs: "Memory storage backend.", 35 | aqua: "def memory(): Storage;", 36 | eval: |_, _| Storage::Memory.into(), 37 | codegen: None, 38 | }, 39 | ImplDecl::Def { 40 | docs: "Sled storage backend.", 41 | aqua: "def sled(): Storage;", 42 | eval: |_, _| Storage::Sled.into(), 43 | codegen: None, 44 | }, 45 | ImplDecl::Def { 46 | docs: "S3 storage backend.", 47 | aqua: "def s3(): Storage;", 48 | eval: |_, _| Storage::S3.into(), 49 | codegen: None, 50 | }, 51 | ImplDecl::Def { 52 | docs: "Azure Blob storage backend.", 53 | aqua: "def az_blob(): Storage;", 54 | eval: |_, _| Storage::AzBlob.into(), 55 | codegen: None, 56 | }, 57 | ImplDecl::Def { 58 | docs: "Google Cloud Storage backend.", 59 | aqua: "def gcs(): Storage;", 60 | eval: |_, _| Storage::Gcs.into(), 61 | codegen: None, 62 | }, 63 | ], 64 | }); 65 | } 66 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/tuple.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::Index; 2 | use crate::builtins::Context; 3 | 4 | use linkme::distributed_slice; 5 | use runtime::prelude::DeepClone; 6 | use serde::Serialize; 7 | use crate::builtins::value::Value; 8 | use crate::builtins::DECLS; 9 | 10 | #[distributed_slice(DECLS)] 11 | fn declare(_ctx: &mut Context) {} 12 | 13 | #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize)] 14 | pub struct Tuple(pub Vec); 15 | 16 | impl DeepClone for Tuple { 17 | fn deep_clone(&self) -> Self { 18 | Tuple(self.0.iter().map(|v| v.deep_clone()).collect()) 19 | } 20 | } 21 | 22 | impl std::fmt::Display for Tuple { 23 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 24 | write!(f, "(")?; 25 | let mut iter = self.0.iter(); 26 | if let Some(v) = iter.next() { 27 | write!(f, "{}", v)?; 28 | for v in iter { 29 | write!(f, ", {}", v)?; 30 | } 31 | } 32 | write!(f, ")") 33 | } 34 | } 35 | 36 | impl std::ops::Add for Tuple { 37 | type Output = Tuple; 38 | 39 | fn add(self, other: Tuple) -> Tuple { 40 | Tuple( 41 | self.0 42 | .into_iter() 43 | .zip(other.0.into_iter()) 44 | .map(|(a, b)| a + b) 45 | .collect(), 46 | ) 47 | } 48 | } 49 | 50 | impl Tuple { 51 | pub fn new(values: Vec) -> Tuple { 52 | Tuple(values) 53 | } 54 | } 55 | 56 | impl<'a> std::ops::Index<&'a Index> for Tuple { 57 | type Output = Value; 58 | 59 | fn index(&self, index: &'a Index) -> &Value { 60 | &self.0[index.data] 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/u128.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::ast::Codegen; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::DECLS; 7 | 8 | #[distributed_slice(DECLS)] 9 | fn declare(ctx: &mut Context) { 10 | ctx.declare(Decl::Type { 11 | docs: "", 12 | aqua: "type u128;", 13 | codegen: Some(Codegen { 14 | rust: "u128", 15 | java: "BigInteger", 16 | egglog: None, 17 | }), 18 | }); 19 | 20 | ctx.declare(Decl::Impl { 21 | aqua: "impl Serde[u128]", 22 | decls: &[], 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/u16.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::ast::Codegen; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::DECLS; 7 | 8 | #[distributed_slice(DECLS)] 9 | fn declare(ctx: &mut Context) { 10 | ctx.declare(Decl::Type { 11 | docs: "", 12 | aqua: "type u16;", 13 | codegen: Some(Codegen { 14 | rust: "u16", 15 | java: "char", 16 | egglog: None, 17 | }), 18 | }); 19 | 20 | ctx.declare(Decl::Impl { 21 | aqua: "impl Serde[u16]", 22 | decls: &[], 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/u32.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::ast::Codegen; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::DECLS; 7 | 8 | #[distributed_slice(DECLS)] 9 | fn declare(ctx: &mut Context) { 10 | ctx.declare(Decl::Type { 11 | docs: "", 12 | aqua: "type u32;", 13 | codegen: Some(Codegen { 14 | rust: "u32", 15 | java: "int", 16 | egglog: None, 17 | }), 18 | }); 19 | 20 | ctx.declare(Decl::Impl { 21 | aqua: "impl Serde[u32]", 22 | decls: &[], 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/u64.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::ast::Codegen; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::DECLS; 7 | 8 | #[distributed_slice(DECLS)] 9 | fn declare(ctx: &mut Context) { 10 | ctx.declare(Decl::Type { 11 | docs: "", 12 | aqua: "type u64;", 13 | codegen: Some(Codegen { 14 | rust: "u64", 15 | java: "long", 16 | egglog: None, 17 | }), 18 | }); 19 | 20 | ctx.declare(Decl::Impl { 21 | aqua: "impl Serde[u64]", 22 | decls: &[], 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/u8.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::ast::Codegen; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::DECLS; 7 | 8 | #[distributed_slice(DECLS)] 9 | fn declare(ctx: &mut Context) { 10 | ctx.declare(Decl::Type { 11 | docs: "", 12 | aqua: "type u8;", 13 | codegen: Some(Codegen { 14 | rust: "u8", 15 | java: "byte", 16 | egglog: None, 17 | }), 18 | }); 19 | 20 | ctx.declare(Decl::Impl { 21 | aqua: "impl Serde[u8]", 22 | decls: &[], 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/unit.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::Context; 2 | 3 | use crate::builtins::DECLS; 4 | use linkme::distributed_slice; 5 | use runtime::prelude::DeepClone; 6 | use serde::Serialize; 7 | 8 | #[distributed_slice(DECLS)] 9 | fn declare(_ctx: &mut Context) {} 10 | 11 | #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize)] 12 | pub struct Unit; 13 | 14 | impl DeepClone for Unit { 15 | fn deep_clone(&self) -> Self { 16 | Unit 17 | } 18 | } 19 | 20 | impl std::fmt::Display for Unit { 21 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 22 | write!(f, "()") 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/url.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | 3 | use linkme::distributed_slice; 4 | use runtime::builtins::url::Url; 5 | 6 | use crate::builtins::value::Value; 7 | use crate::builtins::Context; 8 | use crate::builtins::Decl; 9 | use crate::builtins::ImplDecl; 10 | use crate::builtins::DECLS; 11 | 12 | #[distributed_slice(DECLS)] 13 | fn declare(ctx: &mut Context) { 14 | ctx.declare(Decl::Type { 15 | docs: "", 16 | aqua: "type Url;", 17 | codegen: None, 18 | }); 19 | ctx.declare(Decl::Impl { 20 | aqua: "impl Url", 21 | decls: &[ImplDecl::Def { 22 | docs: "", 23 | aqua: "def parse(s: String): Result[Url];", 24 | codegen: None, 25 | eval: |_ctx, v| { 26 | let v0 = v[0].as_string(); 27 | Url::parse(v0).map(|v| Rc::new(Value::from(v))).into() 28 | }, 29 | }], 30 | }); 31 | } 32 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/usize.rs: -------------------------------------------------------------------------------- 1 | use linkme::distributed_slice; 2 | 3 | use crate::ast::Codegen; 4 | use crate::builtins::Context; 5 | use crate::builtins::Decl; 6 | use crate::builtins::ImplDecl; 7 | use crate::builtins::DECLS; 8 | 9 | #[distributed_slice(DECLS)] 10 | fn declare(ctx: &mut Context) { 11 | ctx.declare(Decl::Type { 12 | docs: "", 13 | aqua: "type usize;", 14 | codegen: Some(Codegen { 15 | rust: "usize", 16 | java: "Long", 17 | egglog: None, 18 | }), 19 | }); 20 | 21 | ctx.declare(Decl::Impl { 22 | aqua: "impl Serde[usize]", 23 | decls: &[], 24 | }); 25 | 26 | ctx.declare(Decl::Impl { 27 | aqua: "impl Display[usize]", 28 | decls: &[ImplDecl::Def { 29 | docs: "", 30 | aqua: "def toString(x: usize): String;", 31 | codegen: Some(Codegen { 32 | rust: "|x| x.to_string()", 33 | java: "(x) -> x.toString()", 34 | egglog: None, 35 | }), 36 | eval: |_ctx, v| { 37 | let a0 = v[0].as_usize(); 38 | runtime::prelude::String::from(a0.to_string()).into() 39 | }, 40 | }], 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /crates/compiler/src/builtins/types/variant.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::Context; 2 | 3 | use std::rc::Rc; 4 | 5 | use crate::ast::Name; 6 | use crate::builtins::value::Value; 7 | use linkme::distributed_slice; 8 | use runtime::traits::DeepClone; 9 | use serde::Serialize; 10 | 11 | use crate::builtins::DECLS; 12 | 13 | #[distributed_slice(DECLS)] 14 | fn declare(_ctx: &mut Context) {} 15 | 16 | #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize)] 17 | pub struct Variant { 18 | pub x: Name, 19 | pub v: Rc, 20 | } 21 | 22 | impl DeepClone for Variant { 23 | fn deep_clone(&self) -> Self { 24 | Variant { 25 | x: self.x.clone(), 26 | v: self.v.deep_clone(), 27 | } 28 | } 29 | } 30 | 31 | impl std::fmt::Display for Variant { 32 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 33 | write!(f, "{}({})", self.x, self.v) 34 | } 35 | } 36 | 37 | impl Variant { 38 | pub fn new(x: Name, v: Value) -> Variant { 39 | Variant { x, v: Rc::new(v) } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /crates/compiler/src/collections/concurrent.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::hash::Hash; 3 | use std::sync::Mutex; 4 | use std::sync::OnceLock; 5 | 6 | use append_only_vec::AppendOnlyVec; 7 | 8 | pub struct ConcurrentMap { 9 | readonly_vec: AppendOnlyVec, 10 | writeonly_map: OnceLock>>, 11 | } 12 | 13 | #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] 14 | pub struct Uid(u16); 15 | 16 | impl ConcurrentMap { 17 | pub const fn new() -> ConcurrentMap { 18 | ConcurrentMap { 19 | readonly_vec: AppendOnlyVec::new(), 20 | writeonly_map: OnceLock::new(), 21 | } 22 | } 23 | 24 | pub fn insert(&self, key: K, value: V) -> Uid { 25 | let mut state = self 26 | .writeonly_map 27 | .get_or_init(|| Mutex::new(HashMap::new())) 28 | .lock() 29 | .unwrap(); 30 | state.get(&key).copied().unwrap_or_else(|| { 31 | let uid = Uid(self.readonly_vec.push(value) as u16); 32 | let prev = state.insert(key, uid); 33 | debug_assert!(prev.is_none()); 34 | uid 35 | }) 36 | } 37 | 38 | pub fn get(&self, key: Uid) -> &V { 39 | &self.readonly_vec[key.0 as usize] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /crates/compiler/src/collections/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod concurrent; 2 | pub mod map; 3 | pub mod ordmap; 4 | pub mod set; 5 | pub mod keyvec; 6 | -------------------------------------------------------------------------------- /crates/compiler/src/collections/ordmap.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | 3 | use std::collections::HashMap; 4 | use std::hash::Hash; 5 | 6 | struct OrdMap { 7 | keys: HashMap, 8 | values: Vec, 9 | } 10 | 11 | impl OrdMap { 12 | fn new() -> Self { 13 | OrdMap { 14 | keys: HashMap::new(), 15 | values: Vec::new(), 16 | } 17 | } 18 | 19 | fn insert(&mut self, key: K, value: V) 20 | where 21 | K: Eq + Hash, 22 | { 23 | let index = self.values.len(); 24 | self.keys.insert(key, index); 25 | self.values.push(value); 26 | } 27 | 28 | fn get(&self, key: &K) -> Option<&V> 29 | where 30 | K: Eq + Hash, 31 | { 32 | self.keys.get(key).map(|&index| &self.values[index]) 33 | } 34 | 35 | fn values(&self) -> impl Iterator { 36 | self.values.iter() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /crates/compiler/src/ffi.rs: -------------------------------------------------------------------------------- 1 | use crate::ast; 2 | use libffi::middle::Type; 3 | 4 | pub struct Ffi { 5 | stack: Stack, 6 | } 7 | 8 | impl Default for Ffi { 9 | fn default() -> Self { 10 | Self::new() 11 | } 12 | } 13 | 14 | struct Stack(Vec); 15 | 16 | impl Stack { 17 | fn new() -> Self { 18 | Self(vec![Scope::new()]) 19 | } 20 | } 21 | 22 | struct Scope(Vec); 23 | 24 | impl Scope { 25 | fn new() -> Self { 26 | Self(Vec::new()) 27 | } 28 | } 29 | 30 | enum Binding { 31 | Cons(Type), 32 | } 33 | 34 | impl Ffi { 35 | pub fn new() -> Self { 36 | Self::default() 37 | } 38 | 39 | #[allow(clippy::only_used_in_recursion)] 40 | pub fn ty(&mut self, t: ast::Type) -> Type { 41 | match t { 42 | ast::Type::Unresolved(_) => unreachable!(), 43 | ast::Type::Cons(_, _) => todo!(), 44 | ast::Type::Alias(_, _) => unreachable!(), 45 | ast::Type::Assoc(_, _, _, _) => unreachable!(), 46 | ast::Type::Var(_) => unreachable!(), 47 | ast::Type::Generic(_) => unreachable!(), 48 | ast::Type::Fun(_, _) => todo!(), 49 | ast::Type::Tuple(ts) => { 50 | let ts = ts.iter().map(|t| self.ty(t.clone())).collect::>(); 51 | Type::structure(ts) 52 | } 53 | ast::Type::Record(xts) => { 54 | let xts = xts 55 | .iter() 56 | .map(|(_, t)| self.ty(t.clone())) 57 | .collect::>(); 58 | Type::structure(xts) 59 | } 60 | ast::Type::Hole => unreachable!(), 61 | ast::Type::Err => unreachable!(), 62 | ast::Type::Array(_, _) => todo!(), 63 | ast::Type::Never => unreachable!(), 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /crates/compiler/src/mir/passes/constant_propagation.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use crate::mir::Constant; 4 | use crate::mir::Function; 5 | use crate::mir::Operand; 6 | use crate::mir::Operation; 7 | use crate::mir::Rvalue; 8 | use crate::mir::Terminator; 9 | 10 | impl Function { 11 | pub fn constant_propagation(&mut self) { 12 | let mut map = HashMap::new(); 13 | 14 | for b in 0..self.blocks.len() { 15 | for stmt in &mut self.blocks[b].stmts { 16 | match &mut stmt.op { 17 | Operation::Assign(p, Rvalue::Use(Operand::Constant(c))) => { 18 | map.insert(p.clone(), c.clone()); 19 | } 20 | Operation::Assign(p, Rvalue::Use(Operand::Copy(src))) => { 21 | if let Some(c) = map.get(src) { 22 | stmt.op = Operation::Assign( 23 | p.clone(), 24 | Rvalue::Use(Operand::Constant(c.clone())), 25 | ); 26 | } 27 | } 28 | Operation::Assign(p, _) => { 29 | map.remove(p); 30 | } 31 | Operation::Call { dest, .. } => { 32 | map.remove(dest); 33 | } 34 | _ => {} 35 | } 36 | } 37 | 38 | if let Some(terminator) = &mut self.blocks[b].terminator { 39 | match terminator { 40 | Terminator::ConditionalGoto(cond, true_block, false_block) => { 41 | if let Operand::Copy(place) = cond { 42 | if let Some(Constant::Bool(b)) = map.get(place) { 43 | *terminator = if *b { 44 | Terminator::Goto(*true_block) 45 | } else { 46 | Terminator::Goto(*false_block) 47 | }; 48 | } 49 | } 50 | } 51 | _ => {} 52 | } 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /crates/compiler/src/mir/passes/merge_blocks.rs: -------------------------------------------------------------------------------- 1 | use crate::mir::Function; 2 | use crate::mir::Terminator; 3 | 4 | impl Function { 5 | pub fn merge_blocks(&mut self) { 6 | let mut visited = vec![false; self.blocks.len()]; 7 | 8 | for i in 0..self.blocks.len() { 9 | if visited[i] { 10 | continue; 11 | } 12 | 13 | let mut chain = Vec::new(); 14 | let mut pred = i; 15 | 16 | while let &Some(Terminator::Goto(succ)) = &self.blocks[pred].terminator { 17 | if self.predecessors[succ].len() == 1 && !visited[succ] { 18 | chain.push(pred); 19 | visited[pred] = true; 20 | pred = succ; 21 | } else { 22 | break; 23 | } 24 | } 25 | 26 | if !chain.is_empty() { 27 | chain.push(pred); 28 | visited[pred] = true; 29 | 30 | // Merge the chain into the first block 31 | let &first = chain.first().unwrap(); 32 | let &second = chain.get(1).unwrap(); 33 | let &last = chain.last().unwrap(); 34 | self.successors[first] = std::mem::take(&mut self.successors[last]); 35 | self.blocks[first].terminator = std::mem::take(&mut self.blocks[last].terminator); 36 | self.predecessors[second].clear(); 37 | 38 | for &succ in chain.iter().skip(1) { 39 | let stmts = std::mem::take(&mut self.blocks[succ].stmts); 40 | self.blocks[first].stmts.extend(stmts); 41 | } 42 | } 43 | } 44 | } 45 | 46 | pub fn with_merge_blocks(mut self) -> Self { 47 | self.merge_blocks(); 48 | self 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /crates/compiler/src/mir/passes/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod borrowck; 2 | pub mod remove_unused; 3 | pub mod remove_unreachable; 4 | pub mod merge_blocks; 5 | pub mod liveness; 6 | pub mod dominators; 7 | -------------------------------------------------------------------------------- /crates/compiler/src/mir/passes/remove_unreachable.rs: -------------------------------------------------------------------------------- 1 | use crate::mir; 2 | use crate::mir::Terminator; 3 | 4 | impl mir::Function { 5 | pub fn remove_unreachable(&mut self) { 6 | let mut visited = vec![false; self.blocks.len()]; 7 | self.dfs(&mut visited, 0); 8 | 9 | let mut block_map = vec![0; self.blocks.len()]; 10 | let mut new_blocks = Vec::with_capacity(visited.iter().filter(|&&v| v).count()); 11 | 12 | for block in &self.blocks { 13 | if visited[block.id] { 14 | block_map[block.id] = new_blocks.len(); 15 | new_blocks.push(block.clone()); 16 | } 17 | } 18 | 19 | self.blocks = new_blocks; 20 | 21 | for block in &mut self.blocks { 22 | block.id = block_map[block.id]; 23 | match &mut block.terminator { 24 | Some(Terminator::Goto(b)) => *b = block_map[*b], 25 | Some(Terminator::ConditionalGoto(_, b0, b1)) => { 26 | *b0 = block_map[*b0]; 27 | *b1 = block_map[*b1]; 28 | } 29 | _ => {} 30 | } 31 | } 32 | 33 | self.successors = vec![]; 34 | self.predecessors = vec![]; 35 | } 36 | 37 | fn dfs(&self, visited: &mut Vec, b: usize) { 38 | if visited[b] { 39 | return; 40 | } 41 | visited[b] = true; 42 | 43 | match &self.blocks[b].terminator { 44 | &Some(Terminator::Goto(b)) => { 45 | self.dfs(visited, b); 46 | } 47 | &Some(Terminator::ConditionalGoto(_, b0, b1)) => { 48 | self.dfs(visited, b0); 49 | self.dfs(visited, b1); 50 | } 51 | _ => {} 52 | } 53 | } 54 | 55 | pub fn with_remove_unreachable(mut self) -> Self { 56 | self.remove_unreachable(); 57 | self 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /crates/compiler/src/mir/utils/constructors.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::Local; 2 | use crate::ast::Name; 3 | use crate::ast::Type; 4 | use crate::collections::set::Set; 5 | use crate::mir::BasicBlock; 6 | use crate::mir::BlockId; 7 | use crate::mir::Function; 8 | use crate::mir::Operation; 9 | use crate::mir::Stmt; 10 | use crate::mir::Terminator; 11 | 12 | impl Stmt { 13 | pub fn new(op: Operation) -> Stmt { 14 | Stmt { 15 | op, 16 | live_in: Set::new(), 17 | live_out: Set::new(), 18 | } 19 | } 20 | } 21 | 22 | impl Function { 23 | pub fn new( 24 | name: Name, 25 | params: Vec, 26 | locals: Vec, 27 | ty: Type, 28 | blocks: Vec, 29 | ) -> Self { 30 | Self { 31 | name, 32 | params, 33 | locals, 34 | ty, 35 | blocks, 36 | domtree: Vec::new(), 37 | successors: Vec::new(), 38 | predecessors: Vec::new(), 39 | postorder: Vec::new(), 40 | preorder: Vec::new(), 41 | reverse_postorder_number: Vec::new(), 42 | } 43 | } 44 | } 45 | 46 | impl BasicBlock { 47 | pub fn new( 48 | id: BlockId, 49 | stmts: Vec, 50 | terminator: Option, 51 | ) -> Self { 52 | Self { 53 | id, 54 | stmts, 55 | terminator, 56 | live_in: Set::new(), 57 | live_out: Set::new(), 58 | dom: Set::new(), 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /crates/compiler/src/mir/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod constructors; 2 | -------------------------------------------------------------------------------- /crates/compiler/src/opt/free.egg: -------------------------------------------------------------------------------- 1 | (sort StringSet (Set String)) 2 | 3 | (function free (Expr) StringSet :merge (set-intersect old new)) 4 | (function free_list (ExprList) StringSet :merge (set-intersect old new)) 5 | (function free_map (ExprMap) StringSet :merge (set-intersect old new)) 6 | 7 | (rule [(= e (ExprInt t v))] [(set (free e) (set-empty))]) 8 | (rule [(= e (ExprFloat t v))] [(set (free e) (set-empty))]) 9 | (rule [(= e (ExprBool t v))] [(set (free e) (set-empty))]) 10 | (rule [(= e (ExprString t v))] [(set (free e) (set-empty))]) 11 | (rule [(= e (ExprChar t v))] [(set (free e) (set-empty))]) 12 | 13 | (rule [(= e (ExprTuple t es))] [(set (free e) (free_list es))]) 14 | (rule [(= e (ExprRecord t es))] [(set (free e) (free_map es))]) 15 | 16 | (rule [(= e (ExprIndex t e1 i)) 17 | (= (free e1) fv)] 18 | [(set (free e) fv)]) 19 | (rule [(= e (ExprField t e1 f)) 20 | (= (free e1) fv)] 21 | [(set (free e) fv)]) 22 | 23 | (rule [(= e (ExprVar t x))] 24 | [(set (free e) (set-insert (set-empty) x))]) 25 | (rule [(= e (ExprDef t x m))] 26 | [(set (free e) (set-empty))]) 27 | 28 | (rule [(= e (ExprCall t e1 es)) 29 | (= (free e1) fv1) 30 | (= (free_list es) fv2)] 31 | [(set (free e) (set-union fv1 fv2))]) 32 | 33 | (rule [(= e (ExprIfElse t c e1 e2)) 34 | (= (free c) fv1) 35 | (= (free e1) fv2) 36 | (= (free e2) fv3)] 37 | [(set (free e) (set-union fv1 (set-union fv2 fv3)))]) 38 | 39 | (rule [(= e (ExprLetIn t x e1 e2)) 40 | (= (free e1) fv1) 41 | (= (free e2) fv2)] 42 | [(set (free e) (set-union fv1 (set-remove fv2 x)))]) 43 | -------------------------------------------------------------------------------- /crates/compiler/src/opt/lib.egg: -------------------------------------------------------------------------------- 1 | (sort Stmt) 2 | (sort StmtList) 3 | (sort Expr) 4 | (sort ExprList) 5 | (sort ExprMap) 6 | (sort Type) 7 | (sort TypeList) 8 | (sort TypeMap) 9 | 10 | (function ExprListCons (Expr ExprList) ExprList) 11 | (function ExprListNil () ExprList) 12 | (function ExprMapCons (String Expr ExprMap) ExprMap) 13 | (function ExprMapNil () ExprMap) 14 | 15 | (function TypeListCons (Type TypeList) TypeList) 16 | (function TypeListNil () TypeList) 17 | (function TypeMapCons (String Type TypeMap) TypeMap) 18 | (function TypeMapNil () TypeMap) 19 | 20 | (function ExprInt (Type i64) Expr) 21 | (function ExprFloat (Type f64) Expr) 22 | (function ExprBool (Type bool) Expr) 23 | (function ExprString (Type String) Expr) 24 | (function ExprChar (Type String) Expr) 25 | (function ExprTuple (Type ExprList) Expr) 26 | (function ExprRecord (Type ExprMap) Expr) 27 | (function ExprIndex (Type Expr i64) Expr) 28 | (function ExprField (Type Expr String) Expr) 29 | (function ExprVar (Type String) Expr) 30 | ; Includes both the egg name and the mangled name. For example: 31 | ; (ExprDef "add" "addi32" (TypeLambda 32 | ; (TypeListCons (TypeCons "i32") (TypeListCons i32 TypeListNil)) 33 | (function ExprDef (Type String String) Expr) 34 | (function ExprCall (Type Expr ExprList) Expr) 35 | (function ExprIfElse (Type Expr Expr Expr) Expr) 36 | (function ExprLetIn (Type String Expr Expr) Expr) 37 | 38 | (function TypeCons (String TypeList) Type) 39 | (function TypeLambda (TypeList Type) Type) 40 | (function TypeTuple (TypeList) Type) 41 | (function TypeRecord (TypeMap) Type) 42 | 43 | (function StmtListCons (Stmt StmtList) StmtList) 44 | (function StmtListNil () StmtList) 45 | (function StmtDef (TypeMap Type String Expr) Stmt) 46 | 47 | (include "typeof.egg") 48 | (include "sugar.egg") 49 | (include "free.egg") 50 | -------------------------------------------------------------------------------- /crates/compiler/src/opt/sugar.egg: -------------------------------------------------------------------------------- 1 | (function Op2 (Type String String Expr Expr) Expr) 2 | 3 | (function ExprList2 (Expr Expr) ExprList) 4 | (function TypeList2 (Type Type) TypeList) 5 | 6 | (rewrite (ExprList2 e0 e1) (ExprListCons e0 (ExprListCons e1 (ExprListNil)))) 7 | (rewrite (TypeList2 t0 t1) (TypeListCons t0 (TypeListCons t1 (TypeListNil)))) 8 | 9 | (rewrite 10 | (Op2 t x m e0 e1) 11 | (ExprCall t 12 | (ExprDef (TypeLambda (TypeList2 (typeof e0) (typeof e1)) t) x m) 13 | (ExprList2 e0 e1))) 14 | -------------------------------------------------------------------------------- /crates/compiler/src/opt/typeof.egg: -------------------------------------------------------------------------------- 1 | (function typeof (Expr) Type) 2 | 3 | (rewrite (typeof (ExprInt t v)) t) 4 | (rewrite (typeof (ExprFloat t v)) t) 5 | (rewrite (typeof (ExprBool t v)) t) 6 | (rewrite (typeof (ExprString t v)) t) 7 | (rewrite (typeof (ExprChar t v)) t) 8 | (rewrite (typeof (ExprTuple t es)) t) 9 | (rewrite (typeof (ExprRecord t es)) t) 10 | (rewrite (typeof (ExprIndex t e1 i)) t) 11 | (rewrite (typeof (ExprField t e1 f)) t) 12 | (rewrite (typeof (ExprVar t x)) t) 13 | (rewrite (typeof (ExprDef t x m)) t) 14 | (rewrite (typeof (ExprCall t e1 es)) t) 15 | (rewrite (typeof (ExprIfElse t c e1 e2)) t) 16 | (rewrite (typeof (ExprLetIn t x e1 e2)) t) 17 | -------------------------------------------------------------------------------- /crates/compiler/src/syntax/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod lexer; 2 | pub mod parser; 3 | pub mod token; 4 | pub mod source; 5 | pub mod span; 6 | pub mod spanned; 7 | pub mod symbol; 8 | pub mod splice; 9 | pub mod precedence; 10 | pub mod lookahead; 11 | -------------------------------------------------------------------------------- /crates/compiler/src/syntax/precedence.rs: -------------------------------------------------------------------------------- 1 | use super::token::Token; 2 | 3 | impl Token { 4 | pub fn expr_infix_bp(self) -> Option<(u8, u8)> { 5 | let bp = match self { 6 | Token::Eq => (1, 2), 7 | Token::DotDot => (2, 3), 8 | Token::And | Token::Or => (3, 4), 9 | Token::EqEq | Token::NotEq | Token::Lt | Token::Gt | Token::Le | Token::Ge => (4, 5), 10 | Token::Plus | Token::Minus => (5, 6), 11 | Token::Star | Token::Slash => (6, 7), 12 | _ => return None, 13 | }; 14 | Some(bp) 15 | } 16 | 17 | pub fn expr_prefix_bp(self) -> Option<((), u8)> { 18 | let bp = match self { 19 | Token::Not | Token::Minus | Token::Star | Token::Ampersand => ((), 8), 20 | _ => return None, 21 | }; 22 | Some(bp) 23 | } 24 | 25 | pub fn expr_postfix_bp(self) -> Option<(u8, ())> { 26 | let bp = match self { 27 | Token::Question | Token::LParen | Token::Dot | Token::Colon | Token::FatArrow => { 28 | (9, ()) 29 | } 30 | _ => return None, 31 | }; 32 | Some(bp) 33 | } 34 | 35 | pub fn pat_infix_bp(self) -> Option<(u8, u8)> { 36 | let bp = match self { 37 | Token::Eq => (1, 2), 38 | Token::Or => (2, 3), 39 | _ => return None, 40 | }; 41 | Some(bp) 42 | } 43 | 44 | pub fn pat_postfix_bp(self) -> Option<(u8, ())> { 45 | let bp = match self { 46 | Token::Colon => (9, ()), 47 | _ => return None, 48 | }; 49 | Some(bp) 50 | } 51 | 52 | pub fn ty_postfix_bp(self) -> Option<(u8, ())> { 53 | let bp = match self { 54 | Token::FatArrow => (9, ()), 55 | _ => return None, 56 | }; 57 | Some(bp) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /crates/compiler/src/syntax/source.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | 3 | use ariadne::Cache as _; 4 | use ariadne::Source; 5 | 6 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] 7 | pub struct SourceId(u16); 8 | 9 | impl SourceId { 10 | pub fn inner(self) -> u16 { 11 | self.0 12 | } 13 | } 14 | 15 | impl std::fmt::Display for SourceId { 16 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 17 | write!(f, "{}", self.0) 18 | } 19 | } 20 | 21 | #[derive(Debug, Default)] 22 | pub struct Cache(Vec<(String, Source>)>); 23 | 24 | impl Cache { 25 | pub fn new() -> Self { 26 | Self(Vec::new()) 27 | } 28 | 29 | pub fn get_pos(&mut self, id: SourceId, i: u32) -> (u32, u32) { 30 | let source = self.fetch(&id).unwrap(); 31 | let (_, l, c) = source.get_byte_line(i as usize).unwrap(); 32 | (l as u32, c as u32) 33 | } 34 | 35 | // TODO: Does not work yet for unicode 36 | pub fn get_byte(&mut self, file: SourceId, (l, c): (u32, u32)) -> u32 { 37 | let source = self.fetch(&file).unwrap(); 38 | let line = source.line(l as usize).unwrap(); 39 | (line.offset() as u32) + c 40 | } 41 | 42 | /// Add a new source to the cache. 43 | pub fn add(&mut self, name: impl ToString, data: impl Into>) -> SourceId { 44 | let id = self.0.len() as u16; 45 | self.0.push((name.to_string(), Source::from(data.into()))); 46 | SourceId(id as u16) 47 | } 48 | } 49 | 50 | impl<'a> ariadne::Cache for Cache { 51 | type Storage = Rc; 52 | 53 | fn fetch(&mut self, id: &SourceId) -> Result<&Source>, Box> { 54 | Ok(&self.0[id.0 as usize].1) 55 | } 56 | 57 | fn display<'b>(&self, id: &'b SourceId) -> Option> { 58 | Some(Box::new(self.0[id.0 as usize].0.clone()) as Box<_>) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /crates/compiler/src/syntax/spanned.rs: -------------------------------------------------------------------------------- 1 | use crate::syntax::span::Span; 2 | 3 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 4 | pub struct Spanned { 5 | pub s: Span, 6 | pub v: T, 7 | } 8 | 9 | impl Spanned { 10 | pub fn new(span: Span, data: T) -> Spanned { 11 | Spanned { s: span, v: data } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /crates/compiler/src/syntax/symbol.rs: -------------------------------------------------------------------------------- 1 | use smol_str::SmolStr; 2 | 3 | use serde::Deserialize; 4 | use serde::Serialize; 5 | use smol_str::ToSmolStr; 6 | 7 | use crate::collections::concurrent::ConcurrentMap; 8 | use crate::collections::concurrent::Uid; 9 | 10 | #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] 11 | pub struct Symbol(Uid); 12 | 13 | impl Symbol { 14 | pub fn as_str(self) -> &'static str { 15 | MAP.get(self.0) 16 | } 17 | 18 | pub fn suffix(self, suffix: impl std::fmt::Display) -> Symbol { 19 | intern(smol_str::format_smolstr!("{}_{}", self.as_str(), suffix)) 20 | } 21 | } 22 | 23 | static MAP: ConcurrentMap = ConcurrentMap::new(); 24 | 25 | fn intern(key: SmolStr) -> Symbol { 26 | Symbol(MAP.insert(key.clone(), key)) 27 | } 28 | 29 | impl<'a> From<&'a str> for Symbol { 30 | fn from(data: &'a str) -> Symbol { 31 | intern(SmolStr::from(data)) 32 | } 33 | } 34 | 35 | impl From for Symbol { 36 | fn from(data: SmolStr) -> Symbol { 37 | intern(data) 38 | } 39 | } 40 | 41 | impl From for Symbol { 42 | fn from(data: String) -> Symbol { 43 | intern(SmolStr::from(data)) 44 | } 45 | } 46 | 47 | impl From for Symbol { 48 | fn from(data: usize) -> Symbol { 49 | intern(data.to_smolstr()) 50 | } 51 | } 52 | 53 | impl std::fmt::Debug for Symbol { 54 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 55 | write!(f, "{}", self.as_str()) 56 | } 57 | } 58 | 59 | impl std::fmt::Display for Symbol { 60 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 61 | write!(f, "{}", MAP.get(self.0)) 62 | } 63 | } 64 | 65 | impl Serialize for Symbol { 66 | fn serialize(&self, serializer: S) -> Result { 67 | serializer.serialize_str(MAP.get(self.0)) 68 | } 69 | } 70 | 71 | impl<'de> Deserialize<'de> for Symbol { 72 | fn deserialize>(deserializer: D) -> Result { 73 | Ok(intern(SmolStr::from(String::deserialize(deserializer)?))) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /crates/compiler/src/transforms/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod mir_to_ast; 2 | pub mod ast_to_mir; 3 | -------------------------------------------------------------------------------- /crates/compiler/src/traversal/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod mapper; 2 | pub mod visitor; 3 | pub mod mappable; 4 | pub mod visitable; 5 | -------------------------------------------------------------------------------- /crates/compiler/src/traversal/visitable.rs: -------------------------------------------------------------------------------- 1 | use crate::ast::passes::infer::solver::Constraint; 2 | use crate::ast::Ast; 3 | use crate::ast::Expr; 4 | use crate::ast::Stmt; 5 | use crate::ast::Type; 6 | 7 | use super::visitor::Visitor; 8 | 9 | pub(crate) trait Visitable { 10 | fn visit(&self, visitor: &mut impl Visitor); 11 | } 12 | 13 | impl Visitable for Ast { 14 | fn visit(&self, visitor: &mut impl Visitor) { 15 | visitor.visit_program(self); 16 | } 17 | } 18 | 19 | impl Visitable for Stmt { 20 | fn visit(&self, visitor: &mut impl Visitor) { 21 | visitor.visit_stmt(self); 22 | } 23 | } 24 | 25 | impl Visitable for Expr { 26 | fn visit(&self, visitor: &mut impl Visitor) { 27 | visitor.visit_expr(self); 28 | } 29 | } 30 | 31 | impl Visitable for Type { 32 | fn visit(&self, visitor: &mut impl Visitor) { 33 | visitor.visit_type(self); 34 | } 35 | } 36 | 37 | impl Visitable for Constraint { 38 | fn visit(&self, visitor: &mut impl Visitor) { 39 | visitor.visit_constraint(self); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /crates/compiler/tests/ast_to_mir.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | mod common; 3 | 4 | use common::passes::ast_to_mir; 5 | use compiler::aqua; 6 | 7 | #[test] 8 | fn test_lift0() { 9 | let _a = ast_to_mir(aqua!("def g(): i32 = 1;")).unwrap(); 10 | // function g() -> i32 { 11 | // val _0: i32; 12 | // 13 | // 'bb0: { 14 | // _0 = 1; 15 | // } 16 | // } 17 | } 18 | 19 | #[test] 20 | fn test_lift1() { 21 | let _a = ast_to_mir(aqua! { 22 | "val x: i32 = 1;" 23 | }) 24 | .unwrap(); 25 | // function g() -> i32 { 26 | // val _0: i32; 27 | // 28 | // 'bb0: { 29 | // _0 = 1; 30 | // } 31 | // } 32 | } 33 | -------------------------------------------------------------------------------- /crates/compiler/tests/capture.rs: -------------------------------------------------------------------------------- 1 | use common::dsl::expr_closure; 2 | use common::dsl::expr_val_place; 3 | use common::dsl::program; 4 | use common::dsl::stmt_expr; 5 | use compiler::aqua; 6 | 7 | use crate::common::passes::capture; 8 | 9 | #[macro_use] 10 | mod common; 11 | 12 | #[test] 13 | fn test_capture0() { 14 | let a = capture(aqua!("(a) => a;")).unwrap(); 15 | let b = program([stmt_expr(expr_closure(["a"], [], expr_val_place("a")))]); 16 | check!(a, b); 17 | } 18 | 19 | #[test] 20 | fn test_capture1() { 21 | let a = capture(aqua!("val b = 0; (a) => a + b;")).unwrap(); 22 | let b = capture(aqua!("val b = 0; (a|b) => a + b;")).unwrap(); 23 | check!(a, b); 24 | } 25 | -------------------------------------------------------------------------------- /crates/compiler/tests/common/check.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! check { 3 | ($a:expr, $msg:literal) => {{ 4 | let msg = indoc::indoc!($msg); 5 | assert!( 6 | $a.msg == msg, 7 | "{}", 8 | common::check::diff($a.msg, msg.to_string()) 9 | ); 10 | }}; 11 | ($a:expr, $b:expr) => { 12 | assert!($a == $b, "{}", { 13 | let a_str = format!("{}", $a); 14 | let b_str = format!("{}", $b); 15 | if a_str != b_str { 16 | common::check::diff(a_str, b_str) 17 | } else { 18 | let a_str = format!("{}", $a.verbose()); 19 | let b_str = format!("{}", $b.verbose()); 20 | if a_str != b_str { 21 | common::check::diff(a_str, b_str) 22 | } else { 23 | let a_str = format!("{:#?}", $a); 24 | let b_str = format!("{:#?}", $b); 25 | common::check::diff(a_str, b_str) 26 | } 27 | } 28 | }); 29 | }; 30 | ($a:expr, $b:expr, $msg:literal) => {{ 31 | let msg = indoc::indoc!($msg); 32 | check!($a.val, $b); 33 | assert!( 34 | $a.msg == msg, 35 | "{}", 36 | common::check::diff($a.msg, msg.to_string()) 37 | ); 38 | }}; 39 | (@value; $a:expr, $b:expr) => {{ 40 | let a_str = format!("{:#?}", $a); 41 | let b_str = format!("{:#?}", $b); 42 | assert!($a == $b, "{}", common::check::diff(a_str, b_str)); 43 | }}; 44 | } 45 | 46 | #[allow(unused)] 47 | pub fn diff(a: String, b: String) -> String { 48 | let mut output = String::new(); 49 | let diff = similar::TextDiff::from_lines(&a, &b); 50 | for change in diff.iter_all_changes() { 51 | let sign = match change.tag() { 52 | similar::ChangeTag::Delete => "A ", 53 | similar::ChangeTag::Insert => "B ", 54 | similar::ChangeTag::Equal => " ", 55 | }; 56 | output.push_str(&format!("{}{}", sign, change)); 57 | } 58 | output 59 | } 60 | -------------------------------------------------------------------------------- /crates/compiler/tests/common/mod.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | pub mod passes; 3 | pub mod dsl; 4 | pub mod check; 5 | -------------------------------------------------------------------------------- /crates/compiler/tests/controlflow.rs: -------------------------------------------------------------------------------- 1 | use compiler::aqua; 2 | 3 | use crate::common::passes::desugar; 4 | 5 | #[macro_use] 6 | mod common; 7 | 8 | #[test] 9 | fn test_val0() { 10 | let a = desugar(aqua!("val x = 0;")).unwrap(); 11 | let b = desugar(aqua!("let x = 0 in ()")).unwrap(); 12 | check!(a, b); 13 | } 14 | 15 | #[test] 16 | fn test_val1() { 17 | let a = desugar(aqua!( 18 | "val x = 0; 19 | val y = 1;" 20 | )) 21 | .unwrap(); 22 | let b = desugar(aqua!( 23 | "let x = 0 in 24 | let y = 1 in 25 | ()" 26 | )) 27 | .unwrap(); 28 | check!(a, b); 29 | } 30 | 31 | #[test] 32 | fn test_val2() { 33 | let a = desugar(aqua!( 34 | "val x = 0; 35 | val y = 1; 36 | val z = 2;" 37 | )) 38 | .unwrap(); 39 | let b = desugar(aqua!( 40 | "let x = 0 in 41 | let y = 1 in 42 | let z = 2 in 43 | ()" 44 | )) 45 | .unwrap(); 46 | check!(a, b); 47 | } 48 | 49 | #[test] 50 | fn test_val3() { 51 | let a = desugar(aqua!( 52 | "var x = 0; 53 | x = 2; 54 | x;" 55 | )) 56 | .unwrap(); 57 | let b = desugar(aqua!( 58 | "let x = 0 in 59 | let x = 2 in 60 | x" 61 | )) 62 | .unwrap(); 63 | check!(a, b); 64 | } 65 | 66 | #[test] 67 | fn test_val4() { 68 | let a = desugar(aqua!( 69 | "var x = 0; 70 | for y in [1,2,3] { 71 | x = x + y; 72 | }" 73 | )) 74 | .unwrap(); 75 | let b = desugar(aqua!( 76 | "let x = 0 in 77 | let x = [1,2,3].fold(0, fun(y) = let x = x + y in x) in 78 | ()" 79 | )) 80 | .unwrap(); 81 | check!(a, b); 82 | } 83 | -------------------------------------------------------------------------------- /crates/compiler/tests/egglog.rs: -------------------------------------------------------------------------------- 1 | mod common; 2 | 3 | #[cfg(feature = "optimiser")] 4 | #[test] 5 | fn test_egglog_int() { 6 | use common::dsl::expr_int; 7 | use common::dsl::program; 8 | use common::dsl::stmt_def; 9 | use common::dsl::types::ty_i32; 10 | use compiler::opt::into_egg::Context; 11 | 12 | let mut ctx = Context::new(); 13 | let a = ctx.from_program(&program([stmt_def( 14 | "f", 15 | [], 16 | [("x", ty_i32())], 17 | ty_i32(), 18 | [], 19 | expr_int("1").with_type(ty_i32()), 20 | )])); 21 | assert_eq!( 22 | a.to_string(), 23 | "(Program (StmtListCons (StmtDef (Def \"f\" (TypeListCons (TypeListNil) (TypeCons \"i32\")) (ExprInt 1 i32)))) ProgramNil)" 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /crates/compiler/tests/expand.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | mod common; 3 | 4 | use crate::common::passes::expand; 5 | use common::dsl::program; 6 | use compiler::aqua; 7 | 8 | #[test] 9 | fn test_expand0() { 10 | let a = expand(aqua!("type T = i32; var x: T = 1;")).unwrap(); 11 | let b = expand(aqua!("var x: i32 = 1;")).unwrap(); 12 | check!(a, b); 13 | } 14 | 15 | #[test] 16 | fn test_expand1() { 17 | let mut s = String::new(); 18 | for i in 1..49 { 19 | s.push_str(&format!("type T{} = T{};", i, i + 1)); 20 | } 21 | s.push_str("type T49 = i32;"); 22 | s.push_str("var x: T1 = 1;"); 23 | 24 | let a = expand(&s).unwrap(); 25 | let b = expand(aqua!("var x: i32 = 1;")).unwrap(); 26 | 27 | check!(a, b); 28 | } 29 | 30 | #[test] 31 | fn test_expand2() { 32 | let a = expand(aqua!("type T = T;")).unwrap_err(); 33 | let b = program([]); 34 | check!( 35 | a, 36 | b, 37 | "Error: Potential cycle detected when trying to expand type alias. 38 | ╭─[test:1:10] 39 | │ 40 | 1 │ type T = T; 41 | │ ─────┬───┬ 42 | │ ╰────── Tried to expand this type alias. 43 | │ │ 44 | │ ╰── Type aliases can only be nested up to 50 times. 45 | ───╯" 46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /crates/compiler/tests/flatten.rs: -------------------------------------------------------------------------------- 1 | use compiler::aqua; 2 | 3 | use crate::common::passes::flatten; 4 | 5 | #[macro_use] 6 | mod common; 7 | 8 | #[test] 9 | fn test_flatten0() { 10 | let a = flatten(aqua!("1 + 2;")).unwrap(); 11 | let b = flatten(aqua!("Add[_, _]::add(1, 2);")).unwrap(); 12 | check!(a, b); 13 | } 14 | 15 | #[test] 16 | fn test_flatten1() { 17 | let a = flatten(aqua!("&1;")).unwrap(); 18 | let b = flatten(aqua!("val x0 = 1; &x0;")).unwrap(); 19 | check!(a, b); 20 | } 21 | 22 | #[test] 23 | fn test_flatten2() { 24 | let a = flatten(aqua!("&&1;")).unwrap(); 25 | let b = flatten(aqua!("val x0 = 1; val x1 = &x0; &x1;")).unwrap(); 26 | check!(a, b); 27 | } 28 | 29 | #[test] 30 | fn test_flatten3() { 31 | let a = flatten(aqua!("&1 + 1;")).unwrap(); 32 | let b = flatten(aqua!("val x0 = 1; Add[_, _]::add(&x0, 1);")).unwrap(); 33 | check!(a, b); 34 | } 35 | 36 | #[test] 37 | fn test_flatten4() { 38 | let a = flatten(aqua!("1+2;")).unwrap(); 39 | let b = flatten(aqua!("Add[_, _]::add(1,2);")).unwrap(); 40 | check!(a, b); 41 | } 42 | 43 | #[test] 44 | fn test_flatten5() { 45 | let a = flatten(aqua!("{ &1; }")).unwrap(); 46 | let b = flatten(aqua!("{ val x0 = 1; &x0; }")).unwrap(); 47 | check!(a, b); 48 | } 49 | 50 | #[test] 51 | fn test_flatten6() { 52 | let a = flatten(aqua!("{ &&1; }")).unwrap(); 53 | let b = flatten(aqua!("{ val x0 = 1; val x1 = &x0; &x1; }")).unwrap(); 54 | check!(a, b); 55 | } 56 | 57 | #[test] 58 | fn test_flatten7() { 59 | let a = flatten(aqua!("{ &1 + 1; }")).unwrap(); 60 | let b = flatten(aqua!("{ val x0 = 1; Add[_, _]::add(&x0, 1); }")).unwrap(); 61 | check!(a, b); 62 | } 63 | -------------------------------------------------------------------------------- /crates/compiler/tests/opt.egg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aqua-language/aqua/4e71a025d373e3284d17b4475af5dba33aba95ea/crates/compiler/tests/opt.egg -------------------------------------------------------------------------------- /crates/compiler/tests/optimiser.egg: -------------------------------------------------------------------------------- 1 | ;; 1 + 2 = 3 2 | (check (= 3 | (Op2 Add (Val (I64 1)) (Val (I64 2))) 4 | (Val (I64 3)))) 5 | 6 | ;; 1 - 2 = -1 7 | (check (= 8 | (Op2 Sub (Val (I64 1)) (Val (I64 2))) 9 | (Val (I64 (-1))))) 10 | 11 | ;; 1 * 2 = 2 12 | (check (= 13 | (Op2 Mul (Val (I64 1)) (Val (I64 2))) 14 | (Val (I64 2)))) 15 | 16 | ;; 1 / 2 = 0 17 | (check (= 18 | (Op2 Div (Val (I64 1)) (Val (I64 2))) 19 | (Val (I64 0)))) 20 | 21 | -------------------------------------------------------------------------------- /crates/compiler/tests/optimiser.rs: -------------------------------------------------------------------------------- 1 | use compiler::opt::Optimiser; 2 | use egglog::ast::parse::ExprParser; 3 | 4 | #[test] 5 | fn test_rewrites() { 6 | let mut opt = Optimiser::new(); 7 | opt.include("optimiser.egg").unwrap(); 8 | } 9 | 10 | #[test] 11 | fn test_parser() { 12 | let mut opt = Optimiser::new(); 13 | let a = ExprParser::new() 14 | .parse(r#"(Op2 Add (Val (I64 6)) (Op2 Mul (Val (I64 2)) (Val (I64 3))))"#) 15 | .unwrap(); 16 | let b = ExprParser::new().parse("(Val (I64 12))").unwrap(); 17 | assert!(opt.check(a, b)); 18 | } 19 | -------------------------------------------------------------------------------- /crates/compiler/tests/source.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn test_source0() { 3 | let mut sources = compiler::syntax::source::Cache::new(); 4 | assert_eq!(sources.add("file0", "val x = 0;").inner(), 0); 5 | assert_eq!(sources.add("file1", "def f() = 1;").inner(), 1); 6 | } 7 | -------------------------------------------------------------------------------- /crates/config/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "config" 3 | version.workspace = true 4 | edition.workspace = true 5 | 6 | [features] 7 | default = ["clap"] 8 | 9 | [dependencies] 10 | clap = { version = "4.5.4", features = ["derive", "string"], optional = true } 11 | -------------------------------------------------------------------------------- /crates/lsp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lsp" 3 | version.workspace = true 4 | edition.workspace = true 5 | 6 | [dependencies] 7 | compiler = { path = "../compiler" } 8 | 9 | lsp-server = "0.7.6" 10 | lsp-types = "0.97.0" 11 | serde_json = "1.0.113" 12 | serde = { version = "1.0.113", features = ["derive"] } 13 | -------------------------------------------------------------------------------- /crates/macros/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "macros" 7 | version = "0.0.0" 8 | dependencies = [ 9 | "proc-macro2", 10 | "quote", 11 | "syn", 12 | ] 13 | 14 | [[package]] 15 | name = "proc-macro2" 16 | version = "1.0.36" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" 19 | dependencies = [ 20 | "unicode-xid", 21 | ] 22 | 23 | [[package]] 24 | name = "quote" 25 | version = "1.0.14" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" 28 | dependencies = [ 29 | "proc-macro2", 30 | ] 31 | 32 | [[package]] 33 | name = "syn" 34 | version = "1.0.85" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7" 37 | dependencies = [ 38 | "proc-macro2", 39 | "quote", 40 | "unicode-xid", 41 | ] 42 | 43 | [[package]] 44 | name = "unicode-xid" 45 | version = "0.2.2" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 48 | -------------------------------------------------------------------------------- /crates/macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "macros" 3 | version.workspace = true 4 | edition.workspace = true 5 | 6 | [lib] 7 | proc-macro = true 8 | 9 | [dependencies] 10 | quote = "1.0.35" 11 | syn = "2.0.48" 12 | proc-macro2 = "1.0.78" 13 | -------------------------------------------------------------------------------- /crates/macros/src/lib.rs: -------------------------------------------------------------------------------- 1 | use proc_macro::TokenStream; 2 | 3 | mod proc_macro_attrs; 4 | mod proc_macro_derives; 5 | mod proc_macros; 6 | pub(crate) mod utils; 7 | 8 | #[proc_macro_derive(Send)] 9 | pub fn derive_send(input: TokenStream) -> TokenStream { 10 | proc_macro_derives::derive_send(syn::parse_macro_input!(input as syn::DeriveInput)) 11 | } 12 | 13 | #[proc_macro_derive(Sync)] 14 | pub fn derive_sync(input: TokenStream) -> TokenStream { 15 | proc_macro_derives::derive_sync(syn::parse_macro_input!(input as syn::DeriveInput)) 16 | } 17 | 18 | #[proc_macro_derive(Unpin)] 19 | pub fn derive_unpin(input: TokenStream) -> TokenStream { 20 | proc_macro_derives::derive_unpin(syn::parse_macro_input!(input as syn::DeriveInput)) 21 | } 22 | 23 | #[proc_macro_derive(DeepClone)] 24 | pub fn derive_deep_clone(input: TokenStream) -> TokenStream { 25 | proc_macro_derives::derive_deep_clone(syn::parse_macro_input!(input as syn::DeriveInput)) 26 | } 27 | 28 | #[proc_macro_derive(Timestamp, attributes(timestamp))] 29 | pub fn derive_extract_timestamp(input: TokenStream) -> TokenStream { 30 | proc_macro_derives::derive_extract_timestamp(syn::parse_macro_input!(input as syn::DeriveInput)) 31 | } 32 | 33 | #[proc_macro_derive(New)] 34 | pub fn derive_new(input: TokenStream) -> TokenStream { 35 | proc_macro_derives::derive_new(syn::parse_macro_input!(input as syn::DeriveInput)) 36 | } 37 | 38 | /// Unwraps a value out of an enum-variant. Panics if it's the wrong variant. 39 | #[proc_macro] 40 | pub fn unwrap(input: TokenStream) -> TokenStream { 41 | proc_macros::unwrap(input) 42 | } 43 | 44 | #[proc_macro_attribute] 45 | pub fn data(_attr: TokenStream, input: TokenStream) -> TokenStream { 46 | proc_macro_attrs::data(syn::parse_macro_input!(input as syn::DeriveInput)) 47 | } 48 | -------------------------------------------------------------------------------- /crates/macros/src/proc_macro_attrs.rs: -------------------------------------------------------------------------------- 1 | use proc_macro as pm; 2 | 3 | #[allow(unused)] 4 | pub(crate) fn data(mut item: syn::DeriveInput) -> pm::TokenStream { 5 | quote::quote! { 6 | #[derive(Debug, Clone, Send, DeepClone, serde::Serialize, serde::Deserialize, Timestamp, New)] 7 | #[serde(crate = "runtime::prelude::serde")] 8 | // #[serde(bound(deserialize = ""))] 9 | #item 10 | } 11 | .into() 12 | } 13 | -------------------------------------------------------------------------------- /crates/macros/src/proc_macro_attrs/export/functions.rs: -------------------------------------------------------------------------------- 1 | use proc_macro as pm; 2 | use quote::quote; 3 | 4 | pub(crate) fn export(_attr: syn::AttributeArgs, item: syn::ItemFn) -> pm::TokenStream { 5 | let mut inputs = item.sig.inputs.clone().into_iter().collect::>(); 6 | let fn_name = &item.sig.ident; 7 | let name = crate::utils::new_id(format!("export_{}", fn_name)); 8 | let output = &item.sig.output; 9 | let (impl_generics, _, where_clause) = item.sig.generics.split_for_impl(); 10 | let (ids, tys): (Vec<_>, Vec<_>) = inputs 11 | .iter() 12 | .map(|i| match i { 13 | syn::FnArg::Receiver(_) => unreachable!(), 14 | syn::FnArg::Typed(i) => (&i.pat, &i.ty), 15 | }) 16 | .unzip(); 17 | if item.sig.asyncness.is_some() { 18 | quote! { 19 | #item 20 | pub async fn #name #impl_generics ((#(#ids,)*):(#(#tys,)*)) #output #where_clause { 21 | #fn_name(#(#ids,)*).await 22 | } 23 | } 24 | } else { 25 | quote! { 26 | #item 27 | pub fn #name #impl_generics ((#(#ids,)*):(#(#tys,)*)) #output #where_clause { 28 | #fn_name(#(#ids,)*) 29 | } 30 | } 31 | } 32 | .into() 33 | } 34 | -------------------------------------------------------------------------------- /crates/macros/src/proc_macro_attrs/rewrite/enums.rs: -------------------------------------------------------------------------------- 1 | use proc_macro as pm; 2 | use quote::quote; 3 | 4 | #[allow(unused)] 5 | pub(crate) fn rewrite(attr: syn::AttributeArgs, mut item: syn::ItemEnum) -> pm::TokenStream { 6 | item.vis = syn::parse_quote!(pub); 7 | item.generics.params.iter_mut().for_each(|g| { 8 | if let syn::GenericParam::Type(t) = g { 9 | t.bounds.push(syn::parse_quote!(Data)) 10 | } 11 | }); 12 | 13 | let (impl_generics, type_generics, where_clause) = item.generics.split_for_impl(); 14 | 15 | let variant_id = item.variants.iter().map(|v| &v.ident).collect::>(); 16 | 17 | quote!( 18 | use prelude::*; 19 | 20 | #[derive(Clone, Debug, Unpin, Serialize, Deserialize)] 21 | #[serde(bound = "")] 22 | #item 23 | ) 24 | .into() 25 | } 26 | -------------------------------------------------------------------------------- /crates/macros/src/proc_macro_attrs/rewrite/externs.rs: -------------------------------------------------------------------------------- 1 | use proc_macro as pm; 2 | 3 | pub(crate) fn rewrite(attr: syn::AttributeArgs, mut item: syn::ItemFn) -> pm::TokenStream { 4 | let unmangled: syn::Path = crate::utils::get_attr_val("unmangled", &attr); 5 | let ids = item.sig.inputs.iter().map(|arg| { 6 | if let syn::FnArg::Typed(p) = arg { 7 | p.pat.as_ref() 8 | } else { 9 | unreachable!() 10 | } 11 | }); 12 | item.sig.abi = None; 13 | if item.sig.asyncness.is_some() { 14 | item.block = syn::parse_quote!({ #unmangled(#(#ids),*).await }); 15 | } else { 16 | item.block = syn::parse_quote!({ #unmangled(#(#ids),*) }); 17 | } 18 | quote::quote!(#item).into() 19 | } 20 | -------------------------------------------------------------------------------- /crates/macros/src/proc_macro_attrs/rewrite/functions.rs: -------------------------------------------------------------------------------- 1 | use proc_macro as pm; 2 | 3 | pub(crate) fn rewrite(_attr: syn::AttributeArgs, mut item: syn::ItemFn) -> pm::TokenStream { 4 | item.sig.generics.params.iter_mut().for_each(|p| { 5 | if let syn::GenericParam::Type(p) = p { 6 | p.bounds.push(syn::parse_quote!(Data)); 7 | } 8 | }); 9 | quote::quote!(#item).into() 10 | } 11 | -------------------------------------------------------------------------------- /crates/macros/src/proc_macro_attrs/rewrite/main.rs: -------------------------------------------------------------------------------- 1 | use proc_macro as pm; 2 | 3 | pub(crate) fn rewrite(_attr: syn::AttributeArgs, _item: syn::ItemFn) -> pm::TokenStream { 4 | todo!() 5 | } 6 | -------------------------------------------------------------------------------- /crates/macros/src/proc_macro_attrs/rewrite/structs.rs: -------------------------------------------------------------------------------- 1 | use proc_macro as pm; 2 | use quote::quote; 3 | 4 | #[allow(unused)] 5 | pub(crate) fn rewrite(attr: syn::AttributeArgs, mut item: syn::ItemStruct) -> pm::TokenStream { 6 | item.vis = syn::parse_quote!(pub); 7 | item.fields.iter_mut().for_each(|field| { 8 | field.vis = syn::parse_quote!(pub); 9 | }); 10 | item.generics.params.iter_mut().for_each(|g| { 11 | if let syn::GenericParam::Type(t) = g { 12 | t.bounds.push(syn::parse_quote!(Data)) 13 | } 14 | }); 15 | let (impl_generics, type_generics, where_clause) = item.generics.split_for_impl(); 16 | 17 | let wrapper_id = item.ident.clone(); 18 | item.ident = crate::utils::new_id(format!("_{}", wrapper_id)); 19 | let id = &item.ident; 20 | 21 | let field_id = item.fields.iter().map(|f| &f.ident).collect::>(); 22 | 23 | let (inner_type, inner_expr) = 24 | if crate::utils::has_meta_key("compact", &crate::utils::get_metas(&attr)) { 25 | (quote::quote!(#id #type_generics), quote::quote!(data)) 26 | } else { 27 | ( 28 | quote::quote!(Rc<#id #type_generics>), 29 | quote::quote!(Rc::new(data)), 30 | ) 31 | }; 32 | 33 | quote!( 34 | use prelude::*; 35 | 36 | #[derive(Clone, Debug, Unpin, Serialize, Deserialize)] 37 | #[serde(bound = "")] 38 | pub struct #wrapper_id #impl_generics(pub #inner_type) #where_clause; 39 | 40 | impl #impl_generics #wrapper_id #type_generics #where_clause { 41 | pub fn new(data: #id #type_generics) -> Self { 42 | Self(#inner_expr) 43 | } 44 | } 45 | 46 | #[derive(Clone, Debug, Unpin, Serialize, Deserialize)] 47 | #[serde(bound = "")] 48 | #item 49 | ) 50 | .into() 51 | } 52 | -------------------------------------------------------------------------------- /crates/macros/src/proc_macros.rs: -------------------------------------------------------------------------------- 1 | use proc_macro::TokenStream; 2 | 3 | pub fn unwrap(input: TokenStream) -> TokenStream { 4 | let mut iter = input.into_iter(); 5 | let expr: syn::Expr = crate::utils::parse(&mut iter); 6 | let path: syn::Path = crate::utils::parse(&mut iter); 7 | quote::quote!(if let #path(v) = &#expr { v.clone() } else { unreachable!() }).into() 8 | } 9 | -------------------------------------------------------------------------------- /crates/macros/src/utils.rs: -------------------------------------------------------------------------------- 1 | use proc_macro as pm; 2 | 3 | pub(crate) fn parse(input: &mut impl Iterator) -> T { 4 | let mut stream = pm::TokenStream::new(); 5 | for token in input.by_ref() { 6 | match token { 7 | pm::TokenTree::Punct(t) if t.as_char() == ',' => break, 8 | _ => stream.extend([token]), 9 | } 10 | } 11 | syn::parse::(stream).unwrap() 12 | } 13 | -------------------------------------------------------------------------------- /crates/repl/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "repl" 3 | version.workspace = true 4 | edition.workspace = true 5 | 6 | [dependencies] 7 | compiler = { path = "../compiler" } 8 | config = { path = "../config" } 9 | 10 | anyhow = { version = "1.0.75" } 11 | regex = { version = "1.10.3" } 12 | rustyline = { version = "14.0.0", features = ["derive", "custom-bindings"] } 13 | colored = { version = "2.0.4" } 14 | -------------------------------------------------------------------------------- /crates/repl/src/config.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, Default, Clone)] 2 | #[cfg_attr(feature = "clap", derive(clap::Parser))] 3 | pub struct Config { 4 | #[cfg_attr(feature = "clap", clap(long, default_value = history()))] 5 | pub history: PathBuf, 6 | } 7 | -------------------------------------------------------------------------------- /crates/repl/src/helper/completer.rs: -------------------------------------------------------------------------------- 1 | // use compiler_passes_lexer::tokens::KEYWORDS; 2 | use rustyline::completion::Completer; 3 | use rustyline::completion::Pair; 4 | use rustyline::Result; 5 | 6 | pub struct KeywordCompleter; 7 | 8 | impl Default for KeywordCompleter { 9 | fn default() -> Self { 10 | Self::new() 11 | } 12 | } 13 | 14 | impl KeywordCompleter { 15 | pub fn new() -> Self { 16 | Self 17 | } 18 | } 19 | 20 | impl Completer for KeywordCompleter { 21 | type Candidate = Pair; 22 | 23 | fn complete( 24 | &self, 25 | line: &str, 26 | pos: usize, 27 | _ctx: &rustyline::Context<'_>, 28 | ) -> Result<(usize, Vec)> { 29 | todo!() 30 | // let mut start = pos - 1; 31 | // let mut end = pos; 32 | // let chars = line.chars().collect::>(); 33 | // while start > 0 { 34 | // match chars[start] { 35 | // 'a'..='z' => start -= 1, 36 | // _ => break, 37 | // } 38 | // } 39 | // while end < line.len() { 40 | // match chars[end] { 41 | // 'a'..='z' => end += 1, 42 | // _ => break, 43 | // } 44 | // } 45 | // let matches = KEYWORDS 46 | // .into_iter() 47 | // .filter(|cmd| cmd.starts_with(&line[start..end])) 48 | // .map(|x| Pair { 49 | // display: x.to_string(), 50 | // replacement: x.to_string(), 51 | // }) 52 | // .collect(); 53 | // Ok((start, matches)) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /crates/repl/src/helper/hinter.rs: -------------------------------------------------------------------------------- 1 | use rustyline::hint::Hinter; 2 | use rustyline::Hinter; 3 | 4 | use super::Repl; 5 | 6 | -------------------------------------------------------------------------------- /crates/repl/src/helper/validator.rs: -------------------------------------------------------------------------------- 1 | use colored::Color::Blue; 2 | use colored::Colorize; 3 | use rustyline::validate::ValidationContext; 4 | use rustyline::validate::ValidationResult; 5 | use rustyline::validate::Validator; 6 | use rustyline::Result; 7 | 8 | #[derive(Default)] 9 | pub struct StmtValidator; 10 | 11 | impl StmtValidator { 12 | pub fn new() -> Self { 13 | Self 14 | } 15 | } 16 | 17 | impl Validator for StmtValidator { 18 | fn validate(&self, ctx: &mut ValidationContext) -> Result { 19 | let input = ctx.input(); 20 | let stmts = StmtIterator::new(input); 21 | if (stmts.count() > 0 && input.ends_with(';')) || input.ends_with('\n') { 22 | Ok(ValidationResult::Valid(None)) 23 | } else if input.is_empty() { 24 | Ok(ValidationResult::Invalid(Some( 25 | " Enter statement".color(Blue).to_string(), 26 | ))) 27 | } else { 28 | return Ok(ValidationResult::Incomplete); 29 | } 30 | } 31 | } 32 | 33 | pub struct StmtIterator<'a> { 34 | input: &'a str, 35 | } 36 | 37 | impl<'a> StmtIterator<'a> { 38 | pub fn new(input: &'a str) -> Self { 39 | Self { 40 | input: input.trim(), 41 | } 42 | } 43 | } 44 | 45 | impl<'a> Iterator for StmtIterator<'a> { 46 | type Item = &'a str; 47 | 48 | fn next(&mut self) -> Option { 49 | let mut depth = 0; 50 | let mut end = 0; 51 | for (i, c) in self.input.char_indices() { 52 | match c { 53 | '(' | '{' | '[' => depth += 1, 54 | ')' | '}' | ']' => depth -= 1, 55 | ';' if depth == 0 => { 56 | end = i; 57 | break; 58 | } 59 | _ => continue, 60 | } 61 | } 62 | if end == 0 { 63 | None 64 | } else { 65 | let stmt = &self.input[..end + 1].trim(); 66 | self.input = &self.input[end + 1..]; 67 | Some(stmt) 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /crates/runtime/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | rustflags = [ "--cfg", "tokio_unstable" ] 3 | -------------------------------------------------------------------------------- /crates/runtime/benches/vec.rs: -------------------------------------------------------------------------------- 1 | use criterion::black_box; 2 | use criterion::criterion_group; 3 | use criterion::criterion_main; 4 | use criterion::Criterion; 5 | 6 | use std::cell::RefCell; 7 | use std::rc::Rc; 8 | 9 | fn for_each_iter(c: &mut Criterion) { 10 | c.bench_function("for_each_iter", |b| { 11 | b.iter(|| { 12 | let iter = 0..1_000_000; 13 | iter.for_each(|x| { 14 | black_box(x); 15 | }); 16 | }); 17 | }); 18 | } 19 | 20 | fn for_each_dyn_iter(c: &mut Criterion) { 21 | c.bench_function("for_each_dyn_iter", |b| { 22 | b.iter(|| { 23 | let iter: Box> = Box::new(0..1_000_000); 24 | iter.for_each(|x| { 25 | black_box(x); 26 | }); 27 | }); 28 | }); 29 | } 30 | 31 | fn push_vec(c: &mut Criterion) { 32 | c.bench_function("push_vec", |b| { 33 | b.iter(|| { 34 | let mut v = std::vec::Vec::::with_capacity(1_000_000); 35 | for i in 0..1_000_000 { 36 | let i = black_box(i); 37 | v.push(i); 38 | } 39 | }); 40 | }); 41 | } 42 | 43 | fn push_rc_refcell_vec(c: &mut Criterion) { 44 | c.bench_function("push_rc_refcell_vec", |b| { 45 | b.iter(|| { 46 | let v = Rc::new(RefCell::new(Vec::::with_capacity(1_000_000))); 47 | for i in 0..1_000_000 { 48 | let mut v = black_box(v.borrow_mut()); 49 | let i = black_box(i); 50 | v.push(i); 51 | } 52 | }); 53 | }); 54 | } 55 | 56 | criterion_group!(b0, for_each_iter, for_each_dyn_iter); 57 | criterion_group!(b1, push_vec, push_rc_refcell_vec); 58 | criterion_main!(b0, b1); 59 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/blob.rs: -------------------------------------------------------------------------------- 1 | use macros::DeepClone; 2 | use serde::Deserialize; 3 | use serde::Serialize; 4 | 5 | use crate::builtins::unchecked_cell::UncheckedCell; 6 | use crate::traits::DeepClone; 7 | 8 | #[derive(Debug, Clone, Serialize, Deserialize, DeepClone)] 9 | #[repr(C)] 10 | pub struct Blob(pub(crate) UncheckedCell>); 11 | 12 | impl std::fmt::Display for Blob { 13 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 14 | write!(f, "Blob({:?})", self.0) 15 | } 16 | } 17 | 18 | impl Blob { 19 | pub fn new(bytes: std::vec::Vec) -> Self { 20 | Self(UncheckedCell::new(bytes)) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/cell.rs: -------------------------------------------------------------------------------- 1 | use macros::DeepClone; 2 | use macros::Send; 3 | use macros::Sync; 4 | use macros::Unpin; 5 | use serde::Deserialize; 6 | use serde::Serialize; 7 | 8 | use crate::traits::DeepClone; 9 | 10 | #[derive(DeepClone, Send, Sync, Unpin, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd)] 11 | #[repr(C)] 12 | pub struct Cell(pub std::rc::Rc>); 13 | 14 | impl Clone for Cell { 15 | fn clone(&self) -> Self { 16 | Cell(self.0.clone()) 17 | } 18 | } 19 | 20 | impl std::hash::Hash for Cell 21 | where 22 | T: std::hash::Hash, 23 | { 24 | fn hash(&self, state: &mut H) { 25 | self.0.borrow().hash(state); 26 | } 27 | } 28 | 29 | impl std::fmt::Debug for Cell { 30 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 31 | self.0.as_ref().fmt(f) 32 | } 33 | } 34 | 35 | impl Cell { 36 | pub fn new(value: T) -> Cell { 37 | Cell(std::rc::Rc::new(std::cell::RefCell::new(value))) 38 | } 39 | 40 | pub fn as_mut(&self) -> std::cell::RefMut { 41 | self.0.borrow_mut() 42 | } 43 | 44 | pub fn as_ref(&self) -> std::cell::Ref { 45 | self.0.borrow() 46 | } 47 | 48 | pub fn share(&self) -> Self { 49 | self.clone() 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/channel.rs: -------------------------------------------------------------------------------- 1 | pub mod spsc; 2 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/dataflow.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | pub struct Dataflow { 3 | pub tx: tokio::sync::broadcast::Sender<()>, 4 | } 5 | 6 | impl Dataflow { 7 | pub fn new(tx: tokio::sync::broadcast::Sender<()>) -> Self { 8 | Self { tx } 9 | } 10 | pub fn run(self) { 11 | self.tx.send(()).unwrap(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/dataframe.rs: -------------------------------------------------------------------------------- 1 | // use crate::cow::Cow; 2 | // use crate::vec::Vec; 3 | // 4 | // pub struct DataFrame(pub Cow); 5 | // 6 | // pub struct Series(pub Cow); 7 | // 8 | // impl DataFrame { 9 | // pub fn new(columns: Vec) -> Self { 10 | // DataFrame(polars::prelude::DataFrame::new(columns.0.take())) 11 | // } 12 | // 13 | // } 14 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/dict.rs: -------------------------------------------------------------------------------- 1 | use std::hash::Hash; 2 | 3 | use serde::Deserialize; 4 | use serde::Serialize; 5 | 6 | use crate::traits::DeepClone; 7 | use crate::HashMap; 8 | 9 | use super::cell::Cell; 10 | 11 | #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] 12 | #[repr(C)] 13 | pub struct Dict(pub Cell>); 14 | 15 | impl std::fmt::Display for Dict { 16 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 17 | write!(f, "{{")?; 18 | let x = self.0.as_ref(); 19 | let mut iter = x.iter(); 20 | if let Some((k, v)) = iter.next() { 21 | write!(f, "{}: {}", k, v)?; 22 | for (k, v) in iter { 23 | write!(f, ", {}: {}", k, v)?; 24 | } 25 | } 26 | write!(f, "}}") 27 | } 28 | } 29 | 30 | impl DeepClone for Dict { 31 | fn deep_clone(&self) -> Self { 32 | let map = self 33 | .0 34 | .as_ref() 35 | .iter() 36 | .map(|(k, v)| (k.deep_clone(), v.deep_clone())) 37 | .collect(); 38 | Dict(Cell::new(map)) 39 | } 40 | } 41 | 42 | impl Dict { 43 | pub fn new() -> Dict { 44 | Dict(Cell::new(HashMap::default())) 45 | } 46 | 47 | pub fn get(&self, key: impl std::borrow::Borrow) -> Option 48 | where 49 | K: Clone, 50 | V: Clone, 51 | { 52 | self.0.as_ref().get(key.borrow()).cloned() 53 | } 54 | 55 | pub fn insert(&self, key: K, val: V) 56 | where 57 | K: Clone, 58 | V: Clone, 59 | { 60 | self.0.as_mut().insert(key, val); 61 | } 62 | 63 | pub fn remove(&self, key: impl std::borrow::Borrow) -> Option 64 | where 65 | K: Clone, 66 | V: Clone, 67 | { 68 | self.0.as_mut().remove(key.borrow()) 69 | } 70 | 71 | pub fn contains_key(&self, key: impl std::borrow::Borrow) -> bool { 72 | self.0.as_ref().contains_key(key.borrow()) 73 | } 74 | } 75 | 76 | impl From> for Dict { 77 | fn from(map: HashMap) -> Self { 78 | Dict(Cell::new(map)) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/file.rs: -------------------------------------------------------------------------------- 1 | use std::io::Read; 2 | 3 | use crate::builtins::blob::Blob; 4 | use crate::builtins::path::Path; 5 | use crate::builtins::string::String; 6 | 7 | #[derive(Debug, Clone)] 8 | #[repr(C)] 9 | pub struct File(pub std::rc::Rc>); 10 | 11 | impl std::fmt::Display for File { 12 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 13 | write!(f, "File({:?})", self.0) 14 | } 15 | } 16 | 17 | impl File { 18 | pub fn open(path: impl Into) -> Self { 19 | File::from(std::fs::File::open(path.into().0).unwrap()) 20 | } 21 | 22 | pub fn read_to_string(self) -> String { 23 | let mut string = std::string::String::new(); 24 | self.0.borrow_mut().read_to_string(&mut string).unwrap(); 25 | String::from(string) 26 | } 27 | 28 | pub fn read_to_bytes(self) -> Blob { 29 | let mut vec = std::vec::Vec::new(); 30 | self.0.borrow_mut().read_to_end(&mut vec).unwrap(); 31 | Blob::new(vec) 32 | } 33 | } 34 | 35 | impl From for File { 36 | fn from(file: std::fs::File) -> Self { 37 | Self(std::rc::Rc::new(std::cell::RefCell::new(file))) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/format.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use serde::Serialize; 3 | 4 | use crate::traits::DeepClone; 5 | 6 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] 7 | #[repr(C)] 8 | pub enum Format { 9 | Csv { sep: char }, 10 | Json, 11 | } 12 | 13 | impl std::fmt::Display for Format { 14 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 15 | match self { 16 | Format::Csv { sep } => write!(f, "Csv({})", sep), 17 | Format::Json => write!(f, "Json"), 18 | } 19 | } 20 | } 21 | 22 | impl DeepClone for Format { 23 | fn deep_clone(&self) -> Self { 24 | self.clone() 25 | } 26 | } 27 | 28 | impl Format { 29 | pub fn csv(sep: char) -> Self { 30 | Self::Csv { sep } 31 | } 32 | pub fn json() -> Self { 33 | Self::Json 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/im_string.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use serde::Serialize; 3 | 4 | use crate::traits::DeepClone; 5 | use crate::SmolStr; 6 | 7 | #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] 8 | pub struct String(pub(crate) SmolStr); 9 | 10 | impl std::fmt::Display for String { 11 | #[inline(always)] 12 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 13 | write!(f, "{}", self.0) 14 | } 15 | } 16 | 17 | impl PartialEq for String { 18 | #[inline(always)] 19 | fn eq(&self, other: &str) -> bool { 20 | self.0 == other 21 | } 22 | } 23 | 24 | impl<'a> PartialEq<&'a str> for String { 25 | #[inline(always)] 26 | fn eq(&self, other: &&'a str) -> bool { 27 | self.0 == *other 28 | } 29 | } 30 | 31 | impl DeepClone for String { 32 | #[inline(always)] 33 | fn deep_clone(&self) -> Self { 34 | Self(self.0.clone()) 35 | } 36 | } 37 | 38 | impl String { 39 | #[inline(always)] 40 | pub fn new>(s: T) -> Self { 41 | Self(SmolStr::from(s.as_ref())) 42 | } 43 | } 44 | 45 | impl<'a> From<&'a str> for String { 46 | #[inline(always)] 47 | fn from(s: &'a str) -> Self { 48 | Self(SmolStr::from(s)) 49 | } 50 | } 51 | 52 | impl From for String { 53 | #[inline(always)] 54 | fn from(s: std::string::String) -> Self { 55 | Self(SmolStr::from(s)) 56 | } 57 | } 58 | 59 | impl String { 60 | pub fn len(&self) -> usize { 61 | self.0.len() 62 | } 63 | 64 | pub fn clear(&self) -> Self { 65 | String::from("") 66 | } 67 | 68 | pub fn concat(&self, other: &Self) -> Self { 69 | let mut s = std::string::String::with_capacity(self.0.len() + other.0.len()); 70 | s.push_str(&self.0); 71 | s.push_str(&other.0); 72 | Self::from(s) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/keyed_stream.rs: -------------------------------------------------------------------------------- 1 | mod drain; 2 | mod filter; 3 | mod flat_map; 4 | mod fork; 5 | pub mod incr_window; 6 | mod join; 7 | mod keyby; 8 | mod map; 9 | mod merge; 10 | mod scan; 11 | mod sink; 12 | mod unkey; 13 | mod window; 14 | 15 | use tokio::sync::mpsc::Receiver; 16 | use tokio::sync::mpsc::Sender; 17 | 18 | use crate::builtins::time::Time; 19 | use crate::traits::Data; 20 | use crate::traits::Key; 21 | use serde::Deserialize; 22 | use serde::Serialize; 23 | 24 | use super::stream::SendError; 25 | 26 | #[derive(Debug, Serialize, Deserialize)] 27 | pub enum KeyedEvent { 28 | Data(Time, K, T), 29 | Watermark(Time), 30 | Snapshot(usize), 31 | Sentinel, 32 | } 33 | 34 | pub struct KeyedStream(pub(crate) Receiver>); 35 | 36 | pub struct KeyedCollector(pub(crate) Sender>); 37 | 38 | impl KeyedStream { 39 | pub async fn recv(&mut self) -> KeyedEvent { 40 | self.0.recv().await.unwrap_or(KeyedEvent::Sentinel) 41 | } 42 | } 43 | 44 | impl KeyedCollector { 45 | pub async fn send(&self, event: KeyedEvent) -> Result<(), SendError> { 46 | self.0.send(event).await.map_err(|_| SendError::Closed) 47 | } 48 | } 49 | 50 | impl KeyedStream { 51 | pub(crate) fn new() -> (KeyedCollector, KeyedStream) { 52 | let (tx, rx) = tokio::sync::mpsc::channel(100); 53 | (KeyedCollector(tx), KeyedStream(rx)) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/keyed_stream/drain.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | use crate::traits::Data; 3 | use crate::traits::Key; 4 | 5 | use super::KeyedEvent; 6 | use super::KeyedStream; 7 | 8 | impl KeyedStream { 9 | pub fn drain(mut self, ctx: &mut Context) { 10 | ctx.sink(|| async move { 11 | loop { 12 | if let KeyedEvent::Sentinel = self.recv().await { 13 | break; 14 | } 15 | } 16 | Ok(()) 17 | }); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/keyed_stream/filter.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | use crate::traits::Data; 3 | use crate::traits::Key; 4 | 5 | use super::KeyedEvent; 6 | use super::KeyedStream; 7 | 8 | impl KeyedStream { 9 | pub fn filter( 10 | mut self, 11 | ctx: &mut Context, 12 | f: impl Fn(&T) -> bool + Send + 'static, 13 | ) -> KeyedStream { 14 | ctx.keyed_operator(move |tx| async move { 15 | loop { 16 | match self.recv().await { 17 | KeyedEvent::Data(t, k, v) => { 18 | if f(&v) { 19 | tx.send(KeyedEvent::Data(t, k, v)).await?; 20 | } 21 | } 22 | KeyedEvent::Watermark(t) => tx.send(KeyedEvent::Watermark(t)).await?, 23 | KeyedEvent::Snapshot(i) => tx.send(KeyedEvent::Snapshot(i)).await?, 24 | KeyedEvent::Sentinel => { 25 | tx.send(KeyedEvent::Sentinel).await?; 26 | break; 27 | } 28 | } 29 | } 30 | Ok(()) 31 | }) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/keyed_stream/flat_map.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::vec::Vec; 2 | use crate::runner::context::Context; 3 | use crate::traits::Data; 4 | use crate::traits::Key; 5 | 6 | use super::KeyedEvent; 7 | use super::KeyedStream; 8 | 9 | impl KeyedStream 10 | where 11 | K: Key, 12 | T: Data, 13 | { 14 | pub fn flat_map( 15 | mut self, 16 | ctx: &mut Context, 17 | f: impl Fn(T) -> Vec + Send + 'static, 18 | ) -> KeyedStream 19 | where 20 | O: Data, 21 | { 22 | ctx.keyed_operator(|tx| async move { 23 | loop { 24 | match self.recv().await { 25 | KeyedEvent::Data(t, k, v) => { 26 | for v in f(v).iter() { 27 | tx.send(KeyedEvent::Data(t, k.deep_clone(), v)).await?; 28 | } 29 | } 30 | KeyedEvent::Watermark(t) => tx.send(KeyedEvent::Watermark(t)).await?, 31 | KeyedEvent::Snapshot(i) => tx.send(KeyedEvent::Snapshot(i)).await?, 32 | KeyedEvent::Sentinel => { 33 | tx.send(KeyedEvent::Sentinel).await?; 34 | break; 35 | } 36 | } 37 | } 38 | Ok(()) 39 | }) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/keyed_stream/fork.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | use crate::traits::Data; 3 | use crate::traits::Key; 4 | use crate::try_pair; 5 | 6 | use super::KeyedEvent; 7 | use super::KeyedStream; 8 | 9 | impl KeyedStream { 10 | pub fn split(mut self, ctx: &mut Context) -> (Self, Self) { 11 | ctx.keyed_co_operator(|tx1, tx2| async move { 12 | loop { 13 | match self.recv().await { 14 | KeyedEvent::Data(t, k1, v1) => { 15 | let k2 = k1.deep_clone(); 16 | let v2 = v1.deep_clone(); 17 | try_pair!(tokio::join!( 18 | tx1.send(KeyedEvent::Data(t, k2, v2)), 19 | tx2.send(KeyedEvent::Data(t, k1, v1)), 20 | )); 21 | } 22 | KeyedEvent::Watermark(t) => { 23 | try_pair!(tokio::join!( 24 | tx1.send(KeyedEvent::Watermark(t)), 25 | tx2.send(KeyedEvent::Watermark(t)) 26 | )); 27 | } 28 | KeyedEvent::Snapshot(i) => { 29 | try_pair!(tokio::join!( 30 | tx1.send(KeyedEvent::Snapshot(i)), 31 | tx2.send(KeyedEvent::Snapshot(i)) 32 | )); 33 | } 34 | KeyedEvent::Sentinel => { 35 | try_pair!(tokio::join!( 36 | tx1.send(KeyedEvent::Sentinel), 37 | tx2.send(KeyedEvent::Sentinel) 38 | )); 39 | break; 40 | } 41 | }; 42 | } 43 | Ok(()) 44 | }) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/keyed_stream/join.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::dict::Dict; 2 | use crate::runner::context::Context; 3 | use crate::traits::Data; 4 | use crate::traits::Key; 5 | 6 | use super::KeyedEvent; 7 | use super::KeyedStream; 8 | 9 | impl KeyedStream { 10 | pub fn join( 11 | mut self, 12 | ctx: &mut Context, 13 | index: Dict, 14 | merge: impl Fn(&T, &R) -> O + Send + 'static, 15 | ) -> KeyedStream 16 | where 17 | R: Data, 18 | O: Data, 19 | { 20 | ctx.keyed_operator(|tx| async move { 21 | loop { 22 | match self.recv().await { 23 | KeyedEvent::Data(t, k, v0) => { 24 | if let Some(v1) = index.get(&k) { 25 | let v2 = merge(&v0, &v1); 26 | tx.send(KeyedEvent::Data(t, k, v2)).await?; 27 | } 28 | } 29 | KeyedEvent::Watermark(t) => { 30 | tx.send(KeyedEvent::Watermark(t)).await?; 31 | } 32 | KeyedEvent::Snapshot(i) => { 33 | tx.send(KeyedEvent::Snapshot(i)).await?; 34 | } 35 | KeyedEvent::Sentinel => { 36 | tx.send(KeyedEvent::Sentinel).await?; 37 | break; 38 | } 39 | } 40 | } 41 | Ok(()) 42 | }) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/keyed_stream/keyby.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | use crate::traits::Data; 3 | use crate::traits::Key; 4 | 5 | use super::KeyedEvent; 6 | use super::KeyedStream; 7 | 8 | impl KeyedStream { 9 | pub fn keyby( 10 | mut self, 11 | ctx: &mut Context, 12 | fun: impl Fn(&T) -> K1 + Send + 'static, 13 | ) -> KeyedStream { 14 | ctx.keyed_operator(|tx| async move { 15 | loop { 16 | match self.0.recv().await.unwrap() { 17 | KeyedEvent::Data(t, _, v) => { 18 | let k = fun(&v); 19 | tx.send(KeyedEvent::Data(t, k, v)).await?; 20 | } 21 | KeyedEvent::Watermark(t) => { 22 | tx.send(KeyedEvent::Watermark(t)).await?; 23 | } 24 | KeyedEvent::Snapshot(i) => { 25 | tx.send(KeyedEvent::Snapshot(i)).await?; 26 | } 27 | KeyedEvent::Sentinel => { 28 | tx.send(KeyedEvent::Sentinel).await?; 29 | break; 30 | } 31 | } 32 | } 33 | Ok(()) 34 | }) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/keyed_stream/map.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | use crate::traits::Data; 3 | use crate::traits::Key; 4 | 5 | use super::KeyedEvent; 6 | use super::KeyedStream; 7 | 8 | impl KeyedStream { 9 | pub fn map( 10 | mut self, 11 | ctx: &mut Context, 12 | f: impl Fn(T) -> O + Send + 'static, 13 | ) -> KeyedStream 14 | where 15 | O: Data, 16 | { 17 | ctx.keyed_operator(|tx| async move { 18 | loop { 19 | match self.recv().await { 20 | KeyedEvent::Data(t, k, v) => tx.send(KeyedEvent::Data(t, k, f(v))).await?, 21 | KeyedEvent::Watermark(t) => tx.send(KeyedEvent::Watermark(t)).await?, 22 | KeyedEvent::Snapshot(i) => tx.send(KeyedEvent::Snapshot(i)).await?, 23 | KeyedEvent::Sentinel => { 24 | tx.send(KeyedEvent::Sentinel).await?; 25 | break; 26 | } 27 | } 28 | } 29 | Ok(()) 30 | }) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/keyed_stream/merge.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::keyed_stream::KeyedEvent; 2 | use crate::runner::context::Context; 3 | use crate::traits::Data; 4 | use crate::traits::Key; 5 | 6 | use super::KeyedStream; 7 | 8 | impl KeyedStream { 9 | pub fn merge(mut self, ctx: &mut Context, mut other: Self) -> Self { 10 | ctx.keyed_operator(|tx| async move { 11 | loop { 12 | let event = tokio::select! { 13 | event = self.recv() => { 14 | if let KeyedEvent::Sentinel = event { 15 | other.recv().await 16 | } else { 17 | event 18 | } 19 | }, 20 | event = other.recv() => { 21 | if let KeyedEvent::Sentinel = event { 22 | self.recv().await 23 | } else { 24 | event 25 | } 26 | }, 27 | }; 28 | match event { 29 | KeyedEvent::Data(t, k1, v1) => { 30 | tx.send(KeyedEvent::Data(t, k1, v1)).await?; 31 | } 32 | KeyedEvent::Watermark(t) => { 33 | tx.send(KeyedEvent::Watermark(t)).await?; 34 | } 35 | KeyedEvent::Snapshot(i) => { 36 | tx.send(KeyedEvent::Snapshot(i)).await?; 37 | } 38 | KeyedEvent::Sentinel => { 39 | tx.send(KeyedEvent::Sentinel).await?; 40 | break; 41 | } 42 | } 43 | } 44 | Ok(()) 45 | }) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/keyed_stream/scan.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | use crate::HashMap; 3 | 4 | use crate::runner::context::Context; 5 | use crate::traits::Data; 6 | use crate::traits::Key; 7 | 8 | use super::KeyedEvent; 9 | use super::KeyedStream; 10 | 11 | impl KeyedStream { 12 | pub fn scan( 13 | mut self, 14 | ctx: &mut Context, 15 | lift: impl Fn(&T) -> P + Send + 'static, 16 | combine: impl Fn(&P, P) -> P + Send + 'static, 17 | lower: impl Fn(K, &P) -> O + Send + 'static, 18 | ) -> KeyedStream 19 | where 20 | P: Data, 21 | O: Data, 22 | { 23 | ctx.keyed_operator(|tx| async move { 24 | let state: HashMap = HashMap::default(); 25 | loop { 26 | match self.recv().await { 27 | KeyedEvent::Data(t, k, v) => { 28 | todo!() 29 | // let p = state.entry(k.clone()).or_insert_with(identity); 30 | // *p = combine(p.clone(), lift(v)); 31 | // tx1.send(KeyedEvent::Data(t, k, lower(p.clone()))) 32 | // .await 33 | // .unwrap(); 34 | } 35 | KeyedEvent::Watermark(t) => { 36 | tx.send(KeyedEvent::Watermark(t)).await?; 37 | } 38 | KeyedEvent::Snapshot(i) => { 39 | tx.send(KeyedEvent::Snapshot(i)).await?; 40 | } 41 | KeyedEvent::Sentinel => { 42 | tx.send(KeyedEvent::Sentinel).await?; 43 | break; 44 | } 45 | } 46 | } 47 | Ok(()) 48 | }) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/keyed_stream/sink.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/keyed_stream/unkey.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::stream::Event; 2 | use crate::builtins::stream::Stream; 3 | use crate::runner::context::Context; 4 | use crate::traits::Data; 5 | use crate::traits::Key; 6 | 7 | use super::KeyedEvent; 8 | use super::KeyedStream; 9 | 10 | impl KeyedStream { 11 | pub fn unkey(mut self, ctx: &mut Context) -> Stream { 12 | ctx.operator(|tx| async move { 13 | loop { 14 | match self.recv().await { 15 | KeyedEvent::Data(t, _, v) => { 16 | tx.send(Event::Data(t, v)).await?; 17 | } 18 | KeyedEvent::Watermark(t) => { 19 | tx.send(Event::Watermark(t)).await?; 20 | } 21 | KeyedEvent::Snapshot(i) => { 22 | tx.send(Event::Snapshot(i)).await?; 23 | } 24 | KeyedEvent::Sentinel => { 25 | tx.send(Event::Sentinel).await?; 26 | break; 27 | } 28 | } 29 | } 30 | Ok(()) 31 | }) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/keyed_stream/window.rs: -------------------------------------------------------------------------------- 1 | pub mod time_tumbling_holistic; 2 | pub mod count_sliding_holistic; 3 | pub mod time_tumbling_holistic_vec; 4 | // pub mod time_sliding_holistic; 5 | pub mod time_sliding_aligned_commutative_associative; 6 | pub mod time_sliding_aligned_holistic; 7 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/keyed_stream/window/time_tumbling_holistic_vec.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | use crate::builtins::duration::Duration; 4 | use crate::builtins::keyed_stream::KeyedEvent; 5 | use crate::builtins::keyed_stream::KeyedStream; 6 | use crate::builtins::stream::window::WindowRange; 7 | use crate::builtins::time::Time; 8 | use crate::runner::context::Context; 9 | use crate::traits::Data; 10 | use crate::traits::Key; 11 | use crate::HashMap; 12 | 13 | impl KeyedStream { 14 | pub fn time_tumbling_holistic_vec_window( 15 | mut self, 16 | ctx: &mut Context, 17 | _duration: Duration, 18 | _compute: impl for<'a> Fn(&K, &'a [T], WindowRange) -> O + Send + 'static, 19 | ) -> KeyedStream 20 | where 21 | O: Data, 22 | { 23 | ctx.keyed_operator(|tx| async move { 24 | let mut _aggs: VecDeque<(Time, HashMap>)> = VecDeque::new(); 25 | loop { 26 | match self.recv().await { 27 | KeyedEvent::Data(_time, _key, _data) => { 28 | todo!() 29 | } 30 | KeyedEvent::Watermark(_time) => { 31 | todo!(); 32 | // tx.send(KeyedEvent::Watermark(time)).await; 33 | } 34 | KeyedEvent::Snapshot(i) => { 35 | tx.send(KeyedEvent::Snapshot(i)).await?; 36 | } 37 | KeyedEvent::Sentinel => { 38 | tx.send(KeyedEvent::Sentinel).await?; 39 | break; 40 | } 41 | } 42 | } 43 | Ok(()) 44 | }) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod array; 2 | pub mod window; 3 | pub mod blob; 4 | pub mod dataflow; 5 | // pub mod dataframe; 6 | pub mod dict; 7 | pub mod duration; 8 | pub mod format; 9 | pub mod file; 10 | // pub mod image; 11 | // pub mod iterator; 12 | pub mod keyed_stream; 13 | // pub mod matrix; 14 | pub mod option; 15 | pub mod path; 16 | pub mod reader; 17 | pub mod result; 18 | pub mod set; 19 | pub mod socket; 20 | pub mod stream; 21 | pub mod string; 22 | pub mod time; 23 | // pub mod url; 24 | pub mod vec; 25 | pub mod writer; 26 | pub mod unchecked_cell; 27 | pub mod cell; 28 | pub mod im_string; 29 | pub mod channel; 30 | pub mod range; 31 | pub mod url; 32 | pub mod bag; 33 | 34 | // #[cfg(feature = "model")] 35 | // pub mod model; 36 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/option.rs: -------------------------------------------------------------------------------- 1 | use macros::DeepClone; 2 | use serde::Deserialize; 3 | use serde::Serialize; 4 | 5 | use crate::traits::DeepClone; 6 | 7 | #[derive(Clone, DeepClone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Hash)] 8 | #[repr(C)] 9 | pub struct Option(pub std::option::Option); 10 | 11 | impl std::fmt::Display for Option { 12 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 13 | match &self.0 { 14 | Some(x) => write!(f, "Some({})", x), 15 | None => write!(f, "None"), 16 | } 17 | } 18 | } 19 | 20 | impl Option { 21 | #[inline(always)] 22 | pub fn some(x: T) -> Self { 23 | Self(Some(x)) 24 | } 25 | 26 | #[inline(always)] 27 | pub fn none() -> Self { 28 | Self(None) 29 | } 30 | 31 | pub fn is_some(self) -> bool { 32 | self.0.is_some() 33 | } 34 | 35 | pub fn is_none(self) -> bool { 36 | self.0.is_none() 37 | } 38 | 39 | pub fn unwrap(self) -> T { 40 | self.0.unwrap() 41 | } 42 | 43 | pub fn map U>(self, f: F) -> Option { 44 | self.0.map(f).into() 45 | } 46 | } 47 | 48 | impl From> for Option { 49 | fn from(x: std::option::Option) -> Self { 50 | Self(x) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/path.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use serde::Serialize; 3 | 4 | #[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Serialize, Deserialize)] 5 | #[repr(C)] 6 | pub struct Path(pub std::path::PathBuf); 7 | 8 | impl std::fmt::Display for Path { 9 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 10 | write!(f, "{}", self.0.display()) 11 | } 12 | } 13 | 14 | impl Path { 15 | pub fn new(path: impl AsRef) -> Self { 16 | Self(std::path::PathBuf::from(path.as_ref())) 17 | } 18 | 19 | pub fn join(&self, path: impl AsRef) -> Self { 20 | Self(self.0.join(path.as_ref())) 21 | } 22 | } 23 | 24 | impl<'a> From<&'a str> for Path { 25 | fn from(path: &'a str) -> Self { 26 | Self::new(path) 27 | } 28 | } 29 | 30 | impl From for Path { 31 | fn from(path: std::path::PathBuf) -> Self { 32 | Self(path) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/range.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use serde::Serialize; 3 | 4 | use crate::traits::DeepClone; 5 | 6 | #[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Serialize, Deserialize)] 7 | #[repr(C)] 8 | pub struct Range { 9 | pub start: Option, 10 | pub end: Option, 11 | } 12 | 13 | impl DeepClone for Range { 14 | fn deep_clone(&self) -> Self { 15 | Range { 16 | start: self.start.deep_clone(), 17 | end: self.end.deep_clone(), 18 | } 19 | } 20 | } 21 | 22 | impl std::fmt::Display for Range { 23 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 24 | match (&self.start, &self.end) { 25 | (Some(start), Some(end)) => write!(f, "{start}..{end}"), 26 | (Some(start), None) => write!(f, "{start}.."), 27 | (None, Some(end)) => write!(f, "..{end}"), 28 | (None, None) => write!(f, ".."), 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/reader.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use serde::Serialize; 3 | 4 | use crate::builtins::path::Path; 5 | use crate::builtins::socket::SocketAddr; 6 | use crate::traits::DeepClone; 7 | 8 | #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] 9 | #[repr(C)] 10 | pub enum Reader { 11 | Stdin, 12 | File { path: Path, watch: bool }, 13 | Http { addr: SocketAddr }, 14 | Tcp { addr: SocketAddr }, 15 | Kafka { addr: SocketAddr, topic: crate::prelude::String }, 16 | } 17 | 18 | impl DeepClone for Reader { 19 | fn deep_clone(&self) -> Self { 20 | self.clone() 21 | } 22 | } 23 | 24 | impl std::fmt::Display for Reader { 25 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 26 | match self { 27 | Reader::Stdin => write!(f, "Stdin"), 28 | Reader::File { path, watch } => write!(f, "File(path={path}, watch={watch})"), 29 | Reader::Http { addr } => write!(f, "Http(addr={})", addr), 30 | Reader::Tcp { addr } => write!(f, "Tcp(addr={addr})"), 31 | Reader::Kafka { addr, topic } => write!(f, "Kafka(addr={addr}, topic={topic})"), 32 | } 33 | } 34 | } 35 | 36 | impl Reader { 37 | pub fn stdin() -> Self { 38 | Self::Stdin 39 | } 40 | pub fn file(path: Path, watch: bool) -> Self { 41 | Self::File { path, watch } 42 | } 43 | pub fn http(addr: SocketAddr) -> Self { 44 | Self::Http { addr } 45 | } 46 | pub fn tcp(addr: SocketAddr) -> Self { 47 | Self::Tcp { addr } 48 | } 49 | pub fn kafka(addr: SocketAddr, topic: crate::prelude::String) -> Self { 50 | Self::Kafka { addr, topic } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/result.rs: -------------------------------------------------------------------------------- 1 | use macros::DeepClone; 2 | 3 | use serde::Deserialize; 4 | use serde::Serialize; 5 | 6 | use crate::builtins::string::String; 7 | use crate::traits::DeepClone; 8 | 9 | #[derive(Debug, DeepClone, Clone, Deserialize, Serialize, Eq, PartialEq, PartialOrd, Ord, Hash)] 10 | #[repr(C)] 11 | pub struct Result(pub std::result::Result); 12 | 13 | impl std::fmt::Display for Result { 14 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 15 | match &self.0 { 16 | std::result::Result::Ok(x) => write!(f, "Ok({})", x), 17 | std::result::Result::Err(x) => write!(f, "Error({})", x), 18 | } 19 | } 20 | } 21 | 22 | impl Result { 23 | pub fn ok(x: T) -> Self { 24 | Self(std::result::Result::Ok(x)) 25 | } 26 | 27 | pub fn error(x: String) -> Self { 28 | Self(std::result::Result::Err(x)) 29 | } 30 | 31 | pub fn is_ok(self) -> bool { 32 | matches!(self.0, std::result::Result::Ok(_)) 33 | } 34 | 35 | pub fn is_error(self) -> bool { 36 | matches!(self.0, std::result::Result::Err(_)) 37 | } 38 | 39 | pub fn unwrap_ok(self) -> T { 40 | match self.0 { 41 | std::result::Result::Ok(x) => x, 42 | std::result::Result::Err(_) => unreachable!(), 43 | } 44 | } 45 | 46 | pub fn unwrap_error(self) -> String { 47 | match self.0 { 48 | std::result::Result::Ok(_) => unreachable!(), 49 | std::result::Result::Err(x) => x, 50 | } 51 | } 52 | 53 | pub fn map(self, f: impl FnOnce(T) -> U) -> Result { 54 | Result(self.0.map(f)) 55 | } 56 | } 57 | 58 | impl From> for Result { 59 | fn from(x: std::result::Result) -> Self { 60 | Self(x.map_err(|x| String::from(x.to_string()))) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/socket.rs: -------------------------------------------------------------------------------- 1 | use std::net::ToSocketAddrs; 2 | 3 | use serde::Deserialize; 4 | use serde::Serialize; 5 | 6 | use crate::builtins::string::String; 7 | 8 | #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] 9 | #[repr(C)] 10 | pub struct SocketAddr(pub std::net::SocketAddr); 11 | 12 | impl std::fmt::Display for SocketAddr { 13 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 14 | write!(f, "{}", self.0) 15 | } 16 | } 17 | 18 | impl SocketAddr { 19 | pub fn new(ip: &'static str, port: u16) -> Self { 20 | Self(std::net::SocketAddr::new(ip.parse().unwrap(), port)) 21 | } 22 | pub fn parse(addr: String) -> Self { 23 | addr.as_ref() 24 | .to_socket_addrs() 25 | .unwrap() 26 | .next() 27 | .map(Self) 28 | .unwrap() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/assert.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | use crate::traits::Data; 3 | 4 | use super::Event; 5 | use super::Stream; 6 | 7 | impl Stream { 8 | pub fn assert(mut self, ctx: &mut Context, iter: I) 9 | where 10 | I: IntoIterator> + Send + 'static, 11 | ::IntoIter: Send + 'static, 12 | T: PartialEq, 13 | { 14 | ctx.sink(|| async move { 15 | let mut iter = iter.into_iter(); 16 | loop { 17 | let next = self.recv().await; 18 | assert_eq!(iter.next().as_ref(), Some(&next)); 19 | if let Event::Sentinel = next { 20 | break; 21 | } 22 | } 23 | Ok(()) 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/batch.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::duration::Duration; 2 | use crate::builtins::time::Time; 3 | use crate::runner::context::Context; 4 | use crate::traits::Data; 5 | 6 | use super::Event; 7 | use super::Stream; 8 | 9 | impl Stream { 10 | pub fn from_iter( 11 | ctx: &mut Context, 12 | iter: I, 13 | f: impl Fn(&T) -> Time + Send + 'static, 14 | watermark_frequency: usize, 15 | slack: Duration, 16 | ) -> Stream 17 | where 18 | I: IntoIterator + Send + 'static, 19 | ::IntoIter: Send + 'static, 20 | { 21 | ctx.operator(move |tx| async move { 22 | let mut latest_time = Time::zero(); 23 | let mut watermark = Time::zero(); 24 | for (i, v) in iter.into_iter().enumerate() { 25 | let time = f(&v); 26 | if time < watermark { 27 | continue; 28 | } 29 | if time > latest_time { 30 | latest_time = time; 31 | } 32 | if i % watermark_frequency == 0 { 33 | watermark = latest_time - slack; 34 | tx.send(Event::Watermark(watermark)).await?; 35 | } 36 | tx.send(Event::Data(time, v)).await?; 37 | } 38 | tx.send(Event::Sentinel).await 39 | }) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/collect.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | use crate::traits::Data; 3 | 4 | use super::Stream; 5 | 6 | impl Stream { 7 | pub fn collect_vec(mut self, ctx: &mut Context, out: tokio::sync::mpsc::Sender>) { 8 | ctx.sink(|| async move { 9 | let mut vec = Vec::new(); 10 | loop { 11 | match self.recv().await { 12 | super::Event::Data(_, v) => vec.push(v), 13 | super::Event::Watermark(_) => {} 14 | super::Event::Snapshot(_) => {} 15 | super::Event::Sentinel => { 16 | out.send(vec).await.unwrap(); 17 | break; 18 | } 19 | } 20 | } 21 | Ok(()) 22 | }) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/drain.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | use crate::traits::Data; 3 | 4 | use super::Event; 5 | use super::Stream; 6 | 7 | impl Stream { 8 | pub fn drain(mut self, ctx: &mut Context) { 9 | ctx.sink(|| async move { 10 | loop { 11 | if let Event::Sentinel = self.recv().await { 12 | break; 13 | } 14 | } 15 | Ok(()) 16 | }); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/dyn_source.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aqua-language/aqua/4e71a025d373e3284d17b4475af5dba33aba95ea/crates/runtime/src/builtins/stream/dyn_source.rs -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/filter.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | use crate::traits::Data; 3 | 4 | use super::Event; 5 | use super::Stream; 6 | 7 | impl Stream { 8 | pub fn filter( 9 | mut self, 10 | ctx: &mut Context, 11 | f: impl Fn(&T) -> bool + Send + 'static, 12 | ) -> Stream { 13 | ctx.operator(|tx| async move { 14 | loop { 15 | match self.recv().await { 16 | Event::Data(t, v) => { 17 | if f(&v) { 18 | tx.send(Event::Data(t, v)).await?; 19 | } 20 | } 21 | Event::Watermark(t) => { 22 | tx.send(Event::Watermark(t)).await?; 23 | } 24 | Event::Snapshot(i) => { 25 | tx.send(Event::Snapshot(i)).await?; 26 | } 27 | Event::Sentinel => { 28 | tx.send(Event::Sentinel).await?; 29 | break; 30 | } 31 | } 32 | } 33 | Ok(()) 34 | }) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/filter_map.rs: -------------------------------------------------------------------------------- 1 | // use crate::builtins::option::Option; 2 | use crate::runner::context::Context; 3 | use crate::traits::Data; 4 | 5 | use super::Event; 6 | use super::Stream; 7 | 8 | impl Stream { 9 | pub fn filter_map( 10 | mut self, 11 | ctx: &mut Context, 12 | f: impl Fn(T) -> Option + Send + 'static, 13 | ) -> Stream 14 | where 15 | O: Data, 16 | { 17 | ctx.operator(|tx| async move { 18 | loop { 19 | match self.recv().await { 20 | Event::Data(t, v) => { 21 | if let Some(v) = f(v) { 22 | tx.send(Event::Data(t, v)).await?; 23 | } 24 | } 25 | Event::Watermark(t) => { 26 | tx.send(Event::Watermark(t)).await?; 27 | } 28 | Event::Snapshot(i) => { 29 | tx.send(Event::Snapshot(i)).await?; 30 | } 31 | Event::Sentinel => { 32 | tx.send(Event::Sentinel).await?; 33 | break; 34 | } 35 | } 36 | } 37 | Ok(()) 38 | }) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/flat_map.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | use crate::traits::Data; 3 | 4 | use super::Event; 5 | use super::Stream; 6 | 7 | impl Stream 8 | where 9 | T: Data, 10 | { 11 | pub fn flat_map( 12 | mut self, 13 | ctx: &mut Context, 14 | f: impl Fn(T) -> I + Send + 'static, 15 | ) -> Stream 16 | where 17 | O: Data, 18 | I: IntoIterator, 19 | ::IntoIter: Send, 20 | { 21 | ctx.operator(|tx| async move { 22 | loop { 23 | match self.recv().await { 24 | Event::Data(t, v) => { 25 | for v in f(v).into_iter() { 26 | tx.send(Event::Data(t, v)).await?; 27 | } 28 | } 29 | Event::Watermark(t) => { 30 | tx.send(Event::Watermark(t)).await?; 31 | } 32 | Event::Snapshot(i) => { 33 | tx.send(Event::Snapshot(i)).await?; 34 | } 35 | Event::Sentinel => { 36 | tx.send(Event::Sentinel).await?; 37 | break; 38 | } 39 | } 40 | } 41 | Ok(()) 42 | }) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/fork.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | use crate::traits::Data; 3 | use crate::try_pair; 4 | 5 | use super::Event; 6 | use super::Stream; 7 | 8 | impl Stream { 9 | pub fn fork(mut self, ctx: &mut Context) -> (Self, Self) { 10 | ctx.co_operator(|tx1, tx2| async move { 11 | loop { 12 | match self.recv().await { 13 | Event::Data(t, v1) => { 14 | let v2 = v1.deep_clone(); 15 | try_pair!(tokio::join!( 16 | tx1.send(Event::Data(t, v2)), 17 | tx2.send(Event::Data(t, v1)) 18 | )); 19 | } 20 | Event::Watermark(t) => { 21 | try_pair!(tokio::join!( 22 | tx1.send(Event::Watermark(t)), 23 | tx2.send(Event::Watermark(t)) 24 | )); 25 | } 26 | Event::Snapshot(i) => { 27 | try_pair!(tokio::join!( 28 | tx1.send(Event::Snapshot(i)), 29 | tx2.send(Event::Snapshot(i)) 30 | )); 31 | } 32 | Event::Sentinel => { 33 | try_pair!(tokio::join!( 34 | tx1.send(Event::Sentinel), 35 | tx2.send(Event::Sentinel) 36 | )); 37 | break; 38 | } 39 | } 40 | } 41 | Ok(()) 42 | }) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/join.rs: -------------------------------------------------------------------------------- 1 | pub mod interval_join; 2 | pub mod tumbling_window_join; 3 | pub mod tumbling_window_join_distinct; 4 | pub mod interval_join_forward; 5 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/keyby.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::keyed_stream::KeyedEvent; 2 | use crate::builtins::keyed_stream::KeyedStream; 3 | use crate::runner::context::Context; 4 | use crate::traits::Data; 5 | 6 | use super::Event; 7 | use super::Stream; 8 | 9 | impl Stream { 10 | pub fn keyby( 11 | mut self, 12 | ctx: &mut Context, 13 | fun: impl Fn(&T) -> K + Send + 'static, 14 | ) -> KeyedStream { 15 | ctx.keyed_operator(|tx1| async move { 16 | loop { 17 | match self.recv().await { 18 | Event::Data(t, v) => { 19 | let k = fun(&v); 20 | tx1.send(KeyedEvent::Data(t, k, v)).await?; 21 | } 22 | Event::Watermark(t) => { 23 | tx1.send(KeyedEvent::Watermark(t)).await?; 24 | } 25 | Event::Snapshot(i) => { 26 | tx1.send(KeyedEvent::Snapshot(i)).await?; 27 | } 28 | Event::Sentinel => { 29 | tx1.send(KeyedEvent::Sentinel).await?; 30 | break; 31 | } 32 | } 33 | } 34 | Ok(()) 35 | }) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/map.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | use crate::traits::Data; 3 | 4 | use super::Event; 5 | use super::Stream; 6 | 7 | impl Stream { 8 | pub fn map(mut self, ctx: &mut Context, f: impl Fn(T) -> O + Send + 'static) -> Stream 9 | where 10 | O: Data, 11 | { 12 | ctx.operator(|tx| async move { 13 | loop { 14 | match self.recv().await { 15 | Event::Data(t, v) => tx.send(Event::Data(t, f(v))).await?, 16 | Event::Watermark(t) => tx.send(Event::Watermark(t)).await?, 17 | Event::Snapshot(i) => tx.send(Event::Snapshot(i)).await?, 18 | Event::Sentinel => { 19 | tx.send(Event::Sentinel).await?; 20 | break; 21 | } 22 | } 23 | } 24 | Ok(()) 25 | }) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/operator.rs: -------------------------------------------------------------------------------- 1 | pub trait Operator { 2 | type In; 3 | type Out; 4 | 5 | fn next(&mut self, input: Self::In) -> Option; 6 | } 7 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/scan.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | use crate::traits::Data; 3 | 4 | use super::Event; 5 | use super::Stream; 6 | 7 | impl Stream { 8 | pub fn scan( 9 | mut self, 10 | ctx: &mut Context, 11 | init: A, 12 | fun: impl Fn(T, A) -> A + Send + 'static, 13 | ) -> Stream { 14 | ctx.operator(|tx| async move { 15 | let mut acc = init; 16 | loop { 17 | match self.recv().await { 18 | Event::Data(t, v) => { 19 | acc = fun(v, acc); 20 | tx.send(Event::Data(t, acc.deep_clone())).await?; 21 | } 22 | Event::Watermark(t) => { 23 | tx.send(Event::Watermark(t)).await?; 24 | } 25 | Event::Snapshot(i) => { 26 | tx.send(Event::Snapshot(i)).await?; 27 | } 28 | Event::Sentinel => { 29 | tx.send(Event::Sentinel).await?; 30 | break; 31 | } 32 | } 33 | } 34 | Ok(()) 35 | }) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/take.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | use crate::traits::Data; 3 | 4 | use super::Event; 5 | use super::Stream; 6 | 7 | impl Stream { 8 | pub fn take(mut self, ctx: &mut Context, mut i: i32) -> Stream { 9 | ctx.operator(move |tx| async move { 10 | loop { 11 | if i == 0 { 12 | tx.send(Event::Sentinel).await?; 13 | break; 14 | } 15 | match self.recv().await { 16 | Event::Data(t, v) => { 17 | tx.send(Event::Data(t, v)).await?; 18 | i -= 1; 19 | } 20 | Event::Watermark(t) => tx.send(Event::Watermark(t)).await?, 21 | 22 | Event::Snapshot(i) => tx.send(Event::Snapshot(i)).await?, 23 | Event::Sentinel => { 24 | tx.send(Event::Sentinel).await?; 25 | break; 26 | } 27 | } 28 | } 29 | Ok(()) 30 | }) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/window.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::duration::Duration; 2 | use crate::builtins::time::Time; 3 | 4 | pub mod count_sliding_aligned_commutative_associative; 5 | pub mod count_sliding_holistic; 6 | pub mod count_sliding_invertible; 7 | pub mod count_tumbling_holistic; 8 | 9 | pub mod time_sliding_aligned_commutative_associative; 10 | pub mod time_sliding_aligned_holistic; 11 | pub mod time_sliding_commutative_invertible; 12 | pub mod time_sliding_invertible; 13 | pub mod time_tumbling_holistic; 14 | 15 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] 16 | pub struct WindowRange { 17 | pub t0: Time, 18 | pub t1: Time, 19 | } 20 | 21 | impl WindowRange { 22 | pub fn new(t0: Time, t1: Time) -> Self { 23 | Self { t0, t1 } 24 | } 25 | 26 | pub fn of(time: Time, duration: Duration, step: Duration) -> Self { 27 | let t0 = align(time, step); 28 | let t1 = t0 + duration; 29 | Self { t0, t1 } 30 | } 31 | } 32 | 33 | pub fn align(time: Time, step: Duration) -> Time { 34 | time.div_floor(step) * step 35 | } 36 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/window/count_sliding_holistic.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | use crate::builtins::stream::Event; 4 | use crate::builtins::stream::Stream; 5 | use crate::runner::context::Context; 6 | use crate::traits::Data; 7 | 8 | impl Stream { 9 | pub fn count_sliding_holistic_window( 10 | mut self, 11 | ctx: &mut Context, 12 | size: usize, 13 | step: usize, 14 | compute: impl Fn(Window) -> O + Send + 'static, 15 | ) -> Stream 16 | where 17 | O: Data, 18 | { 19 | ctx.operator(move |tx| async move { 20 | let mut s: VecDeque = VecDeque::with_capacity(size); 21 | loop { 22 | match self.recv().await { 23 | Event::Data(time, data) => { 24 | s.push_back(data); 25 | if s.len() == size { 26 | let result = compute(Window::new(&s)); 27 | for _ in 0..step { 28 | s.pop_front(); 29 | } 30 | tx.send(Event::Data(time, result.deep_clone())).await?; 31 | } 32 | } 33 | Event::Watermark(time) => { 34 | tx.send(Event::Watermark(time)).await?; 35 | } 36 | Event::Snapshot(i) => { 37 | tx.send(Event::Snapshot(i)).await?; 38 | } 39 | Event::Sentinel => { 40 | tx.send(Event::Sentinel).await?; 41 | break; 42 | } 43 | } 44 | } 45 | Ok(()) 46 | }) 47 | } 48 | } 49 | 50 | pub struct Window<'a, T> { 51 | data: &'a VecDeque, 52 | } 53 | 54 | impl<'a, T> Window<'a, T> { 55 | fn new(data: &'a VecDeque) -> Self { 56 | Self { data } 57 | } 58 | pub fn iter(&self) -> std::collections::vec_deque::Iter<'a, T> { 59 | self.data.iter() 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/window/count_sliding_invertible.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | use crate::builtins::stream::Event; 4 | use crate::builtins::stream::Stream; 5 | use crate::runner::context::Context; 6 | use crate::traits::Data; 7 | 8 | impl Stream { 9 | #[allow(clippy::too_many_arguments)] 10 | pub fn count_sliding_invertible_window( 11 | mut self, 12 | ctx: &mut Context, 13 | size: usize, 14 | step: usize, 15 | init: P, 16 | lift: impl Fn(&T) -> P + Send + 'static, 17 | combine: impl Fn(&P, &P) -> P + Send + 'static, 18 | lower: impl Fn(&P) -> O + Send + 'static, 19 | inverse: impl Fn(&P, &P) -> P + Send + 'static, 20 | ) -> Stream 21 | where 22 | P: Data, 23 | O: Data, 24 | { 25 | ctx.operator(move |tx| async move { 26 | let mut s: P = init; 27 | let mut vec: VecDeque

= VecDeque::new(); 28 | let mut n = 0; 29 | loop { 30 | match self.recv().await { 31 | Event::Data(time, data) => { 32 | let data = lift(&data); 33 | s = combine(&s, &data); 34 | vec.push_back(data); 35 | if n == size { 36 | tx.send(Event::Data(time, lower(&s).deep_clone())).await?; 37 | for _ in 0..step { 38 | let data = vec.pop_front().unwrap(); 39 | s = inverse(&s, &data); 40 | } 41 | n -= step; 42 | } else { 43 | n += 1; 44 | } 45 | } 46 | Event::Watermark(time) => { 47 | tx.send(Event::Watermark(time)).await?; 48 | } 49 | Event::Snapshot(i) => { 50 | tx.send(Event::Snapshot(i)).await?; 51 | } 52 | Event::Sentinel => { 53 | tx.send(Event::Sentinel).await?; 54 | break; 55 | } 56 | } 57 | } 58 | Ok(()) 59 | }) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/window/count_tumbling_holistic.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::stream::Event; 2 | use crate::builtins::stream::Stream; 3 | use crate::runner::context::Context; 4 | use crate::traits::Data; 5 | 6 | impl Stream { 7 | pub fn count_tumbling_holistic_window( 8 | mut self, 9 | ctx: &mut Context, 10 | size: usize, 11 | compute: impl Fn(Window) -> O + Send + 'static, 12 | ) -> Stream 13 | where 14 | O: Data, 15 | { 16 | ctx.operator(move |tx| async move { 17 | let mut agg: Vec = Vec::with_capacity(size); 18 | loop { 19 | match self.recv().await { 20 | Event::Data(time, data) => { 21 | agg.push(data); 22 | if agg.len() == size { 23 | let result = compute(Window::new(&agg)); 24 | tx.send(Event::Data(time, result.deep_clone())).await?; 25 | agg.clear(); 26 | } 27 | } 28 | Event::Watermark(time) => tx.send(Event::Watermark(time)).await?, 29 | Event::Snapshot(i) => tx.send(Event::Snapshot(i)).await?, 30 | Event::Sentinel => { 31 | tx.send(Event::Sentinel).await?; 32 | break; 33 | } 34 | } 35 | } 36 | Ok(()) 37 | }) 38 | } 39 | } 40 | 41 | pub struct Window<'a, T> { 42 | data: &'a Vec, 43 | } 44 | 45 | impl<'a, T> Window<'a, T> { 46 | fn new(data: &'a Vec) -> Self { 47 | Self { data } 48 | } 49 | pub fn iter(&self) -> std::slice::Iter<'a, T> { 50 | self.data.iter() 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/stream/window/time_tumbling_holistic.rs: -------------------------------------------------------------------------------- 1 | use crate::builtins::duration::Duration; 2 | use crate::builtins::stream::Event; 3 | use crate::builtins::stream::Stream; 4 | use crate::builtins::time::Time; 5 | use crate::runner::context::Context; 6 | use crate::traits::Data; 7 | use crate::BTreeMap; 8 | 9 | use super::align; 10 | use super::WindowRange; 11 | 12 | impl Stream { 13 | pub fn time_tumbling_holistic_window( 14 | mut self, 15 | ctx: &mut Context, 16 | duration: Duration, 17 | compute: impl Fn(&[T], WindowRange) -> O + Send + 'static, 18 | ) -> Stream 19 | where 20 | O: Data, 21 | { 22 | ctx.operator(move |tx| async move { 23 | let mut buffer: BTreeMap> = BTreeMap::new(); 24 | loop { 25 | match self.recv().await { 26 | Event::Data(time, data) => { 27 | let t0 = align(time, duration); 28 | buffer.entry(t0).or_default().push(data); 29 | } 30 | Event::Watermark(time) => { 31 | while let Some(entry) = buffer.first_entry() { 32 | let t0 = *entry.key(); 33 | let t1 = t0 + duration; 34 | let wr = WindowRange::new(t0, t1); 35 | if wr.t1 > time { 36 | break; 37 | } 38 | let vs = entry.remove(); 39 | let data = compute(&vs, wr); 40 | tx.send(Event::Data(wr.t1, data.deep_clone())).await?; 41 | } 42 | tx.send(Event::Watermark(time)).await?; 43 | } 44 | Event::Snapshot(i) => { 45 | tx.send(Event::Snapshot(i)).await?; 46 | } 47 | Event::Sentinel => { 48 | tx.send(Event::Sentinel).await?; 49 | break; 50 | } 51 | } 52 | } 53 | Ok(()) 54 | }) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/unchecked_cell.rs: -------------------------------------------------------------------------------- 1 | use macros::Send; 2 | use macros::Sync; 3 | use macros::Unpin; 4 | use serde::Deserialize; 5 | use serde::Serialize; 6 | 7 | use crate::traits::DeepClone; 8 | 9 | #[derive( 10 | Default, Send, Sync, Unpin, Serialize, Deserialize, Eq, PartialEq, Hash, Ord, PartialOrd, 11 | )] 12 | #[repr(C)] 13 | pub struct UncheckedCell(pub std::rc::Rc); 14 | 15 | impl DeepClone for UncheckedCell { 16 | fn deep_clone(&self) -> Self { 17 | Self(self.0.deep_clone()) 18 | } 19 | } 20 | 21 | impl Clone for UncheckedCell { 22 | fn clone(&self) -> Self { 23 | UncheckedCell(self.0.clone()) 24 | } 25 | } 26 | 27 | impl std::ops::Deref for UncheckedCell { 28 | type Target = T; 29 | fn deref(&self) -> &T { 30 | self.0.as_ref() 31 | } 32 | } 33 | 34 | impl std::fmt::Debug for UncheckedCell { 35 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 36 | self.0.as_ref().fmt(f) 37 | } 38 | } 39 | 40 | impl UncheckedCell { 41 | pub(crate) fn new(value: T) -> UncheckedCell { 42 | UncheckedCell(std::rc::Rc::new(value)) 43 | } 44 | 45 | // # Safety 46 | // 47 | // This method can only be used if the caller can guarantee that 48 | // the value is not read or borrowed during the lifetime of `&mut T`. 49 | // 50 | // Borrow checking guarantees that the value is not dropped while 51 | // the reference is still in use. 52 | #[allow(clippy::mut_from_ref)] 53 | pub(crate) unsafe fn as_mut_unchecked(&self) -> &mut T { 54 | let v = std::rc::Rc::into_raw(self.0.clone()) as *mut T; 55 | unsafe { 56 | std::rc::Rc::decrement_strong_count(v); 57 | &mut *v 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/url.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use serde::Serialize; 3 | 4 | use crate::builtins::im_string::String; 5 | use crate::builtins::result::Result; 6 | use crate::traits::DeepClone; 7 | 8 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] 9 | #[repr(C)] 10 | pub struct Url(pub url::Url); 11 | 12 | impl DeepClone for Url { 13 | fn deep_clone(&self) -> Self { 14 | Url(self.0.clone()) 15 | } 16 | } 17 | 18 | impl std::fmt::Display for Url { 19 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 20 | write!(f, "{}", self.0) 21 | } 22 | } 23 | 24 | impl Url { 25 | pub fn parse(s: String) -> Result { 26 | match url::Url::parse(s.0.as_str()) { 27 | Ok(v) => Result::ok(Url(v)), 28 | Err(s) => Result::error(s.to_string().into()), 29 | } 30 | } 31 | 32 | pub fn to_string(self) -> String { 33 | String::from(self.0.to_string()) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/window.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use serde::Serialize; 3 | 4 | use crate::builtins::duration::Duration; 5 | use crate::traits::DeepClone; 6 | 7 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] 8 | #[repr(C)] 9 | pub enum Window { 10 | Tumbling { length: Duration }, 11 | Sliding { duration: Duration, step: Duration }, 12 | Session { gap: Duration }, 13 | Counting { length: i32 }, 14 | Moving { length: i32, step: i32 }, 15 | } 16 | 17 | impl DeepClone for Window { 18 | fn deep_clone(&self) -> Self { 19 | self.clone() 20 | } 21 | } 22 | 23 | impl std::fmt::Display for Window { 24 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 25 | match self { 26 | Window::Tumbling { length } => write!(f, "Tumbling({})", length), 27 | Window::Sliding { duration, step } => write!(f, "Sliding({}, {})", duration, step), 28 | Window::Session { gap } => write!(f, "Session({})", gap), 29 | Window::Counting { length } => write!(f, "Counting({})", length), 30 | Window::Moving { length, step } => write!(f, "Moving({}, {})", length, step), 31 | } 32 | } 33 | } 34 | 35 | impl Window { 36 | pub fn tumbling(length: Duration) -> Self { 37 | Self::Tumbling { length } 38 | } 39 | 40 | pub fn sliding(length: Duration, step: Duration) -> Self { 41 | Self::Sliding { 42 | duration: length, 43 | step, 44 | } 45 | } 46 | 47 | pub fn session(gap: Duration) -> Self { 48 | Self::Session { gap } 49 | } 50 | 51 | pub fn counting(length: i32) -> Self { 52 | Self::Counting { length } 53 | } 54 | 55 | pub fn moving(length: i32, step: i32) -> Self { 56 | Self::Moving { length, step } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /crates/runtime/src/builtins/writer.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use serde::Serialize; 3 | 4 | use crate::builtins::path::Path; 5 | use crate::builtins::socket::SocketAddr; 6 | use crate::builtins::string::String; 7 | use crate::traits::DeepClone; 8 | 9 | #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] 10 | #[repr(C)] 11 | pub enum Writer { 12 | Stdout, 13 | File { path: Path }, 14 | // Http { url: Url }, 15 | Tcp { addr: SocketAddr }, 16 | Kafka { addr: SocketAddr, topic: String }, 17 | } 18 | 19 | impl DeepClone for Writer { 20 | fn deep_clone(&self) -> Self { 21 | self.clone() 22 | } 23 | } 24 | 25 | impl std::fmt::Display for Writer { 26 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 27 | match self { 28 | Writer::Stdout => write!(f, "stdout()"), 29 | Writer::File { path } => write!(f, "file(path={path})"), 30 | // Writer::Http { url } => write!(f, "http(url={url})"), 31 | Writer::Tcp { addr } => write!(f, "tcp(addr={addr})"), 32 | Writer::Kafka { addr, topic } => write!(f, "kafka(addr={addr}, topic={topic})"), 33 | } 34 | } 35 | } 36 | 37 | impl Writer { 38 | pub fn stdout() -> Self { 39 | Self::Stdout 40 | } 41 | pub fn file(path: Path) -> Self { 42 | Self::File { path } 43 | } 44 | // pub fn http(url: Url) -> Self { 45 | // Self::Http { url } 46 | // } 47 | pub fn tcp(addr: SocketAddr) -> Self { 48 | Self::Tcp { addr } 49 | } 50 | pub fn kafka(addr: SocketAddr, topic: String) -> Self { 51 | Self::Kafka { addr, topic } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /crates/runtime/src/formats/json/de.rs: -------------------------------------------------------------------------------- 1 | use serde_json::Deserializer; 2 | 3 | use crate::formats::Decode; 4 | 5 | #[derive(Default)] 6 | pub struct Reader {} 7 | 8 | impl Reader { 9 | pub fn new() -> Self { 10 | Self::default() 11 | } 12 | } 13 | 14 | impl Decode for Reader { 15 | type Error = serde_json::Error; 16 | 17 | fn decode<'de, T>(&mut self, input: &'de [u8]) -> Result 18 | where 19 | T: serde::Deserialize<'de>, 20 | { 21 | let mut deserializer = Deserializer::from_slice(input); 22 | let value = T::deserialize(&mut deserializer)?; 23 | deserializer.end()?; 24 | Ok(value) 25 | } 26 | 27 | fn decode_dyn<'de, T, Tag: Clone>( 28 | &mut self, 29 | input: &'de [u8], 30 | tag: Tag, 31 | ) -> Result::Error> 32 | where 33 | Tag: serde::de::DeserializeSeed<'de, Value = T>, 34 | { 35 | let mut deserializer = Deserializer::from_slice(input); 36 | let value = serde::de::DeserializeSeed::deserialize(tag, &mut deserializer)?; 37 | deserializer.end()?; 38 | Ok(value) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /crates/runtime/src/formats/json/ser.rs: -------------------------------------------------------------------------------- 1 | use crate::formats::Encode; 2 | 3 | #[derive(Default)] 4 | pub struct Writer {} 5 | 6 | impl Writer { 7 | pub fn new() -> Self { 8 | Self {} 9 | } 10 | } 11 | 12 | impl Encode for Writer { 13 | type Error = serde_json::Error; 14 | 15 | fn encode(&mut self, input: &T, output: &mut Vec) -> Result 16 | where 17 | T: serde::Serialize + ?Sized, 18 | { 19 | let mut serializer = serde_json::Serializer::new(output); 20 | input.serialize(&mut serializer)?; 21 | Ok(1) 22 | } 23 | 24 | fn content_type(&self) -> &'static str { 25 | "application/json" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /crates/runtime/src/formats/mod.rs: -------------------------------------------------------------------------------- 1 | use serde::de::DeserializeSeed; 2 | use serde::Deserialize; 3 | use serde::Serialize; 4 | 5 | pub mod csv { 6 | pub mod de; 7 | pub mod ser; 8 | } 9 | 10 | pub mod json { 11 | pub mod de; 12 | pub mod ser; 13 | } 14 | 15 | pub trait Decode { 16 | type Error: std::error::Error + Send; 17 | fn decode<'de, T>(&mut self, input: &'de [u8]) -> Result 18 | where 19 | T: Deserialize<'de>; 20 | 21 | fn decode_dyn<'de, T, Tag>( 22 | &mut self, 23 | input: &'de [u8], 24 | tag: Tag, 25 | ) -> Result::Error> 26 | where 27 | Tag: Clone + DeserializeSeed<'de, Value = T>; 28 | } 29 | 30 | pub trait Encode { 31 | type Error: std::error::Error + Send; 32 | fn encode(&mut self, input: &T, output: &mut Vec) -> Result 33 | where 34 | T: Serialize; 35 | fn content_type(&self) -> &'static str; 36 | } 37 | -------------------------------------------------------------------------------- /crates/runtime/src/logging/mod.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | use std::str::FromStr; 3 | 4 | use tracing_subscriber::prelude::*; 5 | 6 | #[cfg(debug_assertions)] 7 | pub const FILTER: &str = "info,librdkafka=off,rdkafka::client=off"; 8 | 9 | #[cfg(not(debug_assertions))] 10 | pub const FILTER: &str = "warn,librdkafka=off,rdkafka::client=off"; 11 | 12 | pub fn init(path: impl Into) { 13 | let file = std::fs::File::create(path.into()).expect("failed to create log file"); 14 | let fmt = tracing_subscriber::fmt::layer() 15 | .with_file(false) 16 | .with_line_number(false) 17 | .with_ansi(false) 18 | .compact() 19 | .with_writer(file) 20 | .with_filter(tracing_subscriber::filter::EnvFilter::from_str(FILTER).unwrap()); 21 | tracing_subscriber::registry().with(fmt).init(); 22 | } 23 | -------------------------------------------------------------------------------- /crates/runtime/src/runner/current_thread.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | 3 | pub struct CurrentThreadRunner {} 4 | 5 | impl CurrentThreadRunner { 6 | pub fn run(f: impl FnOnce(&mut Context)) { 7 | let future = async { 8 | let ctx = Context::run_local(f).await; 9 | ctx.await_termination().await; 10 | }; 11 | tokio::runtime::Builder::new_current_thread() 12 | .enable_all() 13 | .build() 14 | .expect("Failed to build runtime") 15 | .block_on(future) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /crates/runtime/src/runner/data_parallel.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | 3 | pub struct DataParallelRunner { 4 | txs: Vec>, 5 | threads: Vec>, 6 | } 7 | 8 | impl DataParallelRunner { 9 | pub fn new( 10 | args: [T; N], 11 | f: impl Fn(T, &mut Context) + Clone + Send + 'static, 12 | ) -> Self { 13 | let mut threads = Vec::with_capacity(args.len()); 14 | let mut txs = Vec::with_capacity(args.len()); 15 | for arg in args { 16 | let f = f.clone(); 17 | let (runner_tx, runner_rx) = std::sync::mpsc::channel(); 18 | txs.push(runner_tx); 19 | threads.push(std::thread::spawn(move || { 20 | tokio::runtime::Builder::new_current_thread() 21 | .enable_all() 22 | .build() 23 | .expect("Failed to build runtime") 24 | .block_on(async { 25 | let ctx = Context::run_local(|ctx| f(arg, ctx)).await; 26 | runner_rx.recv().unwrap(); 27 | ctx.await_termination().await; 28 | }); 29 | })); 30 | } 31 | Self { txs, threads } 32 | } 33 | 34 | pub fn run(mut self) { 35 | for tx in self.txs.iter() { 36 | tx.send(()).unwrap(); 37 | } 38 | for thread in self.threads.drain(..) { 39 | thread.join().expect("Failed to join thread"); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /crates/runtime/src/runner/env.rs: -------------------------------------------------------------------------------- 1 | pub struct Context { 2 | join_set: tokio::task::JoinSet<()>, 3 | start: tokio::sync::broadcast::Receiver<()>, 4 | } 5 | -------------------------------------------------------------------------------- /crates/runtime/src/runner/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod data_parallel; 2 | pub mod task_parallel; 3 | pub mod context; 4 | 5 | // #[cfg(feature = "thread-pinning")] 6 | // pub mod pinned_data_parallel; 7 | 8 | pub mod current_thread; 9 | -------------------------------------------------------------------------------- /crates/runtime/src/runner/single_thread.rs: -------------------------------------------------------------------------------- 1 | use crate::context::Context; 2 | 3 | pub struct CurrentThreadRunner {} 4 | 5 | impl CurrentThreadRunner { 6 | pub fn run(f: impl Fn(&mut Context)) { 7 | tokio::runtime::Builder::new_current_thread() 8 | .enable_all() 9 | .build() 10 | .expect("Failed to build runtime") 11 | .block_on(async { 12 | let (tx, rx) = tokio::sync::broadcast::channel(1); 13 | let mut ctx = Context::new(rx); 14 | let local_set = tokio::task::LocalSet::new(); 15 | local_set.run_until(async { f(&mut ctx) }).await; 16 | tx.send(()).unwrap(); 17 | while let Some(_) = ctx.join_set.join_next().await {} 18 | local_set.await; 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /crates/runtime/src/runner/task_parallel.rs: -------------------------------------------------------------------------------- 1 | use crate::runner::context::Context; 2 | 3 | pub struct TaskParallelRunner { 4 | tx: std::sync::mpsc::SyncSender<()>, 5 | } 6 | 7 | impl TaskParallelRunner { 8 | #[cfg(feature = "multi-thread")] 9 | pub fn new(f: impl FnOnce(&mut Context) + Send + 'static) -> Self { 10 | let (tx, rx) = std::sync::mpsc::sync_channel::<()>(1); 11 | tokio::runtime::Builder::new_multi_thread() 12 | .enable_all() 13 | .build() 14 | .expect("Failed to build runtime") 15 | .block_on(async { 16 | let ctx = Context::run(f); 17 | rx.recv().unwrap(); 18 | ctx.await_termination().await; 19 | }); 20 | Self { tx } 21 | } 22 | 23 | #[cfg(not(feature = "multi-thread"))] 24 | pub fn new(f: impl FnOnce(&mut Context) + Send + 'static) -> Self { 25 | let (tx, rx) = std::sync::mpsc::sync_channel::<()>(1); 26 | tokio::runtime::Builder::new_current_thread() 27 | .enable_all() 28 | .build() 29 | .expect("Failed to build runtime") 30 | .block_on(async { 31 | let ctx = Context::run(f); 32 | rx.recv().unwrap(); 33 | ctx.await_termination().await; 34 | }); 35 | Self { tx } 36 | } 37 | 38 | pub fn run(self) { 39 | self.tx.send(()).unwrap(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /crates/runtime/tests/basic.rs: -------------------------------------------------------------------------------- 1 | use runtime::builtins::time::Time; 2 | use runtime::builtins::writer::Writer; 3 | use runtime::prelude::data; 4 | use runtime::prelude::CurrentThreadRunner; 5 | use runtime::prelude::DeepClone; 6 | use runtime::prelude::Duration; 7 | use runtime::prelude::Format; 8 | use runtime::prelude::New; 9 | use runtime::prelude::Path; 10 | use runtime::prelude::Reader; 11 | use runtime::prelude::Send; 12 | use runtime::prelude::Stream; 13 | use runtime::prelude::Timestamp; 14 | 15 | #[data] 16 | struct Data { 17 | x: i32, 18 | y: i32, 19 | z: i32, 20 | } 21 | 22 | const INPUT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/data.csv"); 23 | const OUTPUT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/output.csv"); 24 | 25 | #[test] 26 | fn test() { 27 | CurrentThreadRunner::run(|ctx| { 28 | let s0 = Stream::::source( 29 | ctx, 30 | Reader::file(Path::new(INPUT), false), 31 | Format::csv(','), 32 | |_: Data, t: Time| t, 33 | Duration::from_seconds(1), 34 | Duration::from_seconds(1), 35 | ); 36 | let s1 = Stream::::filter(s0, ctx, |data: &Data| data.y > 5); 37 | let _ = Stream::::sink(s1, ctx, Writer::file(Path::new(OUTPUT)), Format::csv(',')); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /crates/runtime/tests/data.csv: -------------------------------------------------------------------------------- 1 | 1,2,3 2 | 4,5,6 3 | 7,8,9 4 | -------------------------------------------------------------------------------- /crates/runtime/tests/output.csv: -------------------------------------------------------------------------------- 1 | 7,8,9 2 | -------------------------------------------------------------------------------- /crates/runtime/tests/window.rs: -------------------------------------------------------------------------------- 1 | use runtime::prelude::stream::Event; 2 | use runtime::prelude::*; 3 | 4 | #[data] 5 | struct Data { 6 | value: T, 7 | time: Time, 8 | } 9 | 10 | #[ignore] 11 | #[test] 12 | fn test_tumbling_holistic0() { 13 | CurrentThreadRunner::run(|ctx| { 14 | let events = (0..1000).map(|i| Data::new(i, Time::zero())); 15 | Stream::from_iter(ctx, events, |e| e.time, 100, Duration::zero()) 16 | .time_tumbling_holistic_window(ctx, Duration::from_seconds(100), |data, _| { 17 | let sum = data.iter().map(|d| d.value).sum::(); 18 | let min = data.iter().map(|d| d.value).min().unwrap(); 19 | let max = data.iter().map(|d| d.value).max().unwrap(); 20 | (sum, min, max) 21 | }) 22 | .assert( 23 | ctx, 24 | [ 25 | Event::Watermark(Time::zero()), 26 | Event::Data(Time::zero(), (0, 0, 0)), 27 | Event::Data(Time::zero(), (0, 0, 0)), 28 | Event::Data(Time::zero(), (0, 0, 0)), 29 | ], 30 | ); 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /examples/fail.aqua: -------------------------------------------------------------------------------- 1 | def f(): i32 = 1; 2 | 3 | Display[Vec[i32]]::toString(Vec[i32]::new()); 4 | -------------------------------------------------------------------------------- /examples/from-where-limit-into.aqua: -------------------------------------------------------------------------------- 1 | struct Data(time:Time, key:String, value:i32); 2 | 3 | var i:Instance = 4 | from x in Stream[Data]::source( 5 | Reader::file(Path::new("data.csv"), false), 6 | Encoding::csv(','), 7 | (x, t) => x.time, 0s, 1s 8 | ) 9 | where x.value < 50 10 | limit 100 11 | into sink( 12 | Writer::stdout(), 13 | Encoding::csv(',') 14 | ).run(Backend::native()); 15 | -------------------------------------------------------------------------------- /examples/generate-data.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import random 3 | from datetime import datetime, timedelta 4 | 5 | num_points = 1_000_000 6 | 7 | output_file = "data.csv" 8 | 9 | start_time = datetime.now() 10 | 11 | 12 | def random_noise(): 13 | return timedelta(seconds=random.randint(-15, 15)) 14 | 15 | 16 | # Generate data points and write to CSV 17 | with open(output_file, mode='w', newline='') as file: 18 | writer = csv.writer(file) 19 | 20 | for i in range(num_points): 21 | timestamp = start_time + timedelta(minutes=i) + random_noise() 22 | key = f"key_{random.randint(0, 99)}" 23 | value = random.randint(0, 999) 24 | 25 | writer.writerow([timestamp.isoformat(), key, value]) 26 | 27 | print(f"Data written to {output_file}") 28 | -------------------------------------------------------------------------------- /examples/http-server.aqua: -------------------------------------------------------------------------------- 1 | struct Data(time:Time, key:String, value:i32); 2 | 3 | from x in source[Data](http_server(8080), csv(','), (x, t) => x.time, 0s, 1s) 4 | where x.value < 50 5 | limit 100 6 | into sink(stdout_writer(), csv(',')).run(rust()); 7 | 8 | 9 | --------------------------------------------------------------------------------