From a17f289d87998b022e66a93d2b8c88a6e0334048 Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Wed, 12 Feb 2025 11:59:05 +0300 Subject: [PATCH 1/5] add `preserves-definedness` to `newEmptyModule` --- src/komet/kdist/soroban-semantics/auto-allocate.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/komet/kdist/soroban-semantics/auto-allocate.md b/src/komet/kdist/soroban-semantics/auto-allocate.md index 5a24c63..812e118 100644 --- a/src/komet/kdist/soroban-semantics/auto-allocate.md +++ b/src/komet/kdist/soroban-semantics/auto-allocate.md @@ -18,10 +18,19 @@ module WASM-AUTO-ALLOCATE syntax Stmt ::= "newEmptyModule" WasmString // ------------------------------------------- - rule newEmptyModule MODNAME => .K ... + + rule [newEmptyModule-trap]: + newEmptyModule _MODNAME => trap ... + NEXT + NEXT ... + [priority(10)] + + rule [newEmptyModule]: + newEmptyModule MODNAME => .K ... MR => MR [ MODNAME <- NEXT ] NEXT => NEXT +Int 1 ( .Bag => NEXT ... ) ... + [preserves-definedness] syntax Stmts ::= autoAllocModules ( ModuleDecl, Map ) [function] | #autoAllocModules ( Defns , Map ) [function] From 05425efa12326ba9e2b83cc4ca5260c839ab4e4f Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Tue, 21 Jul 2026 21:13:58 +0300 Subject: [PATCH 2/5] allow blockchain state changes in post-execution check --- src/komet/kasmer.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/komet/kasmer.py b/src/komet/kasmer.py index acbe5f1..f9eb5f6 100644 --- a/src/komet/kasmer.py +++ b/src/komet/kasmer.py @@ -10,7 +10,7 @@ from hypothesis import strategies from pyk.cterm import CTerm, cterm_build_claim -from pyk.kast.inner import KSort, KVariable +from pyk.kast.inner import KSequence, KSort, KVariable from pyk.kast.manip import Subst, split_config_from from pyk.kast.outer import KClaim from pyk.kast.prelude.ml import mlEqualsTrue @@ -307,10 +307,12 @@ def make_steps(*args: KInner) -> KInner: lhs_subst['ALWAYSALLOCATE_CELL'] = token(always_allocate) lhs = CTerm(Subst(lhs_subst).apply(conf), [mlEqualsTrue(c) for c in ctrs]) - rhs_subst = subst.copy() - rhs_subst['PROGRAM_CELL'] = STEPS_TERMINATOR - rhs_subst['EXITCODE_CELL'] = token(0) - del rhs_subst['ALWAYSALLOCATE_CELL'] + # Expect the root contract call to terminate successfully while allowing changes to the blockchain state + rhs_subst = { + 'PROGRAM_CELL': STEPS_TERMINATOR, + 'EXITCODE_CELL': token(0), + 'K_CELL': KSequence(), + } rhs = CTerm(Subst(rhs_subst).apply(conf)) claim, _ = cterm_build_claim(name, lhs, rhs) From 5fd2143fc94ee0495056cbc45683559ba8d91397 Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Tue, 21 Jul 2026 21:16:15 +0300 Subject: [PATCH 3/5] make bitwise rules concrete --- src/komet/kdist/soroban-semantics/data.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/komet/kdist/soroban-semantics/data.md b/src/komet/kdist/soroban-semantics/data.md index 7bde93e..7a51e72 100644 --- a/src/komet/kdist/soroban-semantics/data.md +++ b/src/komet/kdist/soroban-semantics/data.md @@ -109,35 +109,35 @@ module HOST-OBJECT | getTag(HostVal) [function, total, symbol(getTag)] | getBody(HostVal) [function, total, symbol(getBody)] // ----------------------------------------------------------------------- - rule getMajor(HostVal(I)) => I >>Int 32 - rule getMinor(HostVal(I)) => (I &Int (#pow(i32) -Int 1)) >>Int 8 - rule getTag(HostVal(I)) => I &Int 255 - rule getBody(HostVal(I)) => I >>Int 8 + rule getMajor(HostVal(I)) => I >>Int 32 [concrete] + rule getMinor(HostVal(I)) => (I &Int (#pow(i32) -Int 1)) >>Int 8 [concrete] + rule getTag(HostVal(I)) => I &Int 255 [concrete] + rule getBody(HostVal(I)) => I >>Int 8 [concrete] syntax Bool ::= isObject(HostVal) [function, total, symbol(isObject)] | isObjectTag(Int) [function, total, symbol(isObjectTag)] | isRelativeObjectHandle(HostVal) [function, total, symbol(isRelativeObjectHandle)] // -------------------------------------------------------------------------------- rule isObject(V) => isObjectTag(getTag(V)) - rule isObjectTag(TAG) => 64 <=Int TAG andBool TAG <=Int 77 + rule isObjectTag(TAG) => 64 <=Int TAG andBool TAG <=Int 77 [concrete] rule isRelativeObjectHandle(V) => getMajor(V) &Int 1 ==Int 0 syntax Int ::= indexToHandle(Int, Bool) [function, total, symbol(indexToHandle)] // -------------------------------------------------------------------------------- - rule indexToHandle(I, false) => (I < I < (I < I < getMajor(V) >>Int 1 + rule getIndex(V) => getMajor(V) >>Int 1 [concrete] syntax HostVal ::= fromHandleAndTag(Int, Int) [function, total, symbol(fromHandleAndTag)] | fromMajorMinorAndTag(Int, Int, Int) [function, total, symbol(fromMajorMinorAndTag)] | fromBodyAndTag(Int, Int) [function, total, symbol(fromBodyAndTag)] // -------------------------------------------------------------------------------- rule fromHandleAndTag(H, T) => fromMajorMinorAndTag(H, 0, T) - rule fromMajorMinorAndTag(MAJ, MIN, TAG) => fromBodyAndTag((MAJ < HostVal((BODY < fromBodyAndTag((MAJ < HostVal((BODY < Date: Tue, 21 Jul 2026 21:17:45 +0300 Subject: [PATCH 4/5] refactor `toSmallValid`/`getTag` --- .../kdist/soroban-semantics/configuration.md | 2 +- src/komet/kdist/soroban-semantics/data.md | 86 +++++++++++-------- .../kdist/soroban-semantics/host/integer.md | 4 +- src/komet/kdist/soroban-semantics/soroban.md | 2 +- 4 files changed, 54 insertions(+), 40 deletions(-) diff --git a/src/komet/kdist/soroban-semantics/configuration.md b/src/komet/kdist/soroban-semantics/configuration.md index d9b66db..cd1b3f6 100644 --- a/src/komet/kdist/soroban-semantics/configuration.md +++ b/src/komet/kdist/soroban-semantics/configuration.md @@ -256,7 +256,7 @@ If `SCV` is a small value, `allocObject(SCV)` returns a small `HostVal` directly STACK => toSmall(SCV) : STACK ALWAYS_ALLOCATE requires alwaysSmall(SCV) - orBool ( toSmallValid(SCV) andBool notBool ALWAYS_ALLOCATE ) + orBool ( isSmall(SCV) andBool notBool ALWAYS_ALLOCATE ) // recursively allocate vector items rule [allocObject-vec]: diff --git a/src/komet/kdist/soroban-semantics/data.md b/src/komet/kdist/soroban-semantics/data.md index 7a51e72..bf09856 100644 --- a/src/komet/kdist/soroban-semantics/data.md +++ b/src/komet/kdist/soroban-semantics/data.md @@ -104,6 +104,10 @@ module HOST-OBJECT imports HOST-OBJECT-SYNTAX imports WASM + syntax Int ::= unwrap(HostVal) [function, total, symbol(HostVal:unwrap)] + // --------------------------------------------------- + rule unwrap(HostVal(I)) => I + syntax Int ::= getMajor(HostVal) [function, total, symbol(getMajor)] | getMinor(HostVal) [function, total, symbol(getMinor)] | getTag(HostVal) [function, total, symbol(getTag)] @@ -143,8 +147,8 @@ module HOST-OBJECT | #quoteUnparseWasmString ( String ) [function, total] rule #quoteUnparseWasmString(S) => #unparseWasmString("\"" +String S +String "\"") - // https://github.com/stellar/stellar-protocol/blob/master/core/cap-0046-01.md#tag-values - syntax Int ::= getTag(ScVal) [function, total] +// https://github.com/stellar/stellar-protocol/blob/master/core/cap-0046-01.md#tag-values + syntax Int ::= getTag(ScVal) [function, total, symbol(getTagScVal)] // ----------------------------------------------------- rule getTag(SCBool(false)) => 0 rule getTag(SCBool(true)) => 1 @@ -152,21 +156,21 @@ module HOST-OBJECT rule getTag(Error(_,_)) => 3 rule getTag(U32(_)) => 4 rule getTag(I32(_)) => 5 - rule getTag(U64(I)) => 6 requires I <=Int #maxU64small - rule getTag(U64(I)) => 64 requires notBool( I <=Int #maxU64small ) - rule getTag(I64(I)) => 7 requires #minI64small <=Int I andBool I <=Int #maxI64small - rule getTag(I64(I)) => 65 requires notBool( #minI64small <=Int I andBool I <=Int #maxI64small ) - rule getTag(U128(I)) => 10 requires I <=Int #maxU64small - rule getTag(U128(I)) => 68 requires notBool( I <=Int #maxU64small ) // U64small and U128small have the same width - rule getTag(I128(I)) => 11 requires #minI64small <=Int I andBool I <=Int #maxI64small - rule getTag(I128(I)) => 69 requires notBool( #minI64small <=Int I andBool I <=Int #maxI64small ) - rule getTag(U256(I)) => 12 requires I <=Int #maxU64small - rule getTag(U256(I)) => 70 requires notBool( I <=Int #maxU64small ) // U64small and U128small have the same width + rule getTag(U64(_) #as I) => 6 requires isSmall(I) + rule getTag(U64(_) #as I) => 64 requires notBool(isSmall(I)) + rule getTag(I64(_) #as I) => 7 requires isSmall(I) + rule getTag(I64(_) #as I) => 65 requires notBool(isSmall(I)) + rule getTag(U128(_) #as I) => 10 requires isSmall(I) + rule getTag(U128(_) #as I) => 68 requires notBool(isSmall(I)) + rule getTag(I128(_) #as I) => 11 requires isSmall(I) + rule getTag(I128(_) #as I) => 69 requires notBool(isSmall(I)) + rule getTag(U256(_) #as I) => 12 requires isSmall(I) + rule getTag(U256(_) #as I) => 70 requires notBool(isSmall(I)) rule getTag(ScVec(_)) => 75 rule getTag(ScMap(_)) => 76 rule getTag(ScAddress(_)) => 77 - rule getTag(Symbol(BS)) => 14 requires lengthString(BS) <=Int 9 - rule getTag(Symbol(BS)) => 74 requires lengthString(BS) >Int 9 + rule getTag(Symbol(_) #as S) => 14 requires isSmall(S) + rule getTag(Symbol(_) #as S) => 74 requires notBool(isSmall(S)) rule getTag(ScBytes(_)) => 72 rule getTag(ScString(_)) => 73 @@ -299,29 +303,39 @@ module HOST-OBJECT syntax HostVal ::= toSmall(ScVal) [function, total, symbol(toSmall)] // --------------------------------------------------------------------------------- - rule toSmall(SCBool(false)) => fromMajorMinorAndTag(0, 0, 0) - rule toSmall(SCBool(true)) => fromMajorMinorAndTag(0, 0, 1) - rule toSmall(Void) => fromMajorMinorAndTag(0, 0, 2) - rule toSmall(Error(TYP, I)) => fromMajorMinorAndTag(I, ErrorType2Int(TYP), 3) - rule toSmall(U32(I)) => fromMajorMinorAndTag(I, 0, 4) - rule toSmall(I32(I)) => fromMajorMinorAndTag(#unsigned(i32, I), 0, 5) + rule toSmall(SCBool(false)) => fromMajorMinorAndTag(0, 0, 0) + rule toSmall(SCBool(true)) => fromMajorMinorAndTag(0, 0, 1) + rule toSmall(Void) => fromMajorMinorAndTag(0, 0, 2) + rule toSmall(Error(TYP, I)) => fromMajorMinorAndTag(I, ErrorType2Int(TYP), 3) + rule toSmall(U32(I)) => fromMajorMinorAndTag(I, 0, 4) + rule toSmall(I32(I)) => fromMajorMinorAndTag(#unsigned(i32, I), 0, 5) requires definedUnsigned(i32, I) - rule toSmall(U64(I)) => fromBodyAndTag(I, 6) requires I <=Int #maxU64small - rule toSmall(I64(I)) => fromBodyAndTag(#unsigned(i56, I), 7) - requires #minI64small <=Int I andBool I <=Int #maxI64small - andBool definedUnsigned(i56, I) - rule toSmall(U128(I)) => fromBodyAndTag(I, 10) requires I <=Int #maxU64small - rule toSmall(I128(I)) => fromBodyAndTag(#unsigned(i56, I), 11) - requires #minI64small <=Int I andBool I <=Int #maxI64small - andBool definedUnsigned(i56, I) - rule toSmall(U256(I)) => fromBodyAndTag(I, 12) requires I <=Int #maxU64small - rule toSmall(Symbol(S)) => fromBodyAndTag(encode6bit(S), 14) requires lengthString(S) <=Int 9 - rule toSmall(_) => HostVal(-1) [owise] - - syntax Bool ::= toSmallValid(ScVal) - [function, total, symbol(toSmallValid)] - // --------------------------------------------------------------------------------- - rule toSmallValid(VAL) => toSmall(VAL) =/=K HostVal(-1) + rule toSmall(U64(I) #as X) => fromBodyAndTag(I, 6) requires isSmall(X) + rule toSmall(I64(I) #as X) => fromBodyAndTag(#unsigned(i56, I), 7) requires isSmall(X) + rule toSmall(U128(I) #as X) => fromBodyAndTag(I, 10) requires isSmall(X) + rule toSmall(I128(I) #as X) => fromBodyAndTag(#unsigned(i56, I), 11) requires isSmall(X) + rule toSmall(U256(I) #as X) => fromBodyAndTag(I, 12) requires isSmall(X) + rule toSmall(Symbol(S) #as X) => fromBodyAndTag(encode6bit(S), 14) requires isSmall(X) + rule toSmall(_) => HostVal(-1) [owise] + + syntax Bool ::= isSmall(ScVal) [function, total, symbol(isSmall)] + // ----------------------------------------------------------------------- + rule isSmall(SCBool(_)) => true + rule isSmall(Void) => true + rule isSmall(Error(_, _)) => true + rule isSmall(U32(_)) => true + rule isSmall(I32(_)) => true + rule isSmall(U64(I)) => isSmallInt(Unsigned, I) + rule isSmall(I64(I)) => isSmallInt(Signed, I) + rule isSmall(U128(I)) => isSmallInt(Unsigned, I) + rule isSmall(I128(I)) => isSmallInt(Signed, I) + rule isSmall(Symbol(S)) => lengthString(S) <=Int 9 + rule isSmall(_) => false [owise] + + syntax Bool ::= isSmallInt(Signedness, Int) [function, total, symbol(isSmallInt)] + // ------------------------------------------------------------------------ + rule isSmallInt(Unsigned, I) => 0 <=Int I andBool I 0 -Int #pow1(i56) <=Int I andBool I returnHostVal => i64.const I ... - HostVal(I) : S => S + returnHostVal => HV ... + HV:HostVal : S => S rule [hostfun-obj-to-u64]: hostCall ( "i" , "0" , [ i64 .ValTypes ] -> [ i64 .ValTypes ] ) diff --git a/src/komet/kdist/soroban-semantics/soroban.md b/src/komet/kdist/soroban-semantics/soroban.md index 0bda5a4..644c8c5 100644 --- a/src/komet/kdist/soroban-semantics/soroban.md +++ b/src/komet/kdist/soroban-semantics/soroban.md @@ -181,7 +181,7 @@ semantics. andBool (notBool isRelativeObjectHandle(VAL)) rule [push-HostVal]: - HostVal(I) => i64.const I ... + HV:HostVal => i64.const unwrap(HV) ... ``` From fee3acf97c582da60e1caa1afa931898bf7dfd80 Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Wed, 12 Aug 2026 12:00:04 +0300 Subject: [PATCH 5/5] add lemmas --- .../kdist/soroban-semantics/komet-lemmas.md | 163 ++++++++++++++---- 1 file changed, 133 insertions(+), 30 deletions(-) diff --git a/src/komet/kdist/soroban-semantics/komet-lemmas.md b/src/komet/kdist/soroban-semantics/komet-lemmas.md index c2b9378..f6b8fb4 100644 --- a/src/komet/kdist/soroban-semantics/komet-lemmas.md +++ b/src/komet/kdist/soroban-semantics/komet-lemmas.md @@ -4,8 +4,6 @@ requires "data.md" module KSOROBAN-LEMMAS [symbolic] imports KWASM-LEMMAS - imports INT-BITWISE-LEMMAS - imports HOST-OBJECT-LEMMAS imports SOROBAN syntax InternalCmd ::= runLemma(ProofStep) | doneLemma(ProofStep) @@ -13,18 +11,7 @@ module KSOROBAN-LEMMAS [symbolic] rule runLemma(S) => doneLemma(S) ... -endmodule - -module INT-BITWISE-LEMMAS [symbolic] - imports INT - imports BOOL - - rule C |Int S => S |Int C [simplification, concrete(C), symbolic(S)] - rule X |Int 0 => X [simplification] - - rule A &Int B => B &Int A [simplification, concrete(A), symbolic(B)] - rule (A &Int B) &Int C => A &Int (B &Int C) [simplification, concrete(B, C)] - rule A &Int (B &Int C) => (A &Int B) &Int C [simplification, symbolic(A, B)] + /// Int Helpers syntax Bool ::= isPowerOf2(Int) [function, total] rule isPowerOf2(I:Int) => I ==Int 1 < (1 < 0 requires I <=Int 0 + syntax Bool ::= isTag(Int) [function, total, symbol(isTag)] + | isHostValInt(Int) [function, total, symbol(isHostValInt)] +//-------------------------------------------------------------------------- + rule isTag(TAG) => 0 <=Int TAG andBool TAG <=Int 255 + rule isHostValInt(I) => 0 <=Int I andBool I <=Int maxInt(i64, Unsigned) [concrete] + + /// Bitwise Lemmas + + rule C |Int S => S |Int C [simplification, concrete(C), symbolic(S)] + rule X |Int 0 => X [simplification] + + rule A &Int B => B &Int A [simplification, concrete(A), symbolic(B)] + rule (A &Int B) &Int C => A &Int (B &Int C) [simplification, concrete(B, C)] + rule A &Int (B &Int C) => (A &Int B) &Int C [simplification, symbolic(A, B)] + rule [modInt-to-bit-mask]: I modInt M => I &Int (M -Int 1) requires isPowerOf2(M) [simplification, concrete(M)] -endmodule + rule X &Int MASK => X + requires isFullMask(MASK) + andBool 0 <=Int X + andBool X <=Int MASK + [simplification] + + /// Integer Lemmas + + // From Wasm Semantics + // rule #signed(ITYPE, N) => N requires 0 <=Int N andBool N N -Int #pow(ITYPE) requires #pow1(ITYPE) <=Int N andBool N N +Int #pow(ITYPE) requires N N requires 0 <=Int N + + // #unsigned(T, A) is always nonnegative once definedUnsigned(T, A) holds + // (A may exceed T's signed max -- definedUnsigned allows up to T's unsigned max). + // - definedUnsigned(T, A): -#pow1(T) <= A < #pow(T) + // - 0 <= A: + // 1) 0 <= A -- branch condition + // 2) #unsigned(T, A) == A -- #unsigned's definition when 0 <= A + // 3) 0 <= #unsigned(T, A) -- substitute 2) into 1) + // - A < 0: + // 1) -#pow1(T) <= A -- definedUnsigned(T,A) + // 2) -#pow1(T) +Int #pow(T) <= A +Int #pow(T) -- add #pow(T) to both sides of 1) + // 3) #pow1(T) <= A +Int #pow(T) -- #pow(T) == 2 *Int #pow1(T) + // 4) #pow1(T) <= #unsigned(T, A) -- A +Int #pow(T) == #unsigned(T, A) since A < 0 + // 5) 0 <= #pow1(T) <= #unsigned(T, A) -- #pow1(T) >= 0 + rule [unsigned-is-nonnegative]: + 0 <=Int #unsigned(T, A) => true + requires definedUnsigned(T, A) + [simplification] + + // #unsigned(T, A) always stays below #pow(T) once definedUnsigned(T, A) holds. + // - definedUnsigned(T, A): -#pow1(T) <= A < #pow(T) + // - 0 <= A: + // 1) A < #pow(T) -- definedUnsigned(T,A) + // 2) #unsigned(T, A) == A -- #unsigned's definition when 0 <= A + // 3) #unsigned(T, A) < #pow(T) -- substitute 2) into 1) + // - A < 0: + // 1) A < 0 -- branch condition + // 2) A +Int #pow(T) < 0 +Int #pow(T) -- add #pow(T) to both sides of 1) + // 3) A +Int #pow(T) < #pow(T) -- 0 +Int #pow(T) == #pow(T) + // 4) #unsigned(T, A) < #pow(T) -- A +Int #pow(T) == #unsigned(T, A) since A < 0 + rule [unsigned-upper-bound]: + #unsigned(T, A) true + requires POW_T ==Int #pow(T) + andBool definedUnsigned(T, A) + [simplification] + + // Round-trip identity: #unsigned packs a signed A into T's unsigned range, + // #signed unpacks it back out. Only recovers A when A was already in T's + // signed range (-#pow1(T) <= A < #pow1(T), tighter than definedUnsigned): + // - 0 <= A (so 0 <= A < #pow1(T) from the requires bounds): + // 1) 0 <= A < #pow1(T) -- requires bounds, this branch + // 2) #unsigned(T, A) == A -- #unsigned's definition when 0 <= A + // 3) 0 <= #unsigned(T, A) < #pow1(T) -- substitute 2) into 1) + // 4) #signed(T, #unsigned(T, A)) == #unsigned(T, A) -- #signed's definition when 0 <= N < #pow1(T), via 3) + // 5) #signed(T, #unsigned(T, A)) == A -- substitute 2) into 4) + // - A < 0 (so -#pow1(T) <= A < 0 from the requires bounds): + // 1) -#pow1(T) <= A < 0 -- requires bounds, this branch + // 2) #unsigned(T, A) == A +Int #pow(T) -- #unsigned's definition when A < 0 + // 3) -#pow1(T) +Int #pow(T) <= A +Int #pow(T) < 0 +Int #pow(T) -- add #pow(T) to all sides of 1) + // 4) #pow1(T) <= A +Int #pow(T) < #pow(T) -- #pow(T) == 2 *Int #pow1(T) + // 5) #pow1(T) <= #unsigned(T, A) < #pow(T) -- substitute 2) into 4) + // 6) #signed(T, #unsigned(T, A)) == #unsigned(T, A) -Int #pow(T) -- #signed's definition when #pow1(T) <= N < #pow(T), via 5) + // 7) #signed(T, #unsigned(T, A)) == A +Int #pow(T) -Int #pow(T) -- substitute 2) into 6) + // 8) #signed(T, #unsigned(T, A)) == A -- simplify 7) + rule [signed-of-unsigned]: + #signed( T , #unsigned( T , A ) ) => A + requires 0 -Int #pow1(T) <=Int A + andBool A T &Int MASK - requires isFullMask(MASK) andBool SHIFT >=Int log2Int(MASK +Int 1) - [simplification, concrete(SHIFT, MASK)] + /// HostVal Lemmas - // #getRange(_,_,8)'s result always fits in 64-bit - rule #getRange(SB, ADDR, 8) &Int 18446744073709551615 => #getRange(SB, ADDR, 8) + rule [getBody-of-fromBodyAndTag]: + getBody(fromBodyAndTag(BODY, _TAG)) => BODY [simplification] + rule [getTag-of-fromBodyAndTag]: + getTag(fromBodyAndTag(_BODY, TAG)) => TAG + [simplification] - rule #getRange(#setRange(_BM, ADDR, VAL, WIDTH), ADDR', WIDTH') => #wrap(WIDTH', VAL) - requires 0 <=Int ADDR - andBool 0 MAJ [simplification] + rule [getMinor-of-fromMajorMinorAndTag]: + getMinor(fromMajorMinorAndTag(_MAJ, MIN, _TAG)) => MIN + [simplification] + + rule [getTag-of-fromMajorMinorAndTag]: + getTag(fromMajorMinorAndTag(_MAJ, _MIN, TAG)) => TAG + [simplification] + + + rule [bitwise-to-getTag]: + unwrap( HV:HostVal ) &Int 255 => getTag( HV ) + [simplification] + + rule I &Int 18446744073709551615 => I + requires isHostValInt(I) + [simplification] + + rule isHostValInt( unwrap(_:HostVal) ) => true [simplification] + + rule [shrs-to-getBody]: + i64 . shr_s unwrap(HV:HostVal) 8 => #extends(i64, i56, getBody(HV)) + [simplification] + + rule [shrs-skip-tag]: + i64 . shr_s unwrap(HV:HostVal) W => #applyIBinOpToVal( + i64 , shr_s, + i64 . shr_s unwrap(HV) 8, + (W -Int 8) + ) + requires 8 T . OP #get(X1) #get(X2) + rule #applyIBinOpToVal(_, _, _, _) => undefined [owise] + endmodule ```