Skip to content

Commit 067be3d

Browse files
committed
feat: add toString visitor
1 parent 131802b commit 067be3d

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed

src/main/scala/io/github/kelvindev15/prolog/core/Term.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.github.kelvindev15.prolog.core
22

3-
import io.github.kelvindev15.prolog.utils.TermVisitor
3+
import io.github.kelvindev15.prolog.utils.{TermVisitor, ToStringTermVisitor}
44

55
trait Visitable:
66
self: Term =>
@@ -10,3 +10,4 @@ trait Term extends Visitable:
1010
def isGround: Boolean
1111
def variables: Seq[Variable]
1212
def asTerm: Term
13+
override def toString: String = accept(ToStringTermVisitor())
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.github.kelvindev15.prolog.utils
2+
import io.github.kelvindev15.prolog.core.Goals.{Conjunction, Disjunction}
3+
import io.github.kelvindev15.prolog.core.RecursiveStruct.BinaryRecursiveStruct
4+
import io.github.kelvindev15.prolog.core.Struct.Clause
5+
import io.github.kelvindev15.prolog.core.{Constant, PrologList, RecursiveStruct, Struct, Variable}
6+
7+
class ToStringTermVisitor extends TermVisitor[String]:
8+
9+
override def visit(atom: Constant.Atom): String = atom.value
10+
override def visit(numeric: Constant.Numeric): String = numeric.value.toString
11+
override def visit(variable: Variable): String = variable.name
12+
override def visit(clause: Struct.Clause): String = clause.head match
13+
case Some(h) => s"${visit(h)} :- ${visit(clause.body)}."
14+
case _ => visit(clause.body)
15+
override def visit(struct: Struct): String = struct match
16+
case atom: Constant.Atom => visit(atom)
17+
case clause: Clause => visit(clause)
18+
case list: PrologList => list.linearizedArguments.map(visit).mkString("[", ", ", "]")
19+
case binaryRecursiveStruct: BinaryRecursiveStruct => visit(binaryRecursiveStruct)
20+
case _ => s"${visit(struct.functor)}${struct.arguments.map(visit).mkString("(", ", ", ")")}"
21+
override def visit(recursiveStruct: BinaryRecursiveStruct): String =
22+
val linearizedArgs = recursiveStruct.linearizedArguments.map(visit)
23+
recursiveStruct match
24+
case _: Conjunction => linearizedArgs.mkString(", ")
25+
case _: Disjunction => linearizedArgs.mkString("; ")
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package io.github.kelvindev15.visitors
2+
3+
import io.github.kelvindev15.prolog.core.Struct.Fact
4+
import io.github.kelvindev15.prolog.dsl.{DeclarativeDSL, PrologDSL}
5+
import org.scalatest.funsuite.AnyFunSuite
6+
import org.scalatest.matchers.should.Matchers
7+
8+
class TestStringTermVisitor extends AnyFunSuite with Matchers with PrologDSL with DeclarativeDSL:
9+
10+
test("Test structs"):
11+
"rainbow"("orange").toString shouldEqual "rainbow(orange)"
12+
"father"("abraham", X).toString shouldEqual "father(abraham, X)"
13+
14+
test("Test facts"):
15+
Fact("abraham").toString shouldEqual "abraham :- true."
16+
Fact("father"(X)).toString shouldEqual "father(X) :- true."
17+
18+
test("Test rules"):
19+
("a" :- "b").toString shouldEqual "a :- b."
20+
("a" :- &&("b", "c", "d")).toString shouldEqual "a :- b, c, d."
21+
("a" :- ||("b", "c", "d")).toString shouldEqual "a :- b; c; d."
22+
23+
test("Test lists"):
24+
list("a", "b", "d").toString shouldEqual "[a, b, d]"
25+
list("a").toString shouldEqual "[a]"
26+
27+
test("Test numeric"):
28+
"pred"(1.3).toString shouldEqual "pred(1.3)"
29+
"pred"(25).toString shouldEqual "pred(25)"

0 commit comments

Comments
 (0)