Skip to content

Commit

Permalink
edit the TuPrologRuntimeException type hierarchy to support a stack o…
Browse files Browse the repository at this point in the history
…f ExecutionContexts for each exception, making MetaError useless
  • Loading branch information
gciatto committed Aug 28, 2020
1 parent 924d9cd commit bab7cac
Show file tree
Hide file tree
Showing 16 changed files with 273 additions and 130 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,31 @@ import kotlin.js.JsName
*
* @param message the detail message string.
* @param cause the cause of this exception.
* @param context The current context at exception creation
* @param contexts a stack of contexts localising the exception
* @param exitStatus The integer code representing the exit status code; it defaults to 1
*
* @author Enrico
*/
class HaltException(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext,
contexts: Array<ExecutionContext>,
@JsName("exitStatus") val exitStatus: Int = 1
) : TuPrologRuntimeException(message, cause, context) {
) : TuPrologRuntimeException(message, cause, contexts) {

constructor(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext,
exitStatus: Int = 1
) : this(message, cause, arrayOf(context), exitStatus)

constructor(cause: Throwable?, context: ExecutionContext, exitStatus: Int = 1)
: this(cause?.toString(), cause, context, exitStatus)

override fun updateContext(newContext: ExecutionContext): HaltException =
HaltException(message, cause, newContext, exitStatus)
HaltException(message, cause, contexts.setFirst(newContext), exitStatus)

override fun pushContext(newContext: ExecutionContext): HaltException =
HaltException(message, cause, contexts.addLast(newContext), exitStatus)
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import kotlin.jvm.JvmStatic
*
* @param message the detail message string.
* @param cause the cause of this exception.
* @param context The current context at exception creation
* @param contexts a stack of contexts localising the exception
* @param type The error type structure
* @param extraData The possible extra data to be carried with the error
*
Expand All @@ -23,10 +23,18 @@ import kotlin.jvm.JvmStatic
abstract class PrologError(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext,
contexts: Array<ExecutionContext>,
@JsName("type") open val type: Struct,
@JsName("extraData") open val extraData: Term? = null
) : TuPrologRuntimeException(message, cause, context) {
) : TuPrologRuntimeException(message, cause, contexts) {

constructor(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext,
type: Struct,
extraData: Term? = null
) : this(message, cause, arrayOf(context), type, extraData)

constructor(cause: Throwable?, context: ExecutionContext, type: Struct, extraData: Term? = null)
: this(cause?.toString(), cause, context, type, extraData)
Expand All @@ -37,8 +45,9 @@ abstract class PrologError(
private fun generateErrorStruct() =
extraData?.let { errorStructOf(type, it) } ?: errorStructOf(type)

override fun updateContext(newContext: ExecutionContext): PrologError =
of(message, cause, newContext, type, extraData)
abstract override fun updateContext(newContext: ExecutionContext): PrologError

abstract override fun pushContext(newContext: ExecutionContext): PrologError

override fun toString(): String = errorStruct.toString()

Expand All @@ -57,33 +66,43 @@ abstract class PrologError(
context: ExecutionContext,
type: Struct,
extraData: Term? = null
): PrologError = of(message, cause, arrayOf(context), type, extraData)

@JvmStatic
@JsName("ofManyContexts")
fun of(
message: String? = null,
cause: Throwable? = null,
contexts: Array<ExecutionContext>,
type: Struct,
extraData: Term? = null
): PrologError = with(type) {
when {
functor == MetaError.typeFunctor && cause is TuPrologRuntimeException -> MetaError(
message,
cause,
context,
extraData
)
functor == InstantiationError.typeFunctor -> InstantiationError(message, cause, context, extraData)
functor == SystemError.typeFunctor -> SystemError(message, cause, context, extraData)
functor == InstantiationError.typeFunctor -> InstantiationError(message, cause, contexts, extraData)
functor == SystemError.typeFunctor -> SystemError(message, cause, contexts, extraData)
functor == ExistenceError.typeFunctor && type.arity == 2 ->
ExistenceError(message, cause, context, ExistenceError.ObjectType.fromTerm(type[0])!!, type[1])
ExistenceError(message, cause, contexts, ExistenceError.ObjectType.fromTerm(type[0])!!, type[1])
functor == DomainError.typeFunctor && arity == 2 && DomainError.Expected.fromTerm(args.first()) != null ->
DomainError(
message,
cause,
context,
contexts,
DomainError.Expected.fromTerm(args.first())!!,
args[1],
extraData
)
functor == TypeError.typeFunctor && arity == 2 && TypeError.Expected.fromTerm(args.first()) != null ->
TypeError(message, cause, context, TypeError.Expected.fromTerm(args.first())!!, args[1], extraData)
TypeError(message, cause, contexts, TypeError.Expected.fromTerm(args.first())!!, args[1], extraData)
functor == EvaluationError.typeFunctor && arity == 1 && EvaluationError.Type.fromTerm(args.single()) != null ->
EvaluationError(message, cause, context, EvaluationError.Type.fromTerm(args.single())!!, extraData)
functor == MessageError.typeFunctor -> MessageError(message, cause, context, extraData)
else -> object : PrologError(message, cause, context, type, extraData) {}
EvaluationError(message, cause, contexts, EvaluationError.Type.fromTerm(args.single())!!, extraData)
functor == MessageError.typeFunctor -> MessageError(message, cause, contexts, extraData)
else -> object : PrologError(message, cause, contexts, type, extraData) {
override fun updateContext(newContext: ExecutionContext): PrologError =
of(this.message, this.cause, this.contexts.setFirst(newContext), this.type, this.extraData)

override fun pushContext(newContext: ExecutionContext): PrologError =
of(this.message, this.cause, this.contexts.addLast(newContext), this.type, this.extraData)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,22 @@ import it.unibo.tuprolog.solve.ExecutionContext
*
* @param message the detail message string.
* @param cause the cause of this exception.
* @param context The current context at exception creation
* @param contexts a stack of contexts localising the exception
*
* @author Giovanni
*/
abstract class PrologWarning(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext
) : TuPrologRuntimeException(message, cause, context)
contexts: Array<ExecutionContext>
) : TuPrologRuntimeException(message, cause, contexts) {
constructor(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext
) : this(message, cause, arrayOf(context))

abstract override fun updateContext(newContext: ExecutionContext): PrologWarning

abstract override fun pushContext(newContext: ExecutionContext): PrologWarning
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,31 @@ import kotlin.js.JsName
*
* @param message the detail message string.
* @param cause the cause of this exception.
* @param context The current context at exception creation
* @param contexts a stack of contexts localising the exception
* @param exceededDuration The time duration exceeded
*
* @author Enrico
*/
class TimeOutException(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext,
contexts: Array<ExecutionContext>,
@JsName("exceededDuration") val exceededDuration: TimeDuration
) : TuPrologRuntimeException(message, cause, context) {
) : TuPrologRuntimeException(message, cause, contexts) {

constructor(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext,
exceededDuration: TimeDuration
) : this(message, cause, arrayOf(context), exceededDuration)

constructor(cause: Throwable?, context: ExecutionContext, exceededDuration: TimeDuration)
: this(cause?.toString(), cause, context, exceededDuration)

override fun updateContext(newContext: ExecutionContext): TimeOutException =
TimeOutException(message, cause, newContext, exceededDuration)
TimeOutException(message, cause, contexts.setFirst(newContext), exceededDuration)

override fun pushContext(newContext: ExecutionContext): TimeOutException =
TimeOutException(message, cause, arrayOf(*contexts, newContext), exceededDuration)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,36 @@ import kotlin.js.JsName
*
* @param message the detail message string.
* @param cause the cause of this exception.
* @param context The current context at exception creation
* @param contexts a stack of contexts localising the exception
*/
open class TuPrologRuntimeException(
message: String? = null,
cause: Throwable? = null,
@JsName("context") val context: ExecutionContext
@JsName("contexts") val contexts: Array<ExecutionContext>
) : TuPrologException(message, cause) {

init {
require(contexts.isNotEmpty())
}

constructor(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext,
vararg otherContexts: ExecutionContext
)
: this(message, cause, arrayOf(context, *otherContexts))

constructor(cause: Throwable?, context: ExecutionContext) : this(cause?.toString(), cause, context)

@JsName("context")
val context: ExecutionContext
get() = contexts[0]

/** The exception stacktrace; shorthand for `context.prologStackTrace` */
@JsName("prologStackTrace")
val prologStackTrace: List<Struct>
get() = context.prologStackTrace
get() = sequenceOf(*contexts).flatMap { it.prologStackTrace.asSequence() }.toList()

/**
* Creates a new exception instance with context field updated to [newContext].
Expand All @@ -33,4 +49,14 @@ open class TuPrologRuntimeException(
@JsName("updateContext")
open fun updateContext(newContext: ExecutionContext): TuPrologRuntimeException =
TuPrologRuntimeException(message, cause, newContext)

@JsName("pushContext")
open fun pushContext(newContext: ExecutionContext): TuPrologRuntimeException =
TuPrologRuntimeException(message, cause, arrayOf(*contexts, context))

protected fun Array<ExecutionContext>.setFirst(item: ExecutionContext): Array<ExecutionContext> =
arrayOf(item, *copyOfRange(1, size))

protected fun Array<ExecutionContext>.addLast(item: ExecutionContext): Array<ExecutionContext> =
arrayOf(*this, item)
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,35 @@ import it.unibo.tuprolog.solve.exception.PrologError
*
* @param message the detail message string.
* @param cause the cause of this exception.
* @param context The current context at exception creation
* @param contexts a stack of contexts localising the exception
* @param expectedDomain The expected domain, that wouldn't have raised the error
* @param actualValue The value not respecting [expectedDomain]
* @param extraData The possible extra data to be carried with the error
*
* @author Enrico
*/
@Suppress("MemberVisibilityCanBePrivate")
class DomainError(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext,
contexts: Array<ExecutionContext>,
val expectedDomain: Expected,
val actualValue: Term,
extraData: Term? = null
) : PrologError(message, cause, context, Atom.of(typeFunctor), extraData) {
) : PrologError(message, cause, contexts, Atom.of(typeFunctor), extraData) {

constructor(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext,
expectedDomain: Expected,
actualValue: Term,
extraData: Term? = null
) : this(message, cause, arrayOf(context), expectedDomain, actualValue, extraData)

override fun updateContext(newContext: ExecutionContext): DomainError =
DomainError(message, cause, contexts.setFirst(newContext), expectedDomain, actualValue, extraData)

override fun pushContext(newContext: ExecutionContext): DomainError =
DomainError(message, cause, contexts.addLast(newContext), expectedDomain, actualValue, extraData)

override val type: Struct by lazy { Struct.of(super.type.functor, expectedDomain.toTerm(), actualValue) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import it.unibo.tuprolog.solve.exception.PrologError
*
* @param message the detail message string.
* @param cause the cause of this exception.
* @param context The current context at exception creation
* @param contexts a stack of contexts localising the exception
* @param errorType The error type
* @param extraData The possible extra data to be carried with the error
*
Expand All @@ -21,10 +21,24 @@ import it.unibo.tuprolog.solve.exception.PrologError
class EvaluationError(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext,
contexts: Array<ExecutionContext>,
val errorType: Type,
extraData: Term? = null
) : PrologError(message, cause, context, Atom.of(typeFunctor), extraData) {
) : PrologError(message, cause, contexts, Atom.of(typeFunctor), extraData) {

constructor(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext,
errorType: Type,
extraData: Term? = null
) : this(message, cause, arrayOf(context), errorType, extraData)

override fun updateContext(newContext: ExecutionContext): EvaluationError =
EvaluationError(message, cause, contexts.setFirst(newContext), errorType, extraData)

override fun pushContext(newContext: ExecutionContext): EvaluationError =
EvaluationError(message, cause, contexts.addLast(newContext), errorType, extraData)

override val type: Struct by lazy { Struct.of(super.type.functor, errorType.toTerm()) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,37 @@ import it.unibo.tuprolog.solve.exception.PrologError
*
* @param message the detail message string.
* @param cause the cause of this exception.
* @param context The current context at exception creation
* @param contexts a stack of contexts localising the exception
* @param expectedType The type of the missing object
* @param actualValue The object whose lack caused the error
* @param extraData The possible extra data to be carried with the error
*/
class ExistenceError(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext,
contexts: Array<ExecutionContext>,
val expectedType: ObjectType,
val actualValue: Term,
extraData: Term? = null
) : PrologError(message, cause, context, Atom.of(typeFunctor), extraData) {
) : PrologError(message, cause, contexts, Atom.of(typeFunctor), extraData) {

constructor(
message: String? = null,
cause: Throwable? = null,
context: ExecutionContext,
expectedType: ObjectType,
actualValue: Term,
extraData: Term? = null
) : this(message, cause, arrayOf(context), expectedType, actualValue, extraData)

override val type: Struct by lazy { Struct.of(super.type.functor, expectedType.toTerm(), actualValue) }

override fun updateContext(newContext: ExecutionContext): ExistenceError =
ExistenceError(message, cause, contexts.setFirst(newContext), expectedType, actualValue, extraData)

override fun pushContext(newContext: ExecutionContext): ExistenceError =
ExistenceError(message, cause, contexts.addLast(newContext), expectedType, actualValue, extraData)

companion object {

fun forProcedure(
Expand Down
Loading

0 comments on commit bab7cac

Please sign in to comment.