1
0
Fork 0
forked from fun/fun

Added a lot of stdlib's to lib/ and many small fixes. (0.16.4)

This commit is contained in:
Johannes Findeisen 2025-10-01 23:05:30 +02:00
commit 2b82a01fb5
9 changed files with 674 additions and 60 deletions

117
lib/arrays.fun Normal file
View file

@ -0,0 +1,117 @@
/*
* This file is part of the Fun programming language.
* https://hanez.org/project/fun/
*
* Copyright 2025 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2025-10-01
*/
// Array utilities
// Return a shallow slice of arr starting at 'start' with 'count' elements (clamped)
fun array_slice(arr, start, count)
number n = len(arr)
number s = start
if (s < 0)
s = 0
if (s > n)
s = n
number c = count
if (c < 0)
c = 0
if (s + c > n)
c = n - s
out = []
number i = 0
while i < c
push(out, arr[s + i])
i = i + 1
return out
// Return a new array with elements in reverse order
fun array_reverse(arr)
out = []
number i = len(arr) - 1
while i >= 0
push(out, arr[i])
i = i - 1
return out
// Concatenate two arrays and return a new array
fun array_concat(a, b)
out = []
number i = 0
while i < len(a)
push(out, a[i])
i = i + 1
number j = 0
while j < len(b)
push(out, b[j])
j = j + 1
return out
// Return the index of the first occurrence of value in arr, or -1
fun array_index_of(arr, value)
number i = 0
number n = len(arr)
while i < n
if (arr[i] == value)
return i
i = i + 1
return -1
// Return 1 if arr contains value, else 0
fun array_contains(arr, value)
return array_index_of(arr, value) >= 0
// Return a new array with only the first occurrence of each element (stable)
fun array_unique(arr)
out = []
number i = 0
number n = len(arr)
while i < n
v = arr[i]
if (array_index_of(out, v) < 0)
push(out, v)
i = i + 1
return out
// Flatten one level: [[1,2],[3],[4,5]] -> [1,2,3,4,5]
fun array_flatten1(arr)
out = []
number i = 0
number n = len(arr)
while i < n
item = arr[i]
// Treat nested arrays as flattenable
if (typeof(item) == "Array")
number j = 0
number m = len(item)
while j < m
push(out, item[j])
j = j + 1
else
push(out, item)
i = i + 1
return out
// Push value to arr only if not present (mutates arr), returns arr
fun array_push_unique_mut(arr, value)
if (!array_contains(arr, value))
push(arr, value)
return arr
// Return a new array that contains all elements of arr and value appended only if not present
fun array_push_unique(arr, value)
out = []
number i = 0
number n = len(arr)
while i < n
push(out, arr[i])
i = i + 1
if (!array_contains(out, value))
push(out, value)
return out

View file

@ -9,54 +9,4 @@
* Added: 2025-10-01
*/
// ASCII string to bytes (printable ASCII 0x20..0x7E)
fun string_to_bytes_ascii(s)
str = to_string(s)
out = []
number i = 0
// ASCII printable ranges
P1 = " !\"#$%&'()*+,-./" // 32..47
P2 = "0123456789" // 48..57
P3 = ":;<=>?@" // 58..64
P4 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // 65..90
P5 = "[\\]^_`" // 91..96
P6 = "abcdefghijklmnopqrstuvwxyz" // 97..122
P7 = "{|}~" // 123..126
while true
ch = substr(str, i, 1)
if (typeof(ch) != "String" || ch == "")
break
number code = -1
idx = find(P1, ch)
if (idx >= 0)
code = 32 + idx
else
idx = find(P2, ch)
if (idx >= 0)
code = 48 + idx
else
idx = find(P3, ch)
if (idx >= 0)
code = 58 + idx
else
idx = find(P4, ch)
if (idx >= 0)
code = 65 + idx
else
idx = find(P5, ch)
if (idx >= 0)
code = 91 + idx
else
idx = find(P6, ch)
if (idx >= 0)
code = 97 + idx
else
idx = find(P7, ch)
if (idx >= 0)
code = 123 + idx
else
// non-printable -> 0
code = 0
push(out, code)
i = i + 1
return out

89
lib/encoding/base64.fun Normal file
View file

