-
Notifications
You must be signed in to change notification settings - Fork 0
/
Class.hpp
90 lines (80 loc) · 3.14 KB
/
Class.hpp
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#ifndef Class_h
#define Class_h
#include "Call.hpp"
#include <string>
#include <unordered_map>
class LoxInstance : public std::enable_shared_from_this<LoxInstance> {
std::shared_ptr<LoxClass> klass;
std::unordered_map<std::string,Value> fields;
public:
LoxInstance(std::shared_ptr<LoxClass> klass) : klass{ klass } {}
Value get(const std::string&);
void set(const std::string&, const Value&);
const std::string toString() const;
};
class LoxClass : public LoxCallable, public std::enable_shared_from_this<LoxClass> {
std::shared_ptr<LoxClass> superclass;
std::string name;
std::unordered_map<std::string,std::shared_ptr<LoxFunction>> methods;
friend const std::string LoxInstance::toString() const;
public:
LoxClass(const std::string& name, std::shared_ptr<LoxClass> superclass,
std::unordered_map<std::string,std::shared_ptr<LoxFunction>>&& methods)
: superclass{ superclass }, name{ name }, methods{ methods } {}
virtual Value call(const Interpreter&, const std::vector<std::shared_ptr<Expr>>&) override;
virtual const size_t arity() const override;
virtual const std::string toString() const override { return "<class " + name + '>'; }
Value findMethod(const std::string&) const;
};
inline Value LoxInstance::get(const std::string& name) {
if (auto iter = fields.find(name); iter != fields.end()) {
return iter->second;
}
Value method = klass->findMethod(name);
if (static_cast<ValueType>(method.index()) == ValueType::Callable) {
return std::dynamic_pointer_cast<LoxFunction>(
std::get<std::shared_ptr<LoxCallable>>(method))
->bind(shared_from_this());
}
throw Error("Undefined property \'" + name + "\'.");
}
inline void LoxInstance::set(const std::string& name, const Value& value) {
if (auto iter = fields.find(name); iter != fields.end()) {
iter->second = value;
}
else {
fields.insert({ name, value });
}
}
inline const std::string LoxInstance::toString() const {
return '<' + klass->name + " instance>";
}
inline Value LoxClass::findMethod(const std::string& name) const {
if (auto iter = methods.find(name); iter != methods.end()) {
return iter->second;
}
else if (superclass) {
return superclass->findMethod(name);
}
else {
return std::monostate{};
}
}
inline Value LoxClass::call(const Interpreter& interpreter, const std::vector<std::shared_ptr<Expr>>& arguments) {
auto instance = std::make_shared<LoxInstance>(shared_from_this());
auto initializer = findMethod("init");
if (static_cast<ValueType>(initializer.index()) == ValueType::Callable) {
std::dynamic_pointer_cast<LoxFunction>(get<std::shared_ptr<LoxCallable>>(initializer))->bind(instance)->call(interpreter, arguments);
}
return instance;
}
inline const size_t LoxClass::arity() const {
auto initializer = findMethod("init");
if (static_cast<ValueType>(initializer.index()) == ValueType::Callable) {
return std::dynamic_pointer_cast<LoxFunction>(get<std::shared_ptr<LoxCallable>>(initializer))->arity();
}
else {
return 0;
}
}
#endif // Class_h