add op/3 to builtin predicates

This commit is contained in:
Mark Thom
2019-03-30 18:14:47 -06:00
parent f55968b1b8
commit 0aefcf7eae
10 changed files with 186 additions and 42 deletions

View File

@@ -1,4 +1,5 @@
use prolog_parser::ast::*;
use prolog_parser::parser::get_desc;
use prolog_parser::tabled_rc::TabledData;
use prolog::instructions::*;
@@ -551,8 +552,25 @@ impl ListingCompiler {
},
Declaration::NonCountedBacktracking(name, arity) =>
Ok(self.add_non_counted_bt_flag(name, arity)),
Declaration::Op(op_decl) =>
op_decl.submit(self.get_module_name(), &mut indices.op_dir),
Declaration::Op(op_decl) => {
let existing_desc = {
let comp_ops = composite_op!(self.module.is_some(), &wam_indices.op_dir,
&mut indices.op_dir);
get_desc(op_decl.name(), comp_ops)
};
if op_decl.0 == 0 {
// remove all instances of the operator.
if self.module.is_none() {
op_decl.remove(&mut wam_indices.op_dir);
}
Ok(())
} else {
op_decl.submit(self.get_module_name(), existing_desc, &mut indices.op_dir)
}
},
Declaration::UseModule(name) =>
self.use_module(name, code_repo, flags, wam_indices, indices),
Declaration::UseQualifiedModule(name, exports) =>

View File

