Melange_compiler_libs.Lambda
type tag_info =
| Blk_constructor of {
name: string,
num_nonconst: int,
attributes: Parsetree.attributes,
}
| Blk_tuple
| Blk_array
| Blk_poly_var(string)
| Blk_record(array(string))
| Blk_module(list(string))
| Blk_module_export(list(Ident.t))
| Blk_extension_slot
| Blk_extension
| Blk_na(string)
| Blk_some
| Blk_some_not_nested
| Blk_record_inlined of {
}
| Blk_record_ext(array(string))
| Blk_lazy_general
| Blk_class
;
let blk_record:
Stdlib.ref((array((Types.label_description, Typedtree.record_label_definition)) =>
tag_info));
let blk_record_ext:
Stdlib.ref((array((Types.label_description, Typedtree.record_label_definition)) =>
tag_info));
let blk_record_inlined:
Stdlib.ref((array((Types.label_description, Typedtree.record_label_definition)) =>
string =>
int =>
tag_info));
let default_tag_info: tag_info;
let ref_tag_info: tag_info;
let fld_record: Stdlib.ref((Types.label_description => field_dbg_info));
let fld_record_inline: Stdlib.ref((Types.label_description => field_dbg_info));
let fld_record_extension:
Stdlib.ref((Types.label_description => field_dbg_info));
let ref_field_info: field_dbg_info;
let fld_na: field_dbg_info;
let ref_field_set_info: set_field_dbg_info;
let fld_record_set:
Stdlib.ref((Types.label_description => set_field_dbg_info));
let fld_record_inline_set:
Stdlib.ref((Types.label_description => set_field_dbg_info));
let fld_record_extension_set:
Stdlib.ref((Types.label_description => set_field_dbg_info));
type pointer_info =
| Pt_constructor of {
name: string,
const: int,
non_const: int,
attributes: Parsetree.attributes,
}
| Pt_constructor_access of {
}
| Pt_variant of {
}
| Pt_module_alias
| Pt_builtin_boolean
| Pt_shape_none
| Pt_assertfalse
| Pt_na
;
type primitive =
| Pbytes_to_string
| Pbytes_of_string
| Pignore
| Pgetglobal(Ident.t)
| Psetglobal(Ident.t)
| Pmakeblock(int, tag_info, Asttypes.mutable_flag, block_shape)
| Pfield(int, immediate_or_pointer, Asttypes.mutable_flag, field_dbg_info)
| Pfield_computed
| Psetfield(int, immediate_or_pointer, initialization_or_assignment, set_field_dbg_info)
| Psetfield_computed(immediate_or_pointer, initialization_or_assignment)
| Pfloatfield(int, field_dbg_info)
| Psetfloatfield(int, initialization_or_assignment, set_field_dbg_info)
| Pduprecord(Types.record_representation, int)
| Prunstack
| Pperform
| Presume
| Preperform
| Pccall(Primitive.description)
| Praise(raise_kind)
| Psequand
| Psequor
| Pnot
| Pnegint
| Paddint
| Psubint
| Pmulint
| Pdivint(is_safe)
| Pmodint(is_safe)
| Pandint
| Porint
| Pxorint
| Plslint
| Plsrint
| Pasrint
| Pintcomp(integer_comparison)
| Pcompare_ints
| Pcompare_floats
| Pcompare_bints(boxed_integer)
| Poffsetint(int)
| Poffsetref(int)
| Pintoffloat
| Pfloatofint
| Pnegfloat
| Pabsfloat
| Paddfloat
| Psubfloat
| Pmulfloat
| Pdivfloat
| Pfloatcomp(float_comparison)
| Pstringlength
| Pstringrefu
| Pstringrefs
| Pbyteslength
| Pbytesrefu
| Pbytessetu
| Pbytesrefs
| Pbytessets
| Pmakearray(array_kind, Asttypes.mutable_flag)
| Pduparray(array_kind, Asttypes.mutable_flag)
For Pduparray
, the argument must be an immutable array. The arguments of Pduparray
give the kind and mutability of the array being *produced* by the duplication.
| Parraylength(array_kind)
| Parrayrefu(array_kind)
| Parraysetu(array_kind)
| Parrayrefs(array_kind)
| Parraysets(array_kind)
| Pisint
| Pisout
| Pbintofint(boxed_integer)
| Pintofbint(boxed_integer)
| Pcvtbint(boxed_integer, boxed_integer)
| Pnegbint(boxed_integer)
| Paddbint(boxed_integer)
| Psubbint(boxed_integer)
| Pmulbint(boxed_integer)
| Pdivbint of {
size: boxed_integer,
is_safe: is_safe,
}
| Pmodbint of {
size: boxed_integer,
is_safe: is_safe,
}
| Pandbint(boxed_integer)
| Porbint(boxed_integer)
| Pxorbint(boxed_integer)
| Plslbint(boxed_integer)
| Plsrbint(boxed_integer)
| Pasrbint(boxed_integer)
| Pbintcomp(boxed_integer, integer_comparison)
| Pbigarrayref(bool, int, bigarray_kind, bigarray_layout)
| Pbigarrayset(bool, int, bigarray_kind, bigarray_layout)
| Pbigarraydim(int)
| Pstring_load_16(bool)
| Pstring_load_32(bool)
| Pstring_load_64(bool)
| Pbytes_load_16(bool)
| Pbytes_load_32(bool)
| Pbytes_load_64(bool)
| Pbytes_set_16(bool)
| Pbytes_set_32(bool)
| Pbytes_set_64(bool)
| Pbigstring_load_16(bool)
| Pbigstring_load_32(bool)
| Pbigstring_load_64(bool)
| Pbigstring_set_16(bool)
| Pbigstring_set_32(bool)
| Pbigstring_set_64(bool)
| Pctconst(compile_time_constant)
| Pbswap16
| Pbbswap(boxed_integer)
| Pint_as_pointer
| Patomic_load of {
immediate_or_pointer: immediate_or_pointer,
}
| Patomic_exchange
| Patomic_cas
| Patomic_fetch_add
| Popaque
| Pdls_get
;
and block_shape = option(list(value_kind));
let equal_value_kind: value_kind => value_kind => bool;
let equal_boxed_integer: boxed_integer => boxed_integer => bool;
let default_pointer_info: pointer_info;
type structured_constant =
| Const_base(Asttypes.constant, pointer_info)
| Const_block(int, tag_info, list(structured_constant))
| Const_float_array(list(string))
| Const_immstring(string)
;
let equal_inline_attribute: inline_attribute => inline_attribute => bool;
let equal_specialise_attribute:
specialise_attribute =>
specialise_attribute =>
bool;
type function_attribute = {
inline: inline_attribute,
specialise: specialise_attribute,
local: local_attribute,
poll: poll_attribute,
is_a_functor: bool,
stub: bool,
tmc_candidate: bool,
return_unit: bool,
};
type lambda =
| Lvar(Ident.t)
| Lmutvar(Ident.t)
| Lconst(structured_constant)
| Lapply(lambda_apply)
| Lfunction(lfunction)
| Llet(let_kind, value_kind, Ident.t, lambda, lambda)
| Lmutlet(value_kind, Ident.t, lambda, lambda)
| Lletrec(list((Ident.t, lambda)), lambda)
| Lprim(primitive, list(lambda), scoped_location)
| Lswitch(lambda, lambda_switch, scoped_location)
| Lstringswitch(lambda, list((string, lambda)), option(lambda), scoped_location)
| Lstaticraise(int, list(lambda))
| Lstaticcatch(lambda, (int, list((Ident.t, value_kind))), lambda)
| Ltrywith(lambda, Ident.t, lambda)
| Lifthenelse(lambda, lambda, lambda)
| Lsequence(lambda, lambda)
| Lwhile(lambda, lambda)
| Lfor(Ident.t, lambda, lambda, Asttypes.direction_flag, lambda)
| Lassign(Ident.t, lambda)
| Lsend(meth_kind, lambda, lambda, list(lambda), scoped_location)
| Levent(lambda, lambda_event)
| Lifused(Ident.t, lambda)
;
and lfunction = pri {
kind: function_kind,
params: list((Ident.t, value_kind)),
return: value_kind,
body: lambda,
attr: function_attribute,
loc: scoped_location,
};
and lambda_apply = {
ap_func: lambda,
ap_args: list(lambda),
ap_loc: scoped_location,
ap_tailcall: tailcall_attribute,
ap_inlined: inline_attribute,
ap_specialised: specialise_attribute,
};
and lambda_switch = {
sw_numconsts: int,
sw_consts: list((int, lambda)),
sw_numblocks: int,
sw_blocks: list((int, lambda)),
sw_failaction: option(lambda),
sw_names: option(switch_names),
};
and lambda_event = {
lev_loc: scoped_location,
lev_kind: lambda_event_kind,
lev_repr: option(Stdlib.ref(int)),
lev_env: Env.t,
};
type program = {
module_ident: Ident.t,
main_module_block_size: int,
required_globals: Ident.Set.t,
code: lambda,
};
let const_unit: structured_constant;
let const_int: ?ptr_info:pointer_info => int => structured_constant;
let lambda_unit: lambda;
let lambda_assert_false: lambda;
let lambda_module_alias: lambda;
let lfunction:
kind:function_kind =>
params:list((Ident.t, value_kind)) =>
return:value_kind =>
body:lambda =>
attr:function_attribute =>
loc:scoped_location =>
lambda;
iter_head_constructor f lam
apply f
to only the first level of sub expressions of lam
. It does not recursively traverse the expression.
Same as iter_head_constructor
, but use a different callback for sub-terms which are in tail position or not.
let transl_prim: string => string => lambda;
Translate a value from a persistent module. For instance:
transl_internal_value "CamlinternalLazy" "force"
let free_variables: lambda => Ident.Set.t;
let transl_module_path: scoped_location => Env.t => Path.t => lambda;
let transl_value_path: scoped_location => Env.t => Path.t => lambda;
let transl_extension_path: scoped_location => Env.t => Path.t => lambda;
let transl_class_path: scoped_location => Env.t => Path.t => lambda;
let subst:
(Ident.t => Types.value_description => Env.t => Env.t) =>
?freshen_bound_variables:bool =>
Ident.Map.t(lambda) =>
lambda =>
lambda;
subst update_env ?freshen_bound_variables s lt
applies a substitution s
to the lambda-term lt
.
Assumes that the image of the substitution is out of reach of the bound variables of the lambda-term (no capture).
update_env
is used to refresh the environment contained in debug events.
freshen_bound_variables
, which defaults to false
, freshens the bound variables within lt
.
A version of subst
specialized for the case where we're just renaming idents.
Bottom-up rewriting, applying the function on each node from the leaves to the root.
Rewrite each immediate sub-term with the function.
let bind_with_value_kind:
let_kind =>
(Ident.t, value_kind) =>
lambda =>
lambda =>
lambda;
let negate_integer_comparison: integer_comparison => integer_comparison;
let swap_integer_comparison: integer_comparison => integer_comparison;
let negate_float_comparison: float_comparison => float_comparison;
let swap_float_comparison: float_comparison => float_comparison;
let default_function_attribute: function_attribute;
let default_stub_attribute: function_attribute;
let function_is_curried: lfunction => bool;
let find_exact_application:
function_kind =>
arity:int =>
list(lambda) =>
option(list(lambda));
Maximal number of parameters for a function, or in other words, maximal length of the params
list of a lfunction
record. This is unlimited (max_int
) for bytecode, but limited (currently to 126) for native code.
let staticfail: lambda;
let is_guarded: lambda => bool;
let raise_kind: raise_kind => string;
let merge_inline_attributes:
inline_attribute =>
inline_attribute =>
option(inline_attribute);