Arithmetic preprocessing
This commit is contained in:
parent
174855d7a3
commit
32165a90f5
3 changed files with 442 additions and 124 deletions
|
@ -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) {
|
||||
|
|
|
@ -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")
|
||||
|
|
Reference in a new issue