compile_appendix(&mut decl_code, &queue, non_counted_bt, wam.machine_flags())?;
- let idx = code_dir.entry((name, arity)).or_insert(CodeIndex::default());
+ let idx = code_dir.entry((name.clone(), arity)).or_insert(CodeIndex::default());
set_code_index!(idx, IndexPtr::Index(p), self.get_module_name());
code.extend(decl_code.into_iter());
}
impl MachineState {
- pub fn numbervar(&self, addr: Addr) -> Option<Var> {
+ pub fn numbervar(&self, offset: &BigInt, addr: Addr) -> Option<Var> {
static CHAR_CODES: [char; 26] = ['A','B','C','D','E','F','G','H','I','J',
'K','L','M','N','O','P','Q','R','S','T',
'U','V','W','X','Y','Z'];
match self.store(self.deref(addr)) {
Addr::Con(Constant::Number(Number::Integer(ref n)))
if !n.is_negative() => {
+ let n = offset + n.as_ref();
+
let i = n.mod_floor(&BigInt::from(26)).to_usize().unwrap();
let j = n.div_floor(&BigInt::from(26));
heap_locs: ReverseHeapVarDict,
printed_vars: HashSet<Addr>,
last_item_idx: usize,
+ pub(crate) numbervars_offset: BigInt,
pub(crate) numbervars: bool,
pub(crate) quoted: bool,
pub(crate) ignore_ops: bool
printed_vars: HashSet::new(),
last_item_idx: 0,
numbervars: false,
+ numbervars_offset: BigInt::zero(),
quoted: false,
ignore_ops: false }
}
let addr = iter.stack().last().cloned().unwrap();
// 7.10.4
- if let Some(var) = iter.machine_st().numbervar(addr) {
+ if let Some(var) = iter.machine_st().numbervar(&self.numbervars_offset, addr) {
iter.stack().pop();
self.state_stack.push(TokenOrRedirect::NumberedVar(var));
return;
ref addr if addr.is_ref() => {
let stub = MachineError::functor_stub(clause_name!("if_"), 3);
let err = MachineError::instantiation_error();
-
+
Err(machine_st.error_form(err, stub))
},
addr => {
let stub = MachineError::functor_stub(clause_name!("if_"), 3);
let err = MachineError::type_error(ValidType::Boolean, addr);
-
+
Err(machine_st.error_form(err, stub))
}
}
use prolog::num::bigint::{BigInt};
use std::collections::HashSet;
+use std::io::{stdout, Write};
use std::mem;
use std::rc::Rc;
let mut output = printer.print(addr);
print!("{}", output.result());
+ stdout().flush().unwrap();
}
};
use prolog::instructions::HeapCellValue;
use prolog::machine::*;
+use prolog::num::*;
use prolog::read::*;
use std::cell::Cell;
}
impl MachineState {
- fn print_with_locs(&self, target: usize, var_dict: &HeapVarDict) -> PrinterOutputter {
+ fn print_with_locs(&self, target: usize, max_var_length: usize, var_dict: &HeapVarDict)
+ -> PrinterOutputter
+ {
let output = PrinterOutputter::new();
let mut printer = HCPrinter::from_heap_locs(&self, output, &var_dict);
printer.quoted = true;
printer.numbervars = true;
+ // the purpose of the offset is to avoid clashes with variable names that might
+ // occur after the addresses in the expanded term are substituted with the variable
+ // names in the pre-expansion term. This formula ensures that all generated "numbervars"-
+ // style variable names will be longer than the keys of the var_dict, and therefore
+ // not equal to any of them.
+ printer.numbervars_offset = pow(BigInt::from(10), max_var_length) * 26;
printer.see_all_locs();
code_repo: &mut CodeRepo, term: &Term, hook: CompileTimeHook)
-> Option<String>
{
- let (term_h, var_dict) = write_term_to_heap(term, self);
+ let term_write_result = write_term_to_heap(term, self);
let h = self.heap.h;
- self[temp_v!(1)] = Addr::HeapCell(term_h);
+ self[temp_v!(1)] = Addr::HeapCell(term_write_result.heap_loc);
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
self[temp_v!(2)] = Addr::HeapCell(h);
self.reset();
None
} else {
- let mut output = self.print_with_locs(h, &var_dict);
+ let &TermWriteResult { heap_loc: _, max_var_length, ref var_dict } = &term_write_result;
+ let mut output = self.print_with_locs(h, max_var_length, var_dict);
output.push_char('.');
self.reset();
let mut parser = Parser::new(inner, atom_tbl, self.flags);
let term = parser.read_term(composite_op!(op_dir))?;
- Ok(write_term_to_heap(&term, self).0)
+ Ok(write_term_to_heap(&term, self).heap_loc)
}
}
}
}
-pub(crate) fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> (usize, HeapVarDict) {
- let h = machine_st.heap.h;
+pub(crate) struct TermWriteResult {
+ pub(crate) heap_loc: usize,
+ pub(crate) max_var_length: usize, // maximum length of the variable names encountered.
+ pub(crate) var_dict: HeapVarDict,
+}
+pub(crate) fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult
+{
+ let heap_loc = machine_st.heap.h;
+
+ let mut max_var_length = 0;
let mut queue = SubtermDeque::new();
let mut var_dict = HeapVarDict::new();
continue;
}
},
- &TermRef::AnonVar(Level::Root)
- | &TermRef::Var(Level::Root, ..)
- | &TermRef::Constant(Level::Root, ..) =>
+ &TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) =>
machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h))),
+ &TermRef::Var(Level::Root, _, ref name) => {
+ max_var_length = std::cmp::max(max_var_length, name.len());
+ machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h)));
+ },
&TermRef::AnonVar(_) => {
if let Some((arity, site_h)) = queue.pop_front() {
if arity > 1 {
}
}
+ max_var_length = std::cmp::max(max_var_length, var.len());
continue;
},
_ => {}
modify_head_of_queue(machine_st, &mut queue, term, h);
}
- (h, var_dict)
+ TermWriteResult { heap_loc, var_dict, max_var_length }
}