/*---------------------------------------------------------------------------
  Copyright 2012-2024, Microsoft Research, Daan Leijen.

  This is free software; you can redistribute it and/or modify it under the
  terms of the Apache License, Version 2.0. A copy of the License can be
  found in the LICENSE file at the root of this distribution.
---------------------------------------------------------------------------*/

/* Core functions.

   This module is implicitly imported and all functions and types
   are always available.
   Some types and operations are required to be defined for the compiler
   to work correctly (i.e. types like `:exn` or `:list`)
*/
module std/corestd/core

pub import std/core/typesstd/core/types
import std/core/undivstd/core/undiv
import std/core/unsafestd/core/unsafe
pub import std/core/hndstd/core/hnd
pub import std/core/exnstd/core/exn
pub import std/core/boolstd/core/bool
pub import std/core/orderstd/core/order
pub import std/core/charstd/core/char
pub import std/core/intstd/core/int
pub import std/core/vectorstd/core/vector
pub import std/core/bytesstd/core/bytes
pub import std/core/bslicestd/core/bslice
pub import std/core/stringstd/core/string
pub import std/core/sslicestd/core/sslice
pub import std/core/liststd/core/list
pub import std/core/maybestd/core/maybe
pub import std/core/maybe2std/core/maybe2
pub import std/core/eitherstd/core/either
pub import std/core/resultstd/core/result
pub import std/core/tuplestd/core/tuple
pub import std/core/lazystd/core/lazy
pub import std/core/showstd/core/show
pub import std/core/debugstd/core/debug
pub import std/core/delayedstd/core/delayed
pub import std/core/consolestd/core/console

extern import
  c  file "core/inline/core"
  cs file "core/inline/core.cs"

// ----------------------------------------------------------------------------
// Builtin effects
// ----------------------------------------------------------------------------

// An alias for the empty effect.
// pub alias total = <>

// An alias for pure effects: a pure function always returns the same result
// when called with the same arguments but may not terminate or raise an exception.
pub alias purestd/core/pure: E = <std/core/types/total: Eexnstd/core/exn/exn: (E, V) -> V,divstd/core/types/div: X>

// The `:global-scope` is a special type constant to denote the global scope
pub type global-scopestd/core/global-scope: S :: S

// The `:net` effect signifies a function may access the network
pub type netstd/core/net: X :: X

// The `:fsys` effect signifies a function may access the file system
pub type fsysstd/core/fsys: X :: X

// The `:ui` effect signifies a function may access the graphics system
pub type uistd/core/ui: X :: X

// The `:blocking` effect signifies that a function may block
pub type blockingstd/core/blocking: X :: X

// The `:ioc-total` effect is used for functions that perform arbitrary I/O operations, but are terminating without raising exceptions.
pub alias ioc-totalstd/core/ioc-total: E = <std/core/types/total: Endetstd/core/types/ndet: X,consolestd/core/console/console: X,netstd/core/net: X,fsysstd/core/fsys: X,uistd/core/ui: X,ststd/core/types/st: H -> E<globalstd/core/types/global: H>>

// The `:ioc` effect ("I/O as in C") is used for functions that perform arbitrary I/O operations, but raise no exceptions
pub alias iocstd/core/ioc: E = <std/core/types/total: Edivstd/core/types/div: X,ioc-totalstd/core/ioc-total: E>

// The `:io` effect is used for functions that perform arbitrary I/O operations.
pub alias iostd/core/io: E = <std/core/types/total: Eexnstd/core/exn/exn: (E, V) -> V,iocstd/core/ioc: E>

// The `:named` effect is the default umbrella effect for named effects
pub type nmdstd/core/nmd: X :: X

// The `:scope` effect is used to ensure named effects cannot escape the scope of their handler
pub type scopestd/core/scope: S -> X :: S -> X


// ----------------------------------------------------------------------------
// Standard Functions
// ----------------------------------------------------------------------------

