Compatability Layer for Tezos Client

For cross-validating this interpreter with the Tezos Client, we need a compatability layer to translate inputs/outputs back and forth.

Michelson Unparser

The unparser converts from an internal representation to Michelson source.

requires "json.md"
requires "michelson.md"

module MICHELSON-UNPARSER
  imports UNIT-TEST-COMMON-SYNTAX
  imports MICHELSON-COMMON

Core Michelson Unparsing

  // We add sorts here to simplify when terms are primitive arguments
  syntax ApplicationData ::= Pair | OrData | OptionData
  syntax Data ::= ApplicationData
  syntax Data ::= Entrypoint

  // Michelson IR Unparsing Entrypoint
  syntax String ::= #unparse(K) [function]
  rule #unparse(O) => #doUnparse(O, false)

  // First argument is term to unparse, second arg is true iff term is a primitive argument
  syntax String ::= #doUnparse(K, Bool) [function]

  rule #doUnparse(Elt D1:Data D2:Data, false) =>
    "Elt " +String
    #doUnparse(D1, true)
    +String " " +String
    #doUnparse(D2, true)

  rule #doUnparse(D1:Data ; DL:DataList, _) =>
    #doUnparse(D1, false) +String
    " ; " +String
    #doUnparse(DL, false)

  rule #doUnparse(M1:MapEntry ; ML:MapEntryList, _) =>
    #doUnparse(M1, false) +String
    " ; " +String
    #doUnparse(ML, false)

  syntax String ::= #unparseTypeAnnotation(TypeAnnotation) [function, functional, hook(STRING.token2string)]
  syntax String ::= #unparseVariableAnnotation(VariableAnnotation) [function, functional, hook(STRING.token2string)]
  syntax String ::= #unparseFieldAnnotation(FieldAnnotation) [function, functional, hook(STRING.token2string)]

  rule #doUnparse(A, _) => #unparseTypeAnnotation(A)
  rule #doUnparse(A, _) => #unparseVariableAnnotation(A)
  rule #doUnparse(A, _) => #unparseFieldAnnotation(A)

  rule #doUnparse(.AnnotationList, _) => ""

  rule #doUnparse(A:Annotation AL:AnnotationList, _) =>
    #doUnparse(A, false) +String
    " " +String
    #doUnparse(AL, false)

  rule #doUnparse(Pair D1 DL:NePairDataList, false) =>
    "Pair " +String
    #doUnparse(D1, true) +String
    " " +String
    #doUnparse(DL, true)

  rule #doUnparse(D1:Data DL:NePairDataList, true) =>
    #doUnparse(D1, true) +String
    " " +String
    #doUnparse(DL, true)

  rule #doUnparse(Left D, false) => "Left " +String #doUnparse(D, true)
  rule #doUnparse(Right D, false) => "Right " +String #doUnparse(D, true)

  rule #doUnparse(Some D, false) => "Some " +String #doUnparse(D, true)
  rule #doUnparse(None, false) => "None"

  rule #doUnparse(D:ApplicationData, true) => "(" +String #doUnparse(D, false) +String ")"

  rule #doUnparse({ ML:MapEntryList }, _) => "{" +String #doUnparse(ML, false) +String "}"
  rule #doUnparse({ DL:DataList }, _) => "{" +String #doUnparse(DL, false) +String "}"
  rule #doUnparse({ }, _) => "{ }"

  rule #doUnparse(I:Int, _) => Int2String(I)
  rule #doUnparse(S:String, _) => "\"" +String S +String "\""

  syntax String ::= #unparseBytes(Bytes, Int, String) [function, functional]
  // -----------------------------------------------------------------------
  rule #unparseBytes(B, N, S) => #unparseBytes(B, N +Int 1, S +String #Char2Hex(B[N]))
    requires N >=Int 0 andBool N <Int lengthBytes(B)
  rule #unparseBytes(B, N, S) => S
    requires N >=Int lengthBytes(B)

  syntax String ::= #Char2Hex(Int)    [function]
                  | #Char2Hex(String) [function]
  // -------------------------------------------
  rule #Char2Hex(I:Int)    => #Char2Hex(Base2String(I, 16))
  rule #Char2Hex(S:String) => S             requires lengthString(S) ==Int 2
  rule #Char2Hex(S:String) => "0" +String S requires lengthString(S) ==Int 1

  rule #doUnparse(M, _) => #unparseBytes(M, 0, "0x")

  rule #doUnparse(true, _) => "True"
  rule #doUnparse(false, _) => "False"

  rule #doUnparse(#token("True", "MichelsonBoolToken"), _) => "True"
  rule #doUnparse(#token("False","MichelsonBoolToken"), _) => "False"

  rule #doUnparse(Unit, _) => "Unit"

  rule #doUnparse(#Timestamp(I), _) => #doUnparse(I, false)
  rule #doUnparse(#ChainId(I), _) => #doUnparse(I, false)
  rule #doUnparse(#KeyHash(S), _) => #doUnparse(S, false)
  rule #doUnparse(#Mutez(I), _) => #doUnparse(I, false)
  rule #doUnparse(#Address(S), _) => #doUnparse(S, false)
  rule #doUnparse(#Contract(A, _), _) => #doUnparse(#ToString(A), false)
  rule #doUnparse(#Key(S), _) => #doUnparse(S, false)
  rule #doUnparse(#Signature(S), _) => #doUnparse(S, false)
  rule #doUnparse(EP:Entrypoint, _) => #doUnparse(#ToString(EP), false)

  // Unparse types.

  rule #doUnparse(int, _) => "int"
  rule #doUnparse(nat, _) => "nat"
  rule #doUnparse(string, _) => "string"
  rule #doUnparse(bytes, _) => "bytes"
  rule #doUnparse(mutez, _) => "mutez"
  rule #doUnparse(bool, _) => "bool"
  rule #doUnparse(key_hash, _) => "key_hash"
  rule #doUnparse(timestamp, _) => "timestamp"
  rule #doUnparse(address, _) => "address"
  rule #doUnparse(key, _) => "key"
  rule #doUnparse(unit, _) => "unit"
  rule #doUnparse(signature, _) => "signature"
  rule #doUnparse(operation, _) => "operation"
  rule #doUnparse(chain_id, _) => "chain_id"
  rule #doUnparse(option, _) => "option"
  rule #doUnparse(list, _) => "list"
  rule #doUnparse(set, _) => "set"
  rule #doUnparse(contract, _) => "contract"
  rule #doUnparse(pair, _) => "pair"
  rule #doUnparse(or, _) => "or"
  rule #doUnparse(lambda, _) => "lambda"
  rule #doUnparse(map, _) => "map"
  rule #doUnparse(big_map, _) => "big_map"

  rule #doUnparse(T:NullaryTypeName (A AL):AnnotationList, false) =>
    #doUnparse(T, false) +String
    " " +String
    #doUnparse(A AL, false)

  rule #doUnparse(T:NullaryTypeName (A AL):AnnotationList, true) =>
    "(" +String #doUnparse(T (A AL), false) +String ")"

  rule #doUnparse(T:NullaryTypeName .AnnotationList, _) => #doUnparse(T, false)

  rule #doUnparse(TyName:UnaryTypeName AL:AnnotationList T, false) =>
    #doUnparse(TyName, false) +String
    " " +String
    #doUnparse(AL, false) +String
    " " +String
    #doUnparse(T, true)

  rule #doUnparse(TyName:UnaryTypeName AL:AnnotationList T, true) =>
    "(" +String #doUnparse(TyName AL T, false) +String ")"

  rule #doUnparse(TyName:BinaryTypeName AL:AnnotationList T1 T2, false) =>
    #doUnparse(TyName, false) +String
    " " +String
    #doUnparse(AL, false) +String
    " " +String
    #doUnparse(T1, true) +String
    " " +String
    #doUnparse(T2, true)

  rule #doUnparse(TyName:BinaryTypeName AL:AnnotationList T1 T2, true) =>
    "(" +String #doUnparse(TyName AL T1 T2, false) +String ")"

  rule #doUnparse(TyName:BinaryPlusTypeName AL:AnnotationList T1:Type TL:NeTypeList, false) =>
    #doUnparse(TyName, false) +String
    " " +String
    #doUnparse(AL, false) +String
    " " +String
    #doUnparse(T1 TL, true)

  rule #doUnparse(TyName:BinaryPlusTypeName AL:AnnotationList T1:Type TL:NeTypeList, true) =>
    "(" +String #doUnparse(TyName AL T1 TL, false) +String ")"

  rule #doUnparse(T1:Type TL:NeTypeList, B:Bool) => #doUnparse(T1, B) +String " " +String #doUnparse(TL, B)

  rule #doUnparse(DROP AList, _) => "DROP" +String #doUnparse(AList, false)
  rule #doUnparse(DROP AList I:Int, _) => "DROP" +String #doUnparse(AList, false) +String " " +String #doUnparse(I, true)
  rule #doUnparse(DIG AList I, _) => "DIG" +String #doUnparse(AList, false) +String " " +String #doUnparse(I, true)
  rule #doUnparse(DUG AList I, _) => "DUG" +String #doUnparse(AList, false) +String " " +String #doUnparse(I, true)
  rule #doUnparse(DUP AList, _) => "DUP" +String #doUnparse(AList, false)
  rule #doUnparse(SWAP AList, _) => "SWAP" +String #doUnparse(AList, false)
  rule #doUnparse(PUSH AList T D, _) => "PUSH" +String #doUnparse(AList, false) +String " " +String #doUnparse(T, true) +String " " +String #doUnparse(D, true)
  rule #doUnparse(SOME AList, _) => "SOME" +String #doUnparse(AList, false)
  rule #doUnparse(NONE AList T, _) => "NONE" +String #doUnparse(AList, false) +String " " +String #doUnparse(T, true)
  rule #doUnparse(UNIT AList, _) => "UNIT" +String #doUnparse(AList, false)
  rule #doUnparse(IF_NONE AList B1 B2, _) => "IF_NONE" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(PAIR AList, _) => "PAIR" +String #doUnparse(AList, false)
  rule #doUnparse(UNPAIR AList, _) => "UNPAIR" +String #doUnparse(AList, false)
  rule #doUnparse(CAR AList, _) => "CAR" +String #doUnparse(AList, false)
  rule #doUnparse(CDR AList, _) => "CDR" +String #doUnparse(AList, false)
  rule #doUnparse(LEFT AList T, _) => "LEFT" +String #doUnparse(AList, false) +String " " +String #doUnparse(T, true)
  rule #doUnparse(RIGHT AList T, _) => "RIGHT" +String #doUnparse(AList, false) +String " " +String #doUnparse(T, true)
  rule #doUnparse(IF_LEFT AList B1 B2, _) => "IF_LEFT" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(IF_RIGHT AList B1 B2, _) => "IF_RIGHT" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(NIL AList T, _) => "NIL" +String #doUnparse(AList, false) +String " " +String #doUnparse(T, true)
  rule #doUnparse(CONS AList, _) => "CONS" +String #doUnparse(AList, false)
  rule #doUnparse(IF_CONS AList B1 B2, _) => "IF_CONS" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(SIZE AList, _) => "SIZE" +String #doUnparse(AList, false)
  rule #doUnparse(EMPTY_SET AList T, _) => "EMPTY_SET" +String #doUnparse(AList, false) +String " " +String #doUnparse(T, true)
  rule #doUnparse(EMPTY_MAP AList T1 T2, _) => "EMPTY_MAP" +String #doUnparse(AList, false) +String " " +String #doUnparse(T1, true) +String " " +String #doUnparse(T2, true)
  rule #doUnparse(EMPTY_BIG_MAP AList T1 T2, _) => "EMPTY_BIG_MAP" +String #doUnparse(AList, false) +String " " +String #doUnparse(T1, true) +String " " +String #doUnparse(T2, true)
  rule #doUnparse(MAP AList B, _) => "MAP" +String #doUnparse(AList, false) +String " " +String #doUnparse(B, true)
  rule #doUnparse(ITER AList B, _) => "ITER" +String #doUnparse(AList, false) +String " " +String #doUnparse(B, true)
  rule #doUnparse(MEM AList, _) => "MEM" +String #doUnparse(AList, false)
  rule #doUnparse(GET AList, _) => "GET" +String #doUnparse(AList, false)
  rule #doUnparse(UPDATE AList, _) => "UPDATE" +String #doUnparse(AList, false)
  rule #doUnparse(IF AList B1 B2, _) => "IF" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(LOOP AList B, _) => "LOOP" +String #doUnparse(AList, false) +String " " +String #doUnparse(B, true)
  rule #doUnparse(LOOP_LEFT AList B, _) => "LOOP_LEFT" +String #doUnparse(AList, false) +String " " +String #doUnparse(B, true)
  rule #doUnparse(LAMBDA AList T1 T2 B, _) => "LAMBDA" +String #doUnparse(AList, false) +String " " +String #doUnparse(T1, true) +String " " +String #doUnparse(T2, true) +String " " +String #doUnparse(B, true)
  rule #doUnparse(EXEC AList, _) => "EXEC" +String #doUnparse(AList, false)
  rule #doUnparse(APPLY AList, _) => "APPLY" +String #doUnparse(AList, false)
  rule #doUnparse(DIP AList B, _) => "DIP" +String #doUnparse(AList, false) +String " " +String #doUnparse(B, true)
  rule #doUnparse(DIP AList I:Int B, _) => "DIP" +String #doUnparse(AList, false) +String " " +String #doUnparse(I, true) +String " " +String #doUnparse(B, true)
  rule #doUnparse(FAILWITH AList, _) => "FAILWITH" +String #doUnparse(AList, false)
  rule #doUnparse(CAST AList, _) => "CAST" +String #doUnparse(AList, false)
  rule #doUnparse(RENAME AList, _) => "RENAME" +String #doUnparse(AList, false)
  rule #doUnparse(CONCAT AList, _) => "CONCAT" +String #doUnparse(AList, false)
  rule #doUnparse(SLICE AList, _) => "SLICE" +String #doUnparse(AList, false)
  rule #doUnparse(PACK AList, _) => "PACK" +String #doUnparse(AList, false)
  rule #doUnparse(UNPACK AList T, _) => "UNPACK" +String #doUnparse(AList, false) +String " " +String #doUnparse(T, true)
  rule #doUnparse(ADD AList, _) => "ADD" +String #doUnparse(AList, false)
  rule #doUnparse(SUB AList, _) => "SUB" +String #doUnparse(AList, false)
  rule #doUnparse(MUL AList, _) => "MUL" +String #doUnparse(AList, false)
  rule #doUnparse(EDIV AList, _) => "EDIV" +String #doUnparse(AList, false)
  rule #doUnparse(ABS AList, _) => "ABS" +String #doUnparse(AList, false)
  rule #doUnparse(ISNAT AList, _) => "ISNAT" +String #doUnparse(AList, false)
  rule #doUnparse(INT AList, _) => "INT" +String #doUnparse(AList, false)
  rule #doUnparse(NEG AList, _) => "NEG" +String #doUnparse(AList, false)
  rule #doUnparse(LSL AList, _) => "LSL" +String #doUnparse(AList, false)
  rule #doUnparse(LSR AList, _) => "LSR" +String #doUnparse(AList, false)
  rule #doUnparse(OR AList, _) => "OR" +String #doUnparse(AList, false)
  rule #doUnparse(AND AList, _) => "AND" +String #doUnparse(AList, false)
  rule #doUnparse(XOR AList, _) => "XOR" +String #doUnparse(AList, false)
  rule #doUnparse(NOT AList, _) => "NOT" +String #doUnparse(AList, false)
  rule #doUnparse(COMPARE AList, _) => "COMPARE" +String #doUnparse(AList, false)
  rule #doUnparse(EQ AList, _) => "EQ" +String #doUnparse(AList, false)
  rule #doUnparse(NEQ AList, _) => "NEQ" +String #doUnparse(AList, false)
  rule #doUnparse(LT AList, _) => "LT" +String #doUnparse(AList, false)
  rule #doUnparse(GT AList, _) => "GT" +String #doUnparse(AList, false)
  rule #doUnparse(LE AList, _) => "LE" +String #doUnparse(AList, false)
  rule #doUnparse(GE AList, _) => "GE" +String #doUnparse(AList, false)
  rule #doUnparse(SELF AList, _) => "SELF" +String #doUnparse(AList, false)
  rule #doUnparse(CONTRACT AList T, _) => "CONTRACT" +String #doUnparse(AList, false) +String " " +String #doUnparse(T, true)
  rule #doUnparse(TRANSFER_TOKENS AList, _) => "TRANSFER_TOKENS" +String #doUnparse(AList, false)
  rule #doUnparse(SET_DELEGATE AList, _) => "SET_DELEGATE" +String #doUnparse(AList, false)
  rule #doUnparse(CREATE_ACCOUNT AList, _) => "CREATE_ACCOUNT" +String #doUnparse(AList, false)
  rule #doUnparse(IMPLICIT_ACCOUNT AList, _) => "IMPLICIT_ACCOUNT" +String #doUnparse(AList, false)
  rule #doUnparse(NOW AList, _) => "NOW" +String #doUnparse(AList, false)
  rule #doUnparse(CHAIN_ID AList, _) => "CHAIN_ID" +String #doUnparse(AList, false)
  rule #doUnparse(AMOUNT AList, _) => "AMOUNT" +String #doUnparse(AList, false)
  rule #doUnparse(BALANCE AList, _) => "BALANCE" +String #doUnparse(AList, false)
  rule #doUnparse(CHECK_SIGNATURE AList, _) => "CHECK_SIGNATURE" +String #doUnparse(AList, false)
  rule #doUnparse(BLAKE2B AList, _) => "BLAKE2B" +String #doUnparse(AList, false)
  rule #doUnparse(SHA256 AList, _) => "SHA256" +String #doUnparse(AList, false)
  rule #doUnparse(SHA512 AList, _) => "SHA512" +String #doUnparse(AList, false)
  rule #doUnparse(HASH_KEY AList, _) => "HASH_KEY" +String #doUnparse(AList, false)
  rule #doUnparse(STEPS_TO_QUOTA AList, _) => "STEPS_TO_QUOTA" +String #doUnparse(AList, false)
  rule #doUnparse(SOURCE AList, _) => "SOURCE" +String #doUnparse(AList, false)
  rule #doUnparse(SENDER AList, _) => "SENDER" +String #doUnparse(AList, false)
  rule #doUnparse(ADDRESS AList, _) => "ADDRESS" +String #doUnparse(AList, false)
  rule #doUnparse(CREATE_CONTRACT AList { C }, _) => "CREATE_CONTRACT" +String #doUnparse(AList, false) +String " {" +String #doUnparse(C, true) +String "}"