@@ -68,23 +68,29 @@ impl MachineError {
SessionError::ParserError(err) => Self::syntax_error(h, err),
SessionError::CannotOverwriteBuiltIn(pred_str)
| SessionError::CannotOverwriteImport(pred_str) =>
Self::permission_error(PermissionError::Modify, pred_str),
Self::permission_error(PermissionError::Modify, "private_procedure", pred_str),
SessionError::ModuleDoesNotContainExport =>
Self::permission_error(PermissionError::Access,
"private_procedure",
clause_name!("module_does_not_contain_claimed_export")),
SessionError::ModuleNotFound =>
Self::permission_error(PermissionError::Access,
"private_procedure",
clause_name!("module_does_not_exist")),
SessionError::OpIsInfixAndPostFix(op) =>
Self::permission_error(PermissionError::Create,
"operator",
op),
_ => unreachable!()
}
}
pub(super)
fn permission_error(err: PermissionError, pred_str: ClauseName) -> Self
fn permission_error(err: PermissionError, index_str: &'static str, pred_str: ClauseName) -> Self
{
let pred_str = HeapCellValue::Addr(Addr::Con(Constant::Atom(pred_str, None)));
let err = vec![heap_atom!(err.as_str()), heap_atom!("private_procedure"), pred_str];
let err = vec![heap_atom!(err.as_str()), heap_atom!(index_str), pred_str];
let mut stub = functor!("permission_error", 3);
stub.extend(err.into_iter());
@@ -144,6 +150,7 @@ impl MachineError {
#[derive(Clone, Copy)]
pub enum PermissionError {
Access,
Create,
Modify,
}
@@ -151,6 +158,7 @@ impl PermissionError {
pub fn as_str(self) -> &'static str {
match self {
PermissionError::Access => "access",
PermissionError::Create => "create",
PermissionError::Modify => "modify"
}
}
@@ -375,7 +383,7 @@ pub enum SessionError {
ModuleDoesNotContainExport,
ModuleNotFound,
NamelessEntry,
OpIsInfixAndPostFix,
OpIsInfixAndPostFix(ClauseName),
ParserError(ParserError),
QueryFailure,
QueryFailureWithException(ClauseName),

View File

@@ -1,5 +1,5 @@
use prolog_parser::ast::*;
use prolog_parser::parser::get_clause_spec;
use prolog_parser::parser::{get_desc, get_clause_spec};
use prolog::clause_types::*;
use prolog::heap_iter::*;
@@ -8,6 +8,7 @@ use prolog::machine::copier::*;
use prolog::machine::machine_errors::*;
use prolog::machine::machine_indices::*;
use prolog::machine::machine_state::*;
use prolog::machine::toplevel::to_op_decl;
use prolog::num::{FromPrimitive, ToPrimitive, Zero};
use prolog::num::bigint::{BigInt};
@@ -568,6 +569,51 @@ impl MachineState {
_ => self.fail = true
}
},
&SystemClauseType::OpDeclaration => {
let priority = self[temp_v!(1)].clone();
let specifier = self[temp_v!(2)].clone();
let op = self[temp_v!(3)].clone();
let priority = match self.store(self.deref(priority)) {
Addr::Con(Constant::Number(Number::Integer(n))) => n.to_usize().unwrap(),
_ => unreachable!()
};
let specifier = match self.store(self.deref(specifier)) {
Addr::Con(Constant::Atom(name, _)) => name,
_ => unreachable!()
};
let op = match self.store(self.deref(op)) {
Addr::Con(Constant::Atom(name, _)) => name,
_ => unreachable!()
};
let module = op.owning_module();
let result = to_op_decl(priority, specifier.as_str(), op)
.map_err(SessionError::from)
.and_then(|op_decl| {
if op_decl.0 == 0 {
Ok(op_decl.remove(&mut indices.op_dir))
} else {
let desc = get_desc(op_decl.name(), composite_op!(&indices.op_dir));
op_decl.submit(module, desc, &mut indices.op_dir)
}
});
match result {
Ok(()) => {},
Err(e) => {
// 8.14.3.3 l)
let e = MachineError::session_error(self.heap.h, e);
let stub = MachineError::functor_stub(clause_name!("op"), 3);
let permission_error = self.error_form(e, stub);
return Err(permission_error);
}
};
},
&SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff =>
self.truncate_if_no_lifted_heap_diff(|h| Addr::HeapCell(h)),
&SystemClauseType::TruncateIfNoLiftedHeapGrowth =>

View File

@@ -115,6 +115,20 @@ fn is_compile_time_hook(name: &ClauseName, terms: &Vec<Box<Term>>) -> Option<Com
type CompileTimeHookCompileInfo = (CompileTimeHook, PredicateClause, VecDeque<TopLevel>);
pub fn to_op_decl(prec: usize, spec: &str, name: ClauseName) -> Result<OpDecl, ParserError>
{
match spec {
"xfx" => Ok(OpDecl(prec, XFX, name)),
"xfy" => Ok(OpDecl(prec, XFY, name)),
"yfx" => Ok(OpDecl(prec, YFX, name)),
"fx" => Ok(OpDecl(prec, FX, name)),
"fy" => Ok(OpDecl(prec, FY, name)),
"xf" => Ok(OpDecl(prec, XF, name)),
"yf" => Ok(OpDecl(prec, YF, name)),
_ => Err(ParserError::InconsistentEntry)
}
}
fn setup_op_decl(mut terms: Vec<Box<Term>>) -> Result<OpDecl, ParserError>
{
let name = match *terms.pop().unwrap() {
@@ -136,16 +150,7 @@ fn setup_op_decl(mut terms: Vec<Box<Term>>) -> Result<OpDecl, ParserError>
_ => return Err(ParserError::InconsistentEntry)
};
match spec.as_str() {
"xfx" => Ok(OpDecl(prec, XFX, name)),
"xfy" => Ok(OpDecl(prec, XFY, name)),
"yfx" => Ok(OpDecl(prec, YFX, name)),
"fx" => Ok(OpDecl(prec, FX, name)),
"fy" => Ok(OpDecl(prec, FY, name)),
"xf" => Ok(OpDecl(prec, XF, name)),
"yf" => Ok(OpDecl(prec, YF, name)),
_ => Err(ParserError::InconsistentEntry)
}
to_op_decl(prec, spec.as_str(), name)
}
fn setup_predicate_indicator(mut term: Term) -> Result<PredicateKey, ParserError>