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) } }