Language "OCaml Light" #12 Core library [ Funcon ocaml-light-core-library Funcon ocaml-light-match-failure Funcon ocaml-light-is-structurally-equal Funcon ocaml-light-to-string Funcon ocaml-light-define-and-display Funcon ocaml-light-evaluate-and-display ] Meta-variables R, S, S1, S2, S3, T, U <: values S* <: values* T+ <: values+
## Abbreviations
*/ Auxiliary
Funcon op-1(X:S=>T) : =>functions(S,T)
~> function abstraction X
Auxiliary
Auxiliary
Funcon op-3(X:tuples(S1,S2,S3)=>T) : =>functions(S1, functions(S2, functions(S3, T)))
~> function abstraction( curry partial-apply-first(function abstraction X, given))
Auxiliary
Funcon partial-apply-first(F:functions(tuples(R,S,T+),U), V:R) :
=>functions(tuples(S,T+),U) ~> function abstraction(apply(F, tuple(V, tuple-elements given)))
/*
`partial-apply-first(F, V)` provides `V` as the first argument to a function
expecting a tuple of 3 or more arguments, returning a function expecting
a tuple of one fewer arguments.
*/ Auxiliary
Funcon arg : T=>T
~> given
Auxiliary
Funcon arg-1 : tuples(S1,S*)=>S1
~> checked index(1, tuple-elements given)
Auxiliary
Funcon arg-2 : tuples(S1,S2,S*)=>S2
~> checked index(2, tuple-elements given)
Auxiliary
Funcon arg-3 : tuples(S1,S2,S3,S*)=>S3
~> checked index(3, tuple-elements given)
## Library
/*
The `ocaml-light-core-library` environment maps most of the names defined
in OCaml Module Pervasives (the initially opened module) to funcon terms.
See [https://caml.inria.fr/pub/docs/manual-ocaml-4.06/core.html] for further
details and comments.
It also maps some other names defined in the OCaml Standard Libarary to
funcon terms (to support tests using them without opening those modules).
*/
Funcon ocaml-light-core-library : =>environments
~> {// Predefined exceptions "Match_failure" |-> op-1(variant("Match_failure", arg)), "Invalid_argument" |-> op-1(variant("Invalid_argument", arg)), "Division_by_zero" |-> variant("Division_by_zero", tuple( )), // Exceptions "raise" |-> op-1(throw(arg)), //Comparisons "(=)" |-> op-2(ocaml-light-is-structurally-equal(arg-1, arg-2)), "(<>)" |-> op-2(not(ocaml-light-is-structurally-equal(arg-1, arg-2))), "(<)" |-> op-2(is-less(arg-1, arg-2)), "(>)" |-> op-2(is-greater(arg-1, arg-2)), "(<=)" |-> op-2(is-less-or-equal(arg-1, arg-2)), "(>=)" |-> op-2(is-greater-or-equal(arg-1, arg-2)), "min" |-> op-2(if-true-else(is-less(arg-1, arg-2), arg-1, arg-2)), "max" |-> op-2(if-true-else(is-greater(arg-1, arg-2), arg-1, arg-2)), "(==)" |-> op-2(if-true-else( and(is-in-type(arg-1, ground-values), is-in-type(arg-2, ground-values)), is-equal(arg-1, arg-2), throw(variant("Invalid_argument", "equal: functional value")))), "(!=)" |-> op-2(if-true-else( and(is-in-type(arg-1, ground-values), is-in-type(arg-2, ground-values)), not is-equal(arg-1, arg-2), throw(variant("Invalid_argument", "equal: functional value")))), // Boolean operations (excluding lazy conditionals) "not" |-> op-1(not(arg)), // Integer arithmetic "(~-)" |-> op-1(implemented-integer integer-negate(arg)), "(~+)" |-> op-1(implemented-integer arg), "succ" |-> op-1(implemented-integer integer-add(arg, 1)), "pred" |-> op-1(implemented-integer integer-subtract(arg, 1)), "(+)" |-> op-2(implemented-integer integer-add(arg-1, arg-2)), "(-)" |-> op-2(implemented-integer integer-subtract(arg-1, arg-2)), "(*)" |-> op-2(implemented-integer integer-multiply(arg-1, arg-2)), "(/)" |-> op-2(implemented-integer if-true-else(is-equal(arg-2, 0), throw(variant("Division_by_zero", tuple( ))), checked integer-divide(arg-1, arg-2))), "(mod)" |-> op-2(implemented-integer checked integer-modulo(arg-1, arg-2)), "abs" |-> op-1(implemented-integer integer-absolute-value(arg)), "max_int" |-> op-1(signed-bit-vector-maximum(implemented-integers-width)), "min_int" |-> op-1(signed-bit-vector-minimum(implemented-integers-width)), // Bitwise operations "(land)" |-> op-2(bit-vector-to-integer bit-vector-and(implemented-bit-vector arg-1, implemented-bit-vector arg-2)), "(lor)" |-> op-2(bit-vector-to-integer bit-vector-or(implemented-bit-vector arg-1, implemented-bit-vector arg-2)), "(lxor)" |-> op-2(bit-vector-to-integer bit-vector-xor(implemented-bit-vector arg-1, implemented-bit-vector arg-2)), "lnot" |-> op-1(bit-vector-to-integer bit-vector-not(implemented-bit-vector arg)), "(lsl)" |-> op-2(bit-vector-to-integer bit-vector-shift-left(implemented-bit-vector arg-1, arg-2)), "(lsr)" |-> op-2(bit-vector-to-integer bit-vector-logical-shift-right(implemented-bit-vector arg-1, arg-2)), "(asr)" |-> op-2(bit-vector-to-integer bit-vector-arithmetic-shift-right(implemented-bit-vector arg-1, arg-2)), // Floating-point arithmetic "(~-.)" |-> op-1(float-negate(implemented-floats-format, arg)), "(~+.)" |-> op-1(arg), "(+.)" |-> op-2(float-add(implemented-floats-format, arg-1, arg-2)), "(-.)" |-> op-2(float-subtract(implemented-floats-format, arg-1, arg-2)), "(*.)" |-> op-2(float-multiply(implemented-floats-format, arg-1, arg-2)), "(/.)" |-> op-2(float-divide(implemented-floats-format, arg-1, arg-2)), "(**)" |-> op-2(float-float-power(implemented-floats-format, arg-1, arg-2)), "sqrt" |-> op-1(float-sqrt(implemented-floats-format, arg)), "exp" |-> op-1(float-exp(implemented-floats-format, arg)), "log" |-> op-1(float-log(implemented-floats-format, arg)), "log10" |-> op-1(float-log10(implemented-floats-format, arg)), "cos" |-> op-1(float-cos(implemented-floats-format, arg)), "sin" |-> op-1(float-sin(implemented-floats-format, arg)), "tan" |-> op-1(float-tan(implemented-floats-format, arg)), "acos" |-> op-1(float-acos(implemented-floats-format, arg)), "asin" |-> op-1(float-asin(implemented-floats-format, arg)), "atan" |-> op-1(float-atan(implemented-floats-format, arg)), "atan2" |-> op-2(float-atan2(implemented-floats-format, arg-1, arg-2)), "cosh" |-> op-1(float-cosh(implemented-floats-format, arg)), "sinh" |-> op-1(float-sinh(implemented-floats-format, arg)), "tanh" |-> op-1(float-tanh(implemented-floats-format, arg)), "ceil" |-> op-1(implemented-integer float-ceiling(implemented-floats-format, arg)), "floor" |-> op-1(implemented-integer float-floor(implemented-floats-format, arg)), "abs_float" |-> op-1(float-absolute-value(implemented-floats-format, arg)), "mod_float" |-> op-2(float-remainder(implemented-floats-format, arg-1, arg-2)), "int_of_float" |-> op-1(implemented-integer float-truncate(implemented-floats-format, arg)), "float_of_int" |-> op-1(implemented-float-literal(string-append(to-string(arg), ".0"))), // String operations "(^)" |-> op-2(string-append(arg-1, arg-2)), // String conversion operations "string_of_int" |-> op-1(to-string(arg)), "int_of_string" |-> op-1(implemented-integer implemented-integer-literal(arg)), "string_of_float" |-> op-1(to-string(arg)), "float_of_string" |-> op-1(implemented-float-literal(arg)), // List operations "(@)" |-> op-2(list-append(arg-1, arg-2)), // Input/output // Output functions on standard output "print_char" |-> op-1(print(to-string(arg))), "print_string" |-> op-1(print(arg)), "print_int" |-> op-1(print(to-string(arg))), "print_float" |-> op-1(print(to-string(arg))), "print_newline" |-> op-1(print "\n"), // Input functions on standard input "read_line" |-> op-1(read), "read_int" |-> op-1(implemented-integer-literal(read)), "read_float" |-> op-1(implemented-float-literal(read)), // References (not represented as mutable records) "ref" |-> op-1(allocate-initialised-variable(implemented-values, arg)), "(!)" |-> op-1(assigned(arg)), "(:=)" |-> op-2(assign(arg-1, arg-2)), // Module List "length" |-> op-1(implemented-integer list-length(arg)), "cons" |-> op-2(cons(arg-1, arg-2)), "hd" |-> op-1(else(head(arg), throw(variant("Failure", "hd")))), "tl" |-> op-1(else(tail(arg), throw(variant("Failure", "tl")))), "rev" |-> op-1(list(reverse(list-elements(arg)))), // Module Array "array_length" |-> op-1(implemented-integer length(vector-elements(arg))), "array_make" |-> op-2(if-true-else(is-greater-or-equal(arg-1, 0), vector(interleave-map( allocate-initialised-variable(values, arg), n-of(arg-1, arg-2))), throw(variant("Invalid_argument", "array_make")))), "array_append" |-> op-2(vector(vector-elements(arg-1), vector-elements(arg-2))), "array_get" |-> op-2(else(assigned(checked index(nat-succ arg-2, vector-elements(arg-1))), throw(variant("Invalid_argument", "array_get")))), "array_set" |-> op-3(else(assign(checked index(nat-succ arg-2, vector-elements(arg-1)), arg-3), throw(variant("Invalid_argument", "array_set")))) }
## Language-specific funcons
### Exception values
Funcon ocaml-light-match-failure : =>variants(tuples(strings, integers, integers))
~> variant("Match_failure", tuple("", 0, 0))
/*
`ocaml-light-match-failure` gives a value to be thrown when a match fails.
The variant value should consist of the source program text, line, and column,
but these are currently not included in the translation of OCaml Light.
*/
Funcon ocaml-light-assert-failure : =>variants(tuples(strings, integers, integers))
~> variant("Assert_failure", tuple("", 0, 0))
/*
`ocaml-light-assert-failure` gives a value to be thrown when an assertion fails.
The variant value should consist of the source program text, line, and column,
but these are currently not included in the translation of OCaml Light.
*/
### Structural equality
Funcon ocaml-light-is-structurally-equal(_:implemented-values, _:implemented-values) : =>booleans
/*
`ocaml-light-is-structurally-equal(V1, V2)` is false whenever `V1` or `V2` contains a
function. For vectors, it compares all their respective assigned values.
It is equality on primitive values, and defined inductively on composite values.
*/ // Unit Type
Rule
ocaml-light-is-structurally-equal(null-value, null-value) ~> true // Booleans Rule ocaml-light-is-structurally-equal(B1:booleans, B2:booleans) ~> is-equal(B1,B2) // Integers Rule ocaml-light-is-structurally-equal(I1:implemented-integers, I2:implemented-integers) ~> is-equal(I1,I2) // Floats Rule ocaml-light-is-structurally-equal(F1:implemented-floats, F2:implemented-floats) ~> is-equal(F1,F2) // Characters Rule ocaml-light-is-structurally-equal(C1:implemented-characters, C2:implemented-characters) ~> is-equal(C1,C2) // Strings Rule ocaml-light-is-structurally-equal(S1:implemented-strings, S2:implemented-strings) ~> is-equal(S1,S2) // Tuples Rule ocaml-light-is-structurally-equal(tuple(), tuple()) ~> true Rule ocaml-light-is-structurally-equal(tuple(), tuple(V+)) ~> false Rule ocaml-light-is-structurally-equal(tuple(V+), tuple()) ~> false Rule ocaml-light-is-structurally-equal(tuple(V, V*), tuple(W, W*)) ~> and(ocaml-light-is-structurally-equal(V, W), ocaml-light-is-structurally-equal(tuple(V*), tuple(W*))) // Lists Rule ocaml-light-is-structurally-equal([], []) ~> true Rule ocaml-light-is-structurally-equal([], [V+]) ~> false Rule ocaml-light-is-structurally-equal([V+], []) ~> false Rule ocaml-light-is-structurally-equal([V,V*], [W,W*]) ~> and(ocaml-light-is-structurally-equal(V,W), ocaml-light-is-structurally-equal([V*], [W*])) // Records Rule dom(Map1) == dom(Map2) ---------------------------------------------------------------------- ocaml-light-is-structurally-equal(record(Map1:maps(_,_)), record(Map2:maps(_,_))) ~> not(is-in-set(false, set(interleave-map( ocaml-light-is-structurally-equal( checked lookup(Map1, given), checked lookup(Map2, given)), set-elements(dom(Map1)))))) // References Rule ocaml-light-is-structurally-equal(V1:variables, V2:variables) ~> ocaml-light-is-structurally-equal(assigned(V1), assigned(V2)) // Vectors Rule ocaml-light-is-structurally-equal(Vec1:vectors(values), Vec2:vectors(values)) ~> ocaml-light-is-structurally-equal([vector-elements(Vec1)], [vector-elements(Vec2)]) // Variants Rule ocaml-light-is-structurally-equal(variant(Con1,V1), variant(Con2,V2)) ~> if-true-else( is-equal(Con1, Con2), if-true-else( or(is-equal(tuple( ), V1), is-equal(tuple( ), V2)), and(is-equal(tuple( ), V1), is-equal(tuple( ), V2)), ocaml-light-is-structurally-equal(V1, V2)), false) // Functions Rule ocaml-light-is-structurally-equal(_:functions(_,_), _:functions(_,_)) ~> throw(variant("Invalid_argument", "equal: functional value"))
### Console display
Funcon ocaml-light-to-string(_:values) : =>strings
/*
`ocaml-light-to-string(V)` gives the string represention of OCaml Light values
as implemented by the ocaml interpreter.
*/
Rule // Unit
ocaml-light-to-string(null-value) ~> "()" Rule // Boo ummary>ocaml-light-to-string(B:booleans) ~> to-string(B) Rule // Int ummary>ocaml-light-to-string(I:integers) ~> to-string(I) Rule // Flo mary>ocaml-light-to-string(F:implemented-floats) ~> to-string(F) Rule // Cha /summary>ocaml-light-to-string(C:implemented-characters) ~> string-append("'", to-string(C), "'") Rule // Str mmary>S =/= [] ---------------------------------------------------------------- ocaml-light-to-string(S:implemented-strings) ~> string-append("\"", S, "\"") Rule // Fun summary>ocaml-light-to-string(_:functions(_,_)) ~> "" Rule // Ref /summary> ocaml-light-to-string(V:variables) ~> string-append("ref ", ocaml-light-to-string(assigned(V))) Rule // Var ummary>ocaml-light-to-string(variant(Con,Arg)) ~> if-true-else(is-equal(tuple( ),Arg), Con, string-append(Con, " ", ocaml-light-to-string(Arg))) Rule // Tup mary>ocaml-light-to-string(tuple(V:values, V+:values+)) ~> string-append( "(", intersperse(", ", interleave-map(ocaml-light-to-string(given), V, V+)), ")") Rule // Lis ary>ocaml-light-to-string([V*:values*]) ~> string-append( "[", intersperse("; ", interleave-map(ocaml-light-to-string(given), V*)), "]") Rule // Vec mmary>ocaml-light-to-string(V:implemented-vectors) ~> string-append( "[|", intersperse("; ", interleave-map( ocaml-light-to-string(assigned(given)), vector-elements(V))), "|]") Rule // Rec mmary>ocaml-light-to-string(record(M:maps(_,_))) ~> string-append( "{", intersperse("; ", interleave-map( string-append(arg-1," = ",ocaml-light-to-string(arg-2)), map-elements(M))), "}")
Funcon ocaml-light-define-and-display(Env:envs) : =>envs
~> sequential( effect left-to-right-map( print(arg-1, " = ", ocaml-light-to-string arg-2, "\n"), map-elements Env), Env)
Funcon ocaml-light-evaluate-and-display(V:implemented-values) : =>envs
~> sequential( print("- = ", ocaml-light-to-string V, "\n"), map())
/*
The following funcons take computations `X` and return (curried) functions. `X` refers to a single function argument as `arg`, or to individual arguments of a curried function of several arguments as `arg-1`, `arg-2`, `arg-3`.