main
Alpha Chen 2 years ago
parent 437a2b9633
commit 6e6a79c84a

@ -1,5 +1,11 @@
module Lox module Lox
class Error < StandardError class Error < StandardError
attr_reader :token, :message
def initialize(token, message)
@token, @message = token, message
end
end end
class ParseError < Error class ParseError < Error
@ -8,16 +14,12 @@ module Lox
error = "Error" error = "Error"
error << " at #{where}" unless where.empty? error << " at #{where}" unless where.empty?
super("[line #{token.line}] #{error}: #{message}")
super(token, "[line #{token.line}] #{error}: #{message}")
end end
end end
class RuntimeError < Error RuntimeError = Class.new(Error)
attr_reader :token ResolverError = Class.new(Error)
def initialize(token, message)
@token = token
super(message)
end
end
end end

@ -1,3 +1,5 @@
require_relative "error"
module Lox module Lox
class Resolver class Resolver
@ -27,12 +29,21 @@ module Lox
nil nil
end 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 private
def with_block def with_block
@scopes.push({}) @scopes.unshift({})
yield yield
@scopes.pop @scopes.shift
end end
def declare(name) def declare(name)
@ -49,5 +60,13 @@ module Lox
scopes[name.lexeme] = true scopes[name.lexeme] = true
end 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
end end

Loading…
Cancel
Save