fpp/compiler/lib/src/main/scala/util/Error.scala
2025-11-18 10:12:00 -08:00

834 lines
31 KiB
Scala

package fpp.compiler.util
import fpp.compiler.util.Location
import java.util.Locale
/** An exception for signaling internal compiler errors */
final case class InternalError(val msg: String) extends Exception {
override def toString = s"internal error: $msg"
}
/** A data type for handling compilation errors */
sealed trait Error {
/** Print the location of a port matching */
def printMatchingLoc(matchingLoc: Location): Unit = {
System.err.println("port matching is specified here:")
System.err.println(matchingLoc)
}
/** Print the location of a previous occurrence */
def printPrevLoc(prevLoc: Location): Unit = {
System.err.println("previous occurrence is here:")
System.err.println(prevLoc)
}
/** Print a note */
def printNote(note: String) = System.err.println(s"note: $note")
/*** Print the error */
def print: Unit = {
this match {
case SyntaxError(loc, msg) => Error.print (Some(loc)) (msg)
case CodeGenError.DuplicateCppFile(file, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate C++ file ${file}")
System.err.println("previous file would be generated here:")
System.err.println(prevLoc)
case CodeGenError.DuplicateJsonFile(file, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate JSON file ${file}")
System.err.println("previous file would be generated here:")
System.err.println(prevLoc)
case CodeGenError.DuplicateXmlFile(file, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate XML file ${file}")
System.err.println("previous file would be generated here:")
System.err.println(prevLoc)
case CodeGenError.EmptyStruct(loc) =>
Error.print (Some(loc)) (s"cannot write XML for an empty struct")
case IncludeError.Cycle(loc, msg) => Error.print (Some(loc)) (msg)
case FileError.CannotOpen(locOpt, name) =>
Error.print (locOpt) (s"cannot open file $name")
case FileError.CannotResolvePath(loc, name) =>
Error.print (Some(loc)) (s"cannot resolve path $name")
case MultiError(errors) =>
errors.foreach(_.print)
case SemanticError.ChannelNotInDictionary(loc, channelName, topologyName) =>
Error.print (Some(loc)) (s"channel $channelName is not in the dictionary for topology $topologyName")
case SemanticError.DivisionByZero(loc) =>
Error.print (Some(loc)) ("division by zero")
case SemanticError.DuplicateConnectionAtMatchedPort(loc, port, portNum, prevLoc, matchingLoc) =>
Error.print (Some(loc)) (s"duplicate connection at matched port $port[$portNum]")
printPrevLoc(prevLoc)
printMatchingLoc(matchingLoc)
case SemanticError.DuplicateDictionaryName(kind, name, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate ${kind} name ${name}")
printPrevLoc(prevLoc)
case SemanticError.DuplicateEnumValue(value, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate enum value ${value}")
printPrevLoc(prevLoc)
case SemanticError.DuplicateIdValue(value, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate identifier value ${value}")
printPrevLoc(prevLoc)
case SemanticError.DuplicateInitSpecifier(phase, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate initialization for phase ${phase}")
printPrevLoc(prevLoc)
case SemanticError.DuplicateInstance(name, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate instance $name")
printPrevLoc(prevLoc)
case SemanticError.DuplicateLimit(loc, prevLoc) =>
Error.print (Some(loc)) ("duplicate limit")
printPrevLoc(prevLoc)
case SemanticError.DuplicateMatchedConnection(
loc,
prevLoc,
matchingLoc
) =>
Error.print (Some(loc)) ("duplicate connection between a matched port array and a single instance")
printPrevLoc(prevLoc)
printMatchingLoc(matchingLoc)
printNote("each port in a matched port array must be connected to a separate instance")
case SemanticError.DuplicateOpcodeValue(value, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate opcode value ${value}")
printPrevLoc(prevLoc)
case SemanticError.DuplicateOutputConnection(loc, portNum, prevLoc) =>
Error.print (Some(loc)) (s"duplicate connection at output port $portNum")
printPrevLoc(prevLoc)
case SemanticError.DuplicateParameter(name, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate parameter ${name}")
System.err.println("previous parameter is here:")
System.err.println(prevLoc)
case SemanticError.DuplicatePattern(kind, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate $kind pattern")
printPrevLoc(prevLoc)
case SemanticError.DuplicatePortInstance(name, loc, importLocs, prevLoc, prevImportLocs) =>
Error.print (Some(loc)) (s"duplicate port instance ${name}")
if (importLocs.nonEmpty) {
System.err.println(s"port imported from here")
importLocs.map(System.err.println)
}
System.err.println("previous instance is here:")
System.err.println(prevLoc)
if (prevImportLocs.nonEmpty) {
System.err.println(s"previous instance imported from here")
prevImportLocs.reverse.map(System.err.println)
}
case SemanticError.DuplicateStateMachineInstance(name, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate state machine instance name ${name}")
printPrevLoc(prevLoc)
case SemanticError.DuplicateStructMember(name, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate struct member ${name}")
System.err.println("previous member is here:")
System.err.println(prevLoc)
case SemanticError.DuplicateTlmPacketSet(name, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate telemetry packet set ${name}")
System.err.println("previous set is here:")
System.err.println(prevLoc)
case SemanticError.DuplicateTopology(name, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate topology ${name}")
printPrevLoc(prevLoc)
case SemanticError.DuplicateInterface(name, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate interface ${name}")
printPrevLoc(prevLoc)
case SemanticError.EmptyArray(loc) =>
Error.print (Some(loc)) ("array expression may not be empty")
case SemanticError.ImplicitDuplicateConnectionAtMatchedPort(
loc,
port,
portNum,
implyingLoc,
matchingLoc,
prevLoc
) =>
Error.print (Some(loc)) (s"implicit duplicate connection at matched port $port[$portNum]")
System.err.println("connection is implied here:")
System.err.println(implyingLoc)
System.err.println("because of matching specified here:")
System.err.println(matchingLoc)
System.err.println("conflicting connection is here:")
System.err.println(prevLoc)
case SemanticError.InconsistentDictionarySpecifier(loc, prevLoc) =>
Error.print (Some(loc)) (s"inconsistent location specifier")
printPrevLoc(prevLoc)
printNote("one specifies dictionary and one does not")
case SemanticError.InconsistentLocationPath(loc, path, prevLoc, prevPath) =>
Error.print (Some(loc)) (s"inconsistent location path ${path}")
printPrevLoc(prevLoc)
System.err.println(s"previous path is ${prevPath}")
case SemanticError.IncorrectDictionarySpecifier(loc, defLoc) =>
Error.print (Some(loc)) (s"incorrect location specifier")
System.err.println(s"actual definition is here:")
System.err.println(defLoc)
printNote("one specifies dictionary and one does not")
case SemanticError.IncorrectLocationPath(loc, specifiedPath, actualLoc) =>
Error.print (Some(loc)) (s"incorrect location path ${specifiedPath}")
System.err.println(s"actual location is ${actualLoc}")
case SemanticError.InvalidArraySize(loc, size) =>
Error.print (Some(loc)) (s"invalid array size $size")
printNote("size must be greater than zero")
case SemanticError.InvalidCommand(loc, msg) =>
Error.print (Some(loc)) (msg)
case SemanticError.InvalidComponentInstance(loc, instanceName, topName) =>
Error.print (Some(loc)) (s"instance $instanceName is not a member of topology $topName")
case SemanticError.InvalidConnection(loc, msg, fromLoc, toLoc, fromPortDefLoc, toPortDefLoc) =>
Error.print (Some(loc)) (msg)
System.err.println("from port is specified here:")
System.err.println(fromLoc)
System.err.println("to port is specified here:")
System.err.println(toLoc)
fromPortDefLoc match {
case Some(loc) =>
System.err.println("from port type is defined here:")
System.err.println(loc)
case _ => ()
}
toPortDefLoc match {
case Some(loc) =>
System.err.println("to port type is defined here:")
System.err.println(loc)
case _ => ()
}
case SemanticError.InvalidDataProducts(loc, msg) =>
Error.print (Some(loc)) (msg)
case SemanticError.InvalidDefComponentInstance(name, loc, msg) =>
Error.print (Some(loc)) (s"invalid component instance definition $name: $msg")
case SemanticError.InvalidEnumConstants(loc) =>
Error.print (Some(loc)) ("enum constants must be all explicit or all implied")
case SemanticError.InvalidEvent(loc, msg) =>
Error.print (Some(loc)) (msg)
case SemanticError.InvalidFormatString(loc, msg) =>
Error.print (Some(loc)) (s"invalid format string: $msg")
case SemanticError.InvalidIntValue(loc, v, msg) =>
Error.print (Some(loc)) (s"invalid integer value $v")
System.err.println(msg)
case SemanticError.InvalidInternalPort(loc, msg) =>
Error.print (Some(loc)) (msg)
case SemanticError.InvalidPattern(loc, msg) =>
Error.print (Some(loc)) (msg)
case SemanticError.InvalidPortInstance(loc, msg, defLoc) =>
Error.print (Some(loc)) (msg)
System.err.println(s"port definition is here:")
System.err.println(defLoc)
case SemanticError.InvalidPortInstanceId(loc, portName, componentName) =>
Error.print (Some(loc)) (s"$portName is not a port instance of component $componentName")
case SemanticError.InvalidPortKind(loc, msg, specLoc) =>
Error.print (Some(loc)) (msg)
System.err.println(s"port instance is specified here:")
System.err.println(specLoc)
case SemanticError.InvalidPortMatching(loc, msg) =>
Error.print (Some(loc)) (msg)
case SemanticError.InvalidPortNumber(loc, portNumber, port, arraySize, specLoc) =>
Error.print (Some(loc)) (s"invalid port number $portNumber for port $port (max is ${arraySize - 1})")
System.err.println(s"port instance is specified here:")
System.err.println(specLoc)
case SemanticError.InvalidPriority(loc) =>
Error.print (Some(loc)) ("only async input may have a priority")
case SemanticError.InvalidQueueFull(loc) =>
Error.print (Some(loc)) ("only async input may have queue full behavior")
case SemanticError.InvalidSpecialPort(loc, msg) =>
Error.print (Some(loc)) (msg)
case SemanticError.InvalidStringSize(loc, size) =>
Error.print (Some(loc)) (s"invalid string size $size")
case SemanticError.InvalidAnonStructMember(memberName, loc, defLoc) =>
Error.print (Some(loc)) (s"no member $memberName in anonymous struct value")
System.err.println("symbol is defined here:")
System.err.println(defLoc)
case SemanticError.InvalidStructMember(memberName, loc, structTypeName, defLoc) =>
Error.print (Some(loc)) (s"no member $memberName in struct type $structTypeName")
System.err.println("symbol is defined here:")
System.err.println(defLoc)
case SemanticError.InvalidTypeForMemberSelection(memberName, loc, typeName) =>
Error.print (Some(loc)) (s"no member $memberName in value of type $typeName")
case SemanticError.InvalidSymbol(name, loc, msg, defLoc) =>
Error.print (Some(loc)) (s"invalid symbol $name: $msg")
System.err.println("symbol is defined here:")
System.err.println(defLoc)
case SemanticError.InvalidTlmChannelName(loc, channelName, componentName) =>
Error.print (Some(loc)) (s"$channelName is not a telemetry channel of component $componentName")
case SemanticError.InvalidTlmPacketSet(loc, name, msg) =>
Error.print (Some(loc)) (s"invalid telemetry packet set $name")
System.err.println(msg)
case SemanticError.InvalidType(loc, msg) =>
Error.print (Some(loc)) (msg)
case SemanticError.InvalidToken(loc, msg) =>
Error.print (Some(loc)) (s"invalid token: $msg")
case SemanticError.MismatchedPortNumbers(
p1Loc: Location,
p1Number: Int,
p2Loc: Location,
p2Number: Int,
matchingLoc: Location
) =>
Error.print (Some(p1Loc)) (s"mismatched port numbers ($p1Number vs. $p2Number)")
System.err.println("conflicting port number is here:")
System.err.println(p2Loc)
printMatchingLoc(matchingLoc)
case SemanticError.MissingAsync(kind, loc) =>
Error.print (Some(loc)) (s"$kind component must have async input")
case SemanticError.MissingConnection(loc, matchingLoc) =>
Error.print (Some(loc)) ("no match for this connection")
printMatchingLoc(matchingLoc)
case SemanticError.MissingPortMatching(loc) =>
Error.print (Some(loc)) ("unmatched connection must go from or to a matched port")
case SemanticError.MissingPort(loc, specMsg, portMsg) =>
Error.print (Some(loc)) (s"component with $specMsg must have $portMsg")
case SemanticError.NoPortAvailableForMatchedNumbering(loc1, loc2, matchingLoc) =>
Error.print (None) (s"no port available for matched numbering")
System.err.println("matched connections are specified here:")
System.err.println(loc1)
System.err.println(loc2)
printMatchingLoc(matchingLoc)
printNote("to be available, a port number must be in bounds and unassigned at each of the matched ports")
case SemanticError.OverlappingIdRanges(
baseId1, name1, loc1, baseId2, maxId2, name2, loc2
) =>
Error.print (None) (
s"base ID $baseId1 for instance $name1 lies inside the ID range [$baseId2, $maxId2] for instance $name2"
)
System.err.println(s"$name1 is defined here")
System.err.println(loc1)
System.err.println(s"$name2 is defined here")
System.err.println(loc2)
case SemanticError.PassiveAsync(loc, importLocs) =>
Error.print (Some(loc)) ("passive component may not have async input")
if (importLocs.nonEmpty) {
System.err.println(s"port instance was imported from here")
importLocs.reverse.map(System.err.println)
}
case SemanticError.PassiveStateMachine(loc) =>
Error.print (Some(loc)) ("passive component may not have a state machine instance")
case SemanticError.RedefinedSymbol(name, loc, prevLoc) =>
Error.print (Some(loc)) (s"redefinition of symbol ${name}")
System.err.println("previous definition is here:")
System.err.println(prevLoc)
case SemanticError.StateMachine.CallSiteTypeMismatch(
loc,
teKind,
teTy,
siteKind,
siteTy
) =>
Error.print (Some(loc)) (s"type mismatch at $teKind")
System.err.println(s"type of $teKind is $teTy")
System.err.println(s"type of $siteKind is $siteTy")
case SemanticError.StateMachine.DuplicateSignal(sigName, stateName, loc, prevLoc) =>
Error.print (Some(loc)) (s"duplicate use of signal $sigName in state $stateName")
System.err.println("previous use is here:")
System.err.println(prevLoc)
case SemanticError.StateMachine.InvalidInitialTransition(loc, msg, destLoc) =>
Error.print (Some(loc)) (msg)
destLoc.map(loc => {
System.err.println("target is defined here:")
System.err.println(loc)
})
case SemanticError.StateMachine.ChoiceCycle(loc, msg) =>
Error.print (Some(loc)) (msg)
case SemanticError.StateMachine.ChoiceTypeMismatch(
loc, toLoc1, to1, toLoc2, to2
) =>
Error.print (Some(loc)) (s"type mismatch at choice")
System.err.println(toLoc1)
System.err.println(s"type of transition is $to1")
System.err.println(toLoc2)
System.err.println(s"type of transition is $to2")
case SemanticError.StateMachine.UnreachableNode(name, loc) =>
Error.print (Some(loc)) (s"$name is unreachable")
case SemanticError.TooManyOutputPorts(loc, numPorts, arraySize, instanceLoc) =>
Error.print (Some(loc)) (s"too many ports connected here (found $numPorts, max is $arraySize)")
System.err.println("for this component instance:")
System.err.println(instanceLoc)
case SemanticError.TypeMismatch(loc, msg) => Error.print (Some(loc)) (msg)
case SemanticError.UndefinedSymbol(name, symbolKind, loc) =>
Error.print (Some(loc)) (s"symbol ${name} is not defined")
printNote(s"looking for a $symbolKind here")
case SemanticError.InterfaceImport(
importLoc,
err
) =>
Error.print (Some(importLoc)) (s"failed to import interface")
err.print
case SemanticError.UseDefCycle(loc, msg) => Error.print (Some(loc)) (msg)
case XmlError.ParseError(file, msg) => Error.printXml (file) (msg)
case XmlError.SemanticError(file, msg) => Error.printXml (file) (msg)
case AnnotatedError(error, note) =>
error.print
printNote(note)
}
}
}
/** An error with a note */
final case class AnnotatedError(error: Error, note: String) extends Error
/** A syntax error */
final case class SyntaxError(loc: Location, msg: String) extends Error
/** A code generation error */
object CodeGenError {
/** Duplicate C++ file path */
final case class DuplicateCppFile(file: String, loc: Location, prevLoc: Location) extends Error
/** Duplicate JSON file path */
final case class DuplicateJsonFile(file: String, loc: Location, prevLoc: Location) extends Error
/** Duplicate XML file path */
final case class DuplicateXmlFile(file: String, loc: Location, prevLoc: Location) extends Error
/** Empty struct */
final case class EmptyStruct(loc: Location) extends Error
}
/** An include error */
object IncludeError {
/** Include cycle */
final case class Cycle(loc: Location, msg: String) extends Error
}
/** A file error */
object FileError {
/** Cannot open file */
final case class CannotOpen(locOpt: Option[Location], name: String) extends Error
/** Cannot resolve path */
final case class CannotResolvePath(loc: Location, name: String) extends Error
}
/** An error representing several other errors */
final case class MultiError(errors: List[Error]) extends Error
/** A semantic error */
object SemanticError {
/** Empty array */
final case class EmptyArray(loc: Location) extends Error
/** Channel not in dictionary */
final case class ChannelNotInDictionary(
loc: Location,
channelName: String,
topologyName: String
) extends Error
/** Division by zero */
final case class DivisionByZero(loc: Location) extends Error
/** Duplicate connection at matched port */
final case class DuplicateConnectionAtMatchedPort(
loc: Location,
port: String,
portNum: Int,
prevLoc: Location,
matchingLoc: Location
) extends Error
/** Duplicate name in dictionary */
final case class DuplicateDictionaryName(
kind: String,
name: String,
loc: Location,
prevLoc: Location
) extends Error
/** Duplicate enum value */
final case class DuplicateEnumValue(
value: String,
loc: Location,
prevLoc: Location
) extends Error
/** Dupliate ID value */
final case class DuplicateIdValue(
value: String,
loc: Location,
prevLoc: Location
) extends Error
/** Duplicate init specifier */
final case class DuplicateInitSpecifier(
phase: Int,
loc: Location,
prevLoc: Location
) extends Error
/** Duplicate instance */
final case class DuplicateInstance(
name: String,
loc: Location,
prevLoc: Location
) extends Error
/** Duplicate telemetry channel limit */
final case class DuplicateLimit(
loc: Location,
prevLoc: Location
) extends Error
/** Duplicate matched connection */
final case class DuplicateMatchedConnection(
loc: Location,
prevLoc: Location,
matchingLoc: Location
) extends Error
/** Duplicate opcode value */
final case class DuplicateOpcodeValue(
value: String,
loc: Location,
prevLoc: Location
) extends Error
/** Duplicate output port */
final case class DuplicateOutputConnection(
loc: Location,
portNum: Int,
prevLoc: Location
) extends Error
/** Duplicate parameter */
final case class DuplicateParameter(
name: String,
loc: Location,
prevLoc: Location
) extends Error
/** Duplicate pattern */
final case class DuplicatePattern(
kind: String,
loc: Location,
prevLoc: Location
) extends Error
/** Duplicate port instance */
final case class DuplicatePortInstance(
name: String,
loc: Location,
importLocs: List[Location],
prevLoc: Location,
prevImportLocs: List[Location]
) extends Error
/** Duplicate state machine instance */
final case class DuplicateStateMachineInstance(
name: String,
loc: Location,
prevLoc: Location
) extends Error
/** Duplicate struct member */
final case class DuplicateStructMember(
name: String,
loc: Location,
prevLoc: Location
) extends Error
/** Duplicate telemetry packet set */
final case class DuplicateTlmPacketSet(
name: String,
loc: Location,
prevLoc: Location
) extends Error
/** Duplicate topology */
final case class DuplicateTopology(
name: String,
loc: Location,
prevLoc: Location
) extends Error
/** Duplicate interface */
final case class DuplicateInterface(
name: String,
loc: Location,
prevLoc: Location
) extends Error
/** Implicit duplicate connection at matched port */
final case class ImplicitDuplicateConnectionAtMatchedPort(
loc: Location,
port: String,
portNum: Int,
implyingLoc: Location,
matchingLoc: Location,
prevLoc: Location
) extends Error
/** Inconsistent dictionary specifiers in location specifiers */
final case class InconsistentDictionarySpecifier(
loc: Location,
prevLoc: Location,
) extends Error
/** Inconsistent location specifiers */
final case class InconsistentLocationPath(
loc: Location,
path: String,
prevLoc: Location,
prevPath: String
) extends Error
/** Incorrect dictionary specifier in location specifier */
final case class IncorrectDictionarySpecifier(
loc: Location,
defLoc: Location
) extends Error
/** Incorrect location specifiers */
final case class IncorrectLocationPath(
loc: Location,
specifiedPath: String,
actualLoc: Location
) extends Error
/** Invalid array size */
final case class InvalidArraySize(loc: Location, size: BigInt) extends Error
/** Invalid command */
final case class InvalidCommand(loc: Location, msg: String) extends Error
/** Invalid component instance */
final case class InvalidComponentInstance(
loc: Location,
instanceName: String,
topName: String
) extends Error
/** Invalid connection */
final case class InvalidConnection(
loc: Location,
msg: String,
fromLoc: Location,
toLoc: Location,
fromPortDefLoc: Option[Location] = None,
toPortDefLoc: Option[Location] = None
) extends Error
/** Invalid data products */
final case class InvalidDataProducts(
loc: Location,
msg: String
) extends Error
/** Invalid component instance definition */
final case class InvalidDefComponentInstance(
name: String,
loc: Location,
msg: String
) extends Error
/** Invalid enum constants */
final case class InvalidEnumConstants(loc: Location) extends Error
/** Invalid event */
final case class InvalidEvent(loc: Location, msg: String) extends Error
/** Invalid format string */
final case class InvalidFormatString(loc: Location, msg: String) extends Error
/** Invalid integer value */
final case class InvalidIntValue(
loc: Location,
v: BigInt,
msg: String
) extends Error
/** Invalid internal port */
final case class InvalidInternalPort(loc: Location, msg: String) extends Error
/** Invalid connection pattern */
final case class InvalidPattern(
loc: Location,
msg: String
) extends Error
/** Invalid port instance */
final case class InvalidPortInstance(
loc: Location,
msg: String,
defLoc: Location
) extends Error
/** Invalid port instance identifier */
final case class InvalidPortInstanceId(
loc: Location,
portName: String,
componentName: String
) extends Error
/** Invalid port kind */
final case class InvalidPortKind(
loc: Location,
msg: String,
specLoc: Location
) extends Error
/** Invalid port matching */
final case class InvalidPortMatching(loc: Location, msg: String) extends Error
/** Invalid port number */
final case class InvalidPortNumber(
loc: Location,
portNumber: Int,
port: String,
size: Int,
specLoc: Location
) extends Error
/** Invalid priority specifier */
final case class InvalidPriority(loc: Location) extends Error
/** Invalid queue full specifier */
final case class InvalidQueueFull(loc: Location) extends Error
/** Invalid special port */
final case class InvalidSpecialPort(loc: Location, msg: String) extends Error
/** Invalid string size */
final case class InvalidStringSize(loc: Location, size: BigInt) extends Error
/** No member in struct type */
final case class InvalidStructMember(
memberName: String,
loc: Location,
structTypeName: String,
defLoc: Location
) extends Error
/** No member in anonymous struct type */
final case class InvalidAnonStructMember(
memberName: String,
loc: Location,
defLoc: Location
) extends Error
/** No member in anonymous struct type */
final case class InvalidTypeForMemberSelection(
memberName: String,
loc: Location,
typeName: String,
) extends Error
/** Invalid symbol */
final case class InvalidSymbol(
name: String,
loc: Location,
msg: String,
defLoc: Location
) extends Error
/** Invalid telemetry channel identifier name */
final case class InvalidTlmChannelName(
loc: Location,
channelName: String,
componentName: String
) extends Error
/** Invalid telemetry packet */
final case class InvalidTlmPacketSet(
loc: Location,
name: String,
msg: String
) extends Error
/** Invalid type */
final case class InvalidType(loc: Location, msg: String) extends Error
/** Mismatched port numbers */
final case class MismatchedPortNumbers(
p1Loc: Location,
p1Number: Int,
p2Loc: Location,
p2Number: Int,
matchingLoc: Location
) extends Error
/** Missing async input */
final case class MissingAsync(kind: String, loc: Location) extends Error
/** Missing connection */
final case class MissingConnection(
loc: Location,
matchingLoc: Location
) extends Error
/** Missing port */
final case class MissingPort(
loc: Location,
specMsg: String,
portmsg: String
) extends Error
final case class MissingPortMatching(
loc: Location
) extends Error
/** Matched port numbering could not find a valid port number */
final case class NoPortAvailableForMatchedNumbering(
loc1: Location,
loc2: Location,
matchingLoc: Location
) extends Error
/** Overlapping ID ranges */
final case class OverlappingIdRanges(
baseId1: BigInt,
name1: String,
loc1: Location,
baseId2: BigInt,
maxId2: BigInt,
name2: String,
loc2: Location
) extends Error
/** Error while importing an interface */
final case class InterfaceImport(
importLoc: Location,
err: Error
) extends Error
/** Passive async input */
final case class PassiveAsync(loc: Location, importLocs: List[Location]) extends Error
final case class PassiveStateMachine(loc: Location) extends Error
/** Redefined symbol */
final case class RedefinedSymbol(
name: String,
loc: Location,
prevLoc: Location
) extends Error
/** Lexer Error */
final case class InvalidToken(
loc: Location,
msg: String,
) extends Error
/** State machine semantic errors */
object StateMachine {
/** Call site type mismatch */
final case class CallSiteTypeMismatch(
loc: Location,
teKind: String,
teTy: String,
siteKind: String,
siteTy: String
) extends Error
/** Duplicate signal */
final case class DuplicateSignal(
sigName: String,
stateName: String,
loc: Location,
prevLoc: Location
) extends Error
/** Invalid initial transition specifier */
final case class InvalidInitialTransition(
loc: Location,
msg: String,
destLoc: Option[Location] = None
) extends Error
/** Choice cycle */
final case class ChoiceCycle(
loc: Location,
msg: String
) extends Error
/** Choice type mismatch */
final case class ChoiceTypeMismatch(
loc: Location,
toLoc1: Location,
to1: String,
tLoc2: Location,
to2: String
) extends Error
/** Unreachable node in the transition graph */
final case class UnreachableNode(
name: String,
loc: Location
) extends Error
}
/** Too many output ports */
final case class TooManyOutputPorts(
loc: Location,
numPorts: Int,
arraySize: Int,
instanceLoc: Location
) extends Error
/** Type mismatch */
final case class TypeMismatch(loc: Location, msg: String) extends Error
/** Undefined symbol */
final case class UndefinedSymbol(name: String, symbolKind: String, loc: Location) extends Error
/** Use-def cycle */
final case class UseDefCycle(loc: Location, msg: String) extends Error
}
/** An F Prime XML error */
object XmlError {
/** A parse error */
final case class ParseError(file: String, msg: String) extends Error
/** A semantic error */
final case class SemanticError(file: String, msg: String) extends Error
}
object Error {
/** The tool in use, if there is one */
private var toolOpt: Option[Tool] = None
/** Set the tool */
def setTool(t: Tool): Unit = { toolOpt = Some(t) }
/** Print an optional value */
def printOpt[T](opt: T): Unit = {
opt match {
case Some(t) => System.err.println(t.toString)
case _ => ()
}
}
/** Print the tool */
def printTool: Unit = printOpt(toolOpt)
/** Print an optional location and a message */
def print (locOpt: Option[Location]) (msg: String): Unit = {
printTool
printOpt(locOpt)
System.err.print("error: ")
System.err.println(msg)
}
/** Print an XML file and a message */
def printXml (file: String) (msg: String): Unit = {
printTool
System.err.println(s"file: $file")
System.err.print("error: ")
System.err.println(msg)
}
}