// SPDX-License-Identifier: GPL-3.0-only // Copyright (c) 2022, Sylvain Huet, Ambermind // Minimacy (r) System //------------ LISTS fun listConcat(p, q)= if p==nil then q else head(p)::listConcat(tail(p), q);; fun _reverse(p, q)= if p==nil then q else _reverse(tail(p), head(p)::q);; fun listReverse(p) = _reverse(p, nil);; fun listContains(l, v)= if l<>nil then (v==head(l))||listContains(tail(l), v);; fun _listPosition(l, v, i)= if l<>nil then if v==head(l) then i else _listPosition(tail(l), v, i+1);; fun listPosition(l, v)= _listPosition(l, v, 0);; fun listMap(l, f)= if l<>nil then let call f(head(l)) -> p in if p==nil then listMap(tail(l), f) else p::listMap(tail(l), f);; fun listFilter(l, f)= listMap(l, lambda(p)= if call f(p) then p);; fun listReduce(l, v0, f)= if l==nil then v0 else listReduce(tail(l), call f(v0, head(l)), f);; fun listVisit(l, f)= if l==nil then true else if call f(head(l)) then listVisit(tail(l), f);; fun listFind(l, f)= if l<>nil then if call f(head(l)) then head(l) else listFind(tail(l), f);; fun listTest(l, f)= nil<>listFind(l, f);; fun listInsert(l, p, fBefore)= if l==nil then p::nil else if call fBefore(p, head(l)) then p::l else head(l)::listInsert(tail(l), p, fBefore);; fun listMatchHead(ll, val)= if ll<>nil then if val==head(head(ll)) then tail(head(ll)) else listMatchHead(tail(ll), val);; fun listRemove(l, a)= if l<>nil then if a==head(l) then tail(l) else head(l)::listRemove(tail(l), a);; fun _listlen(l, n)= if l==nil then n else _listlen(tail(l), n+1);; fun listLength(l)= _listlen(l, 0);; fun listGet(l, n)= if n<=0 then head(l) else listGet(tail(l), n-1);; fun listLast(l)= if nil==tail(l) then head(l) else listLast(tail(l));; fun listCut(l, n) = if l<>nil && n>0 then head(l)::listCut(tail(l), n-1);; fun listSkip(l, n)= if n<=0 then l else listSkip(tail(l), n-1);; fun _reverseConcat(p, q) = if p==nil then q else _reverseConcat(tail(p), head(p)::q);; fun _divide(x, p, r1, r2, fBefore)= if p==nil then [r1, r2] else let p-> a::n in if call fBefore(a, x) then _divide(x, n, a::r1, r2, fBefore) else _divide(x, n, r1, a::r2, fBefore);; fun quicksort(l, fBefore)= if l==nil then nil else let l-> vl::nl in if nl==nil then l else let _divide(vl, nl, nil, nil, fBefore)->[va, na] in _reverseConcat(_reverse(quicksort(va, fBefore), nil), vl::quicksort(na, fBefore));; fun doubleListCompress(ll)= let fifoCreate() -> fifo in fifoList(for l in ll do for p in l do fifoIn(fifo, p));; fun tripleListCompress(lll)= let fifoCreate() -> fifo in fifoList(for ll in lll do for l in ll do for p in l do fifoIn(fifo, p));; //------------ ARRAYS fun arrayFromList(l)= let listLength(l) -> n in let arrayCreate(n, nil) -> a in ( let -1->i in for x in l do set a[set i=i+1]=x; a );; fun listFromArray(a)= let arrayLength(a) -> n in let nil -> l in for i=n-1;i>=0;i-1 do set l=a[i]::l;; fun arrayInit(n, f)= let arrayCreate(n, nil) -> a in ( for i=0;i n in let arrayCreate(n, nil) -> b in ( for v,i of a do set b[i]=call f(v); b );; fun arrayMapIndex(a, f)= let arrayLength(a) -> n in let arrayCreate(n, nil) -> b in ( for v,i of a do set b[i]=call f(i, v); b );; fun arrayReduce(a, v0, f)= for v of a do set v0=call f(v0, v); v0;; fun arrayIndexOf(a, val)= for v,i of a do if val==v then return i; nil;; //------------ HASHMAPS fun hashmapFind(d, f)= let 1< nb in let nil->result in ( for i=0;inil ; let p->[_, _, next] in next do let p->[key, val, _] in if call f(key, val) then return key; nil );; fun hashmapMap(d, f)= let 1< nb in let nil->result in ( for i=0;inil ; let p->[_, _, next] in next do let p->[key, val, _] in let call f(key, val) -> q in if q<>nil then set result=q::result; result );; fun listFromHashmap(d)= hashmapMap(d, lambda(key, val)=[key, val]);; fun hashmapTest(d, f)= nil<>hashmapFind(d, f);; fun hashmapInit(n, l)= let hashmapCreate(n) -> h in ( for [key, val] in l do hashmapSet(h, key, val); h );; //------------ HASHSETS fun hashsetFind(d, f)= let 1< nb in let nil->result in for i=0;i nb in let nil->result in ( for i=0;i q in if q<>nil then set result=q::result; result );; fun listFromHashset(d)= hashsetMap(d, lambda(key)=key);; fun hashsetTest(d, f)= nil<>hashsetFind(d, f);; fun hashsetInit(n, l)= let hashsetCreate(n) -> h in ( for val in l do hashsetAdd(h, val); h );; //------------ REFERENCES struct Ref{any}=[_valRef:any];; fun refCreate(x)=[_valRef=x];; fun refGet(ref) = ref._valRef;; fun refSet(ref, val)= set ref._valRef=val;; //------------ CONSOLE const T0=timeMs();; fun echoTime(v) = let strFromInt(timeMs()-T0) -> str in let if strLength(str)<4 then strRight(strConcat("000", str), 4) else str -> str in echoLn [">", strLeft(str, -3), ".", strRight(str, 3), ": ", v]; v;; fun echoHexLn(v)= echoLn hexFromStr(v);v;; fun hexFromIntN(n, i)= let hexFromInt(i) -> s in strConcat(strCreate(n-strLength(s), '0'), s);; fun hexDump(s)= if s==nil then echoLn "nil" elif s=="" then echoLn "\"\"" else for i=0;i a in (echo " "; echo if a==nil then " " else hexFromIntN(2, a)); echo " "; for j=0;j<16 do let strGet(s, i+j) -> a in echo match a with nil -> " ", a -> if a<32 || a>=0xc0 then "." else strFromChar(a); echoLn "" ); s;; fun hexDumpBytes(s)=hexDump(_bytesAsStr(s)); s;; fun arrayDump(a)= echo "{"; echo strJoin(" ", a); echoLn "}"; a;; //------------ STRINGS fun strEmpty(str)= (str==nil) || (0==strLength(str));; fun strStartsWith(str, val)= strCheckPos(str, val, 0);; fun strEndsWith(str, val)= strCheckPos(str, val, strLength(str)-strLength(val));; fun strContains(str, val)= nil<>strPos(str, val, 0);; fun strFromBool(val)= if val then "true" else if val==false then "false";; fun strTrim(str)= let strLength(str) -> len in for i=0;i=i;j-1 do if 32 len in if lenN then strConcat(strLeft(str, N-1), "*") else str;; fun strPadWithSpace(N, str)= strPad(N, 32, str);; fun intPad(N, i)= if i>=0 then strPadWithSpace(N, strFromInt(i));; fun intPad0(N, i)= if i>=0 then strPad(N, '0', strFromInt(i));; fun _strWithDelimiter(block, str, res)= let strLength(str) -> len in if len<=block then str::res else _strWithDelimiter(block, strLeft(str, len-block), strSlice(str, len-block, block)::res);; fun strWithDelimiter(block, delimiter, str)= strJoin(delimiter, _strWithDelimiter(block, str, nil));; fun intWithDelimiter(delimiter, val)= if val<0 then strConcat("-",strWithDelimiter(3, delimiter, strFromInt(-val))) elif val<>nil then strWithDelimiter(3, delimiter, strFromInt(val));; fun _intShortFormat(v, divisor, l)= if vnil then _intShortFormat(v, divisor, units);; fun intShortFormat(divisor, v)= intShortFormatWithUnits(divisor, v, ""::"k"::"M"::"G"::"T"::"P"::nil);; //------------ MISC fun range(val, mn, mx)= (val>=mn) && (val<=mx);; fun fifoFromList(l)= let fifoCreate() -> fifo in ( for p in l do fifoIn(fifo, p); fifo );; fun bytesInit(n, f)= let bytesCreate(n, 0) -> a in ( for i=0;i