1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
require_relative "expr"

module Lox
  module Stmt
    def self.stmt(name, *children)
      klass = Struct.new(name.to_s, *children) do
        def accept(visitor)
          klass = self.class.to_s.split("::").last.downcase
          visitor.send("visit_#{klass}", self)
        end
      end
      const_set(name, klass)
    end

    stmt :Block, :stmts
    stmt :Class, :name, :superclass, :methods
    stmt :Expr, :expr
    stmt :Function, :name, :params, :body
    stmt :If, :cond, :then, :else
    stmt :Print, :expr
    stmt :Return, :keyword, :value
    stmt :Var, :name, :initializer
    stmt :While, :cond, :body
  end
end