Heya!! This is a long shot, but I figured I'd post here to see if anyone could possibly provide some advice on an FFI integration that I'm currently building and running into some really mind-bending errors.
The repository is here: GitHub - Gopiandcode/clingo-lang: #lang clingo for Racket (WIP)
For context, this package implements a binding to the libclingo ASP solver. The file unsafe.rkt
lists my fairly exhaustive FFI binding for all of the functions from clingo.h
.
The file main.rkt
lists my initial experiments with using the FFI API to make queries from Racket.
The core of my program is:
;; create a context
(define ctrl (clingo-control-new '[] #f #f 20))
(configure-to-enumerate-all-models ctrl)
;; add facts to database
(clingo-control-add ctrl "base" '[] "a :- not b. b :- not a. - a :- b.")
(clingo-control-ground ctrl `[,(make-clingo-part "base" #f 0)] #f #f)
;; ask the solver to solve this database
(define solve-handle (clingo-control-solve ctrl 'clingo-solve-mode-yield '[] #f #f))
;; loop over solutions and print them
(define (loop)
(clingo-solve-handle-resume solve-handle)
(define model (clingo-solve-handle-model solve-handle))
(when model
(print-model model)
(loop)))
(loop)
;; clean up the solver handle
(define solve-result (clingo-solve-handle-get solve-handle))
(println solve-result)
(clingo-solve-handle-close solve-handle)
This actually works pretty well, and I can send queries, and print out the results (using a function from the api to convert solutions to strings) and they match with what I expect.
Inside print-model
, I then started writing some code to translate from clingo's internal representation back to a more racket friendly encoding, via a function symbol->term
, where term
is defined as:
(define term?
(flat-rec-contract term?
(or/c
infinum? ;; #inf
supremum? ;; #sup
number? ;; 1
string? ;; "hello"
symbol? ;; a
(list/c '-
(or/c
symbol?
(cons/c symbol? (listof term?)))) ;; (- a) or (- (f x y))
(cons/c symbol? (listof term?))))) ;; (f x y)
My problem is that my function symbol->term
is not behaving properly, and I'm getting really weird results.
(define/contract (symbol->term sym)
(-> any/c term?)
(define symbol-type (clingo-symbol-type sym))
(match symbol-type
...
['clingo-symbol-type-function
(define is-positive (clingo-symbol-is-positive sym))
(define is-negative (clingo-symbol-is-negative sym))
(define f (string->symbol (clingo-symbol-name sym)))
(define args (map symbol->term (clingo-symbol-arguments sym)))
(define expr (if (null? args) f (cons f args)))
(if is-negative
(list '- expr)
expr)]))
Above I have the relevant snippet from symbol->term; the errors relate to the outputs of the function clingo-symbol-is-negative
, and clingo-symbol-is-positive
, which seem to sometimes return the "wrong" results (sometimes they both return #true
, which is definitely wrong.
I double checked my bindings, and I can't think there's something wrong there:
(define-clingo clingo-symbol-is-positive
(_fun _clingo-symbol (positive : (_ptr o _bool)) -> (res : _bool) ->
(if res positive (raise-clingo-error))))
(define-clingo clingo-symbol-is-negative
(_fun _clingo-symbol (negative : (_ptr o _bool)) -> (res : _bool) ->
(if res negative (raise-clingo-error))))
I've looked at the source of the corresponding functions in the c-code, and they definitely should never return the same results at the very least:
extern "C" bool clingo_symbol_is_negative(clingo_symbol_t val, bool *sign) {
GRINGO_CLINGO_TRY {
clingo_expect(Symbol(val).type() == SymbolType::Fun);
*sign = Symbol(val).sign();
} GRINGO_CLINGO_CATCH;
}
extern "C" bool clingo_symbol_is_positive(clingo_symbol_t val, bool *sign) {
GRINGO_CLINGO_TRY {
clingo_expect(Symbol(val).type() == SymbolType::Fun);
*sign = !Symbol(val).sign();
} GRINGO_CLINGO_CATCH;
}
I assume I've wrapped something wrong, and now am getting some kind of stack corruption , but for the life of me, I don't know where...
Could anyone give some advice as to what I might be doing wrong? or how could I go about debugging this issue?