--- /dev/null
+:- module(error, [must_be/2, can_be/2]).
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ I place this code in the public domain. Use it in any way you want.
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ must_be(Type, Term)
+
+ This predicate is intended for type-checks of built-in predicates.
+
+ It asserts that Term is:
+
+ 1) instantiated *and*
+ 2) instantiated to an instance of the given Type.
+
+ It corresponds to usage mode +Term.
+
+ Currently, the following types are supported:
+
+ - integer
+ - atom
+ - list.
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+must_be(Type, Term) :-
+ must_be_(Type, Term).
+
+
+must_be_(Type, _) :-
+ var(Type),
+ instantiation_error(Type).
+must_be_(integer, Term) :- check_(integer, integer, Term).
+must_be_(atom, Term) :- check_(atom, atom, Term).
+must_be_(list, Term) :- check_(ilist, list, Term).
+
+check_(Pred, Type, Term) :-
+ ( var(Term) -> instantiation_error(Term)
+ ; call(Pred, Term) -> true
+ ; type_error(Type, Term)
+ ).
+
+ilist(V) :- var(V), instantiation_error(V).
+ilist([]).
+ilist([_|Ls]) :- ilist(Ls).
+
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ can_be(Type, Term)
+
+ This predicate is intended for type-checks of built-in predicates.
+
+ It asserts that:
+
+ 1) Term is either a variable or instantiated *and*
+ 2) _if_ it is instantiated, then it is an instance of Type.
+
+ It corresponds to usage mode ?Term.
+
+ It supports the same types as must_be/2.
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+
+can_be(Type, Term) :-
+ ( var(Term) -> true
+ ; must_be(Type, Term)
+ ).
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ Shorthands for throwing ISO errors.
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+instantiation_error(_Term) :-
+ throw(error(instantiation_error, _)).
+
+domain_error(Type, Term) :-
+ throw(error(domain_error(Type, Term), _)).
+
+type_error(Type, Term) :-
+ throw(error(type_error(Type, Term), _)).
-:- module(terms, [numbervars/2]).
+:- module(terms, [numbervars/3]).
-numbervars(Term, N) :-
- integer(N),
- term_variables(Term, Vars),
- numberlist(Vars, N, N1).
+:- use_module(library(error)).
+
+numbervars(Term, N0, N) :-
+ must_be(integer, N0),
+ can_be(integer, N),
+ term_variables(Term, Vars),
+ numberlist(Vars, N0,N).
numberlist([], N,N).
numberlist(['$VAR'(N0)|Vars], N0,N) :-
static LISTS: &str = include_str!("../lib/lists.pl");
static CONTROL: &str = include_str!("../lib/control.pl");
static QUEUES: &str = include_str!("../lib/queues.pl");
+static ERROR: &str = include_str!("../lib/error.pl");
static TERMS: &str = include_str!("../lib/terms.pl");
impl Machine {
compile_user_module(&mut wam, LISTS.as_bytes());
compile_user_module(&mut wam, CONTROL.as_bytes());
compile_user_module(&mut wam, QUEUES.as_bytes());
+ compile_user_module(&mut wam, ERROR.as_bytes());
compile_user_module(&mut wam, TERMS.as_bytes());
wam