<commit_before>require "spec_helper"

require "atomy/codeloader"

describe "data kernel" do
  subject { Atomy::Module.new { use(require_kernel("data")) } }

  it "returns nil" do
    expect(subject.evaluate(ast("data(Point(@x, @y))"), subject.compile_context)).to be_nil
  end

  class DataParent
  end

  def self.it_defines(parent, klass, attrs = {})
    describe "the defined #{klass}" do
      let(:defined_klass) { subject.const_get(klass) }

      it "is constructed with the given arguments" do
        defined_klass.new(*attrs.values) # depends on hash order
      end

      it "has the correct superclass" do
        superclass = parent
        if superclass.is_a?(Symbol)
          superclass = subject.const_get(superclass)
        end

        expect(defined_klass.direct_superclass).to eq(superclass)
      end

      it "defines attribute accessors for each instance variable" do
        point = defined_klass.new(*attrs.values)

        attrs.each do |a, v|
          expect(point.public_send(a)).to eq(v)
        end
      end

      it "defines a prettier #inspect" do
        args = attrs.values.collect(&:to_s).join(", ")
        expect(defined_klass.new(*attrs.values).inspect).to eq("#{klass}(#{args})")
      end

      it "can be pattern-matched" do
        pats = attrs.keys.collect(&:to_s).join(", ")
        args = attrs.values.collect(&:to_s).join(", ")
        expect(subject.evaluate(seq("
          #{klass}(#{pats}) = #{klass} new(#{args})
          [#{pats}]
        "), subject.compile_context)).to eq(attrs.values)
      end

      unless attrs.empty?
        context "when infinitely recursive" do
          it "pretty-prints with dots at the recursion point" do
            point = defined_klass.new(*attrs.values)
            point.public_send(:"#{attrs.keys.first}=", point)
            value_args = attrs.values.collect(&:to_s)
            value_args[0] = "#{klass}(...)"
            values = value_args.join(", ")
            expect(point.inspect).to eq("#{klass}(#{values})")
          end
        end
      end
    end
  end

  describe "a class defined with no children and no parent" do
    before do
      subject.evaluate(ast("data(Point(@x, @y))"), subject.compile_context)
    end

    it_defines Object, :Point, x: 1, y: 2<commit_msg>add test showing data structures can be defined on<commit_after>require "spec_helper"

require "atomy/codeloader"

describe "data kernel" do
  subject { Atomy::Module.new { use(require_kernel("data")) } }

  it "returns nil" do
    expect(subject.evaluate(ast("data(Point(@x, @y))"), subject.compile_context)).to be_nil
  end

  class DataParent
  end

  def self.it_defines(parent, klass, attrs = {})
    describe "the defined #{klass}" do
      let(:defined_klass) { subject.const_get(klass) }

      it "is constructed with the given arguments" do
        defined_klass.new(*attrs.values) # depends on hash order
      end

      it "has the correct superclass" do
        superclass = parent
        if superclass.is_a?(Symbol)
          superclass = subject.const_get(superclass)
        end

        expect(defined_klass.direct_superclass).to eq(superclass)
      end

      it "defines attribute accessors for each instance variable" do
        point = defined_klass.new(*attrs.values)

        attrs.each do |a, v|
          expect(point.public_send(a)).to eq(v)
        end
      end

      it "defines a prettier #inspect" do
        args = attrs.values.collect(&:to_s).join(", ")
        expect(defined_klass.new(*attrs.values).inspect).to eq("#{klass}(#{args})")
      end

      it "can be pattern-matched" do
        pats = attrs.keys.collect(&:to_s).join(", ")
        args = attrs.values.collect(&:to_s).join(", ")
        expect(subject.evaluate(seq("
          #{klass}(#{pats}) = #{klass} new(#{args})
          [#{pats}]
        "), subject.compile_context)).to eq(attrs.values)
      end

      it "can be the target of a definition" do
        pats = attrs.keys.collect(&:to_s).join(", ")
        subject.evaluate(ast("def(#{klass}(#{pats}) some-method): .ok"), subject.compile_context)
        expect(defined_klass.new(*attrs.values).some_method).to eq(:ok)
        expect(Object.new).to_not respond_to(:some_method)
      end

      unless attrs.empty?
        context "when infinitely recursive" do
          it "pretty-prints with dots at the recursion point" do
            point = defined_klass.new(*attrs.values)
            point.public_send(:"#{attrs.keys.first}=", point)
            value_args = attrs.values.collect(&:to_s)
            value_args[0] = "#{klass}(...)"
            values = value_args.join(", ")
            expect(point.inspect).to eq("#{klass}(#{values})")
          end
        end
      end
    end
  end

  describe "a class defined with no children and no parent" do
    before do
      subject.evaluate(ast("data(Point(@x, @y))"), subject.compile_context)
    end

    it_defines Object, :Point, x: 1, y: 2
{'fraction_non_alphanumeric': 0.13505863323898099, 'fraction_numerical': 0.001213101496158512, 'mean_word_length': 2.5925925925925926, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5252911', 'n_tokens_mistral': 1532, 'n_tokens_neox': 1548, 'n_words': 363}