fn bindings_mut(&mut self) -> &mut AllocVarDict;
fn take_bindings(self) -> AllocVarDict;
+ fn max_reg_allocated(&self) -> usize;
fn drain_var_data<'a>(
&mut self,
};
self.compile_query_line(term, term_loc, code, num_perm_vars, is_exposed);
+
+ if self.marker.max_reg_allocated() > MAX_ARITY {
+ return Err(CompilationError::from(ParserError::ExceededMaxArity));
+ }
}
}
}
let iter = FactIterator::from_rule_head_clause(args);
let mut fact = self.compile_target::<FactInstruction, _>(iter, GenContext::Head, false);
+ if self.marker.max_reg_allocated() > MAX_ARITY {
+ return Err(CompilationError::from(ParserError::ExceededMaxArity));
+ }
+
let mut unsafe_var_marker = UnsafeVarMarker::new();
if !fact.is_empty() {
UnsafeVarMarker::from_safe_vars(safe_vars)
}
- pub(crate) fn compile_fact(&mut self, term: &Term) -> Code {
+ pub(crate) fn compile_fact(&mut self, term: &Term) -> Result<Code, CompilationError> {
self.update_var_count(post_order_iter(term));
let mut vs = VariableFixtures::new();
false,
);
+ if self.marker.max_reg_allocated() > MAX_ARITY {
+ return Err(CompilationError::from(ParserError::ExceededMaxArity));
+ }
+
self.mark_unsafe_fact_vars(&mut compiled_fact);
if !compiled_fact.is_empty() {
}
code.push(instr!("proceed"));
- code
+ Ok(code)
}
fn compile_query_line(
self.global_jmp_by_locs_offset = self.jmp_by_locs.len();
let clause_code = match clause {
- &PredicateClause::Fact(ref fact, ..) => self.compile_fact(fact),
+ &PredicateClause::Fact(ref fact, ..) => self.compile_fact(fact)?,
&PredicateClause::Rule(ref rule, ..) => self.compile_rule(rule)?,
};
};
}
- fn alloc_reg_to_var<'a, Target>(
+ fn alloc_reg_to_var<'a, Target: CompilationTarget<'a>>(
&mut self,
var: &String,
lvl: Level,
term_loc: GenContext,
target: &mut Vec<Instruction>,
- ) -> usize
- where
- Target: CompilationTarget<'a>,
- {
+ ) -> usize {
match term_loc {
GenContext::Head => {
if let Level::Shallow = lvl {
self.arg_c = 1;
self.temp_lb = arity + 1;
}
+
+ #[inline(always)]
+ fn max_reg_allocated(&self) -> usize {
+ std::cmp::max(self.temp_lb, self.arg_c)
+ }
}
match tl {
&TopLevel::Query(_) => Err(CompilationError::ExpectedRel),
&TopLevel::Predicate(ref clauses) => cg.compile_predicate(&clauses),
- &TopLevel::Fact(ref fact, ..) => Ok(cg.compile_fact(fact)),
+ &TopLevel::Fact(ref fact, ..) => cg.compile_fact(fact),
&TopLevel::Rule(ref rule, ..) => cg.compile_rule(rule),
}
}
pub enum CompilationError {
Arithmetic(ArithmeticError),
ParserError(ParserError),
- // BadPendingByte,
CannotParseCyclicTerm,
- // ExpandedTermsListNotAList,
ExpectedRel,
- // ExpectedTopLevelTerm,
InadmissibleFact,
InadmissibleQueryTerm,
InconsistentEntry,
- // InvalidDoubleQuotesDecl,
- // InvalidHook,
InvalidMetaPredicateDecl,
InvalidModuleDecl,
InvalidModuleExport,
&CompilationError::Arithmetic(..) => {
functor!(atom!("arithmetic_error"))
}
- // &CompilationError::BadPendingByte =>
- // functor!(atom_from_ss!("bad_pending_byte"), atom_tbl),
&CompilationError::CannotParseCyclicTerm => {
functor!(atom!("cannot_parse_cyclic_term"))
}
- // &CompilationError::ExpandedTermsListNotAList =>
- // functor!(atom_tbl.build_with_static_str("expanded_terms_list_is_not_a_list")),
&CompilationError::ExpectedRel => {
functor!(atom!("expected_relation"))
}
- // &CompilationError::ExpectedTopLevelTerm =>
- // functor!(atom_from_ss!("expected_atom_or_cons_or_clause"), atom_tbl),
&CompilationError::InadmissibleFact => {
functor!(atom!("inadmissible_fact"))
}
&CompilationError::InconsistentEntry => {
functor!(atom!("inconsistent_entry"))
}
- // &CompilationError::InvalidDoubleQuotesDecl =>
- // functor!(atom_from_ss!("invalid_double_quotes_declaration"), atom_tbl),
- // &CompilationError::InvalidHook =>
- // functor!(atom_from_ss!("invalid_hook"), atom_tbl),
&CompilationError::InvalidMetaPredicateDecl => {
functor!(atom!("invalid_meta_predicate_decl"))
}
}
}
-/*
-fn setup_scoped_predicate_indicator(term: &mut Term) -> Result<ScopedPredicateKey, CompilationError>
-{
- match term {
- Term::Clause(_, ref name, ref mut terms, Some(_))
- if name.as_str() == ":" && terms.len() == 2 =>
- {
- let mut predicate_indicator = *terms.pop().unwrap();
- let module_name = *terms.pop().unwrap();
-
- let module_name = module_name
- .to_constant()
- .and_then(|c| c.to_atom())
- .ok_or(CompilationError::InvalidModuleExport)?;
-
- let key = setup_predicate_indicator(&mut predicate_indicator)?;
-
- Ok((module_name, key))
- }
- _ => Err(CompilationError::InvalidModuleExport),
- }
-}
-*/
-
fn setup_module_export(
mut term: Term,
atom_tbl: &mut AtomTable,
* -
* ?
*/
+
fn setup_meta_predicate<'a, LS: LoadState<'a>>(
mut terms: Vec<Term>,
loader: &mut Loader<'a, LS>,
#[derive(Debug)]
pub enum ParserError {
BackQuotedString(usize, usize),
- UnexpectedChar(char, usize, usize),
- UnexpectedEOF,
+ ExceededMaxArity,
IO(IOError),
IncompleteReduction(usize, usize),
InvalidSingleQuotedCharacter(char),
+ LexicalError(lexical::Error),
MissingQuote(usize, usize),
NonPrologChar(usize, usize),
ParseBigInt(usize, usize),
- LexicalError(lexical::Error),
+ UnexpectedChar(char, usize, usize),
+ UnexpectedEOF,
Utf8Error(usize, usize),
}
impl ParserError {
pub fn line_and_col_num(&self) -> Option<(usize, usize)> {
match self {
- &ParserError::BackQuotedString(line_num, col_num)
- | &ParserError::UnexpectedChar(_, line_num, col_num)
- | &ParserError::IncompleteReduction(line_num, col_num)
- | &ParserError::MissingQuote(line_num, col_num)
- | &ParserError::NonPrologChar(line_num, col_num)
- | &ParserError::ParseBigInt(line_num, col_num)
- | &ParserError::Utf8Error(line_num, col_num) => Some((line_num, col_num)),
+ &ParserError::BackQuotedString(line_num, col_num) |
+ &ParserError::IncompleteReduction(line_num, col_num) |
+ &ParserError::MissingQuote(line_num, col_num) |
+ &ParserError::NonPrologChar(line_num, col_num) |
+ &ParserError::ParseBigInt(line_num, col_num) |
+ &ParserError::UnexpectedChar(_, line_num, col_num) |
+ &ParserError::Utf8Error(line_num, col_num) => Some((line_num, col_num)),
_ => None,
}
}
pub fn as_atom(&self) -> Atom {
match self {
ParserError::BackQuotedString(..) => atom!("back_quoted_string"),
- ParserError::UnexpectedChar(..) => atom!("unexpected_char"),
- ParserError::UnexpectedEOF => atom!("unexpected_end_of_file"),
+ ParserError::ExceededMaxArity => atom!("exceeded_max_arity"),
ParserError::IncompleteReduction(..) => atom!("incomplete_reduction"),
ParserError::InvalidSingleQuotedCharacter(..) => atom!("invalid_single_quoted_character"),
ParserError::IO(_) => atom!("input_output_error"),
ParserError::MissingQuote(..) => atom!("missing_quote"),
ParserError::NonPrologChar(..) => atom!("non_prolog_character"),
ParserError::ParseBigInt(..) => atom!("cannot_parse_big_int"),
+ ParserError::UnexpectedChar(..) => atom!("unexpected_char"),
+ ParserError::UnexpectedEOF => atom!("unexpected_end_of_file"),
ParserError::Utf8Error(..) => atom!("utf8_conversion_error"),
}
}
};
inner.add_lines_read(num_lines_read);
- Ok(write_term_to_heap(&term, &mut self.heap, &mut self.atom_tbl))
+ write_term_to_heap(&term, &mut self.heap, &mut self.atom_tbl)
}
}
term: &Term,
heap: &mut Heap,
atom_tbl: &mut AtomTable,
-) -> TermWriteResult {
+) -> Result<TermWriteResult, ParserError> {
let term_writer = TermWriter::new(heap, atom_tbl);
term_writer.write_term_to_heap(term)
}
}
}
- fn write_term_to_heap(mut self, term: &'a Term) -> TermWriteResult {
+ fn write_term_to_heap(mut self, term: &'a Term) -> Result<TermWriteResult, ParserError> {
let heap_loc = self.heap.len();
for term in breadth_first_iter(term, true) {
self.push_stub_addr();
}
&TermRef::Clause(Level::Root, _, ref ct, subterms) => {
+ if subterms.len() > MAX_ARITY {
+ return Err(ParserError::ExceededMaxArity);
+ }
+
self.heap.push(if subterms.len() == 0 {
heap_loc_as_cell!(heap_loc + 1)
} else {
self.modify_head_of_queue(&term, h);
}
- TermWriteResult {
+ Ok(TermWriteResult {
heap_loc,
var_dict: self.var_dict,
- }
+ })
}
}