/
LoxInstance.swift
55 lines (48 loc) · 1.84 KB
/
LoxInstance.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//
// LoxInstance.swift
// slox
//
// Created by Danielle Kefford on 3/4/24.
//
class LoxInstance: Equatable {
// `klass` is what is used in the interpreter when we need
// to know the class of a particular instance. Every Lox
// instance, including Lox classes, need to have a non-nil
// parent class, and so we lazily construct one if the
// instance/class was initialized with a nil one, which will
// only ever happen for the class of a so-called metaclass.
// We do it lazily so we can avoid instantiating an infinite
// tower of parent instances of LoxClass.
private var _klass: LoxClass?
var klass: LoxClass {
if _klass == nil {
// Only metaclasses should ever have a `nil` value for `_klass`
let selfClass = self as! LoxClass
_klass = LoxClass(name: "\(selfClass.name) metaclass", superclass: nil, methods: [:])
}
return _klass!
}
var properties: [String: LoxValue] = [:]
/// - 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.
init(klass: LoxClass?) {
self._klass = klass
}
func get(propertyName: String) throws -> LoxValue {
if let propertyValue = self.properties[propertyName] {
return propertyValue
}
if let method = klass.findMethod(name: propertyName) {
let boundMethod = method.bind(instance: self)
return .userDefinedFunction(boundMethod)
}
throw RuntimeError.undefinedProperty(propertyName)
}
func set(propertyName: String, propertyValue: LoxValue) {
self.properties[propertyName] = propertyValue
}
static func == (lhs: LoxInstance, rhs: LoxInstance) -> Bool {
return lhs === rhs
}
}