class Fancy
  class AST

    class Match < Node
      def initialize(line, expr, clauses)
        super(line)
        @expr = expr
        @clauses = clauses
      end

      def bytecode(g)
        pos(g)

        # create labels for each clause body.
        clause_labels = []
        @clauses.size.times do
          clause_labels << g.new_label
        end
        end_label = g.new_label

        # ok, let's emit the bytecode
        @expr.bytecode(g)

        @clauses.each_with_index do |c, i|
          g.dup # save the @expr since we need to reuse it
          c.match_expr.bytecode(g)
          g.swap
          g.send :":===", 1

          # if match_arg is given, get a localvar slot and set the
          # result of the === call to it
          if c.match_arg
            @match_arg_var = g.state.scope.new_local c.match_arg
            g.set_local @match_arg_var.slot
          end

          g.git clause_labels[i]
        end
        g.pop
        g.push_nil
        g.goto end_label

        clause_labels.each_with_index do |label, i|
          label.set!
          g.pop
          @clauses[i].val_expr.bytecode(g)

          # set match_arg local slot to nil, so it's only visible
          # within the case body
          if @match_arg_var
            g.push_nil
            g.set_local @match_arg_var.slot
            g.pop
          end

          g.goto end_label
        end

        end_label.set!
      end
    end

    class MatchClause < Node
      attr_reader :match_expr, :val_expr, :match_arg
      def initialize(line, match_expr, val_expr, match_args)
        super(line)
        if match_expr.kind_of?(Fancy::AST::Identifier) && match_expr.identifier == "_"
          match_expr = Fancy::AST::Identifier.new(match_expr.line, "Object")
        end
        @match_expr = match_expr
        @val_expr = val_expr

        # use name so we get the identifier as a symbol
        # for now, only use the first, we only support 1 match arg in the bootstrap compiler
        @match_arg = match_args.map(&:name).first
      end
    end

  end
end
