Module Catala_runtime

The OCaml runtime.

Types

type nonrec unit = unit
type nonrec bool = bool
type money = Z.t

Number of cents

type integer = Z.t
type decimal = Q.t
type date = Dates_calc.date
type duration = Dates_calc.period
type date_rounding = Dates_calc.date_rounding =
  1. | RoundUp
  2. | RoundDown
  3. | AbortOnRound
type code_location = {
  1. filename : string;
  2. start_line : int;
  3. start_column : int;
  4. end_line : int;
  5. end_column : int;
  6. law_headings : string list;
}
type io_input =
  1. | NoInput
    (*

    For an internal variable defined only in the scope, and does not appear in the input.

    *)
  2. | OnlyInput
    (*

    For variables that should not be redefined in the scope, because they appear in the input.

    *)
  3. | Reentrant
    (*

    For variables defined in the scope that can also be redefined by the caller as they appear in the input.

    *)

This type characterizes the three levels of visibility for a given scope variable with regards to the scope's input and possible redefinitions inside the scope.

type io_log = {
  1. io_input : io_input;
  2. io_output : bool;
    (*

    true if the variable is an output

    *)
}

Exceptions

type error =
  1. | AssertionFailed
    (*

    An assertion in the program doesn't hold

    *)
  2. | NoValue
    (*

    No computation with valid conditions found

    *)
  3. | Conflict
    (*

    Two different valid computations at that point

    *)
  4. | DivisionByZero
    (*

    The denominator happened to be 0 here

    *)
  5. | ListEmpty
    (*

    Element access on an empty list

    *)
  6. | NotSameLength
    (*

    Traversing multiple lists of different lengths

    *)
  7. | UncomparableValues
    (*

    Equality check or comparison on functions

    *)
  8. | DateError of string
    (*

    Errors related to date and duration computations

    *)
  9. | Impossible
    (*

    The "impossible" keyword was reached

    *)
val error_to_string : error -> string

Returns the capitalized tag of the error as a string

val error_message : error -> string

Returns a short explanation message about the error

exception Error of error * code_location list * string option
exception Empty

Value Embedding

Runtime type encoding

module Value : sig ... end
val equal : 'a Value.ty -> code_location -> 'a -> 'a -> bool

Polymorphic, structural equality using runtime type information

val compare : 'a Value.ty -> code_location -> 'a -> 'a -> int

Polymorphic, structural comparison using runtime type information

Catala types utils

module type CatalaType = sig ... end
module Optional : sig ... end
module type ExternalTypeSpec = sig ... end

This interface must be supplied to extend the Catala runtime with abstract types

Execution traces

The trace construction mechanism is a stateful process (i.e., non-reentrant) that collect traces emitted by the generated trace constructors defined below.

The built trace is organized as a tree where each node represent a trace element (e.g., a variable definition, a branching, etc.) which may have sub-traces. For instance, a function that defines local variable definitions will be represented as a FunCall node with a sub_trace containing these LocalVarDef sub-nodes.

Conceptually, whenever we reach a trace event, we open a scope, evaluate the sub-expression potentially yielding new traces that will be its sub-nodes, close the scope and finalize this trace node with the computed sub-expression value.

Whenever a runtime error is triggered, we insert an Error node as a sub-trace of the currently opened scope and re-raise this error. This is automatically performed by the with_trace wrapper.

The global trace state can be retrieved using the retrieve_trace accessor and cleared using reset_trace.

Traces types

type trace_kind =
  1. | ScopeCall of trace_ident_decl
    (*

    Scope call with the scope declaration information

    *)
  2. | ScopeVarDef of {
    1. var : trace_ident_decl;
    2. io : io_log;
    }
    (*

    Scope variable definition with its declaration information and its i/o kind

    *)
  3. | LocalVarDef of string
    (*

    Let-binding of a local variable with its name

    *)
  4. | LocalTupDef of string list
    (*

    Let-binding of a local tuple with the name of each binded variable

    *)
  5. | FunCall of trace_ident_decl
    (*

    Function call with its declaration information

    *)
  6. | BranchingCondition
    (*

    Branching condition for an if-then-else or a pattern matching

    *)
  7. | IfBranching
    (*

    Branch taken of the consequence or alternative of an if-then-else

    *)
  8. | MatchBranching of {
    1. constructor_name : string;
    }
    (*

    Pattern taken of a pattern-matching

    *)
  9. | Assertion
    (*

    Beginning of an assertion

    *)
  10. | Exception of {
    1. label : (string * code_location) option;
      (*

      Exception label and its position in case of named exception

      *)
    2. cons_pos : code_location;
      (*

      Position of the consequence that would be evaluated if this exception gets fulfilled

      *)
    }
    (*

    Scope variable definition exception

    *)
  11. | Error of {
    1. error : error;
      (*

      Runtime error itself

      *)
    2. locs : code_location list;
      (*

      Extra-relevant locations

      *)
    3. message : string option;
      (*

      User-faced error message

      *)
    }
    (*

    Runtime error description

    *)

