11.5.1
change qtlssvuynkwmzmmmqwxvyztywssnrmlu
commit 53f0df6f9e49679d53c035ed714a60d9623525d7
author Alpha Chen <alpha@kejadlen.dev>
date
parent uylvopro
diff --git a/ruby/lib/lox/resolver.rb b/ruby/lib/lox/resolver.rb
index 19520d6..ac5aa27 100644
--- a/ruby/lib/lox/resolver.rb
+++ b/ruby/lib/lox/resolver.rb
@@ -7,6 +7,7 @@ module Lox
       @interpreter = interpreter
 
       @scopes = []
+      @current_func = :NONE
     end
 
     def resolve(*resolvees)
@@ -29,7 +30,7 @@ module Lox
       declare(stmt.name)
       define(stmt.name)
 
-      resolve_function(stmt)
+      resolve_function(stmt, :FUNCTION)
       nil
     end
 
@@ -40,6 +41,7 @@ module Lox
 
     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
     end
 
@@ -106,15 +108,26 @@ module Lox
       @interpreter.resolve(expr, depth)
     end
 
-    def resolve_function(fn)
-      with_scope do
-        fn.params.each do |param|
-          declare(param)
-          define(param)
+    def resolve_function(fn, type)
+      with_func_type(type) do
+        with_scope do
+          fn.params.each do |param|
+            declare(param)
+            define(param)
+          end
+          resolve(*fn.body)
         end
-        resolve(*fn.body)
       end
     end
 
+    def with_func_type(type)
+      enclosing_func = @current_func
+      @current_func = type
+
+      yield
+
+      @current_func = enclosing_func
+    end
+
   end
 end
diff --git a/ruby/test/lox/test_resolver.rb b/ruby/test/lox/test_resolver.rb
index 5509e86..81706eb 100644
--- a/ruby/test/lox/test_resolver.rb
+++ b/ruby/test/lox/test_resolver.rb
@@ -51,6 +51,14 @@ class TestResolver < Lox::Test
     end
   end
 
+  def test_returning_from_top_level
+    assert_raises Lox::ResolverError do
+      resolve(<<~SRC)
+        return;
+      SRC
+    end
+  end
+
   private
 
   def assert_resolved(expected, src)