Module: Tins::DynamicScope

Includes:
Scope
Defined in:
lib/tins/dslkit.rb

Overview

A module that provides dynamic scope-based variable binding with hash contexts.

This module extends the basic Scope functionality to enable dynamic variable binding where variables can be set and accessed like methods, but stored in hash-based contexts. It’s particularly useful for building DSLs, template engines, and context-sensitive applications.

Examples:

Basic dynamic scoping

include Tins::DynamicScope

dynamic_scope do
  self.foo = "value"  # Sets variable in current scope
  puts foo           # => "value" (reads from current scope)
end

Nested scopes with variable shadowing

include Tins::DynamicScope

dynamic_scope do
  self.foo = "outer"
  dynamic_scope do
    self.foo = "inner"  # Shadows outer foo only in inner scope
    puts foo           # => "inner"
  end
  puts foo             # => "outer" (restored from outer scope)
end

Variable existence checking

include Tins::DynamicScope

dynamic_scope do
  assert_equal false, dynamic_defined?(:foo)
  self.foo = "value"
  assert_equal true, dynamic_defined?(:foo)
end

Defined Under Namespace

Classes: Context

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Scope

#scope, #scope_block, #scope_get, #scope_pop, #scope_push, #scope_reverse, #scope_top

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(id, *args) ⇒ Object

Handles method calls that don’t match existing methods.

This implements the core dynamic variable binding behavior:

  • For read operations (no arguments): Looks up the method name in active scopes and returns the value if found, otherwise delegates to super for normal method resolution

  • For write operations (one argument + = suffix): Sets the value in current scope

  • For all other cases: Delegates to super for normal method resolution

Parameters:

  • id (Symbol)

    The method name being called

  • args (Array)

    Arguments passed to the method

Returns:

  • (Object)

    The result of the dynamic variable access or delegation



1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
# File 'lib/tins/dslkit.rb', line 1127

def method_missing(id, *args)
  self.dynamic_scope_name ||= :variables
  if args.empty? and scope_reverse(dynamic_scope_name) { |c| c.key?(id) and return c[id] }
    super
  elsif args.size == 1 and id.to_s =~ /(.*?)=\Z/
    c = scope_top(dynamic_scope_name) or super
    c[$1] = args.first
  else
    super
  end
end

Instance Attribute Details

#dynamic_scope_nameObject

The name of the dynamic scope to use (defaults to :variables).



1091
1092
1093
# File 'lib/tins/dslkit.rb', line 1091

def dynamic_scope_name
  @dynamic_scope_name
end

Instance Method Details

#dynamic_defined?(id) ⇒ Boolean

Checks if a variable is defined in any active dynamic scope.

Parameters:

  • id (Symbol)

    The variable name to check

Returns:

  • (Boolean)

    true if the variable is defined in any active scope, false otherwise



1097
1098
1099
1100
1101
# File 'lib/tins/dslkit.rb', line 1097

def dynamic_defined?(id)
  self.dynamic_scope_name ||= :variables
  scope_reverse(dynamic_scope_name) { |c| c.key?(id) and return true }
  false
end

#dynamic_scope {|void| ... } ⇒ Object

Creates a new dynamic scope context.

This method pushes a new Context object onto the scope stack and yields to the provided block. When the block completes, the context is automatically popped from the stack.

Yields:

  • (void)

    The block to execute within the dynamic scope

Returns:

  • (Object)

    The result of the block execution



1111
1112
1113
1114
# File 'lib/tins/dslkit.rb', line 1111

def dynamic_scope(&block)
  self.dynamic_scope_name ||= :variables
  scope_block(Context.new, dynamic_scope_name, &block)
end