use crate::parser::ast::*; use crate::atom_table::*; use crate::forms::*; use crate::instructions::*; use crate::iterators::*; use crate::types::*; pub(crate) struct FactInstruction; pub(crate) struct QueryInstruction; pub(crate) trait CompilationTarget<'a> { type Iterator: Iterator>; fn iter(term: &'a Term) -> Self::Iterator; fn to_constant(lvl: Level, literal: Literal, r: RegType) -> Instruction; fn to_list(lvl: Level, r: RegType) -> Instruction; fn to_structure(lvl: Level, name: Atom, arity: usize, r: RegType) -> Instruction; fn to_void(num_subterms: usize) -> Instruction; fn is_void_instr(instr: &Instruction) -> bool; fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Instruction; fn incr_void_instr(instr: &mut Instruction); fn constant_subterm(literal: Literal) -> Instruction; fn argument_to_variable(r: RegType, r: usize) -> Instruction; fn argument_to_value(r: RegType, val: usize) -> Instruction; fn unsafe_argument_to_value(r: RegType, val: usize) -> Instruction; fn move_to_register(r: RegType, val: usize) -> Instruction; fn subterm_to_variable(r: RegType) -> Instruction; fn subterm_to_value(r: RegType) -> Instruction; fn unsafe_subterm_to_value(r: RegType) -> Instruction; fn clause_arg_to_instr(r: RegType) -> Instruction; } impl<'a> CompilationTarget<'a> for FactInstruction { type Iterator = FactIterator<'a>; fn iter(term: &'a Term) -> Self::Iterator { breadth_first_iter(term, RootIterationPolicy::NotIterated) } fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Instruction { Instruction::GetConstant(lvl, HeapCellValue::from(constant), reg) } fn to_structure(lvl: Level, name: Atom, arity: usize, reg: RegType) -> Instruction { Instruction::GetStructure(lvl, name, arity, reg) } fn to_list(lvl: Level, reg: RegType) -> Instruction { Instruction::GetList(lvl, reg) } fn to_void(num_subterms: usize) -> Instruction { Instruction::UnifyVoid(num_subterms) } fn is_void_instr(instr: &Instruction) -> bool { match instr { &Instruction::UnifyVoid(_) => true, _ => false, } } fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Instruction { Instruction::GetPartialString(lvl, string, r, has_tail) } fn incr_void_instr(instr: &mut Instruction) { match instr { &mut Instruction::UnifyVoid(ref mut incr) => *incr += 1, _ => {} } } fn constant_subterm(constant: Literal) -> Instruction { Instruction::UnifyConstant(HeapCellValue::from(constant)) } fn argument_to_variable(arg: RegType, val: usize) -> Instruction { Instruction::GetVariable(arg, val) } fn move_to_register(arg: RegType, val: usize) -> Instruction { Instruction::GetVariable(arg, val) } fn argument_to_value(arg: RegType, val: usize) -> Instruction { Instruction::GetValue(arg, val) } fn unsafe_argument_to_value(arg: RegType, val: usize) -> Instruction { Instruction::GetValue(arg, val) } fn subterm_to_variable(val: RegType) -> Instruction { Instruction::UnifyVariable(val) } fn subterm_to_value(val: RegType) -> Instruction { Instruction::UnifyValue(val) } fn unsafe_subterm_to_value(val: RegType) -> Instruction { Instruction::UnifyLocalValue(val) } fn clause_arg_to_instr(val: RegType) -> Instruction { Instruction::UnifyVariable(val) } } impl<'a> CompilationTarget<'a> for QueryInstruction { type Iterator = QueryIterator<'a>; fn iter(term: &'a Term) -> Self::Iterator { post_order_iter(term) } fn to_structure(_lvl: Level, name: Atom, arity: usize, r: RegType) -> Instruction { Instruction::PutStructure(name, arity, r) } fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Instruction { Instruction::PutConstant(lvl, HeapCellValue::from(constant), reg) } fn to_list(lvl: Level, reg: RegType) -> Instruction { Instruction::PutList(lvl, reg) } fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Instruction { Instruction::PutPartialString(lvl, string, r, has_tail) } fn to_void(subterms: usize) -> Instruction { Instruction::SetVoid(subterms) } fn is_void_instr(instr: &Instruction) -> bool { match instr { &Instruction::SetVoid(_) => true, _ => false, } } fn incr_void_instr(instr: &mut Instruction) { match instr { &mut Instruction::SetVoid(ref mut incr) => *incr += 1, _ => {} } } fn constant_subterm(constant: Literal) -> Instruction { Instruction::SetConstant(HeapCellValue::from(constant)) } fn argument_to_variable(arg: RegType, val: usize) -> Instruction { Instruction::PutVariable(arg, val) } fn move_to_register(arg: RegType, val: usize) -> Instruction { Instruction::GetVariable(arg, val) } fn argument_to_value(arg: RegType, val: usize) -> Instruction { Instruction::PutValue(arg, val) } fn unsafe_argument_to_value(arg: RegType, val: usize) -> Instruction { match arg { RegType::Perm(p) => Instruction::PutUnsafeValue(p, val), RegType::Temp(_) => Instruction::PutValue(arg, val), } } fn subterm_to_variable(val: RegType) -> Instruction { Instruction::SetVariable(val) } fn subterm_to_value(val: RegType) -> Instruction { Instruction::SetValue(val) } fn unsafe_subterm_to_value(val: RegType) -> Instruction { Instruction::SetLocalValue(val) } fn clause_arg_to_instr(val: RegType) -> Instruction { Instruction::SetValue(val) } }