Arithmetic preprocessing

This commit is contained in:
Tibo De Peuter 2025-04-28 12:20:03 +02:00
parent 174855d7a3
commit 32165a90f5
Signed by: tdpeuter
GPG key ID: 38297DE43F75FFE2
3 changed files with 442 additions and 124 deletions

View file

@ -1,24 +1,13 @@
package interpreter
import io.Logger
import prolog.ast.arithmetic.Expression
import prolog.ast.logic.Clause
import prolog.ast.logic.Fact
import prolog.ast.logic.LogicOperand
import prolog.ast.logic.Rule
import prolog.ast.terms.Atom
import prolog.ast.terms.Body
import prolog.ast.terms.Goal
import prolog.ast.terms.Head
import prolog.ast.terms.Structure
import prolog.ast.terms.Term
import prolog.builtins.Conjunction
import prolog.builtins.Cut
import prolog.builtins.Disjunction
import prolog.builtins.Fail
import prolog.builtins.False
import prolog.builtins.Not
import prolog.builtins.Query
import prolog.builtins.True
import prolog.ast.terms.*
import prolog.builtins.*
/**
* Preprocessor for Prolog
@ -45,12 +34,14 @@ open class Preprocessor {
is Fact -> {
Fact(preprocess(clause.head) as Head)
}
is Rule -> {
Rule(
preprocess(clause.head) as Head,
preprocess(clause.body as Term) as Body
)
}
else -> clause
}
}
@ -65,23 +56,70 @@ open class Preprocessor {
Structure(Atom("fail"), emptyList()) -> Fail
Atom("!") -> Cut()
Structure(Atom("!"), emptyList()) -> Cut()
else -> {
is Structure -> {
// Preprocess the arguments first to recognize builtins
val args = term.arguments.map { preprocess(it) }
when {
term is Structure && term.functor == ",/2" -> {
val args = term.arguments.map { preprocess(it) }
// TODO Remove hardcoding by storing the functors as constants in operators?
// Logic
term.functor == ",/2" -> {
Conjunction(args[0] as LogicOperand, args[1] as LogicOperand)
}
term is Structure && term.functor == ";/2" -> {
val args = term.arguments.map { preprocess(it) }
term.functor == ";/2" -> {
Disjunction(args[0] as LogicOperand, args[1] as LogicOperand)
}
term is Structure && term.functor == "\\+/1" -> {
val args = term.arguments.map { preprocess(it) }
term.functor == "\\+/1" -> {
Not(args[0] as Goal)
}
// Arithmetic
term.functor == "=\\=/2" && args.all { it is Expression } -> {
EvaluatesToDifferent(args[0] as Expression, args[1] as Expression)
}
term.functor == "=:=/2" && args.all { it is Expression } -> {
EvaluatesTo(args[0] as Expression, args[1] as Expression)
}
term.functor == "is/2" && args.all { it is Expression } -> {
Is(args[0] as Expression, args[1] as Expression)
}
term.functor == "-/1" && args.all { it is Expression } -> {
Negate(args[0] as Expression)
}
term.functor == "-/2" && args.all { it is Expression } -> {
Subtract(args[0] as Expression, args[1] as Expression)
}
term.functor == "+/1" && args.all { it is Expression } -> {
Positive(args[0] as Expression)
}
term.functor == "+/2" && args.all { it is Expression } -> {
Add(args[0] as Expression, args[1] as Expression)
}
term.functor == "*/2" && args.all { it is Expression } -> {
Multiply(args[0] as Expression, args[1] as Expression)
}
term.functor == "//2" && args.all { it is Expression } -> {
Divide(args[0] as Expression, args[1] as Expression)
}
term.functor == "between/3" && args.all { it is Expression } -> {
Between(args[0] as Expression, args[1] as Expression, args[2] as Expression)
}
else -> term
}
}
else -> term
}
if (prepped != term || prepped::class != term::class) {

View file

@ -62,11 +62,11 @@ class EvaluatesTo(private val left: Expression, private val right: Expression) :
/**
* True when Number is the value to which Expr evaluates.
*/
class Is(private val left: Expression, private val right: Expression) :
Operator(Atom("is"), left, right), Satisfiable {
class Is(val number: Expression, val expr: Expression) :
Operator(Atom("is"), number, expr), Satisfiable {
override fun satisfy(subs: Substitutions): Answers {
val t1 = left.simplify(subs)
val t2 = right.simplify(subs)
val t1 = number.simplify(subs)
val t2 = expr.simplify(subs)
if (!atomic(t2.to, subs)) {
return sequenceOf(Result.failure(IllegalArgumentException("Right operand must be instantiated")))
@ -119,7 +119,7 @@ open class Subtract(private val expr1: Expression, private val expr2: Expression
/**
* Result = Expr1 * Expr2
*/
class Multiply(private val expr1: Expression, private val expr2: Expression) :
class Multiply(val expr1: Expression, val expr2: Expression) :
ArithmeticOperator(Atom("*"), expr1, expr2) {
override fun simplify(subs: Substitutions): Simplification {
val result = Variable("Result")