Prechádzať zdrojové kódy

Refactor Expression: Add prefix expression

xcbosa mbp16 2 rokov pred
rodič
commit
bf345d62ed

+ 12 - 4
XCTreeLang.xcodeproj/project.pbxproj

@@ -59,6 +59,8 @@
 		756916A22A28FE20005FF14B /* XCTLRuntimeTypeInstance.m in Sources */ = {isa = PBXBuildFile; fileRef = 756916A02A28FE20005FF14B /* XCTLRuntimeTypeInstance.m */; };
 		756916A52A28FF05005FF14B /* module.modulemap in Sources */ = {isa = PBXBuildFile; fileRef = 756916A42A28FF05005FF14B /* module.modulemap */; };
 		756916A72A28FF3D005FF14B /* module.modulemap in Sources */ = {isa = PBXBuildFile; fileRef = 756916A62A28FF3D005FF14B /* module.modulemap */; };
+		756916AA2A29A0B8005FF14B /* XCTLPrefixExpression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 756916A92A29A0B8005FF14B /* XCTLPrefixExpression.swift */; };
+		756916AC2A29A357005FF14B /* XCTLExpression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 756916AB2A29A357005FF14B /* XCTLExpression.swift */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -142,6 +144,8 @@
 		756916A02A28FE20005FF14B /* XCTLRuntimeTypeInstance.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XCTLRuntimeTypeInstance.m; sourceTree = "<group>"; };
 		756916A42A28FF05005FF14B /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		756916A62A28FF3D005FF14B /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
+		756916A92A29A0B8005FF14B /* XCTLPrefixExpression.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTLPrefixExpression.swift; sourceTree = "<group>"; };
+		756916AB2A29A357005FF14B /* XCTLExpression.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTLExpression.swift; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -214,22 +218,22 @@
 			isa = PBXGroup;
 			children = (
 				7520C4082A283B1E0010E7F8 /* VirtualStatement */,
+				7520C4002A283B1E0010E7F8 /* XCTLStatement.swift */,
+				7520C3FE2A283B1E0010E7F8 /* XCTLStatementType.swift */,
 				7520C3F82A283B1E0010E7F8 /* XCTLImportStatement.swift */,
+				7520C4032A283B1E0010E7F8 /* XCTLExportStatement.swift */,
 				7520C3F92A283B1E0010E7F8 /* XCTLImmediateStatement.swift */,
 				7520C3FA2A283B1E0010E7F8 /* XCTLLazyEqualStatement.swift */,
 				7520C3FB2A283B1E0010E7F8 /* XCTLRootStatement.swift */,
 				7520C3FC2A283B1E0010E7F8 /* XCTLNextthanStatement.swift */,
 				7520C3FD2A283B1E0010E7F8 /* XCTLInitStatement.swift */,
-				7520C3FE2A283B1E0010E7F8 /* XCTLStatementType.swift */,
 				7520C3FF2A283B1E0010E7F8 /* XCTLSwitchStatement.swift */,
-				7520C4002A283B1E0010E7F8 /* XCTLStatement.swift */,
 				7520C4012A283B1E0010E7F8 /* XCTLParagraphStatement.swift */,
 				7520C4022A283B1E0010E7F8 /* XCTLFunctionCallStatement.swift */,
-				7520C4032A283B1E0010E7F8 /* XCTLExportStatement.swift */,
 				7520C4042A283B1E0010E7F8 /* XCTLEqualthanStatement.swift */,
 				7520C4052A283B1E0010E7F8 /* XCTLMorethanStatement.swift */,
-				7520C4062A283B1E0010E7F8 /* XCTLElseStatement.swift */,
 				7520C4072A283B1E0010E7F8 /* XCTLLessthanStatement.swift */,
+				7520C4062A283B1E0010E7F8 /* XCTLElseStatement.swift */,
 				7520C40A2A283B1E0010E7F8 /* XCTLVariableRefStatement.swift */,
 				756916882A286A90005FF14B /* XCTLSetStatement.swift */,
 				7569168D2A2896FE005FF14B /* XCTLReturnStatement.swift */,