// Apply a function `f` to a specified argument `x`.
pub fun applystd/core/apply: forall<a,b,e> (f : (a) -> e b, x : a) -> e b(ff: (_189) -> _190 _191,xx: _189)result: -> 203 202
  ff: (_189) -> _190 _191(xx: _189)

// Compose two functions `f` and `g`.
pub fun ostd/core/o: forall<a,b,c,e> (f : (a) -> e b, g : (c) -> e a) -> ((x : c) -> e b)(ff: (_227) -> _219 _220,gg: (_218) -> _219 _227)result: -> total (x : 243) -> 244 242
  fnfn: (x : _218) -> _219 _220(xx: _218) ff: (_227) -> _219 _220(gg: (_218) -> _219 _227(xx: _218))

// The `ignore` function ignores its argument.
pub fun ignorestd/core/ignore: forall<a> (x : a) -> ()( xx: $259 : aa: V )result: -> total () : (std/core/types/unit: V)std/core/types/unit: V
  (std/core/types/Unit: ())std/core/types/Unit: ()

// Return a 'constant' function that ignores its argument and always returns the same result
pub fun conststd/core/const: forall<a,b> (default : a) -> ((x : b) -> a)( defaultdefault: $272 : aa: V )result: -> total (x : 287) -> 286 : totalstd/core/types/total: E (( x : bb: V ) -> astd/core/types/total: E)
  fnfn: ($273) -> $272(_) defaultdefault: $272

// Concise way to ensure two expressions have the same type.
pub fun same-typestd/core/same-type: forall<a> (x : a, y : a) -> a( xx: $295 : aa: V, yy: $295 : aa: V )result: -> total 303 : astd/core/types/total: E
  xx: $295

// ----------------------------------------------------------------------------
// Control statements
// ----------------------------------------------------------------------------

// The `while` fun executes `action`  as long as `pred`  is `true`.
pub fun whilestd/core/while: forall<e> (predicate : () -> <div|e> bool, action : () -> <div|e> ()) -> <div|e> ()( predicatepredicate: () -> <div|$308> bool : () -> <divstd/core/types/div: X|std/core/types/effect-extend: (X, E) -> Eee: E> boolstd/core/types/bool: V, actionaction: () -> <div|$308> () : () -> <divstd/core/types/div: X|std/core/types/effect-extend: (X, E) -> Eee: E> (std/core/types/unit: V)std/core/types/unit: V )result: -> <div|329> () : <divstd/core/types/div: X|std/core/types/effect-extend: (X, E) -> Eee: E> (std/core/types/unit: V)std/core/types/unit: V
  if predicatepredicate: () -> <div|$308> bool() then
    actionaction: () -> <div|$308> ()()
    whilestd/core/while: (predicate : () -> <div|$308> bool, action : () -> <div|$308> ()) -> <div|$308> ()(predicatepredicate: () -> <div|$308> bool, actionaction: () -> <div|$308> ())std/core/types/Unit: ()

// The `repeat` fun executes `action`  `n`  times.
pub fun repeatstd/core/repeat: forall<e> (n : int, action : () -> e ()) -> e ()( ^nn: int : intstd/core/types/int: V, actionaction: () -> $1373 () : () -> ee: E (std/core/types/unit: V)std/core/types/unit: V )result: -> 1389 () : ee: E (std/core/types/unit: V)std/core/types/unit: V
  forstd/core/for: (n : int, action : (int) -> $1373 ()) -> $1373 ()(nn: int) fnfn: (i : int) -> $1373 ()(ii: int)
    actionaction: () -> $1373 ()()


