From 493a653b783aace3c5656caf1a10aae53ee93278 Mon Sep 17 00:00:00 2001 From: Shaunak Pagnis Date: Thu, 11 Oct 2018 11:31:30 -0400 Subject: [PATCH] Adds respond_to_missing? in classes where method_missing is implemented. Also uses guard clause instead of deep conditional nesting in scope.rb method_missing Also adds 'super' check in method_missing so that it doesn't blow on actual missing methods --- lib/rubex/data_type/type_def.rb | 9 +++++-- lib/rubex/symbol_table/scope.rb | 44 ++++++++++++++++----------------- spec/no_gil_spec.rb | 3 ++- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/lib/rubex/data_type/type_def.rb b/lib/rubex/data_type/type_def.rb index 78e1496..141eb3b 100644 --- a/lib/rubex/data_type/type_def.rb +++ b/lib/rubex/data_type/type_def.rb @@ -26,8 +26,13 @@ def base_type @old_type end - def method_missing(meth, *args, &block) - @old_type.send(meth, *args, &block) + def method_missing(method_name, *args, &block) + return super unless @old_type.respond_to?(method_name) + @old_type.send(method_name, *args, &block) + end + + def respond_to_missing?(method_name, *args) + @old_type.respond_to?(method_name) || super end end end diff --git a/lib/rubex/symbol_table/scope.rb b/lib/rubex/symbol_table/scope.rb index e509a5a..a3c652e 100644 --- a/lib/rubex/symbol_table/scope.rb +++ b/lib/rubex/symbol_table/scope.rb @@ -60,8 +60,8 @@ def declare_var(name: "", c_name: "", type: nil, value: nil, extern: false) end def declare_sue name:, c_name:, type:, extern: - entry = Rubex::SymbolTable::Entry.new( - name, c_name, type, nil) + entry = Rubex::SymbolTable::Entry.new( + name, c_name, type, nil) entry.extern = extern @entries[name] = entry @sue_entries << entry @@ -71,7 +71,7 @@ def declare_sue name:, c_name:, type:, extern: end def declare_type type:, extern: - entry = Rubex::SymbolTable::Entry.new(nil, nil, type, nil) + entry = Rubex::SymbolTable::Entry.new(nil, nil, type, nil) entry.extern = extern @type_entries << entry @@ -99,7 +99,7 @@ def add_carray name: ,c_name: ,dimension: ,type: ,value: nil # Add a Ruby class to the current scope. def add_ruby_class name: , c_name:, scope:, ancestor:, extern: - type = Rubex::DataType::RubyClass.new name, c_name, scope, ancestor + type = Rubex::DataType::RubyClass.new name, c_name, scope, ancestor entry = Rubex::SymbolTable::Entry.new name, c_name, type, nil entry.extern = extern @entries[name] = entry @@ -139,7 +139,7 @@ def allocate_temp type @temp_counter += 1 c_name = Rubex::TEMP_PREFIX + @temp_counter.to_s entry = Rubex::SymbolTable::Entry.new c_name, c_name, type, - Expression::Literal::CNull.new('NULL') + Expression::Literal::CNull.new('NULL') @entries[c_name] = entry @temp_entries << entry else @@ -157,7 +157,7 @@ def release_temp c_name def [] entry @entries[entry] or raise(Rubex::SymbolNotFoundError, - "Symbol #{entry} does not exist in this scope.") + "Symbol #{entry} does not exist in this scope.") end def has_entry? entry @@ -169,7 +169,7 @@ def find name return recursive_find(name, self) end - private + private def recursive_find name, scope if scope if scope.has_entry?(name) @@ -241,7 +241,7 @@ def initialize name, outer_scope # args - Rubex::AST::ArgumentList. Creates sym. table entries for args. def add_arg name:, c_name:, type:, value: - entry = Rubex::SymbolTable::Entry.new name, c_name, type, value + entry = Rubex::SymbolTable::Entry.new name, c_name, type, value check_entry name @entries[name] = entry @arg_entries << entry @@ -274,7 +274,7 @@ def upgrade_symbols_to_global end remove_global_from_local_entries - + @outer_scope.global_entries.each do |entry| entry.c_name = Rubex::GLOBAL_PREFIX + @name + entry.c_name end @@ -310,22 +310,22 @@ def upgrade_symbols_to_global # Therefore these variables get declared inside the begin block callback # as well. So whenever one of these Arrays is called for this particular # scope, we preturn an empty array so that nothing gets declared. - def method_missing meth, *args, &block - return [] if meth == :var_entries - ret = @outer_scope.send(meth, *args, &block) - if ret.is_a?(Rubex::SymbolTable::Entry) - if !ret.extern? - if !ret.type.c_function? && !ret.type.ruby_method? && - !ret.type.ruby_class? - @block_entries << ret - end - end - end - + def method_missing(method_name, *args, &block) + return super unless @outer_scope.respond_to?(method_name) + return [] if method_name == :var_entries + ret = @outer_scope.send(method_name, *args, &block) + return ret unless ret.is_a?(Rubex::SymbolTable::Entry) + return ret if ret.extern? + return ret if ret.type.c_function? || ret.type.ruby_method? || ret.type.ruby_class? + @block_entries << ret ret end - private + def respond_to_missing?(method_name, *args) + @outer_scope.respond_to?(method_name) || super + end + + private def remove_global_from_local_entries @outer_scope.arg_entries -= @outer_scope.global_entries diff --git a/spec/no_gil_spec.rb b/spec/no_gil_spec.rb index 8a5a928..fb3bc00 100644 --- a/spec/no_gil_spec.rb +++ b/spec/no_gil_spec.rb @@ -28,7 +28,8 @@ n = Thread.new { work_without_gil(N) } m = Thread.new { work_without_gil(N) } - n.join; m.join + n.join + m.join end end end