@@ -18,7 +18,6 @@ use crate::frame::{Scope, ScopeRef};
1818use crate :: pyobject:: {
1919AttributeProtocol , IdProtocol , PyContext , PyFuncArgs , PyObjectRef , PyResult , TypeProtocol ,
2020} ;
21- use std:: rc:: Rc ;
2221
2322#[ cfg( not( target_arch ="wasm32" ) ) ]
2423use crate :: stdlib:: io:: io_open;
@@ -191,12 +190,11 @@ fn builtin_eval(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
191190 vm,
192191 args,
193192 required =[ ( source, None ) ] ,
194- optional =[
195- ( _globals, Some ( vm. ctx. dict_type( ) ) ) ,
196- ( locals, Some ( vm. ctx. dict_type( ) ) )
197- ]
193+ optional =[ ( globals, None ) , ( locals, Some ( vm. ctx. dict_type( ) ) ) ]
198194) ;
199195
196+ let scope =make_scope ( vm, globals, locals) ?;
197+
200198// Determine code object:
201199let code_obj =if objtype:: isinstance ( source, & vm. ctx . code_type ( ) ) {
202200 source. clone ( )
@@ -215,8 +213,6 @@ fn builtin_eval(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
215213return Err ( vm. new_type_error ( "code argument must be str or code object" . to_string ( ) ) ) ;
216214} ;
217215
218- let scope =make_scope ( vm, locals) ;
219-
220216// Run the source:
221217 vm. run_code_obj ( code_obj. clone ( ) , scope)
222218}
@@ -228,12 +224,11 @@ fn builtin_exec(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
228224 vm,
229225 args,
230226 required =[ ( source, None ) ] ,
231- optional =[
232- ( _globals, Some ( vm. ctx. dict_type( ) ) ) ,
233- ( locals, Some ( vm. ctx. dict_type( ) ) )
234- ]
227+ optional =[ ( globals, None ) , ( locals, Some ( vm. ctx. dict_type( ) ) ) ]
235228) ;
236229
230+ let scope =make_scope ( vm, globals, locals) ?;
231+
237232// Determine code object:
238233let code_obj =if objtype:: isinstance ( source, & vm. ctx . str_type ( ) ) {
239234let mode = compile:: Mode :: Exec ;
@@ -252,26 +247,48 @@ fn builtin_exec(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
252247return Err ( vm. new_type_error ( "source argument must be str or code object" . to_string ( ) ) ) ;
253248} ;
254249
255- let scope =make_scope ( vm, locals) ;
256-
257250// Run the code:
258251 vm. run_code_obj ( code_obj, scope)
259252}
260253
261- fn make_scope ( vm : & mut VirtualMachine , locals : Option < & PyObjectRef > ) ->ScopeRef {
262- // handle optional global and locals
263- let locals =if let Some ( locals) = locals{
264- locals. clone ( )
265- } else {
266- vm. new_dict ( )
254+ fn make_scope (
255+ vm : & mut VirtualMachine ,
256+ globals : Option < & PyObjectRef > ,
257+ locals : Option < & PyObjectRef > ,
258+ ) ->PyResult < ScopeRef > {
259+ let dict_type = vm. ctx . dict_type ( ) ;
260+ let globals =match globals{
261+ Some ( arg) =>{
262+ if arg. is ( & vm. get_none ( ) ) {
263+ None
264+ } else {
265+ if vm. isinstance ( arg, & dict_type) ?{
266+ Some ( arg)
267+ } else {
268+ let arg_typ = arg. typ ( ) ;
269+ let actual_type = vm. to_pystr ( & arg_typ) ?;
270+ let expected_type_name = vm. to_pystr ( & dict_type) ?;
271+ return Err ( vm. new_type_error ( format ! (
272+ "globals must be a {}, not {}" ,
273+ expected_type_name, actual_type
274+ ) ) ) ;
275+ }
276+ }
277+ }
278+ None =>None ,
267279} ;
268280
269- // TODO: handle optional globals
270- // Construct new scope:
271- Rc :: new ( Scope {
272- locals,
273- parent : None ,
274- } )
281+ let current_scope = vm. current_scope ( ) ;
282+ let parent =match globals{
283+ Some ( dict) =>Some ( Scope :: new ( dict. clone ( ) , Some ( vm. get_builtin_scope ( ) ) ) ) ,
284+ None => current_scope. parent . clone ( ) ,
285+ } ;
286+ let locals =match locals{
287+ Some ( dict) => dict. clone ( ) ,
288+ None => current_scope. locals . clone ( ) ,
289+ } ;
290+
291+ Ok ( Scope :: new ( locals, parent) )
275292}
276293
277294fn builtin_format ( vm : & mut VirtualMachine , args : PyFuncArgs ) ->PyResult {