summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/prism/ffi.rb29
-rw-r--r--lib/prism/parse_result.rb28
2 files changed, 55 insertions, 2 deletions
diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb
index eda61b3ead..35b91e41b2 100644
--- a/lib/prism/ffi.rb
+++ b/lib/prism/ffi.rb
@@ -478,10 +478,35 @@ module Prism
values << scopes.length
scopes.each do |scope|
+ locals = nil
+ forwarding = 0
+
+ case scope
+ when Array
+ locals = scope
+ when Scope
+ locals = scope.locals
+
+ scope.forwarding.each do |forward|
+ case forward
+ when :* then forwarding |= 0x1
+ when :** then forwarding |= 0x2
+ when :& then forwarding |= 0x4
+ when :"..." then forwarding |= 0x8
+ else raise ArgumentError, "invalid forwarding value: #{forward}"
+ end
+ end
+ else
+ raise TypeError, "wrong argument type #{scope.class.inspect} (expected Array or Prism::Scope)"
+ end
+
template << "L"
- values << scope.length
+ values << locals.length
+
+ template << "C"
+ values << forwarding
- scope.each do |local|
+ locals.each do |local|
name = local.name
template << "L"
values << name.bytesize
diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb
index e76ea7e17e..9a3e7c5b79 100644
--- a/lib/prism/parse_result.rb
+++ b/lib/prism/parse_result.rb
@@ -879,4 +879,32 @@ module Prism
freeze
end
end
+
+ # This object is passed to the various Prism.* methods that accept the
+ # `scopes` option as an element of the list. It defines both the local
+ # variables visible at that scope as well as the forwarding parameters
+ # available at that scope.
+ class Scope
+ # The list of local variables that are defined in this scope. This should be
+ # defined as an array of symbols.
+ attr_reader :locals
+
+ # The list of local variables that are forwarded to the next scope. This
+ # should by defined as an array of symbols containing the specific values of
+ # :*, :**, :&, or :"...".
+ attr_reader :forwarding
+
+ # Create a new scope object with the given locals and forwarding.
+ def initialize(locals, forwarding)
+ @locals = locals
+ @forwarding = forwarding
+ end
+ end
+
+ # Create a new scope with the given locals and forwarding options that is
+ # suitable for passing into one of the Prism.* methods that accepts the
+ # `scopes` option.
+ def self.scope(locals: [], forwarding: [])
+ Scope.new(locals, forwarding)
+ end
end