diff --git a/collects/datalog/parse.rkt b/collects/datalog/parse.rkt index 83e524991d..316ea79bdd 100644 --- a/collects/datalog/parse.rkt +++ b/collects/datalog/parse.rkt @@ -46,6 +46,7 @@ (literal [(predicate-sym LPAREN RPAREN) (make-literal (make-srcloc $1-start-pos $3-end-pos) $1 empty)] [(predicate-sym LPAREN terms RPAREN) (make-literal (make-srcloc $1-start-pos $4-end-pos) $1 $3)] [(predicate-sym) (make-literal (make-srcloc $1-start-pos $1-end-pos) $1 empty)] + [(term NEQUAL term) (make-literal (make-srcloc $1-start-pos $3-end-pos) '!= (list $1 $3))] [(term EQUAL term) (make-literal (make-srcloc $1-start-pos $3-end-pos) '= (list $1 $3))]) (predicate-sym [(IDENTIFIER) (string->symbol $1)] [(STRING) $1]) diff --git a/collects/datalog/private/lex.rkt b/collects/datalog/private/lex.rkt index 58b9f498eb..e2ca602fed 100644 --- a/collects/datalog/private/lex.rkt +++ b/collects/datalog/private/lex.rkt @@ -3,7 +3,7 @@ (prefix-in : parser-tools/lex-sre)) (define-tokens dtokens (VARIABLE IDENTIFIER STRING)) -(define-empty-tokens dpunct (LPAREN COMMA RPAREN TSTILE DOT EQUAL TILDE QMARK EOF)) +(define-empty-tokens dpunct (LPAREN COMMA RPAREN TSTILE DOT EQUAL NEQUAL TILDE QMARK EOF)) (define-lex-abbrev line-break #\newline) (define-lex-abbrev id-chars (char-complement (char-set "(,)=:.~?\"% \n"))) (define-lex-abbrev variable-re (:: upper-case (:* (:or upper-case lower-case (char-set "0123456789_"))))) @@ -38,6 +38,7 @@ [#\~ (token-TILDE)] [#\? (token-QMARK)] [#\= (token-EQUAL)] + ["!=" (token-NEQUAL)] [(eof) (token-EOF)])) (provide dtokens dpunct diff --git a/collects/datalog/runtime.rkt b/collects/datalog/runtime.rkt index 481d1c8786..4bf5b5f679 100644 --- a/collects/datalog/runtime.rkt +++ b/collects/datalog/runtime.rkt @@ -128,6 +128,14 @@ [(unify-term (empty-env) a b) => (lambda (env) (equal-test (subst-term env a) (subst-term env b)))] [else (equal-test a b)])] + [(struct literal (srcloc '!= (list a b))) + (define (equal-test a b) + (unless (term-equal? a b) + (fact! sg (make-literal srcloc '!= (list a b))))) + (cond + [(unify-term (empty-env) a b) + => (lambda (env) (equal-test (subst-term env a) (subst-term env b)))] + [else (equal-test a b)])] [_ (search-theory! sg)])) (define sg (make-subgoal q empty empty)) diff --git a/collects/datalog/scribblings/datalog.scrbl b/collects/datalog/scribblings/datalog.scrbl index 6942712205..79d741441b 100644 --- a/collects/datalog/scribblings/datalog.scrbl +++ b/collects/datalog/scribblings/datalog.scrbl @@ -43,7 +43,7 @@ included in a string. The remaining characters may be specified using escape cha A literal, is a predicate symbol followed by an optional parenthesized list of comma separated terms. A predicate symbol is either an identifier or a string. A term is either a variable or a constant. As with predicate symbols, a constant is either an identifier or a string. As a special case, -two terms separated by @litchar["="] is a literal for the equality predicate. +two terms separated by @litchar["="] (@litchar["!="]) is a literal for the equality (inequality) predicate. The following are literals: @verbatim[#:indent 4 #<