@@ -7,8 +7,6 @@ use crate::debray_allocator::*;
77use crate :: forms:: * ;
88use crate :: instructions:: * ;
99use crate :: iterators:: * ;
10- use crate :: machine:: disjuncts:: * ;
11- use crate :: machine:: stack:: Stack ;
1210use crate :: targets:: QueryInstruction ;
1311use crate :: types:: * ;
1412
@@ -22,6 +20,7 @@ use dashu::base::BitTest;
2220use num_order:: NumOrd ;
2321use ordered_float:: { Float , OrderedFloat } ;
2422
23+ use std:: cell:: Cell ;
2524use std:: cmp:: { max, min, Ordering } ;
2625use std:: convert:: TryFrom ;
2726use std:: f64;
@@ -52,56 +51,127 @@ impl Default for ArithmeticTerm {
5251 }
5352}
5453
54+ #[ derive( Debug ) ]
55+ pub ( crate ) struct ArithInstructionIterator < ' a > {
56+ state_stack : Vec < TermIterState < ' a > > ,
57+ }
58+
5559pub ( crate ) type ArithCont = ( CodeDeque , Option < ArithmeticTerm > ) ;
5660
61+ impl < ' a > ArithInstructionIterator < ' a > {
62+ fn push_subterm ( & mut self , lvl : Level , term : & ' a Term ) {
63+ self . state_stack
64+ . push ( TermIterState :: subterm_to_state ( lvl, term) ) ;
65+ }
66+
67+ fn from ( term : & ' a Term ) -> Result < Self , ArithmeticError > {
68+ let state = match term {
69+ Term :: AnonVar => return Err ( ArithmeticError :: UninstantiatedVar ) ,
70+ Term :: Clause ( cell, name, terms) => {
71+ TermIterState :: Clause ( Level :: Shallow , 0 , cell, * name, terms)
72+ }
73+ Term :: Literal ( cell, cons) => TermIterState :: Literal ( Level :: Shallow , cell, cons) ,
74+ Term :: Cons ( ..) | Term :: PartialString ( ..) | Term :: CompleteString ( ..) => {
75+ return Err ( ArithmeticError :: NonEvaluableFunctor (
76+ Literal :: Atom ( atom ! ( "." ) ) ,
77+ 2 ,
78+ ) )
79+ }
80+ Term :: Var ( cell, var_ptr) => TermIterState :: Var ( Level :: Shallow , cell, var_ptr. clone ( ) ) ,
81+ } ;
82+
83+ Ok ( ArithInstructionIterator {
84+ state_stack : vec ! [ state] ,
85+ } )
86+ }
87+ }
88+
89+ #[ derive( Debug ) ]
90+ pub ( crate ) enum ArithTermRef < ' a > {
91+ Literal ( Literal ) ,
92+ Op ( Atom , usize ) , // name, arity.
93+ Var ( Level , & ' a Cell < VarReg > , VarPtr ) ,
94+ }
95+
96+ impl < ' a > Iterator for ArithInstructionIterator < ' a > {
97+ type Item = Result < ArithTermRef < ' a > , ArithmeticError > ;
98+
99+ fn next ( & mut self ) -> Option < Self :: Item > {
100+ while let Some ( iter_state) = self . state_stack . pop ( ) {
101+ match iter_state {
102+ TermIterState :: AnonVar ( _) => return Some ( Err ( ArithmeticError :: UninstantiatedVar ) ) ,
103+ TermIterState :: Clause ( lvl, child_num, cell, name, subterms) => {
104+ let arity = subterms. len ( ) ;
105+
106+ if child_num == arity {
107+ return Some ( Ok ( ArithTermRef :: Op ( name, arity) ) ) ;
108+ } else {
109+ self . state_stack . push ( TermIterState :: Clause (
110+ lvl,
111+ child_num + 1 ,
112+ cell,
113+ name,
114+ subterms,
115+ ) ) ;
116+
117+ self . push_subterm ( lvl. child_level ( ) , & subterms[ child_num] ) ;
118+ }
119+ }
120+ TermIterState :: Literal ( _, _, c) => return Some ( Ok ( ArithTermRef :: Literal ( * c) ) ) ,
121+ TermIterState :: Var ( lvl, cell, var_ptr) => {
122+ return Some ( Ok ( ArithTermRef :: Var ( lvl, cell, var_ptr) ) ) ;
123+ }
124+ _ => {
125+ return Some ( Err ( ArithmeticError :: NonEvaluableFunctor (
126+ Literal :: Atom ( atom ! ( "." ) ) ,
127+ 2 ,
128+ ) ) ) ;
129+ }
130+ } ;
131+ }
132+
133+ None
134+ }
135+ }
136+
57137#[ derive( Debug ) ]
58138pub ( crate ) struct ArithmeticEvaluator < ' a > {
59139 marker : & ' a mut DebrayAllocator ,
60140 interm : Vec < ArithmeticTerm > ,
61141 interm_c : usize ,
62142}
63143
64- fn push_literal ( interm : & mut Vec < ArithmeticTerm > , c : HeapCellValue ) -> Result < ( ) , ArithmeticError > {
65- let c = unmark_cell_bits ! ( c ) ;
144+ pub ( crate ) trait ArithmeticTermIter < ' a > {
145+ type Iter : Iterator < Item = Result < ArithTermRef < ' a > , ArithmeticError > > ;
66146
67- read_heap_cell ! ( c,
68- ( HeapCellValueTag :: Fixnum , n) => {
69- interm. push( ArithmeticTerm :: Number ( Number :: Fixnum ( n) ) )
70- }
71- ( HeapCellValueTag :: Cons , cons_ptr) => {
72- match_untyped_arena_ptr!( cons_ptr,
73- ( ArenaHeaderTag :: Integer , n) => {
74- interm. push( ArithmeticTerm :: Number ( Number :: Integer ( n) ) ) ;
75- }
76- ( ArenaHeaderTag :: Rational , n) => {
77- interm. push( ArithmeticTerm :: Number ( Number :: Rational ( n) ) ) ;
78- }
79- _ => return Err ( ArithmeticError :: NonEvaluableFunctor ( c, 0 ) ) ,
80- ) ;
81- }
82- ( HeapCellValueTag :: Atom , ( name, arity) ) => {
83- debug_assert_eq!( arity, 0 ) ;
84-
85- match name {
86- atom!( "pi" ) => interm. push( ArithmeticTerm :: Number (
87- Number :: Float ( OrderedFloat ( std:: f64 :: consts:: PI ) ) ,
88- ) ) ,
89- atom!( "epsilon" ) => interm. push( ArithmeticTerm :: Number (
90- Number :: Float ( OrderedFloat ( std:: f64 :: EPSILON ) ) ,
91- ) ) ,
92- atom!( "e" ) => interm. push( ArithmeticTerm :: Number (
93- Number :: Float ( OrderedFloat ( std:: f64 :: consts:: E ) ) ,
94- ) ) ,
95- _ => unreachable!( ) ,
96- }
97- }
98- ( HeapCellValueTag :: F64 , n) => {
99- interm. push( ArithmeticTerm :: Number ( Number :: Float ( * n) ) ) ;
100- }
101- _ => {
102- return Err ( ArithmeticError :: NonEvaluableFunctor ( c, 0 ) ) ;
103- }
104- ) ;
147+ fn iter ( self ) -> Result < Self :: Iter , ArithmeticError > ;
148+ }
149+
150+ impl < ' a > ArithmeticTermIter < ' a > for & ' a Term {
151+ type Iter = ArithInstructionIterator < ' a > ;
152+
153+ fn iter ( self ) -> Result < Self :: Iter , ArithmeticError > {
154+ ArithInstructionIterator :: from ( self )
155+ }
156+ }
157+
158+ fn push_literal ( interm : & mut Vec < ArithmeticTerm > , c : & Literal ) -> Result < ( ) , ArithmeticError > {
159+ match c {
160+ Literal :: Fixnum ( n) => interm. push ( ArithmeticTerm :: Number ( Number :: Fixnum ( * n) ) ) ,
161+ Literal :: Integer ( n) => interm. push ( ArithmeticTerm :: Number ( Number :: Integer ( * n) ) ) ,
162+ Literal :: Float ( n) => interm. push ( ArithmeticTerm :: Number ( Number :: Float ( * n. as_ptr ( ) ) ) ) ,
163+ Literal :: Rational ( n) => interm. push ( ArithmeticTerm :: Number ( Number :: Rational ( * n) ) ) ,
164+ Literal :: Atom ( name) if name == & atom ! ( "e" ) => interm. push ( ArithmeticTerm :: Number (
165+ Number :: Float ( OrderedFloat ( std:: f64:: consts:: E ) ) ,
166+ ) ) ,
167+ Literal :: Atom ( name) if name == & atom ! ( "pi" ) => interm. push ( ArithmeticTerm :: Number (
168+ Number :: Float ( OrderedFloat ( std:: f64:: consts:: PI ) ) ,
169+ ) ) ,
170+ Literal :: Atom ( name) if name == & atom ! ( "epsilon" ) => interm. push ( ArithmeticTerm :: Number (
171+ Number :: Float ( OrderedFloat ( f64:: EPSILON ) ) ,
172+ ) ) ,
173+ _ => return Err ( ArithmeticError :: NonEvaluableFunctor ( * c, 0 ) ) ,
174+ }
105175
106176 Ok ( ( ) )
107177}
@@ -143,7 +213,7 @@ impl<'a> ArithmeticEvaluator<'a> {
143213 atom ! ( "float_fractional_part" ) => Ok ( Instruction :: FloatFractionalPart ( a1, t) ) ,
144214 atom ! ( "sign" ) => Ok ( Instruction :: Sign ( a1, t) ) ,
145215 atom ! ( "\\ " ) => Ok ( Instruction :: BitwiseComplement ( a1, t) ) ,
146- _ => Err ( ArithmeticError :: NonEvaluableFunctor ( atom_as_cell ! ( name) , 1 ) ) ,
216+ _ => Err ( ArithmeticError :: NonEvaluableFunctor ( Literal :: Atom ( name) , 1 ) ) ,
147217 }
148218 }
149219
@@ -175,7 +245,7 @@ impl<'a> ArithmeticEvaluator<'a> {
175245 atom ! ( "rem" ) => Ok ( Instruction :: Rem ( a1, a2, t) ) ,
176246 atom ! ( "gcd" ) => Ok ( Instruction :: Gcd ( a1, a2, t) ) ,
177247 atom ! ( "atan2" ) => Ok ( Instruction :: ATan2 ( a1, a2, t) ) ,
178- _ => Err ( ArithmeticError :: NonEvaluableFunctor ( atom_as_cell ! ( name) , 2 ) ) ,
248+ _ => Err ( ArithmeticError :: NonEvaluableFunctor ( Literal :: Atom ( name) , 2 ) ) ,
179249 }
180250 }
181251
@@ -231,70 +301,52 @@ impl<'a> ArithmeticEvaluator<'a> {
231301 self . get_binary_instr ( name, a1, a2, ninterm)
232302 }
233303 _ => Err ( ArithmeticError :: NonEvaluableFunctor (
234- atom_as_cell ! ( name) ,
304+ Literal :: Atom ( name) ,
235305 arity,
236306 ) ) ,
237307 }
238308 }
239309
240310 pub ( crate ) fn compile_is (
241311 & mut self ,
242- src : & mut FocusedHeapRefMut ,
243- term_loc : usize ,
244- context : GenContext ,
312+ src : & ' a Term ,
313+ term_loc : GenContext ,
245314 arg : usize ,
246315 ) -> Result < ArithCont , ArithmeticError > {
247316 let mut code = CodeDeque :: new ( ) ;
248- let mut stack = Stack :: uninitialized ( ) ;
249- let mut iter = query_iterator :: < false > ( & mut src. heap , & mut stack, term_loc) ;
250-
251- let chunk_num = context. chunk_num ( ) ;
252-
253- while let Some ( term) = iter. next ( ) {
254- read_heap_cell ! ( term,
255- ( HeapCellValueTag :: AttrVar | HeapCellValueTag :: Var , term_loc) => {
256- let lvl = iter. level( ) ;
257-
258- let r = match self . marker. var_data. var_locs_to_nums. get( VarPtrIndex { chunk_num, term_loc } ) {
259- VarPtr :: Numbered ( var_num) => {
260- let old_r = self . marker. get_var_binding( var_num) ;
261-
262- if lvl == Level :: Root {
263- self . marker. mark_non_callable( var_num, arg, context, & mut code)
264- } else if context. is_last( ) || old_r. reg_num( ) == 0 {
265- let r = old_r;
266-
267- if r. reg_num( ) == 0 {
268- self . marker. mark_var:: <QueryInstruction >(
269- var_num, lvl, context, & mut code,
270- )
271- } else {
272- self . marker. increment_running_count( var_num) ;
273- r
274- }
275- } else {
276- self . marker. increment_running_count( var_num) ;
277- old_r
278- }
279- }
280- VarPtr :: Anon => {
281- self . marker. mark_anon_var:: <QueryInstruction >( lvl, context, & mut code)
317+
318+ for term_ref in src. iter ( ) ? {
319+ match term_ref? {
320+ ArithTermRef :: Literal ( c) => push_literal ( & mut self . interm , & c) ?,
321+ ArithTermRef :: Var ( lvl, cell, name) => {
322+ let var_num = name. to_var_num ( ) . unwrap ( ) ;
323+
324+ let r = if lvl == Level :: Shallow {
325+ self . marker
326+ . mark_non_callable ( var_num, arg, term_loc, cell, & mut code)
327+ } else if term_loc. is_last ( ) || cell. get ( ) . norm ( ) . reg_num ( ) == 0 {
328+ let r = self . marker . get_binding ( var_num) ;
329+
330+ if r. reg_num ( ) == 0 {
331+ self . marker . mark_var :: < QueryInstruction > (
332+ var_num, lvl, cell, term_loc, & mut code,
333+ ) ;
334+ cell. get ( ) . norm ( )
335+ } else {
336+ self . marker . increment_running_count ( var_num) ;
337+ r
282338 }
339+ } else {
340+ self . marker . increment_running_count ( var_num) ;
341+ cell. get ( ) . norm ( )
283342 } ;
284343
285344 self . interm . push ( ArithmeticTerm :: Reg ( r) ) ;
286345 }
287- ( HeapCellValueTag :: Atom , ( name, arity) ) => {
288- if arity == 0 {
289- push_literal( & mut self . interm, atom_as_cell!( name) ) ?;
290- } else {
291- code. push_back( self . instr_from_clause( name, arity) ?) ;
292- }
293- }
294- _ => {
295- push_literal( & mut self . interm, term) ?;
346+ ArithTermRef :: Op ( name, arity) => {
347+ code. push_back ( self . instr_from_clause ( name, arity) ?) ;
296348 }
297- ) ;
349+ }
298350 }
299351
300352 Ok ( ( code, self . interm . pop ( ) ) )
0 commit comments