This commit is contained in:
Tibo De Peuter 2025-05-07 20:22:14 +02:00
parent dff53b4e68
commit 65c4d925d3
Signed by: tdpeuter
GPG key ID: 38297DE43F75FFE2
15 changed files with 270 additions and 83 deletions

View file

@ -0,0 +1,91 @@
package prolog.builtins
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertInstanceOf
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import prolog.ast.arithmetic.Integer
import prolog.ast.terms.AnonymousVariable
import prolog.ast.terms.Atom
import prolog.ast.terms.Structure
import prolog.ast.terms.Variable
class AnalysingAndConstructionOperatorsTests {
@Test
fun `functor(foo, foo, 0)`() {
val functor = Functor(Atom("foo"), Atom("foo"), Integer(0))
val result = functor.satisfy(emptyMap()).toList()
assertEquals(1, result.size, "Expected 1 result")
assertTrue(result[0].isSuccess, "Expected success")
assertTrue(result[0].getOrNull()!!.isEmpty(), "Expected empty substitutions")
}
@Test
fun `functor(foo(X), foo, Y)`() {
val functor = Functor(
Structure(Atom("foo"), listOf(Variable("X"))),
Atom("foo"),
Variable("Y")
)
val result = functor.satisfy(emptyMap()).toList()
assertEquals(1, result.size, "Expected 1 result")
assertTrue(result[0].isSuccess, "Expected success")
val subs = result[0].getOrNull()!!
assertEquals(1, subs.size, "Expected 1 substitution")
assertEquals(Integer(1), subs[Variable("Y")])
}
@Test
fun `functor(foo, X, Y)`() {
val atom = Atom("foo")
val functor = Functor(atom, Variable("X"), Variable("Y"))
val result = functor.satisfy(emptyMap()).toList()
assertEquals(1, result.size, "Expected 1 result")
assertTrue(result[0].isSuccess, "Expected success")
val subs = result[0].getOrNull()!!
assertEquals(2, subs.size, "Expected 2 substitutions")
assertEquals(atom.functor.name, subs[Variable("X")])
assertEquals(atom.functor.arity, subs[Variable("Y")])
}
@Test
fun `functor(X, foo, 1)`() {
val functor = Functor(Variable("X"), Atom("foo"), Integer(1))
val result = functor.satisfy(emptyMap()).toList()
assertEquals(1, result.size, "Expected 1 result")
assertTrue(result[0].isSuccess, "Expected success")
val subs = result[0].getOrNull()!!
assertEquals(1, subs.size, "Expected 1 substitution")
assertInstanceOf(Structure::class.java, subs[Variable("X")])
val structure = subs[Variable("X")] as Structure
assertEquals(Atom("foo"), structure.name)
assertEquals(1, structure.arguments.size)
assertInstanceOf(AnonymousVariable::class.java, structure.arguments[0])
}
@Test
fun `functor(foo(a), foo, 0)`() {
val functor = Functor(Structure(Atom("foo"), listOf(Atom("a"))), Atom("foo"), Integer(0))
val result = functor.satisfy(emptyMap()).toList()
assertTrue(result.isEmpty(), "Expected no results")
}
@Test
fun `functor(foo(X), foo, 0)`() {
val functor = Functor(Structure(Atom("foo"), listOf(Variable("X"))), Atom("foo"), Integer(0))
val result = functor.satisfy(emptyMap()).toList()
assertTrue(result.isEmpty(), "Expected no results")
}
}

View file

@ -8,14 +8,13 @@ import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
import prolog.ast.Database
import prolog.ast.Database.Program
import prolog.ast.logic.Clause
import prolog.ast.logic.Fact
import prolog.ast.logic.Predicate
import prolog.ast.logic.Rule
import prolog.ast.terms.Atom
import prolog.ast.terms.Functor
import prolog.ast.terms.FunctorInfo
import prolog.ast.terms.Structure
import prolog.ast.terms.Variable
@ -40,7 +39,7 @@ class DatabaseOperatorsTests {
createAssert(fact).satisfy(emptyMap())
assertEquals(1, Program.db.predicates.size, "Expected 1 predicate")
assertEquals(fact, Program.db.predicates["a/_"]!!.clauses[0])
assertEquals(fact, Program.db.predicates[FunctorInfo.of("a/_")]!!.clauses[0])
}
@Test
@ -49,7 +48,7 @@ class DatabaseOperatorsTests {
createAssert(fact).satisfy(emptyMap())
assertEquals(1, Program.db.predicates.size, "Expected 1 predicate")
assertEquals(fact, Program.db.predicates["a/1"]!!.clauses[0])
assertEquals(fact, Program.db.predicates[FunctorInfo.of("a/1")]!!.clauses[0])
}
@Test
@ -61,7 +60,7 @@ class DatabaseOperatorsTests {
createAssert(rule).satisfy(emptyMap())
assertEquals(1, Program.db.predicates.size, "Expected 1 predicate")
assertEquals(rule, Program.db.predicates["a/1"]!!.clauses[0])
assertEquals(rule, Program.db.predicates[FunctorInfo.of("a/1")]!!.clauses[0])
}
}
@ -92,8 +91,8 @@ class DatabaseOperatorsTests {
AssertA(rule2).satisfy(emptyMap())
assertEquals(1, Program.db.predicates.size, "Expected 1 predicate")
assertEquals(rule2, Program.db.predicates["a/1"]!!.clauses[0])
assertEquals(rule1, Program.db.predicates["a/1"]!!.clauses[1])
assertEquals(rule2, Program.db.predicates[FunctorInfo.of("a/1")]!!.clauses[0])
assertEquals(rule1, Program.db.predicates[FunctorInfo.of("a/1")]!!.clauses[1])
}
}
@ -117,8 +116,8 @@ class DatabaseOperatorsTests {
AssertZ(rule2).satisfy(emptyMap())
assertEquals(1, Program.db.predicates.size, "Expected 1 predicate")
assertEquals(rule1, Program.db.predicates["a/1"]!!.clauses[0])
assertEquals(rule2, Program.db.predicates["a/1"]!!.clauses[1])
assertEquals(rule1, Program.db.predicates[FunctorInfo.of("a/1")]!!.clauses[0])
assertEquals(rule2, Program.db.predicates[FunctorInfo.of("a/1")]!!.clauses[1])
}
}
@ -309,20 +308,20 @@ class DatabaseOperatorsTests {
val control = Program.query(Structure(Atom("a"), listOf(Variable("X")))).toList()
assertEquals(3, control.size, "Expected 3 results")
assertEquals(3, Program.db.predicates["a/1"]!!.clauses.size, "Expected 3 clauses")
assertEquals(3, Program.db.predicates[FunctorInfo.of("a/1")]!!.clauses.size, "Expected 3 clauses")
val retract = RetractAll(Structure(Atom("a"), listOf(Variable("X"))))
val result = retract.satisfy(emptyMap()).toList()
assertEquals(1, result.size, "Expected 1 result")
assertTrue(result[0].isSuccess, "Expected success")
assertEquals(0, Program.db.predicates["a/1"]!!.clauses.size, "Expected 0 clauses")
assertEquals(0, Program.db.predicates[FunctorInfo.of("a/1")]!!.clauses.size, "Expected 0 clauses")
}
@Test
fun `If Head refers to a predicate that is not defined, it is implicitly created as a dynamic predicate`() {
val predicateName = "idonotyetexist"
val predicateFunctor = "$predicateName/1"
val predicateFunctor = FunctorInfo.of("$predicateName/1")
assertFalse(predicateFunctor in Program.db.predicates, "Expected predicate to not exist before")