@ -0,0 +1,89 @@
/*
* This file is part of the Fun programming language.
* https://hanez.org/project/fun/
*
* Copyright 2025 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2025-10-01
*/
// Base64 encode/decode for byte arrays (RFC 4648, standard alphabet)
fun b64_encode_bytes(bytes)
table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
out = []
number i = 0
number n = len(bytes)
while i + 2 < n
number b0 = bytes[i]
number b1 = bytes[i + 1]
number b2 = bytes[i + 2]
number v = b0 * 65536 + b1 * 256 + b2
number c0 = (v / 262144) % 64 // bits 18..23
number c1 = (v / 4096) % 64 // bits 12..17
number c2 = (v / 64) % 64 // bits 6..11
number c3 = v % 64 // bits 0..5
push(out, substr(table, c0, 1))
push(out, substr(table, c1, 1))
push(out, substr(table, c2, 1))
push(out, substr(table, c3, 1))
i = i + 3
number rem = n - i
if (rem == 1)
number b0 = bytes[i]
number v = b0 * 65536
number c0 = (v / 262144) % 64
number c1 = (v / 4096) % 64
push(out, substr(table, c0, 1))
push(out, substr(table, c1, 1))
push(out, "=")
push(out, "=")
else if (rem == 2)
number b0 = bytes[i]
number b1 = bytes[i + 1]
number v = b0 * 65536 + b1 * 256
number c0 = (v / 262144) % 64
number c1 = (v / 4096) % 64
number c2 = (v / 64) % 64
push(out, substr(table, c0, 1))
push(out, substr(table, c1, 1))
push(out, substr(table, c2, 1))
push(out, "=")
return join(out, "")
fun b64_decode_to_bytes(s)
table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
str = to_string(s)
out = []
// build reverse lookup: index in table is value
// Since we don't have a map, use find on each char
number i = 0
number n = len(str)
while i < n
// read 4 chars
c0 = substr(str, i, 1)
c1 = substr(str, i + 1, 1)
c2 = substr(str, i + 2, 1)
c3 = substr(str, i + 3, 1)
number v0 = find(table, c0)
number v1 = find(table, c1)
number pad2 = (c2 == "=")
number pad3 = (c3 == "=")
number v2 = pad2 ? 0 : find(table, c2)
number v3 = pad3 ? 0 : find(table, c3)
number twentyfour = v0 * 262144 + v1 * 4096 + v2 * 64 + v3
// bytes
number b0 = (twentyfour / 65536) % 256
number b1 = (twentyfour / 256) % 256
number b2 = twentyfour % 256
push(out, b0)
if (!pad2)
push(out, b1)
if (!pad3)
push(out, b2)
i = i + 4
return out

90
lib/math.fun Normal file
View file

@ -0,0 +1,90 @@
/*
* This file is part of the Fun programming language.
* https://hanez.org/project/fun/
*
* Copyright 2025 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2025-10-01
*/
// Math helpers
fun abs(x)
if (x < 0)
return -x
return x
fun clamp(x, lo, hi)
v = x
if (v < lo) v = lo
if (v > hi) v = hi
return v
fun gcd(a, b)
number x = abs(a)
number y = abs(b)
while y != 0
t = x % y
x = y
y = t
return x
fun lcm(a, b)
if (a == 0) || (b == 0)
return 0
return abs(a * b) / gcd(a, b)
// integer exponent (exp >= 0)
fun powi(base, exp)
number e = exp
if (e < 0)
// simple fallback for negative: 0 for now (no floats)
return 0
number result = 1
number b = base
while e > 0
if (e % 2 == 1)
result = result * b
b = b * b
e = e / 2
return result
// Min/Max over three numbers
fun min3(a, b, c)
m = a
if (b < m) m = b
if (c < m) m = c
return m
fun max3(a, b, c)
m = a
if (b > m) m = b
if (c > m) m = c
return m
// Array min/max (for non-empty arrays)
fun array_min(arr)
number n = len(arr)
if (n == 0)
return 0
m = arr[0]
number i = 1
while i < n
if (arr[i] < m)
m = arr[i]
i = i + 1
return m
fun array_max(arr)
number n = len(arr)
if (n == 0)
return 0
m = arr[0]
number i = 1
while i < n
if (arr[i] > m)
m = arr[i]
i = i + 1
return m

View file

