SNAPKITTYWEST's picture
October 2026 main drop: mirror from GitHub
d8df231 verified
Raw History Blame Contribute Delete
3.22 kB
-- Copyright (c) 2026 Ahmad Ali Parr. All rights reserved.
-- SPDX-License-Identifier: LicenseRef-Proprietary
-- Public source visibility does not grant an open-source license. See LICENSE.
module Main
import Data.Nat
%default total
||| Abstract execution status. Resource exhaustion is not successful termination.
data Status = Running | Halted | OutOfFuel | OutOfMemory | Failed
||| Minimal control term for the first machine milestone.
||| Extend only after the selected Unlambda dialect is specified.
data Term = PrimI | PrimK | PrimS | Apply Term Term | DelayedTerm Term
record Machine where
constructor MkMachine
control : Term
fuel : Nat
status : Status
||| A transition outcome always records the next explicit machine status.
data Transition = Advanced Machine | Finished Machine
||| Fuel is consumed exactly once for an ordinary transition.
consumeRunning : Term -> Nat -> Machine
consumeRunning t Z = MkMachine t Z OutOfFuel
consumeRunning t (S k) = MkMachine t k Running
consumeFuel : Machine -> Machine
consumeFuel (MkMachine t n Running) = consumeRunning t n
consumeFuel (MkMachine t n Halted) = MkMachine t n Halted
consumeFuel (MkMachine t n OutOfFuel) = MkMachine t n OutOfFuel
consumeFuel (MkMachine t n OutOfMemory) = MkMachine t n OutOfMemory
consumeFuel (MkMachine t n Failed) = MkMachine t n Failed
||| The transition function is intentionally a control-model stub until
||| the full Unlambda operational semantics are fixed in spec/.
stepControl : Machine -> Transition
stepControl m@(MkMachine _ Z Running) = Finished (consumeFuel m)
stepControl m@(MkMachine _ (S _) Running) = Advanced (consumeFuel m)
stepControl m = Finished m
||| A structural fact: consuming fuel never increases the fuel counter.
natLteRefl : (n : Nat) -> LTE n n
natLteRefl Z = LTEZero
natLteRefl (S n) = LTESucc (natLteRefl n)
natLteNext : (n : Nat) -> LTE n (S n)
natLteNext Z = LTEZero
natLteNext (S n) = LTESucc (natLteNext n)
fuelDoesNotIncrease : (m : Machine) -> fuel (consumeFuel m) `LTE` fuel m
fuelDoesNotIncrease (MkMachine t Z Running) = LTEZero
fuelDoesNotIncrease (MkMachine t (S k) Running) = natLteNext k
fuelDoesNotIncrease (MkMachine t n Halted) = natLteRefl n
fuelDoesNotIncrease (MkMachine t n OutOfFuel) = natLteRefl n
fuelDoesNotIncrease (MkMachine t n OutOfMemory) = natLteRefl n
fuelDoesNotIncrease (MkMachine t n Failed) = natLteRefl n
||| One running transition consumes exactly one unit, not two or zero.
positiveFuelConsumesOne : (t : Term) -> (n : Nat) ->
fuel (consumeFuel (MkMachine t (S n) Running)) = n
positiveFuelConsumesOne t n = Refl
||| Heap exhaustion remains distinct from generic failure and termination.
memoryExhaustionIsPreserved : (t : Term) -> (n : Nat) ->
status (consumeFuel (MkMachine t n OutOfMemory)) = OutOfMemory
memoryExhaustionIsPreserved t n = Refl
||| Resource exhaustion is explicit when a running machine has zero fuel.
zeroFuelIsNotHalted : (t : Term) -> status (consumeFuel (MkMachine t Z Running)) = OutOfFuel
zeroFuelIsNotHalted t = Refl
main : IO ()
main = do
let initial = MkMachine PrimI 1 Running
case stepControl initial of
Advanced next => putStrLn "step: advanced"
Finished next => putStrLn "step: finished"