Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rebis-dev: Fix UB in build_meta_predicate_clause #2764

Open
wants to merge 12 commits into
base: rebis-dev
Choose a base branch
from
Prev Previous commit
Next Next commit
remove Term
mthom committed Oct 26, 2024
commit fa1b052422da275645f4d44ac7483739071173d7
4 changes: 2 additions & 2 deletions build/instructions_template.rs
Original file line number Diff line number Diff line change
@@ -192,9 +192,9 @@ enum ReplCodePtr {
DynamicProperty,
#[strum_discriminants(strum(props(Arity = "3", Name = "$abolish_clause")))]
AbolishClause,
#[strum_discriminants(strum(props(Arity = "3", Name = "$asserta")))]
#[strum_discriminants(strum(props(Arity = "2", Name = "$asserta")))]
Asserta,
#[strum_discriminants(strum(props(Arity = "3", Name = "$assertz")))]
#[strum_discriminants(strum(props(Arity = "2", Name = "$assertz")))]
Assertz,
#[strum_discriminants(strum(props(Arity = "4", Name = "$retract_clause")))]
Retract,
16 changes: 6 additions & 10 deletions src/allocator.rs
Original file line number Diff line number Diff line change
@@ -4,8 +4,6 @@ use crate::forms::*;
use crate::instructions::*;
use crate::targets::*;

use std::cell::Cell;

pub(crate) trait Allocator {
fn new() -> Self;

@@ -19,37 +17,35 @@ pub(crate) trait Allocator {
fn mark_non_var<'a, Target: CompilationTarget<'a>>(
&mut self,
lvl: Level,
heap_loc: usize,
context: GenContext,
cell: &'a Cell<RegType>,
code: &mut CodeDeque,
);
) -> RegType;

#[allow(clippy::too_many_arguments)]
fn mark_reserved_var<'a, Target: CompilationTarget<'a>>(
&mut self,
var_num: usize,
lvl: Level,
cell: &Cell<VarReg>,
term_loc: GenContext,
context: GenContext,
code: &mut CodeDeque,
r: RegType,
is_new_var: bool,
);
) -> RegType;

fn mark_cut_var(&mut self, var_num: usize, chunk_num: usize) -> RegType;

fn mark_var<'a, Target: CompilationTarget<'a>>(
&mut self,
var_num: usize,
lvl: Level,
cell: &Cell<VarReg>,
context: GenContext,
code: &mut CodeDeque,
);
) -> RegType;

fn reset(&mut self);
fn reset_arg(&mut self, arg_num: usize);
fn reset_at_head(&mut self, args: &[Term]);
fn reset_at_head(&mut self, term: &mut FocusedHeap, head_loc: usize);
fn reset_contents(&mut self);

fn advance_arg(&mut self);
94 changes: 55 additions & 39 deletions src/arithmetic.rs
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@ use crate::debray_allocator::*;
use crate::forms::*;
use crate::instructions::*;
use crate::iterators::*;
use crate::machine::stack::Stack;
use crate::parser::ast::FocusedHeap;
use crate::targets::QueryInstruction;
use crate::types::*;

@@ -20,7 +22,6 @@ use dashu::base::BitTest;
use num_order::NumOrd;
use ordered_float::{Float, OrderedFloat};

use std::cell::Cell;
use std::cmp::{max, min, Ordering};
use std::convert::TryFrom;
use std::f64;
@@ -51,13 +52,14 @@ impl Default for ArithmeticTerm {
}
}

pub(crate) type ArithCont = (CodeDeque, Option<ArithmeticTerm>);

/*
#[derive(Debug)]
pub(crate) struct ArithInstructionIterator<'a> {
state_stack: Vec<TermIterState<'a>>,
}

pub(crate) type ArithCont = (CodeDeque, Option<ArithmeticTerm>);

impl<'a> ArithInstructionIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_stack
@@ -134,13 +136,6 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
}
}

#[derive(Debug)]
pub(crate) struct ArithmeticEvaluator<'a> {
marker: &'a mut DebrayAllocator,
interm: Vec<ArithmeticTerm>,
interm_c: usize,
}

pub(crate) trait ArithmeticTermIter<'a> {
type Iter: Iterator<Item = Result<ArithTermRef<'a>, ArithmeticError>>;

@@ -154,23 +149,31 @@ impl<'a> ArithmeticTermIter<'a> for &'a Term {
ArithInstructionIterator::from(self)
}
}
*/

