From ca32ed939900ff58204d465aad902af6873d0f97 Mon Sep 17 00:00:00 2001 From: quephird Date: Wed, 27 Mar 2024 15:42:15 -0700 Subject: [PATCH] `UserDefinedFunction` and `LoxInstance` now get assigned UUIDs upon instantiation so that hashing `LoxValue` makes more sense. --- slox/LoxInstance.swift | 4 ++++ slox/LoxValue.swift | 24 ++++++++++-------------- slox/UserDefinedFunction.swift | 16 ++++++++++++++++ 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/slox/LoxInstance.swift b/slox/LoxInstance.swift index 4dd3fbc..d2c1677 100644 --- a/slox/LoxInstance.swift +++ b/slox/LoxInstance.swift @@ -5,6 +5,8 @@ // Created by Danielle Kefford on 3/4/24. // +import Foundation + class LoxInstance { // `klass` is what is used in the interpreter when we need // to know the class of a particular instance. Every Lox @@ -24,12 +26,14 @@ class LoxInstance { return _klass! } var properties: [String: LoxValue] = [:] + var objectId: UUID /// - Parameter klass: The class this instance belongs to. /// Use `nil` if this instance *is* a class; the `klass` property /// will then instantiate a metaclass for it on demand. required init(klass: LoxClass?) { self._klass = klass + self.objectId = UUID() } func get(propertyName: String) throws -> LoxValue { diff --git a/slox/LoxValue.swift b/slox/LoxValue.swift index a0bf1c9..d40922e 100644 --- a/slox/LoxValue.swift +++ b/slox/LoxValue.swift @@ -117,7 +117,6 @@ enum LoxValue: CustomStringConvertible, Equatable, Hashable { } } - // NOTA BENE: This equality conformance is only for unit tests static func == (lhs: LoxValue, rhs: LoxValue) -> Bool { switch (lhs, rhs) { case (.string(let lhsString), .string(let rhsString)): @@ -132,6 +131,10 @@ enum LoxValue: CustomStringConvertible, Equatable, Hashable { return lhsBoolean == rhsBoolean case (.nil, .nil): return true + case (.userDefinedFunction(let leftFunc), .userDefinedFunction(let rightFunc)): + return leftFunc.objectId == rightFunc.objectId + case (.nativeFunction(let leftFunc), .nativeFunction(let rightFunc)): + return leftFunc == rightFunc case (.instance(let leftList as LoxList), .instance(let rightList as LoxList)): return leftList.elements == rightList.elements default: @@ -140,33 +143,26 @@ enum LoxValue: CustomStringConvertible, Equatable, Hashable { } // TODO: Check with Becca if this is even remotely sensible + // especially with the function and instance cases, as they + // don't make much sense as candidates for keys func hash(into hasher: inout Hasher) { switch self { case .string(let string): - hasher.combine("string") hasher.combine(string) case .double(let double): - hasher.combine("double") hasher.combine(double) case .int(let int): - hasher.combine("int") hasher.combine(int) case .boolean(let boolean): - hasher.combine("boolean") hasher.combine(boolean) case .nil: - hasher.combine("nil") + break case .userDefinedFunction(let userDefinedFunction): - hasher.combine("userDefinedFunction") - hasher.combine(userDefinedFunction.name) - hasher.combine(userDefinedFunction.params) + hasher.combine(userDefinedFunction.objectId) case .nativeFunction(let nativeFunction): - hasher.combine("nativeFunction") - hasher.combine(nativeFunction.hashValue) + hasher.combine(nativeFunction) case .instance(let instance): - hasher.combine("instance") - hasher.combine(instance.klass.name) - hasher.combine(instance.properties) + hasher.combine(instance.objectId) } } } diff --git a/slox/UserDefinedFunction.swift b/slox/UserDefinedFunction.swift index 0ade56a..da190e3 100644 --- a/slox/UserDefinedFunction.swift +++ b/slox/UserDefinedFunction.swift @@ -5,6 +5,8 @@ // Created by Danielle Kefford on 2/29/24. // +import Foundation + struct UserDefinedFunction: LoxCallable, Equatable { var name: String var params: [Token] @@ -14,6 +16,20 @@ struct UserDefinedFunction: LoxCallable, Equatable { var enclosingEnvironment: Environment var body: [ResolvedStatement] var isInitializer: Bool + var objectId: UUID + + init(name: String, + params: [Token], + enclosingEnvironment: Environment, + body: [ResolvedStatement], + isInitializer: Bool) { + self.name = name + self.params = params + self.enclosingEnvironment = enclosingEnvironment + self.body = body + self.isInitializer = isInitializer + self.objectId = UUID() + } func call(interpreter: Interpreter, args: [LoxValue]) throws -> LoxValue { let newEnvironment = Environment(enclosingEnvironment: enclosingEnvironment)