Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raise human-readable error in case of incorrect usage of _on or _ special variables in expressions #234

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions shared/src/main/scala/io/kaitai/struct/ClassTypeProvider.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,24 @@ import io.kaitai.struct.datatype.DataType
import io.kaitai.struct.datatype.DataType._
import io.kaitai.struct.exprlang.Ast
import io.kaitai.struct.format._
import io.kaitai.struct.precompile.{EnumNotFoundError, FieldNotFoundError, TypeNotFoundError, TypeUndecidedError}
import io.kaitai.struct.precompile.{EnumNotFoundError, ExpressionError, FieldNotFoundError, TypeNotFoundError, TypeUndecidedError}
import io.kaitai.struct.translators.TypeProvider

class ClassTypeProvider(classSpecs: ClassSpecs, var topClass: ClassSpec) extends TypeProvider {
var nowClass = topClass
val allClasses: ClassSpecs = classSpecs

/**
* Type of the `_` variable in the expression. That variable is defined in
* `repeat-until` and `valid: expr` contexts and refers to the attribute
* just parsed.
*/
var _currentIteratorType: Option[DataType] = None
/**
* Type of the `_on` variable in the expression. That variable is defined in
* `cases.<case>` contexts and refers to the value of `switch-on` expression.
*/
var _currentSwitchType: Option[DataType] = None
def currentIteratorType: DataType = _currentIteratorType.get
def currentSwitchType: DataType = _currentSwitchType.get

override def determineType(attrName: String): DataType = {
determineType(nowClass, attrName)
Expand All @@ -30,14 +37,20 @@ class ClassTypeProvider(classSpecs: ClassSpecs, var topClass: ClassSpec) extends
topClass.toDataType
case Identifier.PARENT =>
if (inClass.parentClass == UnknownClassSpec)
throw new RuntimeException(s"Unable to derive ${Identifier.PARENT} type in ${inClass.name.mkString("::")}")
throw new ExpressionError(s"Unable to derive '${Identifier.PARENT}' type in '${inClass.nameAsStr}'")
inClass.parentClass.toDataType
case Identifier.IO =>
KaitaiStreamType
case Identifier.ITERATOR =>
currentIteratorType
_currentIteratorType match {
case Some(value) => value
case None => throw new ExpressionError(s"Context variable '$attrName' is available only in the 'repeat-until' and 'valid/expr' attributes")
}
case Identifier.SWITCH_ON =>
currentSwitchType
_currentSwitchType match {
case Some(value) => value
case None => throw new ExpressionError(s"Context variable '$attrName' is available only in the 'cases.<case>' expressions")
}
case Identifier.INDEX =>
CalcIntType
case Identifier.SIZEOF =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import io.kaitai.struct.translators.MethodArgType
* Base class for all expression-related errors, not localized to a certain path
* in source file.
*/
sealed abstract class ExpressionError(msg: String) extends RuntimeException(msg)
sealed class ExpressionError(msg: String) extends RuntimeException(msg)
class TypeMismatchError(msg: String) extends ExpressionError(msg)
class TypeUndecidedError(msg: String) extends ExpressionError(msg)
class WrongMethodCall(val dataType: MethodArgType, val methodName: String, val expectedSigs: Iterable[String], val actualSig: String)
Expand Down
Loading