diff --git a/ruby/lib/lox/resolver.rb b/ruby/lib/lox/resolver.rb index c52819c..25e14c6 100644 --- a/ruby/lib/lox/resolver.rb +++ b/ruby/lib/lox/resolver.rb @@ -33,7 +33,8 @@ module Lox @scopes.last["this"] = true stmt.methods.each do |method| - resolve_function(method, :METHOD) + decl = method.name.lexeme == "init" ? :INIT : :METHOD + resolve_function(method, decl) end define(stmt.name) @@ -59,9 +60,15 @@ module Lox end def visit_print(stmt) = resolve(stmt.expr) + def visit_return(stmt) raise ResolverError.new(stmt.keyword, "Can't return from top-level code.") if @current_func == :NONE - resolve(stmt.value) if stmt.value + + return unless stmt.value + + raise ResolverError.new(stmt.keyword, "Can't return a value from an initializer.") if @current_func == :INIT + + resolve(stmt.value) end def visit_var(stmt) diff --git a/ruby/test/lox/test_interpreter.rb b/ruby/test/lox/test_interpreter.rb index 849af6b..a3f5073 100644 --- a/ruby/test/lox/test_interpreter.rb +++ b/ruby/test/lox/test_interpreter.rb @@ -431,6 +431,24 @@ class TestInterpreter < Lox::Test var foo = Foo(); print foo.init(); SRC + + assert_raises Lox::ResolverError do + interpret(<<~SRC) + class Foo { + init() { + return "something else"; + } + } + SRC + end + + assert_interpreted "", <<~SRC + class Foo { + init() { + return; + } + } + SRC end private