2023-03-05 21:55:20 +00:00
|
|
|
{builtins ->
|
|
|
|
|
if := builtins.if
|
|
|
|
|
== := builtins.==
|
|
|
|
|
> := builtins.>
|
|
|
|
|
< := builtins.<
|
|
|
|
|
>= := builtins.>=
|
|
|
|
|
<= := builtins.<=
|
|
|
|
|
+ := builtins.+
|
|
|
|
|
- := builtins.-
|
|
|
|
|
* := builtins.*
|
|
|
|
|
/ := builtins./
|
|
|
|
|
join := builtins.join
|
|
|
|
|
print := builtins.print
|
|
|
|
|
dump := builtins.dump
|
|
|
|
|
disasm := builtins.disasm
|
|
|
|
|
tostring := builtins.tostring
|
|
|
|
|
not := builtins.not
|
|
|
|
|
len := builtins.len
|
|
|
|
|
type := builtins.type
|
2023-03-07 20:37:37 +00:00
|
|
|
loop := builtins.loop
|
2023-03-05 21:55:20 +00:00
|
|
|
gc := builtins.gc
|
|
|
|
|
backtrace := builtins.backtrace
|
|
|
|
|
fopen := builtins.fopen
|
|
|
|
|
fread := builtins.fread
|
|
|
|
|
fwrite := builtins.fwrite
|
|
|
|
|
fclose := builtins.fclose
|
2023-03-30 18:33:53 +00:00
|
|
|
load-file := builtins.load-file
|
|
|
|
|
load-string := builtins.load-string
|
2023-03-23 22:38:35 +00:00
|
|
|
get-optional := builtins.get-optional
|
2023-03-29 20:33:40 +00:00
|
|
|
raise := builtins.raise
|
2023-03-23 22:38:35 +00:00
|
|
|
symbol := builtins.symbol
|
2023-03-05 21:55:20 +00:00
|
|
|
-serialize-bytecode := builtins.-serialize-bytecode
|
|
|
|
|
-unserialize-bytecode := builtins.-unserialize-bytecode
|
|
|
|
|
|
2023-03-23 22:38:35 +00:00
|
|
|
Some := (builtins.getsym-Some)
|
|
|
|
|
|
2023-03-05 21:55:20 +00:00
|
|
|
-named := { name f ->
|
|
|
|
|
builtins.set-func-name f name
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-07 20:37:37 +00:00
|
|
|
while := { cond body ->
|
|
|
|
|
res := nil
|
|
|
|
|
loop {
|
|
|
|
|
if (cond) {
|
|
|
|
|
res = (body)
|
|
|
|
|
true
|
|
|
|
|
} {
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for := {
|
|
|
|
|
end body ->
|
|
|
|
|
for 0 end body
|
|
|
|
|
start end body ->
|
|
|
|
|
if (> start end) {
|
|
|
|
|
for start -1 end body
|
|
|
|
|
} {
|
|
|
|
|
for start 1 end body
|
|
|
|
|
}
|
|
|
|
|
start step end body ->
|
|
|
|
|
end-not-reached := if (> step 0) {{ < start end }} {{ > start end }}
|
|
|
|
|
out := nil
|
|
|
|
|
while end-not-reached {
|
|
|
|
|
out = body start
|
|
|
|
|
start = + start step
|
|
|
|
|
}
|
|
|
|
|
out
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-05 21:55:20 +00:00
|
|
|
& := { ~strings ->
|
|
|
|
|
join "" strings
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
partial := { f ~a1 ->
|
|
|
|
|
{ ~a2 ->
|
|
|
|
|
f ~a1 ~a2
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
compose := {
|
|
|
|
|
f -> f
|
|
|
|
|
f ~fs ->
|
|
|
|
|
fs-composed := compose ~fs
|
|
|
|
|
{ ~args ->
|
|
|
|
|
f (fs-composed ~args)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
!= := -named '!= (compose not ==)
|
|
|
|
|
!> := -named '!> (compose not >)
|
|
|
|
|
!< := -named '!< (compose not <)
|
|
|
|
|
!>= := -named '!>= (compose not >=)
|
|
|
|
|
!<= := -named '!<= (compose not <=)
|
|
|
|
|
|
2023-03-07 20:37:37 +00:00
|
|
|
has := {
|
|
|
|
|
pred cmp y ->
|
|
|
|
|
{ x ->
|
|
|
|
|
cmp (pred x) y
|
|
|
|
|
}
|
|
|
|
|
pred y ->
|
|
|
|
|
has pred == y
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-07 20:51:40 +00:00
|
|
|
identity := { x -> x }
|
|
|
|
|
|
|
|
|
|
is := -named 'is (partial has identity)
|
|
|
|
|
|
2023-03-29 20:36:38 +00:00
|
|
|
++ := { x -> + x 1 }
|
|
|
|
|
-- := { x -> - x 1 }
|
|
|
|
|
|
2023-03-07 20:51:40 +00:00
|
|
|
-raw-substring := builtins.substring
|
|
|
|
|
substr := {
|
|
|
|
|
start s ->
|
|
|
|
|
substr start (len s) s
|
2023-07-03 21:39:29 +00:00
|
|
|
start?(is < 0) newlen s ->
|
|
|
|
|
substr (+ start (len s)) newlen s
|
|
|
|
|
start newlen?(is < 0) s ->
|
|
|
|
|
substr start (+ newlen (- (len s) start)) s
|
|
|
|
|
start newlen s ->
|
|
|
|
|
-raw-substring s start newlen
|
2023-03-07 20:51:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-raw-stringsearch := builtins.stringsearch
|
|
|
|
|
strsearch := {
|
|
|
|
|
needle haystack ->
|
|
|
|
|
-raw-stringsearch haystack needle
|
|
|
|
|
needle start?(is < 0) haystack ->
|
|
|
|
|
strsearch needle (+ start (len s)) haystack
|
|
|
|
|
needle start haystack ->
|
|
|
|
|
off := (strsearch needle (substr start haystack))
|
|
|
|
|
if (== off nil) { nil } { + start off }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
split := ({
|
|
|
|
|
split-aux := { maxlen-reached sep s ->
|
|
|
|
|
sep-len := len sep
|
|
|
|
|
parts := []
|
|
|
|
|
loop {
|
2023-03-29 20:36:38 +00:00
|
|
|
if (maxlen-reached (++ (len parts))) {
|
2023-03-07 20:51:40 +00:00
|
|
|
parts = [~parts s]
|
|
|
|
|
false
|
|
|
|
|
} {
|
|
|
|
|
off := strsearch sep s
|
|
|
|
|
if (== nil off) {
|
|
|
|
|
parts = [~parts s]
|
|
|
|
|
false
|
|
|
|
|
} {
|
|
|
|
|
parts = [~parts (substr 0 off s)]
|
|
|
|
|
s = substr (+ off sep-len) s
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parts
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
split := {
|
|
|
|
|
sep s ->
|
|
|
|
|
split-aux {false} sep s
|
|
|
|
|
sep maxlen s ->
|
|
|
|
|
split-aux (is >= maxlen) sep s
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2023-03-07 20:37:37 +00:00
|
|
|
keach := {
|
|
|
|
|
d?(has type 'dict) body ->
|
|
|
|
|
out := nil
|
|
|
|
|
builtins.iterate-dict d { k v ->
|
|
|
|
|
out = body k v
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
out
|
|
|
|
|
l?(has type 'list) body ->
|
|
|
|
|
out := nil
|
|
|
|
|
for (len l) { i ->
|
|
|
|
|
out = body i l@i
|
|
|
|
|
}
|
|
|
|
|
out
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
each := { container body ->
|
|
|
|
|
keach container { _ v ->
|
|
|
|
|
body v
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-04 20:46:22 +00:00
|
|
|
andalso := {
|
|
|
|
|
f ->
|
|
|
|
|
(f)
|
|
|
|
|
f ~fs ->
|
|
|
|
|
result := (f)
|
|
|
|
|
if result { andalso ~fs } { result }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
orelse := {
|
|
|
|
|
f ->
|
|
|
|
|
(f)
|
|
|
|
|
f ~fs ->
|
|
|
|
|
result := (f)
|
|
|
|
|
if result { result } { orelse ~fs }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
find-first := { l f ->
|
|
|
|
|
out := nil
|
|
|
|
|
i := 0
|
|
|
|
|
n := len l
|
|
|
|
|
while {andalso {== out nil} {< i n}} {
|
|
|
|
|
{
|
|
|
|
|
Some:x ->
|
|
|
|
|
out = Some::x
|
|
|
|
|
nil ->
|
|
|
|
|
} (f l@i)
|
|
|
|
|
|
|
|
|
|
i = ++ i
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unwrap-some := {
|
|
|
|
|
Some:x then _ -> then x
|
|
|
|
|
x _ else -> else x
|
|
|
|
|
x then -> unwrap-some x then identity
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 22:38:35 +00:00
|
|
|
has-key := { k container ->
|
|
|
|
|
{
|
|
|
|
|
Some: _ -> true
|
|
|
|
|
nil -> false
|
|
|
|
|
} (get-optional k container)
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-30 18:33:53 +00:00
|
|
|
run-file := { f ->
|
|
|
|
|
((load-file f))
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-03 21:33:19 +00:00
|
|
|
tonumber := {
|
|
|
|
|
x ->
|
|
|
|
|
tonumber 10 x
|
|
|
|
|
10 x?(has type 'number) ->
|
|
|
|
|
x
|
|
|
|
|
base x ->
|
|
|
|
|
builtins.tonumber base (tostring x)
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-04 20:46:22 +00:00
|
|
|
modules := ({
|
|
|
|
|
loaded-modules := [->]
|
|
|
|
|
searchers := []
|
|
|
|
|
|
|
|
|
|
ImportError := symbol 'ImportError
|
|
|
|
|
|
|
|
|
|
add-searcher := { s ->
|
|
|
|
|
searchers = [~searchers s]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add-searcher { m ->
|
|
|
|
|
unwrap-some (get-optional m loaded-modules) { mod ->
|
2023-07-03 21:39:29 +00:00
|
|
|
Some::{ Some::mod }
|
2023-04-04 20:46:22 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add-searcher { m ->
|
|
|
|
|
unwrap-some (builtins.cmod-searcher m) { loader ->
|
2023-07-03 21:39:29 +00:00
|
|
|
Some::{
|
|
|
|
|
Some::(loader)
|
|
|
|
|
}
|
2023-04-04 20:46:22 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
import := { name ->
|
|
|
|
|
maybe-mod := find-first searchers { s ->
|
|
|
|
|
unwrap-some (s name) { loader ->
|
|
|
|
|
loader name
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
Some:mod ->
|
|
|
|
|
loaded-modules@name = mod
|
|
|
|
|
mod
|
|
|
|
|
nil ->
|
|
|
|
|
raise ImportError::(& "Module " name " not found")
|
|
|
|
|
} maybe-mod
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add-preloaded-module := { name mod ->
|
|
|
|
|
loaded-modules@name = mod
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
modules := [
|
|
|
|
|
'import -> import
|
|
|
|
|
'add-searcher -> add-searcher
|
|
|
|
|
'add-preloaded-module -> add-preloaded-module
|
|
|
|
|
'ImportError -> ImportError
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
add-preloaded-module 'modules modules
|
|
|
|
|
|
|
|
|
|
modules
|
|
|
|
|
})
|
|
|
|
|
|
2023-07-03 21:39:29 +00:00
|
|
|
map := {
|
|
|
|
|
_ [] -> []
|
|
|
|
|
f [x ~xs] ->
|
|
|
|
|
[(f x) ~(map f xs)]
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-05 21:55:20 +00:00
|
|
|
# Dictionary of exported functions
|
|
|
|
|
[
|
|
|
|
|
'if -> if
|
|
|
|
|
'== -> ==
|
|
|
|
|
'> -> >
|
|
|
|
|
'< -> <
|
|
|
|
|
'>= -> >=
|
|
|
|
|
'<= -> <=
|
|
|
|
|
'+ -> +
|
|
|
|
|
'- -> -
|
|
|
|
|
'* -> *
|
|
|
|
|
'/ -> /
|
|
|
|
|
'join -> join
|
|
|
|
|
'print -> print
|
|
|
|
|
'dump -> dump
|
|
|
|
|
'disasm -> disasm
|
|
|
|
|
'tostring -> tostring
|
2023-07-03 21:33:19 +00:00
|
|
|
'tonumber -> tonumber
|
2023-03-05 21:55:20 +00:00
|
|
|
'not -> not
|
|
|
|
|
'len -> len
|
|
|
|
|
'type -> type
|
2023-03-07 20:37:37 +00:00
|
|
|
'loop -> loop
|
2023-03-05 21:55:20 +00:00
|
|
|
'while -> while
|
2023-03-07 20:37:37 +00:00
|
|
|
'for -> for
|
2023-03-05 21:55:20 +00:00
|
|
|
'gc -> gc
|
|
|
|
|
'backtrace -> backtrace
|
|
|
|
|
'fopen -> fopen
|
|
|
|
|
'fread -> fread
|
|
|
|
|
'fwrite -> fwrite
|
|
|
|
|
'fclose -> fclose
|
2023-03-30 18:33:53 +00:00
|
|
|
'load-file -> load-file
|
|
|
|
|
'load-string -> load-string
|
|
|
|
|
'run-file -> run-file
|
2023-03-05 21:55:20 +00:00
|
|
|
'-serialize-bytecode -> -serialize-bytecode
|
|
|
|
|
'-unserialize-bytecode -> -unserialize-bytecode
|
|
|
|
|
'& -> &
|
2023-03-07 20:51:40 +00:00
|
|
|
'substr -> substr
|
|
|
|
|
'strsearch -> strsearch
|
|
|
|
|
'split -> split
|
2023-03-05 21:55:20 +00:00
|
|
|
'partial -> partial
|
|
|
|
|
'compose -> compose
|
2023-03-07 20:37:37 +00:00
|
|
|
'has -> has
|
2023-03-07 20:51:40 +00:00
|
|
|
'identity -> identity
|
|
|
|
|
'is -> is
|
2023-03-05 21:55:20 +00:00
|
|
|
'!= -> !=
|
|
|
|
|
'!> -> !>
|
|
|
|
|
'!< -> !<
|
|
|
|
|
'!>= -> !>=
|
|
|
|
|
'!<= -> !<=
|
2023-03-29 20:36:38 +00:00
|
|
|
'++ -> ++
|
|
|
|
|
'-- -> --
|
2023-03-07 20:37:37 +00:00
|
|
|
'keach -> keach
|
|
|
|
|
'each -> each
|
2023-03-23 22:38:35 +00:00
|
|
|
'get-optional -> get-optional
|
2023-03-29 20:33:40 +00:00
|
|
|
'raise -> raise
|
2023-03-23 22:38:35 +00:00
|
|
|
'has-key -> has-key
|
|
|
|
|
'symbol -> symbol
|
|
|
|
|
'Some -> Some
|
2023-03-30 20:11:44 +00:00
|
|
|
'get-argv -> builtins.get-argv
|
2023-04-04 20:46:22 +00:00
|
|
|
'andalso -> andalso
|
|
|
|
|
'orelse -> orelse
|
|
|
|
|
'find-first -> find-first
|
|
|
|
|
'unwrap-some -> unwrap-some
|
|
|
|
|
'import -> modules.import
|
2023-07-03 21:39:29 +00:00
|
|
|
'map -> map
|
2023-03-05 21:55:20 +00:00
|
|
|
]
|
|
|
|
|
}
|