lib/loxxy/back_end/resolver.rb in loxxy-0.2.06 vs lib/loxxy/back_end/resolver.rb in loxxy-0.3.00

- old
+ new

@@ -115,10 +115,13 @@ aWhileStmt.condition&.accept(aVisitor) end # A variable declaration adds a new variable to current scope def before_var_stmt(aVarStmt) + # Oddly enough, Lox allows the re-definition of a variable at top-level scope + return if scopes.size == 1 && scopes.last[aVarStmt.name] + declare(aVarStmt.name) end def after_var_stmt(aVarStmt) define(aVarStmt.name) @@ -136,11 +139,11 @@ # Variable expressions require their variables resolved def before_variable_expr(aVarExpr) var_name = aVarExpr.name if !scopes.empty? && (scopes.last[var_name] == false) - raise StandardError, "Can't read variable #{var_name} in its own initializer" + raise Loxxy::RuntimeError, "Can't read variable #{var_name} in its own initializer" end end def after_variable_expr(aVarExpr, aVisitor) resolve_local(aVarExpr, aVisitor) @@ -203,22 +206,21 @@ def end_scope scopes.pop end - # rubocop: disable Style/SoleNestedConditional def declare(aVarName) return if scopes.empty? curr_scope = scopes.last - if scopes.size > 1 # Not at top-level? # Oddly enough, Lox allows variable re-declaration at top-level - if curr_scope.include?(aVarName) - msg = "Error at '#{aVarName}': Already variable with this name in this scope." - raise Loxxy::RuntimeError, msg - end + if curr_scope.include?(aVarName) + msg = "Error at '#{aVarName}': Already variable with this name in this scope." + raise Loxxy::RuntimeError, msg + elsif curr_scope.size == 255 && current_function != :none + msg = "Error at '#{aVarName}': Too many local variables in function." + raise Loxxy::RuntimeError, msg end - # rubocop: enable Style/SoleNestedConditional # The initializer is not yet processed. # Mark the variable as 'not yet ready' = exists but may not be referenced yet curr_scope[aVarName] = false end