finalize operator support.
This commit is contained in:
16
README.md
16
README.md
@@ -18,7 +18,7 @@ Extend rusty-wam to include the following, among other features:
|
|||||||
* call/N as a built-in meta-predicate (_done_).
|
* call/N as a built-in meta-predicate (_done_).
|
||||||
* ISO Prolog compliant throw/catch (_done_).
|
* ISO Prolog compliant throw/catch (_done_).
|
||||||
* Built-in and user-defined operators of all fixities, with custom
|
* 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.
|
* Bignum and floating point arithmetic.
|
||||||
* Built-in control operators (`,`, `;`, `->`, etc.).
|
* Built-in control operators (`,`, `;`, `->`, etc.).
|
||||||
* Attributed variables using the SICStus Prolog interface and
|
* Attributed variables using the SICStus Prolog interface and
|
||||||
@@ -51,7 +51,7 @@ The following predicates are built-in to rusty-wam.
|
|||||||
* catch/3
|
* catch/3
|
||||||
* duplicate_term/2
|
* duplicate_term/2
|
||||||
* false/0
|
* false/0
|
||||||
* not/1
|
* (\+)/1
|
||||||
* throw/1
|
* throw/1
|
||||||
* var/1
|
* var/1
|
||||||
|
|
||||||
@@ -125,3 +125,15 @@ X = call(f, z).
|
|||||||
Note that the values of variables belonging to successful queries are
|
Note that the values of variables belonging to successful queries are
|
||||||
printed out, on one line each. Uninstantiated variables are denoted by
|
printed out, on one line each. Uninstantiated variables are denoted by
|
||||||
a number preceded by an underscore (`X = _0` in an example above).
|
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)).
|
||||||
|
```
|
||||||
@@ -60,7 +60,12 @@ impl PredicateClause {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum Declaration {
|
||||||
|
Op(usize, Specifier, Atom)
|
||||||
|
}
|
||||||
|
|
||||||
pub enum TopLevel {
|
pub enum TopLevel {
|
||||||
|
Declaration(Declaration),
|
||||||
Fact(Term),
|
Fact(Term),
|
||||||
Predicate(Vec<PredicateClause>),
|
Predicate(Vec<PredicateClause>),
|
||||||
Query(Vec<QueryTerm>),
|
Query(Vec<QueryTerm>),
|
||||||
@@ -144,6 +149,10 @@ macro_rules! is_op {
|
|||||||
($x:expr) => ( $x & (XF | YF | FX | FY | XFX | XFY | YFX) != 0 )
|
($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 {
|
macro_rules! is_infix {
|
||||||
($x:expr) => ( ($x & (XFX | XFY | YFX)) != 0 )
|
($x:expr) => ( ($x & (XFX | XFY | YFX)) != 0 )
|
||||||
}
|
}
|
||||||
@@ -196,6 +205,7 @@ pub enum ParserError
|
|||||||
InadmissibleFact,
|
InadmissibleFact,
|
||||||
InadmissibleQueryTerm,
|
InadmissibleQueryTerm,
|
||||||
IncompleteReduction,
|
IncompleteReduction,
|
||||||
|
InconsistentDeclaration,
|
||||||
InconsistentPredicate,
|
InconsistentPredicate,
|
||||||
ParseBigInt,
|
ParseBigInt,
|
||||||
ParseFloat(ParseFloatError),
|
ParseFloat(ParseFloatError),
|
||||||
|
|||||||
@@ -101,7 +101,10 @@ fn get_builtins() -> Code {
|
|||||||
trust_me!(),
|
trust_me!(),
|
||||||
proceed!(),
|
proceed!(),
|
||||||
duplicate_term!(), // duplicate_term/2, 71.
|
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)
|
pub fn build_code_dir() -> (Code, CodeDir, OpDir)
|
||||||
@@ -111,8 +114,11 @@ pub fn build_code_dir() -> (Code, CodeDir, OpDir)
|
|||||||
|
|
||||||
let builtin_code = get_builtins();
|
let builtin_code = get_builtins();
|
||||||
|
|
||||||
op_dir.insert((String::from(":-"), Fixity::In), (XFX, 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), (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
|
// 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)
|
// (an extra register is needed for the predicate name)
|
||||||
@@ -123,10 +129,11 @@ pub fn build_code_dir() -> (Code, CodeDir, OpDir)
|
|||||||
code_dir.insert((String::from("atomic"), 1), (PredicateKeyType::BuiltIn, 1));
|
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("var"), 1), (PredicateKeyType::BuiltIn, 3));
|
||||||
code_dir.insert((String::from("false"), 0), (PredicateKeyType::BuiltIn, 61));
|
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("duplicate_term"), 2), (PredicateKeyType::BuiltIn, 71));
|
||||||
code_dir.insert((String::from("catch"), 3), (PredicateKeyType::BuiltIn, 5));
|
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("throw"), 1), (PredicateKeyType::BuiltIn, 59));
|
||||||
|
code_dir.insert((String::from("="), 2), (PredicateKeyType::BuiltIn, 73));
|
||||||
|
|
||||||
(builtin_code, code_dir, op_dir)
|
(builtin_code, code_dir, op_dir)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -250,6 +250,8 @@ pub fn read() -> String {
|
|||||||
pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<'b>
|
pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<'b>
|
||||||
{
|
{
|
||||||
match tl {
|
match tl {
|
||||||
|
&TopLevel::Declaration(ref decl) =>
|
||||||
|
wam.submit_decl(decl),
|
||||||
&TopLevel::Predicate(ref clauses) => {
|
&TopLevel::Predicate(ref clauses) => {
|
||||||
let mut cg = CodeGenerator::<DebrayAllocator>::new();
|
let mut cg = CodeGenerator::<DebrayAllocator>::new();
|
||||||
let compiled_pred = cg.compile_predicate(clauses);
|
let compiled_pred = cg.compile_predicate(clauses);
|
||||||
|
|||||||
@@ -439,6 +439,47 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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>
|
pub fn submit_query<'a>(&mut self, code: Code, alloc_locs: AllocVarDict<'a>) -> EvalSession<'a>
|
||||||
{
|
{
|
||||||
let mut heap_locs = HashMap::new();
|
let mut heap_locs = HashMap::new();
|
||||||
|
|||||||
@@ -62,6 +62,13 @@ macro_rules! get_var_in_query {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
macro_rules! get_value {
|
||||||
|
($r:expr, $arg:expr) => (
|
||||||
|
FactInstruction::GetValue($r, $arg)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! get_var_in_fact {
|
macro_rules! get_var_in_fact {
|
||||||
($r:expr, $arg:expr) => (
|
($r:expr, $arg:expr) => (
|
||||||
FactInstruction::GetVariable($r, $arg)
|
FactInstruction::GetVariable($r, $arg)
|
||||||
|
|||||||
Submodule src/prolog/parser updated: de2a1a7364...b7a8133b75
Reference in New Issue
Block a user