// Executes `action`  for each integer from `start` to `end` (including `end` ).
// If `start > end`  the function returns without any call to `action` .
pub fun range/forstd/core/range/for: forall<e> (start : int, end : int, action : (int) -> e ()) -> e ()( ^startstart: int: intstd/core/types/int: V, endend: int : intstd/core/types/int: V, actionaction: (int) -> $1275 () : (intstd/core/types/int: V) -> ee: E (std/core/types/unit: V)std/core/types/unit: V )result: -> 1344 () : ee: E (std/core/types/unit: V)std/core/types/unit: V
  fun reprep: (i : int) -> $1275 ()( ^ii: int : intstd/core/types/int: V )result: -> $1275 ()
    if ii: int <=std/core/int/(<=): (x : int, y : int) -> $1275 bool endend: int then
      actionaction: (int) -> $1275 ()(ii: int)
      reprep: (i : int) -> $1275 ()(pretend-decreasingstd/core/undiv/pretend-decreasing: (x : int) -> $1275 int(ii: int.incstd/core/int/inc: (i : int) -> $1275 int))std/core/types/Unit: ()
  reprep: (i : int) -> $1275 ()(startstart: int)

// Executes `action` `n` times for each integer from `0` to `n - 1`.
// If `n <= 0`  the function returns without any call to `action` .
pub fun forstd/core/for: forall<e> (n : int, action : (int) -> e ()) -> e ()( ^nn: int : intstd/core/types/int: V, actionaction: (int) -> $1348 () : (intstd/core/types/int: V) -> ee: E (std/core/types/unit: V)std/core/types/unit: V )result: -> 1367 () : ee: E (std/core/types/unit: V)std/core/types/unit: V
  range/forstd/core/range/for: (start : int, end : int, action : (int) -> $1348 ()) -> $1348 ()(0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
, nn: int -std/core/int/(-): (x : int, y : int) -> $1348 int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
, actionaction: (int) -> $1348 ()
) // Executes `action` for each integer between `start` to `end` (including `end` ). // If `start > end` the function returns without any call to `action` . // If `action` returns `Just`, the iteration is stopped and the result returned pub fun range/for-whilestd/core/range/for-while: forall<a,e> (start : int, end : int, action : (int) -> e maybe<a>) -> e maybe<a>( startstart: int: intstd/core/types/int: V, endend: int : intstd/core/types/int: V, actionaction: (int) -> $1394 maybe<$1393> : (intstd/core/types/int: V) -> ee: E maybestd/core/types/maybe: V -> V<aa: V> )result: -> 1487 maybe<1486> : ee: E maybestd/core/types/maybe: V -> V<aa: V> fun reprep: (i : int) -> $1394 maybe<$1393>( ii: int : intstd/core/types/int: V )result: -> $1394 maybe<$1393> if ii: int <=std/core/int/(<=): (x : int, y : int) -> $1394 bool endend: int then match actionaction: (int) -> $1394 maybe<$1393>(ii: int) Nothingstd/core/types/Nothing: forall<a> maybe<a> -> reprep: (i : int) -> $1394 maybe<$1393>(pretend-decreasingstd/core/undiv/pretend-decreasing: (x : int) -> $1394 int(ii: int.incstd/core/int/inc: (i : int) -> $1394 int)) Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(xx: $1393) -> Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(xx: $1393) else Nothingstd/core/types/Nothing: forall<a> maybe<a> reprep: (i : int) -> $1394 maybe<$1393>(startstart: int) // Executes `action` for each integer between [0,`n`) (excluding `n` ). // If `n <= 0` the function returns without any call to `action` . // If `action` returns `Just`, the iteration is stopped and the result returned pub fun for-whilestd/core/for-while: forall<a,e> (n : int, action : (int) -> e maybe<a>) -> e maybe<a>( nn: int : intstd/core/types/int: V, actionaction: (int) -> $1495 maybe<$1494> : (intstd/core/types/int: V) -> ee: E maybestd/core/types/maybe: V -> V<aa: V> )result: -> 1522 maybe<1521> : ee: E maybestd/core/types/maybe: V -> V<aa: V> range/for-whilestd/core/range/for-while: (start : int, end : int, action : (int) -> $1495 maybe<$1494>) -> $1495 maybe<$1494>(0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
, nn: int -std/core/int/(-): (x : int, y : int) -> $1495 int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
, actionaction: (int) -> $1495 maybe<$1494>
) // Fold over the integers between [`start`,`end`] (including `end`). pub fun range/foldstd/core/range/fold: forall<a,e> (start : int, end : int, init : a, f : (int, a) -> e a) -> e a( startstart: int : intstd/core/types/int: V, endend: int : intstd/core/types/int: V, initinit: $741 : aa: V, ff: (int, $741) -> $742 $741 : (intstd/core/types/int: V,aa: V) -> ee: E aa: V )result: -> 824 823 : ee: E aa: V if startstart: int >std/core/int/(>): (x : int, y : int) -> $742 bool endend: int then initinit: $741 else val xx: $741 = ff: (int, $741) -> $742 $741(startstart: int,initinit: $741) foldstd/core/range/fold: (start : int, end : int, init : $741, f : (int, $741) -> $742 $741) -> $742 $741(pretend-decreasingstd/core/undiv/pretend-decreasing: (x : int) -> $742 int(startstart: int.incstd/core/int/inc: (i : int) -> $742 int), endend: int, xx: $741, ff: (int, $741) -> $742 $741) // Fold over the integers between [0,`upto`) (excluding `upto`). pub fun foldstd/core/fold: forall<a,e> (upto : int, init : a, f : (int, a) -> e a) -> e a( uptoupto: int : intstd/core/types/int: V, initinit: $712 : aa: V, ff: (int, $712) -> $713 $712 : (intstd/core/types/int: V,aa: V) -> ee: E aa: V )result: -> 740 739 : ee: E aa: V range/foldstd/core/range/fold: (start : int, end : int, init : $712, f : (int, $712) -> $713 $712) -> $713 $712( 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
, uptoupto: int.decstd/core/int/dec: (i : int) -> $713 int, initinit: $712, ff: (int, $712) -> $713 $712
) // Fold over the integers between [`start`,`end`] (including `end`) or until `f` returns `Nothing` pub fun range/fold-whilestd/core/range/fold-while: forall<a,e> (start : int, end : int, init : a, f : (int, a) -> e maybe<a>) -> e a( startstart: int : intstd/core/types/int: V, endend: int : intstd/core/types/int: V, initinit: $870 : aa: V, ff: (int, $870) -> $871 maybe<$870> : (intstd/core/types/int: V,aa: V) -> ee: E maybestd/core/types/maybe: V -> V<aa: V> )result: -> 961 960 : ee: E aa: V if startstart: int >std/core/int/(>): (x : int, y : int) -> $871 bool endend: int then initinit: $870 else match ff: (int, $870) -> $871 maybe<$870>(startstart: int,initinit: $870) Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(xx: $870) -> range/fold-whilestd/core/range/fold-while: (start : int, end : int, init : $870, f : (int, $870) -> $871 maybe<$870>) -> $871 $870(pretend-decreasingstd/core/undiv/pretend-decreasing: (x : int) -> $871 int(startstart: int.incstd/core/int/inc: (i : int) -> $871 int), endend: int, xx: $870, ff: (int, $870) -> $871 maybe<$870>) Nothingstd/core/types/Nothing: forall<a> maybe<a> -> initinit: $870 // Fold over the integers between [0,`n`) (excluding `n`) or until `f` returns `Nothing` pub fun fold-whilestd/core/fold-while: forall<a,e> (n : int, init : a, f : (int, a) -> e maybe<a>) -> e a( nn: int : intstd/core/types/int: V, initinit: $841 : aa: V, ff: (int, $841) -> $842 maybe<$841> : (intstd/core/types/int: V,aa: V) -> ee: E maybestd/core/types/maybe: V -> V<aa: V> )result: -> 869 868 : ee: E aa: V range/fold-whilestd/core/range/fold-while: (start : int, end : int, init : $841, f : (int, $841) -> $842 maybe<$841>) -> $842 $841( 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
, nn: int.decstd/core/int/dec: (i : int) -> $842 int, initinit: $841, ff: (int, $841) -> $842 maybe<$841>
) // ---------------------------------------------------------------------------- // Generic equality and comparison // ---------------------------------------------------------------------------- // Generic inequality pub fun default/(!=)std/core/default/(!=): forall<a,e> (x : a, y : a, @implicit/(==) : (a, a) -> e bool) -> e bool(xx: $418 : aa: V, yy: $418 : aa: V, (@implicit/==)?(==): ($418, $418) -> $419 bool : (aa: V,aa: V) -> ee: E boolstd/core/types/bool: V )result: -> 532 bool : ee: E boolstd/core/types/bool: V notstd/core/types/not: (b : bool) -> $419 bool(xx: $418==?(==): ($418, $418) -> $419 boolyy: $418) // Generic equality if `cmp` exists pub fun default/cmp/(==)std/core/default/cmp/(==): forall<a,e> (x : a, y : a, @implicit/cmp : (a, a) -> e order) -> e bool(xx: $339 : aa: V, yy: $339 : aa: V, @implicit/cmp?cmp: ($339, $339) -> $340 order : (aa: V,aa: V) -> ee: E orderstd/core/types/order: V )result: -> 411 bool : ee: E boolstd/core/types/bool: V match cmp?cmp: ($339, $339) -> $340 order(xx: $339,yy: $339) Eqstd/core/types/Eq: order -> Truestd/core/types/True: bool _ -> Falsestd/core/types/False: bool // Generic greater than pub fun default/cmp/(>)std/core/default/cmp/(>): forall<a,e> (x : a, y : a, @implicit/cmp : (a, a) -> e order) -> e bool(xx: $539 : aa: V, yy: $539 : aa: V, @implicit/cmp?cmp: ($539, $539) -> $540 order : (aa: V,aa: V) -> ee: E orderstd/core/types/order: V )result: -> 705 bool : ee: E boolstd/core/types/bool: V cmp?cmp: ($539, $539) -> $540 order(xx: $539,yy: $539) ==std/core/order/(==): (x : order, y : order) -> $540 bool Gtstd/core/types/Gt: order // Generic lower than pub fun default/cmp/(<)std/core/default/cmp/(<): forall<a,e> (x : a, y : a, @implicit/cmp : (a, a) -> e order) -> e bool(xx: $978 : aa: V, yy: $978 : aa: V, @implicit/cmp?cmp: ($978, $978) -> $979 order : (aa: V,aa: V) -> ee: E orderstd/core/types/order: V )result: -> 1144 bool : ee: E boolstd/core/types/bool: V cmp?cmp: ($978, $978) -> $979 order(xx: $978,yy: $978) ==std/core/order/(==): (x : order, y : order) -> $979 bool Ltstd/core/types/Lt: order // Generic greater than or equal pub fun default/cmp/(>=)std/core/default/cmp/(>=): forall<a,e> (x : a, y : a, @implicit/cmp : (a, a) -> e order) -> e bool(xx: $1151 : aa: V, yy: $1151 : aa: V, @implicit/cmp?cmp: ($1151, $1151) -> $1152 order : (aa: V,aa: V) -> ee: E orderstd/core/types/order: V )result: -> 1206 bool : ee: E boolstd/core/types/bool: V notstd/core/types/not: (b : bool) -> $1152 bool(xx: $1151 <std/core/default/cmp/(<): (x : $1151, y : $1151, @implicit/cmp : ($1151, $1151) -> $1152 order) -> $1152 bool
?cmp=?cmp
yy: $1151
) // Generic lower than or equal pub fun default/cmp/(<=)std/core/default/cmp/(<=): forall<a,e> (x : a, y : a, @implicit/cmp : (a, a) -> e order) -> e bool(xx: $1213 : aa: V, yy: $1213 : aa: V, @implicit/cmp?cmp: ($1213, $1213) -> $1214 order : (aa: V,aa: V) -> ee: E orderstd/core/types/order: V )result: -> 1268 bool : ee: E boolstd/core/types/bool: V notstd/core/types/not: (b : bool) -> $1214 bool(xx: $1213 >std/core/default/cmp/(>): (x : $1213, y : $1213, @implicit/cmp : ($1213, $1213) -> $1214 order) -> $1214 bool
?cmp=?cmp
yy: $1213
) // ---------------------------------------------------------------------------- // Main // ---------------------------------------------------------------------------- // Used by the compiler to wrap main console applications pub extern main-consolestd/core/main-console: forall<a,e> (main : () -> e a) -> e a : forall<aa: V,ee: E> ( main : () -> ee: E aa: V ) -> ee: E aa: V c "kk_main_console" cs inline "Primitive.MainConsole<##1>(#1)" js inline "(#1)()" // Return the host environment: `dotnet`, `browser`, `webworker`, `node`, or `libc`. pub extern hoststd/core/host: () -> ndet string() : ndetstd/core/types/ndet: X stringstd/core/types/string: V c "kk_get_host" cs inline "\"dotnet\"" js inline "$std_core_console._host" // The default exception handler prints an exception to the console as "uncaught". pub fun @default-exn(actionaction: () -> <console,exn|$1568> () : () -> <exnstd/core/exn/exn: (E, V) -> V,consolestd/core/console/console: X|std/core/types/effect-extend: (X, E) -> Eee: E> (std/core/types/unit: V)std/core/types/unit: V )result: -> <console|1771> () : <consolestd/core/console/console: X|std/core/types/effect-extend: (X, E) -> Eee: E> (std/core/types/unit: V)std/core/types/unit: V withwith: () -> <console,exn|$1568> () final ctl throw-exnhandler: (() -> <console,exn|$1568> ()) -> <console|$1568> ()( exnexn: exception : exceptionstd/core/exn/exception: V ) printlnstd/core/console/string/println: (s : string) -> <console|$1568> ()( "uncaught exception: "literal: string
count= 20
++std/core/types/(++): (x : string, y : string) -> <console|$1568> string exnexn: exception.showstd/core/exn/show: (exn : exception) -> <console|$1568> string ) actionaction: () -> <console,exn|$1568> ()() // ---------------------------------------------------------------------------- // Non determinism // ---------------------------------------------------------------------------- noinline val unique-countstd/core/unique-count: ref<global,int> : refstd/core/types/ref: (H, V) -> V<globalstd/core/types/global: H,intstd/core/types/int: V> = unsafe-totalstd/core/unsafe/unsafe-total: (action : () -> <alloc<global>|_1793> ref<global,int>) -> ref<global,int>{ refstd/core/types/ref: (value : int) -> <alloc<global>|_1793> ref<global,int>(0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
)
} // Returns a unique integer (modulo 32-bits). pub fun uniquestd/core/unique: () -> ndet int()result: -> ndet int : ndetstd/core/types/ndet: X intstd/core/types/int: V unsafe-totalstd/core/unsafe/unsafe-total: (action : () -> <read<global>,write<global>|_1845> int) -> ndet int val uu: int = !std/core/types/ref/(!): (ref : ref<global,int>, @implicit/hdiv : hdiv<global,int,<write<global>|_1845>>) -> <read<global>,write<global>|_1845> int
?hdiv=iev@1815
unique-countstd/core/unique-count: ref<global,int> unique-countstd/core/unique-count: ref<global,int> :=std/core/types/set: (ref : ref<global,int>, assigned : int) -> <read<global>,write<global>|_1845> () uu: int+std/core/int/(+): (x : int, y : int) -> <read<global>,write<global>|_1845> int1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
uu: int // ---------------------------------------------------------------------------- // Stream // ---------------------------------------------------------------------------- // A `:stream` is a co-inductive type representing an infinite list of elements. pub co type streamstd/core/stream: V -> V<aa: V> con Nextstd/core/Next: forall<a> (head : a, tail : stream<a>) -> stream<a>(headstd/core/stream/head: forall<a> (stream : stream<a>) -> a:aa: V, tailstd/core/stream/tail: forall<a> (stream : stream<a>) -> stream<a>: streamstd/core/stream: V -> V<aa: V> )