Class: WLang::HashScope

Inherits:
Object
  • Object
show all
Defined in:
lib/wlang/hash_scope.rb

Overview

Implements a scoping mechanism on top of a ruby hash (accessible through pairing). Such a scope mimics hashses for has_key?, [] and []= methods. A scope has an accessible parent. Scopes form a tree, the root being accessible using its natural accessor. Scope lookup (has_key? and []) uses the hierarchy to find accessible variables.

Branching a scope allows installing new variables that hide variables with the same name in the parent scope. Branching is made easy through the branch methods that accepts a block, passing the child as first argument:

scope = HashScope.new(:name => 'wlang')
puts scope[:name]    # prints 'wlang'
scope.branch(:name => 'other') do |child|
  puts child[:name]  # prints 'other'
end
puts scope[:name]    # prints 'wlang'

This branching mechanism is intended to be used to keep a current scope as instance variable of a using class:

# We create an initial scope at construction
def initialize
  @scope = HashScope.new
end

# Appends the current scope with new key/value pairs. Yields the block
# with the new scope and restore the original one after that.
def do_something_with_a_new_scope(hash = {})
  @scope = @scope.branch(:name => 'other')
    yield if block_given?
  @scope = @scope.parent
end

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (HashScope) initialize(pairing = nil, parent = nil)

Creates a scope instance with a parent and initial pairing through a Hash

Raises:

  • (ArgumentError)


47
48
49
50
51
# File 'lib/wlang/hash_scope.rb', line 47

def initialize(pairing = nil, parent = nil)
  raise ArgumentError, "Hash expected for pairing #{pairing.class} received" unless (pairing.nil? or Hash===pairing)
  @pairing = pairing || {}
  @parent = parent
end

Instance Attribute Details

- (Object) pairing (readonly)

The key/value pairing inside this scope



43
44
45
# File 'lib/wlang/hash_scope.rb', line 43

def pairing
  @pairing
end

- (Object) parent (readonly)

The parent scope, or nil if no such parent



40
41
42
# File 'lib/wlang/hash_scope.rb', line 40

def parent
  @parent
end

Instance Method Details

- (Object) [](key, delegate = true)

Returns the value associated to a key, delegating to parent if not found and allowed



66
67
68
# File 'lib/wlang/hash_scope.rb', line 66

def [](key, delegate = true)
  pairing.has_key?(key) ? pairing[key] : (delegate && parent && parent[key])
end

- (Object) []=(key, value)

Associates a key to a value inside this scope



71
72
73
# File 'lib/wlang/hash_scope.rb', line 71

def []=(key, value)
  pairing[key] = value
end

- (Object) branch(pairing = nil) {|child| ... }

Creates a new child scope and returns it. If a block is given, yields the block with the child scope

Yields:

  • (child)


77
78
79
80
81
# File 'lib/wlang/hash_scope.rb', line 77

def branch(pairing = nil)
  child = HashScope.new(pairing, self)
  yield child if block_given?
  child
end

- (Boolean) has_key?(key, delegate = true)

Checks if a key exists in this scope, delegating to parent if not found and allowed



60
61
62
# File 'lib/wlang/hash_scope.rb', line 60

def has_key?(key, delegate = true)
  pairing.has_key?(key) || (!delegate.nil? && !parent.nil? && parent.has_key?(key))
end

- (Object) root

Returns the root scope



54
55
56
# File 'lib/wlang/hash_scope.rb', line 54

def root
  @root ||= (parent ? parent.root : self)
end

- (Object) to_h

Converts this scope to a full hash with all variables



84
85
86
# File 'lib/wlang/hash_scope.rb', line 84

def to_h
  parent ? parent.to_h.merge(pairing) : pairing.dup
end