mirror of
https://github.com/Nexoniarz/Finch.git
synced 2026-11-03 08:54:25 +00:00
Finch 2.4.0: methods, maps, errors as values; str() of any value; macOS and ARM64 docs; Kate support
- fn Struct.method(...) with self by reference, also on C structs
- map[K]V: insertion-ordered hash maps, literals, m[k] += 1, has/get/remove/keys/values
- -> T! / -> !, return error(...), or <value>, or { err }, try; fallible int/float/read_file/write_file/delete_file
- for i, x in list / for k, v in map
- print and str() share one text formatter
- LSP: method and map completion, method signatures; grammar and snippets for VS Code and Kate
- tests: 74 (methods, errors, maps + 11 failure cases); docs at all three levels, en and pl
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
fd86eb885c
commit
b872be3176
55 changed files with 3400 additions and 336 deletions
86
tests/run/errors.fch
Normal file
86
tests/run/errors.fch
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
struct Config {
|
||||
str name
|
||||
int port = 8080
|
||||
}
|
||||
|
||||
fn parse_port(str text) -> int! {
|
||||
n := int(text) or { return error("the port '" + text + "' is not a number") }
|
||||
if n < 1 || n > 65535 {
|
||||
return error("the port " + str(n) + " is out of range")
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
fn parse_config(str line) -> Config! {
|
||||
parts := line.split("=")
|
||||
if parts.len != 2 {
|
||||
return error("expected name=port, got '" + line + "'")
|
||||
}
|
||||
port := try parse_port(parts[1].trim()) // a failure here fails parse_config too
|
||||
return Config(parts[0].trim(), port)
|
||||
}
|
||||
|
||||
fn save(str path, str text) -> ! {
|
||||
if path.len == 0 {
|
||||
return error("no file name")
|
||||
}
|
||||
try write_file(path, text)
|
||||
}
|
||||
|
||||
struct Account {
|
||||
int balance
|
||||
}
|
||||
|
||||
fn Account.withdraw(int amount) -> ! {
|
||||
if amount > self.balance {
|
||||
return error("not enough money: " + str(self.balance) + " < " + str(amount))
|
||||
}
|
||||
self.balance -= amount
|
||||
}
|
||||
|
||||
fn first_number([]str words) -> int! {
|
||||
for w in words {
|
||||
n := int(w) or { continue }
|
||||
return n
|
||||
}
|
||||
return error("no numbers")
|
||||
}
|
||||
|
||||
fn main() -> ! {
|
||||
print(parse_port("80") or 0)
|
||||
print(parse_port("abc") or -1)
|
||||
print(parse_port("99999") or -1)
|
||||
|
||||
for line in ["web = 80", "db=5432", "bad", "x = y", "big = 70000"] {
|
||||
c := parse_config(line) or {
|
||||
print("skipped:", err)
|
||||
continue
|
||||
}
|
||||
print(c)
|
||||
}
|
||||
|
||||
print(int("12") or 0, int(" 7 ") or 0, int("seven") or 0, float("2.5") or 0, float("") or -1.0)
|
||||
|
||||
text := read_file("does/not/exist.txt") or "default text"
|
||||
print(text)
|
||||
read_file("does/not/exist.txt") or { print("read failed:", err.starts_with("can't read the file")) }
|
||||
|
||||
save("", "x") or { print("save failed:", err) }
|
||||
try save("errors_tmp.txt", "saved")
|
||||
print(try read_file("errors_tmp.txt"))
|
||||
try delete_file("errors_tmp.txt")
|
||||
delete_file("errors_tmp.txt") or { print("second delete failed") }
|
||||
|
||||
a := Account(100)
|
||||
a.withdraw(30) or { print("no") }
|
||||
a.withdraw(500) or { print(err) }
|
||||
print(a.balance)
|
||||
|
||||
print(first_number(["a", "b", "42", "7"]) or 0, first_number(["x"]) or -1)
|
||||
|
||||
// nested: the fallback can be another call that may fail
|
||||
print(parse_port("x") or parse_port("443") or 0)
|
||||
|
||||
try parse_port("not a port") // main fails: prints the error, exit code 1
|
||||
print("never printed")
|
||||
}
|
||||
Loading…
Reference in a new issue