From 2cab819c40aa4046eaeec14e3b987a37b313047a Mon Sep 17 00:00:00 2001 From: Araozu Date: Mon, 1 Jan 2024 09:11:41 -0500 Subject: [PATCH] Use square brackets for arrays --- md/learn/collections/arrays.md | 17 ++-- md/learn/flow-control/loops.md | 12 +-- md/learn/functions/declaration.md | 19 ++-- md/learn/functions/lambdas.md | 6 +- md/learn/functions/parameters.md | 10 +-- md/learn/ideas/idea_1.md | 50 +++++++++++ md/learn/index.md | 143 +++++++++++++----------------- static/js/prism.thp.js | 2 +- 8 files changed, 144 insertions(+), 115 deletions(-) diff --git a/md/learn/collections/arrays.md b/md/learn/collections/arrays.md index a91c975..e2d15f4 100644 --- a/md/learn/collections/arrays.md +++ b/md/learn/collections/arrays.md @@ -1,23 +1,21 @@ # Arrays -No destructuring (for now?). There's no `[]` syntax -for constructing arrays +Use square brackets as usual. ## Usage ```thp -let fruits = Array("apple", "banana", "cherry") -let apple = fruits.[0] +let fruits = ["apple", "banana", "cherry"] +let apple = fruits[0] print(apple) -let mut numbers = Array(0, 1, 2, 3) +let mut numbers = [0, 1, 2, 3] -// Note the dot -numbers.[3] = 5 +numbers[3] = 5 -print(numbers.[3]) // 5 +print(numbers[3]) // 5 ``` @@ -29,6 +27,9 @@ Array[String] Array[Int] ``` +The Array signature __requires__ the word `Array`. +There is no `Int[]` or `[Int]` signature, since that would cause +problems with the language's grammar. diff --git a/md/learn/flow-control/loops.md b/md/learn/flow-control/loops.md index 96c7c64..29bd095 100644 --- a/md/learn/flow-control/loops.md +++ b/md/learn/flow-control/loops.md @@ -5,7 +5,7 @@ Braces are required. ```thp -let numbers = Array(0, 1, 2, 3) +let numbers = [0, 1, 2, 3] for number in numbers { @@ -20,9 +20,9 @@ for #(index, number) in numbers.entries() ```thp let dict = Obj { - "apple": 10, - "banana": 7, - "cherries": 3, + apple: 10, + banana: 7, + cherries: 3, } for #(key, value) in dict @@ -45,12 +45,12 @@ for value in collection ## While loop ```thp -let colors = Array("red", "green", "blue") +let colors = ["red", "green", "blue"] let mut index = 0 while index < colors.size() { - print("{colors.[index]}") + print("{colors[index]}") index += 1 } ``` diff --git a/md/learn/functions/declaration.md b/md/learn/functions/declaration.md index 43c0a06..3e516c7 100644 --- a/md/learn/functions/declaration.md +++ b/md/learn/functions/declaration.md @@ -41,7 +41,7 @@ let number = get_secure_random_number(0, 65535) ```thp fun get_first_item[T](Array[T] array) -> T { - array.[0] + array[0] } let first = get_first_item[Int](numbers) @@ -75,22 +75,23 @@ fun html_special_chars( // ... } -html_special_chars(input, double_encode: false) +html_special_chars(input, double_encoding: false) ``` +TBD: If & how named arguments affect the order of the parameters + ## Named arguments with different names ```thp -fun replace( - String in: input, - String each: pattern, - String with: replacement, -) -> String +fun greet( + String name, + String from: city, +) { - // Use input, pattern and replacement + print("Hello {name} from {city}!") } -replace(each: " ", in: "my name", with: "-") +greet(name: "John", from: "LA") ``` diff --git a/md/learn/functions/lambdas.md b/md/learn/functions/lambdas.md index 36c22de..921cae1 100644 --- a/md/learn/functions/lambdas.md +++ b/md/learn/functions/lambdas.md @@ -24,7 +24,7 @@ By default closures **always** capture variables as **references**. ```thp let mut x = 20 -val f = fun() { +let f = fun() { print(x) } @@ -46,7 +46,7 @@ fun(parameters) clone(variables) { ```thp let mut x = 20 -val f = fun() clone(x) { +let f = fun() clone(x) { print(x) } @@ -62,7 +62,7 @@ f() // 20 ```thp numbers.map { - it * 2 + $0 * 2 } ``` diff --git a/md/learn/functions/parameters.md b/md/learn/functions/parameters.md index 9e77b76..fb607e4 100644 --- a/md/learn/functions/parameters.md +++ b/md/learn/functions/parameters.md @@ -24,21 +24,21 @@ fun count(Array[Int] numbers) -> Int { ## Mutable reference ```thp -fun push_25(&Array[Int] numbers) { +fun push_25(mut Array[Int] numbers) { numbers.push(25) // Ok, will also mutate the original array } ``` -Placing a `&` before the type makes the parameter a mutable +Placing a `mut` before the type makes the parameter a mutable reference. Mutable methods can be used, and the original data **can** be mutated. -The caller *must* also use `&`. +The caller *must* also use `mut`. ```thp let numbers = Array(0, 1, 2, 3) -push_25(&numbers) // Pass `numbers` as reference. +push_25(mut numbers) // Pass `numbers` as reference. print(numbers(4)) // `Some(25)` ``` @@ -60,7 +60,7 @@ of the parameter (CoW). The original data will **not** be mutated. ```thp let numbers = Array(1, 2, 3, 4) -add_25(numbers) // Pass `numbers` as clone. +add_25(clone numbers) // Pass `numbers` as clone. print(numbers(4)) // None ``` diff --git a/md/learn/ideas/idea_1.md b/md/learn/ideas/idea_1.md index dab5b65..cb35fec 100644 --- a/md/learn/ideas/idea_1.md +++ b/md/learn/ideas/idea_1.md @@ -199,3 +199,53 @@ let f1 = add1 >> times2 f1(5) // 12 ``` + + +```thp +function_call[Datatype](param1, param2) { + // lambda +} + +function_call([arr1, arr2]) +function_call[Datatype]([arr1, arr2]) + + +fun test[A, B](A a, B b) -> B {} + + +Array[String] v = 20 + +val x = Obj { + Array[Int] x: [1, 2, 3] +} + +value + [1, 2, 3] + +value + [Int] + + +value[0] + + +let functions = [ + {0}, + {1}, + {2}, +] + +let index = 0 + +functions[index]() + + + +``` + +```thp +fun main() +{ + // Using the turbofish operator + let result = "42".parse[Int]() +} +``` + diff --git a/md/learn/index.md b/md/learn/index.md index 5ce436a..4b548ac 100644 --- a/md/learn/index.md +++ b/md/learn/index.md @@ -55,7 +55,7 @@ These are **not** aspects that THP looks to solve or implement. $has_key = str_contains($haystack, 'needle'); // THP -val has_key = haystack.contains("needle") +let has_key = haystack.contains("needle") ``` - Explicit variable declaration @@ -93,7 +93,7 @@ $cat = new Cat("Michifu", 7); $cat->meow(); // THP -val cat = Cat("Michifu", 7) +let cat = Cat("Michifu", 7) cat.meow(); ``` @@ -113,8 +113,9 @@ use Some::Deeply::Nested::{Class, Interface} ``` - Different module syntax +- Explicit module declaration - PSR-4 required -- No `include` or `require` +- No `include`, `include_once`, `require` or `require_once` --- @@ -124,93 +125,69 @@ Other things: - ADTs -### Runtime changes +## Runtime changes -THP should add as little runtime as possible. +Where possible THP will compile to available PHP functions/classes/methods/etc. + +For example: ```thp -// ===== current ======= -val name = "John" -var name = "John" - -String name = "John" -var String name = "John" +// This expression +let greeting = + match get_person() + | Some(person) if person.age > 18 + { + "Welcome, {person.name}" + } + | Some(person) + { + "I'm sorry {person.name}, you need to be 18 or older" + } + | None + { + "Nobody is here" + } - -// ===== new? ======= -let name = "John" -let mut name = "John" - -String name = "John" -mut String name = "John" - - -// For primitive datatypes (Int, Float, Bool, String?) - -// Cloned -fun add(Int x) -// Still cloned, but the x **binding** can be mutated, not the original variable -fun add(mut Int x) -// Same as 1st -fun add(clone Int x) - - -// For other datatypes - -// Pass an immutable reference -fun add(Obj o) -// Pass a mutable reference -fun add(mut Obj o) -// Clone the argument -fun add(clone Obj o) - - -// Only references are passed, not "variables" (as PHP calls them) -let john = Obj {name: "John"} -/* - john --------> {name: "John"} -*/ - -fun set_empty(mut Obj person) { - /* - john ------┬--> {name: "John"} - person ----┘ - */ - - // This creates a **new** Obj, and the variable `person` now points to it. - person = Obj {name: "Alex"} - /* - john ---------> {name: "John"} - person -------> {name: "Alex"} - */ +// Would compile to: +$greeting = null; +$_person = get_person(); +if ($_person !== null) { + if ($_person["age"] > 18) { + $greeting = "Welcome, " . $_person["name"]; + } + else { + $greeting = "I'm sorry " . $_person["name"] . ", you need to be 18 or older"; + } } - -set_empty(mut obj) - -print(obj) // Obj {name: "John"} - -``` - - - -## Example - -```thp -use PDO -use Globals::Env - -val (Some(dbUri) Some(dbUser) Some(dbPassword)) = ( - Env::get("DB_URI") - Env::get("DB_USERNAME") - Env::get("DB_PASSWORD") -) else { - die("All 3 db environment variables must be set.") + $greeting = "Nobody is here"; } - -match PDO(dbUri dbUser dbPassword) -| Ok(connection) { /* db operations */ } -| Err(pdoException) { /* handle exception */ } ``` +However, more advanced datatypes & helper functions will require a sort of +runtime (new classes/functions/etc) or abuse the language's syntax/semantics. + + +```thp +// TBD: Enum compilation +enum IpAddress { + V4(String), + V6(String), +} + +let ip_1 = IpAddress::V4("255.255.0.0") + + +// Would possibly compile to: +enum IpAddress { + V4, + V6, +} + +$ip_1 = [IpAddress::V4, "255.255.0.0"] +``` + +Such changes will be documented + + diff --git a/static/js/prism.thp.js b/static/js/prism.thp.js index bbf6baa..487144e 100644 --- a/static/js/prism.thp.js +++ b/static/js/prism.thp.js @@ -15,7 +15,7 @@ Prism.languages.thp = { pattern: /(["])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, greedy: true, }, - "keyword": /\b(?:static|const|enum|loop|use|break|catch|continue|do|else|finally|for|fun|if|in|fn|nil|return|throw|try|while|type|match|with|of|abstract|class|interface|private|pub|obj|override|open|init|let|mut)\b/, + "keyword": /\b(?:static|const|enum|loop|use|break|catch|continue|do|else|finally|for|fun|if|in|fn|nil|return|throw|try|while|type|match|with|of|abstract|class|interface|private|pub|obj|override|open|init|let|mut|clone)\b/, "number": /\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i, "operator": /[<>]=?|[!=]=?=?|--?|\$|\+\+?|&&?|\|\|?|[?*/~^%]/, "punctuation": /[{}[\];(),.]/,