Use square brackets for arrays

master
Araozu 2024-01-01 09:11:41 -05:00
parent e2119b135b
commit 2cab819c40
8 changed files with 144 additions and 115 deletions

View File

@ -1,23 +1,21 @@
# Arrays # Arrays
No destructuring (for now?). There's no `[]` syntax Use square brackets as usual.
for constructing arrays
## Usage ## Usage
```thp ```thp
let fruits = Array("apple", "banana", "cherry") let fruits = ["apple", "banana", "cherry"]
let apple = fruits.[0] let apple = fruits[0]
print(apple) 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] 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.

View File

@ -5,7 +5,7 @@
Braces are required. Braces are required.
```thp ```thp
let numbers = Array(0, 1, 2, 3) let numbers = [0, 1, 2, 3]
for number in numbers for number in numbers
{ {
@ -20,9 +20,9 @@ for #(index, number) in numbers.entries()
```thp ```thp
let dict = Obj { let dict = Obj {
"apple": 10, apple: 10,
"banana": 7, banana: 7,
"cherries": 3, cherries: 3,
} }
for #(key, value) in dict for #(key, value) in dict
@ -45,12 +45,12 @@ for value in collection
## While loop ## While loop
```thp ```thp
let colors = Array("red", "green", "blue") let colors = ["red", "green", "blue"]
let mut index = 0 let mut index = 0
while index < colors.size() while index < colors.size()
{ {
print("{colors.[index]}") print("{colors[index]}")
index += 1 index += 1
} }
``` ```

View File

@ -41,7 +41,7 @@ let number = get_secure_random_number(0, 65535)
```thp ```thp
fun get_first_item[T](Array[T] array) -> T fun get_first_item[T](Array[T] array) -> T
{ {
array.[0] array[0]
} }
let first = get_first_item[Int](numbers) 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 ## Named arguments with different names
```thp ```thp
fun replace( fun greet(
String in: input, String name,
String each: pattern, String from: city,
String with: replacement, )
) -> String
{ {
// Use input, pattern and replacement print("Hello {name} from {city}!")
} }
replace(each: " ", in: "my name", with: "-") greet(name: "John", from: "LA")
``` ```

View File

@ -24,7 +24,7 @@ By default closures **always** capture variables as **references**.
```thp ```thp
let mut x = 20 let mut x = 20
val f = fun() { let f = fun() {
print(x) print(x)
} }
@ -46,7 +46,7 @@ fun(parameters) clone(variables) {
```thp ```thp
let mut x = 20 let mut x = 20
val f = fun() clone(x) { let f = fun() clone(x) {
print(x) print(x)
} }
@ -62,7 +62,7 @@ f() // 20
```thp ```thp
numbers.map { numbers.map {
it * 2 $0 * 2
} }
``` ```

View File

@ -24,21 +24,21 @@ fun count(Array[Int] numbers) -> Int {
## Mutable reference ## Mutable reference
```thp ```thp
fun push_25(&Array[Int] numbers) { fun push_25(mut Array[Int] numbers) {
numbers.push(25) // Ok, will also mutate the original array 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 reference. Mutable methods can be used, and the original
data **can** be mutated. data **can** be mutated.
The caller *must* also use `&`. The caller *must* also use `mut`.
```thp ```thp
let numbers = Array(0, 1, 2, 3) 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)` print(numbers(4)) // `Some(25)`
``` ```
@ -60,7 +60,7 @@ of the parameter (CoW). The original data will **not** be mutated.
```thp ```thp
let numbers = Array(1, 2, 3, 4) 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 print(numbers(4)) // None
``` ```

View File

@ -199,3 +199,53 @@ let f1 = add1 >> times2
f1(5) // 12 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]()
}
```

View File

@ -55,7 +55,7 @@ These are **not** aspects that THP looks to solve or implement.
$has_key = str_contains($haystack, 'needle'); $has_key = str_contains($haystack, 'needle');
// THP // THP
val has_key = haystack.contains("needle") let has_key = haystack.contains("needle")
``` ```
- Explicit variable declaration - Explicit variable declaration
@ -93,7 +93,7 @@ $cat = new Cat("Michifu", 7);
$cat->meow(); $cat->meow();
// THP // THP
val cat = Cat("Michifu", 7) let cat = Cat("Michifu", 7)
cat.meow(); cat.meow();
``` ```
@ -113,8 +113,9 @@ use Some::Deeply::Nested::{Class, Interface}
``` ```
- Different module syntax - Different module syntax
- Explicit module declaration
- PSR-4 required - PSR-4 required
- No `include` or `require` - No `include`, `include_once`, `require` or `require_once`
--- ---
@ -124,93 +125,69 @@ Other things:
- ADTs - 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 ```thp
// ===== current ======= // This expression
val name = "John" let greeting =
var name = "John" match get_person()
| Some(person) if person.age > 18
String name = "John" {
var String name = "John" "Welcome, {person.name}"
}
| Some(person)
{
// ===== new? ======= "I'm sorry {person.name}, you need to be 18 or older"
let name = "John" }
let mut name = "John" | None
{
String name = "John" "Nobody is here"
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"}
*/
} }
set_empty(mut obj)
print(obj) // Obj {name: "John"} // Would compile to:
$greeting = null;
``` $_person = get_person();
if ($_person !== null) {
if ($_person["age"] > 18) {
$greeting = "Welcome, " . $_person["name"];
## 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 { else {
die("All 3 db environment variables must be set.") $greeting = "I'm sorry " . $_person["name"] . ", you need to be 18 or older";
}
}
else {
$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

View File

@ -15,7 +15,7 @@ Prism.languages.thp = {
pattern: /(["])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, pattern: /(["])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
greedy: true, 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, "number": /\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,
"operator": /[<>]=?|[!=]=?=?|--?|\$|\+\+?|&&?|\|\|?|[?*/~^%]/, "operator": /[<>]=?|[!=]=?=?|--?|\$|\+\+?|&&?|\|\|?|[?*/~^%]/,
"punctuation": /[{}[\];(),.]/, "punctuation": /[{}[\];(),.]/,