@@ -244,6 +248,8 @@
 			isa = PBXGroup;
 			children = (
 				7520C4092A283B1E0010E7F8 /* XCTLListStatement.swift */,
+				756916AB2A29A357005FF14B /* XCTLExpression.swift */,
+				756916A92A29A0B8005FF14B /* XCTLPrefixExpression.swift */,
 			);
 			path = VirtualStatement;
 			sourceTree = "<group>";
@@ -463,12 +469,14 @@
 				756916972A28DFE7005FF14B /* XCTLBreakStatement.swift in Sources */,
 				7520C4312A283B1E0010E7F8 /* XCTLRuntimeVariable.swift in Sources */,
 				756916912A28C46D005FF14B /* XCTLEnumerator.swift in Sources */,
+				756916AC2A29A357005FF14B /* XCTLExpression.swift in Sources */,
 				7520C42C2A283B1E0010E7F8 /* XCTLLessthanStatement.swift in Sources */,
 				7520C4332A283B1E0010E7F8 /* XCTLRuntimeVariableType.swift in Sources */,
 				7520C4202A283B1E0010E7F8 /* XCTLRootStatement.swift in Sources */,
 				756916932A28C4B6005FF14B /* XCTLRange.swift in Sources */,
 				7520C42A2A283B1E0010E7F8 /* XCTLMorethanStatement.swift in Sources */,
 				756916A52A28FF05005FF14B /* module.modulemap in Sources */,
+				756916AA2A29A0B8005FF14B /* XCTLPrefixExpression.swift in Sources */,
 				756916A72A28FF3D005FF14B /* module.modulemap in Sources */,
 				7520C4292A283B1E0010E7F8 /* XCTLEqualthanStatement.swift in Sources */,
 				7569168E2A2896FE005FF14B /* XCTLReturnStatement.swift in Sources */,

+ 32 - 0
XCTreeLang.xcodeproj/xcuserdata/xcbosa.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -244,5 +244,37 @@
             landmarkType = "7">
          </BreakpointContent>
       </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "E9505515-9E5C-4EFE-9B32-A48E0B2D4CFB"
+            shouldBeEnabled = "Yes"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "XCTreeLang/Statements/VirtualStatement/XCTLListStatement.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "45"
+            endingLineNumber = "45"
+            landmarkName = "parseStatement(fromLexerToSelf:fromParent:)"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "02E0C6D5-D1F2-4EC6-A561-65772D6F96C6"
+            shouldBeEnabled = "Yes"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "XCTreeLang/Statements/XCTLImportStatement.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "29"
+            endingLineNumber = "29"
+            landmarkName = "parseStatement(fromLexerToSelf:fromParent:)"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
    </Breakpoints>
 </Bucket>

+ 20 - 0
XCTreeLang/Runtime/XCTLRuntimeAbstractContext.swift

@@ -7,6 +7,24 @@
 
 import Foundation
 
+internal class XCTLRuntimeVariableStackFrame {
+    
+    private var stack = [XCTLRuntimeVariable]()
+    
+    internal func pushVariable(_ variable: XCTLRuntimeVariable) {
+        self.stack.append(variable)
+    }
+    
+    internal func popVariable() -> XCTLRuntimeVariable? {
+        self.stack.popLast()
+    }
+    
+    internal var isEmpty: Bool {
+        return self.stack.isEmpty
+    }
+    
+}
+
 internal protocol XCTLRuntimeAbstractContext: AnyObject {
     
     var nativeObjectInstance: NSObject { get }
@@ -34,4 +52,6 @@ internal protocol XCTLRuntimeAbstractContext: AnyObject {
     
     func getParentContext() -> XCTLRuntimeAbstractContext?
     
+    var variableStack: XCTLRuntimeVariableStackFrame { get set }
+    
 }

+ 2 - 0
XCTreeLang/Runtime/XCTLRuntimeContext.swift

@@ -243,4 +243,6 @@ internal class XCTLRuntimeContext: XCTLRuntimeAbstractContext {
         return nil
     }
     
+    var variableStack = XCTLRuntimeVariableStackFrame()
+    
 }

+ 2 - 0
XCTreeLang/Runtime/XCTLRuntimeSubContext.swift

@@ -133,4 +133,6 @@ internal class XCTLRuntimeSubContext: XCTLRuntimeAbstractContext {
         self.forFrame = frame
     }
     
