Skip to content

Instantly share code, notes, and snippets.

@Justasic
Last active May 1, 2023 16:00
Show Gist options
  • Select an option

  • Save Justasic/3b5ad2c351851623e6e423b4a429c1f3 to your computer and use it in GitHub Desktop.

Select an option

Save Justasic/3b5ad2c351851623e6e423b4a429c1f3 to your computer and use it in GitHub Desktop.

Revisions

  1. Justasic revised this gist May 1, 2023. No changes.
  2. Justasic revised this gist May 1, 2023. No changes.
  3. Justasic created this gist May 1, 2023.
    261 changes: 261 additions & 0 deletions tlo.hexpat
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,261 @@
    #include <std/mem.pat>
    #include <std/io.pat>
    #include <std/sys.pat>

    enum ConstructorIDType : u32 {
    CID_TLSTYPE = 0x12eb4386,
    CID_NATCONST = 0x8ce940b1,
    CID_NATVAR = 0x4e8a14f0,
    CID_EXPRNAT = 0xdcb49bd8,
    CID_EXPRTYPE = 0xecc9da78,
    CID_TYPEVAR = 0x0142ceae,
    CID_TYPEEXPR = 0xc1863d08,
    CID_TLSARG = 0x29dfe61b,
    CID_ARRAY = 0xd9fb20de,
    CID_COMBINATORLEFT = 0x4c12c6d9,
    CID_COMBINATORLEFTBUILTIN = 0xcd211f63,
    CID_COMBINATORRIGHT = 0x2c064372,
    CID_COMBINATOR = 0x5c0a1ed5,
    CID_SCHEMAv2 = 0x3a2f9be2
    };

    // These flags are defined in types and expressions
    bitfield TypeFlags
    {
    tf_bare : 1; // Is the type expression bare
    tf_nocons : 1; // unknown?
    padding : 8;
    tf_empty : 1; // unknown?
    padding : 6;
    tf_optvar : 1; // Is the argument optional? (eg. wrapped in '{}' or flagged)
    tf_excl : 1; // Is the argument a forwarded function? (via !)
    padding : 1;
    tf_optfield : 1; // Is the argument hidden with a field mask
    tf_novar : 1; // unknown? only used with "Maybe" and "Bool" types
    padding : 3;
    tf_defcon : 1; // Does the type have a default constructor (e.g. constructor that will be used if no magic is presented.)
    padding : 1;
    tf_forwarded: 1;
    padding : 4;
    };

    // These flags only make sense for functions, not types
    bitfield CombinatorFlags
    {
    cf_read : 1; // Does the function represent a read query
    cf_write : 1; // Does the function represent a write query
    cf_internal : 1; // Is the function used only for internal engine interconnection
    cf_kphp : 1; // Is the function processed by kPHP RPC server
    };


    struct TLString
    {
    if (std::mem::read_signed($, sizeof(u8)) == 254)
    {
    $ += 1; // Skip 254
    u24 length;
    }
    else
    u8 length;

    char value[this.length];
    padding[-(this.length + 1) & 3];
    };

    // tls.type#12eb4386 name:int id:string constructors_num:int flags:int arity:int params_type:long = tls.Type;
    struct TLSType
    {
    ConstructorIDType ConstructorID;
    s32 name;
    TLString id;
    s32 constructors_num;
    s32 flags;
    s32 arity;
    s64 params_type;
    };

    // tls.natConst#8ce940b1 value:int = tls.NatExpr;
    struct NatConst
    {
    ConstructorIDType ConstructorID;
    s32 value;
    };

    // tls.natVar#4e8a14f0 dif:int var_num:int = tls.NatExpr;
    struct NatVar
    {
    ConstructorIDType ConstructorID;
    s32 dif;
    s32 var_num;
    };

    struct NatExpr
    {
    if (u32(std::mem::read_signed($, sizeof(u32))) == ConstructorIDType::CID_NATVAR)
    NatVar;
    else if (u32(std::mem::read_signed($, sizeof(u32))) == ConstructorIDType::CID_NATCONST)
    NatConst;
    else
    std::assert(false, std::format("Invalid ExprNat value CID: {:#x} @ {:#x}", u32(std::mem::read_signed($, sizeof(u32))), $));
    };

    // tls.exprNat#dcb49bd8 _:tls.NatExpr = tls.Expr;
    struct ExprNat
    {
    ConstructorIDType ConstructorID;

    NatExpr underscore;
    };

    using TypeVar;
    using typeExpr;
    using Array;

    struct TypeExpr
    {
    if (u32(std::mem::read_signed($, sizeof(u32))) == ConstructorIDType::CID_TYPEVAR)
    TypeVar;
    else if (u32(std::mem::read_signed($, sizeof(u32))) == ConstructorIDType::CID_TYPEEXPR)
    typeExpr;
    else if (u32(std::mem::read_signed($, sizeof(u32))) == ConstructorIDType::CID_ARRAY)
    Array;
    else
    std::assert(false, std::format("Invalid TypeExpr value CID: {:#x} @ {:#x}", u32(std::mem::read_signed($, sizeof(u32))), $));
    };

    // tls.exprType#ecc9da78 _:tls.TypeExpr = tls.Expr;
    struct ExprType
    {
    ConstructorIDType ConstructorID;

    TypeExpr underscore;
    };

    // tls.typeVar#0142ceae var_num:int flags:int = tls.TypeExpr;
    struct TypeVar
    {
    ConstructorIDType ConstructorID;
    s32 var_num;
    s32 flags;
    };

    struct Expr
    {
    if (u32(std::mem::read_signed($, sizeof(u32))) == ConstructorIDType::CID_EXPRTYPE)
    ExprType;
    else if (u32(std::mem::read_signed($, sizeof(u32))) == ConstructorIDType::CID_EXPRNAT)
    ExprNat;
    else
    std::assert(false, std::format("Invalid typeExpr value CID: {:#x} @ {:#x}", u32(std::mem::read_signed($, sizeof(u32))), $));
    };

    // tls.typeExpr#c1863d08 name:int flags:int children_num:# children:children_num*[tls.Expr] = tls.TypeExpr;
    struct typeExpr
    {
    ConstructorIDType ConstructorID;
    s32 name;
    s32 flags;
    u32 children_num;
    Expr children[this.children_num];
    };

    bitfield ArgFlags
    {
    padding : 1;
    exist_bit : 1;
    var_bit : 1;
    padding : 29;
    };

    // tls.arg#29dfe61b id:string flags:# var_num:flags.2?int exist_var_num:flags.1?int
    // exist_var_bit:flags.1?int type:tls.TypeExpr = tls.Arg;
    struct Arg
    {
    ConstructorIDType ConstructorID;
    TLString id;
    ArgFlags flags;

    if (flags.var_bit)
    s32 var_num;
    if (flags.exist_bit)
    {
    s32 exist_var_num;
    s32 exist_var_bit;
    }

    TypeExpr type;
    };

    // tls.array#d9fb20de multiplicity:tls.NatExpr args_num:# args:args_num*[tls.Arg] = tls.TypeExpr;
    struct Array
    {
    ConstructorIDType ConstructorID;

    NatExpr multiplicity;

    u32 args_num;
    Arg args[this.args_num];
    };

    // tls.combinatorLeft#4c12c6d9 args_num:# args:args_num*[tls.Arg] = tls.CombinatorLeft;
    struct TLSCombinerLeft
    {
    ConstructorIDType ConstructorID;
    u32 args_num;
    Arg args[this.args_num];
    };

    // tls.combinatorLeftBuiltin#cd211f63 = tls.CombinatorLeft;
    struct combinatorLeftBuiltin
    {
    ConstructorIDType ConstructorID;
    };

    struct CombinatorLeft
    {
    if (u32(std::mem::read_signed($, sizeof(u32))) == ConstructorIDType::CID_COMBINATORLEFTBUILTIN)
    combinatorLeftBuiltin;
    else if (u32(std::mem::read_signed($, sizeof(u32))) == ConstructorIDType::CID_COMBINATORLEFT)
    TLSCombinerLeft;
    else
    std::assert(false, std::format("Invalid combinator left value CID: {:#x} @ {:#x}", u32(std::mem::read_signed($, sizeof(u32))), $));
    };

    // tls.combinatorRight#2c064372 value:tls.TypeExpr = tls.CombinatorRight;
    struct CombinatorRight
    {
    ConstructorIDType ConstructorID;

    TypeExpr value;
    };

    // tls.combinator#5c0a1ed5 name:int id:string type_name:int
    // left:tls.CombinatorLeft right:tls.CombinatorRight = tls.Combinator;
    struct Combinator
    {
    ConstructorIDType ConstructorID;
    s32 name;
    TLString id;
    s32 type_name;

    CombinatorLeft left;
    CombinatorRight right;
    };

    // tls.schema_v2 version:int date:int types_num:# types:types_num*[tls.Type]
    // constructor_num:# constructors:constructor_num*[tls.Combinator]
    // functions_num:# functions:functions_num*[tls.Combinator] = tls.Schema;
    struct schemav2
    {
    ConstructorIDType ConstructorID;
    s32 version;
    s32 date;
    u32 types_num;
    TLSType types[this.types_num];
    u32 constructor_num;
    Combinator constructors[this.constructor_num];
    u32 functions_num;
    Combinator functions[this.functions_num];
    };
    schemav2 schema @ 0x00;