Macro Unparsing

  rule #doUnparse(CMPEQ AList, _) => "CMPEQ" +String #doUnparse(AList, false)
  rule #doUnparse(CMPNEQ AList, _) => "CMPNEQ" +String #doUnparse(AList, false)
  rule #doUnparse(CMPLT AList, _) => "CMPLT" +String #doUnparse(AList, false)
  rule #doUnparse(CMPGT AList, _) => "CMPGT" +String #doUnparse(AList, false)
  rule #doUnparse(CMPLE AList, _) => "CMPLE" +String #doUnparse(AList, false)
  rule #doUnparse(CMPGE AList, _) => "CMPGE" +String #doUnparse(AList, false)

  rule #doUnparse(IFEQ AList B1 B2, _) => "IFEQ" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(IFNEQ AList B1 B2, _) => "IFNEQ" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(IFLT AList B1 B2, _) => "IFLT" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(IFGT AList B1 B2, _) => "IFGT" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(IFLE AList B1 B2, _) => "IFLE" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(IFGE AList B1 B2, _) => "IFGE" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(IFCMPEQ AList B1 B2, _) => "IFCMPEQ" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(IFCMPNEQ AList B1 B2, _) => "IFCMPNEQ" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(IFCMPLT AList B1 B2, _) => "IFCMPLT" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(IFCMPGT AList B1 B2, _) => "IFCMPGT" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(IFCMPLE AList B1 B2, _) => "IFCMPLE" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)
  rule #doUnparse(IFCMPGE AList B1 B2, _) => "IFCMPGE" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)

  rule #doUnparse(FAIL AList, _) => "FAIL" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT AList, _) => "ASSERT" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_EQ AList, _) => "ASSERT_EQ" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_NEQ AList, _) => "ASSERT_NEQ" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_LT AList, _) => "ASSERT_LT" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_LE AList, _) => "ASSERT_LE" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_GT AList, _) => "ASSERT_GT" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_GE AList, _) => "ASSERT_GE" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_CMPEQ AList, _) => "ASSERT_CMPEQ" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_CMPNEQ AList, _) => "ASSERT_CMPNEQ" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_CMPLT AList, _) => "ASSERT_CMPLT" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_CMPLE AList, _) => "ASSERT_CMPLE" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_CMPGT AList, _) => "ASSERT_CMPGT" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_CMPGE AList, _) => "ASSERT_CMPGE" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_NONE AList, _) => "ASSERT_NONE" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_SOME AList, _) => "ASSERT_SOME" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_LEFT AList, _) => "ASSERT_LEFT" +String #doUnparse(AList, false)
  rule #doUnparse(ASSERT_RIGHT AList, _) => "ASSERT_RIGHT" +String #doUnparse(AList, false)

  rule #doUnparse(IF_SOME AList B1 B2, _) => "IF_SOME" +String #doUnparse(AList, false) +String " " +String #doUnparse(B1, true) +String " " +String #doUnparse(B2, true)

  rule #doUnparse(SET_CAR AList, _) => "SET_CAR" +String #doUnparse(AList, false)
  rule #doUnparse(SET_CDR AList, _) => "SET_CDR" +String #doUnparse(AList, false)

  rule #doUnparse(MAP_CAR AList Body, _) => "MAP_CAR" +String #doUnparse(AList, false) +String " " +String #doUnparse(Body,false)
  rule #doUnparse(MAP_CDR AList Body, _) => "MAP_CDR" +String #doUnparse(AList, false) +String " " +String #doUnparse(Body,false)

  rule #doUnparse(DUP AList N:Int, _) => "DUP" +String #doUnparse(AList, false) +String " " +String #doUnparse(N:Int,false)

  rule #doUnparse(D:DIPMacro A B, _) => #DIPMacroToString(D) +String
                                        " " +String
                                        #doUnparse(A, false) +String
                                        " " +String
                                        #doUnparse(B, false)

  rule #doUnparse(D:DUPMacro A, _) => #DUPMacroToString(D) +String
                                      " " +String
                                      #doUnparse(A, false)

  rule #doUnparse(C:CDARMacro A, _) => #CDARMacroToString(C) +String
                                       " " +String
                                       #doUnparse(A, false)

  rule #doUnparse(C:SetCDARMacro A, _) => #SetCDARMacroToString(C) +String
                                          " " +String
                                          #doUnparse(A, false)

  rule #doUnparse(C:MapCDARMacro A Body, _) => #MapCDARMacroToString(C) +String
                                               " " +String
                                               #doUnparse(A, false) +String
					       " " +String
					       #doUnparse(Body, false)

