awalterschulze / gominikanren

a Go implementation of miniKanren, an embedded Domain Specific Language for logic programming.
Other
38 stars 2 forks source link

very recursive breaks #2

Closed awalterschulze closed 4 years ago

awalterschulze commented 6 years ago
(defrel (very-recursiveo)
  (conde
    ((nevero))
    ((very-recursiveo))
    ((alwayso))
    ((very-recursiveo))
    ((nevero))))

This causes an infinite loop and a stack overflow

func VeryRecursiveO() micro.Goal {
    return Conde(
        micro.NeverO(),
        VeryRecursiveO(),
        micro.AlwaysO(),
        VeryRecursiveO(),
        micro.NeverO(),
    )
}

And this also creates a stack overflow, but in djsjointo

func VeryRecursiveO() micro.Goal {
    return Conde(
        micro.NeverO(),
        func(s *micro.State) micro.StreamOfStates {
            return VeryRecursiveO()(s)
        },
        micro.AlwaysO(),
        func(s *micro.State) micro.StreamOfStates {
            return VeryRecursiveO()(s)
        },
        micro.NeverO(),
    )
}

Here is a test to run it

func TestRecursive(t *testing.T) {
    micro.RunGoal(
        1,
        micro.CallFresh(func(q *ast.SExpr) micro.Goal {
            return VeryRecursiveO()
        }),
    )
}

And here is conde, which is probably incorrect

/*
scheme code:

    (define-syntax conde
        (syntax-rules () (
            (conde (g ...) ...)
            (disj (conj g ...) ...)
        ))
    )
*/
func Conde(gs ...micro.Goal) micro.Goal {
    if len(gs) == 0 {
        return micro.DisjointO(micro.ConjunctionO(gs...))
    }
    goals := make([]micro.Goal, len(gs))
    copy(goals, gs)
    goals[0] = micro.ConjunctionO(gs...)
    return micro.DisjointO(goals...)
}