@@ -14,8 +14,9 @@ use ruby_prism::Node;
1414use super :: bytes_to_name;
1515use super :: calls:: install_method_call;
1616use super :: variables:: {
17- install_class_var_read, install_class_var_write, install_ivar_read, install_ivar_write,
18- install_local_var_read, install_local_var_write, install_self,
17+ install_class_var_read, install_class_var_write, install_global_var_read,
18+ install_global_var_write, install_ivar_read, install_ivar_write, install_local_var_read,
19+ install_local_var_write, install_self,
1920} ;
2021
2122/// Collect positional and keyword arguments from AST argument nodes.
@@ -81,6 +82,8 @@ pub(crate) enum NeedsChildKind<'a> {
8182 ClassVarWrite { cvar_name : String , value : Node < ' a > } ,
8283 /// Local variable write: need to process value, then call finish_local_var_write
8384 LocalVarWrite { var_name : String , value : Node < ' a > } ,
85+ /// Global variable write: need to process value, then call install_global_var_write
86+ GlobalVarWrite { gvar_name : String , value : Node < ' a > } ,
8487 /// Method call: need to process receiver, then call finish_method_call
8588 MethodCall {
8689 receiver : Node < ' a > ,
@@ -142,6 +145,19 @@ pub(crate) fn dispatch_simple(genv: &mut GlobalEnv, lenv: &mut LocalEnv, node: &
142145 } ;
143146 }
144147
148+ // Global variable read: $name
149+ // Ruby: uninitialized global variables are nil.
150+ // Register the nil vertex so repeated reads of the same uninitialized
151+ // variable reuse one vertex instead of allocating a new Source each time.
152+ if let Some ( gvar_read) = node. as_global_variable_read_node ( ) {
153+ let gvar_name = bytes_to_name ( gvar_read. name ( ) . as_slice ( ) ) ;
154+ let vtx = install_global_var_read ( genv, & gvar_name) . unwrap_or_else ( || {
155+ let nil_vtx = genv. new_source ( Type :: Nil ) ;
156+ install_global_var_write ( genv, gvar_name, nil_vtx)
157+ } ) ;
158+ return DispatchResult :: Vertex ( vtx) ;
159+ }
160+
145161 // self
146162 if node. as_self_node ( ) . is_some ( ) {
147163 return DispatchResult :: Vertex ( install_self ( genv) ) ;
@@ -226,6 +242,15 @@ pub(crate) fn dispatch_needs_child<'a>(node: &Node<'a>, source: &str) -> Option<
226242 } ) ;
227243 }
228244
245+ // Global variable write: $name = value
246+ if let Some ( gvar_write) = node. as_global_variable_write_node ( ) {
247+ let gvar_name = bytes_to_name ( gvar_write. name ( ) . as_slice ( ) ) ;
248+ return Some ( NeedsChildKind :: GlobalVarWrite {
249+ gvar_name,
250+ value : gvar_write. value ( ) ,
251+ } ) ;
252+ }
253+
229254 // Local variable write: x = value
230255 if let Some ( write_node) = node. as_local_variable_write_node ( ) {
231256 let var_name = bytes_to_name ( write_node. name ( ) . as_slice ( ) ) ;
@@ -329,6 +354,10 @@ pub(crate) fn process_needs_child(
329354 let value_vtx = super :: install:: install_node ( genv, lenv, changes, source, & value) ?;
330355 Some ( install_class_var_write ( genv, cvar_name, value_vtx) )
331356 }
357+ NeedsChildKind :: GlobalVarWrite { gvar_name, value } => {
358+ let value_vtx = super :: install:: install_node ( genv, lenv, changes, source, & value) ?;
359+ Some ( install_global_var_write ( genv, gvar_name, value_vtx) )
360+ }
332361 NeedsChildKind :: LocalVarWrite { var_name, value } => {
333362 let value_vtx = super :: install:: install_node ( genv, lenv, changes, source, & value) ?;
334363 Some ( finish_local_var_write ( genv, lenv, changes, var_name, value_vtx) )
0 commit comments