diff --git a/ruby/lib/lox/resolver.rb b/ruby/lib/lox/resolver.rb index 0683335..381efe9 100644 --- a/ruby/lib/lox/resolver.rb +++ b/ruby/lib/lox/resolver.rb @@ -32,6 +32,7 @@ module Lox with_superclass_scope = if stmt.superclass raise ResolverError.new(stmt.superclass.name, "A class can't inherit from itself.") if stmt.name.lexeme == stmt.superclass.name.lexeme + @current_class = :SUBCLASS resolve(stmt.superclass) ->(&block) { with_scope(super: true) { block.call } } else @@ -121,6 +122,9 @@ module Lox end def visit_super(expr) + raise ResolverError.new(expr.keyword, "Can't use 'super' outside of a class.") if @current_class == :NONE + raise ResolverError.new(expr.keyword, "Can't use 'super' in a class with no superclass.") if @current_class != :SUBCLASS + resolve_local(expr, expr.keyword) nil end diff --git a/ruby/test/lox/test_interpreter.rb b/ruby/test/lox/test_interpreter.rb index 446af71..237395c 100644 --- a/ruby/test/lox/test_interpreter.rb +++ b/ruby/test/lox/test_interpreter.rb @@ -528,6 +528,23 @@ class TestInterpreter < Lox::Test SRC end + def test_invalid_super + assert_raises Lox::ResolverError do + interpret(<<~SRC) + class Eclair { + cook() { + super.cook(); + print "Pipe full of crème pâtissière."; + } + } + SRC + end + + assert_raises Lox::ResolverError do + interpret("super.notEvenInAClass();") + end + end + private def assert_interpreted(expected, src)