The following macros are currently disabled.

  rule #doUnparse(P:PairMacro A, _) => #PairMacroToString(P) +String
                                       " " +String
                                       #doUnparse(A, false)

  rule #doUnparse(U:UnpairMacro A, _) => #UnpairMacroToString(U) +String
                                         " " +String
                                         #doUnparse(A, false)

Michelson Groups/TZT Extexnsion Unparsing

  rule #doUnparse(storage T, _) => "storage " +String #doUnparse(T, true)
  rule #doUnparse(parameter T, _) => "parameter " +String #doUnparse(T, true)

  rule #doUnparse((C:CodeDecl ; S:StorageDecl ; P:ParameterDecl):Contract, _) =>
    #doUnparse(C, false) +String
    "; " +String
    #doUnparse(S, false) +String
    "; " +String
    #doUnparse(P, false)

  rule #doUnparse((C:CodeDecl ; S:StorageDecl ; P:ParameterDecl ;):Contract, _) =>
    #doUnparse(C, false) +String
    "; " +String
    #doUnparse(S, false) +String
    "; " +String
    #doUnparse(P, false) +String
    ";"

  rule #doUnparse(Contract S:String T:Type, _) =>
    "Contract " +String
    #doUnparse(S, false) +String
    " " +String
    #doUnparse(T, true)

  rule #doUnparse(O:OtherContractsMapEntry ; O':OtherContractsMapEntry ; Os:OtherContractsMapEntryList, _) =>
    #doUnparse(O, false) +String
    "; " +String
    #doUnparse(O' ; Os, false)

  rule #doUnparse(O:OtherContractsMapEntry ; .OtherContractsMapEntryList, _) => #doUnparse(O, false)

  rule #doUnparse(.OtherContractsMapEntryList, _) => ""

  rule #doUnparse(Big_map I T1 T2 { }, _) =>
    "Big_map" +String
    #doUnparse(I, false) +String
    " " +String
    #doUnparse(T1, true) +String
    " " +String
    #doUnparse(T2, true) +String
    " { }"

  rule #doUnparse(Big_map I T1 T2 ML:NeMapLiteral, _) =>
    "Big_map" +String
    #doUnparse(I, false) +String
    " " +String
    #doUnparse(T1, true) +String
    " " +String
    #doUnparse(T2, true) +String
    " " +String
    #doUnparse(ML, false)

  rule #doUnparse(O:BigMapEntry ; O':BigMapEntry ; Os:BigMapEntryList, _) =>
    #doUnparse(O, false) +String
    "; " +String
    #doUnparse(O' ; Os, false)

  rule #doUnparse(O:BigMapEntry ; .BigMapEntryList, _) => #doUnparse(O, false)

  rule #doUnparse(.BigMapEntryList, _) => ""

  rule #doUnparse(contract { C }, _) => "contract { " +String #doUnparse(C, false) +String "}"
  rule #doUnparse(now I, _) => "now " +String #doUnparse(I, false)
  rule #doUnparse(sender S, _) => "sender " +String #doUnparse(S, false)
  rule #doUnparse(source S, _) => "source " +String #doUnparse(S, false)
  rule #doUnparse((chain_id S):Group, _) => "chain_id " +String #doUnparse(S, false)
  rule #doUnparse(self S, _) => "self " +String #doUnparse(S, false)
  rule #doUnparse(amount S, _) => "amount " +String #doUnparse(S, false)
  rule #doUnparse(balance S, _) => "balance " +String #doUnparse(S, false)
  rule #doUnparse(other_contracts { S }, _) => "other_contracts {" +String #doUnparse(S, false) +String "}"
  rule #doUnparse(parameter_value S, _) => "parameter_value " +String #doUnparse(S, false)
  rule #doUnparse(storage_value S, _) => "storage_value " +String #doUnparse(S, false)
  rule #doUnparse(big_maps { S }, _) => "big_maps {" +String #doUnparse(S, false) +String "}"

  rule #doUnparse(G:Group ; Gs:Groups, _) => #doUnparse(G, false) +String ";\n" +String #doUnparse(Gs, false)

  rule #doUnparse(Stack_elt T D, _) =>
    "Stack_elt " +String
    #doUnparse(T, true) +String
    " " +String
    #doUnparse(D, true)

  rule #doUnparse(S:StackElementLiteral ; Ss:StackElementList, _) =>
    #doUnparse(S, false) +String
    "; " +String
    #doUnparse(Ss, false)
    requires notBool Ss ==K .StackElementList

  rule #doUnparse(S:StackElementLiteral ; .StackElementList, _) => #doUnparse(S, false)

  rule #doUnparse(.StackElementList, _) => ""

  rule #doUnparse({ S:StackElementList }, _) =>
    "{" +String
    #doUnparse(S, false) +String
    "}"

  rule #doUnparse(Create_contract { C } O M D I, _) =>
    "Create_contract { " +String
    #doUnparse(C, true) +String
    " } " +String
    #doUnparse(O, true) +String
    " " +String
    #doUnparse(M, true) +String
    " " +String
    #doUnparse(D, true) +String
    " " +String
    #doUnparse(I, true)

  rule #doUnparse(Transfer_tokens O M A:Entrypoint I, _) =>
    "Transfer_tokens " +String
    #doUnparse(O, true) +String
    " " +String
    #doUnparse(M, true) +String
    " " +String
    #doUnparse(A, true) +String
    " " +String
    #doUnparse(I, true)

  rule #doUnparse(Transfer_tokens O M A:String I, _) =>
    "Transfer_tokens " +String
    #doUnparse(O, true) +String
    " " +String
    #doUnparse(M, true) +String
    " " +String
    #doUnparse(A, true) +String
    " " +String
    #doUnparse(I, true)

  rule #doUnparse(Set_delegate O I, _) =>
    "Set_delegate " +String
    #doUnparse(O, true) +String
    " " +String
    #doUnparse(I, true)

  rule #doUnparse(( Failed D ), _) => "( Failed " +String #doUnparse(D, true) +String ")"

  rule #doUnparse(( MutezOverflow I1 I2 ), _) =>
    "( MutezOverflow " +String
    #doUnparse(I1, true) +String
    " " +String
    #doUnparse(I2, true) +String
    ")"

  rule #doUnparse(( MutezUnderflow I1 I2 ), _) =>
    "( MutezUnderflow " +String
    #doUnparse(I1, true) +String
    " " +String
    #doUnparse(I2, true) +String
    ")"

  rule #doUnparse(( GeneralOverflow I1 I2 ), _) =>
    "( GeneralOverflow " +String
    #doUnparse(I1, true) +String
    " " +String
    #doUnparse(I2, true) +String
    ")"

  rule #doUnparse(code I, _) => "code " +String #doUnparse(I, true)
  rule #doUnparse(input C, _) => "input " +String #doUnparse(C, true)
  rule #doUnparse(output LS, _) => "output " +String #doUnparse(LS, true)

  rule #doUnparse(_:Wildcard, _) => "_"
