[
  {
    "path": ".gitignore",
    "content": "#Logs\napplication/logs/*.php\n\n# Content types\n/application/xml/types/*.xml\n\n# Custom builds and generated php files\n/core/documentation/build\n/core/views/admin/content/translations.php\n\n# Attachs and cache files #\n*.tmp\n/attach/cache/\n/attach/\n/application/cache/_bancha/*.css\n/application/cache/_bancha/*.js\n\nGemfile.lock\n*.pyc\n*.doc\n*.txt\n\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: ruby\nrvm:\n  - 2.2.3\nscript:\n  - bundle exec rake\n"
  },
  {
    "path": "Gemfile",
    "content": "source 'https://rubygems.org'\n\ngroup :development, :test do\n  gem 'bundler'\n  gem 'rspec'\n  gem 'skeptic'\n  gem 'rake'\nend"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 Alexander Ivanov\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "[![Build Status](https://travis-ci.org/alehander42/hivemind.svg?branch=master)](https://travis-ci.org/alehander42/hivemind)\n[![MIT License](http://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\n# hivemind\n\nA prototype of a multi-syntax programming language.\n\nHivemind has a core language defined by its AST and configurable syntaxes acting like plugins.\n\nThe concept of \"syntax\" for hivemind is similar to\n\n* a theme for a text editor\n* a skin for a gui app\n* a json/html/xml template for a MVC web app\n\nSyntaxes are defined using code-like examples for core ast nodes and they act in a bidirectional way:\n  * they are used to parse source code using that syntax\n  * and to render code in that syntax\n  * **source in each syntax is automatically transltable to another syntax**\n\nTools for the language would also support representations of source grouped by class or methods or as a graph \n\nSyntaxes look like that:\n\nA pythonic syntax:\n\n```python\n#if_statement\nif <test>:\n    <true_branch>\nelse:\n    <else_branch>\n\n#assign\n<left> = <right>\n\n#call\n<function>(<<args:', '>>)\n\n#attribute\n<object>.<label>\n\n#attribute_assign\n<object>.<label> = <right>\n\n#binary\n<left> <operation> <right>\n\n#list\n[<<elements:', '>>]\n\n#method_statement\nmethod <method_name>(<<args:', '>>):\n    <<body>>\n\n#class_statement\nclass <class_name>:\n    <<methods:''>>\n\n#module_statement\nmodule <module_name>:\n    <<elements>>\n\n```\n\nA lisp-like syntax\n\n```\n#if_statement\n(if <test>\n    <true_branch>\n    <else_branch>)\n\n#assign\n(define <left> <right>)\n\n#method_statement\n(method <method_name> (<<args:' '>>)\n    <<body>>)\n\n#attribute\n<object>.<label>\n\n#attribute_assign\n(update <object>.<label> <right>)\n\n#binary\n(<operation> <left> <right>)\n\n#call\n(! <function> <<args:' '>>)\n\n#list\n_(<<elements:' '>>)\n\n#class_statement\n(class <class_name>\n    <<methods>>)\n\n#module_statement\n(module <module_name>\n    <<elements>>)\n```\n\n# Examples\n\n[pythonic example](examples/shape_pythonic.hm)\n[schemelike example](examples/shape_paren.hm)\n\n# Installation\n\n```\ngem install hivemind\n```\n\n# Usage\n\nRun a file\n\n```bash\nhivemind <filename>\n```\n\nTranslate a file into another syntax representation\n\n```bash\nhivemind render a.hm pythonic a2.hm\n```\n\n# Goals\n\n* Experiment with diffent syntaxes in different contexts\n* Use different sub-language seamlessly across the same codebase\n* A possible solution for the expression problem (just convert between different representations)\n\n\n# Language\n\nThe core language is just a simple python/ruby-like language for now.\n\n\n# History\n\nCreated for the HackFMI 5\n\n# Future development\n\n* fluid folder/file structure representations\n* editor plugins\n* more syntaxes\n\n## License\n\nCopyright 2016 [Alexander Ivanov](https://twitter.com/alehander42)\n\nDistributed under the MIT License.\n\n"
  },
  {
    "path": "Rakefile",
    "content": "require 'rubygems'\nrequire 'bundler'\nbegin\n  Bundler.setup(:default, :development)\nrescue Bundler::BundlerError => e\n  $stderr.puts e.message\n  $stderr.puts \"Run `bundle install` to install missing gems\"\n  exit e.status_code\nend\nrequire 'rake'\n\nrequire 'rspec/core'\nrequire 'rspec/core/rake_task'\nRSpec::Core::RakeTask.new(:spec) do |spec|\n  spec.pattern = FileList['spec/**/*_spec.rb']\nend\n\ntask :default => :spec\n"
  },
  {
    "path": "bin/hivemind",
    "content": "#!/usr/bin/env ruby\n\n$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))\n\nrequire 'hivemind'\n\nSYNTAXES_PATH = File.join(File.expand_path(File.join(File.dirname(__FILE__), '..')), 'syntaxes')\n\ndef astify(source, syntax)\n  parser, refs = Hivemind::Syntax.generate_syntax(syntax)\n  success, tree, _ = parser.parse(source, refs)\n  tree\nend\n\ndef syntax_file(f)\n  File.read(File.join(SYNTAXES_PATH, \"#{f}.syntax\"))\nend\n\nif ARGV.length == 1\n  filename = ARGV[0]\n  source = File.read(filename)\n  syntax_line, _, source = source.partition(\"\\n\")\n  if !syntax_line.start_with? 'syntax: '\n    puts \"file doesn't specify a syntax\"\n    exit 1\n  end\n  syntax = syntax_file(syntax_line.partition(': ').last)\n  tree = astify(source.lstrip, syntax)\n  vm = Hivemind::VM.new(tree)\n  result = vm.run Hivemind::Runtime::HivemindEnv\nelsif ARGV.length == 4\n  filename, second_syntax_name, save = ARGV[1..-1]\n  source = File.read(filename)\n  syntax_line, _, source = source.partition(\"\\n\")\n  if !syntax_line.start_with? 'syntax: '\n    puts \"first line of file doesn't specify a syntax\"\n    exit 1\n  end\n  first  = syntax_file(syntax_line.partition(': ').last)\n  second = syntax_file(second_syntax_name)\n  tree = astify(source.lstrip, first)\n  result = Hivemind::Renderer.new(tree, second).render\n  File.write(save, \"syntax: #{second_syntax_name}\\n\\n#{result}\")\nelse\n  puts <<-USAGE\n    hivemind <filename>\n      runs the file\n    hivemind render <filename> <syntax> <new_filename>\n      renders the source with <syntax>\n  USAGE\nend\n\n"
  },
  {
    "path": "examples/a.hm",
    "content": "syntax: pythonic\n\nclass Object:\n    method start(self):\n        e = 2\n        e.display()\n"
  },
  {
    "path": "examples/a_paren.hm",
    "content": "syntax: paren\n\n(class Rectangle\n    (method init (self a b)\n        (update self.a a)\n        (update self.b b))\n\n    (method area (self)\n        (* self.a self.b)))\n"
  },
  {
    "path": "examples/b.hm",
    "content": "syntax: pythonic\n\nclass Rectangle:\n    method init(self, a, b):\n        self.a = a\n        self.b = b\n\n    method area(self):\n        self.a * self.b\n"
  },
  {
    "path": "examples/shape.hm",
    "content": "syntax: pythonic\n\nclass Rectangle:\n    method init(self, a, b):\n        self.a = a\n        self.b = b\n\n    method area(self):\n        self.a * self.b\n\nclass Circle:\n    method init(self, r):\n        self.r = r\n\n    method area(self):\n        3.14 * self.r * self.r\n\nclass Object:\n    method start(self):\n        e = Rectangle.new(2, 4)\n        f = e.area()\n        f.display()\n        c = Circle.new(4)\n        g = c.area()\n        g.display()\n"
  },
  {
    "path": "examples/shape_paren.hm",
    "content": "syntax: paren\n\n(class Rectangle\n    (method init (self a b)\n        (update self.a a)\n        (update self.b b))\n\n    (method area (self)\n        (* self.a self.b)))\n\n(class Circle\n    (method init (self r)\n        (update self.r r))\n\n    (method area (self)\n        (* 3.14 (* self.r self.r))))\n\n(class Object\n    (method start (self)\n        (define e (! Rectangle.new 2 4))\n        (define f (! e.area ))\n        (! f.display )\n        (define c (! Circle.new 4))\n    (define g (! c.area ))\n        (! g.display )))\n\n"
  },
  {
    "path": "examples/shape_pythonic.hm",
    "content": "syntax: pythonic\n\nclass Rectangle:\n        method init(self, a, b):\n        self.a = a\n    self.b = b\n\n    method area(self):\n        self.a * self.b\n\nclass Circle:\n        method init(self, r):\n        self.r = r\n\n    method area(self):\n        3.14 * self.r * self.r\n\nclass Object:\n        method start(self):\n        e = Rectangle.new(2, 4)\n    f = e.area()\n    f.display()\n    c = Circle.new(4)\n    g = c.area()\n    g.display()\n\n"
  },
  {
    "path": "hivemind.gemspec",
    "content": "# Generated by jeweler\n# DO NOT EDIT THIS FILE DIRECTLY\n# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'\n# -*- encoding: utf-8 -*-\n# stub: skeptic 0.0.16 ruby lib\n\nGem::Specification.new do |s|\n  s.name = \"hivemind\"\n  s.version = \"0.1\"\n\n  s.required_rubygems_version = Gem::Requirement.new(\">= 0\") if s.respond_to? :required_rubygems_version=\n  s.require_paths = [\"lib\"]\n  s.authors = [\"Alexander Ivanov\"]\n  s.date = \"2016-03-12\"\n  s.description = \"A multi-syntax programming language\"\n  s.email = \"alehande42@gmail.com\"\n  s.executables = [\"hivemind\"]\n  s.extra_rdoc_files = [\n    \"LICENSE\",\n    \"README.md\"\n  ]\n  s.files = [\n    \"bin/hivemind\",\n    \"lib/hivemind.rb\",\n    \".gitignore\",\n    \"Gemfile\",\n    \"LICENSE\",\n    \"README.md\",\n    \"Rakefile\",\n    \"hivemind.gemspec\",\n    \"lib/hivemind/code_viewer.rb\",\n    \"lib/hivemind/combinators.rb\",\n    \"lib/hivemind/environment.rb\",\n    \"lib/hivemind/errors.rb\",\n    \"lib/hivemind/renderer.rb\",\n    \"lib/hivemind/runtime.rb\",\n    \"lib/hivemind/syntax.rb\",\n    \"lib/hivemind/universal_ast.rb\",\n    \"lib/hivemind/vm.rb\",\n    \"spec/spec_helper.rb\",\n    \"spec/hivemind/parser_spec.rb\",\n    \"spec/hivemind/vm_spec.rb\",\n    \"spec/hivemind/universal_ast_spec.rb\",\n    \"syntaxes/pythonic.syntax\",\n    \"syntaxes/lolcode.syntax\",\n    \"syntaxes/paren.syntax\"\n  ]\n  s.homepage = \"http://github.com/alehander42/hivemind\"\n  s.licenses = [\"MIT\"]\n  s.rubygems_version = \"2.4.8\"\n  s.summary = \"A multi-syntax language\"\n\n  s.add_development_dependency(%q<rspec>, [\"= 2.14.1\"])\n  s.add_development_dependency(%q<bundler>, [\">= 0\"])\n  s.add_development_dependency(%q<skeptic>, [\">= 0\"])\nend\n\n"
  },
  {
    "path": "lib/hivemind/code_viewer.rb",
    "content": "#  'universal_ast'\n\n# module Hivemind\n#   class CodeViewer\n#     def initialize(tree)\n#       @tree = tree\n#     end\n\n#     def view_as(query)\n#       hierarchy = QueryAnalyzer.parse(query)\n#       rebuild_tree(hierarchy)\n#     end\n\n#     def rebuild_tree(hierarchy)\n#       if hierarchy[0].type == @code_view.hierarchy[0].type\n#         # only sorting maybe\n#         # and sorting still not supported\n#         @tree\n#       else\n#         # method > code\n#         new_tree = UniversalAST::Image.new([])\n#         top = {}\n#         if hierarchy[0].type == :method\n#           @tree.statements.each do |statement|\n#             statement.methods.each do |method|\n#               top[method.method_name.value] ||= {}\n#               top[method.method_name.value][statement.class_name.value] = [args, method.body]\n#             end\n#           end\n#         else\n#            @tree.statements.each do |statement|\n#              statement.body.each do |method|\n#                top[method.class_name.value] ||= {}\n#                top[method.class_name.value][statement.method_name.value] = [args, method.body]\n#              end\n#            end\n#         end\n#       end\n#     end\n#   end\n# end\n"
  },
  {
    "path": "lib/hivemind/combinators.rb",
    "content": "require_relative 'universal_ast'\n\nclass Combinator\n  def &(other)\n    And.new(self, other)\n  end\n\n  def |(other)\n    Or.new(self, other)\n  end\nend\n\nclass Lit < Combinator\n  attr_reader :value\n\n  def initialize(value)\n    @value = value\n  end\n\n  def parse(input, refs)\n    if input.start_with?(@value)\n      [true, @value, input[@value.length.. -1]]\n    else\n      [false, '', input]\n    end\n  end\nend\n\nclass Mat < Combinator\n  attr_reader :regex\n\n  def initialize(regex)\n    @regex = /\\A#{regex}/\n  end\n\n  def parse(input, refs)\n    match = @regex.match(input)\n    if match\n      [true, input[0..match.to_s.size - 1], input[match.to_s.size.. -1]]\n    else\n      [false, '', input]\n    end\n  end\nend\n\nclass Binary < Combinator\n  attr_accessor :first, :second\n\n  def initialize(first, second)\n    @first, @second = first, second\n  end\nend\n\nclass And < Binary\n  def parse(input, refs)\n    first_success, first_result, remaining = @first.parse(input, refs)\n    if first_success\n      second_success, second_result, remaining  = @second.parse(remaining, refs)\n      if second_success\n        return [true, combine(first_result, second_result), remaining]\n      end\n    end\n    [false, [], input]\n  end\n\n  def combine(first_result, second_result)\n    if @first.is_a?(And)\n      first_result + [second_result]\n    else\n      [first_result, second_result]\n    end\n  end\nend\n\nclass Or < Binary\n  def parse(input, refs)\n    [@first, @second].each do |combinator|\n      success, result, remaining = combinator.parse(input, refs)\n      return [true, result, remaining] if success\n    end\n    [false, '', input]\n  end\nend\n\nclass Many < Combinator\n  attr_accessor :parser\n\n  def initialize(parser, as: nil)\n    @parser = parser\n  end\n\n  def parse(input, refs)\n    success = true\n    remaining = input\n    results = []\n    while success\n      success, result, remaining = @parser.parse(remaining, refs)\n      results.push(result) if success\n    end\n    [true, results, remaining]\n  end\nend\n\nclass Join < Combinator\n  attr_accessor :parser, :as\n\n  def initialize(parser, separator, as: nil)\n    @parser = parser\n    @separator = separator\n    @as = as.to_sym\n    @separator_parser = Lit.new(@separator) & Mat.new(/ */) #workaround hivemind\n    @@depth ||= 0\n  end\n\n  def parse(input, refs)\n    success = true\n    remaining = input\n    results = []\n    while success\n      # puts \"#{'  ' * @@depth}BEFORE \" + @parser.label.to_s\n      # p [\"  \" * @@depth, remaining]\n\n      # @@depth += 1\n      success, result, remaining = @parser.parse(remaining, refs)\n      # @@depth -= 1\n      # puts \"#{'  ' * @@depth}AFTER \" + @parser.label.to_s\n      # p [\"  \" * @@depth, success, remaining, results.length]\n      # puts\n\n      results.push(result) if success\n      if success\n        if remaining.start_with? '    (' # fix later\n          remaining = \"\\n#{remaining}\"\n        end\n        success, result, remaining = @separator_parser.parse(remaining, refs)\n      end\n    end\n    [true, results, remaining]\n  end\nend\n\nclass Ref < Combinator\n  attr_accessor :label\n\n  def initialize(label, as: nil)\n    @label = label\n    @as = as\n  end\n\n  def parse(input, refs)\n    ref_parser = refs[@label.to_sym]\n    ref_parser.parse(input, refs)\n  end\nend\n\nclass Maybe < Combinator\n  attr_accessor :parser\n\n  def initialize(parser)\n    @parser = parser\n  end\n\n  def parse(input, refs)\n    _, result, remaining = @parser.parse(input, refs)\n    [true, result, remaining]\n  end\nend\n\nclass Apply < Combinator\n  attr_accessor :parser\n  attr_reader :transformation\n\n  def initialize(parser, &transformation)\n    @parser, @transformation = parser, transformation\n  end\n\n  def parse(input, refs)\n    success, result, remaining = @parser.parse(input, refs)\n    result = @transformation.call(result) if success\n    [success, result, remaining]\n  end\nend\n\ndef literal(value)\n  Literal.new(value)\nend\n\ndef many(combinator)\n  Many.new(combinator)\nend\n\ndef maybe(combinator)\n  Maybe.new(combinator)\nend\n\ndef apply(combinator, &transformation)\n  Apply.new(combinator, &transformation)\nend\n\ndef match(regex)\n  Match.new(regex)\nend\n"
  },
  {
    "path": "lib/hivemind/environment.rb",
    "content": "require_relative 'errors'\n\nmodule Hivemind\n  class Environment\n    attr_reader :parent, :values, :top\n    attr_accessor :current_self\n\n    def initialize(parent, **values)\n      @parent, @values, @top = parent, values, (parent.nil? ? values : parent.top)\n    end\n\n    def [](key)\n      value = fetch key\n      return value if value\n      raise HivemindMissingNameError.new(\"#{key} is missing\")\n    end\n\n    def fetch(key)\n      current = self\n      until current.nil? || current.values.key?(key)\n        current = current.parent\n      end\n      return current.values[key] unless current.nil?\n      nil\n    end\n\n    def []=(key, value)\n      @values[key] = value\n    end\n  end\nend\n\n"
  },
  {
    "path": "lib/hivemind/errors.rb",
    "content": "module Hivemind\n  class HivemindMissingNameError < StandardError\n  end\n\n  class HivemindAccessError < StandardError\n  end\nend\n"
  },
  {
    "path": "lib/hivemind/renderer.rb",
    "content": "require_relative 'syntax'\n\nmodule Hivemind\n  \n  BASE_RULES = {\n    image: -> element, depth = 0 do\n      element.statements.map { |s| render_element(s) }.join(\"\\n\")\n    end,\n\n    int: -> element, depth = 0 do\n      element.value.to_s\n    end,\n\n    float: -> element, depth = 0 do\n      element.value.to_s\n    end,\n\n    string: -> element, depth = 0 do\n      '\"' + element.value.to_s + '\"'\n    end,\n\n    name: -> element, depth = 0 do\n      element.value.to_s\n    end,\n\n    operation: -> element, depth = 0 do\n      element.value.to_s\n    end\n  }\n\n  class Renderer\n    def initialize(tree, syntax)\n      @tree, @syntax = tree, syntax\n      @rules = BASE_RULES.merge(Syntax.load_rules(syntax))\n    end\n\n    def render(depth = 0)\n      render_element(@tree, depth).gsub(/\\n\\n+/, \"\\n\\n\").gsub(/\\)\\s+\\)/, '))').gsub(/\\}\\s+\\}/, '}}')\n    end\n\n    def offset(depth = 0)\n      '    ' * depth\n    end\n\n    def render_element(element, depth = 0)\n      rule = @rules[element.class.name.split('::').last.downcase.gsub('attributeassign', 'attribute_assign').gsub('statement', '_statement').to_sym]\n      depth += 1 if element.class.name.end_with?('MethodStatement')\n      # p \"for #{element.class.name.split('::').last.downcase.gsub('statement', '_statement').to_sym} #{depth}\"\n      offset(depth) + if rule.is_a?(String)\n        render_template rule, element, depth\n      elsif rule.is_a?(Proc)\n        instance_exec element, depth, &rule\n      end\n    end\n\n    def render_template(plan, element, depth = 0)\n      plan = plan.gsub(/\\<\\<([a-zA-Z_]+)\\:'([^\\']*)'\\>\\>/) do\n        element.send(Regexp.last_match[1]).map(&method(:render_element)).join(Regexp.last_match[2])\n      end\n      # p plan\n      plan = plan.gsub(/\\<\\<([a-zA-Z_]+)\\>\\>/) do\n        element.send(Regexp.last_match[1]).map { |e| render_element(e, depth) }.join(\"\\n\")\n      end\n      p plan\n      plan = plan.gsub(/\\<([a-zA-Z_]+)\\>/) do\n        render_element(element.send(Regexp.last_match[1]))\n      end\n      plan\n    end\n  end\nend\n"
  },
  {
    "path": "lib/hivemind/runtime.rb",
    "content": "require_relative 'environment'\n\nmodule Hivemind\n  module Runtime\n    class HivemindObject\n      attr_reader :data, :klass\n\n      def initialize(data, klass)\n      \t@data, @klass = data, klass\n      end\n    end\n\n    class HivemindClass\n      attr_reader :label, :methods, :parent\n\n      def initialize(label, parent = nil, methods = {})\n      \t@label, @parent, @methods = label, parent, methods\n      end\n\n      def define_hivemind_method(label, &handler)\n        @methods[label] = handler\n      end\n\n      def dispatch_method(label)\n        current = self\n        until current.nil? || current.methods.key?(label)\n          current = current.parent\n        end\n        !current ? nil : current.methods[label]\n      end\n    end\n\n    class HivemindModule\n      attr_reader :label, :elements\n\n      def initialize(label, elements = [])\n        @elements = elements\n      end\n    end\n\n    def self.hivemind_string(value)\n      HivemindObject.new({_value: value}, HivemindEnv[:String])\n    end\n\n    def self.hivemind_numbr(value)\n      HivemindObject.new({_value: value}, HivemindEnv[value.is_a?(Fixnum) ? :Int : :Float])\n    end\n\n    def self.hivemind_object(data)\n      HivemindObject.new(data, HivemindEnv[:Object])\n    end\n\n    HivemindEnv = Environment.new(nil, \n      Object: HivemindClass.new('Object')\n    )\n\n    HivemindEnv[:Class] = HivemindClass.new('Class', HivemindEnv[:Object])\n    HivemindEnv[:String] = HivemindClass.new('String', HivemindEnv[:Object])\n    HivemindEnv[:Int] = HivemindClass.new('Int', HivemindEnv[:Object])\n    HivemindEnv[:Float] = HivemindClass.new('Float', HivemindEnv[:Object])\n    HivemindEnv[:Boolean] = HivemindClass.new('Boolean', HivemindEnv[:Object])\n    HivemindEnv[:@true] = HivemindObject.new({}, HivemindEnv[:Boolean])\n    HivemindEnv[:NilClass] = HivemindClass.new('NilClass', HivemindEnv[:Object])\n    HivemindEnv[:@nil] = HivemindObject.new({}, HivemindEnv[:NilClass])\n\n    HivemindEnv[:Object].define_hivemind_method(:display) do |hivemind_self, *args, env|\n      puts hivemind_self.call(hivemind_self.klass.dispatch_method(:to_string), args, env).data[:_value]\n    end\n\n    HivemindEnv[:Object].define_hivemind_method(:to_string) do |hivemind_self, *args, env|\n      # p hivemind_self\n      if [HivemindEnv[:Int], HivemindEnv[:Float], HivemindEnv[:String], HivemindEnv[:Boolean]].include? hivemind_self.klass\n        hivemind_string(hivemind_self.data[:_value])\n      elsif hivemind_self.klass == HivemindEnv[:NilClass]\n        hivemind_string('null')\n      else\n        y = ''\n        i = 0\n        y2 = []\n        hivemind_self.data.each do |key, value|\n          y2 << key.to_s + ':' + value.call(value.klass.dispatch_method(:to_string), [], env).data[:_value].to_s\n        end\n        y = y2.join(', ') \n        hivemind_string(\"{#{y}}\")\n      end\n    end\n  end\nend\n\n\n"
  },
  {
    "path": "lib/hivemind/syntax.rb",
    "content": "require_relative 'combinators'\n\nmodule Hivemind\n\n  # BaseGrammar = Phoenix::Grammar.new\n  # BaseGrammar.rules = {\n  #   segment: many(ref(:keyword_structure), as: :elements),\n  #   keyword_structure: ref(:module) | ref(:class) | ref(:method),\n  #   method: lit('module') & some(ws) & ref(:name, as: :module_name) & \n  #           many(ref(:expr), as: :body),\n  #   expr:   ref(:if) | ref(:sequence) | ref(:attribute) | ref(:attribute_assign) |\n  #           ref(:assign) | ref(:literal),\n  #   sequence: ref(:list) | ref(:dictionary),\n  #   list:   lit('[') & join(ref(:expr), ', ', as: :elements) & lit(']'),\n  #   dictionary: lit('{') & join(ref(:pair), ', ', as: :elements) & lit('}'),\n  #   pair: ref(:expr, as: :key) & some(ws) & '=>' & some(ws) & ref(:expr, as: :value),\n  #   attribute: ref(:expr, as: :object, except: :attribute) & '.' & ref(:name, as: :label),\n  #   attribute_assign: ref(:expr, as: :object, except: :attribute) & '.' & ref(:name, as: :label) & some(ws) & lit('=') & some(ws) & ref(:expr, as: :right),\n  #   assign: ref(:name, as: :left) & some(ws) & lit('=') & some(ws) & ref(:expr, as: :right),\n  #   literal: ref(:string) | ref(:boolean) | ref(:nil_literal) | ref(:number) | ref(:name)\n  #   name: regex(/[a-zA-Z_]+/, as: :value),\n  #   string: lit('\"') & regex(/[^\"]*/, as: :value) + lit('\"'),\n  #   number: regex(/[0-9]+(\\.[0-9]+)?/, as: :value),\n  #   boolean: ref(:true_literal) | ref(:false_literal),\n  #   true_literal: 'true',\n  #   false_literal: 'false',\n  #   nil_literal: 'nil',\n  #   :if => lit('if') & some(ws) & ref(:expr, as: :test) & lit(':') & nl & indent & join(ref(:expr), \"\\n\", as: :true_branch) &\n  #          nl & dedent & lit('else') & lit(':') & nl & indent & join(ref(:expr), \"\\n\", as: :else_branch) & nl & dedent,\n  #   :class => lit('class') & some(ws) & ref(:name, as: :class_name) &\n  #             many(ref(:ex)\n\n  # }\n\n\n  TYPES = {\n    assign: {\n      left: :name,\n      right: :expr\n    },\n\n    attribute: {\n      object: :expr_no_attr,\n      label: :name_or_attr\n    },\n\n    image: {\n      statements: :class_statement\n    },\n\n    binary: {\n      left: :expr_no_binary,\n      operation: :operation,\n      right: :expr\n    },\n\n    attribute_assign: {\n      object: :expr_no_attr,\n      label: :name_or_attr,\n      right: :expr\n    },\n\n    call: {\n      function: :expr_no_call,\n      args: :expr\n    },\n\n    list: {\n      elements: :expr\n    },\n\n    dictionary: {\n      pair: :pair\n    },\n\n    pair: {\n      key: :string,\n      value: :expr\n    },\n\n    method_statement: {\n      method_name: :name,\n      args: :name,\n      body: :expr\n    },\n\n    class_statement: {\n      class_name: :name,\n      methods: :method_statement\n    },\n\n    module_statement: {\n      module_name: :name,\n      elements: :statement\n    },\n\n    if_statement: {\n      test: :expr,\n      true_branch: :expr,\n      else_branch: :expr\n    }\n  }\n\n  class Syntax\n    def self.generate_syntax(bidirectional_grammar)\n      new(bidirectional_grammar).generate\n    end\n\n    def initialize(grammar)\n      @grammar_source = grammar\n    end\n\n    def generate\n      # parse grammar\n      # combine into base grammar\n      rules = self.class.load_rules(@grammar_source)\n      refs = {}\n\n      rules.each do |name, rule|\n        refs[:\"_#{name}\"] = parse_rule rule, TYPES[name]\n      end\n\n      [REFS[:image], REFS.merge(refs)]\n    end\n\n    def parse_rule(rule, types)\n      parsers = []\n      tokens = []\n      token = ''\n      i = 0\n      while i < rule.length\n        z = rule[i]\n        if '<>'.include?(z)\n          tokens << token unless token.empty?\n          token = ''\n          if z == '>'\n            if rule[i + 1] == '>'\n              tokens << '>>'\n              i += 1\n            else\n              tokens << '>'\n            end\n          elsif z == '<'\n            if rule[i + 1] == '<'\n              tokens << '<<'\n              i += 1\n            else\n              tokens << '<'\n            end\n          end\n        elsif z == \"'\"\n          tokens << token unless token.empty?\n          token = ''\n          j = i\n          i += 1\n          while rule[i] != \"'\"\n            i += 1\n          end\n          tokens << rule[j..i]\n        elsif z == ' '\n          tokens << token unless token.empty?\n          token = ''\n          j = i\n          while rule[i] == ' '\n            i += 1\n          end\n          tokens << rule[j..i - 1]\n          i -= 1\n        elsif z == \"\\n\"\n          tokens << token unless token.empty?\n          tokens << \"\\n\"\n        elsif z.match /[a-zA-Z_0-9]/\n          token += z\n        else\n          tokens << token unless token.empty?\n          token = ''\n          tokens << z\n        end\n        i += 1\n      end\n      tokens << token unless token.empty?\n\n      r = 0\n      in_var = false\n\n      tokens.each_with_index do |token, i|\n        if token == '>>'\n          if tokens[i - 2] == ':'\n            parsers << Join.new(\n                Ref.new(types[tokens[i - 3].to_sym]),\n                tokens[i - 1][1..-2], as: tokens[i - 3])\n          else\n            parsers << Join.new(Ref.new(types[tokens[i - 1].to_sym]), \"\\n#{'    ' * r}\", as: tokens[i - 1])\n            #Many.new(Ref.new(types[tokens[i - 1].to_sym]), as: tokens[i - 1])\n          end\n          in_var = false\n        elsif token == '>'\n          parsers << Ref.new(types[tokens[i - 1].to_sym])\n          in_var = false\n        elsif token == \"\\n\"\n          parsers << Ref.new(:nl)\n          if tokens[i + 1] == \"\\n\"\n            e = 2\n          elsif tokens[i + 1]\n            match = tokens[i + 1].match /([    ]+)/\n            if match.nil? || match.captures.empty?\n              indent = 0\n            else\n              indent = match.captures.first.size / 4\n            end\n            if indent > r\n              parsers << Ref.new(:indent)\n            elsif indent < r\n              parsers << Ref.new(:dedent)\n            end\n            r = indent\n          end \n        elsif token.match(/\\A +\\z/) \n          parsers << Ref.new(:ws)\n        elsif (token == '<<' || token == '<') && tokens[i + 1] >= 'a' && tokens[i + 1] <= 'z'\n          in_var = true\n        elsif !in_var \n          parsers << Lit.new(token)\n        end\n      end\n      # parsers.map { |pa| puts pa.inspect }\n      parsers.reduce(:&)\n    end\n\n    def self.load_rules(grammar)\n      lines = grammar.split(\"\\n\")\n      rules = {}\n      current_rule = nil\n      rule_body = []\n      lines.each do |line|\n        if line.start_with? '#'\n          if not current_rule.nil?\n            rule_body << \"\\n\" if rule_body.length > 1\n            rules[current_rule.to_sym] = rule_body.join(\"\\n\")\n            rule_body = []\n          end\n          current_rule = line[1..-1].strip\n        elsif line.strip != ''\n          rule_body << line\n        end\n      end\n      rule_body << \"\\n\" if rule_body.length > 1\n      rules[current_rule.to_sym] = rule_body.join(\"\\n\")\n      rules\n    end\n  end\n  \n  Name = UniversalAST::Name\n  Number = UniversalAST::Number\n  Assign = UniversalAST::Assign\n  Element = UniversalAST::Element\n  Call = UniversalAST::Call\n  List = UniversalAST::List\n  Dictionary = UniversalAST::Dictionary\n  Pair = UniversalAST::Pair\n  Attribute = UniversalAST::Attribute\n  AttributeAssign = UniversalAST::AttributeAssign\n  IfStatement = UniversalAST::IfStatement\n  MethodStatement = UniversalAST::MethodStatement\n  ClassStatement = UniversalAST::ClassStatement\n  Image = UniversalAST::Image\n  Operation = UniversalAST::Operation\n  Float = UniversalAST::Float\n  Int = UniversalAST::Int\n\n  REFS = {\n    name: Apply.new(Mat.new(/[a-zA-Z][a-zA-Z_]*/)) do |result|\n      Name.new(result.to_sym)\n    end,\n    \n    image: Apply.new(Join.new(Ref.new(:class_statement), \"\", as: :statements)) do |children|\n      # d = children.select { |child| child.is_a?(MethodStatement) }\n      e = children.select { |child| child.is_a?(ClassStatement) }\n      # obj = e.find { |element| element.is_a?(ClassStatement) && element.class_name == :Object }\n      # p e[0].class_name\n      # if obj.nil? && !d.empty?\n      #   obj = ClassStatement.new(Name.new(:Object), d)\n      #   e << obj\n      # elsif obj\n      #   obj.methods += d\n      # end\n      Image.new(e)\n    end,\n\n    statement: Ref.new(:module_statement) | Ref.new(:class_statement) | Ref.new(:method_statement), \n\n    number: Ref.new(:float) | Ref.new(:int),\n\n    float: Apply.new(Mat.new(/[0-9]+\\.[0-9]+/)) do |result|\n      Float.new(result.to_f)\n    end,\n\n    int: Apply.new(Mat.new(/[0-9]+/)) do |result|\n      Int.new(result.to_i)\n    end,\n\n    string: Apply.new(Mat.new(/\\\"[^\\\"]*\\\"/)) do |result|\n      String.new(result[1..-2])\n    end,\n\n    ws: Mat.new(/ +/),\n\n    nl: Mat.new(/\\n*/),\n\n    indent: Lit.new(''),\n\n    dedent: Lit.new(''),\n\n    expr: Ref.new(:attribute_assign) | Ref.new(:assign) | Ref.new(:binary) | Ref.new(:call) | Ref.new(:attribute) | Ref.new(:number) | Ref.new(:name) | Ref.new(:string),\n\n    expr_no_attr: Ref.new(:number) | Ref.new(:nil) | Ref.new(:name) | Ref.new(:string),\n\n    expr_no_call: Ref.new(:binary) | Ref.new(:attribute) | Ref.new(:number) | Ref.new(:name) | Ref.new(:string),\n\n    nil: Lit.new('nil'),\n\n    name_or_attr: Ref.new(:name) | Ref.new(:attribute), \n\n    assign: Apply.new(Ref.new(:_assign)) do |results|\n      Assign.new(*results.select { |r| r.is_a?(Element) })\n    end,\n\n    attribute_assign: Apply.new(Ref.new(:_attribute_assign)) do |results|\n      AttributeAssign.new(*results.select { |r| r.is_a?(Element) })\n    end,\n\n    call: Apply.new(Ref.new(:_call)) do |results|\n      function, args = results.select { |r| r.is_a?(Element) || r.is_a?(Array) }\n      Call.new(function, args)\n    end,\n\n    list: Apply.new(Ref.new(:_list)) do |results|\n      List.new(results[1])\n    end,\n\n    dictionary: Apply.new(Ref.new(:_dictionary)) do |results|\n      Dictionary.new(results[1])\n    end,\n\n    pair: Apply.new(Ref.new(:_pair)) do |results|\n      key, value = results.select { |r| r.is_a?(Element) }\n      Pair.new(key, value)\n    end,\n\n    binary: Apply.new(Ref.new(:_binary)) do |results|\n      if results[0].is_a?(String)\n        results = results[1..-1]\n      end\n      # detect operation intelligently\n      tokens = results[0], results[2], results[4]      \n      if tokens[0].is_a?(UniversalAST::Operation)\n        operation, left, right = tokens\n      elsif tokens[1].is_a?(UniversalAST::Operation)\n        left, operation, right = tokens\n      else\n        left, right, operation = tokens\n      end\n      # p results\n      UniversalAST::Binary.new(left, operation, right)\n    end,\n\n    expr_no_binary: Ref.new(:attribute) | Ref.new(:number) | Ref.new(:name) | Ref.new(:string),\n\n    operation: Apply.new(Lit.new('+') | Lit.new('-') | Lit.new('**') | Lit.new('/') | Lit.new('*') | Lit.new('||')) do |result|\n      Operation.new(result)\n    end, \n\n    attribute: Apply.new(Ref.new(:_attribute)) do |results|\n      object, label = results.select { |r| r.is_a?(Element) }\n      Attribute.new(object, label)\n    end, \n\n    if_statement: Apply.new(Ref.new(:_if_statement)) do |results|\n      test, true_branch, else_branch = results.select { |r| r.is_a?(Element) || r.is_a?(Array) }\n      IfStatement.new(test, true_branch, else_branch)\n    end,\n\n    method_statement: Apply.new(Ref.new(:_method_statement)) do |results|\n      method_name, args, body = results.select { |r| r.is_a?(Element) || r.is_a?(Array) }\n      MethodStatement.new(method_name, args, body)\n    end,\n    \n    class_statement: Apply.new(Ref.new(:_class_statement)) do |results|\n      class_name, methods = results.select { |r| r.is_a?(Element) || r.is_a?(Array) }\n      ClassStatement.new(class_name, methods)\n    end,\n\n    module_statement: Apply.new(Ref.new(:_module_statement)) do |results|\n      module_name, classes = results.select { |r| r.is_a?(Element) || r.is_a?(Array) }\n      ModuleStatement.new(module_name, classes)\n    end\n  }\n\nend\n\n\n\n\n\n"
  },
  {
    "path": "lib/hivemind/universal_ast.rb",
    "content": "module Hivemind\n  module UniversalAST\n    class Element\n      def self.fields(*labels)\n        define_method(:initialize) do |*args|\n          args.zip(labels).each do |arg, label|\n            instance_variable_set \"@#{label}\", arg\n          end\n        end\n        attr_reader *labels\n      end\n\n      def offset(depth)\n        '    ' * depth\n      end\n    end\n\n    class IfStatement < Element\n      # if <test>:\n      #   <<true-branch>>\n      # else:\n      #   <<else-branch>>\n\n      fields :test, :true_branch, :else_branch\n\n      def render(depth = 0)\n        \"#{offset(depth)}If\\n#{offset(depth + 1)}#{@test.render(depth + 1)}\\n\"\n        \"#{@true_branch.render(depth + 1)}\\n#{@else_branch.render(depth + 1)}\\n\"\n      end\n    end\n\n    class Assign < Element\n      # <left> = <right>\n\n      fields :left, :right\n\n      def render(depth = 0)\n        \"#{offset(depth)}Assign left: #{@left.render} right: #{@right.render}\"\n      end\n    end\n\n    class Attribute < Element\n      # <object>.<label>\n\n      fields :object, :label\n\n      def render(depth = 0)\n        \"#{offset(depth)}Attribute : #{@object.render} #{@label.render}\"\n      end\n    end\n\n    class AttributeAssign < Element\n      # <object>.<label> = <right>\n\n      fields :object, :label, :right\n\n      def render(depth = 0)\n        \"#{offset(depth)}AttributeAssign : #{@object.render} #{@label.render} #{@right.render}\"\n      end\n    end\n\n    class Call < Element\n      # <function>(<<args:', '>>)\n\n      fields :function, :args\n\n      def render(depth = 0)\n        \"#{offset(depth)}Call\\n#{@function.render(depth + 1)}\\n#{offset(depth + 1)}#{@args.map(&:render).join(' ')}\\n\"\n      end\n    end\n\n    class List < Element\n      # [el1, el2..]\n\n      fields :elements\n\n      def render(depth = 0)\n        \"#{offset(depth)}List\\n#{@elements.map { |e| e.render(depth + 1) }.join(\"\\n\")}\"\n      end\n    end\n\n    class Dictionary < Element\n      # {key1: val1, key2: val2..}\n\n      fields :pairs\n    end\n\n    class Binary < Element\n      # <left> <operation> <right>\n\n      fields :left, :operation, :right\n\n      def render(depth = 0)\n        \"#{offset(depth)}Binary #{@left.render} #{@operation.value} #{@right.render}\"\n      end\n    end\n\n    class MethodStatement < Element\n      # method <method-name>(<<args:', '):\n      #   <<body>>\n\n      fields :method_name, :args, :body\n\n      def render(depth = 0)\n        \"#{offset(depth)}MethodStatement #{@method_name.value} #{@args.map(&:render).join(' ')}\\n\" +\n        \"#{@body.map { |e| e.render(depth + 1) }.join(\"\\n\")}\\n\"\n      end\n    end\n\n    class ClassStatement < Element\n      # type <class-name>:\n      #   <<methods>>\n\n      fields :class_name, :methods\n\n      def render(depth = 0)\n        \"#{offset(depth)}ClassStatement #{@class_name.value}\\n\" + \n        \"#{@methods.map { |e| e.render(depth + 1) }.join(\"\\n\")}\\n\"\n      end\n    end\n\n    class Value < Element\n      fields :value\n\n      def render(depth = 0)\n        \"#{offset(depth)}#{@value}\"\n      end\n    end\n\n    class Name < Value\n    end\n\n    class String < Value\n    end\n\n    class Number < Value\n    end\n\n    class Int < Number\n    end\n\n    class Float < Number\n    end\n\n    class Operation < Value\n    end\n\n    class ModuleStatement < Element\n      # module <module-name>:\n      #   <<children>>\n\n      fields :module_name, :elements\n    end\n\n    class Pair < Element\n      # key => value\n      fields :key, :value\n    end\n\n    class Image < Element\n      fields :statements\n\n      def render(depth = 0)\n        @statements.map(&:render).join \"\\n\"\n      end\n    end\n  end\nend\n\n"
  },
  {
    "path": "lib/hivemind/vm.rb",
    "content": "require_relative 'runtime'\nrequire_relative 'universal_ast'\n\nmodule Hivemind\n  class VM\n    def initialize(ast)\n      @ast = ast\n    end\n\n    def run(env)\n      @ast.run env\n    end\n  end\n\n  class Runtime::HivemindObject\n    def call(function, args, env)\n      if function.is_a?(UniversalAST::MethodStatement)\n        args_values = {:self => self}\n        function.args[1..-1].zip(args) do |label, arg|\n          args_values[label.value.to_sym] = arg\n        end\n        body_env = Environment.new(env, **args_values)\n        function.body.map { |expr| expr.run(body_env) }[-1] || env.top[:@nil]\n      else\n        function.call self, *args, env\n      end\n    end\n  end\n\n  class Runtime::HivemindClass\n    def call(function, args, env)\n      h = Runtime::HivemindObject.new({}, self)\n      function = dispatch_method(:init)\n      if function.is_a?(UniversalAST::MethodStatement)\n        args_values = {:self => h}\n        function.args[1..-1].zip(args) do |label, arg|\n          args_values[label.value.to_sym] = arg\n        end\n        body_env = Environment.new(env, **args_values)\n        function.body.map { |expr| expr.run(body_env) }[-1] || env.top[:@nil]\n      else\n        function.call h, *args, env\n      end\n      h\n    end\n  end\n    \n  module UniversalAST\n    class Image\n      def run(env)\n        @statements.each do |statement|\n          statement.run(env)\n        end\n        # puts env.top[:Object].methods.keys\n        if env.top[:Object].methods.key? :start\n          weird_object = Runtime::hivemind_object({})\n          weird_object.call(env.top[:Object].methods[:start], [], env)\n        else\n          env.top[:@nil]\n        end\n      end\n    end\n\n    class ModuleStatement\n      def run(env)\n        module_statement = Runtime::HivemindModule.new(@module_name)\n        @statements.each do |statement|\n          module_statement.elements[@statement.is_a?(ModuleStatement) ? @statement.module_name : @statement.class_name] =\n            statement.run(env)\n        end\n        env\n      end\n    end\n\n    class If\n      def run(env)\n        if @test.run(env) == env.top[:@true]\n          @true_branch.run env\n        else\n          @else_branch.run env\n        end\n      end\n    end\n\n    class Assign\n      def run(env)\n        env[@left.value.to_sym] = @right.run(env)\n      end\n    end\n\n    class Attribute\n      def run(env)\n        obj = @object.run(env)\n        env.current_self = obj\n\n        if obj.respond_to?(:data) \n          if obj.data.key? @label.value\n            obj.data[@label.value]\n          else\n            method = obj.klass.dispatch_method(@label.value)\n            if method\n              method\n            else\n              raise HivemindAccessError.new(\"No #{@label.value} in obj\")\n            end\n          end\n        else\n          obj.methods[@label.value]\n        end\n      end\n    end\n\n    class AttributeAssign\n      def run(env)\n        @object.run(env).data[@label.value] = @right.run(env)\n      end\n    end\n\n    class Call\n      def run(env)\n        if !@function.is_a?(Attribute)\n          function = @function.run(env)\n          env.current_self.call(function, @args.map { |arg| arg.run(env) }, env)\n        elsif @function.label.value != :new\n          obj = @function.object.run(env)\n          function = obj.klass.dispatch_method(@function.label.value)\n          obj.call(function, @args.map { |arg| arg.run(env) }, env)\n        else\n          obj = @function.object.run(env)\n          function == obj.dispatch_method(:init)\n          obj.call(function, @args.map { |arg| arg.run(env) }, env)\n        end\n      end\n    end\n\n    class Binary\n      def run(env)\n        Runtime::hivemind_numbr(@left.run(env).data[:_value].send(@operation.value, @right.run(env).data[:_value]))\n      end\n    end\n\n    class List\n      def run(env)\n        Runtime::HivemindObject.new({_elements: @elements.map { |elem| elem.run(env) }}, env.top[:List])\n      end\n    end\n\n    class Dictionary\n      def run(env)\n        dict = {}\n        @pairs.each do |pair|\n          dict[pair.key.value.to_sym] = pair.value.run(env)\n        end\n        Runtime::HivemindObject.new({_dict: dict}, env.top[:Dict])\n      end\n    end\n\n    class Value\n      def run(env)\n        Runtime::HivemindObject.new({_value: @value}, env.top[self.class.name.split('::').last.to_sym])\n      end\n    end\n\n    class ClassStatement\n      def run(env)\n        definition = env.fetch(@class_name.value) || Runtime::HivemindClass.new(@class_name.value, env.top[:Object], {})\n        @methods.each do |method|\n          definition.methods[method.method_name.value] = method\n        end\n        env[@class_name.value] = definition\n      end\n    end\n\n    class MethodStatement\n      def run(env)\n        self\n      end\n    end\n\n    class Name\n      def run(env)\n        env[@value]\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/hivemind.rb",
    "content": "require_relative 'hivemind/universal_ast'\nrequire_relative 'hivemind/environment'\nrequire_relative 'hivemind/vm'\nrequire_relative 'hivemind/runtime'\nrequire_relative 'hivemind/syntax'\nrequire_relative 'hivemind/renderer'\n"
  },
  {
    "path": "spec/hivemind/parser_spec.rb",
    "content": ""
  },
  {
    "path": "spec/hivemind/universal_ast_spec.rb",
    "content": "require 'spec_helper'\n\nmodule Hivemind\n  module UniversalAST\n    describe Element do\n      it 'fields initializes a class with given labels' do\n        class A < Element\n          fields :a\n        end\n        \n        expect(A.new(2).a).to eq(2)\n      end\n    end\n    \n    describe ModuleStatement do\n      it 'is initialized with an elements attribute' do\n        mod = ModuleStatement.new('ha', [])\n        expect(mod.elements).to eq([])\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/hivemind/vm_spec.rb",
    "content": "require 'spec_helper'\n\nmodule Hivemind\n  describe VM do\n    it 'should work for a program with a single number' do\n      vm = VM.new UniversalAST::Number.new(44)\n      expect(vm.run(Runtime::HivemindEnv).data[:_value]).to eq 44\n    end\n  end\nend\n"
  },
  {
    "path": "spec/spec_helper.rb",
    "content": "# well, really, no time for a lot of tests now\n# dirty fast prototyping\n\n$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))\n$LOAD_PATH.unshift(File.dirname(__FILE__))\nrequire 'rspec'\nrequire 'hivemind'\n"
  },
  {
    "path": "syntaxes/lolcode.syntax",
    "content": "#if_statement\n<test> O RLY\n    YA RLY\n    <<true_branch>>\n    NO WAI\n    <<else_branch>>\n\n\n#assign\nDO <left> <right>\n\n#method_statement\nHOW DUZ I <method_name>(<<args:' '>>)\n    <<body>>\nIF U SAY SO\n\n#attribute\n<object> HEY <label>\n\n#attribute_assign\n<object> BE <label> <right>\n\n#call\nGIMME <function> (<<args:' '>>)\n\n#class_statement\nTOM SAYS <class_name>\n    <<methods>>\nLOVE\n\n#module_statement\nHAI <module_name>\n    <<elements>>\nKTHXBYE\n"
  },
  {
    "path": "syntaxes/paren.syntax",
    "content": "#if_statement\n(if <test>\n    <true_branch>\n    <else_branch>)\n\n#assign\n(define <left> <right>)\n\n#method_statement\n(method <method_name> (<<args:' '>>)\n    <<body>>)\n\n#attribute\n<object>.<label>\n\n#attribute_assign\n(update <object>.<label> <right>)\n\n#binary\n(<operation> <left> <right>)\n\n#call\n(! <function> <<args:' '>>)\n\n#list\n_(<<elements:' '>>)\n\n#class_statement\n(class <class_name>\n    <<methods>>)\n\n#module_statement\n(module <module_name>\n    <<elements>>)\n"
  },
  {
    "path": "syntaxes/pythonic.syntax",
    "content": "#if_statement\nif <test>:\n    <true_branch>\nelse:\n    <else_branch>\n\n#assign\n<left> = <right>\n\n#call\n<function>(<<args:', '>>)\n\n#attribute\n<object>.<label>\n\n#attribute_assign\n<object>.<label> = <right>\n\n#binary\n<left> <operation> <right>\n\n#list\n[<<elements:', '>>]\n\n#method_statement\nmethod <method_name>(<<args:', '>>):\n    <<body>>\n\n#class_statement\nclass <class_name>:\n    <<methods:''>>\n\n#module_statement\nmodule <module_name>:\n    <<elements>>\n\n"
  }
]