This type describes all the different trace kind generated throughout execution

and trace_ident_decl = {
  1. name : string;
  2. decl_pos : code_location;
}

Variable-kind declaration info, i.e., name and declaration position

type trace = trace_element list
and trace_element = {
  1. kind : trace_kind;
    (*

    The kind of trace

    *)
  2. pos : code_location;
    (*

    The expression pos responsible for this trace

    *)
  3. value : Value.t option;
    (*

    The resulting evaluated value. No value present on error.

    *)
  4. sub_trace : trace;
    (*

    Sub elements of the trace. E.g., a ScopeCall trace will contain ScopeVarDef traces in its sub-trace.

    *)
}

Trace node

Trace constructors

val begin_trace : trace_kind -> code_location -> unit

Begins a trace scope given a trace_kind and its code_location.

val end_trace : ?value:Value.t -> unit -> unit

Ends the currently opened trace scope and register the value.

val single_trace : trace_kind -> code_location -> unit

Equivalent to a sequence of begin_trace then end_trace. Used for error reporting.

val with_trace : embed:('a -> Value.t) -> trace_kind -> code_location -> (unit -> 'a) -> 'a

Wrapper that takes a function f and insert a begin_trace before f () and a end_trace afterwards. It also retrieves and embeds the computed value.

It also catches runtime's errors and insert a single_trace before re-raising it. When it occurs, a flag is also set so that callers do not catch it again.

Trace accessors

val retrieve_trace : unit -> trace

Finalize the global trace state and returns the immutable trace value.

val reset_trace : unit -> unit

Resets the global trace state.

Pretty printers

module Print : sig ... end

This module is for setting options and internals, use Value.format to print values

JSON printers

module Json : sig ... end

Constructors and conversions

Rounding

val round : Q.t -> Z.t

This helper function rounds a rational to the nearest integer. Tie-breaker is the "half away from zero" rule: 0.5 is rounded to 1.0 and -0.5 is rounded to -1.0. This function shall be used anytime rounding is necessary.

Money

val money_of_cents_string : string -> money
val money_of_units_int : int -> money
val money_of_decimal : decimal -> money

Warning: rounds to nearest cent, using round.

val money_of_cents_integer : integer -> money
val money_to_float : money -> float
val money_to_string : money -> string
val money_to_cents : money -> integer
val money_round : money -> money

Rounds to the nearest currency unit using round.

Decimals

val decimal_of_string : string -> decimal
val decimal_to_string : max_prec_digits:int -> decimal -> string
val decimal_of_integer : integer -> decimal
val decimal_of_float : float -> decimal
val decimal_to_float : decimal -> float
val decimal_round : decimal -> decimal

Rounds to the nearest integer using round.

val decimal_of_money : money -> decimal

Integers

val integer_of_string : string -> integer
val integer_to_string : integer -> string
val integer_to_int : integer -> int
val integer_of_int : int -> integer
val integer_of_decimal : decimal -> integer
val integer_log2 : integer -> int
val integer_exponentiation : integer -> int -> integer

Dates

val day_of_month_of_date : date -> integer
val month_number_of_date : date -> integer
val is_leap_year : integer -> bool
val year_of_date : date -> integer
val date_to_string : date -> string
val date_of_numbers : int -> int -> int -> date

Usage: date_of_numbers year month day.

Raises Failure on invalid inputs

val first_day_of_month : date -> date
val last_day_of_month : date -> date
val date_to_years_months_days : date -> int * int * int

Durations

val duration_of_numbers : int -> int -> int -> duration

Usage : duration_of_numbers year mounth day.

val duration_to_years_months_days : duration -> int * int * int

Times

val duration_to_string : duration -> string

Defaults

val handle_exceptions : ('a * code_location) Optional.t array -> ('a * code_location) Optional.t

