aboutsummaryrefslogtreecommitdiffstats
path: root/lib/term.ml
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/term.ml15
-rw-r--r--lib/term.mli9
2 files changed, 24 insertions, 0 deletions
diff --git a/lib/term.ml b/lib/term.ml
index a0dc760..fcef6f9 100644
--- a/lib/term.ml
+++ b/lib/term.ml
@@ -2,6 +2,7 @@ type t =
| Integer of Z.t
| Rational of Q.t
| String of string
+ | Reference of string
| Nil
| Record of t Label.Map.t
@@ -9,6 +10,16 @@ let integer z = Integer z
let string s = String s
let nil = Nil
+let reference name =
+ let is_letter c = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') in
+ let is_body c = is_letter c || (c >= '0' && c <= '9') || c = '_' in
+ if
+ String.length name > 0
+ && is_letter name.[0]
+ && String.for_all is_body name
+ then Ok (Reference name)
+ else Error (`Invalid_reference name)
+
let rational ~num ~den =
if Z.equal den Z.zero then Error `Zero_denominator
else
@@ -52,6 +63,7 @@ let rec compare a b =
| Integer x, Integer y -> Z.compare x y
| Rational x, Rational y -> Q.compare x y
| String x, String y -> String.compare x y
+ | Reference x, Reference y -> String.compare x y
| Nil, Nil -> 0
| Record x, Record y -> Label.Map.compare compare x y
| Integer _, _ -> -1
@@ -60,6 +72,8 @@ let rec compare a b =
| _, Rational _ -> 1
| String _, _ -> -1
| _, String _ -> 1
+ | Reference _, _ -> -1
+ | _, Reference _ -> 1
| Nil, _ -> -1
| _, Nil -> 1
@@ -81,6 +95,7 @@ let rec pp fmt t =
| Integer z -> Z.pp_print fmt z
| Rational q -> Q.pp_print fmt q
| String s -> Format.fprintf fmt "%S" s
+ | Reference name -> Format.fprintf fmt "#%s" name
| Nil -> Format.pp_print_string fmt "#()"
| Record map -> (
match as_cell t with
diff --git a/lib/term.mli b/lib/term.mli
index cf79d89..8dc201e 100644
--- a/lib/term.mli
+++ b/lib/term.mli
@@ -17,6 +17,11 @@ type t = private
its minimal shape, so integer membership inclusion holds
literally. *)
| String of string
+ | Reference of string
+ (** A relation reference, written [#Name]: a first-class
+ value denoting a relation by name, resolved through the
+ catalog of a state. Distinct from {!String} on purpose;
+ identity is not representation. *)
| Nil (** The empty sequence, written [#()]. *)
| Record of t Label.Map.t
(** A nonempty labeled tuple. Attribute order is canonical
@@ -30,6 +35,10 @@ val nil : t
(** The empty sequence, [#()]. The distinguished base every
{!sequence} chain ends in. *)
+val reference : string -> (t, [ `Invalid_reference of string ]) result
+(** A relation reference. Validates the name: a letter, then
+ letters, digits, or underscores. *)
+
val rational : num:Z.t -> den:Z.t -> (t, [ `Zero_denominator ]) result
(** Normalizes on entry: reduces by the gcd, moves the sign to the
numerator, and collapses to {!Integer} when the reduced