+    var variableStack = XCTLRuntimeVariableStackFrame()
+    
 }

+ 30 - 0
XCTreeLang/Statements/VirtualStatement/XCTLExpression.swift

@@ -0,0 +1,30 @@
+//
+//  XCTLExpression.swift
+//  XCTreeLang
+//
+//  Created by 邢铖 on 2023/6/2.
+//
+
+import Foundation
+
+/// 表示语句的部分是向表达式栈推入值、消耗值还是不操作栈
+internal enum XCTLExpressionValue: Int {
+    /// 消耗值
+    case consume = -1
+    /// 推入值
+    case product = 1
+    /// 不操作表达式栈
+    case none = 0
+}
+
+internal protocol XCTLExpression {
+    
+    func parseStatement(fromLexerToSelf lex: XCTLLexer, fromParent: XCTLStatement?, terminatorType: XCTLTokenType) throws
+    
+}
+
+internal protocol XCTLExpressionPart {
+    
+    var expressionValue: XCTLExpressionValue { get }
+    
+}

+ 75 - 0
XCTreeLang/Statements/VirtualStatement/XCTLPrefixExpression.swift

@@ -0,0 +1,75 @@
+//
+//  XCTLPrefixExpression.swift
+//  XCTreeLang
+//
+//  Created by 邢铖 on 2023/6/2.
+//
+
+import Foundation
+
+internal class XCTLPrefixExpression: XCTLStatement, XCTLExpression {
+    
+    var type: XCTLStatementType { .expressionPrefix }
+    
+    var holdingObject: XCTLRuntimeVariable { .void }
+    
+    var parent: XCTLStatement?
+    
+    var statements = [XCTLStatement]()
+    
+    func matchSelfStatement(lex: XCTLLexer) throws -> XCTLStatement? {
+        fatalError("\(self.type.rawValue) can not parse automatically.")
+    }
+    
+    func parseStatement(fromLexerToSelf lex: XCTLLexer, fromParent: XCTLStatement?) throws {
+        fatalError("\(self.type.rawValue) can not parse automatically.")
+    }
+    
+    func parseStatement(fromLexerToSelf lex: XCTLLexer, fromParent: XCTLStatement?, terminatorType: XCTLTokenType) throws {
+        self.parent = fromParent
+        var stackValue = 0
+        while try lex.peek().type != terminatorType {
+            var stmt: XCTLStatement & XCTLExpressionPart
+            let position = lex.position
+            
+            do {
+                stmt = try self.parseNextStatement(forLexer: lex, prototypes: XCTLExpressionPrototypes) as! XCTLStatement & XCTLExpressionPart
+            } catch _ as XCTLCompileTimeError {
+                lex.position = position
+                break
+            }
+            
+            stackValue += stmt.expressionValue.rawValue
+            if stackValue > 1 {
+                lex.position = position
+                break
+            }
+            
+            self.statements.append(stmt)
+            
+            if stmt.type == .typeFunctionCall {
+                break
+            }
+        }
+    }
+    
+    func evaluate(inContext context: XCTLRuntimeAbstractContext) throws -> XCTLRuntimeVariable {
+        let originalVariableStack = context.variableStack
+        
+        let variableStack = XCTLRuntimeVariableStackFrame()
+        context.variableStack = variableStack
+        for it in statements {
+            _ = try it.evaluate(inContext: context)
+        }
+        guard let resultValue = variableStack.popVariable() else {
+            throw XCTLRuntimeError.variableStackNoObject
+        }
+        if !variableStack.isEmpty {
+            throw XCTLRuntimeError.variableStackNotEmptyAfterTerminator
+        }
+        
+        context.variableStack = originalVariableStack
+        return resultValue
+    }
+    
+}

+ 1 - 1
XCTreeLang/Statements/XCTLEqualthanStatement.swift

@@ -34,7 +34,7 @@ internal class XCTLEqualthanStatement : XCTLStatement {
         self.parent = fromParent
         self.condStmt = condStmt
         try lex.next()
-        self.compareValueStmt = try self.parseNextStatement(forLexer: lex)
+        self.compareValueStmt = try self.parseNextExpression(forLexer: lex, terminator: .typeOpenBrace)
         try self.childrenStmt.parseStatement(fromLexerToSelf: lex, fromParent: self)
     }
     

