Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file eval.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146(* Top-level expression evaluator and value-to-int conversion.
The full struct-internal expression machinery (with [Ref]/[Sizeof_this]/
[Field_pos] resolution against bound fields) lives in [Codec] as the
[compile_int_arr] family, which compiles expressions to [int array]
accessors at codec construction. This module is the residual evaluator
for the [Wire.of_string]/[Wire.encode] paths, which only ever
evaluate expressions in [empty]: no field references, no cross-field
dependencies. *)openTypestypectx=(string*int)listletempty:ctx=[]letbindnamevctx=(name,v)::ctx(* Convert a typed value to [int]. Returns [None] for types that don't
fit in OCaml int (uint64 over 2^63, non-numeric). *)letrecint_of:typea.atyp->a->intoption=funtypv->matchtypwith|Uint8->Somev|Uint16_->Somev|Uint_var_->Somev|Uint32_->Some(UInt32.to_intv)|Uint63_->Some(UInt63.to_intv)|Uint64_->Int64.unsigned_to_intv|Int8->Somev|Int16_->Somev|Int32_->Somev|Int64_->Int64.unsigned_to_intv|Float32_->None|Float64_->None|Bits_->Somev|Enum{base;_}->int_ofbasev|Where{inner;_}->int_ofinnerv|Single_elem{elem;_}->int_ofelemv|Apply{typ;_}->int_oftypv|Map{inner;encode;_}->int_ofinner(encodev)|Unit|All_bytes|All_zeros|Zeroterm|Zeroterm_at_most_|Array_|Byte_array_|Byte_array_where_|Byte_slice_|Casetype_|Struct_|Type_ref_|Qualified_ref_|Codec_|Optional_|Optional_or_|Repeat_->None(* Hot-path variant of [int_of] for the cross-field size/offset/present
readers, which need a plain [int]. Returns it directly (no [Some] box on the
numeric path). A [uint64]/[int64] beyond the native int range is adversarial
input and raises [Parse_error] ([Value_out_of_range]); a non-integer field
referenced where an integer is required is a schema error and raises
[Invalid_argument]. *)letint_overflowv=raise_out_of_range~at:0vletnot_an_integer()=invalid_arg"Wire: non-integer field referenced where an integer is required"letrecint_of_exn:typea.atyp->a->int=funtypv->matchtypwith|Uint8->v|Uint16_->v|Uint_var_->v|Uint32_->UInt32.to_intv|Uint63_->UInt63.to_intv|Uint64_->(matchInt64.unsigned_to_intvwithSomen->n|None->int_overflowv)|Int8->v|Int16_->v|Int32_->v|Int64_->(matchInt64.unsigned_to_intvwithSomen->n|None->int_overflowv)|Float32_->not_an_integer()|Float64_->not_an_integer()|Bits_->v|Enum{base;_}->int_of_exnbasev|Where{inner;_}->int_of_exninnerv|Single_elem{elem;_}->int_of_exnelemv|Apply{typ;_}->int_of_exntypv|Map{inner;encode;_}->int_of_exninner(encodev)|Unit|All_bytes|All_zeros|Zeroterm|Zeroterm_at_most_|Array_|Byte_array_|Byte_array_where_|Byte_slice_|Casetype_|Struct_|Type_ref_|Qualified_ref_|Codec_|Optional_|Optional_or_|Repeat_->not_an_integer()letrecexpr:typea.ctx->aexpr->a=functxe->matchewith|Intn->n|Int64n->n|Boolb->b|Ref(I,name)->(matchList.assoc_optnamectxwith|Somev->v|None->failwith("Eval.expr: unbound field "^name^" (cross-field references are only valid inside a struct)"))|Ref(I64,name)->failwith("Eval.expr: unbound int64 field "^name^" (cross-field references are only valid inside a struct)")|Param_refp->!(p.cell())|Sizeoft->field_wire_sizet|>Option.value~default:0|Sizeof_this->0|Field_pos->0|Add(a,b)->exprctxa+exprctxb|Sub(a,b)->exprctxa-exprctxb|Mul(a,b)->exprctxa*exprctxb|Div(a,b)->exprctxa/exprctxb|Mod(a,b)->exprctxamodexprctxb|Land(a,b)->exprctxalandexprctxb|Land64(a,b)->Int64.logand(exprctxa)(exprctxb)|Lor(a,b)->exprctxalorexprctxb|Lxor(a,b)->exprctxalxorexprctxb|Lnota->lnot(exprctxa)|Lsl(a,b)->exprctxalslexprctxb|Lsr(a,b)->exprctxalsrexprctxb|Eq(a,b)->exprctxa=exprctxb|Ne(a,b)->exprctxa<>exprctxb|Lt(a,b)->compare_exprctxab<0|Le(a,b)->compare_exprctxab<=0|Gt(a,b)->compare_exprctxab>0|Ge(a,b)->compare_exprctxab>=0|And(a,b)->exprctxa&&exprctxb|Or(a,b)->exprctxa||exprctxb|Nota->not(exprctxa)|Cast(width,e)->(letv=exprctxeinmatchwidthwith|`U8->vland0xFF|`U16->vland0xFFFF|`U32->vland0xFFFF_FFFF|`U64->v)|If_then_else(c,t,e)->ifexprctxcthenexprctxtelseexprctxeandcompare_expr:typea.ctx->aexpr->aexpr->int=functxab->matchawith|Int64_->compare_int64_exprctxab|Ref(I64,_)->compare_int64_exprctxab|_->Stdlib.compare(exprctxa)(exprctxb)andcompare_int64_exprctx(a:int64expr)(b:int64expr)=Int64.unsigned_compare(exprctxa)(exprctxb)