@ -2,14 +2,202 @@
* This file is part of the Fun programming language.
* https://hanez.org/project/fun/
*
* Copyright 2025 Johannes Findeisen <you@hanez.org>
* Copyright 2025 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2025-10-01
*/
// This file should not contain code! It should just include all string related
// functions from core/*.fun.
// Extra string utilities
#include <core/string_to_bytes_ascii.fun>
// Trim whitespace on the left (space, tab, CR, LF)
fun str_ltrim(s)
src = to_string(s)
number i = 0
ws = " \t\r\n"
while i < len(src)
ch = substr(src, i, 1)
if (find(ws, ch) < 0)
break
i = i + 1
return substr(src, i, len(src) - i)
// Trim whitespace on the right
fun str_rtrim(s)
src = to_string(s)
number i = len(src) - 1
ws = " \t\r\n"
while i >= 0
ch = substr(src, i, 1)
if (find(ws, ch) < 0)
break
i = i - 1
return substr(src, 0, i + 1)
// Trim both sides
fun str_trim(s)
return str_rtrim(str_ltrim(s))
// Return 1 if s starts with prefix, else 0
fun str_starts_with(s, prefix)
a = to_string(s)
p = to_string(prefix)
if (len(p) > len(a))
return 0
return substr(a, 0, len(p)) == p
// Return 1 if s ends with suffix, else 0
fun str_ends_with(s, suffix)
a = to_string(s)
p = to_string(suffix)
number la = len(a)
number lp = len(p)
if (lp > la)
return 0
return substr(a, la - lp, lp) == p
// Split by a single-character delimiter, returns array of strings
fun str_split(s, delim)
src = to_string(s)
d = to_string(delim)
// Use only the first character of delim
if (len(d) == 0)
return [src]
dd = substr(d, 0, 1)
parts = []
buf = []
number i = 0
number n = len(src)
while i < n
ch = substr(src, i, 1)
if (ch == dd)
push(parts, join(buf, ""))
buf = []
else
push(buf, ch)
i = i + 1
// tail
push(parts, join(buf, ""))
return parts
// Replace all occurrences of 'from' with 'to' (naive scan)
fun str_replace_all(s, from, to)
src = to_string(s)
f = to_string(from)
t = to_string(to)
number n = len(src)
number lf = len(f)
if (lf == 0)
return src
out = []
number i = 0
while i < n
if (i + lf <= n) && (substr(src, i, lf) == f)
push(out, t)
i = i + lf
else
push(out, substr(src, i, 1))
i = i + 1
return join(out, "")
// Lowercase transform for ASCII A..Z
fun str_to_lower(s)
src = to_string(s)
U = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
L = "abcdefghijklmnopqrstuvwxyz"
out = []
number i = 0
number n = len(src)
while i < n
ch = substr(src, i, 1)
idx = find(U, ch)
if (idx >= 0)
push(out, substr(L, idx, 1))
else
push(out, ch)
i = i + 1
return join(out, "")
// Uppercase transform for ASCII a..z
fun str_to_upper(s)
src = to_string(s)
U = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
L = "abcdefghijklmnopqrstuvwxyz"
out = []
number i = 0
number n = len(src)
while i < n
ch = substr(src, i, 1)
idx = find(L, ch)
if (idx >= 0)
push(out, substr(U, idx, 1))
else
push(out, ch)
i = i + 1
return join(out, "")
// Repeat string s 'count' times
fun str_repeat(s, count)
src = to_string(s)
number c = count
if (c <= 0)
return ""
parts = []
number i = 0
while i < c
push(parts, src)
i = i + 1
return join(parts, "")
// ASCII string to bytes (printable ASCII 0x20..0x7E)
fun string_to_bytes_ascii(s)
str = to_string(s)
out = []
number i = 0
// ASCII printable ranges
P1 = " !\"#$%&'()*+,-./" // 32..47
P2 = "0123456789" // 48..57
P3 = ":;<=>?@" // 58..64
P4 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // 65..90
P5 = "[\\]^_`" // 91..96
P6 = "abcdefghijklmnopqrstuvwxyz" // 97..122
P7 = "{|}~" // 123..126
while true
ch = substr(str, i, 1)
if (typeof(ch) != "String" || ch == "")
break
number code = -1
idx = find(P1, ch)
if (idx >= 0)
code = 32 + idx
else
idx = find(P2, ch)
if (idx >= 0)
code = 48 + idx
else
idx = find(P3, ch)
if (idx >= 0)
code = 58 + idx
else
idx = find(P4, ch)
if (idx >= 0)
code = 65 + idx
else
idx = find(P5, ch)
if (idx >= 0)
code = 91 + idx
else
idx = find(P6, ch)
if (idx >= 0)
code = 97 + idx
else
idx = find(P7, ch)
if (idx >= 0)
code = 123 + idx
else
// non-printable -> 0
code = 0
push(out, code)
i = i + 1
return out

48
lib/utils/range.fun Normal file
View file

@ -0,0 +1,48 @@
/*
* This file is part of the Fun programming language.
* https://hanez.org/project/fun/
*
* Copyright 2025 Johannes Findeisen
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2025-10-01
*/
// Range utilities (end-exclusive)
// range(n) -> [0, 1, ..., n-1]
fun range(n)
out = []
number i = 0
while i < n
push(out, i)
i = i + 1
return out
// range2(start, end) -> [start, start+1, ..., end-1]
fun range2(start, end)
out = []
number i = start
while i < end
push(out, i)
i = i + 1
return out
// range3(start, end, step) with positive or negative step (non-zero)
fun range3(start, end, step)
out = []
number s = step
if (s == 0)
return out
if (s > 0)
number i = start
while i < end
push(out, i)
i = i + s
else
number j = start
while j > end
push(out, j)
j = j + s
return out