* call/N as a built-in meta-predicate (_done_).
* ISO Prolog compliant throw/catch (_done_).
* Built-in and user-defined operators of all fixities, with custom
- associativity and precedence (_in progress_).
+ associativity and precedence (_done_).
* Bignum and floating point arithmetic.
* Built-in control operators (`,`, `;`, `->`, etc.).
* Attributed variables using the SICStus Prolog interface and
* catch/3
* duplicate_term/2
* false/0
-* not/1
+* (\+)/1
* throw/1
* var/1
Note that the values of variables belonging to successful queries are
printed out, on one line each. Uninstantiated variables are denoted by
-a number preceded by an underscore (`X = _0` in an example above).
\ No newline at end of file
+a number preceded by an underscore (`X = _0` in an example above).
+
+Lastly, rusty-wam supports dynamic operators:
+```
+prolog> :- op(500, yfx, +).
+prolog> :- op(500, yfx, -).
+prolog> :- op(200, fy, -).
+prolog> :- op(400, yfx, *).
+prolog> :- op(400, yfx, /).
+prolog> ?- X = -5 + 3 - (2 * 4) / 8.
+true.
+X = -(+(-(5), 3), /(*(2, 4), 8)).
+```
\ No newline at end of file
}
}
+pub enum Declaration {
+ Op(usize, Specifier, Atom)
+}
+
pub enum TopLevel {
+ Declaration(Declaration),
Fact(Term),
Predicate(Vec<PredicateClause>),
Query(Vec<QueryTerm>),
($x:expr) => ( $x & (XF | YF | FX | FY | XFX | XFY | YFX) != 0 )
}
+macro_rules! is_postfix {
+ ($x:expr) => ( $x & (XF | YF) != 0 )
+}
+
macro_rules! is_infix {
($x:expr) => ( ($x & (XFX | XFY | YFX)) != 0 )
}
InadmissibleFact,
InadmissibleQueryTerm,
IncompleteReduction,
- InconsistentPredicate,
+ InconsistentDeclaration,
+ InconsistentPredicate,
ParseBigInt,
ParseFloat(ParseFloatError),
// TokenTooLong,
trust_me!(),
proceed!(),
duplicate_term!(), // duplicate_term/2, 71.
- proceed!()]
+ proceed!(),
+ fact![get_value!(temp_v!(1), 2)], // =/2, 73.
+ proceed!(),
+ ]
}
pub fn build_code_dir() -> (Code, CodeDir, OpDir)
let builtin_code = get_builtins();
- op_dir.insert((String::from(":-"), Fixity::In), (XFX, 1200));
- op_dir.insert((String::from("?-"), Fixity::Pre), (FX, 1200));
-
+ op_dir.insert((String::from(":-"), Fixity::In), (XFX, 1200));
+ op_dir.insert((String::from(":-"), Fixity::Pre), (FX, 1200));
+ op_dir.insert((String::from("?-"), Fixity::Pre), (FX, 1200));
+ op_dir.insert((String::from("\\+"), Fixity::Pre), (FY, 900));
+ op_dir.insert((String::from("="), Fixity::In), (XFX, 700));
+
// there are 63 registers in the VM, so call/N is defined for all 0 <= N <= 62
// (an extra register is needed for the predicate name)
for arity in 0 .. 63 {
code_dir.insert((String::from("atomic"), 1), (PredicateKeyType::BuiltIn, 1));
code_dir.insert((String::from("var"), 1), (PredicateKeyType::BuiltIn, 3));
code_dir.insert((String::from("false"), 0), (PredicateKeyType::BuiltIn, 61));
- code_dir.insert((String::from("not"), 1), (PredicateKeyType::BuiltIn, 62));
+ code_dir.insert((String::from("\\+"), 1), (PredicateKeyType::BuiltIn, 62));
code_dir.insert((String::from("duplicate_term"), 2), (PredicateKeyType::BuiltIn, 71));
code_dir.insert((String::from("catch"), 3), (PredicateKeyType::BuiltIn, 5));
code_dir.insert((String::from("throw"), 1), (PredicateKeyType::BuiltIn, 59));
+ code_dir.insert((String::from("="), 2), (PredicateKeyType::BuiltIn, 73));
(builtin_code, code_dir, op_dir)
}
pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<'b>
{
match tl {
+ &TopLevel::Declaration(ref decl) =>
+ wam.submit_decl(decl),
&TopLevel::Predicate(ref clauses) => {
let mut cg = CodeGenerator::<DebrayAllocator>::new();
let compiled_pred = cg.compile_predicate(clauses);
}
}
+ pub fn submit_decl<'a>(&mut self, decl: &Declaration) -> EvalSession<'a> {
+ match decl {
+ &Declaration::Op(prec, spec, ref name) => {
+ lazy_static! {
+ static ref ERR_STRING: String = String::from("an operator can't be both \
+ infix and postfix.");
+ }
+
+ if is_infix!(spec) {
+ match self.op_dir.get(&(name.clone(), Fixity::Post)) {
+ Some(_) => return EvalSession::EntryFailure(ERR_STRING.clone()),
+ _ => {}
+ };
+ }
+
+ if is_postfix!(spec) {
+ match self.op_dir.get(&(name.clone(), Fixity::In)) {
+ Some(_) => return EvalSession::EntryFailure(ERR_STRING.clone()),
+ _ => {}
+ };
+ }
+
+ if prec > 0 {
+ match spec {
+ XFY | XFX | YFX => self.op_dir.insert((name.clone(), Fixity::In),
+ (spec, prec)),
+ XF | YF => self.op_dir.insert((name.clone(), Fixity::Post), (spec, prec)),
+ FX | FY => self.op_dir.insert((name.clone(), Fixity::Pre), (spec,prec)),
+ _ => None
+ };
+ } else {
+ self.op_dir.remove(&(name.clone(), Fixity::Pre));
+ self.op_dir.remove(&(name.clone(), Fixity::In));
+ self.op_dir.remove(&(name.clone(), Fixity::Post));
+ }
+
+ EvalSession::EntrySuccess
+ }
+ }
+ }
+
pub fn submit_query<'a>(&mut self, code: Code, alloc_locs: AllocVarDict<'a>) -> EvalSession<'a>
{
let mut heap_locs = HashMap::new();
)
}
+
+macro_rules! get_value {
+ ($r:expr, $arg:expr) => (
+ FactInstruction::GetValue($r, $arg)
+ )
+}
+
macro_rules! get_var_in_fact {
($r:expr, $arg:expr) => (
FactInstruction::GetVariable($r, $arg)
-Subproject commit de2a1a73649e2c52a05d19ff33f08c33c22b3973
+Subproject commit b7a8133b75f0a7d5b7e29c1f4edf18cae4f8c56f