Class: Liquor::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/liquor/context.rb

Constant Summary collapse

RESERVED_NAMES =
%w(_env _buf _storage
__LINE__ __FILE__ __ENCODING__ BEGIN END alias and begin
break case class def do else elsif end ensure false for in
module next nil not or redo rescue retry return self super
then true undef when yield if unless while until).freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(compiler, externals) ⇒ Context

Returns a new instance of Context.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/liquor/context.rb', line 15

def initialize(compiler, externals)
  @compiler  = compiler
  @externals = externals

  @emitter   = Emitter.new(self)

  @variables = Set[]
  @var_stack = []

  @mapping   = {}
  @map_stack = []

  @retired   = Set[]

  @nesting   = 1

  @externals.each do |external|
    declare external
  end
end

Instance Attribute Details

#compilerObject (readonly)

Returns the value of attribute compiler.



5
6
7
# File 'lib/liquor/context.rb', line 5

def compiler
  @compiler
end

#emitterObject (readonly)

Returns the value of attribute emitter.



5
6
7
# File 'lib/liquor/context.rb', line 5

def emitter
  @emitter
end

#externalsObject (readonly)

Returns the value of attribute externals.



6
7
8
# File 'lib/liquor/context.rb', line 6

def externals
  @externals
end

#nestingObject (readonly)

Returns the value of attribute nesting.



7
8
9
# File 'lib/liquor/context.rb', line 7

def nesting
  @nesting
end

#variablesObject (readonly)

Returns the value of attribute variables.



6
7
8
# File 'lib/liquor/context.rb', line 6

def variables
  @variables
end

Instance Method Details

#access(name, loc = nil) ⇒ Object



87
88
89
90
91
92
93
94
95
# File 'lib/liquor/context.rb', line 87

def access(name, loc=nil)
  name = name.to_s

  if variable?(name)
    @mapping[name]
  else
    raise NameError.new("variable `#{name}' is undefined", loc)
  end
end

#allocated?(name) ⇒ Boolean

Returns:

  • (Boolean)


48
49
50
# File 'lib/liquor/context.rb', line 48

def allocated?(name)
  builtin?(name) || function?(name) || variable?(name)
end

#builtin?(name) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/liquor/context.rb', line 36

def builtin?(name)
  %w(true false null).include? name
end

#declare(name, loc = nil) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/liquor/context.rb', line 64

def declare(name, loc=nil)
  name   = name.to_s

  if builtin?(name) || function?(name)
    raise NameError.new("identifier `#{name}' is already occupied by #{type name}", loc)
  end

  shadow = @var_stack.count > 0 && @var_stack[-1].include?(name)

  if !@variables.include?(name) || shadow
    mapped, idx = name, 0
    while RESERVED_NAMES.include?(mapped) ||
          @mapping.values.include?(mapped) ||
          @retired.include?(mapped)
      mapped = "#{name}_m#{idx}" # `m' stands for `mangled'
      idx += 1
    end

    @variables.add name
    @mapping[name] = mapped
  end
end

#function?(name) ⇒ Boolean

Returns:

  • (Boolean)


40
41
42
# File 'lib/liquor/context.rb', line 40

def function?(name)
  @compiler.has_function? name
end

#nestObject



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/liquor/context.rb', line 97

def nest
  @var_stack.push @variables
  @variables = @variables.dup

  @map_stack.push @mapping
  @mapping = @mapping.dup

  @nesting  += 1

  yield
ensure
  @retired  += @mapping.values

  @variables = @var_stack.pop
  @mapping   = @map_stack.pop

  @nesting  -= 1
end

#type(name) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
# File 'lib/liquor/context.rb', line 52

def type(name)
  if builtin?(name)
    :builtin
  elsif function?(name)
    :function
  elsif variable?(name)
    :variable
  else
    :free
  end
end

#variable?(name) ⇒ Boolean

Returns:

  • (Boolean)


44
45
46
# File 'lib/liquor/context.rb', line 44

def variable?(name)
  @variables.include? name
end