1
+ use std:: cell:: Cell ;
1
2
use std:: cmp:: Ordering ;
2
3
use std:: collections:: BTreeMap ;
3
4
@@ -8,13 +9,14 @@ use crate::machine::mock_wam::CompositeOpDir;
8
9
use crate :: machine:: {
9
10
F64Offset , F64Ptr , Fixnum , Number , BREAK_FROM_DISPATCH_LOOP_LOC , LIB_QUERY_SUCCESS ,
10
11
} ;
11
- use crate :: parser:: ast:: { Var , VarPtr } ;
12
+ use crate :: parser:: ast:: { Literal , Term as AstTerm , Var , VarPtr } ;
12
13
use crate :: parser:: parser:: { Parser , Tokens } ;
13
14
use crate :: read:: { write_term_to_heap, TermWriteResult } ;
14
15
15
16
use dashu:: { Integer , Rational } ;
16
17
use indexmap:: IndexMap ;
17
18
19
+ use super :: AtomTable ;
18
20
use super :: { streams:: Stream , Atom , AtomCell , HeapCellValue , HeapCellValueTag , Machine } ;
19
21
20
22
#[ cfg( test) ]
@@ -401,6 +403,47 @@ impl Term {
401
403
debug_assert_eq ! ( term_stack. len( ) , 1 ) ;
402
404
term_stack. pop ( ) . unwrap ( )
403
405
}
406
+
407
+ pub ( crate ) fn into_ast_term ( self , machine : & mut Machine ) -> AstTerm {
408
+ match self {
409
+ Term :: Integer ( i) => AstTerm :: Literal (
410
+ Cell :: default ( ) ,
411
+ Literal :: Integer ( arena_alloc ! ( i, & mut machine. machine_st. arena) ) ,
412
+ ) ,
413
+ Term :: Rational ( r) => AstTerm :: Literal (
414
+ Cell :: default ( ) ,
415
+ Literal :: Rational ( arena_alloc ! ( r, & mut machine. machine_st. arena) ) ,
416
+ ) ,
417
+ Term :: Float ( f) => AstTerm :: Literal (
418
+ Cell :: default ( ) ,
419
+ Literal :: Float ( float_alloc ! ( f, & mut machine. machine_st. arena) . as_offset ( ) ) ,
420
+ ) ,
421
+ Term :: Atom ( a) => AstTerm :: Literal (
422
+ Cell :: default ( ) ,
423
+ Literal :: Atom ( AtomTable :: build_with ( & machine. machine_st . atom_tbl , & a) ) ,
424
+ ) ,
425
+ Term :: String ( s) => AstTerm :: Literal (
426
+ Cell :: default ( ) ,
427
+ Literal :: String ( AtomTable :: build_with ( & machine. machine_st . atom_tbl , & s) ) ,
428
+ ) ,
429
+ Term :: List ( l) => l. iter ( ) . rev ( ) . fold (
430
+ AstTerm :: Literal ( Cell :: default ( ) , Literal :: Atom ( atom ! ( "[]" ) ) ) ,
431
+ |tail, head| {
432
+ AstTerm :: Cons (
433
+ Cell :: default ( ) ,
434
+ Box :: new ( head. clone ( ) . into_ast_term ( machine) ) ,
435
+ Box :: new ( tail) ,
436
+ )
437
+ } ,
438
+ ) ,
439
+ Term :: Compound ( f, args) => AstTerm :: Clause (
440
+ Cell :: default ( ) ,
441
+ AtomTable :: build_with ( & machine. machine_st . atom_tbl , & f) ,
442
+ args. into_iter ( ) . map ( |x| x. into_ast_term ( machine) ) . collect ( ) ,
443
+ ) ,
444
+ Term :: Var ( v) => AstTerm :: Var ( Cell :: default ( ) , VarPtr :: from ( v) ) ,
445
+ }
446
+ }
404
447
}
405
448
406
449
/// An iterator though the leaf answers of a query.
@@ -525,6 +568,42 @@ impl Iterator for QueryState<'_> {
525
568
}
526
569
}
527
570
571
+ enum QueryInfoInner {
572
+ String ( String ) ,
573
+ Term ( Term ) ,
574
+ }
575
+
576
+ /// Information for a query used inside `[Machine::run_query]`.
577
+ ///
578
+ /// See `[IntoQuery]` trait.
579
+ pub struct QueryInfo {
580
+ inner : QueryInfoInner ,
581
+ }
582
+
583
+ /// Something that can be used as a query.
584
+ ///
585
+ /// See `[Machine::run_query]`.
586
+ pub trait IntoQuery {
587
+ /// Convert to a query.
588
+ fn into_query ( self ) -> QueryInfo ;
589
+ }
590
+
591
+ impl < T : Into < String > > IntoQuery for T {
592
+ fn into_query ( self ) -> QueryInfo {
593
+ QueryInfo {
594
+ inner : QueryInfoInner :: String ( self . into ( ) ) ,
595
+ }
596
+ }
597
+ }
598
+
599
+ impl IntoQuery for Term {
600
+ fn into_query ( self ) -> QueryInfo {
601
+ QueryInfo {
602
+ inner : QueryInfoInner :: Term ( self ) ,
603
+ }
604
+ }
605
+ }
606
+
528
607
impl Machine {
529
608
/// Loads a module into the [`Machine`] from a string.
530
609
pub fn load_module_string ( & mut self , module_name : & str , program : impl Into < String > ) {
@@ -569,22 +648,31 @@ impl Machine {
569
648
}
570
649
571
650
/// Runs a query.
572
- pub fn run_query ( & mut self , query : impl Into < String > ) -> QueryState {
573
- let mut parser = Parser :: new (
574
- Stream :: from_owned_string ( query. into ( ) , & mut self . machine_st . arena ) ,
575
- & mut self . machine_st ,
576
- ) ;
577
- let op_dir = CompositeOpDir :: new ( & self . indices . op_dir , None ) ;
578
- let term = parser
579
- . read_term ( & op_dir, Tokens :: Default )
580
- . expect ( "Failed to parse query" ) ;
651
+ pub fn run_query ( & mut self , query : impl IntoQuery ) -> QueryState {
652
+ let ast_term = match query. into_query ( ) . inner {
653
+ QueryInfoInner :: String ( query_string) => {
654
+ let mut parser = Parser :: new (
655
+ Stream :: from_owned_string ( query_string, & mut self . machine_st . arena ) ,
656
+ & mut self . machine_st ,
657
+ ) ;
658
+ let op_dir = CompositeOpDir :: new ( & self . indices . op_dir , None ) ;
659
+
660
+ parser
661
+ . read_term ( & op_dir, Tokens :: Default )
662
+ . expect ( "Failed to parse query" )
663
+ }
664
+ QueryInfoInner :: Term ( query_term) => query_term. into_ast_term ( self ) ,
665
+ } ;
581
666
582
667
self . allocate_stub_choice_point ( ) ;
583
668
584
669
// Write parsed term to heap
585
- let term_write_result =
586
- write_term_to_heap ( & term, & mut self . machine_st . heap , & self . machine_st . atom_tbl )
587
- . expect ( "couldn't write term to heap" ) ;
670
+ let term_write_result = write_term_to_heap (
671
+ & ast_term,
672
+ & mut self . machine_st . heap ,
673
+ & self . machine_st . atom_tbl ,
674
+ )
675
+ . expect ( "couldn't write term to heap" ) ;
588
676
589
677
let var_names: IndexMap < _ , _ > = term_write_result
590
678
. var_dict
0 commit comments