Class: Loxxy::BackEnd::SymbolTable

Inherits:
Object
  • Object
show all
Defined in:
lib/loxxy/back_end/symbol_table.rb

Overview

A symbol table is basically a mapping from a name onto an object that holds information associated with that name. It is a data structure that keeps track of variables and their respective environment where they are declared. The key requirements for the symbol are:

  • To perform fast lookup operations: given a name, retrieve the corresponding object.
  • To allow the efficient insertion of names and related information
  • To support the nesting of environments
  • To handle the entry environment and exit environment events,
  • To cope with variable redefinition in nested environment The terminology 'symbol table' comes from the compiler design community.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(anEnv = nil) ⇒ SymbolTable

Build symbol table with given environment as root.

Parameters:



32
33
34
35
# File 'lib/loxxy/back_end/symbol_table.rb', line 32

def initialize(anEnv = nil)
  @name2envs = {}
  init_root(anEnv) # Set default (global) environment
end

Instance Attribute Details

#current_envEnvironment (readonly)

Returns The current environment.

Returns:



28
29
30
# File 'lib/loxxy/back_end/symbol_table.rb', line 28

def current_env
  @current_env
end

#name2envsHash{String => Array<Environment>} (readonly)

Mapping between a name and the environment(s) where it is defined

Returns:



22
23
24
# File 'lib/loxxy/back_end/symbol_table.rb', line 22

def name2envs
  @name2envs
end

#rootEnvironment (readonly)

Returns The top-level environment (= root of environment tree).

Returns:

  • (Environment)

    The top-level environment (= root of environment tree)



25
26
27
# File 'lib/loxxy/back_end/symbol_table.rb', line 25

def root
  @root
end

Instance Method Details

#all_variablesObject

Return all variables defined in the current .. root chain. Variables are sorted top-down and left-to-right.



104
105
106
107
108
109
110
111
112
113
114
# File 'lib/loxxy/back_end/symbol_table.rb', line 104

def all_variables
  vars = []
  skope = current_env
  while skope
    vars_of_environment = skope.defns.select { |_, item| item.kind_of?(Variable) }
    vars = vars_of_environment.values.concat(vars)
    skope = skope.enclosing
  end

  vars
end

#empty?Boolean

Returns iff there is no entry in the symbol table

Returns:

  • (Boolean)


39
40
41
# File 'lib/loxxy/back_end/symbol_table.rb', line 39

def empty?
  name2envs.empty?
end

#enter_environment(anEnv) ⇒ Object

Use this method to signal the interpreter that a given environment to be a child of current environment and to be itself the new current environment.

Parameters:



46
47
48
49
50
51
52
53
# File 'lib/loxxy/back_end/symbol_table.rb', line 46

def enter_environment(anEnv)
  if anEnv.enclosing && (anEnv.enclosing != current_env)
    anEnv.predecessor = current_env
  else
    anEnv.enclosing = current_env
  end
  @current_env = anEnv
end

#insert(anEntry) ⇒ String

Add an entry with given name to current environment.

Parameters:

Returns:

  • (String)

    Internal name of the entry



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/loxxy/back_end/symbol_table.rb', line 79

def insert(anEntry)
  current_env.insert(anEntry)
  name = anEntry.name
  if name2envs.include?(name)
    name2envs[name] << current_env
  else
    name2envs[name] = [current_env]
  end

  anEntry.name
end

#leave_environmentObject

Raises:

  • (StandardError)


55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/loxxy/back_end/symbol_table.rb', line 55

def leave_environment
  unless current_env.embedding
    current_env.defns.each_pair do |nm, _item|
      environments = name2envs[nm]
      if environments.size == 1
        name2envs.delete(nm)
      else
        environments.pop
        name2envs[nm] = environments
      end
    end
  end
  raise StandardError, 'Cannot remove root environment.' if current_env == root

  if current_env.predecessor
    @current_env = current_env.predecessor
  else
    @current_env = current_env.enclosing
  end
end

#lookup(aName) ⇒ BackEnd::Variable

Search for the object with the given name

Parameters:

  • aName (String)

Returns:



94
95
96
97
98
99
100
# File 'lib/loxxy/back_end/symbol_table.rb', line 94

def lookup(aName)
  environments = name2envs.fetch(aName, nil)
  return nil if environments.nil?

  sc = environments.last
  sc.defns[aName]
end