-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcallable.py
102 lines (77 loc) · 3.11 KB
/
callable.py
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
91
92
93
94
95
96
97
98
99
100
101
102
from abc import ABCMeta, abstractmethod
from stmt import Function
from environment import Environment
from tokens import Token
from typing import Dict, List
class ReturnBubble(Exception):
def __init__(self, value):
self.value = value
class HootCallable(metaclass=ABCMeta):
@abstractmethod
def call(self, interpreter, arguments: List, error_token: Token): pass
@abstractmethod
def arity(self, interpreter, arguments: List): pass
class HootInstance:
def __init__(self, klass):
self.klass = klass
self.fields = {}
def get(self, name: Token):
if name.lexeme in self.fields:
return self.fields[name.lexeme]
method = self.klass.find_method(name.lexeme)
if method != None:
return method.bind(self)
raise RuntimeError(name, f"Undefined property '{name.lexeme}'.")
def set_(self, name: Token, value):
self.fields[name.lexeme] = value
def __repr__(self):
return f"{self.klass.name} instance"
class HootClass(HootCallable):
def __init__(self, name, superclass, methods: Dict):
self.superclass = superclass
self.name = name
self.methods = methods
def find_method(self, name: str):
if name in self.methods:
return self.methods[name]
if self.superclass != None:
return self.superclass.find_method(name)
def call(self, interpreter, arguments: List, error_token: Token):
instance = HootInstance(self)
initializer = self.find_method("init")
if initializer != None:
initializer.bind(instance).call(
interpreter, arguments, error_token)
return instance
def arity(self, interpreter, arguments):
initializer = self.find_method("init")
if initializer == None:
return 0
return initializer.arity(interpreter, arguments)
def __repr__(self):
return self.name
class HootFunction(HootCallable):
def __init__(self, declaration: Function, closure: Environment, is_initializer: bool):
self.declaration = declaration
self.closure = closure
self.is_initializer = is_initializer
def bind(self, instance: HootInstance):
environment = Environment(self.closure)
environment.define("this", instance)
return HootFunction(self.declaration, environment, self.is_initializer)
def arity(self, interpreter, arguments):
return len(self.declaration.params)
def call(self, interpreter, arguments: List, error_token: Token):
environment = Environment(self.closure)
for idx, param in enumerate(self.declaration.params):
environment.define(param.lexeme, arguments[idx])
try:
interpreter.execute_block(self.declaration.body, environment)
except ReturnBubble as return_value:
if self.is_initializer:
return self.closure.get_at(0, "this")
return return_value.value
if self.is_initializer:
return self.closure.get_at(0, "this")
def __repr__(self):
return f"<fn {self.declaration.name.lexeme}>"