diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8d52091b..2313ea0a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -57,18 +57,6 @@ jobs: - name: Test slow_odgi run: make -C slow_odgi test SMALL=1 - test-parser: - name: test DSL parser - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1 - - run: cargo install runt - - run: cargo build - working-directory: ./pollen - - run: runt -v - working-directory: ./pollen - test-flatgfa: name: test FlatGFA runs-on: ubuntu-latest diff --git a/pollen/Cargo.lock b/pollen/Cargo.lock deleted file mode 100644 index fdb949ff..00000000 --- a/pollen/Cargo.lock +++ /dev/null @@ -1,212 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cpufeatures" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" -dependencies = [ - "libc", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "pest" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1acb4a4365a13f749a93f1a094a7805e5cfa0955373a9de860d962eaa3a5fe5a" -dependencies = [ - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "666d00490d4ac815001da55838c500eafb0320019bbaa44444137c48b443a853" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ca01446f50dbda87c1786af8770d535423fa8a53aec03b8f4e3d7eb10e0929" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pest_meta" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56af0a30af74d0445c0bf6d9d051c979b516a1a5af790d251daee76005420a48" -dependencies = [ - "once_cell", - "pest", - "sha2", -] - -[[package]] -name = "pollen" -version = "0.1.0" -dependencies = [ - "lazy_static", - "pest", - "pest_derive", -] - -[[package]] -name = "proc-macro2" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "sha2" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "syn" -version = "2.0.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - -[[package]] -name = "unicode-ident" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" diff --git a/pollen/Cargo.toml b/pollen/Cargo.toml deleted file mode 100644 index edbb2161..00000000 --- a/pollen/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "pollen" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -lazy_static = "1.1" -pest = "2.5.6" -pest_derive = "2.0" \ No newline at end of file diff --git a/pollen/pollen-docs.md b/pollen/pollen-docs.md deleted file mode 100644 index d9c2fd71..00000000 --- a/pollen/pollen-docs.md +++ /dev/null @@ -1,220 +0,0 @@ -===== Pollen Features ===== - -1.1 Basics - -Variable initialization: - -``` -t v1; -v1 = e1; -``` -or - -``` -type v2 = e2; -``` - -For now, to keep things simple, variables can only be declared once within the -same scope. This means that -``` -int v = 1; -bool v = true; -``` -is semantically invalid. - -2. Types -2.1 Basic Types - -`T = int | bool | char` - - -2.2 Abstract Data Types - -Array types are expressed as `T[]`, and can be nested up to a depth of 4. -(We could extend the functionality to allow for deeper nesting, but for now -this should be more than fine.) - -Strings are essentially lists of characters. - -Record types: `R = {f1: t1, f2 : t2, ..., fn : tn}` if `t1 ... t2 in t` - -Without considering pangenomic types, our type system would look something -like: - -`t = T | T[] | String` - - -2.3 Pangenomic types - -`Segment | Step | Path | Edge | Handle | base | Strand` - -Where `Segment`, `Step`, `Path`, `Edge`, and `Handle` are all named record types. - -So, - -`T = int | bool | char | base` - -`P = Segment | Step | Path | Edge | Handle | Strand` - -`t = T | T[] | String | P | List | List

| R` - - -3. If/else - -If statement: -``` -if b { - ... -} -``` - -If/else statement: -``` -if b { - ... -} else { - ... -} -``` - -If/elif: -``` -if b1 { - ... -} elif b2 { - ... -} [else {...}] // Optional catch-all else block -``` - -4. Loops -4.1 While Loops - -``` -while i < len { - ... -} -``` - -This is in a similar style to the for-each loop syntax given below, which I find -more intuitive than the Java/C++ style syntax. - - -4.2 For Loops - -For-each loops: -``` -for var in Iterable { - ... -} -``` - -I think that allowing Java/C++ style for loops, which look like -` for(int i = 0; i < length, i = i + 1) { ... }`, would be confusing given the -pythonic syntax of for-each loops. They may also not come up that often, since -most of our iteration will probably be on existing graph datastructures, and -the same functionality can be accomplished with while loops where necessary. - - -5. Data Types -5.1 Integers -Represents values between −2^63 to 2^63 − 1. Operations: +, -, *, /, % -(where / is integer division, like in python 2), <, >, <=, =>, ==, != - -In order of precedence: (*, /, %), (+, -) - (<, >, <=, =>), (==, !=) // doesn't matter - -At some point, it would be nice to support the unary operators `-` and `++`. - - -5.2 Booleans -Since our typing system resembles Java or C++, to avoid confusion, perhaps -our boolean literals should as well: - -``` -bool b1 = true; -bool b2 = false; -``` - -Boolean binary operators: ==, !=, &&, || - -Boolean unary operator: ! - -Precedence: !, (==, !=), (&&, ||) - -a == b && c => (a == b) && c vs. a == (b && c), which are clearly not equivalent -(the former can only be true if c is true). - - -5.3 Tuples - -Initialization: -``` -t = (p1, p2) -``` - -Access: -``` -t.0 -t.1 -``` - -(Notes on hardware implementation: could (a) use registers, (b) use vectors -plus splicing whenever we retrieve an element from a list, if bitwidths vary; -could also use splicers with registers to reduce the total # of registers via -register sharing) - - -5.4 Records - -Initialization: -``` -r = {f1 = e2; f2 = e2; ...; fn = en} -``` - -Initialization from another record: - -Option 1: -``` -r2 = {r with f1 = e1'; ...; fn = en'} -``` - -Option 2: -``` -r2 = {f1 = e1'; ..r} -``` - -We don't need both initialization types, although supporting both of these -syntaxes seems perfectly viable; I lean towards the first option because it -looks more like regular english and is perhaps more intuitive to people who -aren't experts in CS, but both seem fine. - - -5.3 Arrays - -Declarations: - -``` -int[] arr = Array[n](); // An array of length n -int[] arr = Array[n](0); // Initialize the array with 0s -int[] arr = [0, 1, 2, 4]; // Define each element of the array -(node*int)[] depths = Array[node_count()](); // An array of tuples mapping nodes to integers -``` - -Access/Assignment: -``` arr[i] = e ``` - -Length: -```arr.length()``` - -Or, if we're feeling spicy, we could use ```arr.size()``` so that users only -have to remember one keyword (vs. different keywords for arrays and sets/dicts/lists) - -6. Functions - -Function declaration: - -``` t fun(t1 input1, t2 input2, ..., tn inputn) { - ... - [return e1, ..., en] // Optional return statement -} -``` \ No newline at end of file diff --git a/pollen/runt.toml b/pollen/runt.toml deleted file mode 100644 index c43e5aae..00000000 --- a/pollen/runt.toml +++ /dev/null @@ -1,10 +0,0 @@ -ver = "0.4.1" - -# Check that all pollen programs parse correctly -[[tests]] -name = "parser tests" -paths = [ - "tests/*.pollen", -] -cmd = "./target/debug/pollen {}" -expect_dir = "tests/parse-out/" \ No newline at end of file diff --git a/pollen/src/ast/mod.rs b/pollen/src/ast/mod.rs deleted file mode 100644 index 4139cd7d..00000000 --- a/pollen/src/ast/mod.rs +++ /dev/null @@ -1,178 +0,0 @@ -#[derive(Debug)] -#[derive(Clone)] -pub struct Id(pub String); - -#[derive(Debug)] -pub enum Import { - Import { file: String }, - ImportAs { file: String, name: Id }, - ImportFrom { file: String, funcs: Vec<(Id, Option)> } -} - -#[derive(Debug)] -#[derive(Clone)] -pub enum Typ { - Int, - Bool, - Char, - Path, - Node, - Step, - Edge, - Base, - String, - Strand, - Tuple(Box, Box), - Set(Box) -} - -#[derive(Debug)] -#[derive(Clone)] -pub enum BinOp { - Add, - Sub, - Mult, - Div, - Mod, - Exp, - Lt, - Gt, - Leq, - Geq, - Eq, - Neq, - And, - Or -} - -#[derive(Debug)] -#[derive(Clone)] -pub enum UOp { - Not -} - -#[derive(Debug)] -#[derive(Clone)] -pub struct RecordField{ - pub field: Id, - pub val: Expr -} - -#[derive(Debug)] -#[derive(Clone)] -pub enum Expr { - Integer(i32), - Bool(bool), - Char(char), - StringLit(String), - Var(Id), - BinOpExpr { - lhs: Box, - op: BinOp, - rhs: Box - }, - UOpExpr { - op: UOp, - expr: Box - }, - ArrayAccess { - expr: Box, - idx: Box - }, - Record { - typ: Typ, - fields: Vec - }, - RecordUpdate { - parent: Box, - fields: Vec - }, - Tuple { - lhs : Box, - rhs : Box - }, - FieldAccess { - object: Box, - field: Box - }, - FuncCall { - name: Id, - args: Vec - }, - MethodCall { - object: Box, - method: Id, - args: Vec - }, - ObjInitialization{ - typ: Typ - } -} - -#[derive(Debug)] -#[derive(Clone)] -pub enum Stmt { - Decl { - typ: Typ, - id: Id, - expr: Option, - }, - GraphDecl { - id: Id - }, - ParsetDecl { - id: Id, - typ: Typ, - graph_id: Option - }, - Assign { - id: Id, - expr: Expr - }, - Block { - stmts: Vec> - }, - If { - guard: Expr, - if_block: Box, // Block stmt - elif_block: Option>, // If stmt - else_block: Option> // Block stmt - }, - While { - guard: Expr, - body: Box - }, - For { - id: Id, - iterator: Expr, - body: Box - }, - FuncCallStmt { - name: Id, - args: Vec - }, - MethodCallStmt { - object: Expr, - method: Id, - args: Vec - }, - EmitTo { - expr: Expr, - set_id: Id - } -} - -#[derive(Debug)] -pub struct FuncDef { - pub name: Id, - pub args: Vec<(Id, Typ)>, - pub ret_typ: Option, - pub stmts: Vec, - pub ret: Option -} - -#[derive(Debug)] -pub struct Prog { - pub imports: Vec, - pub func_defs: Vec, -} \ No newline at end of file diff --git a/pollen/src/main.rs b/pollen/src/main.rs deleted file mode 100755 index 923ad3a0..00000000 --- a/pollen/src/main.rs +++ /dev/null @@ -1,830 +0,0 @@ -use std::env; -use std::fs::File; -use std::io::prelude::*; -use std::path::Path; - -#[macro_use] -extern crate lazy_static; -extern crate pest; -#[macro_use] -extern crate pest_derive; - -use pest::iterators::{ Pair, Pairs }; -use pest::pratt_parser::{Assoc::*, Op, PrattParser}; -use pest::Parser; - -pub mod ast; -use crate::ast::*; - -#[derive(Parser)] -#[grammar = "pollen.pest"] -pub struct PollenParser; - -lazy_static! { - static ref PRATT_PARSER: PrattParser = { - - // Precedence is defined lowest to highest - PrattParser::new() - .op(Op::postfix(Rule::array_access)) - .op(Op::infix(Rule::or, Left)) - .op(Op::infix(Rule::and, Left)) - .op(Op::infix(Rule::eq, Left) | Op::infix(Rule::neq, Left)) - .op(Op::infix(Rule::gt, Left) | Op::infix(Rule::lt, Left) - | Op::infix(Rule::geq, Left) | Op::infix(Rule::leq, Left)) - // Addition and subtract have equal precedence - .op(Op::infix(Rule::add, Left) | Op::infix(Rule::sub, Left)) - .op(Op::infix(Rule::mult, Left) | Op::infix(Rule::div, Left) - | Op::infix(Rule::modulo, Left)) - .op(Op::prefix(Rule::not)) - .op(Op::infix(Rule::field_access, Left)) - }; -} - -pub fn parse_prog(mut prog: Pairs) -> Prog { - let Some(imports) = prog.next() else { unreachable!("Prog has no pairs") }; - let Some(func_defs) = prog.next() else { unreachable!("Prog has only one pair") }; - Prog{ - imports: parse_imports(imports), - func_defs: parse_func_defs(func_defs) - } -} - -pub fn parse_imports(imports: Pair) -> Vec { - let mut import_stmts = Vec::new(); - match imports.as_rule() { - Rule::imports => { - let inner = imports.into_inner(); - for import in inner { import_stmts.push(parse_import(import)) } - }, - rule => { unreachable!("Imports expected, found {:?}", rule)} - } - import_stmts -} - -pub fn parse_import(import: Pair) -> Import { - - fn parse_func_as_id(func_as_id: Pair) -> (Id, Option) { - match func_as_id.as_rule() { - Rule::func_as_id => { - let mut inner = func_as_id.into_inner(); - let func_name = { - let Some(pair) = inner.next() else { unreachable!("Function id expected")}; - parse_id(pair) - }; - let import_name = { - if let Some(pair) = inner.next() { - Some(parse_id(pair)) - } else { - None - } - }; - (func_name, import_name) - }, - rule => { unreachable!("Expected func_as_id, found {:?}", rule)} - } - } - - match import.as_rule() { - Rule::import_as => { - let mut inner = import.into_inner(); - let filename = { - let Some(pair) = inner.next() else { unreachable!("Import statement has no filename")}; - pair.as_str().to_string() - }; - if let Some(pair) = inner.next() { - // This statement specifies a new filename - let identifier = parse_id(pair); - Import::ImportAs { - file: filename, - name: identifier - } - } - else { - Import::Import { - file: filename - } - } - }, - Rule::import_from => { - let mut inner = import.into_inner(); - let filename = { - let Some(pair) = inner.next() else { unreachable!("Import statement has no filename")}; - pair.as_str().to_string() - }; - let mut func_as_ids = Vec::new(); - while let Some(pair) = inner.next() { - let func_as_id = parse_func_as_id(pair); - func_as_ids.push(func_as_id); - } - - Import::ImportFrom { - file: filename, - funcs: func_as_ids - } - }, - rule => { unreachable!("{:?} is not recognized as an import stmt", rule) - } - } -} - -pub fn parse_func_defs(func_defs: Pair) -> Vec { - let mut func_defs_vec = Vec::new(); - let mut inner = func_defs.into_inner(); - while let Some(func_def) = inner.next() { - func_defs_vec.push(parse_func_def(func_def)) - }; - func_defs_vec -} - -fn parse_func_def(func_def: Pair) -> FuncDef { - let mut inner = { - match func_def.as_rule() { - Rule::func_def => func_def.into_inner(), - rule => panic!("Expected func_def, got {:?}", rule) - } - }; - - // Function name - let name = { - let Some(pair) = inner.next() else { unreachable!("Function definition has no name") }; - parse_id(pair) - }; - - // Function arguments and types - let args = { - let Some(pair) = inner.next() else { unreachable!("Function definition has no name") }; - parse_func_def_args(pair) - }; - - // Optional return type - let ret_typ = { - let Some(pair) = inner.next() else { unreachable!("Function definition has no name") }; - match pair.into_inner().next() { - Some(pair) => Some(parse_typ(pair)), - _ => None - } - }; - - // Function body - let mut func_body = { - let Some(pair) = inner.next() else { unreachable!("Function definition has no body") }; - pair.into_inner() - }; - - // Inner statements - let mut stmts = Vec::new(); - loop { - if let Some(pair) = func_body.peek() { - match pair.as_rule() { - Rule::ret => break, - Rule::stmt => { - let stmt = parse_stmt(pair); - stmts.push(stmt); - func_body.next(); - }, - rule => unreachable!("Function bodies cannot produce {:?}", rule), - } - } else { - break; - } - } - - // Optional return - let ret_expr = { - if let Some(ret) = func_body.next() { - let Some(expr) = ret.into_inner().next() else { - unreachable!("Return statements must have an expression") - }; - Some(parse_expr(expr.into_inner())) - } else { - None - } - }; - - // If stmts is empty and ret_expr is None, the function body is empty - if stmts.is_empty() && ret_expr.is_none() { - panic!("The function body of {:?} is empty", name) - } - - FuncDef { - name: name, - args: args, - ret_typ: ret_typ, - stmts: stmts, - ret: ret_expr - } -} - -fn parse_func_def_args(arg_list: Pair) -> Vec<(Id, Typ)> { - match arg_list.as_rule() { - Rule::func_def_args => { - let mut args = Vec::new(); - let mut inner = arg_list.into_inner(); - while let Some(pair) = inner.next() { - // Consume the next two pairs: the id and the type - let id = parse_id(pair); - let typ = { - let Some(pair) = inner.next() else { - unreachable!("Function type signature is incomplete") - }; - parse_typ(pair) - }; - args.push((id, typ)); - } - args - }, - rule => {panic!("{:?} is not a list of function arguments", rule)} - } -} - -fn parse_stmt(stmt: Pair) -> Stmt { - match stmt.as_rule() { - Rule::decl => { - let mut inner = stmt.into_inner(); - let id = { - let Some(pair) = inner.next() else { - unreachable!("A declaration requires an Id") - }; - parse_id(pair) - }; - let typ = { - let Some(pair) = inner.next() else { - unreachable!("Expected inner statement, found nothing") - }; - parse_typ(pair) - }; - let expr_opt = { - println!("Just the expr: {:?}", inner); - if inner.peek().is_none() { - // println!("This declaration does not give an initialization"); - None - } - else { - Some(parse_expr(inner)) - } - }; - Stmt::Decl { - typ: typ, - id: id, - expr: expr_opt - } - }, - Rule::graph_decl => { - let mut inner = stmt.into_inner(); - let id = { - let Some(pair) = inner.next() else { - unreachable!("A graph declaration requires an Id") - }; - parse_id(pair) - }; - Stmt::GraphDecl { - id: id - } - }, - Rule::parset_decl => { - let mut inner = stmt.into_inner(); - let id = { - let Some(pair) = inner.next() else { - unreachable!("A parset declaration requires an Id") - }; - parse_id(pair) - }; - let typ = { - let Some(pair) = inner.next() else { - unreachable!("A parset declaration requires a type") - }; - parse_typ(pair) - }; - let graph_id = { - if let Some(pair) = inner.next() { - Some(parse_id(pair)) - } else { - None - } - }; - Stmt::ParsetDecl { - id: id, - typ: typ, - graph_id: graph_id - } - }, - Rule::assign => { - // Just contains an id and an expression - let mut inner = stmt.into_inner(); - let id = { - let Some(pair) = inner.next() else { - unreachable!("A declaration requires an Id") - }; - parse_id(pair) - }; - let expr = { - parse_expr(inner) - }; - Stmt::Assign { - id: id, - expr: expr - } - }, - Rule::block => { - let mut stmts = Vec::new(); - for s in stmt.into_inner() { - stmts.push(Box::new(parse_stmt(s))); - } - Stmt::Block { stmts: stmts } - }, - Rule::if_stmt => { - let mut inner = stmt.into_inner(); - // if guard - let guard = { - let Some(pair) = inner.next() else { - unreachable!("An if statement requires a guard") - }; - parse_expr(pair.into_inner()) - }; - // if block - let if_block = { - let Some(pair) = inner.next() else { - unreachable!("No if block found") - }; - Box::new(parse_stmt(pair)) - }; - let mut else_block = None; - struct ElifStmt{ - guard: Expr, - block: Stmt - } - let mut elif_stmts = Vec::new(); - while let Some(pair) = inner.next() { - match pair.as_rule() { - // else block - Rule::block => { - else_block = { - Some(Box::new(parse_stmt(pair))) - }; - }, - _ => { - // elifs consume the next two pairs - let elif_guard = { - parse_expr(pair.into_inner()) - }; - let elif_block = { - let Some(pair) = inner.next() else { - unreachable!("No elif block found") - }; - parse_stmt(pair) - }; - elif_stmts.push( - ElifStmt{ guard: elif_guard, block: elif_block} - ); - } - } - } - // TODO: Questionable cloning happening here - let elif = elif_stmts.iter().rfold(None, - |next_elif, elif_stmt| { - let ElifStmt { guard, block } = elif_stmt; - Some(Box::new( - Stmt::If { - guard: guard.clone(), - if_block: Box::new(block.clone()), - elif_block: next_elif, - else_block: None - } - )) - } - ); - - Stmt::If { - guard : guard, - if_block : if_block, - elif_block: elif, - else_block: else_block, - } - }, - Rule::while_stmt => { - // Contains a guard and a block - let mut inner = stmt.into_inner(); - let guard = { - let Some(pair) = inner.next() else { - unreachable!("While loop has no guard") - }; - parse_expr(pair.into_inner()) - }; - let block = { - let Some(pair) = inner.next() else { - unreachable!("While loop has no body") - }; - parse_stmt(pair) - }; - Stmt::While { - guard: guard, - body: Box::new(block) - } - }, - Rule::for_stmt => { - // Contains a guard and a block - let mut inner = stmt.into_inner(); - let id = { - let Some(pair) = inner.next() else { - unreachable!("For loop with no id") - }; - parse_id(pair) - }; - let iterator = { - let Some(pair) = inner.next() else { - unreachable!("For loop with no iterator") - }; - parse_expr(pair.into_inner()) - }; - let body = { - let Some(pair) = inner.next() else { - unreachable!("For loop with no body") - }; - parse_stmt(pair) - }; - Stmt::For { - id: id, - iterator: iterator, - body: Box::new(body) - } - }, - Rule::emit_to => { - // Contains an expression and a set identifier - let mut inner = stmt.into_inner(); - let expr = { - let pair = inner.next().unwrap(); - parse_expr(pair.into_inner()) - }; - let set_id = { - let pair = inner.next().unwrap(); - parse_id(pair) - }; - Stmt::EmitTo { - expr: expr, - set_id: set_id - } - }, - Rule::call_stmt => { - let object = parse_expr(stmt.into_inner()); - match object { - Expr::FuncCall{ name, args } => { - Stmt::FuncCallStmt { - name: name, - args: args - } - }, - Expr::MethodCall{ object, method, args } => { - Stmt::MethodCallStmt { - object: *object, - method: method, - args: args - } - }, - _ => { panic!("A call_stmt must either be a function call or a method call") } - } - }, - Rule::stmt => { - let mut inner = stmt.into_inner(); - let s = { - if let Some(pair) = inner.next() { - parse_stmt(pair) - } else { - unreachable!("Statement has no inner statement") - } - }; - assert!(inner.next().is_none()); - s - } - rule => unreachable!("{:?} Not recognized", rule) - } -} - -fn parse_expr(expression: Pairs) -> Expr { - PRATT_PARSER - .map_primary(|primary| match primary.as_rule() { - Rule::integer_lit => ast::Expr::Integer(primary.as_str().parse::().unwrap()), - Rule::true_lit => Expr::Bool(true), - Rule::false_lit => Expr::Bool(false), - Rule::char_lit => Expr::Char(parse_char(primary.into_inner().next().unwrap())), - Rule::string_lit => { - let mut string = String::new(); - for character in primary.into_inner() { - string.push(parse_char(character)); - } - Expr::StringLit(string) - }, - Rule::identifier => Expr::Var(parse_id(primary)), - Rule::record_lit => { - // record_lit looks like Record { f1: e1, ..., fn:en } - let mut inner = primary.into_inner(); - let typ = { - let Some(pair) = inner.next() else { - unreachable!("An if statement requires a guard") - }; - parse_typ(pair) - }; - let mut fields = Vec::new(); - while let Some(pair) = inner.next() { - // Consume the next two pairs - let field = { - parse_id(pair) - }; - let val = { - let Some(pair) = inner.next() else { - unreachable!("Each field needs a value") - }; - parse_expr(pair.into_inner()) - }; - fields.push( - RecordField{ field: field, val: val} - ); - } - Expr::Record { - typ: typ, - fields: fields - } - }, - Rule::record_update_lit => { - // record_update_lit looks like { e1 with f1: e1, ..., fn:en } - let mut inner = primary.into_inner(); - let parent = { - let Some(pair) = inner.next() else { - unreachable!("Record update requires a record") - }; - parse_expr(pair.into_inner()) - }; - let mut fields = Vec::new(); - while let Some(pair) = inner.next() { - // Consume the next two pairs - let field = { - parse_id(pair) - }; - let val = { - let Some(pair) = inner.next() else { - unreachable!("Each field needs a value") - }; - parse_expr(pair.into_inner()) - }; - fields.push( - RecordField{ field: field, val: val} - ); - } - Expr::RecordUpdate { - parent: Box::new(parent), - fields: fields - } - }, - Rule::tuple_lit => { - let mut inner = primary.into_inner(); - let Some(lhs) = inner.next() else { unreachable!("tuple has no lhs") }; - let Some(rhs) = inner.next() else { unreachable!("tuple has no rhs") }; - assert!(inner.next().is_none()); - Expr::Tuple { - lhs: Box::new(parse_expr(lhs.into_inner())), - rhs: Box::new(parse_expr(rhs.into_inner())) - } - } - Rule::obj_initialize => { - let typ = parse_typ(primary.into_inner().next().unwrap()); - Expr::ObjInitialization{ typ: typ } - }, - Rule::func_call => { - let mut inner = primary.into_inner(); - let func_name = { - let Some(pair) = inner.next() else { - unreachable!("A function call requires a name") - }; - parse_id(pair) - }; - let args = { - let Some(pair) = inner.next() else { - unreachable!("A function call needs 0 or more arguments") - }; - parse_call_args(pair) - }; - Expr::FuncCall { - name: func_name, - args: args - } - }, - Rule::expr => { - // If this rule has been reached then - // this is a parenthesized expression - - // println!("Full expr: {:?}", inner); - parse_expr(primary.into_inner()) - } - rule => unreachable!("Expr::parse expected atom, found {:?}", rule) - }) - .map_prefix(|op, exp| { - let op = match op.as_rule() { - Rule::not => UOp::Not, - rule => unreachable!("{:?} not recognized as a uop", rule), - }; - Expr::UOpExpr { - op, - expr: Box::new(exp), - } - }) - .map_postfix(|exp, op| { - let idx_expr = match op.as_rule() { - Rule::array_access => { - let mut inner = op.into_inner(); - let Some(expr) = inner.next() else { - unreachable!("array access requires an expression") - }; - parse_expr(expr.into_inner()) - } - rule => unreachable!("{:?} not recognized as a postfix", rule) - }; - - Expr::ArrayAccess { - expr: Box::new(exp), - idx: Box::new(idx_expr) - } - }) - .map_infix(|lhs, op, rhs| { - enum OpType { - Binary(BinOp), - FieldAccess - } - let op_typ = match op.as_rule() { - Rule::add => OpType::Binary(BinOp::Add), - Rule::sub => OpType::Binary(BinOp::Sub), - Rule::mult => OpType::Binary(BinOp::Mult), - Rule::div => OpType::Binary(BinOp::Div), - Rule::modulo => OpType::Binary(BinOp::Mod), - Rule::lt => OpType::Binary(BinOp::Lt), - Rule::gt => OpType::Binary(BinOp::Gt), - Rule::leq => OpType::Binary(BinOp::Leq), - Rule::geq => OpType::Binary(BinOp::Geq), - Rule::eq => OpType::Binary(BinOp::Eq), - Rule::neq => OpType::Binary(BinOp::Neq), - Rule::and => OpType::Binary(BinOp::And), - Rule::or => OpType::Binary(BinOp::Or), - Rule::field_access => OpType::FieldAccess, - rule => unreachable!("Expr::parse expected infix operation, found {:?}", rule), - }; - match op_typ { - OpType::Binary(op) => { - Expr::BinOpExpr { - lhs: Box::new(lhs), - op, - rhs: Box::new(rhs), - } - } - OpType::FieldAccess => { - match rhs { - Expr::FuncCall { name, args } => { - Expr::MethodCall { - object: Box::new(lhs), - method: name, - args: args - } - }, - _ => { - Expr::FieldAccess { - object: Box::new(lhs), - field: Box::new(rhs) - } - } - } - } - } - }) - .parse(expression) -} - -fn parse_call_args(arg_list: Pair) -> Vec { - match arg_list.as_rule() { - Rule::call_args => { - let mut args = Vec::new(); - for arg in arg_list.into_inner() { - args.push( - parse_expr(arg.into_inner()) - ); - } - args - }, - rule => {panic!("{:?} is not a list of function arguments", rule)} - } -} - -fn parse_id(id: Pair) -> Id { - match id.as_rule() { - Rule::identifier => Id(id.as_str().to_string()), - rule => panic!("Identifier expected, but {:?} found", rule) - } -} - -fn parse_typ(typ: Pair) -> Typ { - // println!("Type Pair: {:#?}", typ); - match typ.as_rule() { - Rule::atomic_typ => match typ.as_str() { - "int" => Typ::Int, - "bool" => Typ::Bool, - "char" => Typ::Char, - "Path" => Typ::Path, - "Segment" => Typ::Node, - "Step" => Typ::Step, - "Edge" => Typ::Edge, - "Base" => Typ::Base, - "String" => Typ::String, - "Strand" => Typ::Strand, - t => unreachable!("Unknown type: {}", t) - }, - Rule::tuple_typ => { - let mut inner = typ.into_inner(); - let t1 = { - if let Some(pair) = inner.next() { - parse_typ(pair) - } else { - unreachable!("Expected first tuple type but found nothing") - } - }; - let t2 = { - if let Some(pair) = inner.next() { - parse_typ(pair) - } else { - unreachable!("Expected second tuple type but found nothing") - } - }; - assert!(inner.next().is_none()); - Typ::Tuple(Box::new(t1), Box::new(t2)) - }, - Rule::set_typ => { - let mut inner = typ.into_inner(); - let t = { - if let Some(pair) = inner.next() { - parse_typ(pair) - } else { - unreachable!("Expected first tuple type but found nothing") - } - }; - assert!(inner.next().is_none()); - Typ::Set(Box::new(t)) - } - rule => unreachable!("Unknown type: {:?}", rule) - // TODO - probably replace this with a Result<> return type - } -} - -fn parse_char(character: Pair) -> char { - match character.as_rule() { - Rule::back_backslash => '\\', - Rule::back_tab => '\t', - Rule::back_newline => '\n', - Rule::back_single_quote => '\'', - Rule::back_double_quote => '\"', - Rule::normal_char => character.as_str().chars().nth(0).unwrap(), - rule => unreachable!("Expected char but got {:?}", rule) - } -} - -fn extract_file(filename: String) -> String { - // Create a path to the desired file - let path = Path::new(&filename); - let display = path.display(); - - // Open the path in read-only mode, returns `io::Result` - let mut file = match File::open(&path) { - Err(why) => panic!("Couldn't open file {}: {}", display, why), - Ok(file) => file, - }; - - // Read the file contents into a string, returns `io::Result` - let mut s = String::new(); - match file.read_to_string(&mut s) { - Err(why) => panic!("Couldn't read file {}: {}", display, why), - Ok(_) => s - } -} - -pub fn main() { - let args: Vec = env::args().collect(); - - let prog: String = match args.len() { - // one argument passed - 2 => { - match args[1].parse() { - Ok(filename) => extract_file(filename), - Err(e) => panic!("Failed with error: {:?}", e) - } - }, - n => { - panic!("Expected one argument but found {}", n-1); - } - }; - - match PollenParser::parse(Rule::file, &prog) { - Ok(mut pairs) => { - println!( - "{:#?}", - parse_prog(pairs.next().unwrap().into_inner()) - ); - } - Err(e) => { - eprintln!("{:?}", e); - } - } -} diff --git a/pollen/src/parse.rs b/pollen/src/parse.rs deleted file mode 100644 index 04e16ec3..00000000 --- a/pollen/src/parse.rs +++ /dev/null @@ -1,17 +0,0 @@ -extern crate pest; -#[macro_use] -extern crate pest_derive; - -use pest::Parser; - -#[derive(Parser)] -#[grammar = "pollen.pest"] -pub struct PollenParser; - -pub fn parse() { - let successful_parse = PollenParser::parse(Rule::var, "Var1"); - println!("{:?}", successful_parse); - - let unsuccessful_parse = PollenParser::parse(Rule::var, "1v"); - println!("{:?}", unsuccessful_parse); -} \ No newline at end of file diff --git a/pollen/src/pollen.pest b/pollen/src/pollen.pest deleted file mode 100644 index f23826f9..00000000 --- a/pollen/src/pollen.pest +++ /dev/null @@ -1,160 +0,0 @@ -WHITESPACE = _{ " " | "\t" | NEWLINE } -COMMENT = _{ ("//" ~ (!NEWLINE ~ ANY)* ~ (NEWLINE | EOI)) - | "/*" ~ (!"*/" ~ ANY)* ~ "*/" } - -// Excludes type keywords -// keywords = _{ "if" | "elif" | "else" | "for" | "in" | "while" } - -/* ----- Program ----- */ -file = { - SOI - ~ imports - ~ func_defs - ~ EOI -} - imports = { import* } - func_defs = { func_def+ } - -/* ----- Import ----- */ -import = _{ import_as | import_from } - -import_as = { "import" ~ filename ~ ("as" ~ identifier)? ~ ";" } -import_from = { "from" ~ filename ~ "import" ~ func_as_id ~ ("," ~ func_as_id)* ~ ";"} - func_as_id = { identifier ~ ("as" ~ identifier)? } - -// TODO: Probably make this less permissible -filename = @{ (!(WHITESPACE | ";") ~ ANY)+ } - -/* ----- Types ----- */ -// Types that do not contain fields or method calls - -atomic_typ = { "int" | "bool" | "char" | "Path" | "Segment" | "Step" | "Edge" - | "Base" | "String" | "Strand" } - -// TODO: allow larger tuples -tuple_typ = { "(" ~ atomic_typ ~ ("*" ~ atomic_typ)/*+*/ ~ ")" } - -set_typ = { "Set<" ~ typ ~ ">" } - -// String and Strand are not atomic types because they cannot be part of tuples -typ = _{ atomic_typ | set_typ | tuple_typ /* | typ ~ ( "[]"* ) */ } - -/* Record types are not included because the user will never - need to explicitly define one */ - - -/* ----- Literals ----- */ -integer_lit = @{ ("+" | "-")? ~ ASCII_DIGIT+ } -bool_lit = _{ true_lit | false_lit } - true_lit = { "true" } - false_lit = { "false" } - -single_quote = _{ "'" } -double_quote = _{ "\"" } -backslack = _{ "\\" } - -backspace_chars = _{ back_backslash | back_tab | back_newline | back_single_quote - | back_double_quote } - back_backslash = { "\\\\" } - back_tab = { "\\t" } - back_newline = { "\\n" } - back_single_quote = @{ "\\" ~ single_quote } - back_double_quote = @{ "\\" ~ double_quote } - -normal_char = { !backslack ~ ANY } - -char = _{ backspace_chars | normal_char } -char_lit = ${ (single_quote ~ (!single_quote ~ char) ~ single_quote) } -string_lit = ${ double_quote ~ (!double_quote ~ char)* ~ double_quote } -// TODO: Try to find a way to use string_lit and strand_lit via precedence? - -// array_lit = { "[" ~ expr? ~ ("," ~ expr)* ~ "]" } -record_lit = { typ ~ "{" ~ - identifier ~ ":" ~ expr ~ - ("," ~ identifier ~ ":" ~ expr)* ~ "}" - } -record_update_lit = { "{" ~ expr ~ "with" ~ - identifier ~ ":" ~ expr ~ - ("," ~ identifier ~ ":" ~ expr)* ~ "}" - } -tuple_lit = { "(" ~ expr ~ "," ~ expr ~ ")" } - -literal = _{ integer_lit | bool_lit | char_lit | string_lit - | record_lit | record_update_lit | tuple_lit } - - -/* ----- Expressions ----- */ - -identifier = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_" | "-" | "'" )* } - -binop = _{ add | sub | mult | div | modulo | geq | leq | lt | gt | eq | neq | - and | or | field_access } - add = { "+" } - sub = { "-" } - mult = { "*" } - div = { "/" } - modulo = { "%" } - geq = { "<=" } - leq = { ">=" } - lt = { "<" } - gt = { ">" } - eq = { "==" } - neq = { "!=" } - and = { "&&" } - or = { "||" } - field_access = { "." } - - -// unary operator(s) -prefix = _{ not } - not = { "!" } - -call_begin = { "(" } - -obj_initialize = { typ ~ "()" } -call_args = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" } -func_call = { identifier ~ call_args } - -term = _{ literal | obj_initialize | func_call | identifier | "(" ~ expr ~ ")" | "[" ~ expr ~ "]" } - -array_access = { "[" ~ expr ~ "]" } -postfix = _{ array_access } -term_ext = _ { prefix* ~ term ~ postfix* } - -expr = { term_ext ~ (binop ~ term_ext) * } - - -/* ----- Statements ---- */ -decl = { identifier ~ ":" ~ typ ~ ("=" ~ expr)? ~ ";"} -graph_decl = { "graph" ~ identifier ~ ";" } -parset_decl = { "parset" ~ identifier ~ "[" ~ typ ~ ("," ~ identifier)? ~ "]" ~ ";"} - -assign = { identifier ~ "=" ~ expr ~ ";" } -// assign = { (((identifier | array_access | record_access) ~ ("=" | "+=") ~ expr) | (identifier ~ "++")) ~ ";"} - -block = { "{" ~ stmt+ ~ "}" } - -// Control Flow -if_stmt = { "if" ~ expr ~ block ~ ("elif" ~ expr ~ block)* ~ ("else" ~ block)? } -while_stmt = { "while" ~ expr ~ block } -for_stmt = { "for" ~ identifier ~ "in" ~ expr ~ block } - -// Function call -call_stmt = { expr ~ ";" } - -// Emit statements -emit_to = { "emit" ~ expr ~ "to" ~ identifier ~ ";" } - -stmt = { decl | graph_decl | parset_decl | assign | block - | if_stmt | while_stmt | for_stmt | emit_to | call_stmt } - -func_def = { "def" ~ identifier ~ - func_def_args ~ - ret_typ ~ - func_body - } - func_def_args = { "(" ~ (identifier ~ ":" ~ typ ~ ("," ~ identifier ~ ":" ~ typ)*)? ~ ")" } - ret_typ = { ("->" ~ typ)? } - // function definitions must contain at least one statement or return - func_body = { "{" ~ stmt* ~ ret? ~ "}" } - ret = { "return" ~ expr ~ ";" } diff --git a/pollen/src/test.rs b/pollen/src/test.rs deleted file mode 100644 index 02c2a4be..00000000 --- a/pollen/src/test.rs +++ /dev/null @@ -1,5 +0,0 @@ - - -fn main() { - -} \ No newline at end of file diff --git a/pollen/tests/crush.pol b/pollen/tests/crush.pol deleted file mode 100644 index 5b554a6f..00000000 --- a/pollen/tests/crush.pol +++ /dev/null @@ -1,19 +0,0 @@ -graph out_g; -parset out_segs[Segment, out_g]; - -for segment in in_g { - seq = Strand(); - in_n = false; - for c in segment.sequence { - if c == 'N' { - if !in_n { - in_n = true; - seq.push(c); - } - } else { - in_n = false; - seq.push(c); - } - } - emit { segment with sequence: seq } to out_segs; -} \ No newline at end of file diff --git a/pollen/tests/crush.pollen b/pollen/tests/crush.pollen deleted file mode 100644 index 339c360b..00000000 --- a/pollen/tests/crush.pollen +++ /dev/null @@ -1,18 +0,0 @@ -def crush() { - graph out_g; - parset out_segs[Segment, out_g]; - for segment in Segments { - seq = Strand(); - in_n = false; - for c in segment.sequence { - if (c == 'N' && !in_n) { - in_n = true; - seq.push(c); - } else { - in_n = false; - seq.push(c); - } - } - emit { segment with sequence: seq } to out_segs; - } -} \ No newline at end of file diff --git a/pollen/tests/degree.pol b/pollen/tests/degree.pol deleted file mode 100644 index 7138a316..00000000 --- a/pollen/tests/degree.pol +++ /dev/null @@ -1,6 +0,0 @@ -// Output is a (Segment, int) set. -outset out_degs[(Segment, int)]; - -for segment in in_g.segments { - emit (segment, segment.edges.size()) to out_degs; -} \ No newline at end of file diff --git a/pollen/tests/degree.pollen b/pollen/tests/degree.pollen deleted file mode 100644 index d152d19f..00000000 --- a/pollen/tests/degree.pollen +++ /dev/null @@ -1,8 +0,0 @@ -def degree() { - // Output is a (Segment, int) set. - parset out_degs[(Segment*int)]; - - for segment in in_g.segments { - emit (segment, segment.edges.size()) to out_degs; - } -} \ No newline at end of file diff --git a/pollen/tests/depth.pol b/pollen/tests/depth.pol deleted file mode 100644 index ceb1fd8d..00000000 --- a/pollen/tests/depth.pol +++ /dev/null @@ -1,6 +0,0 @@ -// Output is a (Segment, int) set. -outset out_depths[(Segment, int)]; - -for segment in in_g.segments { - emit (segment, segment.steps.size()) to out_depths; -} \ No newline at end of file diff --git a/pollen/tests/depth.pollen b/pollen/tests/depth.pollen deleted file mode 100644 index eadc7f5f..00000000 --- a/pollen/tests/depth.pollen +++ /dev/null @@ -1,21 +0,0 @@ -// Compute the node depth, considering a subset of paths in the graph - -def depth(subset_paths: Set) { - parset depths[(Segment*int)]; - for segment in segments { - depth = 0; - for step in segment.steps { - consider_path = false; - // Should be more efficient to use a bitvector instead - for path in subset_paths { - if step.path == path { - consider_path = true; - } - } - if consider_path { - depth = depth + 1; - } - } - emit (segment, depth) to depths; - } -} \ No newline at end of file diff --git a/pollen/tests/flip.pol b/pollen/tests/flip.pol deleted file mode 100644 index 4f59af87..00000000 --- a/pollen/tests/flip.pol +++ /dev/null @@ -1,37 +0,0 @@ -graph out_g; -parset out_steps[Step, out_g]; -parset out_paths[Path, out_g]; - -local is_rev(Path path) { - fw = 0; - bw = 0; - for step in path.steps { - sh = step.handle; - len = sh.segment.sequence.length(); - if sh.orientation { - fw += len; - } - else { - bw += len; - } - } - return bw > fw; -} - -local flip_path(Path path) { - if is_rev(path) { - for step in rev(path.steps) { - emit { - step with handle: - { step.handle with - orientation = !step.handle.orientation - } - } to out_steps; - } - } - emit { path with steps: path_steps } to out_paths; -} - -for path in in_g.paths { - flip_path(path); -} diff --git a/pollen/tests/flip.pollen b/pollen/tests/flip.pollen deleted file mode 100644 index 00150d0b..00000000 --- a/pollen/tests/flip.pollen +++ /dev/null @@ -1,39 +0,0 @@ -def flip() { - graph out_g; - - for path in paths { - flip_path(path); - } -} - -def flip_path(path: Path) { - parset out_steps[Step, out_g]; - max_step_idx = path.length() - 1; - if is_rev(path) { - for step in path.steps { - emit - { step with handle: - { step.handle with - orientation: !step.handle.orientation - }, - idx: max_step_idx - step.idx - } to out_steps; - } - } -} - -def is_rev(path: Path) { - fw = 0; - bw = 0; - for step in path.steps { - sh = step.handle; - len = sh.segment.length(); - if sh.orientation { - fw = fw + len; - } - else { - bw = bw + len; - } - } - return bw > fw; -} \ No newline at end of file diff --git a/pollen/tests/overlap.pol b/pollen/tests/overlap.pol deleted file mode 100644 index 6ba41eab..00000000 --- a/pollen/tests/overlap.pol +++ /dev/null @@ -1,12 +0,0 @@ -// Output is a (Path, Path) set. -outset out_overlaps[(Path, Path)]; - -for path in in_g.paths { - for step in path.steps { - for s in step.handle.segment.steps { - if s.path != path { - emit (path, s.path) to out_overlaps; - } - } - } -} \ No newline at end of file diff --git a/pollen/tests/overlap.pollen b/pollen/tests/overlap.pollen deleted file mode 100644 index 58200282..00000000 --- a/pollen/tests/overlap.pollen +++ /dev/null @@ -1,14 +0,0 @@ -def overlap() { - // Output is a (Path, Path) set. - parset out_overlaps[(Path*Path)]; - - for path in paths { - for step in path.steps { - for s in step.handle.segment.steps { - if s.path != path { - emit (path, s.path) to out_overlaps; - } - } - } - } -} \ No newline at end of file diff --git a/pollen/tests/parse-out/crush.expect b/pollen/tests/parse-out/crush.expect deleted file mode 100644 index b731d7bb..00000000 --- a/pollen/tests/parse-out/crush.expect +++ /dev/null @@ -1,191 +0,0 @@ -Prog { - imports: [], - func_defs: [ - FuncDef { - name: Id( - "crush", - ), - args: [], - ret_typ: None, - stmts: [ - GraphDecl { - id: Id( - "out_g", - ), - }, - ParsetDecl { - id: Id( - "out_segs", - ), - typ: Node, - graph_id: Some( - Id( - "out_g", - ), - ), - }, - For { - id: Id( - "segment", - ), - iterator: Var( - Id( - "Segments", - ), - ), - body: Block { - stmts: [ - Assign { - id: Id( - "seq", - ), - expr: ObjInitialization { - typ: Strand, - }, - }, - Assign { - id: Id( - "in_n", - ), - expr: Bool( - false, - ), - }, - For { - id: Id( - "c", - ), - iterator: FieldAccess { - object: Var( - Id( - "segment", - ), - ), - field: Var( - Id( - "sequence", - ), - ), - }, - body: Block { - stmts: [ - If { - guard: BinOpExpr { - lhs: BinOpExpr { - lhs: Var( - Id( - "c", - ), - ), - op: Eq, - rhs: Char( - 'N', - ), - }, - op: And, - rhs: UOpExpr { - op: Not, - expr: Var( - Id( - "in_n", - ), - ), - }, - }, - if_block: Block { - stmts: [ - Assign { - id: Id( - "in_n", - ), - expr: Bool( - true, - ), - }, - MethodCallStmt { - object: Var( - Id( - "seq", - ), - ), - method: Id( - "push", - ), - args: [ - Var( - Id( - "c", - ), - ), - ], - }, - ], - }, - elif_block: None, - else_block: Some( - Block { - stmts: [ - Assign { - id: Id( - "in_n", - ), - expr: Bool( - false, - ), - }, - MethodCallStmt { - object: Var( - Id( - "seq", - ), - ), - method: Id( - "push", - ), - args: [ - Var( - Id( - "c", - ), - ), - ], - }, - ], - }, - ), - }, - ], - }, - }, - EmitTo { - expr: RecordUpdate { - parent: Var( - Id( - "segment", - ), - ), - fields: [ - RecordField { - field: Id( - "sequence", - ), - val: Var( - Id( - "seq", - ), - ), - }, - ], - }, - set_id: Id( - "out_segs", - ), - }, - ], - }, - }, - ], - ret: None, - }, - ], -} diff --git a/pollen/tests/parse-out/degree.expect b/pollen/tests/parse-out/degree.expect deleted file mode 100644 index 37a225fc..00000000 --- a/pollen/tests/parse-out/degree.expect +++ /dev/null @@ -1,76 +0,0 @@ -Prog { - imports: [], - func_defs: [ - FuncDef { - name: Id( - "degree", - ), - args: [], - ret_typ: None, - stmts: [ - ParsetDecl { - id: Id( - "out_degs", - ), - typ: Tuple( - Node, - Int, - ), - graph_id: None, - }, - For { - id: Id( - "segment", - ), - iterator: FieldAccess { - object: Var( - Id( - "in_g", - ), - ), - field: Var( - Id( - "segments", - ), - ), - }, - body: Block { - stmts: [ - EmitTo { - expr: Tuple { - lhs: Var( - Id( - "segment", - ), - ), - rhs: MethodCall { - object: FieldAccess { - object: Var( - Id( - "segment", - ), - ), - field: Var( - Id( - "edges", - ), - ), - }, - method: Id( - "size", - ), - args: [], - }, - }, - set_id: Id( - "out_degs", - ), - }, - ], - }, - }, - ], - ret: None, - }, - ], -} diff --git a/pollen/tests/parse-out/depth.expect b/pollen/tests/parse-out/depth.expect deleted file mode 100644 index 178f9275..00000000 --- a/pollen/tests/parse-out/depth.expect +++ /dev/null @@ -1,181 +0,0 @@ -Prog { - imports: [], - func_defs: [ - FuncDef { - name: Id( - "depth", - ), - args: [ - ( - Id( - "subset_paths", - ), - Set( - Path, - ), - ), - ], - ret_typ: None, - stmts: [ - ParsetDecl { - id: Id( - "depths", - ), - typ: Tuple( - Node, - Int, - ), - graph_id: None, - }, - For { - id: Id( - "segment", - ), - iterator: Var( - Id( - "segments", - ), - ), - body: Block { - stmts: [ - Assign { - id: Id( - "depth", - ), - expr: Integer( - 0, - ), - }, - For { - id: Id( - "step", - ), - iterator: FieldAccess { - object: Var( - Id( - "segment", - ), - ), - field: Var( - Id( - "steps", - ), - ), - }, - body: Block { - stmts: [ - Assign { - id: Id( - "consider_path", - ), - expr: Bool( - false, - ), - }, - For { - id: Id( - "path", - ), - iterator: Var( - Id( - "subset_paths", - ), - ), - body: Block { - stmts: [ - If { - guard: BinOpExpr { - lhs: FieldAccess { - object: Var( - Id( - "step", - ), - ), - field: Var( - Id( - "path", - ), - ), - }, - op: Eq, - rhs: Var( - Id( - "path", - ), - ), - }, - if_block: Block { - stmts: [ - Assign { - id: Id( - "consider_path", - ), - expr: Bool( - true, - ), - }, - ], - }, - elif_block: None, - else_block: None, - }, - ], - }, - }, - If { - guard: Var( - Id( - "consider_path", - ), - ), - if_block: Block { - stmts: [ - Assign { - id: Id( - "depth", - ), - expr: BinOpExpr { - lhs: Var( - Id( - "depth", - ), - ), - op: Add, - rhs: Integer( - 1, - ), - }, - }, - ], - }, - elif_block: None, - else_block: None, - }, - ], - }, - }, - EmitTo { - expr: Tuple { - lhs: Var( - Id( - "segment", - ), - ), - rhs: Var( - Id( - "depth", - ), - ), - }, - set_id: Id( - "depths", - ), - }, - ], - }, - }, - ], - ret: None, - }, - ], -} diff --git a/pollen/tests/parse-out/flip.expect b/pollen/tests/parse-out/flip.expect deleted file mode 100644 index 61049f7b..00000000 --- a/pollen/tests/parse-out/flip.expect +++ /dev/null @@ -1,393 +0,0 @@ -Prog { - imports: [], - func_defs: [ - FuncDef { - name: Id( - "flip", - ), - args: [], - ret_typ: None, - stmts: [ - GraphDecl { - id: Id( - "out_g", - ), - }, - For { - id: Id( - "path", - ), - iterator: Var( - Id( - "paths", - ), - ), - body: Block { - stmts: [ - FuncCallStmt { - name: Id( - "flip_path", - ), - args: [ - Var( - Id( - "path", - ), - ), - ], - }, - ], - }, - }, - ], - ret: None, - }, - FuncDef { - name: Id( - "flip_path", - ), - args: [ - ( - Id( - "path", - ), - Path, - ), - ], - ret_typ: None, - stmts: [ - ParsetDecl { - id: Id( - "out_steps", - ), - typ: Step, - graph_id: Some( - Id( - "out_g", - ), - ), - }, - Assign { - id: Id( - "max_step_idx", - ), - expr: BinOpExpr { - lhs: MethodCall { - object: Var( - Id( - "path", - ), - ), - method: Id( - "length", - ), - args: [], - }, - op: Sub, - rhs: Integer( - 1, - ), - }, - }, - If { - guard: FuncCall { - name: Id( - "is_rev", - ), - args: [ - Var( - Id( - "path", - ), - ), - ], - }, - if_block: Block { - stmts: [ - For { - id: Id( - "step", - ), - iterator: FieldAccess { - object: Var( - Id( - "path", - ), - ), - field: Var( - Id( - "steps", - ), - ), - }, - body: Block { - stmts: [ - EmitTo { - expr: RecordUpdate { - parent: Var( - Id( - "step", - ), - ), - fields: [ - RecordField { - field: Id( - "handle", - ), - val: RecordUpdate { - parent: FieldAccess { - object: Var( - Id( - "step", - ), - ), - field: Var( - Id( - "handle", - ), - ), - }, - fields: [ - RecordField { - field: Id( - "orientation", - ), - val: UOpExpr { - op: Not, - expr: FieldAccess { - object: FieldAccess { - object: Var( - Id( - "step", - ), - ), - field: Var( - Id( - "handle", - ), - ), - }, - field: Var( - Id( - "orientation", - ), - ), - }, - }, - }, - ], - }, - }, - RecordField { - field: Id( - "idx", - ), - val: BinOpExpr { - lhs: Var( - Id( - "max_step_idx", - ), - ), - op: Sub, - rhs: FieldAccess { - object: Var( - Id( - "step", - ), - ), - field: Var( - Id( - "idx", - ), - ), - }, - }, - }, - ], - }, - set_id: Id( - "out_steps", - ), - }, - ], - }, - }, - ], - }, - elif_block: None, - else_block: None, - }, - ], - ret: None, - }, - FuncDef { - name: Id( - "is_rev", - ), - args: [ - ( - Id( - "path", - ), - Path, - ), - ], - ret_typ: None, - stmts: [ - Assign { - id: Id( - "fw", - ), - expr: Integer( - 0, - ), - }, - Assign { - id: Id( - "bw", - ), - expr: Integer( - 0, - ), - }, - For { - id: Id( - "step", - ), - iterator: FieldAccess { - object: Var( - Id( - "path", - ), - ), - field: Var( - Id( - "steps", - ), - ), - }, - body: Block { - stmts: [ - Assign { - id: Id( - "sh", - ), - expr: FieldAccess { - object: Var( - Id( - "step", - ), - ), - field: Var( - Id( - "handle", - ), - ), - }, - }, - Assign { - id: Id( - "len", - ), - expr: MethodCall { - object: FieldAccess { - object: Var( - Id( - "sh", - ), - ), - field: Var( - Id( - "segment", - ), - ), - }, - method: Id( - "length", - ), - args: [], - }, - }, - If { - guard: FieldAccess { - object: Var( - Id( - "sh", - ), - ), - field: Var( - Id( - "orientation", - ), - ), - }, - if_block: Block { - stmts: [ - Assign { - id: Id( - "fw", - ), - expr: BinOpExpr { - lhs: Var( - Id( - "fw", - ), - ), - op: Add, - rhs: Var( - Id( - "len", - ), - ), - }, - }, - ], - }, - elif_block: None, - else_block: Some( - Block { - stmts: [ - Assign { - id: Id( - "bw", - ), - expr: BinOpExpr { - lhs: Var( - Id( - "bw", - ), - ), - op: Add, - rhs: Var( - Id( - "len", - ), - ), - }, - }, - ], - }, - ), - }, - ], - }, - }, - ], - ret: Some( - BinOpExpr { - lhs: Var( - Id( - "bw", - ), - ), - op: Gt, - rhs: Var( - Id( - "fw", - ), - ), - }, - ), - }, - ], -} diff --git a/pollen/tests/parse-out/overlap.expect b/pollen/tests/parse-out/overlap.expect deleted file mode 100644 index 11b124b5..00000000 --- a/pollen/tests/parse-out/overlap.expect +++ /dev/null @@ -1,147 +0,0 @@ -Prog { - imports: [], - func_defs: [ - FuncDef { - name: Id( - "overlap", - ), - args: [], - ret_typ: None, - stmts: [ - ParsetDecl { - id: Id( - "out_overlaps", - ), - typ: Tuple( - Path, - Path, - ), - graph_id: None, - }, - For { - id: Id( - "path", - ), - iterator: Var( - Id( - "paths", - ), - ), - body: Block { - stmts: [ - For { - id: Id( - "step", - ), - iterator: FieldAccess { - object: Var( - Id( - "path", - ), - ), - field: Var( - Id( - "steps", - ), - ), - }, - body: Block { - stmts: [ - For { - id: Id( - "s", - ), - iterator: FieldAccess { - object: FieldAccess { - object: FieldAccess { - object: Var( - Id( - "step", - ), - ), - field: Var( - Id( - "handle", - ), - ), - }, - field: Var( - Id( - "segment", - ), - ), - }, - field: Var( - Id( - "steps", - ), - ), - }, - body: Block { - stmts: [ - If { - guard: BinOpExpr { - lhs: FieldAccess { - object: Var( - Id( - "s", - ), - ), - field: Var( - Id( - "path", - ), - ), - }, - op: Neq, - rhs: Var( - Id( - "path", - ), - ), - }, - if_block: Block { - stmts: [ - EmitTo { - expr: Tuple { - lhs: Var( - Id( - "path", - ), - ), - rhs: FieldAccess { - object: Var( - Id( - "s", - ), - ), - field: Var( - Id( - "path", - ), - ), - }, - }, - set_id: Id( - "out_overlaps", - ), - }, - ], - }, - elif_block: None, - else_block: None, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - ], - ret: None, - }, - ], -} diff --git a/pollen/tests/parse-out/paths.expect b/pollen/tests/parse-out/paths.expect deleted file mode 100644 index d06374c0..00000000 --- a/pollen/tests/parse-out/paths.expect +++ /dev/null @@ -1,101 +0,0 @@ -Prog { - imports: [], - func_defs: [ - FuncDef { - name: Id( - "emit_paths", - ), - args: [], - ret_typ: None, - stmts: [ - ParsetDecl { - id: Id( - "out_paths", - ), - typ: Tuple( - Step, - Step, - ), - graph_id: None, - }, - For { - id: Id( - "path", - ), - iterator: Var( - Id( - "Paths", - ), - ), - body: Block { - stmts: [ - EmitTo { - expr: Tuple { - lhs: ArrayAccess { - expr: FieldAccess { - object: Var( - Id( - "path", - ), - ), - field: Var( - Id( - "steps", - ), - ), - }, - idx: Integer( - 0, - ), - }, - rhs: ArrayAccess { - expr: FieldAccess { - object: Var( - Id( - "path", - ), - ), - field: Var( - Id( - "steps", - ), - ), - }, - idx: BinOpExpr { - lhs: MethodCall { - object: FieldAccess { - object: Var( - Id( - "path", - ), - ), - field: Var( - Id( - "steps", - ), - ), - }, - method: Id( - "size", - ), - args: [], - }, - op: Sub, - rhs: Integer( - 1, - ), - }, - }, - }, - set_id: Id( - "out_paths", - ), - }, - ], - }, - }, - ], - ret: None, - }, - ], -} diff --git a/pollen/tests/paths.pol b/pollen/tests/paths.pol deleted file mode 100644 index a23b7c06..00000000 --- a/pollen/tests/paths.pol +++ /dev/null @@ -1,14 +0,0 @@ -// Since Pollen doesn't explicitly have path identifiers, -// we print the start and end steps of each path -// (akin to `odgi paths --idx = graph.og --list-paths --list-paths-start-end`). -// See https://odgi.readthedocs.io/en/latest/rst/commands/odgi_paths.html -// for more options for the `paths` command. - -// Output is a (Step, Step) set. -outset out_paths[(Step, Step)]; - -for path in Paths { - emit (path.steps[0], - path.steps[path.steps.size() - 1]) - to out_paths; -} \ No newline at end of file diff --git a/pollen/tests/paths.pollen b/pollen/tests/paths.pollen deleted file mode 100644 index af104ca8..00000000 --- a/pollen/tests/paths.pollen +++ /dev/null @@ -1,16 +0,0 @@ -def emit_paths() { - // Since Pollen doesn't explicitly have path identifiers, - // we print the start and end steps of each path - // (akin to `odgi paths --idx = graph.og --list-paths --list-paths-start-end`). - // See https://odgi.readthedocs.io/en/latest/rst/commands/odgi_paths.html - // for more options for the `paths` command. - - // Output is a (Step, Step) set. - parset out_paths[(Step*Step)]; - - for path in Paths { - emit ( path.steps[0], - path.steps[path.steps.size() - 1]) - to out_paths; - } -} \ No newline at end of file diff --git a/pollen/tests/test1.txt b/pollen/tests/test1.txt deleted file mode 100644 index a1f6c68d..00000000 --- a/pollen/tests/test1.txt +++ /dev/null @@ -1,192 +0,0 @@ -// This is a comment. It does not get parsed - -import lib1; -import lib2 as library2; -from lib3 import f1; -from lib4 import f1 as f1', f2 as f2'; - -def test1() { - // Integer literals - i: int = 3; - id': int = 4; - i: int = -3; - i: int = +2; - - // Boolean literals - bool1: bool = true; - b2: bool = false; - - i: int; - b: bool; - c: char; - n: Segment; - s: Step; - e: Edge; - str: String; - strand: Strand; - b: Base; - - // Characters... oh boy here we go - - c1: char = 'a'; - c2 : char = 'b'; - c3 : char = '?'; - c_4 : char = 'n'; - c_5 : char = 't'; - - // Backspace characters - c8: char = '\\'; - c4: char = '\n'; - c5: char = '\t'; - c6: char = '\''; - c7: char = '\"'; - nother_char : char = '"'; - also_a_char : char = ' '; - - s1: String = "'"; - s2: String = "Hello world!"; - //Backspace strings - s2: String = "\\"; - s3: String = "\n"; - s4: String = "\t"; - s5: String = "\""; - empty_str : String = ""; - s6: String = "Hello world!\n"; - - binop : int = i + id2; - blskdf_ : int = 3 - (-5); - binop2: int = i * 1; - sdf:char = 9 / 3; - n: Segment = 5 % 2; - b: Step = 2 < 3; - TTTT: Strand = 5 > true; - b: Step = (2 <= 3); - TTTT: Strand = 5 >= true; - b: Step = 2 == 3; - TTTT: Strand = 5 != true; - string : Strand = !true && !(!false); - boolean : bool = false || (true && !false); - - // Parenthesis - TTTT : Strand = (5 != true); - TTTT : Strand = [5 != true]; - - /* - and = { "&&" } - or = { "||" } - */ - - SD : bool = !(true); - - // Parenthesis - int1 : int = 3 * (2 + 4); - int1 : int = [3 * (2 + 4)]; - - // Reassignment - a = 3; - - // Block Statements - - { - n: Segment = 5 % 2; - b: Step = 2 < 3; - } - - { - ans = 42; - } - - // Graph and Parset declarations - graph out_g; - parset out_segs[Segment, out_g]; - parset depth[int]; - - /* --- Control Flow --- */ - - // If statements - if b { - a = 1; - } - - if b { a = -1; } else { a = 0; } - - if b2 { - a = 2; - } elif b3 { c = 4; } - - if guard1 { - l = 0; - } elif guard2 { - l = 1; - } elif guard3 { - l = 2; - } - - if true { - ans = 0; - } elif false { - ans = 1; - } elif b3 { - // unreachable - ans = 2; - } else { - ans = 3; - } - - // while loops - while e { - a = a.b + 1; - } - - // for loops - for s in node.step { - depth = depth + 1; - } - - /* --- Records --- */ - step : Step = node.step; - node : Segment = Segment { sequence: sequence, steps: steps' }; - record2 : int = { record1 with B: "Hard Times" }; - - // Field Access - i: int = 3.field; - f: int = (Segment { num : 4 }).num; - - /* --- Complex Types --- */ - s: Set; - - tuple1: (int*bool); - tuple2: (Segment*bool) = (node, true); - - /* --- Emit Statements --- */ - emit 5 to s; - emit 2 * 3 to s1; - emit { node with seq: seq' } to s2; - - /* --- Calls --- */ - // Object initialization - new_strand: Strand = Strand(); - c: char = String().first; - // Function Calls - v1: int = funct1(arg1); - v2: bool = func2(a1, a2); - v3: Segment = fun3(fun'(a), b); - - // Method Calls - v4: Strand = new_strand.push('A'); - v5: int = (int { record: true }).method(); - - // Function Calls - f1(); - f2(arg1); - f3(5, f2(true)); - func_id(arg1, arg2); - // Method Calls - obj.method(); - obj.inner.method(arg1); - 4.meth(); -} - -def func2(arg1: int) -> int { - return arg1; -} \ No newline at end of file diff --git a/pollen/types.md b/pollen/types.md deleted file mode 100644 index 953132c0..00000000 --- a/pollen/types.md +++ /dev/null @@ -1,45 +0,0 @@ -# Core types in Pollen - -Below is a user reference for key types and data structures in the Pollen language. - - type Graph = { - segments: Set; - paths: Set; - links: Set; - } - - type Segment = { - sequence: Strand; //ACTGAC, etc. - links: Set; //links encode their direction + orientation - steps: Set; //steps that go through segment - } - - type Handle = { - segment: Segment; - orientation: bool; - } - - type Path = { - steps: List; - } - - type Step = { - path: Path; - idx: int; //where in the path is this sequence? - handle: Handle; //segment + orientation - } - - enum Base = { - A, - C, - T, - G, - N, - } - type Strand = List; - - type Link = { - start: Handle; - end: Handle; - } - \ No newline at end of file