// // XCTLRuntimeVariable.swift // notebook // // Created by 邢铖 on 2023/5/18. // import Foundation public class XCTLRuntimeVariable: NSObject { public var type: XCTLRuntimeVariableType public var rawValue: String public var rawObject: NSObject? public var rawFunction: (([XCTLRuntimeVariable]) throws -> XCTLRuntimeVariable)? // public var leftValue: XCTLRuntimeVariable? // public var leftValueMemberName: String? internal weak var rawFunctionStatement: XCTLStatement? public func toString() -> String { if type == .typeFuncImpl || type == .typeFuncIntrinsic { return "Function" } if type == .typeObject { return self.rawObject?.description ?? "" } return self.rawValue } public class func variableFromSwiftAny(_ value: Any) throws -> XCTLRuntimeVariable { if value is NSNull { return .void } if let value = value as? String { return XCTLRuntimeVariable(type: .typeString, rawValue: value) } if let value = value as? Double { return XCTLRuntimeVariable(type: .typeNumber, rawValue: value.description) } if let value = value as? Bool { return XCTLRuntimeVariable(type: .typeBoolean, rawValue: value.description) } if let value = value as? NSObject { return XCTLRuntimeVariable(rawObject: value) } throw XCTLRuntimeError.callingTypeEncodingError } public init(type: XCTLRuntimeVariableType, rawValue: String) { self.type = type self.rawValue = rawValue self.rawObject = nil self.rawFunction = nil } public init(rawObject: NSObject) { self.type = .typeObject self.rawValue = "" self.rawObject = rawObject self.rawFunction = nil } public init(funcImpl: @escaping ([XCTLRuntimeVariable]) throws -> XCTLRuntimeVariable) { self.type = .typeFuncIntrinsic self.rawValue = "" self.rawObject = nil self.rawFunction = funcImpl } internal init(funcImplStmt: XCTLStatement) { self.type = .typeFuncImpl self.rawValue = "" self.rawObject = nil self.rawFunction = nil self.rawFunctionStatement = funcImplStmt } public var stringValue: String { return self.rawValue } public var intValue: Int { return Int(self.rawValue)! } public var doubleValue: Double { return Double(self.rawValue)! } public var boolValue: Bool { return Bool(self.rawValue)! } public var objectValue: NSObject { return self.rawObject! } public static var void: XCTLRuntimeVariable { return XCTLRuntimeVariable(type: .typeVoid, rawValue: "") } public var nativeValue: Any { switch self.type { case .typeVoid: return NSNull() case .typeObject: return self.objectValue case .typeString: return self.stringValue case .typeNumber: return self.doubleValue case .typeBoolean: return self.boolValue case .typeFuncIntrinsic: return self.rawFunction ?? NSNull() case .typeFuncImpl: return NSNull() } } public func nativeValue(typeId: Character) throws -> Any { switch typeId { case "i": guard let nativeValue = self.nativeValue as? Double else { throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: typeId.description, nativeType: self.type.rawValue) } return Int32(nativeValue) case "I": guard let nativeValue = self.nativeValue as? Double else { throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: typeId.description, nativeType: self.type.rawValue) } return UInt32(nativeValue) case "s": guard let nativeValue = self.nativeValue as? Double else { throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: typeId.description, nativeType: self.type.rawValue) } return Int16(nativeValue) case "S": guard let nativeValue = self.nativeValue as? Double else { throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: typeId.description, nativeType: self.type.rawValue) } return UInt16(nativeValue) case "f": guard let nativeValue = self.nativeValue as? Double else { throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: typeId.description, nativeType: self.type.rawValue) } return Float(nativeValue) case "d": guard let nativeValue = self.nativeValue as? Double else { throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: typeId.description, nativeType: self.type.rawValue) } return nativeValue case "l": guard let nativeValue = self.nativeValue as? Double else { throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: typeId.description, nativeType: self.type.rawValue) } return Int64(nativeValue) case "L": guard let nativeValue = self.nativeValue as? Double else { throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: typeId.description, nativeType: self.type.rawValue) } return UInt64(nativeValue) case "q": guard let nativeValue = self.nativeValue as? Double else { throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: typeId.description, nativeType: self.type.rawValue) } return Int64(nativeValue) case "Q": guard let nativeValue = self.nativeValue as? Double else { throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: typeId.description, nativeType: self.type.rawValue) } return UInt64(nativeValue) case "c": guard let nativeValue = self.nativeValue as? Double else { guard let nativeValue = self.nativeValue as? String else { throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: typeId.description, nativeType: self.type.rawValue) } return Int8((nativeValue.first ?? " ").utf8.first!) } return Int8(nativeValue) case "C": guard let nativeValue = self.nativeValue as? Double else { guard let nativeValue = self.nativeValue as? String else { throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: typeId.description, nativeType: self.type.rawValue) } return UInt8((nativeValue.first ?? " ").utf8.first!) } return UInt8(nativeValue) case "b": guard let nativeValue = self.nativeValue as? Bool else { throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: typeId.description, nativeType: self.type.rawValue) } return nativeValue case "@": guard let nativeValue = self.nativeValue as? NSObject else { throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: typeId.description, nativeType: self.type.rawValue) } return nativeValue default: throw XCTLRuntimeError.cannotCastObjectToNativeTypeWhenSetProperty(runtimeType: "\(typeId) (Unknown TypeId)", nativeType: self.type.rawValue) } } public func executeFunc(arg: [XCTLRuntimeVariable]) throws -> XCTLRuntimeVariable { return try self.rawFunction!(arg) } }