Checkpoint
This commit is contained in:
parent
e3c84e1761
commit
e73e5cbfc8
32 changed files with 1354 additions and 92 deletions
152
src/prolog/builtins/arithmeticOperators.kt
Normal file
152
src/prolog/builtins/arithmeticOperators.kt
Normal file
|
@ -0,0 +1,152 @@
|
|||
package prolog.builtins
|
||||
|
||||
import prolog.ast.arithmetic.ArithmeticOperator
|
||||
import prolog.ast.arithmetic.Expression
|
||||
import prolog.ast.logic.LogicOperand
|
||||
import prolog.ast.logic.LogicOperator
|
||||
import prolog.ast.logic.Provable
|
||||
import prolog.ast.terms.*
|
||||
import prolog.logic.*
|
||||
|
||||
// TODO >
|
||||
|
||||
// TODO <
|
||||
|
||||
// TODO =<
|
||||
|
||||
// TODO >=
|
||||
|
||||
/**
|
||||
* True if expression Expr1 evaluates to a number non-equal to Expr2.
|
||||
*/
|
||||
class EvaluatesToDifferent(private val left: Expression, private val right: Expression) :
|
||||
ArithmeticOperator(Atom("=\\="), left, right) {
|
||||
override fun evaluate(subs: Substituted): Pair<Term, Substituted> {
|
||||
val t1 = left.evaluate(subs)
|
||||
val t2 = right.evaluate(subs)
|
||||
|
||||
// Should both be instantiated
|
||||
if (!atomic(t1.first) || !atomic(t2.first)) {
|
||||
throw IllegalArgumentException("Both operands must be instantiated")
|
||||
}
|
||||
|
||||
return if (equivalent(t1.first, t2.first)) {
|
||||
Pair(False, emptyMap())
|
||||
} else {
|
||||
Pair(True, t1.second + t2.second)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* True if Expr1 evaluates to a number equal to Expr2.
|
||||
*/
|
||||
class EvaluatesTo(private val left: Expression, private val right: Expression) :
|
||||
ArithmeticOperator(Atom("=:="), left, right) {
|
||||
override fun evaluate(subs: Substituted): Pair<Term, Substituted> {
|
||||
val t1 = left.evaluate(subs)
|
||||
val t2 = right.evaluate(subs)
|
||||
|
||||
// Should both be instantiated
|
||||
if (!atomic(t1.first) || !atomic(t2.first)) {
|
||||
throw IllegalArgumentException("Both operands must be instantiated")
|
||||
}
|
||||
|
||||
return if (equivalent(t1.first, t2.first)) {
|
||||
Pair(True, t1.second + t2.second)
|
||||
} else {
|
||||
Pair(False, emptyMap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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), Provable {
|
||||
override fun prove(subs: Substituted): Sequence<Substituted> {
|
||||
val t1 = left.evaluate(subs)
|
||||
val t2 = right.evaluate(subs)
|
||||
|
||||
if (!atomic(t2.first)) {
|
||||
throw IllegalArgumentException("Arguments are not sufficiently instantiated")
|
||||
}
|
||||
|
||||
return unifyLazy(t1.first, t2.first, subs).map{ it + t1.second + t2.second }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Result = -Expr
|
||||
*/
|
||||
class Negate(operand: Expression) : Subtract(Integer(0), operand)
|
||||
|
||||
/**
|
||||
* Result = Expr
|
||||
*/
|
||||
class Positive(operand: Expression) : Add(Integer(0), operand)
|
||||
|
||||
/**
|
||||
* Result = Expr1 + Expr2
|
||||
*/
|
||||
open class Add(private val expr1: Expression, private val expr2: Expression) :
|
||||
ArithmeticOperator(Atom("+"), expr1, expr2) {
|
||||
override fun evaluate(subs: Substituted): Pair<Term, Substituted> {
|
||||
val result = Variable("Result")
|
||||
val map = plus(expr1, expr2, result, subs)
|
||||
return result.evaluate(map.first())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Result = Expr1 - Expr2
|
||||
*/
|
||||
open class Subtract(private val expr1: Expression, private val expr2: Expression) :
|
||||
ArithmeticOperator(Atom("-"), expr1, expr2) {
|
||||
override fun evaluate(subs: Substituted): Pair<Term, Substituted> {
|
||||
val result = Variable("Result")
|
||||
val map = plus(expr2, result, expr1, subs)
|
||||
return result.evaluate(map.first())
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Expr * Expr
|
||||
/**
|
||||
* Result = Expr1 * Expr2
|
||||
*/
|
||||
class Multiply(private val expr1: Expression, private val expr2: Expression) :
|
||||
ArithmeticOperator(Atom("*"), expr1, expr2) {
|
||||
override fun evaluate(subs: Substituted): Pair<Term, Substituted> {
|
||||
val result = Variable("Result")
|
||||
val map = mul(expr1, expr2, result, subs)
|
||||
return result.evaluate(map.first())
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Expr / Expr
|
||||
|
||||
// TODO Expr mod Expr
|
||||
|
||||
// TODO Expr rem Expr
|
||||
|
||||
class Between(private val expr1: Expression, private val expr2: Expression, private val expr3: Expression) :
|
||||
Operator(Atom("between"), expr1, expr2) {
|
||||
override fun prove(subs: Substituted): Sequence<Substituted> {
|
||||
val e1 = expr1.evaluate(subs)
|
||||
val e2 = expr2.evaluate(subs)
|
||||
val e3 = expr3.evaluate(subs)
|
||||
|
||||
require(e1.first is Integer && e2.first is Integer) { "Arguments must be integers" }
|
||||
|
||||
val v1 = e1.first as Integer
|
||||
val v2 = e2.first as Integer
|
||||
|
||||
return if (variable(e3.first)) {
|
||||
between(v1, v2, e3.first as Variable).map { it + e1.second + e2.second }
|
||||
} else {
|
||||
between(v1, v2, e3.first as Integer).map { it + e1.second + e2.second }
|
||||
}
|
||||
}
|
||||
}
|
Reference in a new issue