def null def program-name func println { | print "\n" print } construct _str_ext { ; new { any | with this ; null clone this settype "construct" dyn-objcall } to-bytes { [int] | str-to-bytes } } include _str_ext in str construct _mega-ext { ; swap { .. | with this ; i mswap i -- mswap } mswap { .. | mswap } foreach { | with this ; def i 0 =i while { i this lt } { i callable call i ++ =i } } } include _mega-ext in mega construct _array-ext { ; get { any | array-get } sget { any|null | with idx this ; idx this:len lt idx -1 gt and dup if { pop idx this:get 2 stop } not if { null } } len { mega | array-len } set { any | array-set } to-stack { .. | with this ; def len this:len =len def i 0 =i while { i len lt } { i this:get i ++ =i } } foreach { | with callable this ; def i 0 =i while { i this:len lt } { i this:get callable call i ++ =i } } to-str { str | bytes-to-str } 0 { any | with this ; 0 this:get } 1 { any | with this ; 1 this:get } 2 { any | with this ; 2 this:get } 3 { any | with this ; 3 this:get } 4 { any | with this ; 4 this:get } } include _array-ext in array "iter.spl" import construct List { array ; construct { this | with array this ; array this:=array this } get { any | _:array:get } sget { any|null | _:array:sget } len { mega | _:array:len } set { any | _:array:set } } construct _GrowingArray { ; push-front { | with item this ; [ item this:array:to-stack ] this:=array } push { | with item this ; [ this:array:to-stack item ] this:=array } insert { | with item index this ; this:array:len index - =index [ this:array:to-stack index:mswap item (index ++):mswap ] this:=array } } construct _ShrinkingArray { ; pop-front { any | with this ; 0 this:remove } pop { any | with this ; this:array:len not if { null 2 stop } def item [ this:array:to-stack =item ] this:=array item } remove { any | with index this ; this:array:len not if { null 2 stop } def item this:array:len index - =index [ this:array:to-stack index:mswap =item (index --):mswap ] this:=array item } } include _GrowingArray in List include _ShrinkingArray in List construct ArrayIter { array idx ; construct { this | with array this ; array this:=array 0 this:=idx this } next { any | with this ; this:idx dup ++ this:=idx this:array:sget } } construct _IterableArray { ; iter { ArrayIter | with this ; this gettype "array" eq dup if { pop this ArrayIter:new 2 stop } not if { this:array ArrayIter:new } } } include _Iter in ArrayIter include _IterableArray in List include _IterableArray in array construct MicroMap { pairs ; construct { this | with pairs this ; pairs null eq if { 0 anew List:new =pairs } pairs:unwrap this:=pairs this } get-entry { [any,any]|null | with key this ; this:pairs:iter { mega | 0 swap:get key eq } swap:filter _:next } get-or-create-entry { [any,any] | with key this ; { [any,any] | [ key null ] dup this:pairs:push } key this:get-entry:unwrap-or } get { any | with key this ; this:pairs:iter { mega | 0 swap:get key eq } swap:filter { any | 1 swap:get } swap:map _:next } set { any | with key val this ; val 1 (key this:get-or-create-entry):set } remove { any | with key this ; this:pairs:iter { mega | 0 swap:get key eq not } swap:filter _:collect List:new =pairs } iter { ArrayIter | with this ; this:pairs:iter } } construct Range { lower upper step ; construct { this | with lower upper this ; lower _mega this:=lower upper _mega this:=upper 1 this:=step this } set-step { this | with step this ; step this:=step this } iter { RangeIter | with this ; this RangeIter:new } item { mega|null | with index this ; def itm index this:step * this:lower + =itm (itm this:upper lt) (itm this:lower lt not) and dup if { pop itm 2 stop } not if { null 2 stop } } } construct RangeIter { range idx ; construct { this | with range this ; range this:=range 0 this:=idx this } next { mega | with this ; this:idx dup ++ this:=idx this:range:item } } include _Iter in RangeIter construct shadow { } "Copy array"; func acopy { array | with arr1 arr2 idx1 idx2 len ; def i 0 =i while { i len lt } { (( i idx1 + ) arr1:get) (i idx2 +) arr2:set; i ++ =i } arr2 } func aadd { array | with arr1 arr2 ; def newarr arr1:len arr2:len + anew =newarr arr1 newarr 0 0 arr1:len acopy =newarr arr2 newarr 0 arr1:len arr2:len acopy =newarr newarr } func concat { str | with a b ; a _array b _array aadd _str } func panic { | with msg ; program-name dup if { program-name print " panicked at:" println } not if { "Program panicked at:" println } { | with it ; it println } trace:foreach "Panic message:" println " " print msg println def map env =map "SPL_PANIC_DUMP" env:get dup if { "Dumping because SPL_PANIC_DUMP is set." println null =map dyn-__dump } not if { "SPL_PLAIN_PANIC" map:get dup if { "Not dumping because SPL_PLAIN_PANIC is set." println } not if { "Type 'Yes^M' to dump. You can set SPL_PANIC_DUMP to always dump " "on panic, or SPL_PLAIN_PANIC to never dump." concat println readln "Yes" eq if { null =map dyn-__dump } } } "Exiting." println 1 exit } { | with msg this ; this not if { "Assertion failed!" panic } } "assert" "int" dyn-def-method { | with msg this ; this if { "Assertion failed!" panic } } "nassert" "int" dyn-def-method func assert-eq { any any | with a b ; a b eq not if { "Equality assertion failed!" panic } a b } func [ { shadow | "array" "shadow" settype } func ] { array | [ alit-end } func env { MicroMap | get-env List:new MicroMap:new } func ++ { mega | 1 + } func -- { mega | 1 - } func _ { | } func call-main-on-file { | with file ; "@" file concat import update-types argv main exit } func update-types { | { | with type ; { self | } "unwrap" type dyn-def-method { self | swap pop } "unwrap-or" type dyn-def-method } dyn-all-types:foreach { | with this ; "null cannot be unwrapped." panic } "unwrap" "null" dyn-def-method { any | with fb this ; fb call } "unwrap-or" "null" dyn-def-method } update-types