shift to builtins
This commit is contained in:
15
src/main.rs
15
src/main.rs
@@ -1,6 +1,7 @@
|
||||
#[macro_use] extern crate downcast;
|
||||
extern crate termion;
|
||||
|
||||
#[macro_use]
|
||||
mod prolog;
|
||||
|
||||
use prolog::ast::*;
|
||||
@@ -10,6 +11,7 @@ use prolog::machine::*;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub static BUILTINS: &str = include_str!("./prolog/lib/builtins.pl");
|
||||
pub static LISTS: &str = include_str!("./prolog/lib/lists.pl");
|
||||
pub static CONTROL: &str = include_str!("./prolog/lib/control.pl");
|
||||
pub static QUEUES: &str = include_str!("./prolog/lib/queues.pl");
|
||||
@@ -33,12 +35,19 @@ fn load_init_str(wam: &mut Machine, src_str: &str)
|
||||
}
|
||||
}
|
||||
|
||||
fn load_init_str_and_include(wam: &mut Machine, src_str: &str, module: &'static str)
|
||||
{
|
||||
load_init_str(wam, src_str);
|
||||
wam.use_module_in_toplevel(clause_name!(module));
|
||||
}
|
||||
|
||||
fn prolog_repl() {
|
||||
let mut wam = Machine::new();
|
||||
|
||||
load_init_str(&mut wam, LISTS);
|
||||
load_init_str(&mut wam, CONTROL);
|
||||
load_init_str(&mut wam, QUEUES);
|
||||
load_init_str_and_include(&mut wam, BUILTINS, "builtins");
|
||||
// load_init_str(&mut wam, LISTS);
|
||||
// load_init_str(&mut wam, CONTROL);
|
||||
// load_init_str(&mut wam, QUEUES);
|
||||
|
||||
loop {
|
||||
print!("prolog> ");
|
||||
|
||||
@@ -192,11 +192,13 @@ pub trait SubModuleUser {
|
||||
// returns true on successful import.
|
||||
fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool {
|
||||
let name = name.defrock_brackets();
|
||||
|
||||
let mut found_op = false;
|
||||
|
||||
{
|
||||
let mut insert_op_dir = |fix| {
|
||||
if let Some(op_data) = submodule.op_dir.get(&(name.clone(), fix)) {
|
||||
self.op_dir().insert((name.clone(), fix), op_data.clone());
|
||||
found_op = true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -212,7 +214,7 @@ pub trait SubModuleUser {
|
||||
self.insert_dir_entry(name, arity, code_data.clone());
|
||||
true
|
||||
} else {
|
||||
false
|
||||
found_op
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +229,7 @@ pub trait SubModuleUser {
|
||||
return EvalSession::from(SessionError::ModuleDoesNotContainExport);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EvalSession::EntrySuccess
|
||||
}
|
||||
|
||||
@@ -594,7 +596,7 @@ impl InlinedClauseType {
|
||||
(">", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThan)),
|
||||
("<", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThan)),
|
||||
(">=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThanOrEqual)),
|
||||
("<=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual)),
|
||||
("=<", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual)),
|
||||
("=\\=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual)),
|
||||
("=:=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal)),
|
||||
("atom", 1) => Some(InlinedClauseType::IsAtom),
|
||||
@@ -808,14 +810,14 @@ impl ClauseType {
|
||||
|
||||
pub fn name(&self) -> ClauseName {
|
||||
match self {
|
||||
&ClauseType::AcyclicTerm => clause_name!("$acyclic_term"),
|
||||
&ClauseType::AcyclicTerm => clause_name!("acyclic_term"),
|
||||
&ClauseType::Arg => clause_name!("arg"),
|
||||
&ClauseType::CallN => clause_name!("call"),
|
||||
&ClauseType::CallWithInferenceLimit => clause_name!("call_with_inference_limit"),
|
||||
&ClauseType::Catch => clause_name!("catch"),
|
||||
&ClauseType::Compare => clause_name!("compare"),
|
||||
&ClauseType::CompareTerm(qt) => clause_name!(qt.name()),
|
||||
&ClauseType::CyclicTerm => clause_name!("$cyclic_term"),
|
||||
&ClauseType::CyclicTerm => clause_name!("cyclic_term"),
|
||||
&ClauseType::Display => clause_name!("display"),
|
||||
&ClauseType::DuplicateTerm => clause_name!("duplicate_term"),
|
||||
&ClauseType::Eq => clause_name!("=="),
|
||||
@@ -823,26 +825,30 @@ impl ClauseType {
|
||||
&ClauseType::Ground => clause_name!("ground"),
|
||||
&ClauseType::Inlined(inlined) => clause_name!(inlined.name()),
|
||||
&ClauseType::Is => clause_name!("is"),
|
||||
&ClauseType::KeySort => clause_name!("$keysort"),
|
||||
&ClauseType::KeySort => clause_name!("keysort"),
|
||||
&ClauseType::NotEq => clause_name!("\\=="),
|
||||
&ClauseType::Op(ref name, ..) => name.clone(),
|
||||
&ClauseType::Named(ref name, ..) => name.clone(),
|
||||
&ClauseType::SetupCallCleanup => clause_name!("setup_call_cleanup"),
|
||||
&ClauseType::System(ref system) => system.name(),
|
||||
&ClauseType::Sort => clause_name!("$sort"),
|
||||
&ClauseType::Sort => clause_name!("sort"),
|
||||
&ClauseType::Throw => clause_name!("throw")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from(name: ClauseName, arity: usize, fixity: Option<Fixity>) -> Self {
|
||||
if let Some(inlined_ct) = InlinedClauseType::from(name.as_str(), arity) {
|
||||
return ClauseType::Inlined(inlined_ct);
|
||||
}
|
||||
|
||||
match (name.as_str(), arity) {
|
||||
("$acyclic_term", 1) => ClauseType::AcyclicTerm,
|
||||
("acyclic_term", 1) => ClauseType::AcyclicTerm,
|
||||
("arg", 3) => ClauseType::Arg,
|
||||
("call", _) => ClauseType::CallN,
|
||||
("call_with_inference_limit", 3) => ClauseType::CallWithInferenceLimit,
|
||||
("catch", 3) => ClauseType::Catch,
|
||||
("compare", 3) => ClauseType::Compare,
|
||||
("$cyclic_term", 1) => ClauseType::CyclicTerm,
|
||||
("cyclic_term", 1) => ClauseType::CyclicTerm,
|
||||
("@>", 2) => ClauseType::CompareTerm(CompareTermQT::GreaterThan),
|
||||
("@<", 2) => ClauseType::CompareTerm(CompareTermQT::LessThan),
|
||||
("@>=", 2) => ClauseType::CompareTerm(CompareTermQT::GreaterThanOrEqual),
|
||||
@@ -855,10 +861,10 @@ impl ClauseType {
|
||||
("functor", 3) => ClauseType::Functor,
|
||||
("ground", 1) => ClauseType::Ground,
|
||||
("is", 2) => ClauseType::Is,
|
||||
("$keysort", 2) => ClauseType::KeySort,
|
||||
("keysort", 2) => ClauseType::KeySort,
|
||||
("\\==", 2) => ClauseType::NotEq,
|
||||
("setup_call_cleanup", 3) => ClauseType::SetupCallCleanup,
|
||||
("$sort", 2) => ClauseType::Sort,
|
||||
("sort", 2) => ClauseType::Sort,
|
||||
("throw", 1) => ClauseType::Throw,
|
||||
_ => if let Some(fixity) = fixity {
|
||||
ClauseType::Op(name, fixity, CodeIndex::default())
|
||||
|
||||
@@ -739,17 +739,17 @@ fn get_builtins() -> Code {
|
||||
]
|
||||
}
|
||||
|
||||
pub fn build_code_and_op_dirs() -> (CodeDir, OpDir)
|
||||
pub fn default_op_dir() -> OpDir
|
||||
{
|
||||
let mut code_dir = HashMap::new();
|
||||
let mut op_dir = HashMap::new();
|
||||
|
||||
let builtin = ClauseName::BuiltIn("builtin");
|
||||
|
||||
op_dir.insert((clause_name!(":-"), Fixity::In), (XFX, 1200, builtin.clone()));
|
||||
op_dir.insert((clause_name!(":-"), Fixity::Pre), (FX, 1200, builtin.clone()));
|
||||
op_dir.insert((clause_name!("?-"), Fixity::Pre), (FX, 1200, builtin.clone()));
|
||||
|
||||
let mut op_dir = HashMap::new();
|
||||
let module_name = clause_name!("builtins");
|
||||
|
||||
op_dir.insert((clause_name!(":-"), Fixity::In), (XFX, 1200, module_name.clone()));
|
||||
op_dir.insert((clause_name!(":-"), Fixity::Pre), (FX, 1200, module_name.clone()));
|
||||
op_dir.insert((clause_name!("?-"), Fixity::Pre), (FX, 1200, module_name.clone()));
|
||||
// op_dir.insert((clause_name!("/"), Fixity::In), (YFX, 400, module_name.clone()));
|
||||
|
||||
/*
|
||||
// control operators.
|
||||
op_dir.insert((clause_name!("\\+"), Fixity::Pre), (FY, 900, builtin.clone()));
|
||||
op_dir.insert((clause_name!("="), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
@@ -761,8 +761,7 @@ pub fn build_code_and_op_dirs() -> (CodeDir, OpDir)
|
||||
op_dir.insert((clause_name!("/\\"), Fixity::In), (YFX, 500, builtin.clone()));
|
||||
op_dir.insert((clause_name!("\\/"), Fixity::In), (YFX, 500, builtin.clone()));
|
||||
op_dir.insert((clause_name!("xor"), Fixity::In), (YFX, 500, builtin.clone()));
|
||||
op_dir.insert((clause_name!("//"), Fixity::In), (YFX, 400, builtin.clone()));
|
||||
op_dir.insert((clause_name!("/"), Fixity::In), (YFX, 400, builtin.clone()));
|
||||
op_dir.insert((clause_name!("//"), Fixity::In), (YFX, 400, builtin.clone()));
|
||||
op_dir.insert((clause_name!("div"), Fixity::In), (YFX, 400, builtin.clone()));
|
||||
op_dir.insert((clause_name!("*"), Fixity::In), (YFX, 400, builtin.clone()));
|
||||
op_dir.insert((clause_name!("-"), Fixity::Pre), (FY, 200, builtin.clone()));
|
||||
@@ -819,7 +818,7 @@ pub fn build_code_and_op_dirs() -> (CodeDir, OpDir)
|
||||
code_dir.insert((clause_name!("integer"), 1), CodeIndex::from((163, builtin.clone())));
|
||||
code_dir.insert((clause_name!("display"), 1), CodeIndex::from((208, builtin.clone())));
|
||||
|
||||
code_dir.insert((clause_name!("is"), 2), CodeIndex::from((210, builtin.clone())));
|
||||
//code_dir.insert((clause_name!("is"), 2), CodeIndex::from((210, builtin.clone())));
|
||||
code_dir.insert((clause_name!(">"), 2), CodeIndex::from((212, builtin.clone())));
|
||||
code_dir.insert((clause_name!("<"), 2), CodeIndex::from((214, builtin.clone())));
|
||||
code_dir.insert((clause_name!(">="), 2), CodeIndex::from((216, builtin.clone())));
|
||||
@@ -851,14 +850,13 @@ pub fn build_code_and_op_dirs() -> (CodeDir, OpDir)
|
||||
code_dir.insert((clause_name!("\\=@="), 2), CodeIndex::from((408, builtin.clone())));
|
||||
code_dir.insert((clause_name!("compare"), 3), CodeIndex::from((480, builtin.clone())));
|
||||
code_dir.insert((clause_name!("atom"), 1), CodeIndex::from((481, builtin.clone())));
|
||||
code_dir.insert((clause_name!("sort"), 2), CodeIndex::from((483, builtin.clone())));
|
||||
code_dir.insert((clause_name!("keysort"), 2), CodeIndex::from((484, builtin.clone())));
|
||||
code_dir.insert((clause_name!("acyclic_term"), 1), CodeIndex::from((485, builtin.clone())));
|
||||
code_dir.insert((clause_name!("cyclic_term"), 1), CodeIndex::from((486, builtin.clone())));
|
||||
|
||||
(code_dir, op_dir)
|
||||
*/
|
||||
op_dir
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn default_build() -> (Code, CodeDir, OpDir)
|
||||
{
|
||||
let builtin_code = get_builtins();
|
||||
@@ -866,64 +864,4 @@ pub fn default_build() -> (Code, CodeDir, OpDir)
|
||||
|
||||
(builtin_code, code_dir, op_dir)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn builtin_module() -> Module
|
||||
{
|
||||
let (code_dir, op_dir) = build_code_and_op_dirs();
|
||||
let mut module_decl = module_decl!(clause_name!("builtin"),
|
||||
vec![(clause_name!("atomic"), 1),
|
||||
(clause_name!("var"), 1),
|
||||
(clause_name!("false"), 0),
|
||||
(clause_name!("catch"), 3),
|
||||
(clause_name!("throw"), 1),
|
||||
(clause_name!("(\\+)"), 1),
|
||||
(clause_name!("duplicate_term"), 2),
|
||||
(clause_name!("(=)"), 2),
|
||||
(clause_name!("true"), 0),
|
||||
(clause_name!("(,)"), 2),
|
||||
(clause_name!("(;)"), 2),
|
||||
(clause_name!("->"), 2),
|
||||
(clause_name!("functor"), 3),
|
||||
(clause_name!("arg"), 3),
|
||||
(clause_name!("(=..)"), 3),
|
||||
(clause_name!("display"), 1),
|
||||
(clause_name!("is"), 2),
|
||||
(clause_name!("(>)"), 2),
|
||||
(clause_name!("(<)"), 2),
|
||||
(clause_name!("(>=)"), 2),
|
||||
(clause_name!("(=<)"), 2),
|
||||
(clause_name!("(=\\=)"), 2),
|
||||
(clause_name!("(=:=)"), 2),
|
||||
(clause_name!("(@>)"), 2),
|
||||
(clause_name!("(@<)"), 2),
|
||||
(clause_name!("(@>=)"), 2),
|
||||
(clause_name!("(@=<)"), 2),
|
||||
(clause_name!("(=@=)"), 2),
|
||||
(clause_name!("(\\=@=)"), 2),
|
||||
(clause_name!("(==)"), 2),
|
||||
(clause_name!("(\\==)"), 2),
|
||||
(clause_name!("length"), 2),
|
||||
(clause_name!("compound"), 1),
|
||||
(clause_name!("rational"), 1),
|
||||
(clause_name!("integer"), 1),
|
||||
(clause_name!("string"), 1),
|
||||
(clause_name!("float"), 1),
|
||||
(clause_name!("nonvar"), 1),
|
||||
(clause_name!("ground"), 1),
|
||||
(clause_name!("setup_call_cleanup"), 3),
|
||||
(clause_name!("call_with_inference_limit"), 3),
|
||||
(clause_name!("compare"), 3),
|
||||
(clause_name!("atom"), 1),
|
||||
(clause_name!("sort"), 2),
|
||||
(clause_name!("keysort"), 2),
|
||||
(clause_name!("acyclic_term"), 1),
|
||||
(clause_name!("cyclic_term"), 1),
|
||||
(clause_name!("$skip_max_list"), 4)]);
|
||||
|
||||
for arity in 0 .. 63 {
|
||||
module_decl.exports.push((clause_name!("call"), arity));
|
||||
}
|
||||
|
||||
Module { module_decl, code_dir: as_module_code_dir(code_dir), op_dir }
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -550,7 +550,7 @@ fn compile_query(terms: Vec<QueryTerm>, queue: Vec<TopLevel>, code_size: usize,
|
||||
let mut code = try!(cg.compile_query(&terms));
|
||||
|
||||
compile_appendix(&mut code, queue)?;
|
||||
|
||||
|
||||
let query_info = QueryInfo {};
|
||||
query_info.label_clauses(code_size, code_dir, &mut code);
|
||||
|
||||
@@ -617,7 +617,9 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
|
||||
}
|
||||
|
||||
let mut module: Option<Module> = None;
|
||||
let (mut code_dir, mut op_dir) = build_code_and_op_dirs();
|
||||
|
||||
let mut code_dir = CodeDir::new();
|
||||
let mut op_dir = default_op_dir();
|
||||
|
||||
let mut code = Vec::new();
|
||||
|
||||
@@ -630,10 +632,10 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
|
||||
return EvalSession::from(ParserError::ExpectedRel),
|
||||
TopLevelPacket::Decl(TopLevel::Declaration(Declaration::Module(module_decl)), _) =>
|
||||
if module.is_none() {
|
||||
let (builtin_code_dir, builtin_op_dir) = build_code_and_op_dirs();
|
||||
// let builtin_op_dir = default_module_setup(module_decl.name.clone());
|
||||
|
||||
code_dir.extend(builtin_code_dir.into_iter());
|
||||
op_dir.extend(builtin_op_dir.into_iter());
|
||||
// code_dir.extend(builtin_code_dir.into_iter());
|
||||
// op_dir.extend(builtin_op_dir.into_iter());
|
||||
|
||||
module = Some(Module::new(module_decl));
|
||||
} else {
|
||||
|
||||
@@ -141,6 +141,8 @@ impl MachineState {
|
||||
self.heap.append(err);
|
||||
|
||||
self.registers[1] = Addr::HeapCell(h);
|
||||
self.goto_throw();
|
||||
|
||||
self.set_ball();
|
||||
self.unwind_stack();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,10 +434,16 @@ pub(crate) trait CallPolicy: Any {
|
||||
},
|
||||
&ClauseType::CallN =>
|
||||
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
|
||||
if let Some(idx) = code_dirs.get(name.clone(), arity, clause_name!("user")) {
|
||||
self.context_call(machine_st, name, arity, idx, lco)
|
||||
} else {
|
||||
Err(machine_st.existence_error(name, arity))
|
||||
let user = clause_name!("user");
|
||||
|
||||
match ClauseType::from(name.clone(), arity, None) {
|
||||
ClauseType::Op(..) | ClauseType::Named(..) =>
|
||||
if let Some(idx) = code_dirs.get(name.clone(), arity, user) {
|
||||
self.context_call(machine_st, name, arity, idx, lco)
|
||||
} else {
|
||||
Err(machine_st.existence_error(name, arity))
|
||||
},
|
||||
ct => self.try_call_clause(machine_st, code_dirs, &ct, arity, lco),
|
||||
}
|
||||
} else {
|
||||
Ok(())
|
||||
|
||||
@@ -1041,7 +1041,15 @@ impl MachineState {
|
||||
self.p = CodePtr::DirEntry(59, clause_name!("builtin"));
|
||||
}
|
||||
|
||||
fn unwind_stack(&mut self) {
|
||||
pub(super) fn set_ball(&mut self) {
|
||||
let addr = self[temp_v!(1)].clone();
|
||||
self.ball.boundary = self.heap.h;
|
||||
|
||||
let mut duplicator = DuplicateBallTerm::new(self);
|
||||
duplicator.duplicate_term(addr);
|
||||
}
|
||||
|
||||
pub(super) fn unwind_stack(&mut self) {
|
||||
self.b = self.block;
|
||||
self.or_stack.truncate(self.b);
|
||||
|
||||
@@ -1614,14 +1622,7 @@ impl MachineState {
|
||||
self.p += 1;
|
||||
},
|
||||
&BuiltInInstruction::SetBall => {
|
||||
let addr = self[temp_v!(1)].clone();
|
||||
self.ball.boundary = self.heap.h;
|
||||
|
||||
{
|
||||
let mut duplicator = DuplicateBallTerm::new(self);
|
||||
duplicator.duplicate_term(addr);
|
||||
};
|
||||
|
||||
self.set_ball();
|
||||
self.p += 1;
|
||||
},
|
||||
&BuiltInInstruction::SetCutPoint(r) =>
|
||||
|
||||
@@ -70,14 +70,15 @@ impl<'a> SubModuleUser for MachineCodeIndex<'a> {
|
||||
impl Machine {
|
||||
pub fn new() -> Self {
|
||||
let atom_tbl = Rc::new(RefCell::new(HashSet::new()));
|
||||
let (code, code_dir, op_dir) = default_build();
|
||||
let op_dir = default_op_dir(); //TODO: change to the builtins module once it's done.
|
||||
//let (code, code_dir, op_dir) = default_build();
|
||||
|
||||
Machine {
|
||||
ms: MachineState::new(atom_tbl),
|
||||
call_policy: Box::new(DefaultCallPolicy {}),
|
||||
cut_policy: Box::new(DefaultCutPolicy {}),
|
||||
code,
|
||||
code_dir,
|
||||
code: Code::new(),
|
||||
code_dir: CodeDir::new(),
|
||||
term_dir: TermDir::new(),
|
||||
op_dir,
|
||||
modules: HashMap::new(),
|
||||
|
||||
Submodule src/prolog/parser updated: 1b3bcc77f2...51e38dd242
@@ -393,17 +393,13 @@ impl RelationWorker {
|
||||
if name.as_str() == "!" || name.as_str() == "blocked_!" {
|
||||
Ok(QueryTerm::BlockedCut)
|
||||
} else {
|
||||
Ok(QueryTerm::Clause(r, ClauseType::Named(name, CodeIndex::default()),
|
||||
vec![]))
|
||||
Ok(QueryTerm::Clause(r, ClauseType::Named(name, CodeIndex::default()), vec![]))
|
||||
},
|
||||
Term::Var(_, ref v) if v.as_str() == "!" =>
|
||||
Ok(QueryTerm::UnblockedCut(Cell::default())),
|
||||
Term::Clause(r, name, mut terms, fixity) =>
|
||||
if let Some(system_ct) = SystemClauseType::from(name.as_str(), terms.len()) {
|
||||
Ok(QueryTerm::Clause(r, ClauseType::System(system_ct), terms))
|
||||
}
|
||||
else if let Some(inlined_ct) = InlinedClauseType::from(name.as_str(), terms.len()) {
|
||||
Ok(QueryTerm::Clause(r, ClauseType::Inlined(inlined_ct), terms))
|
||||
} else if name.as_str() == ";" {
|
||||
if terms.len() == 2 {
|
||||
let term = Term::Clause(r, name.clone(), terms, fixity);
|
||||
@@ -612,7 +608,10 @@ impl<R: Read> TopLevelWorker<R> {
|
||||
};
|
||||
}
|
||||
|
||||
results.push(deque_to_packet(append_preds(&mut preds), rel_worker.parse_queue()?));
|
||||
if !preds.is_empty() {
|
||||
results.push(deque_to_packet(append_preds(&mut preds), rel_worker.parse_queue()?));
|
||||
}
|
||||
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user