@@ -102,9 +102,11 @@ public struct VisuStructSimulationState: Equatable, Sendable {
102102 public var variables : [ String : VisuStructSimulationValue ]
103103 public var outputLines : [ String ]
104104 public var inputRequest : VisuStructSimulationInputRequest ?
105- public var inputError : String ?
105+ /// Fehler zur letzten Eingabe (z. B. keine Zahl); Text in der App über `VisuStructSimulationNotice` lokalisieren.
106+ public var inputErrorNotice : VisuStructSimulationNotice ?
106107 public var lastTrace : String ?
107- public var message : String ?
108+ /// Hinweis nach dem letzten Schritt (Ende, Fehler); `nil` während die Simulation normal läuft.
109+ public var notice : VisuStructSimulationNotice ?
108110 /// Nach einem Fehler bleibt die Simulation auf dem fehlerhaften Schritt stehen, bis sie zurückgesetzt wird.
109111 public var isHalted : Bool
110112
@@ -113,22 +115,29 @@ public struct VisuStructSimulationState: Equatable, Sendable {
113115 variables : [ String : VisuStructSimulationValue ] = [ : ] ,
114116 outputLines : [ String ] = [ ] ,
115117 inputRequest : VisuStructSimulationInputRequest ? = nil ,
116- inputError : String ? = nil ,
118+ inputErrorNotice : VisuStructSimulationNotice ? = nil ,
117119 lastTrace : String ? = nil ,
118- message : String ? = nil ,
120+ notice : VisuStructSimulationNotice ? = nil ,
119121 isHalted : Bool = false
120122 ) {
121123 self . stepIndex = stepIndex
122124 self . variables = variables
123125 self . outputLines = outputLines
124126 self . inputRequest = inputRequest
125- self . inputError = inputError
127+ self . inputErrorNotice = inputErrorNotice
126128 self . lastTrace = lastTrace
127- self . message = message
129+ self . notice = notice
128130 self . isHalted = isHalted
129131 }
130132}
131133
134+ extension VisuStructSimulationState {
135+ /// Englischer Text von `notice` (Tests, Protokolle).
136+ public var message : String ? { notice ? . englishText }
137+ /// Englischer Text von `inputErrorNotice`.
138+ public var inputError : String ? { inputErrorNotice ? . englishText }
139+ }
140+
132141public struct VisuStructSimulationEngine : Equatable , Sendable {
133142 public private( set) var steps : [ VisuStructSimulationStep ]
134143 public private( set) var state : VisuStructSimulationState
@@ -157,7 +166,7 @@ public struct VisuStructSimulationEngine: Equatable, Sendable {
157166 public mutating func step ( ) {
158167 guard canStep else {
159168 if state . inputRequest == nil && ! state . isHalted {
160- state . message = " Simulation finished. "
169+ state . notice = . finished
161170 }
162171 return
163172 }
@@ -196,13 +205,13 @@ public struct VisuStructSimulationEngine: Equatable, Sendable {
196205 return
197206 }
198207 if state . inputRequest != nil {
199- state . message = nil
208+ state . notice = nil
200209 return
201210 }
202211 state . stepIndex += 1
203- state . message = state . stepIndex >= steps . count ? " Simulation finished. " : nil
212+ state . notice = state . stepIndex >= steps . count ? . finished : nil
204213 } catch {
205- state . message = error . localizedDescription
214+ state . notice = VisuStructSimulationNotice ( error )
206215 state . isHalted = true
207216 }
208217 }
@@ -214,13 +223,13 @@ public struct VisuStructSimulationEngine: Equatable, Sendable {
214223 try assignValue ( value , to : request . variableName )
215224 state . lastTrace = " \( request . variableName ) = input -> \( value . description ) "
216225 } catch {
217- state . inputError = error . localizedDescription
226+ state . inputErrorNotice = VisuStructSimulationNotice ( error )
218227 return
219228 }
220229 state . inputRequest = nil
221- state . inputError = nil
230+ state . inputErrorNotice = nil
222231 state . stepIndex += 1
223- state . message = state . stepIndex >= steps . count ? " Simulation finished. " : nil
232+ state . notice = state . stepIndex >= steps . count ? . finished : nil
224233 }
225234
226235 private static func parseInputValue ( _ rawValue : String , as valueType : VisuStructSimulationValueType ) throws -> VisuStructSimulationValue {
@@ -230,12 +239,12 @@ public struct VisuStructSimulationEngine: Equatable, Sendable {
230239 switch valueType {
231240 case . int :
232241 guard let value = Int ( trimmed ) else {
233- throw SimulationError . invalidInput ( " Please enter a whole number. " )
242+ throw SimulationError . invalidInput ( . wholeNumberExpected )
234243 }
235244 return . int ( value )
236245 case . double :
237246 guard let value = Double ( trimmed ) else {
238- throw SimulationError . invalidInput ( " Please enter a number. " )
247+ throw SimulationError . invalidInput ( . numberExpected )
239248 }
240249 return . double ( value )
241250 case . string :
@@ -346,7 +355,7 @@ public struct VisuStructSimulationEngine: Equatable, Sendable {
346355 steps . remove ( at : state . stepIndex )
347356 steps . insert ( contentsOf : branchSteps , at : state . stepIndex )
348357 state . lastTrace = " \( condition ) -> \( result ? " true " : " false " ) "
349- state . message = ! branchSteps . isEmpty ? nil : ( state . stepIndex >= steps . count ? " Simulation finished. " : nil )
358+ state . notice = ! branchSteps . isEmpty ? nil : ( state . stepIndex >= steps . count ? . finished : nil )
350359 }
351360
352361 private mutating func executeSwitchSelection ( _ step : VisuStructSimulationStep ) throws {
@@ -366,7 +375,7 @@ public struct VisuStructSimulationEngine: Equatable, Sendable {
366375 steps . remove ( at : state . stepIndex )
367376 steps . insert ( contentsOf : caseSteps , at : state . stepIndex )
368377 state . lastTrace = " \( selector ) -> \( selectedCase . name ) "
369- state . message = ! caseSteps . isEmpty ? nil : ( state . stepIndex >= steps . count ? " Simulation finished. " : nil )
378+ state . notice = ! caseSteps . isEmpty ? nil : ( state . stepIndex >= steps . count ? . finished : nil )
370379 }
371380
372381 private mutating func executeForLoopStart ( _ step : VisuStructSimulationStep ) throws {
@@ -419,7 +428,7 @@ public struct VisuStructSimulationEngine: Equatable, Sendable {
419428 steps . insert ( contentsOf : bodySteps + [ incrementStep , conditionStep ] , at : state . stepIndex )
420429 } else {
421430 steps . remove ( at : state . stepIndex )
422- state . message = state . stepIndex >= steps . count ? " Simulation finished. " : nil
431+ state . notice = state . stepIndex >= steps . count ? . finished : nil
423432 }
424433 }
425434
@@ -449,10 +458,10 @@ public struct VisuStructSimulationEngine: Equatable, Sendable {
449458 )
450459 steps . remove ( at : state . stepIndex )
451460 steps . insert ( contentsOf : bodySteps + [ conditionStep ] , at : state . stepIndex )
452- state . message = ! bodySteps . isEmpty ? nil : ( state . stepIndex >= steps . count ? " Simulation finished. " : nil )
461+ state . notice = ! bodySteps . isEmpty ? nil : ( state . stepIndex >= steps . count ? . finished : nil )
453462 } else {
454463 steps . remove ( at : state . stepIndex )
455- state . message = state . stepIndex >= steps . count ? " Simulation finished. " : nil
464+ state . notice = state . stepIndex >= steps . count ? . finished : nil
456465 }
457466 }
458467
@@ -469,7 +478,7 @@ public struct VisuStructSimulationEngine: Equatable, Sendable {
469478 )
470479 steps . remove ( at : state . stepIndex )
471480 steps . insert ( contentsOf : bodySteps + [ conditionStep ] , at : state . stepIndex )
472- state . message = ! bodySteps . isEmpty ? nil : ( state . stepIndex >= steps . count ? " Simulation finished. " : nil )
481+ state . notice = ! bodySteps . isEmpty ? nil : ( state . stepIndex >= steps . count ? . finished : nil )
473482 }
474483
475484 private mutating func executeDoUntilCondition ( _ step : VisuStructSimulationStep ) throws {
@@ -491,7 +500,7 @@ public struct VisuStructSimulationEngine: Equatable, Sendable {
491500 steps . insert ( contentsOf : bodySteps + [ conditionStep ] , at : state . stepIndex )
492501 } else {
493502 steps . remove ( at : state . stepIndex )
494- state . message = state . stepIndex >= steps . count ? " Simulation finished. " : nil
503+ state . notice = state . stepIndex >= steps . count ? . finished : nil
495504 }
496505 }
497506
@@ -509,14 +518,14 @@ public struct VisuStructSimulationEngine: Equatable, Sendable {
509518 steps . remove ( at : state . stepIndex )
510519 steps . insert ( contentsOf : bodySteps + [ loopStep ] , at : state . stepIndex )
511520 state . lastTrace = " true -> true "
512- state . message = ! bodySteps . isEmpty ? nil : " Infinite loop has no body. "
521+ state . notice = ! bodySteps . isEmpty ? nil : . infiniteLoopWithoutBody
513522 }
514523
515524 private mutating func execute ( statement rawText : String ) throws {
516525 let text = rawText . trimmingCharacters ( in : . whitespacesAndNewlines )
517526 if text . lowercased ( ) . hasPrefix ( " input: " ) {
518527 state . inputRequest = try parseInputRequest ( text )
519- state . inputError = nil
528+ state . inputErrorNotice = nil
520529 return
521530 }
522531
@@ -1343,20 +1352,53 @@ private enum SimulationError: LocalizedError, Equatable {
13431352 case invalidExpression ( String )
13441353 case unknownVariable ( String )
13451354 case divisionByZero
1346- case invalidInput ( String )
1355+ case invalidInput ( VisuStructSimulationNotice )
1356+
1357+ var notice : VisuStructSimulationNotice {
1358+ switch self {
1359+ case . unsupportedStatement ( let text ) : return . unsupportedStatement ( text )
1360+ case . invalidExpression ( let text ) : return . invalidExpression ( text )
1361+ case . unknownVariable ( let name ) : return . unknownVariable ( name )
1362+ case . divisionByZero : return . divisionByZero
1363+ case . invalidInput ( let notice ) : return notice
1364+ }
1365+ }
1366+
1367+ var errorDescription : String ? { notice . englishText }
1368+ }
1369+
1370+ /// Meldungen der Simulation, unabhängig von der Sprache; die App übersetzt sie.
1371+ public enum VisuStructSimulationNotice : Equatable , Sendable {
1372+ case finished
1373+ case infiniteLoopWithoutBody
1374+ case unsupportedStatement ( String )
1375+ case invalidExpression ( String )
1376+ case unknownVariable ( String )
1377+ case divisionByZero
1378+ case wholeNumberExpected
1379+ case numberExpected
1380+ /// Fehler aus einer anderen Quelle, nur als Text bekannt.
1381+ case other ( String )
1382+
1383+ init ( _ error : Error ) {
1384+ if let simulationError = error as? SimulationError {
1385+ self = simulationError . notice
1386+ } else {
1387+ self = . other ( error . localizedDescription )
1388+ }
1389+ }
13471390
1348- var errorDescription : String ? {
1391+ public var englishText : String {
13491392 switch self {
1350- case . unsupportedStatement ( let text ) :
1351- return " Unsupported statement: \( text ) "
1352- case . invalidExpression ( let text ) :
1353- return " Invalid expression: \( text ) "
1354- case . unknownVariable ( let name ) :
1355- return " Unknown variable: \( name ) "
1356- case . divisionByZero :
1357- return " Division by zero. "
1358- case . invalidInput ( let message ) :
1359- return message
1393+ case . finished : return " Simulation finished. "
1394+ case . infiniteLoopWithoutBody : return " Infinite loop has no body. "
1395+ case . unsupportedStatement ( let text ) : return " Unsupported statement: \( text ) "
1396+ case . invalidExpression ( let text ) : return " Invalid expression: \( text ) "
1397+ case . unknownVariable ( let name ) : return " Unknown variable: \( name ) "
1398+ case . divisionByZero : return " Division by zero. "
1399+ case . wholeNumberExpected : return " Please enter a whole number. "
1400+ case . numberExpected : return " Please enter a number. "
1401+ case . other ( let text ) : return text
13601402 }
13611403 }
13621404}
0 commit comments