Class: Ikra::TypeInference::SymbolTable

Inherits:
Object
  • Object
show all
Defined in:
lib/types/inference/symbol_table.rb

Overview

This is a symbol table that stores type information about variables. Ruby has a “flat” variable scope in method, i.e., variables defined in loop bodies, if statement bodies, or begin nodes are also visible outside of them.

Every method/block has its own symbol table.

Defined Under Namespace

Classes: Variable

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSymbolTable

Returns a new instance of SymbolTable.



36
37
38
39
40
# File 'lib/types/inference/symbol_table.rb', line 36

def initialize
    # This is a mapping from variable names to Variable instances.
    @symbols = {}
    @return_type = Types::UnionType.new
end

Instance Attribute Details

#return_typeObject (readonly)

Returns the value of attribute return_type.



31
32
33
# File 'lib/types/inference/symbol_table.rb', line 31

def return_type
  @return_type
end

#symbolsObject (readonly)

For debug purposes



34
35
36
# File 'lib/types/inference/symbol_table.rb', line 34

def symbols
  @symbols
end

Instance Method Details

#[](variable_name) ⇒ Object



46
47
48
49
50
51
52
# File 'lib/types/inference/symbol_table.rb', line 46

def [](variable_name)
    if !has_variable?(variable_name)
        raise AssertionError.new("Variable #{variable_name} not defined")
    end

    return @symbols[variable_name].type
end

#clear!Object



42
43
44
# File 'lib/types/inference/symbol_table.rb', line 42

def clear!
    @symbols = {}
end

#declare_variable(variable_name, type: Types::UnionType.new, kind: :local) ⇒ Object

Declares a local variable and overwrites (shadows) existing variables (lexical variables). Use this method for method/block parameters.



119
120
121
122
# File 'lib/types/inference/symbol_table.rb', line 119

def declare_variable(variable_name, type: Types::UnionType.new, kind: :local)
    @symbols[variable_name] = Variable.new(type: Types::UnionType.new, kind: kind)
    expand_type(variable_name, type)
end

#ensure_variable_declared(variable_name, type: Types::UnionType.new, kind: :local) ⇒ Object

Declares a local variable. This method should be used only for regular local variables (not parameters). Does not shadow lexical variables.



108
109
110
111
112
113
114
115
# File 'lib/types/inference/symbol_table.rb', line 108

def ensure_variable_declared(variable_name, type: Types::UnionType.new, kind: :local)
    if !has_variable?(variable_name)
        declare_variable(variable_name, type: type, kind: kind)
    else
        # Extend type of variable
        expand_type(variable_name, type)
    end
end

#expand_return_type(type) ⇒ Object



98
99
100
# File 'lib/types/inference/symbol_table.rb', line 98

def expand_return_type(type)
    @return_type.expand(type)
end

#expand_type(variable_name, type) ⇒ Object



88
89
90
91
92
93
94
95
96
# File 'lib/types/inference/symbol_table.rb', line 88

def expand_type(variable_name, type)
    if !has_variable?(variable_name)
        raise AssertionError.new(
            "Attempt to expand type of variable #{variable_name} but not found in " +
            " symbol table")
    end

    @symbols[variable_name].type.expand(type)
end

#read!(variable_name) ⇒ Object



54
55
56
57
58
59
60
61
# File 'lib/types/inference/symbol_table.rb', line 54

def read!(variable_name)
    if !has_variable?(variable_name)
        raise AssertionError.new(
            "Variable #{variable_name} read but not found in symbol table")
    end

    @symbols[variable_name].read = true
end

#read_and_written_variablesObject



84
85
86
# File 'lib/types/inference/symbol_table.rb', line 84

def read_and_written_variables
    return read_variables + written_variables
end

#read_variablesObject



72
73
74
75
76
# File 'lib/types/inference/symbol_table.rb', line 72

def read_variables
    return @symbols.select do |k, v|
        v.read
    end.keys
end

#written!(variable_name) ⇒ Object



63
64
65
66
67
68
69
70
# File 'lib/types/inference/symbol_table.rb', line 63

def written!(variable_name)
    if !has_variable?(variable_name)
        raise AssertionError.new(
            "Variable #{variable_name} written but not found in symbol table")
    end

    @symbols[variable_name].written = true
end

#written_variablesObject



78
79
80
81
82
# File 'lib/types/inference/symbol_table.rb', line 78

def written_variables
    return @symbols.select do |k, v|
        v.written
    end.keys
end