{"id":20112278,"url":"https://github.com/swiftaff/toylang","last_synced_at":"2025-03-02T18:42:07.231Z","repository":{"id":38775668,"uuid":"499525935","full_name":"Swiftaff/toylang","owner":"Swiftaff","description":"A functional toy language using Polish Notation which compiles to Rust for fun and experimentation.","archived":false,"fork":false,"pushed_at":"2023-06-01T10:41:53.000Z","size":2948,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-13T05:44:27.055Z","etag":null,"topics":["compiler","debugger","functional-language","language","polish-notation","prefix-notation","programming-language","rust","rust-lang","rust-library","toy","toy-language","toy-project","windows"],"latest_commit_sha":null,"homepage":"https://swiftaff.github.io/toylang/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Swiftaff.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-03T13:40:54.000Z","updated_at":"2023-05-02T12:54:11.000Z","dependencies_parsed_at":"2024-11-13T18:30:25.798Z","dependency_job_id":null,"html_url":"https://github.com/Swiftaff/toylang","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Swiftaff%2Ftoylang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Swiftaff%2Ftoylang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Swiftaff%2Ftoylang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Swiftaff%2Ftoylang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Swiftaff","download_url":"https://codeload.github.com/Swiftaff/toylang/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241556731,"owners_count":19981874,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compiler","debugger","functional-language","language","polish-notation","prefix-notation","programming-language","rust","rust-lang","rust-library","toy","toy-language","toy-project","windows"],"created_at":"2024-11-13T18:19:38.546Z","updated_at":"2025-03-02T18:42:07.207Z","avatar_url":"https://github.com/Swiftaff.png","language":"Rust","readme":"\u003cimg align=\"left\" width=\"80\" alt=\"Toylang\" src=\"./icon.png\"\u003e\n\u003ch1\u003eToylang\u003c/h1\u003e\n\nA functional toy language using Polish Notation / Prefix Notation which compiles to Rust for fun and experimentation (Windows only for now)\n\nWork in progress [VS Code Extension](https://github.com/Swiftaff/toylang-vscode)\n\nRustdocs [documentation](https://swiftaff.github.io/toylang/toylang/index.html)\n\nCustom [Debugger](#debugger)\n\n## Build\n\nBuilds the `/src/main.rs` into an executable at `/target/debug/toylang.exe` or `/target/release/toylang.exe`\n\n```\ncargo build\n```\n\nor\n\n```\ncargo build --release\n```\n\n## Usage\n\nCreate a file e.g. `test.toy` containing the toy language in the same directory (or elsewhere).\n\nPass the required input filepath using the input arg (-i or --input)\n\nPass the optional output directory using the output arg (-o or --output). Otherwise by default `output.rs` is saved into the current directory.\nFor development you may wish to output to `src\\\\bin` by convention to make use of `cargo run --bin output` below.\n\n```\ntoylang -i test.toy\n```\n\nor\n\n```\ntoylang.exe --input ..\\\\..\\\\somewhere\\\\else\\\\test.toy --output src\\\\bin\n```\n\nCompile errors will appear in the console.\n\n```\nTOYLANG COMPILE ERROR:\n----------\n= monkey monkeys\n         ^^^^^^^ is not a valid expression: must be either an: integer, e.g. 12345, float, e.g. 123.45, existing constant, e.g. x, string, e.g. \"string\", function, e.g. + 1 2\n----------\n= monkey monkeys\n^ No valid expression was found\n----------\n```\n\nOr on success a compiled `output.rs` file will be saved to the output directory.\n\nYou can then build THAT file with cargo as needed, i.e. output to `src\\\\bin` and add this to the \"Cargo.toml\"\n\n```\n[[bin]]\nname = \"output\"\n```\n\nThen compile and run the output file\n\n```\ncargo run --bin output\n```\n\nor\n\n```\ncargo run --release --bin output\n```\n\nAnd your final compiled `output.exe` will be saved to, and run from `\\\\target\\\\debug` or `\\\\target\\\\release`\n\n## Debugger\n\nPass the debug flag (-d or --debug) to open an interactive debugger which steps through the state of the Compiler's AST to troublshoot compilation errors.\n\n```\ntoylang -i test.toy -d\n```\n\n![Interactive Debugger](interactive-debugger.gif)\n\n## Toy language Syntax Examples\n\n### Hello, world\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003eToy\u003c/th\u003e\u003cth\u003eRust\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\n\n```\n\n// print\n@ \"Hello, world!\"\n@ 1\n@ 1.23\n\n```\n\n\u003c/td\u003e\u003ctd\u003e\n\n```rust\nfn main() {\n    // print\n    println!(\"{}\", \"Hello, world!\".to_string());\n    println!(\"{}\", 1);\n    println!(\"{}\", 1.23);\n}\n```\n\n\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n### Constant assignment\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003eToy\u003c/th\u003e\u003cth\u003eRust\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\n\n```\n\n// single line comments\n// assign values to constants\n= an_integer 123\n= a_float 123.45\n= a_reference an_integer\n= a_string \"string\"\n\n// basic arithmetic built in functions\n= addition + 1 2\n= subtraction - 5.4 3.2\n= multiplication * 3 4\n= division / 1.0 2.0\n= modulus % 42.0 3.14\n\n// booleans and equality\n= is_true true\n= is_false false\n// the below constants are all assigned the value true\n= equal == 1 1\n= not_equal != 1 2\n= greater_than \u003e 2 1\n= less_than \u003c 1 2\n= gte \u003e= 2 1\n= lte \u003c= 1 2\n\n// if expressions\n= a ? true \"true\" \"false\"\n= b ? is_true \"true\" \"false\"\n= c ? \u003c 1 2 \"true\" \"false\"\n\n= get_true \\ bool =\u003e true\n\n\n= d ? get_true \"true\" \"false\"\n\n= get_truer \\ i64 bool arg1 =\u003e \u003e arg1 5\n\n\n= e ? get_truer 10 \"true\" \"false\"\n\n= get_more_true \\ i64 i64 i64 bool arg1 arg2 arg3 =\u003e\n  \u003c + arg1 + arg2 arg3 10\n\n= f ? get_more_true 1 2 3 \"true\" \"false\"\n\n```\n\n\u003c/td\u003e\u003ctd\u003e\n\n```rust\nfn main() {\n    // single line comments\n    // assign values to constants\n    let an_integer: i64 = 123;\n    let a_float: f64 = 123.45;\n    let a_reference: i64 = an_integer;\n    let a_string: String = \"string\".to_string();\n\n    // basic arithmetic built in functions\n    let addition: i64 = 1 + 2;\n    let subtraction: f64 = 5.4 - 3.2;\n    let multiplication: i64 = 3 * 4;\n    let division: f64 = 1.0 / 2.0;\n    let modulus: f64 = 42.0 % 3.14;\n\n    // booleans and equality\n    let is_true: bool = true;\n    let is_false: bool = false;\n    // the below constants are all assigned the value true\n    let equal: bool = 1 == 1;\n    let not_equal: bool = 1 != 2;\n    let greater_than: bool = 2 \u003e 1;\n    let less_than: bool = 1 \u003c 2;\n    let gte: bool = 2 \u003e= 1;\n    let lte: bool = 1 \u003c= 2;\n\n    // if expressions\n    let a = if true { \"true\" } else { \"false\" };\n    let b = is_true { \"true\" } else { \"false\" };\n    let c = 1 \u003c 2 { \"true\" } else { \"false\" };\n\n    fn get_true() -\u003e bool {\n        true\n    }\n    let d = get_true() { \"true\" } else { \"false\" };\n\n    fn get_truer(arg1: i64) -\u003e bool {\n        arg1 \u003e 5\n    }\n    let e = get_truer(10) { \"true\" } else { \"false\" };\n\n    fn get_more_true(arg1: i64, arg2: i64, arg3: i64) -\u003e bool {\n        arg1 + arg2 + arg3 \u003c 10\n    }\n    let f = get_more_true(1, 2, 3) { \"true\" } else { \"false\" }\n}\n```\n\n\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n### Function definition\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003eToy\u003c/th\u003e\u003cth\u003eRust\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\n\n```\n\n// single line functions\n// one i64 argument, returns i64\n= function_name \\ i64 i64 arg1 =\u003e + 123 arg1\n//                ^       ^       ^_return expression\n//                 \\       \\_ argument names\n//                  \\_argument types, return type last\n\n\n\n// multi line functions\n// two i64 arguments, returns i64\n= multiline_fn_name \\ i64 i64 i64 arg1 arg2 =\u003e\n= x + arg1 123\n= y - x arg2\n= z * y 10\n\n// z is the first expression\n// (not an assignment) so it is\n// the return value of the function\nz\n\n\n// use parenthesis to pass a function\n// as an argument - becomes a \u0026dyn Fn\n// first argument in parenthesis defines\n// a single argument which is a function\n// which takes an i64 and returns an i64\n// second argument is an i64\n// and function returns an i64\n= take_fn_as_first_parameter \\ (i64 i64) i64 i64 arg1 arg2 =\u003e\n\n// then the function body calls the\n// arg1 with arg2 as the parameter\narg1 arg2\n\n\n// function calls\nfunction_name 123\nmultiline_fn_name + 123 456 789\n\n// also when passing a function as a parameter\n// must wrap it in parenthesis so it doesn't evaluate\ntake_fn_as_first_parameter ( function_name ) 321\n\n\n// fibonacci Example\n= fibonacci \\ i64 i64 n =\u003e ? \u003c n 2 1 + fibonacci - n 1 fibonacci - n 2\n@ fibonacci 10\n\n\n\n\n\n\n\n\n\n\n```\n\n\u003c/td\u003e\u003ctd\u003e\n\n```rust\nfn main() {\n    // single line functions\n    fn function_name(arg1: i64) -\u003e i64 {\n        123 + arg1\n    }\n\n\n\n\n\n    // multi line functions\n    // two i64 arguments, returns i64\n    fn multiline_fn_name(arg1: i64, arg2: i64) -\u003e i64 {\n        let x: i64 = arg1 + 123;\n        let y: i64 = x - arg2;\n        let z: i64 = y * 10;\n\n        // z is the first expression\n        // (not an assignment) so it is\n        // the return value of the function\n        z\n    }\n\n    // use parenthesis to pass a function\n    // as an argument - becomes a \u0026dyn Fn\n    // first argument in parenthesis defines\n    // a single argument which is a function\n    // which takes an i64 and returns an i64\n    // second argument is an i64\n    // and function returns an i64\n    fn take_fn_as_first_parameter(arg1: \u0026dyn Fn(i64) -\u003e i64, arg2: i64) -\u003e i64 {\n\n        // then the function body calls the\n        // arg1 with arg2 as the parameter\n        arg1(arg2)\n    }\n\n    // function calls\n    function_name(123);\n    multiline_fn_name(123 + 456, 789);\n\n    // also when passing a function as a parameter\n    // must wrap it in parenthesis so it doesn't evaluate\n    take_fn_as_first_parameter(\u0026function_name, 321);\n\n\n    // fibonacci example\n    fn main() {\n        fn fibonacci(n: i64) -\u003e i64 {\n            if n \u003c 2 {\n                1\n            } else {\n                fibonacci(n - 1) + fibonacci(n - 2)\n            }\n        }\n        println!(\"{}\", fibonacci(10));\n    }\n\n}\n```\n\n\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n### Lists\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003eToy\u003c/th\u003e\u003cth\u003eRust\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\n\n```\n\n// empty Lists\n= empty1 [ i64 ]\n= empty2 [ f64 ]\n\n// list of Ints\n= ints [ 1 2 3 4 5 ]\n\n// list of floats\n= floats [ 1.1 2.2 3.3 ]\n\n// list of strings\n= strings [ \"1\" \"2\" \"3\" ]\n\n// map\n= list [ 1 ]\n= mapfn \\ i64 i64 i =\u003e * i 100\n\n\n= mapped List::map list ( mapfn )\n\n// append\n= list1 [ 1 ]\n= list2 [ 2 3 ]\n= appended List::append list1 list2\n\n// len\n= list [ 1 2 3 ]\n= len List::len list\n\n```\n\n\u003c/td\u003e\u003ctd\u003e\n\n```rust\nfn main() {\n    // empty lists\n    let empty1: Vec\u003ci64\u003e = vec![];\n    let empty2: Vec\u003cf64\u003e = vec![];\n\n    // list of Ints\n    let ints = vec![ 1, 2, 3 ];\n\n    // list of floats\n    let floats = vec![ 1.1, 2.2, 3.3];\n\n    // list of strings\n    let strings = vec![ \"1\".to_string(), \"2\".to_string(), \"3\".to_string() ];\n\n    // map\n    let list: Vec\u003ci64\u003e = vec![ 1 ];\n    fn mapfn(i: i64) -\u003e i64 {\n        i * 100\n    }\n    let mapped: Vec\u003ci64\u003e = list.iter().map(mapfn).collect();\n\n    // append\n    let list1: Vec\u003ci64\u003e = vec![ 1 ];\n    let list2: Vec\u003ci64\u003e = vec![ 2 3 ];\n    let appended: Vec\u003ci64\u003e = list1.iter().cloned().chain(list2.iter().cloned()).collect();\n\n    // len\n    let list: Vec\u003ci64\u003e = [1, 2, 3];\n    let len: i64 = list.len() as i64;\n}\n```\n\n\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n### Structs\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003eToy\u003c/th\u003e\u003cth\u003eRust\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\n\n```\n// Define a struct\n= newstruct { = firstname \"firstname\" = surname \"surname\" = age 21 }\n\n// Or, using short notation using ConstantRefs\n// = firstname \"firstname\"\n// = surname \"surname\"\n// = age 21\n// = newstruct { firstname surname age }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n//Edit a struct\n= newstruct.age 99\n\n//Print (debug) a full struct\n@ newstruct\n//\n```\n\n\u003c/td\u003e\u003ctd\u003e\n\n```rust\n// Define a struct\n#[derive(Clone, Debug)]\npub struct Newstruct {\n    pub firstname: String,\n    pub surname: String,\n    pub age: i64,\n}\n\nimpl Newstruct {\n    pub fn new(firstname: String, surname: String, age: i64) -\u003e Newstruct {\n        Newstruct {\n            firstname,\n            surname,\n            age,\n        }\n    }\n}\n\nfn main() {\n    let mut newstruct: Newstruct = Newstruct::new(\"firstname\".to_string(), \"surname\".to_string(), 21);\n\n    //Edit a struct\n    newstruct.age = 99;\n\n    //Print (debug) a full struct\n    println!(\"{:?}\", \u0026newstruct);\n}\n```\n\n\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswiftaff%2Ftoylang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswiftaff%2Ftoylang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswiftaff%2Ftoylang/lists"}