XCTLForStatement.swift 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. //
  2. // XCTLForStatement.swift
  3. // XCTreeLang
  4. //
  5. // Created by 邢铖 on 2023/6/1.
  6. //
  7. import Foundation
  8. public class XCTLForStatement: XCTLStatement {
  9. var type: XCTLStatementType { .typeFor }
  10. var holdingObject: XCTLRuntimeVariable { .void }
  11. var parent: XCTLStatement?
  12. var iteratorName: String = ""
  13. var enumeratorVariableStatement: XCTLStatement!
  14. var listStatement = XCTLListStatement()
  15. func matchSelfStatement(lex: XCTLLexer) throws -> XCTLStatement? {
  16. if try lex.next().type == .typeFor {
  17. return XCTLForStatement()
  18. }
  19. return nil
  20. }
  21. func parseStatement(fromLexerToSelf lex: XCTLLexer, fromParent: XCTLStatement?) throws {
  22. self.parent = fromParent
  23. try lex.next()
  24. let iteratorNameToken = try lex.next()
  25. if iteratorNameToken.type != .typeIdentifier {
  26. throw XCTLCompileTimeError.unexpectTokenInStatement(expect: XCTLTokenType.typeIdentifier.rawValue, butGot: iteratorNameToken.rawValue)
  27. }
  28. self.iteratorName = iteratorNameToken.rawValue
  29. let inToken = try lex.next()
  30. if inToken.type != .typeIn {
  31. throw XCTLCompileTimeError.unexpectTokenInStatement(expect: XCTLTokenType.typeIn.rawValue, butGot: inToken.rawValue)
  32. }
  33. self.enumeratorVariableStatement = try self.parseNextExpression(forLexer: lex, terminator: .typeOpenBrace, prototypes: XCTLShortExpressionPrototypes)
  34. try self.listStatement.parseStatement(fromLexerToSelf: lex, fromParent: self)
  35. lex.lastStatement = self
  36. }
  37. func evaluate(inContext context: XCTLRuntimeAbstractContext) throws -> XCTLRuntimeVariable {
  38. let enumeratorVariable = try self.enumeratorVariableStatement.evaluate(inContext: context)
  39. if enumeratorVariable.type != .typeObject {
  40. throw XCTLRuntimeError.unexpectedVariableType(expect: XCTLRuntimeVariableType.typeObject.rawValue, butGot: enumeratorVariable.type.rawValue)
  41. }
  42. var enumerator: XCTLEnumerator!
  43. if let enumeratorImpl = enumeratorVariable.objectValue as? XCTLEnumerator {
  44. enumerator = enumeratorImpl
  45. }
  46. if let enumeratorProvider = enumeratorVariable.objectValue as? XCTLEnumeratorProvider {
  47. enumerator = enumeratorProvider.provideEnumerator()
  48. }
  49. if enumerator == nil {
  50. throw XCTLRuntimeError.variableNotImplementProtocol(protocolName: "XCTLEnumerator or XCTLEnumeratorProvider")
  51. }
  52. let context = context.makeSubContext()
  53. let listFrame = context.findListFrame()
  54. let forFrame = XCTLForStatementFrame()
  55. context.recordForFrame(forFrame)
  56. while true {
  57. let value = enumerator.moveNext()
  58. if value.type == .typeVoid {
  59. break
  60. }
  61. context.setValueIgnoreParent(value, forName: self.iteratorName)
  62. _ = try self.listStatement.evaluate(inContext: context)
  63. if forFrame.breakForEvaluate {
  64. break
  65. }
  66. if let listFrame = listFrame,
  67. listFrame.breakListEvaluate {
  68. break
  69. }
  70. }
  71. return .void
  72. }
  73. }