@@ -4,6 +4,7 @@ use core::fmt::Debug;
44use core:: ops:: { Add , Mul } ;
55use rustc_hash:: FxHashMap ;
66use std:: sync:: Arc ;
7+ use std:: cell:: RefCell ;
78
89pub struct Class ( Arc < Script > ) ;
910
@@ -16,7 +17,20 @@ pub(crate) struct Script {
1617#[ derive( Debug ) ]
1718pub struct Instance {
1819 script : Arc < Script > ,
19- variables : Box < [ Box < dyn ScriptType > ] > ,
20+ // TODO we have 3 options to solve the `A.foo() -> B.bar() -> A.foo()` problem:
21+ // * We use `Cell<Box<[_]>>`. This *should* have relatively little overhead but is
22+ // very unintuitive, and the second `A.foo()` call will only see old variable names.
23+ // It is also likely still less efficient than `RefCell` due to an extra alloc.
24+ // * We use `RefCell<Box<[_]>>`. This is arguably the most "Rusty" way in terms of
25+ // "don't alias stuff", but is not very intuitive compared to other languages
26+ // and may also end up being impractical.
27+ // * We use `Box<[Cell<_>]>`. This will allow mimicking other scripting languages in
28+ // terms of (expected) behaviour but may be less efficient than `RefCell`.
29+ // The second and third option should be measured for performance. If the latter is
30+ // fast enough (or perhaps even faster) we should use that.
31+ // For now, the second option is chosen as the third can't be undone without being a
32+ // massive breaking change.
33+ variables : RefCell < Box < [ Box < dyn ScriptType > ] > > ,
2034}
2135
2236#[ derive( Debug ) ]
@@ -29,10 +43,11 @@ pub enum CallError {
2943 IsEmpty ,
3044 InvalidOperator ,
3145 IncompatibleType ,
46+ AlreadyBorrowed ,
3247}
3348
3449pub trait ScriptType : Debug + Any {
35- fn call ( & mut self , function : & str , args : & [ & dyn ScriptType ] ) -> CallResult < CallError > ;
50+ fn call ( & self , function : & str , args : & [ & dyn ScriptType ] ) -> CallResult < CallError > ;
3651
3752 fn dup ( & self ) -> Box < dyn ScriptType > ;
3853
@@ -129,7 +144,7 @@ impl Class {
129144 pub fn instance ( & self ) -> Instance {
130145 Instance {
131146 script : self . 0 . clone ( ) ,
132- variables : Box :: new ( [ ] ) ,
147+ variables : RefCell :: new ( Box :: new ( [ ] ) ) ,
133148 }
134149 }
135150}
@@ -141,8 +156,12 @@ impl From<Script> for Class {
141156}
142157
143158impl ScriptType for Instance {
144- fn call ( & mut self , function : & str , args : & [ & dyn ScriptType ] ) -> CallResult < CallError > {
145- self . script . call ( function, & mut self . variables , args)
159+ fn call ( & self , function : & str , args : & [ & dyn ScriptType ] ) -> CallResult < CallError > {
160+ if let Ok ( mut vars) = self . variables . try_borrow_mut ( ) {
161+ self . script . call ( function, & mut vars, args)
162+ } else {
163+ Err ( CallError :: AlreadyBorrowed )
164+ }
146165 }
147166
148167 fn dup ( & self ) -> Box < dyn ScriptType > {
@@ -155,24 +174,27 @@ impl ScriptType for Instance {
155174}
156175
157176impl ScriptType for ( ) {
158- fn call ( & mut self , _: & str , _: & [ & dyn ScriptType ] ) -> CallResult < CallError > {
177+ fn call ( & self , _: & str , _: & [ & dyn ScriptType ] ) -> CallResult < CallError > {
159178 Err ( CallError :: IsEmpty )
160179 }
161180
162181 impl_dup ! ( ) ;
163182}
164183
165184impl ScriptType for isize {
166- fn call ( & mut self , _: & str , _: & [ & dyn ScriptType ] ) -> CallResult < CallError > {
185+ fn call ( & self , _: & str , _: & [ & dyn ScriptType ] ) -> CallResult < CallError > {
167186 todo ! ( )
168187 }
169188
170189 impl_dup ! ( ) ;
171190}
172191
173192impl ScriptType for f64 {
174- fn call ( & mut self , _: & str , _: & [ & dyn ScriptType ] ) -> CallResult < CallError > {
175- todo ! ( )
193+ fn call ( & self , func : & str , _: & [ & dyn ScriptType ] ) -> CallResult < CallError > {
194+ Ok ( Box :: new ( match func {
195+ "sqrt" => self . sqrt ( ) ,
196+ _ => return Err ( CallError :: UndefinedFunction ) ,
197+ } ) )
176198 }
177199
178200 impl_dup ! ( ) ;
@@ -193,23 +215,23 @@ impl ScriptType for f64 {
193215}
194216
195217impl ScriptType for Box < str > {
196- fn call ( & mut self , _: & str , _: & [ & dyn ScriptType ] ) -> CallResult < CallError > {
218+ fn call ( & self , _: & str , _: & [ & dyn ScriptType ] ) -> CallResult < CallError > {
197219 todo ! ( )
198220 }
199221
200222 impl_dup ! ( ) ;
201223}
202224
203225impl ScriptType for char {
204- fn call ( & mut self , _: & str , _: & [ & dyn ScriptType ] ) -> CallResult < CallError > {
226+ fn call ( & self , _: & str , _: & [ & dyn ScriptType ] ) -> CallResult < CallError > {
205227 todo ! ( )
206228 }
207229
208230 impl_dup ! ( ) ;
209231}
210232
211233impl ScriptType for String {
212- fn call ( & mut self , _: & str , _: & [ & dyn ScriptType ] ) -> CallResult < CallError > {
234+ fn call ( & self , _: & str , _: & [ & dyn ScriptType ] ) -> CallResult < CallError > {
213235 todo ! ( )
214236 }
215237
0 commit comments