finalize operator support.
This commit is contained in:
@@ -60,7 +60,12 @@ impl PredicateClause {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Declaration {
|
||||
Op(usize, Specifier, Atom)
|
||||
}
|
||||
|
||||
pub enum TopLevel {
|
||||
Declaration(Declaration),
|
||||
Fact(Term),
|
||||
Predicate(Vec<PredicateClause>),
|
||||
Query(Vec<QueryTerm>),
|
||||
@@ -144,6 +149,10 @@ macro_rules! is_op {
|
||||
($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 )
|
||||
}
|
||||
@@ -196,7 +205,8 @@ pub enum ParserError
|
||||
InadmissibleFact,
|
||||
InadmissibleQueryTerm,
|
||||
IncompleteReduction,
|
||||
InconsistentPredicate,
|
||||
InconsistentDeclaration,
|
||||
InconsistentPredicate,
|
||||
ParseBigInt,
|
||||
ParseFloat(ParseFloatError),
|
||||
// TokenTooLong,
|
||||
|
||||
@@ -101,7 +101,10 @@ fn get_builtins() -> Code {
|
||||
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)
|
||||
@@ -111,9 +114,12 @@ 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 {
|
||||
@@ -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("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)
|
||||
}
|
||||
|
||||
@@ -250,6 +250,8 @@ pub fn read() -> String {
|
||||
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);
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
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 {
|
||||
($r:expr, $arg:expr) => (
|
||||
FactInstruction::GetVariable($r, $arg)
|
||||
|
||||
Submodule src/prolog/parser updated: de2a1a7364...b7a8133b75
Reference in New Issue
Block a user