endmodule

Common

Here are common files shared between different compatibility semantics.


module COMPAT-COMMON
  imports UNIT-TEST-COMMON-SYNTAX
  imports MICHELSON-UNPARSER

  configuration <k> $PGM:Pgm </k>
                <knownaddrs> .Map </knownaddrs>
                <out stream="stdout"> .List </out>
                <returncode exit=""> 1 </returncode>

When the <k> cell is empty, we consider execution successful

  rule <k> .K </k>
       <returncode> 1 => 0 </returncode>
endmodule

Contract Expander

module CONTRACT-EXPANDER-SYNTAX
  imports UNIT-TEST-SYNTAX
endmodule

module CONTRACT-EXPANDER
  imports COMPAT-COMMON

  syntax Block ::= #StackEltToPush(StackElementLiteral) [function]
  rule #StackEltToPush(Stack_elt (contract _:AnnotationList T:Type) D:Data) => { PUSH .AnnotationList address .AnnotationList D ;
                                                                                 CONTRACT .AnnotationList T ;
                                                                                 IF_SOME .AnnotationList { } { UNIT .AnnotationList ; FAILWITH .AnnotationList } }
  rule #StackEltToPush(Stack_elt T D) => { PUSH .AnnotationList T D } [owise]

  syntax Block ::= #StackToPush(LiteralStack) [function]

  syntax Block ::= #StackToPushAux(StackElementList, Block) [function]
  rule #StackToPush( { Se } ) => #StackToPushAux(Se, { DROP .AnnotationList 0 })
  rule #StackToPushAux(Se ; Ls, { I:DataList })  => #StackToPushAux(Ls, { #StackEltToPush(Se) ; I }) requires notBool Ls ==K .StackElementList
  rule #StackToPushAux(Se, { I:DataList })  => { #StackEltToPush(Se) ; I }
  rule #StackToPushAux(.StackElementList, { I:DataList }) => { I }

  syntax Contract ::= #FillTemplateContract(Block, Block, Type) [function]

  syntax Bool ::= #CodeBlockEndsWithFail(Block) [function]
  rule #CodeBlockEndsWithFail( { } ) => false
  rule #CodeBlockEndsWithFail( { { Is } } ) => #CodeBlockEndsWithFail( { Is } )
  rule #CodeBlockEndsWithFail( { I:Instruction } ) => ((FAILWITH _) :=K I) [owise]
  rule #CodeBlockEndsWithFail( { _:Instruction ; Is } ) => #CodeBlockEndsWithFail( { Is } )

  rule #FillTemplateContract(PushBlock, CodeBlock, ParamType) =>
  parameter ParamType ; storage unit .AnnotationList ; code { DROP .AnnotationList ; PushBlock ; CodeBlock ; UNIT #token("@exitToken", "VariableAnnotation") ; FAILWITH .AnnotationList }  ;
  requires notBool #CodeBlockEndsWithFail(CodeBlock)

  rule #FillTemplateContract(PushBlock, CodeBlock, ParamType) =>
  parameter ParamType ; storage unit .AnnotationList ; code { DROP .AnnotationList ; PushBlock ; CodeBlock }  ;
  requires #CodeBlockEndsWithFail(CodeBlock)

  syntax LiteralStack ::= #FindInputGroup(Groups) [function]
  rule #FindInputGroup(input T) => T
  rule #FindInputGroup(input T ; _) => T
  rule #FindInputGroup(_ ; G) => #FindInputGroup(G) [owise]

  syntax Block ::= #FindCodeGroup(Groups) [function]
  rule #FindCodeGroup(code T) => { T }
  rule #FindCodeGroup(code T ; _) => { T }
  rule #FindCodeGroup(_ ; G) => #FindCodeGroup(G) [owise]

  syntax Type ::= #FindParamType(Groups) [function]
  rule #FindParamType(parameter T) => T
  rule #FindParamType(parameter T ; _) => T
  rule #FindParamType(_:Group) => unit .AnnotationList [owise]
  rule #FindParamType(_ ; Rs) => #FindParamType(Rs) [owise]

  rule <k> G:Groups => . </k>
       <out> ... .List => ListItem(#unparse(#FillTemplateContract(#StackToPush(#FindInputGroup(G)), #FindCodeGroup(G), #FindParamType(G)))) </out>
endmodule

Extractor

module EXTRACTOR-SYNTAX
  imports UNIT-TEST-SYNTAX
endmodule

module EXTRACTOR
  imports COMPAT-COMMON
  imports JSON

  syntax JSONKey ::= #KeyFromGroup(Group) [function]

  rule #KeyFromGroup(G:ContractGroup) => "contract"
  rule #KeyFromGroup(G:NowGroup) => "now"
  rule #KeyFromGroup(G:SenderGroup) => "sender"
  rule #KeyFromGroup(G:SourceGroup) => "source"
  rule #KeyFromGroup(G:ChainGroup) => "chain_id"
  rule #KeyFromGroup(G:SelfGroup) => "self"
  rule #KeyFromGroup(G:AmountGroup) => "amount"
  rule #KeyFromGroup(G:BalanceGroup) => "balance"
  rule #KeyFromGroup(G:BigMapGroup) => "big_maps"
  rule #KeyFromGroup(G:ContractsGroup) => "other_contracts"
  rule #KeyFromGroup(G:CodeGroup) => "code"
  rule #KeyFromGroup(G:InputGroup) => "input"
  rule #KeyFromGroup(G:OutputGroup) => "output"
  rule #KeyFromGroup(G:ParameterDecl) => "parameter"
  rule #KeyFromGroup(G:ParameterValueGroup) => "parameter_value"
  rule #KeyFromGroup(G:StorageValueGroup) => "storage_value"

  syntax K ::= #GroupContent(Group) [function]
  rule #GroupContent(contract { C }) => C
  rule #GroupContent(now C) => C
  rule #GroupContent(sender C) => C
  rule #GroupContent(source C) => C
  rule #GroupContent(chain_id C) => C
  rule #GroupContent(self C) => C
  rule #GroupContent(amount C) => C
  rule #GroupContent(balance C) => C
  rule #GroupContent(other_contracts { C }) => C
  rule #GroupContent(code C) => C
  rule #GroupContent(input C) => C
  rule #GroupContent(output C) => C
  rule #GroupContent(parameter C) => C
  rule #GroupContent(big_maps { C }) => C
  rule #GroupContent(parameter_value C) => C
  rule #GroupContent(storage_value C) => C

  syntax JSON  ::= #GroupsToJson(Groups)      [function]
  syntax JSONs ::= #GroupsToJsonInner(Groups) [function]
  syntax JSON  ::= #GroupToJson(Group)        [function]
  syntax JSON  ::= #GroupToJson(Group,Bool)   [function]

  rule #GroupsToJson(Gs) => { #GroupsToJsonInner(Gs) }

  rule #GroupsToJsonInner(G ; Gs) => #GroupToJson(G) , #GroupsToJsonInner(Gs)
  rule #GroupsToJsonInner(G)      => #GroupToJson(G)

  // check if we need to add braces around our output group
  rule #GroupToJson(G) => #GroupToJson(G, #KeyFromGroup(G) in SetItem("other_contracts") SetItem("big_maps"))

  rule #GroupToJson(G, false) => #KeyFromGroup(G) :             #unparse(#GroupContent(G))
  rule #GroupToJson(G, true)  => #KeyFromGroup(G) : "{" +String #unparse(#GroupContent(G)) +String "}"

  rule <k> Gs:Groups => . </k>
       <out> ... .List => ListItem(JSON2String(#GroupsToJson(Gs))) </out>
       <returncode> 1 => 0 </returncode>
endmodule

Input Creator

module INPUT-CREATOR-SYNTAX
  imports UNIT-TEST-SYNTAX
endmodule

module INPUT-CREATOR
  imports COMPAT-COMMON

  syntax Data ::= #DataForType(Type) [function]
  rule #DataForType(int _) => 0
  rule #DataForType(nat _) => 0
  rule #DataForType(string _) => ""
  rule #DataForType(bytes _) => .Bytes
  rule #DataForType(mutez _) => 0
  rule #DataForType(bool _) => true
  rule #DataForType(key_hash _) => "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV"
  rule #DataForType(timestamp _) => 0
  rule #DataForType(address _) => "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV"

//  rule #DataForType(key _)
  rule #DataForType(unit _) => Unit
//  rule #DataForType(signature _)
//  rule #DataForType(operation _)
//  rule #DataForType(chain_id _)

  rule #DataForType(pair _ T1:Type T2:Type) => Pair #DataForType(T1) #DataForType(T2)

  rule #DataForType(option _ _) => None
  rule #DataForType(list _ _) => { }
  rule #DataForType(set _ _) => { }
//  rule #DataForType(contract _ _) => None
  rule #DataForType(or _ T1 _) => #DataForType(T1)
  rule #DataForType(lambda _ _ T2) => { DROP .AnnotationList ; PUSH .AnnotationList T2 #DataForType(T2) }
  rule #DataForType(map _ _ _) => { }
  rule #DataForType(big_map _ _ _) => { }

  syntax Type ::= #FindParamType(Pgm) [function]
  rule #FindParamType(parameter T) => T
  rule #FindParamType(parameter T ; Rs) => T
  rule #FindParamType(_:Group) => unit .AnnotationList [owise]
  rule #FindParamType(_ ; Rs) => #FindParamType(Rs) [owise]

  rule <k> G:Pgm => . </k>
       <out> ... .List => ListItem(#unparse(#DataForType(#FindParamType(G)))) </out>
endmodule

Output Compare

module OUTPUT-COMPARE-COMMON-SYNTAX
  imports UNIT-TEST-COMMON-SYNTAX
  syntax RealOutputGroup ::= "real_output" OutputStack
  syntax Group ::= RealOutputGroup
endmodule

module OUTPUT-COMPARE-SYNTAX
  imports UNIT-TEST-SYNTAX
  imports OUTPUT-COMPARE-COMMON-SYNTAX
endmodule

module OUTPUT-COMPARE
  imports OUTPUT-COMPARE-COMMON-SYNTAX
  imports COMPAT-COMMON
  imports K-REFLECTION
  imports MATCHER

  syntax KItem ::= #decodeBinary(Bytes)  [function]
  // -----------------------------------------------
  rule #decodeBinary(B) => #system("decode-michelson-operation.py "
                           +String #unparseBytes(B, 0, ""))

  syntax BlockchainOperation ::= #parseOperation(KItem) [function]
  // -------------------------------------------------------------
  rule #parseOperation(#systemResult(0, Stdout, _)) => #parseKORE(Stdout)

  syntax KItem ::= #CheckOutput(OutputStack, OutputStack) // Expected, Actual

  rule #MichelineToNative(B:Bytes, operation _, KnownAddrs, BigMaps)
    => #MichelineToNative(#parseOperation(#decodeBinary(B)),
                          operation .AnnotationList,
                          KnownAddrs,
                          BigMaps)

  syntax KItem ::= "#Failed"

  rule <k> #CheckOutput( X:FailedStack , X:FailedStack ) => . ... </k>

  rule <k> #CheckOutput( { .StackElementList } , { .StackElementList } ) => . ... </k>

  rule <k> #CheckOutput( { Stack_elt ET ED } , { Stack_elt AT AD } )
        => .
           ...
       </k>
       <knownaddrs> KnownAddrs </knownaddrs>
    requires #Matches(#MichelineToNative(ED, ET, KnownAddrs, .Map),
                      #MichelineToNative(AD, AT, KnownAddrs, .Map))

  rule <k> #CheckOutput( { Stack_elt ET ED } , { Stack_elt AT AD } )
        => #Failed
           ...
       </k>
       <knownaddrs> KnownAddrs </knownaddrs>
       <out> ...
             .List
          => ListItem("Mismatch - Expected: " +String #unparse(#MichelineToNative(ED, ET, KnownAddrs, .Map)) +String
                                  " Actual: " +String #unparse(#MichelineToNative(AD, AT, KnownAddrs, .Map))
                     )
       </out> [owise]

  rule <k> #CheckOutput( { Stack_elt ET ED ; Es } , { Stack_elt AT AD ; As } )
        => #CheckOutput( { Es } , { As } )
           ...
       </k>
       <knownaddrs> KnownAddrs </knownaddrs>
    requires #Matches(#MichelineToNative(ED, ET, KnownAddrs, .Map), #MichelineToNative(AD, AT, KnownAddrs, .Map))

  rule <k> #CheckOutput( { Stack_elt ET ED ; Es } , { Stack_elt AT AD ; As } )
        => #Failed
           ...
       </k>
       <knownaddrs> KnownAddrs </knownaddrs>
       <out> ...
             .List
          => ListItem("Mismatch - Expected: " +String #unparse(#MichelineToNative(ED, ET, KnownAddrs, .Map))
                          +String " Actual: " +String #unparse(#MichelineToNative(AD, AT, KnownAddrs, .Map))
                     )
       </out> [owise]

  rule <k> other_contracts { M } ; Gs => Gs </k>
       <knownaddrs> _ => #OtherContractsMapToKMap(M) </knownaddrs>

  rule <k> real_output AOS ; output EOS => #CheckOutput(EOS, AOS) ... </k>
endmodule