+ 1 - 1
XCTreeLang/Statements/XCTLForStatement.swift

@@ -43,7 +43,7 @@ public class XCTLForStatement: XCTLStatement {
             throw XCTLCompileTimeError.unexpectTokenInStatement(expect: XCTLTokenType.typeIn.rawValue, butGot: inToken.rawValue)
         }
         
-        self.enumeratorVariableStatement = try self.parseNextStatement(forLexer: lex, prototypes: XCTLExpressionPrototypes)
+        self.enumeratorVariableStatement = try self.parseNextExpression(forLexer: lex, terminator: .typeOpenBrace)
         
         try self.listStatement.parseStatement(fromLexerToSelf: lex, fromParent: self)
     }

+ 17 - 19
XCTreeLang/Statements/XCTLFunctionCallStatement.swift

@@ -7,20 +7,20 @@
 
 import Foundation
 
-internal class XCTLFunctionCallStatement: XCTLStatement {
+internal class XCTLFunctionCallStatement: XCTLStatement, XCTLExpressionPart {
     
     var type: XCTLStatementType { .typeFunctionCall }
     
+    var expressionValue: XCTLExpressionValue { .consume }
+    
     var holdingObject: XCTLRuntimeVariable { .void }
     
-    var functionName: String = ""
     var argumentStatements = [XCTLStatement]()
     
     weak var parent: XCTLStatement?
     
     func matchSelfStatement(lex: XCTLLexer) throws -> XCTLStatement? {
-        if try lex.next().type == .typeIdentifier,
-           try lex.next().type == .typeOpenBracket {
+        if try lex.next().type == .typeOpenBracket {
             return XCTLFunctionCallStatement()
         }
         return nil
@@ -28,35 +28,33 @@ internal class XCTLFunctionCallStatement: XCTLStatement {
     
     func parseStatement(fromLexerToSelf lex: XCTLLexer, fromParent: XCTLStatement?) throws {
         self.parent = fromParent
-//        try lex.next()
-        let identifier = try lex.next()
-        if identifier.type != .typeIdentifier {
-            throw XCTLCompileTimeError.unexpectTokenInStatement(expect: XCTLTokenType.typeIdentifier.rawValue, butGot: identifier.type.rawValue)
-        }
-        self.functionName = identifier.rawValue
-        let openBracket = try lex.next()
-        if openBracket.type != .typeOpenBracket {
-            throw XCTLCompileTimeError.unexpectTokenInStatement(expect: XCTLTokenType.typeOpenBracket.rawValue, butGot: identifier.type.rawValue)
-        }
+        
+        _ = try lex.next()
+        
         while try lex.peek().type != .typeCloseBracket {
-            self.argumentStatements.append(try self.parseNextStatement(forLexer: lex))
+            self.argumentStatements.append(try self.parseNextExpression(forLexer: lex))
         }
+        
         try lex.next()
     }
     
     func evaluate(inContext context: XCTLRuntimeAbstractContext) throws -> XCTLRuntimeVariable {
-        if let funcValue = context.value(forName: self.functionName) {
+        if let funcValue = context.variableStack.popVariable() {
             let arg = try argumentStatements.map({ try $0.evaluate(inContext: context) })
             if funcValue.type == .typeFuncImpl,
                let funcStmt = funcValue.rawFunctionStatement as? XCTLLateExecuteStatement {
-                return try funcStmt.doRealEvaluate(inContext: context, withArgs: arg)
+                let result = try funcStmt.doRealEvaluate(inContext: context, withArgs: arg)
+                context.variableStack.pushVariable(result)
+                return result
             }
             if funcValue.type != .typeFuncIntrinsic {
                 throw XCTLRuntimeError.unexpectedVariableType(expect: XCTLRuntimeVariableType.typeFuncIntrinsic.rawValue, butGot: funcValue.type.rawValue)
             }
-            return funcValue.executeFunc(arg: arg)
+            let result = funcValue.executeFunc(arg: arg)
+            context.variableStack.pushVariable(result)
+            return result
         }
-        throw XCTLRuntimeError.undefinedVariable(variableName: self.functionName)
+        throw XCTLRuntimeError.variableStackNoObject
     }
     
 }

+ 9 - 4
XCTreeLang/Statements/XCTLImmediateStatement.swift

@@ -7,10 +7,12 @@
 
 import Foundation
 
-internal class XCTLImmediateStatement: XCTLStatement {
+internal class XCTLImmediateStatement: XCTLStatement, XCTLExpressionPart {
     
     var type: XCTLStatementType { .typeImmediateValue }
     
+    var expressionValue: XCTLExpressionValue { .product }
+    
     var holdingObject: XCTLRuntimeVariable { .void }
     
     var immediateToken: XCTLToken = .eof
@@ -29,16 +31,19 @@ internal class XCTLImmediateStatement: XCTLStatement {
     }
     
     func evaluate(inContext context: XCTLRuntimeAbstractContext) throws -> XCTLRuntimeVariable {
+        var resultValue: XCTLRuntimeVariable
         switch immediateToken.type {
         case .typeImmediateString:
-            return .init(type: .typeString, rawValue: immediateToken.rawValue)
+            resultValue = .init(type: .typeString, rawValue: immediateToken.rawValue)
         case .typeImmediateNumber:
-            return .init(type: .typeNumber, rawValue: immediateToken.rawValue)
+            resultValue = .init(type: .typeNumber, rawValue: immediateToken.rawValue)
         case .typeImmediateBool:
-            return .init(type: .typeBoolean, rawValue: immediateToken.rawValue)
+            resultValue = .init(type: .typeBoolean, rawValue: immediateToken.rawValue)
         default:
             fatalError()
         }
+        context.variableStack.pushVariable(resultValue)
+        return resultValue
     }
     
 }

+ 1 - 1
XCTreeLang/Statements/XCTLLazyEqualStatement.swift

@@ -42,7 +42,7 @@ internal class XCTLLazyEqualStatement: XCTLStatement {
         if equalToken.type != .typeEqual {
             throw XCTLCompileTimeError.unexpectTokenInStatement(expect: XCTLTokenType.typeEqual.rawValue, butGot: equalToken.type.rawValue)
         }
-        self.equalToStatement = try self.parseNextStatement(forLexer: lex)
+        self.equalToStatement = try self.parseNextExpression(forLexer: lex)
     }
     
     func evaluate(inContext context: XCTLRuntimeAbstractContext) throws -> XCTLRuntimeVariable {

+ 1 - 1
XCTreeLang/Statements/XCTLLessthanStatement.swift

@@ -38,7 +38,7 @@ internal class XCTLLessthanStatement : XCTLStatement {
         self.parent = fromParent
         self.condStmt = condStmt
         try lex.next()
-        self.compareValueStmt = try self.parseNextStatement(forLexer: lex)
+        self.compareValueStmt = try self.parseNextExpression(forLexer: lex, terminator: .typeOpenBrace)
         try self.childrenStmt.parseStatement(fromLexerToSelf: lex, fromParent: self)
     }
     

+ 1 - 1
XCTreeLang/Statements/XCTLMorethanStatement.swift

@@ -38,7 +38,7 @@ internal class XCTLMorethanStatement : XCTLStatement {
         self.parent = fromParent
         self.condStmt = condStmt
         try lex.next()
-        self.compareValueStmt = try self.parseNextStatement(forLexer: lex)
+        self.compareValueStmt = try self.parseNextExpression(forLexer: lex, terminator: .typeOpenBrace)
         try self.childrenStmt.parseStatement(fromLexerToSelf: lex, fromParent: self)
     }
     

+ 1 - 1
XCTreeLang/Statements/XCTLReturnStatement.swift

@@ -41,7 +41,7 @@ internal class XCTLReturnStatement: XCTLStatement {
         
         try lex.next()
         
-        self.returnValueStatement = try self.parseNextStatement(forLexer: lex, prototypes: XCTLExpressionPrototypes)
+        self.returnValueStatement = try self.parseNextExpression(forLexer: lex)
     }
     
     func evaluate(inContext context: XCTLRuntimeAbstractContext) throws -> XCTLRuntimeVariable {

+ 1 - 1
XCTreeLang/Statements/XCTLSetStatement.swift

@@ -34,7 +34,7 @@ internal class XCTLSetStatement: XCTLStatement {
             throw XCTLCompileTimeError.unexpectTokenInStatement(expect: XCTLTokenType.typeEqual.rawValue, butGot: equalToken.type.rawValue)
         }
         
-        self.setToStatement = try self.parseNextStatement(forLexer: lex, prototypes: XCTLExpressionPrototypes)
+        self.setToStatement = try self.parseNextExpression(forLexer: lex)
     }
     
     func evaluate(inContext context: XCTLRuntimeAbstractContext) throws -> XCTLRuntimeVariable {

+ 7 - 3
XCTreeLang/Statements/XCTLStatement.swift

@@ -122,9 +122,7 @@ internal var XCTLStatementPrototypes: [XCTLStatement] = [
 internal var XCTLExpressionPrototypes: [XCTLStatement] = [
     XCTLFunctionCallStatement(),
     XCTLImmediateStatement(),
-    XCTLVariableRefStatement(),
-    XCTLSetStatement(),
-    XCTLReturnStatement()
+    XCTLVariableRefStatement()
 ]
 
 internal func XCTLStatementParseNextStatement(forLexer lex: XCTLLexer,
@@ -157,4 +155,10 @@ internal extension XCTLStatement {
         return try XCTLStatementParseNextStatement(forLexer: lex, fromParent: self, prototypes: prototypes)
     }
     
+    func parseNextExpression(forLexer lex: XCTLLexer, terminator: XCTLTokenType = .typeEOF) throws -> XCTLStatement & XCTLExpression {
+        let prefixExpr = XCTLPrefixExpression()
+        try prefixExpr.parseStatement(fromLexerToSelf: lex, fromParent: self, terminatorType: terminator)
+        return prefixExpr
+    }
+    
 }

+ 2 - 0
XCTreeLang/Statements/XCTLStatementType.swift

@@ -45,4 +45,6 @@ internal enum XCTLStatementType: String {
     case typeBreak
     case typeContinue
     
+    case expressionPrefix
+    
 }

+ 1 - 1
XCTreeLang/Statements/XCTLSwitchStatement.swift

@@ -32,7 +32,7 @@ internal class XCTLSwitchStatement: XCTLStatement, XCTLConditionParentStatement
     func parseStatement(fromLexerToSelf lex: XCTLLexer, fromParent: XCTLStatement?) throws {
         self.parent = fromParent
         try lex.next()
-        self.switchingObjectStmt = try self.parseNextStatement(forLexer: lex, prototypes: XCTLExpressionPrototypes)
+        self.switchingObjectStmt = try self.parseNextExpression(forLexer: lex, terminator: .typeOpenBrace)
         try self.childrenStmt.parseStatement(fromLexerToSelf: lex, fromParent: self)
     }
     

+ 4 - 1
XCTreeLang/Statements/XCTLVariableRefStatement.swift

@@ -7,10 +7,12 @@
 
 import Foundation
 
-internal class XCTLVariableRefStatement: XCTLStatement, XCTLBackableStatement {
+internal class XCTLVariableRefStatement: XCTLStatement, XCTLBackableStatement, XCTLExpressionPart {
     
     var type: XCTLStatementType { .typeVariableRef }
     
+    var expressionValue: XCTLExpressionValue { .product }
+    
     var holdingObject: XCTLRuntimeVariable { .void }
     
     var variableName: String = ""
@@ -65,6 +67,7 @@ internal class XCTLVariableRefStatement: XCTLStatement, XCTLBackableStatement {
             currentValue = newValue
             nextMemberStmt = nextStmt.nextVariableRefStmt
         }
+        context.variableStack.pushVariable(currentValue)
         return currentValue
     }
     

+ 3 - 0
XCTreeLang/XCTLRuntimeError.swift

@@ -27,5 +27,8 @@ public enum XCTLRuntimeError: Error {
     case variableNotImplementProtocol(protocolName: String)
     case unknownMethodForName(name: String)
     
+    case variableStackNoObject
+    case variableStackNotEmptyAfterTerminator
+    
 }