|
|
|
@ -1,3 +1,5 @@
|
|
|
|
|
require_relative "error"
|
|
|
|
|
|
|
|
|
|
module Lox
|
|
|
|
|
class Resolver
|
|
|
|
|
|
|
|
|
@ -27,12 +29,21 @@ module Lox
|
|
|
|
|
nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def visit_variable(expr)
|
|
|
|
|
if !@scopes.empty? && @scopes.last[expr.name.lexeme] == false
|
|
|
|
|
raise ResolverError.new(expr.name, "Can't read local variable in its own initializer.")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
resolve_local(expr, expr.name)
|
|
|
|
|
nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
|
|
def with_block
|
|
|
|
|
@scopes.push({})
|
|
|
|
|
@scopes.unshift({})
|
|
|
|
|
yield
|
|
|
|
|
@scopes.pop
|
|
|
|
|
@scopes.shift
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def declare(name)
|
|
|
|
@ -49,5 +60,13 @@ module Lox
|
|
|
|
|
scopes[name.lexeme] = true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def resolve_local(expr, name)
|
|
|
|
|
scope_and_depth = @scopes.each.with_index.find {|scope, depth| scope.has_key?(name.lexeme) }
|
|
|
|
|
return unless scope_and_depth
|
|
|
|
|
|
|
|
|
|
scope, depth = scope_and_depth
|
|
|
|
|
@interpreter.resolve(expr, depth)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|