purescript-0.15.0: tests/purs/passing/4179.purs
module Main where
import Prelude
import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Console (log)
import Test.Assert (assertEqual)
import CustomAssert (assertThrows)
force :: forall a b. (Unit -> b) -> b
force f = f unit
alpha = { backref: \_ -> bravo, x: 1 }
bravo = force \_ -> alpha.x
complicatedIdentity :: forall a. a -> a
complicatedIdentity = h
where
-- This highly contrived function tests that escalating force is caught and
-- doesn't cause an infinite loop during compilation. ("Escalating force"
-- means that invoking `f` with two argument leads to `f` being invoked with
-- three arguments, and so on.)
-- If the escalating loop in `f` isn't taken into account, `h` might be
-- initialized before `g`, which will lead to a run-time error. The intended
-- behavior is to lazily initialize `g` and `h` together, and let the fact
-- that at run time `g` never actually dereferences `h` resolve the
-- initialization ordering.
f :: forall a. Int -> { tick :: a -> a, tock :: a -> a }
f n = { tick: if n <= 0 then identity else (f (n - 1)).tock identity, tock: \a -> g n a }
g :: forall a. Int -> a -> a
g = (\bit -> if bit then \n -> (f n).tick else const h) true
h :: forall a. a -> a
h = (\n -> (f n).tick) 10
foreign import runtimeImportImpl :: forall a. Maybe String -> (String -> Maybe String) -> String -> (Maybe String -> Effect a) -> Effect a
runtimeImport :: forall a. String -> (Maybe String -> Effect a) -> Effect a
runtimeImport = runtimeImportImpl Nothing Just
type ID = forall a. a -> a
main = do
err <- assertThrows \_ ->
let
selfOwn = { a: 1, b: force \_ -> selfOwn.a }
in selfOwn
assertEqual { actual: err, expected: "ReferenceError: selfOwn was needed before it finished initializing (module Main, line 52)" }
err2 <- assertThrows \_ ->
let
f = (\_ -> { left: g identity, right: h identity }) unit
g :: ID -> ID
g x = (j x x x).right
h :: ID -> ID -> { left :: ID, right :: ID }
h x = j x x
j x y z = { left: x y z, right: f.left }
in f
assertEqual { actual: err2, expected: "ReferenceError: f was needed before it finished initializing (module Main, line 66)" }
assertEqual { actual: bravo, expected: 1 }
runtimeImport "InitializationError" \err3 -> do
assertEqual { actual: err3, expected: Just "ReferenceError: alphaArray was needed before it finished initializing (module InitializationError, line 0)" } -- TODO: fix the 0
log "Done"