Operators

module Oper : sig ... end
include module type of Oper
val o_not : bool -> bool
val o_length : 'a array -> integer
val o_toint_rat : decimal -> integer
val o_toint_mon : money -> integer
val o_torat_int : integer -> decimal
val o_torat_mon : money -> decimal
val o_tomoney_rat : decimal -> money
val o_tomoney_int : integer -> money
val o_getDay : date -> integer
val o_getMonth : date -> integer
val o_getYear : date -> integer
val o_firstDayOfMonth : date -> date
val o_lastDayOfMonth : date -> date
val o_round_mon : money -> money
val o_round_rat : decimal -> decimal
val o_minus_int : integer -> integer
val o_minus_rat : decimal -> decimal
val o_minus_mon : money -> money
val o_minus_dur : duration -> duration
val o_and : bool -> bool -> bool
val o_or : bool -> bool -> bool
val o_xor : bool -> bool -> bool
val o_eq : 'a Value.ty -> code_location -> 'a -> 'a -> bool
val o_lt : 'a Value.ty -> code_location -> 'a -> 'a -> bool
val o_lte : 'a Value.ty -> code_location -> 'a -> 'a -> bool
val o_gt : 'a Value.ty -> code_location -> 'a -> 'a -> bool
val o_gte : 'a Value.ty -> code_location -> 'a -> 'a -> bool
val o_map : ('a -> 'b) -> 'a array -> 'b array
val o_map2 : code_location -> ('a -> 'b -> 'c) -> 'a array -> 'b array -> 'c array
  • raises Runtime.NotSameLength
val o_reduce : ('a -> 'a -> 'a) -> 'a array -> 'a Optional.t
val o_concat : 'a array -> 'a array -> 'a array
val o_filter : ('a -> bool) -> 'a array -> 'a array
val o_add_int_int : integer -> integer -> integer
val o_add_rat_rat : decimal -> decimal -> decimal
val o_add_mon_mon : money -> money -> money
val o_add_dat_dur : date_rounding -> code_location -> date -> duration -> date
val o_add_dur_dur : duration -> duration -> duration
val o_sub_int_int : integer -> integer -> integer
val o_sub_rat_rat : decimal -> decimal -> decimal
val o_sub_mon_mon : money -> money -> money
val o_sub_dat_dat : date -> date -> duration
val o_sub_dat_dur : date_rounding -> code_location -> date -> duration -> date
val o_sub_dur_dur : duration -> duration -> duration
val o_mult_int_int : integer -> integer -> integer
val o_mult_rat_rat : decimal -> decimal -> decimal
val o_mult_mon_int : money -> integer -> money
val o_mult_mon_rat : money -> decimal -> money
val o_mult_dur_int : duration -> integer -> duration
val o_div_int_int : code_location -> integer -> integer -> decimal
val o_div_rat_rat : code_location -> decimal -> decimal -> decimal
val o_div_mon_mon : code_location -> money -> money -> decimal
val o_div_mon_int : code_location -> money -> integer -> money
val o_div_mon_rat : code_location -> money -> decimal -> money
val o_div_dur_dur : code_location -> duration -> duration -> decimal
val o_fold : ('a -> 'b -> 'a) -> 'a -> 'b array -> 'a
val o_find : ('a -> bool) -> 'a array -> 'a Optional.t
val o_sort_asc : 'b Value.ty -> code_location -> ('a -> 'b) -> 'a array -> 'a array
val o_sort_desc : 'b Value.ty -> code_location -> ('a -> 'b) -> 'a array -> 'a array
val o_toclosureenv : 'a -> Stdlib.Obj.t
val o_fromclosureenv : Stdlib.Obj.t -> 'a

Modules API

type hash = string
val register_module : string -> (string * Stdlib.Obj.t) list -> ?types:(string * (module CatalaType)) list -> hash -> unit

Registers a module by the given name defining the given bindings. Required for evaluation to be able to access the given values. The last argument is expected to be a hash of the source file and the Catala version, and will in time be used to ensure that the module and the interface are in sync

val check_module : string -> hash -> (unit, hash) Stdlib.result

Returns Ok if it has been registered with the correct hash, Error h if there is a hash mismatch.

Raises Not_found if the module does not exist at all

val lookup_value : (string * string) -> Stdlib.Obj.t
val lookup_type : (string * string) -> (module CatalaType)