Demonstrate Racket/Datalog interop more and add unsyntax

This commit is contained in:
Jay McCarthy 2014-04-16 12:58:59 -06:00
parent d6a3d27e54
commit 744fde1fa8
4 changed files with 94 additions and 31 deletions

View File

@ -99,7 +99,7 @@
[terms (listof term/c)])] [terms (listof term/c)])]
[literal-equal? (literal? literal? . -> . boolean?)] [literal-equal? (literal? literal? . -> . boolean?)]
[struct external ([srcloc srcloc/c] [struct external ([srcloc srcloc/c]
[predicate-sym symbol?] [predicate-sym any/c]
[predicate procedure?] [predicate procedure?]
[arg-terms (listof term/c)] [arg-terms (listof term/c)]
[ans-terms (listof term/c)])] [ans-terms (listof term/c)])]

View File

@ -15,6 +15,7 @@
The Datalog database can be directly used by Racket programs through this API. The Datalog database can be directly used by Racket programs through this API.
@examples[#:eval the-eval @examples[#:eval the-eval
#:escape UNSYNTAX-NOT
(define family (make-theory)) (define family (make-theory))
(datalog family (datalog family
@ -25,6 +26,17 @@ The Datalog database can be directly used by Racket programs through this API.
(datalog family (datalog family
(? (parent X joseph2))) (? (parent X joseph2)))
(datalog family
(? (parent X (string->symbol "joseph2"))))
(let ([atom 'joseph2])
(datalog family
(? (parent X #,atom))))
(let ([table 'parent])
(datalog family
(? (#,table X joseph2))))
(datalog family (datalog family
(? (parent joseph2 X))) (? (parent joseph2 X)))
@ -48,7 +60,9 @@ The Datalog database can be directly used by Racket programs through this API.
(? (parent x X)))) (? (parent x X))))
(datalog family (datalog family
(? (add1 1 :- X)))] (? (add1 1 :- X)))
(datalog family
(? (#,(λ (x) (+ x 1)) 1 :- X)))]
@defthing[theory/c contract?]{ A contract for Datalog theories. } @defthing[theory/c contract?]{ A contract for Datalog theories. }
@ -75,9 +89,23 @@ Statements are either assertions, retractions, or queries.
@defform[(? question)]{ Queries the literal and prints the result literals. } @defform[(? question)]{ Queries the literal and prints the result literals. }
Questions are either literals or external queries. Questions are either literals or external queries.
Literals are represented as @racket[identifier] or @racket[(identifier term ...)].
External queries are represented as @racket[(identifier term ... :- term ...)], where @racket[identifier] is bound to a procedure that when given the first set of terms as arguments returns the second set of terms as values. Literals are represented as @racket[identifier] or @racket[(table term ...)].
A term is either a non-capitalized identifiers for a constant symbol, a Racket datum for a constant datum, or a capitalized identifier for a variable symbol. Bound identifiers in terms are treated as datums.
A table is either an identifier or @RACKET[#,expr] where @racket[expr]
evaluates to a symbol.
External queries are represented as @racket[(ext-table term ... :-
term ...)], where @racket[ext-table] is an identifier bound to a
procedure or @RACKET[#,expr] where @racket[expr] evaluates to a
procedure that when given the first set of terms as arguments returns
the second set of terms as values.
A term is either a non-capitalized identifiers for a constant symbol,
a Racket expression for a constant datum, or a capitalized identifier
for a variable symbol, or @RACKET[#,expr] where @racket[expr]
evaluates to a constant datum. Bound identifiers in terms are treated
as the datum they are bound to.
External queries invalidate Datalog's guaranteed termination. For example, this program does not terminate: External queries invalidate Datalog's guaranteed termination. For example, this program does not terminate:
@racketblock[ @racketblock[

View File

@ -139,44 +139,53 @@
(define-syntax (datalog-literal/bind stx) (datalog-literal/b stx #t)) (define-syntax (datalog-literal/bind stx) (datalog-literal/b stx #t))
(define-syntax (datalog-literal/ref stx) (datalog-literal/b stx #f)) (define-syntax (datalog-literal/ref stx) (datalog-literal/b stx #f))
(define-for-syntax (datalog-literal/b stx binding?) (begin-for-syntax
(syntax-parse (define-syntax-class table-id
stx #:literals (unsyntax)
#:literals (:-) (pattern sym:id
[(_ sym:id) #:attr ref #''sym
(syntax-property #:attr val #'sym)
(quasisyntax/loc #'sym (pattern (unsyntax sym:expr)
(literal #,(srcloc-list #'sym) 'sym empty)) #:attr ref #'sym
(if binding? 'disappeared-binding 'disappeared-use) #:attr val #'sym))
(syntax-local-introduce #'sym))] (define (datalog-literal/b stx binding?)
[(_ (~and tstx (sym:id arg ... :- ans ...))) (syntax-parse
(quasisyntax/loc #'tstx stx
(external #,(srcloc-list #'tstx) 'sym sym #:literals (:-)
(list (datalog-term arg) ...) [(_ sym:table-id)
(list (datalog-term ans) ...)))] (syntax-property
[(_ (~and tstx (sym:id e ...))) (quasisyntax/loc #'sym
(syntax-property (literal #,(srcloc-list #'sym) sym.ref empty))
(quasisyntax/loc #'tstx (if binding? 'disappeared-binding 'disappeared-use)
(literal #,(srcloc-list #'tstx) 'sym (syntax-local-introduce #'sym))]
(list (datalog-term e) [(_ (~and tstx (sym:table-id arg ... :- ans ...)))
...))) (quasisyntax/loc #'tstx
(if binding? 'disappeared-binding 'disappeared-use) (external #,(srcloc-list #'tstx) 'sym sym.val
(syntax-local-introduce #'sym))])) (list (datalog-term arg) ...)
(list (datalog-term ans) ...)))]
[(_ (~and tstx (sym:table-id e ...)))
(syntax-property
(quasisyntax/loc #'tstx
(literal #,(srcloc-list #'tstx) sym.ref
(list (datalog-term e)
...)))
(if binding? 'disappeared-binding 'disappeared-use)
(syntax-local-introduce #'sym))])))
(define-syntax (datalog-literal-var-selector stx) (define-syntax (datalog-literal-var-selector stx)
(syntax-parse (syntax-parse
stx stx
#:literals (:-) #:literals (:-)
[(_ sym:id) [(_ sym:table-id)
(quasisyntax/loc #'sym (λ (l) (hasheq)))] (quasisyntax/loc #'sym (λ (l) (hasheq)))]
[(_ (~and tstx (sym:id arg ... :- ans ...))) [(_ (~and tstx (sym:table-id arg ... :- ans ...)))
(quasisyntax/loc #'tstx (quasisyntax/loc #'tstx
(match-lambda (match-lambda
[(external _srcloc _predsym _pred args anss) [(external _srcloc _predsym _pred args anss)
(terms->hasheq (list (datalog-term arg) ... (terms->hasheq (list (datalog-term arg) ...
(datalog-term ans) ...) (datalog-term ans) ...)
(append args anss))]))] (append args anss))]))]
[(_ (~and tstx (sym:id e ...))) [(_ (~and tstx (sym:table-id e ...)))
(quasisyntax/loc #'tstx (quasisyntax/loc #'tstx
(match-lambda (match-lambda
[(literal _srcloc _predsym ts) [(literal _srcloc _predsym ts)
@ -194,6 +203,7 @@
(define-syntax (datalog-term stx) (define-syntax (datalog-term stx)
(syntax-parse (syntax-parse
stx stx
#:literals (unsyntax)
[(_ sym:id) [(_ sym:id)
(cond (cond
[(identifier-binding #'sym 0) [(identifier-binding #'sym 0)
@ -205,6 +215,9 @@
[else [else
(quasisyntax/loc #'sym (quasisyntax/loc #'sym
(constant #,(srcloc-list #'sym) 'sym))])] (constant #,(srcloc-list #'sym) 'sym))])]
[(_ (unsyntax sym:expr))
(quasisyntax/loc #'sym
(constant #,(srcloc-list #'sym) sym))]
[(_ sym:expr) [(_ sym:expr)
(quasisyntax/loc #'sym (quasisyntax/loc #'sym
(constant #,(srcloc-list #'sym) sym))])) (constant #,(srcloc-list #'sym) sym))]))

View File

@ -15,6 +15,23 @@
(? (parent X joseph2))) (? (parent X joseph2)))
=> =>
(list (hasheq 'X 'joseph3)) (list (hasheq 'X 'joseph3))
(datalog parent
(? (parent X (string->symbol "joseph2"))))
=>
(list (hasheq 'X 'joseph3))
(let ([atom 'joseph2])
(datalog parent
(? (parent X #,atom))))
=>
(list (hasheq 'X 'joseph3))
(let ([table 'parent])
(datalog parent
(? (#,table X joseph2))))
=>
(list (hasheq 'X 'joseph3))
(datalog parent (datalog parent
(? (parent joseph2 X))) (? (parent joseph2 X)))
@ -58,6 +75,11 @@
(? (add1 1 :- X))) (? (add1 1 :- X)))
=> =>
(list (hasheq 'X 2)) (list (hasheq 'X 2))
(datalog parent
(? (#,(λ (x) (+ x 1)) 1 :- X)))
=>
(list (hasheq 'X 2))
(let () (let ()
(define new-parent (define new-parent