#[derive(Debug)]
pub(crate) struct ArithmeticEvaluator<'a> {
marker: &'a mut DebrayAllocator,
interm: Vec<ArithmeticTerm>,
interm_c: usize,
}

fn push_literal(interm: &mut Vec<ArithmeticTerm>, c: &Literal) -> Result<(), ArithmeticError> {
fn push_literal(interm: &mut Vec<ArithmeticTerm>, c: Literal) -> Result<(), ArithmeticError> {
match c {
Literal::Fixnum(n) => interm.push(ArithmeticTerm::Number(Number::Fixnum(*n))),
Literal::Integer(n) => interm.push(ArithmeticTerm::Number(Number::Integer(*n))),
Literal::Fixnum(n) => interm.push(ArithmeticTerm::Number(Number::Fixnum(n))),
Literal::Integer(n) => interm.push(ArithmeticTerm::Number(Number::Integer(n))),
Literal::Float(n) => interm.push(ArithmeticTerm::Number(Number::Float(*n.as_ptr()))),
Literal::Rational(n) => interm.push(ArithmeticTerm::Number(Number::Rational(*n))),
Literal::Atom(name) if name == &atom!("e") => interm.push(ArithmeticTerm::Number(
Literal::Rational(n) => interm.push(ArithmeticTerm::Number(Number::Rational(n))),
Literal::Atom(name) if name == atom!("e") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::consts::E)),
)),
Literal::Atom(name) if name == &atom!("pi") => interm.push(ArithmeticTerm::Number(
Literal::Atom(name) if name == atom!("pi") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::consts::PI)),
)),
Literal::Atom(name) if name == &atom!("epsilon") => interm.push(ArithmeticTerm::Number(
Literal::Atom(name) if name == atom!("epsilon") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(f64::EPSILON)),
)),
_ => return Err(ArithmeticError::NonEvaluableFunctor(*c, 0)),
_ => return Err(ArithmeticError::NonEvaluableFunctor(c, 0)),
}

Ok(())
@@ -309,44 +312,57 @@ impl<'a> ArithmeticEvaluator<'a> {

pub(crate) fn compile_is(
&mut self,
src: &'a Term,
term_loc: GenContext,
src: &mut FocusedHeap,
term_loc: usize,
context: GenContext,
arg: usize,
) -> Result<ArithCont, ArithmeticError> {
let mut code = CodeDeque::new();

for term_ref in src.iter()? {
match term_ref? {
ArithTermRef::Literal(c) => push_literal(&mut self.interm, c)?,
ArithTermRef::Var(lvl, cell, name) => {
let var_num = name.to_var_num().unwrap();

let r = if lvl == Level::Shallow {
self.marker
.mark_non_callable(var_num, arg, term_loc, cell, &mut code)
} else if term_loc.is_last() || cell.get().norm().reg_num() == 0 {
let r = self.marker.get_binding(var_num);
let mut stack = Stack::uninitialized();
let mut iter = query_iterator::<false>(&mut src.heap, &mut stack, term_loc);

while let Some(term) = iter.next() {
read_heap_cell!(term,
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
let lvl = iter.level();
let var_ptr = src.var_locs.read_next_var_ptr_at_key(h).unwrap();
let var_num = var_ptr.to_var_num().unwrap();
let old_r = self.marker.get_var_binding(var_num);

let r = if lvl == Level::Root {
self.marker.mark_non_callable(var_num, arg, context, &mut code)
} else if context.is_last() || old_r.reg_num() == 0 {
let r = old_r;

if r.reg_num() == 0 {
self.marker.mark_var::<QueryInstruction>(
var_num, lvl, cell, term_loc, &mut code,
);
cell.get().norm()
var_num, lvl, context, &mut code,
)
} else {
self.marker.increment_running_count(var_num);
r
}
} else {
self.marker.increment_running_count(var_num);
cell.get().norm()
old_r
};

self.interm.push(ArithmeticTerm::Reg(r));
}
ArithTermRef::Op(name, arity) => {
code.push_back(self.instr_from_clause(name, arity)?);
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
push_literal(&mut self.interm, Literal::Atom(name))?;
} else {
code.push_back(self.instr_from_clause(name, arity)?);
}
}
}
_ => {
match Literal::try_from(term) {
Ok(lit) => push_literal(&mut self.interm, lit)?,
_ => unreachable!()
}
}
);
}

Ok((code, self.interm.pop()))
Loading