99
1010
1111class LoxInstance :
12- def __init__ (self , class_ : "LoxClass" ) -> None :
12+ def __init__ (
13+ self , class_ : "LoxClass" , base_class_instance : "LoxInstance | None" = None
14+ ) -> None :
1315 self .class_ = class_
1416 self .fields : Dict [str , object ] = {}
17+ self .base_class_instance : LoxInstance | None = base_class_instance
1518
1619 def __str__ (self ) -> str :
1720 return f"<{ self .class_ .name ()} instance at 0x{ id (self ):x} >"
@@ -34,6 +37,18 @@ def get(self, name: Token, interpreter: "Interpreter") -> object:
3437 if name .string_repr in self .class_ .class_ .methods :
3538 return self .class_ .class_ .methods [name .string_repr ]
3639
40+ if self .base_class_instance is not None :
41+ try :
42+ return self .base_class_instance .get (name , interpreter )
43+ except RuntimeException as r :
44+ if str (r ).startswith ("Error: There is no attribute" ):
45+ raise RuntimeException (
46+ f'Error: There is no attribute "{ name .string_repr } " on an instance of class "{ self .class_ .name ()} "' ,
47+ token = name ,
48+ )
49+ else :
50+ raise r
51+
3752 raise RuntimeException (
3853 f'Error: There is no attribute "{ name .string_repr } " on an instance of class "{ self .class_ .name ()} "' ,
3954 token = name ,
@@ -49,12 +64,14 @@ def __init__(
4964 name_ : str ,
5065 methods : Dict [str , LoxFunction ],
5166 getters : Dict [str , LoxFunction ] = {},
67+ base_class : "LoxClass | None" = None ,
5268 ) -> None :
5369 LoxInstance .__init__ (self , Meta ())
5470 Callable .__init__ (self )
5571 self .name_ = name_
5672 self .methods = methods
5773 self .getters = getters
74+ self .base_class = base_class
5875
5976 def __str__ (self ) -> str :
6077 return f"<class { self .name_ } >"
@@ -71,11 +88,21 @@ def arity(self) -> int:
7188 return constructor .arity ()
7289
7390 @override
74- def call (self , interpreter : "Interpreter" , args : List [object ]) -> object :
75- instance = LoxInstance (class_ = self )
76- constructor = self .methods .get ("init" )
77- if constructor is not None :
78- constructor .bind (instance ).call (interpreter , args )
91+ def call (
92+ self ,
93+ interpreter : "Interpreter" ,
94+ args : List [object ],
95+ do_not_call_init : bool = False ,
96+ ) -> object :
97+ base_class_instance : LoxInstance | None = None
98+ if self .base_class :
99+ base_class_instance = self .base_class .call (interpreter , [], True ) # type: ignore
100+
101+ instance = LoxInstance (class_ = self , base_class_instance = base_class_instance )
102+ if not do_not_call_init :
103+ constructor = self .methods .get ("init" )
104+ if constructor is not None :
105+ constructor .bind (instance ).call (interpreter , args )
79106 return instance
80107
81108
@@ -86,6 +113,7 @@ def __init__(self) -> None:
86113 self .name_ = "Meta"
87114 self .methods : Dict [str , LoxFunction ] = {}
88115 self .getters : Dict [str , LoxFunction ] = {}
116+ self .base_class = None
89117
90118 def __str__ (self ) -> str :
91119 return f"<meta { self .name_ } >"
@@ -102,9 +130,15 @@ def arity(self) -> int:
102130 return constructor .arity ()
103131
104132 @override
105- def call (self , interpreter : "Interpreter" , args : List [object ]) -> object :
133+ def call (
134+ self ,
135+ interpreter : "Interpreter" ,
136+ args : List [object ],
137+ do_not_call_init : bool = False ,
138+ ) -> object :
106139 instance = LoxInstance (class_ = self )
107- constructor = self .methods .get ("init" )
108- if constructor is not None :
109- constructor .bind (instance ).call (interpreter , args )
140+ if not do_not_call_init :
141+ constructor = self .methods .get ("init" )
142+ if constructor is not None :
143+ constructor .bind (instance ).call (interpreter , args )
110144 return instance
0 commit comments