Repository: alehander42/hivemind
Branch: master
Commit: 8a0727078b56
Files: 31
Total size: 42.3 KB
Directory structure:
gitextract_mc_17_3g/
├── .gitignore
├── .travis.yml
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── bin/
│ └── hivemind
├── examples/
│ ├── a.hm
│ ├── a_paren.hm
│ ├── b.hm
│ ├── shape.hm
│ ├── shape_paren.hm
│ └── shape_pythonic.hm
├── hivemind.gemspec
├── lib/
│ ├── hivemind/
│ │ ├── code_viewer.rb
│ │ ├── combinators.rb
│ │ ├── environment.rb
│ │ ├── errors.rb
│ │ ├── renderer.rb
│ │ ├── runtime.rb
│ │ ├── syntax.rb
│ │ ├── universal_ast.rb
│ │ └── vm.rb
│ └── hivemind.rb
├── spec/
│ ├── hivemind/
│ │ ├── parser_spec.rb
│ │ ├── universal_ast_spec.rb
│ │ └── vm_spec.rb
│ └── spec_helper.rb
└── syntaxes/
├── lolcode.syntax
├── paren.syntax
└── pythonic.syntax
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
#Logs
application/logs/*.php
# Content types
/application/xml/types/*.xml
# Custom builds and generated php files
/core/documentation/build
/core/views/admin/content/translations.php
# Attachs and cache files #
*.tmp
/attach/cache/
/attach/
/application/cache/_bancha/*.css
/application/cache/_bancha/*.js
Gemfile.lock
*.pyc
*.doc
*.txt
================================================
FILE: .travis.yml
================================================
language: ruby
rvm:
- 2.2.3
script:
- bundle exec rake
================================================
FILE: Gemfile
================================================
source 'https://rubygems.org'
group :development, :test do
gem 'bundler'
gem 'rspec'
gem 'skeptic'
gem 'rake'
end
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2016 Alexander Ivanov
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
[](https://travis-ci.org/alehander42/hivemind)
[](LICENSE)
# hivemind
A prototype of a multi-syntax programming language.
Hivemind has a core language defined by its AST and configurable syntaxes acting like plugins.
The concept of "syntax" for hivemind is similar to
* a theme for a text editor
* a skin for a gui app
* a json/html/xml template for a MVC web app
Syntaxes are defined using code-like examples for core ast nodes and they act in a bidirectional way:
* they are used to parse source code using that syntax
* and to render code in that syntax
* **source in each syntax is automatically transltable to another syntax**
Tools for the language would also support representations of source grouped by class or methods or as a graph
Syntaxes look like that:
A pythonic syntax:
```python
#if_statement
if <test>:
<true_branch>
else:
<else_branch>
#assign
<left> = <right>
#call
<function>(<<args:', '>>)
#attribute
<object>.<label>
#attribute_assign
<object>.<label> = <right>
#binary
<left> <operation> <right>
#list
[<<elements:', '>>]
#method_statement
method <method_name>(<<args:', '>>):
<<body>>
#class_statement
class <class_name>:
<<methods:''>>
#module_statement
module <module_name>:
<<elements>>
```
A lisp-like syntax
```
#if_statement
(if <test>
<true_branch>
<else_branch>)
#assign
(define <left> <right>)
#method_statement
(method <method_name> (<<args:' '>>)
<<body>>)
#attribute
<object>.<label>
#attribute_assign
(update <object>.<label> <right>)
#binary
(<operation> <left> <right>)
#call
(! <function> <<args:' '>>)
#list
_(<<elements:' '>>)
#class_statement
(class <class_name>
<<methods>>)
#module_statement
(module <module_name>
<<elements>>)
```
# Examples
[pythonic example](examples/shape_pythonic.hm)
[schemelike example](examples/shape_paren.hm)
# Installation
```
gem install hivemind
```
# Usage
Run a file
```bash
hivemind <filename>
```
Translate a file into another syntax representation
```bash
hivemind render a.hm pythonic a2.hm
```
# Goals
* Experiment with diffent syntaxes in different contexts
* Use different sub-language seamlessly across the same codebase
* A possible solution for the expression problem (just convert between different representations)
# Language
The core language is just a simple python/ruby-like language for now.
# History
Created for the HackFMI 5
# Future development
* fluid folder/file structure representations
* editor plugins
* more syntaxes
## License
Copyright 2016 [Alexander Ivanov](https://twitter.com/alehander42)
Distributed under the MIT License.
================================================
FILE: Rakefile
================================================
require 'rubygems'
require 'bundler'
begin
Bundler.setup(:default, :development)
rescue Bundler::BundlerError => e
$stderr.puts e.message
$stderr.puts "Run `bundle install` to install missing gems"
exit e.status_code
end
require 'rake'
require 'rspec/core'
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec) do |spec|
spec.pattern = FileList['spec/**/*_spec.rb']
end
task :default => :spec
================================================
FILE: bin/hivemind
================================================
#!/usr/bin/env ruby
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
require 'hivemind'
SYNTAXES_PATH = File.join(File.expand_path(File.join(File.dirname(__FILE__), '..')), 'syntaxes')
def astify(source, syntax)
parser, refs = Hivemind::Syntax.generate_syntax(syntax)
success, tree, _ = parser.parse(source, refs)
tree
end
def syntax_file(f)
File.read(File.join(SYNTAXES_PATH, "#{f}.syntax"))
end
if ARGV.length == 1
filename = ARGV[0]
source = File.read(filename)
syntax_line, _, source = source.partition("\n")
if !syntax_line.start_with? 'syntax: '
puts "file doesn't specify a syntax"
exit 1
end
syntax = syntax_file(syntax_line.partition(': ').last)
tree = astify(source.lstrip, syntax)
vm = Hivemind::VM.new(tree)
result = vm.run Hivemind::Runtime::HivemindEnv
elsif ARGV.length == 4
filename, second_syntax_name, save = ARGV[1..-1]
source = File.read(filename)
syntax_line, _, source = source.partition("\n")
if !syntax_line.start_with? 'syntax: '
puts "first line of file doesn't specify a syntax"
exit 1
end
first = syntax_file(syntax_line.partition(': ').last)
second = syntax_file(second_syntax_name)
tree = astify(source.lstrip, first)
result = Hivemind::Renderer.new(tree, second).render
File.write(save, "syntax: #{second_syntax_name}\n\n#{result}")
else
puts <<-USAGE
hivemind <filename>
runs the file
hivemind render <filename> <syntax> <new_filename>
renders the source with <syntax>
USAGE
end
================================================
FILE: examples/a.hm
================================================
syntax: pythonic
class Object:
method start(self):
e = 2
e.display()
================================================
FILE: examples/a_paren.hm
================================================
syntax: paren
(class Rectangle
(method init (self a b)
(update self.a a)
(update self.b b))
(method area (self)
(* self.a self.b)))
================================================
FILE: examples/b.hm
================================================
syntax: pythonic
class Rectangle:
method init(self, a, b):
self.a = a
self.b = b
method area(self):
self.a * self.b
================================================
FILE: examples/shape.hm
================================================
syntax: pythonic
class Rectangle:
method init(self, a, b):
self.a = a
self.b = b
method area(self):
self.a * self.b
class Circle:
method init(self, r):
self.r = r
method area(self):
3.14 * self.r * self.r
class Object:
method start(self):
e = Rectangle.new(2, 4)
f = e.area()
f.display()
c = Circle.new(4)
g = c.area()
g.display()
================================================
FILE: examples/shape_paren.hm
================================================
syntax: paren
(class Rectangle
(method init (self a b)
(update self.a a)
(update self.b b))
(method area (self)
(* self.a self.b)))
(class Circle
(method init (self r)
(update self.r r))
(method area (self)
(* 3.14 (* self.r self.r))))
(class Object
(method start (self)
(define e (! Rectangle.new 2 4))
(define f (! e.area ))
(! f.display )
(define c (! Circle.new 4))
(define g (! c.area ))
(! g.display )))
================================================
FILE: examples/shape_pythonic.hm
================================================
syntax: pythonic
class Rectangle:
method init(self, a, b):
self.a = a
self.b = b
method area(self):
self.a * self.b
class Circle:
method init(self, r):
self.r = r
method area(self):
3.14 * self.r * self.r
class Object:
method start(self):
e = Rectangle.new(2, 4)
f = e.area()
f.display()
c = Circle.new(4)
g = c.area()
g.display()
================================================
FILE: hivemind.gemspec
================================================
# Generated by jeweler
# DO NOT EDIT THIS FILE DIRECTLY
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
# -*- encoding: utf-8 -*-
# stub: skeptic 0.0.16 ruby lib
Gem::Specification.new do |s|
s.name = "hivemind"
s.version = "0.1"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.require_paths = ["lib"]
s.authors = ["Alexander Ivanov"]
s.date = "2016-03-12"
s.description = "A multi-syntax programming language"
s.email = "alehande42@gmail.com"
s.executables = ["hivemind"]
s.extra_rdoc_files = [
"LICENSE",
"README.md"
]
s.files = [
"bin/hivemind",
"lib/hivemind.rb",
".gitignore",
"Gemfile",
"LICENSE",
"README.md",
"Rakefile",
"hivemind.gemspec",
"lib/hivemind/code_viewer.rb",
"lib/hivemind/combinators.rb",
"lib/hivemind/environment.rb",
"lib/hivemind/errors.rb",
"lib/hivemind/renderer.rb",
"lib/hivemind/runtime.rb",
"lib/hivemind/syntax.rb",
"lib/hivemind/universal_ast.rb",
"lib/hivemind/vm.rb",
"spec/spec_helper.rb",
"spec/hivemind/parser_spec.rb",
"spec/hivemind/vm_spec.rb",
"spec/hivemind/universal_ast_spec.rb",
"syntaxes/pythonic.syntax",
"syntaxes/lolcode.syntax",
"syntaxes/paren.syntax"
]
s.homepage = "http://github.com/alehander42/hivemind"
s.licenses = ["MIT"]
s.rubygems_version = "2.4.8"
s.summary = "A multi-syntax language"
s.add_development_dependency(%q<rspec>, ["= 2.14.1"])
s.add_development_dependency(%q<bundler>, [">= 0"])
s.add_development_dependency(%q<skeptic>, [">= 0"])
end
================================================
FILE: lib/hivemind/code_viewer.rb
================================================
# 'universal_ast'
# module Hivemind
# class CodeViewer
# def initialize(tree)
# @tree = tree
# end
# def view_as(query)
# hierarchy = QueryAnalyzer.parse(query)
# rebuild_tree(hierarchy)
# end
# def rebuild_tree(hierarchy)
# if hierarchy[0].type == @code_view.hierarchy[0].type
# # only sorting maybe
# # and sorting still not supported
# @tree
# else
# # method > code
# new_tree = UniversalAST::Image.new([])
# top = {}
# if hierarchy[0].type == :method
# @tree.statements.each do |statement|
# statement.methods.each do |method|
# top[method.method_name.value] ||= {}
# top[method.method_name.value][statement.class_name.value] = [args, method.body]
# end
# end
# else
# @tree.statements.each do |statement|
# statement.body.each do |method|
# top[method.class_name.value] ||= {}
# top[method.class_name.value][statement.method_name.value] = [args, method.body]
# end
# end
# end
# end
# end
# end
# end
================================================
FILE: lib/hivemind/combinators.rb
================================================
require_relative 'universal_ast'
class Combinator
def &(other)
And.new(self, other)
end
def |(other)
Or.new(self, other)
end
end
class Lit < Combinator
attr_reader :value
def initialize(value)
@value = value
end
def parse(input, refs)
if input.start_with?(@value)
[true, @value, input[@value.length.. -1]]
else
[false, '', input]
end
end
end
class Mat < Combinator
attr_reader :regex
def initialize(regex)
@regex = /\A#{regex}/
end
def parse(input, refs)
match = @regex.match(input)
if match
[true, input[0..match.to_s.size - 1], input[match.to_s.size.. -1]]
else
[false, '', input]
end
end
end
class Binary < Combinator
attr_accessor :first, :second
def initialize(first, second)
@first, @second = first, second
end
end
class And < Binary
def parse(input, refs)
first_success, first_result, remaining = @first.parse(input, refs)
if first_success
second_success, second_result, remaining = @second.parse(remaining, refs)
if second_success
return [true, combine(first_result, second_result), remaining]
end
end
[false, [], input]
end
def combine(first_result, second_result)
if @first.is_a?(And)
first_result + [second_result]
else
[first_result, second_result]
end
end
end
class Or < Binary
def parse(input, refs)
[@first, @second].each do |combinator|
success, result, remaining = combinator.parse(input, refs)
return [true, result, remaining] if success
end
[false, '', input]
end
end
class Many < Combinator
attr_accessor :parser
def initialize(parser, as: nil)
@parser = parser
end
def parse(input, refs)
success = true
remaining = input
results = []
while success
success, result, remaining = @parser.parse(remaining, refs)
results.push(result) if success
end
[true, results, remaining]
end
end
class Join < Combinator
attr_accessor :parser, :as
def initialize(parser, separator, as: nil)
@parser = parser
@separator = separator
@as = as.to_sym
@separator_parser = Lit.new(@separator) & Mat.new(/ */) #workaround hivemind
@@depth ||= 0
end
def parse(input, refs)
success = true
remaining = input
results = []
while success
# puts "#{' ' * @@depth}BEFORE " + @parser.label.to_s
# p [" " * @@depth, remaining]
# @@depth += 1
success, result, remaining = @parser.parse(remaining, refs)
# @@depth -= 1
# puts "#{' ' * @@depth}AFTER " + @parser.label.to_s
# p [" " * @@depth, success, remaining, results.length]
# puts
results.push(result) if success
if success
if remaining.start_with? ' (' # fix later
remaining = "\n#{remaining}"
end
success, result, remaining = @separator_parser.parse(remaining, refs)
end
end
[true, results, remaining]
end
end
class Ref < Combinator
attr_accessor :label
def initialize(label, as: nil)
@label = label
@as = as
end
def parse(input, refs)
ref_parser = refs[@label.to_sym]
ref_parser.parse(input, refs)
end
end
class Maybe < Combinator
attr_accessor :parser
def initialize(parser)
@parser = parser
end
def parse(input, refs)
_, result, remaining = @parser.parse(input, refs)
[true, result, remaining]
end
end
class Apply < Combinator
attr_accessor :parser
attr_reader :transformation
def initialize(parser, &transformation)
@parser, @transformation = parser, transformation
end
def parse(input, refs)
success, result, remaining = @parser.parse(input, refs)
result = @transformation.call(result) if success
[success, result, remaining]
end
end
def literal(value)
Literal.new(value)
end
def many(combinator)
Many.new(combinator)
end
def maybe(combinator)
Maybe.new(combinator)
end
def apply(combinator, &transformation)
Apply.new(combinator, &transformation)
end
def match(regex)
Match.new(regex)
end
================================================
FILE: lib/hivemind/environment.rb
================================================
require_relative 'errors'
module Hivemind
class Environment
attr_reader :parent, :values, :top
attr_accessor :current_self
def initialize(parent, **values)
@parent, @values, @top = parent, values, (parent.nil? ? values : parent.top)
end
def [](key)
value = fetch key
return value if value
raise HivemindMissingNameError.new("#{key} is missing")
end
def fetch(key)
current = self
until current.nil? || current.values.key?(key)
current = current.parent
end
return current.values[key] unless current.nil?
nil
end
def []=(key, value)
@values[key] = value
end
end
end
================================================
FILE: lib/hivemind/errors.rb
================================================
module Hivemind
class HivemindMissingNameError < StandardError
end
class HivemindAccessError < StandardError
end
end
================================================
FILE: lib/hivemind/renderer.rb
================================================
require_relative 'syntax'
module Hivemind
BASE_RULES = {
image: -> element, depth = 0 do
element.statements.map { |s| render_element(s) }.join("\n")
end,
int: -> element, depth = 0 do
element.value.to_s
end,
float: -> element, depth = 0 do
element.value.to_s
end,
string: -> element, depth = 0 do
'"' + element.value.to_s + '"'
end,
name: -> element, depth = 0 do
element.value.to_s
end,
operation: -> element, depth = 0 do
element.value.to_s
end
}
class Renderer
def initialize(tree, syntax)
@tree, @syntax = tree, syntax
@rules = BASE_RULES.merge(Syntax.load_rules(syntax))
end
def render(depth = 0)
render_element(@tree, depth).gsub(/\n\n+/, "\n\n").gsub(/\)\s+\)/, '))').gsub(/\}\s+\}/, '}}')
end
def offset(depth = 0)
' ' * depth
end
def render_element(element, depth = 0)
rule = @rules[element.class.name.split('::').last.downcase.gsub('attributeassign', 'attribute_assign').gsub('statement', '_statement').to_sym]
depth += 1 if element.class.name.end_with?('MethodStatement')
# p "for #{element.class.name.split('::').last.downcase.gsub('statement', '_statement').to_sym} #{depth}"
offset(depth) + if rule.is_a?(String)
render_template rule, element, depth
elsif rule.is_a?(Proc)
instance_exec element, depth, &rule
end
end
def render_template(plan, element, depth = 0)
plan = plan.gsub(/\<\<([a-zA-Z_]+)\:'([^\']*)'\>\>/) do
element.send(Regexp.last_match[1]).map(&method(:render_element)).join(Regexp.last_match[2])
end
# p plan
plan = plan.gsub(/\<\<([a-zA-Z_]+)\>\>/) do
element.send(Regexp.last_match[1]).map { |e| render_element(e, depth) }.join("\n")
end
p plan
plan = plan.gsub(/\<([a-zA-Z_]+)\>/) do
render_element(element.send(Regexp.last_match[1]))
end
plan
end
end
end
================================================
FILE: lib/hivemind/runtime.rb
================================================
require_relative 'environment'
module Hivemind
module Runtime
class HivemindObject
attr_reader :data, :klass
def initialize(data, klass)
@data, @klass = data, klass
end
end
class HivemindClass
attr_reader :label, :methods, :parent
def initialize(label, parent = nil, methods = {})
@label, @parent, @methods = label, parent, methods
end
def define_hivemind_method(label, &handler)
@methods[label] = handler
end
def dispatch_method(label)
current = self
until current.nil? || current.methods.key?(label)
current = current.parent
end
!current ? nil : current.methods[label]
end
end
class HivemindModule
attr_reader :label, :elements
def initialize(label, elements = [])
@elements = elements
end
end
def self.hivemind_string(value)
HivemindObject.new({_value: value}, HivemindEnv[:String])
end
def self.hivemind_numbr(value)
HivemindObject.new({_value: value}, HivemindEnv[value.is_a?(Fixnum) ? :Int : :Float])
end
def self.hivemind_object(data)
HivemindObject.new(data, HivemindEnv[:Object])
end
HivemindEnv = Environment.new(nil,
Object: HivemindClass.new('Object')
)
HivemindEnv[:Class] = HivemindClass.new('Class', HivemindEnv[:Object])
HivemindEnv[:String] = HivemindClass.new('String', HivemindEnv[:Object])
HivemindEnv[:Int] = HivemindClass.new('Int', HivemindEnv[:Object])
HivemindEnv[:Float] = HivemindClass.new('Float', HivemindEnv[:Object])
HivemindEnv[:Boolean] = HivemindClass.new('Boolean', HivemindEnv[:Object])
HivemindEnv[:@true] = HivemindObject.new({}, HivemindEnv[:Boolean])
HivemindEnv[:NilClass] = HivemindClass.new('NilClass', HivemindEnv[:Object])
HivemindEnv[:@nil] = HivemindObject.new({}, HivemindEnv[:NilClass])
HivemindEnv[:Object].define_hivemind_method(:display) do |hivemind_self, *args, env|
puts hivemind_self.call(hivemind_self.klass.dispatch_method(:to_string), args, env).data[:_value]
end
HivemindEnv[:Object].define_hivemind_method(:to_string) do |hivemind_self, *args, env|
# p hivemind_self
if [HivemindEnv[:Int], HivemindEnv[:Float], HivemindEnv[:String], HivemindEnv[:Boolean]].include? hivemind_self.klass
hivemind_string(hivemind_self.data[:_value])
elsif hivemind_self.klass == HivemindEnv[:NilClass]
hivemind_string('null')
else
y = ''
i = 0
y2 = []
hivemind_self.data.each do |key, value|
y2 << key.to_s + ':' + value.call(value.klass.dispatch_method(:to_string), [], env).data[:_value].to_s
end
y = y2.join(', ')
hivemind_string("{#{y}}")
end
end
end
end
================================================
FILE: lib/hivemind/syntax.rb
================================================
require_relative 'combinators'
module Hivemind
# BaseGrammar = Phoenix::Grammar.new
# BaseGrammar.rules = {
# segment: many(ref(:keyword_structure), as: :elements),
# keyword_structure: ref(:module) | ref(:class) | ref(:method),
# method: lit('module') & some(ws) & ref(:name, as: :module_name) &
# many(ref(:expr), as: :body),
# expr: ref(:if) | ref(:sequence) | ref(:attribute) | ref(:attribute_assign) |
# ref(:assign) | ref(:literal),
# sequence: ref(:list) | ref(:dictionary),
# list: lit('[') & join(ref(:expr), ', ', as: :elements) & lit(']'),
# dictionary: lit('{') & join(ref(:pair), ', ', as: :elements) & lit('}'),
# pair: ref(:expr, as: :key) & some(ws) & '=>' & some(ws) & ref(:expr, as: :value),
# attribute: ref(:expr, as: :object, except: :attribute) & '.' & ref(:name, as: :label),
# attribute_assign: ref(:expr, as: :object, except: :attribute) & '.' & ref(:name, as: :label) & some(ws) & lit('=') & some(ws) & ref(:expr, as: :right),
# assign: ref(:name, as: :left) & some(ws) & lit('=') & some(ws) & ref(:expr, as: :right),
# literal: ref(:string) | ref(:boolean) | ref(:nil_literal) | ref(:number) | ref(:name)
# name: regex(/[a-zA-Z_]+/, as: :value),
# string: lit('"') & regex(/[^"]*/, as: :value) + lit('"'),
# number: regex(/[0-9]+(\.[0-9]+)?/, as: :value),
# boolean: ref(:true_literal) | ref(:false_literal),
# true_literal: 'true',
# false_literal: 'false',
# nil_literal: 'nil',
# :if => lit('if') & some(ws) & ref(:expr, as: :test) & lit(':') & nl & indent & join(ref(:expr), "\n", as: :true_branch) &
# nl & dedent & lit('else') & lit(':') & nl & indent & join(ref(:expr), "\n", as: :else_branch) & nl & dedent,
# :class => lit('class') & some(ws) & ref(:name, as: :class_name) &
# many(ref(:ex)
# }
TYPES = {
assign: {
left: :name,
right: :expr
},
attribute: {
object: :expr_no_attr,
label: :name_or_attr
},
image: {
statements: :class_statement
},
binary: {
left: :expr_no_binary,
operation: :operation,
right: :expr
},
attribute_assign: {
object: :expr_no_attr,
label: :name_or_attr,
right: :expr
},
call: {
function: :expr_no_call,
args: :expr
},
list: {
elements: :expr
},
dictionary: {
pair: :pair
},
pair: {
key: :string,
value: :expr
},
method_statement: {
method_name: :name,
args: :name,
body: :expr
},
class_statement: {
class_name: :name,
methods: :method_statement
},
module_statement: {
module_name: :name,
elements: :statement
},
if_statement: {
test: :expr,
true_branch: :expr,
else_branch: :expr
}
}
class Syntax
def self.generate_syntax(bidirectional_grammar)
new(bidirectional_grammar).generate
end
def initialize(grammar)
@grammar_source = grammar
end
def generate
# parse grammar
# combine into base grammar
rules = self.class.load_rules(@grammar_source)
refs = {}
rules.each do |name, rule|
refs[:"_#{name}"] = parse_rule rule, TYPES[name]
end
[REFS[:image], REFS.merge(refs)]
end
def parse_rule(rule, types)
parsers = []
tokens = []
token = ''
i = 0
while i < rule.length
z = rule[i]
if '<>'.include?(z)
tokens << token unless token.empty?
token = ''
if z == '>'
if rule[i + 1] == '>'
tokens << '>>'
i += 1
else
tokens << '>'
end
elsif z == '<'
if rule[i + 1] == '<'
tokens << '<<'
i += 1
else
tokens << '<'
end
end
elsif z == "'"
tokens << token unless token.empty?
token = ''
j = i
i += 1
while rule[i] != "'"
i += 1
end
tokens << rule[j..i]
elsif z == ' '
tokens << token unless token.empty?
token = ''
j = i
while rule[i] == ' '
i += 1
end
tokens << rule[j..i - 1]
i -= 1
elsif z == "\n"
tokens << token unless token.empty?
tokens << "\n"
elsif z.match /[a-zA-Z_0-9]/
token += z
else
tokens << token unless token.empty?
token = ''
tokens << z
end
i += 1
end
tokens << token unless token.empty?
r = 0
in_var = false
tokens.each_with_index do |token, i|
if token == '>>'
if tokens[i - 2] == ':'
parsers << Join.new(
Ref.new(types[tokens[i - 3].to_sym]),
tokens[i - 1][1..-2], as: tokens[i - 3])
else
parsers << Join.new(Ref.new(types[tokens[i - 1].to_sym]), "\n#{' ' * r}", as: tokens[i - 1])
#Many.new(Ref.new(types[tokens[i - 1].to_sym]), as: tokens[i - 1])
end
in_var = false
elsif token == '>'
parsers << Ref.new(types[tokens[i - 1].to_sym])
in_var = false
elsif token == "\n"
parsers << Ref.new(:nl)
if tokens[i + 1] == "\n"
e = 2
elsif tokens[i + 1]
match = tokens[i + 1].match /([ ]+)/
if match.nil? || match.captures.empty?
indent = 0
else
indent = match.captures.first.size / 4
end
if indent > r
parsers << Ref.new(:indent)
elsif indent < r
parsers << Ref.new(:dedent)
end
r = indent
end
elsif token.match(/\A +\z/)
parsers << Ref.new(:ws)
elsif (token == '<<' || token == '<') && tokens[i + 1] >= 'a' && tokens[i + 1] <= 'z'
in_var = true
elsif !in_var
parsers << Lit.new(token)
end
end
# parsers.map { |pa| puts pa.inspect }
parsers.reduce(:&)
end
def self.load_rules(grammar)
lines = grammar.split("\n")
rules = {}
current_rule = nil
rule_body = []
lines.each do |line|
if line.start_with? '#'
if not current_rule.nil?
rule_body << "\n" if rule_body.length > 1
rules[current_rule.to_sym] = rule_body.join("\n")
rule_body = []
end
current_rule = line[1..-1].strip
elsif line.strip != ''
rule_body << line
end
end
rule_body << "\n" if rule_body.length > 1
rules[current_rule.to_sym] = rule_body.join("\n")
rules
end
end
Name = UniversalAST::Name
Number = UniversalAST::Number
Assign = UniversalAST::Assign
Element = UniversalAST::Element
Call = UniversalAST::Call
List = UniversalAST::List
Dictionary = UniversalAST::Dictionary
Pair = UniversalAST::Pair
Attribute = UniversalAST::Attribute
AttributeAssign = UniversalAST::AttributeAssign
IfStatement = UniversalAST::IfStatement
MethodStatement = UniversalAST::MethodStatement
ClassStatement = UniversalAST::ClassStatement
Image = UniversalAST::Image
Operation = UniversalAST::Operation
Float = UniversalAST::Float
Int = UniversalAST::Int
REFS = {
name: Apply.new(Mat.new(/[a-zA-Z][a-zA-Z_]*/)) do |result|
Name.new(result.to_sym)
end,
image: Apply.new(Join.new(Ref.new(:class_statement), "", as: :statements)) do |children|
# d = children.select { |child| child.is_a?(MethodStatement) }
e = children.select { |child| child.is_a?(ClassStatement) }
# obj = e.find { |element| element.is_a?(ClassStatement) && element.class_name == :Object }
# p e[0].class_name
# if obj.nil? && !d.empty?
# obj = ClassStatement.new(Name.new(:Object), d)
# e << obj
# elsif obj
# obj.methods += d
# end
Image.new(e)
end,
statement: Ref.new(:module_statement) | Ref.new(:class_statement) | Ref.new(:method_statement),
number: Ref.new(:float) | Ref.new(:int),
float: Apply.new(Mat.new(/[0-9]+\.[0-9]+/)) do |result|
Float.new(result.to_f)
end,
int: Apply.new(Mat.new(/[0-9]+/)) do |result|
Int.new(result.to_i)
end,
string: Apply.new(Mat.new(/\"[^\"]*\"/)) do |result|
String.new(result[1..-2])
end,
ws: Mat.new(/ +/),
nl: Mat.new(/\n*/),
indent: Lit.new(''),
dedent: Lit.new(''),
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),
expr_no_attr: Ref.new(:number) | Ref.new(:nil) | Ref.new(:name) | Ref.new(:string),
expr_no_call: Ref.new(:binary) | Ref.new(:attribute) | Ref.new(:number) | Ref.new(:name) | Ref.new(:string),
nil: Lit.new('nil'),
name_or_attr: Ref.new(:name) | Ref.new(:attribute),
assign: Apply.new(Ref.new(:_assign)) do |results|
Assign.new(*results.select { |r| r.is_a?(Element) })
end,
attribute_assign: Apply.new(Ref.new(:_attribute_assign)) do |results|
AttributeAssign.new(*results.select { |r| r.is_a?(Element) })
end,
call: Apply.new(Ref.new(:_call)) do |results|
function, args = results.select { |r| r.is_a?(Element) || r.is_a?(Array) }
Call.new(function, args)
end,
list: Apply.new(Ref.new(:_list)) do |results|
List.new(results[1])
end,
dictionary: Apply.new(Ref.new(:_dictionary)) do |results|
Dictionary.new(results[1])
end,
pair: Apply.new(Ref.new(:_pair)) do |results|
key, value = results.select { |r| r.is_a?(Element) }
Pair.new(key, value)
end,
binary: Apply.new(Ref.new(:_binary)) do |results|
if results[0].is_a?(String)
results = results[1..-1]
end
# detect operation intelligently
tokens = results[0], results[2], results[4]
if tokens[0].is_a?(UniversalAST::Operation)
operation, left, right = tokens
elsif tokens[1].is_a?(UniversalAST::Operation)
left, operation, right = tokens
else
left, right, operation = tokens
end
# p results
UniversalAST::Binary.new(left, operation, right)
end,
expr_no_binary: Ref.new(:attribute) | Ref.new(:number) | Ref.new(:name) | Ref.new(:string),
operation: Apply.new(Lit.new('+') | Lit.new('-') | Lit.new('**') | Lit.new('/') | Lit.new('*') | Lit.new('||')) do |result|
Operation.new(result)
end,
attribute: Apply.new(Ref.new(:_attribute)) do |results|
object, label = results.select { |r| r.is_a?(Element) }
Attribute.new(object, label)
end,
if_statement: Apply.new(Ref.new(:_if_statement)) do |results|
test, true_branch, else_branch = results.select { |r| r.is_a?(Element) || r.is_a?(Array) }
IfStatement.new(test, true_branch, else_branch)
end,
method_statement: Apply.new(Ref.new(:_method_statement)) do |results|
method_name, args, body = results.select { |r| r.is_a?(Element) || r.is_a?(Array) }
MethodStatement.new(method_name, args, body)
end,
class_statement: Apply.new(Ref.new(:_class_statement)) do |results|
class_name, methods = results.select { |r| r.is_a?(Element) || r.is_a?(Array) }
ClassStatement.new(class_name, methods)
end,
module_statement: Apply.new(Ref.new(:_module_statement)) do |results|
module_name, classes = results.select { |r| r.is_a?(Element) || r.is_a?(Array) }
ModuleStatement.new(module_name, classes)
end
}
end
================================================
FILE: lib/hivemind/universal_ast.rb
================================================
module Hivemind
module UniversalAST
class Element
def self.fields(*labels)
define_method(:initialize) do |*args|
args.zip(labels).each do |arg, label|
instance_variable_set "@#{label}", arg
end
end
attr_reader *labels
end
def offset(depth)
' ' * depth
end
end
class IfStatement < Element
# if <test>:
# <<true-branch>>
# else:
# <<else-branch>>
fields :test, :true_branch, :else_branch
def render(depth = 0)
"#{offset(depth)}If\n#{offset(depth + 1)}#{@test.render(depth + 1)}\n"
"#{@true_branch.render(depth + 1)}\n#{@else_branch.render(depth + 1)}\n"
end
end
class Assign < Element
# <left> = <right>
fields :left, :right
def render(depth = 0)
"#{offset(depth)}Assign left: #{@left.render} right: #{@right.render}"
end
end
class Attribute < Element
# <object>.<label>
fields :object, :label
def render(depth = 0)
"#{offset(depth)}Attribute : #{@object.render} #{@label.render}"
end
end
class AttributeAssign < Element
# <object>.<label> = <right>
fields :object, :label, :right
def render(depth = 0)
"#{offset(depth)}AttributeAssign : #{@object.render} #{@label.render} #{@right.render}"
end
end
class Call < Element
# <function>(<<args:', '>>)
fields :function, :args
def render(depth = 0)
"#{offset(depth)}Call\n#{@function.render(depth + 1)}\n#{offset(depth + 1)}#{@args.map(&:render).join(' ')}\n"
end
end
class List < Element
# [el1, el2..]
fields :elements
def render(depth = 0)
"#{offset(depth)}List\n#{@elements.map { |e| e.render(depth + 1) }.join("\n")}"
end
end
class Dictionary < Element
# {key1: val1, key2: val2..}
fields :pairs
end
class Binary < Element
# <left> <operation> <right>
fields :left, :operation, :right
def render(depth = 0)
"#{offset(depth)}Binary #{@left.render} #{@operation.value} #{@right.render}"
end
end
class MethodStatement < Element
# method <method-name>(<<args:', '):
# <<body>>
fields :method_name, :args, :body
def render(depth = 0)
"#{offset(depth)}MethodStatement #{@method_name.value} #{@args.map(&:render).join(' ')}\n" +
"#{@body.map { |e| e.render(depth + 1) }.join("\n")}\n"
end
end
class ClassStatement < Element
# type <class-name>:
# <<methods>>
fields :class_name, :methods
def render(depth = 0)
"#{offset(depth)}ClassStatement #{@class_name.value}\n" +
"#{@methods.map { |e| e.render(depth + 1) }.join("\n")}\n"
end
end
class Value < Element
fields :value
def render(depth = 0)
"#{offset(depth)}#{@value}"
end
end
class Name < Value
end
class String < Value
end
class Number < Value
end
class Int < Number
end
class Float < Number
end
class Operation < Value
end
class ModuleStatement < Element
# module <module-name>:
# <<children>>
fields :module_name, :elements
end
class Pair < Element
# key => value
fields :key, :value
end
class Image < Element
fields :statements
def render(depth = 0)
@statements.map(&:render).join "\n"
end
end
end
end
================================================
FILE: lib/hivemind/vm.rb
================================================
require_relative 'runtime'
require_relative 'universal_ast'
module Hivemind
class VM
def initialize(ast)
@ast = ast
end
def run(env)
@ast.run env
end
end
class Runtime::HivemindObject
def call(function, args, env)
if function.is_a?(UniversalAST::MethodStatement)
args_values = {:self => self}
function.args[1..-1].zip(args) do |label, arg|
args_values[label.value.to_sym] = arg
end
body_env = Environment.new(env, **args_values)
function.body.map { |expr| expr.run(body_env) }[-1] || env.top[:@nil]
else
function.call self, *args, env
end
end
end
class Runtime::HivemindClass
def call(function, args, env)
h = Runtime::HivemindObject.new({}, self)
function = dispatch_method(:init)
if function.is_a?(UniversalAST::MethodStatement)
args_values = {:self => h}
function.args[1..-1].zip(args) do |label, arg|
args_values[label.value.to_sym] = arg
end
body_env = Environment.new(env, **args_values)
function.body.map { |expr| expr.run(body_env) }[-1] || env.top[:@nil]
else
function.call h, *args, env
end
h
end
end
module UniversalAST
class Image
def run(env)
@statements.each do |statement|
statement.run(env)
end
# puts env.top[:Object].methods.keys
if env.top[:Object].methods.key? :start
weird_object = Runtime::hivemind_object({})
weird_object.call(env.top[:Object].methods[:start], [], env)
else
env.top[:@nil]
end
end
end
class ModuleStatement
def run(env)
module_statement = Runtime::HivemindModule.new(@module_name)
@statements.each do |statement|
module_statement.elements[@statement.is_a?(ModuleStatement) ? @statement.module_name : @statement.class_name] =
statement.run(env)
end
env
end
end
class If
def run(env)
if @test.run(env) == env.top[:@true]
@true_branch.run env
else
@else_branch.run env
end
end
end
class Assign
def run(env)
env[@left.value.to_sym] = @right.run(env)
end
end
class Attribute
def run(env)
obj = @object.run(env)
env.current_self = obj
if obj.respond_to?(:data)
if obj.data.key? @label.value
obj.data[@label.value]
else
method = obj.klass.dispatch_method(@label.value)
if method
method
else
raise HivemindAccessError.new("No #{@label.value} in obj")
end
end
else
obj.methods[@label.value]
end
end
end
class AttributeAssign
def run(env)
@object.run(env).data[@label.value] = @right.run(env)
end
end
class Call
def run(env)
if !@function.is_a?(Attribute)
function = @function.run(env)
env.current_self.call(function, @args.map { |arg| arg.run(env) }, env)
elsif @function.label.value != :new
obj = @function.object.run(env)
function = obj.klass.dispatch_method(@function.label.value)
obj.call(function, @args.map { |arg| arg.run(env) }, env)
else
obj = @function.object.run(env)
function == obj.dispatch_method(:init)
obj.call(function, @args.map { |arg| arg.run(env) }, env)
end
end
end
class Binary
def run(env)
Runtime::hivemind_numbr(@left.run(env).data[:_value].send(@operation.value, @right.run(env).data[:_value]))
end
end
class List
def run(env)
Runtime::HivemindObject.new({_elements: @elements.map { |elem| elem.run(env) }}, env.top[:List])
end
end
class Dictionary
def run(env)
dict = {}
@pairs.each do |pair|
dict[pair.key.value.to_sym] = pair.value.run(env)
end
Runtime::HivemindObject.new({_dict: dict}, env.top[:Dict])
end
end
class Value
def run(env)
Runtime::HivemindObject.new({_value: @value}, env.top[self.class.name.split('::').last.to_sym])
end
end
class ClassStatement
def run(env)
definition = env.fetch(@class_name.value) || Runtime::HivemindClass.new(@class_name.value, env.top[:Object], {})
@methods.each do |method|
definition.methods[method.method_name.value] = method
end
env[@class_name.value] = definition
end
end
class MethodStatement
def run(env)
self
end
end
class Name
def run(env)
env[@value]
end
end
end
end
================================================
FILE: lib/hivemind.rb
================================================
require_relative 'hivemind/universal_ast'
require_relative 'hivemind/environment'
require_relative 'hivemind/vm'
require_relative 'hivemind/runtime'
require_relative 'hivemind/syntax'
require_relative 'hivemind/renderer'
================================================
FILE: spec/hivemind/parser_spec.rb
================================================
================================================
FILE: spec/hivemind/universal_ast_spec.rb
================================================
require 'spec_helper'
module Hivemind
module UniversalAST
describe Element do
it 'fields initializes a class with given labels' do
class A < Element
fields :a
end
expect(A.new(2).a).to eq(2)
end
end
describe ModuleStatement do
it 'is initialized with an elements attribute' do
mod = ModuleStatement.new('ha', [])
expect(mod.elements).to eq([])
end
end
end
end
================================================
FILE: spec/hivemind/vm_spec.rb
================================================
require 'spec_helper'
module Hivemind
describe VM do
it 'should work for a program with a single number' do
vm = VM.new UniversalAST::Number.new(44)
expect(vm.run(Runtime::HivemindEnv).data[:_value]).to eq 44
end
end
end
================================================
FILE: spec/spec_helper.rb
================================================
# well, really, no time for a lot of tests now
# dirty fast prototyping
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$LOAD_PATH.unshift(File.dirname(__FILE__))
require 'rspec'
require 'hivemind'
================================================
FILE: syntaxes/lolcode.syntax
================================================
#if_statement
<test> O RLY
YA RLY
<<true_branch>>
NO WAI
<<else_branch>>
#assign
DO <left> <right>
#method_statement
HOW DUZ I <method_name>(<<args:' '>>)
<<body>>
IF U SAY SO
#attribute
<object> HEY <label>
#attribute_assign
<object> BE <label> <right>
#call
GIMME <function> (<<args:' '>>)
#class_statement
TOM SAYS <class_name>
<<methods>>
LOVE
#module_statement
HAI <module_name>
<<elements>>
KTHXBYE
================================================
FILE: syntaxes/paren.syntax
================================================
#if_statement
(if <test>
<true_branch>
<else_branch>)
#assign
(define <left> <right>)
#method_statement
(method <method_name> (<<args:' '>>)
<<body>>)
#attribute
<object>.<label>
#attribute_assign
(update <object>.<label> <right>)
#binary
(<operation> <left> <right>)
#call
(! <function> <<args:' '>>)
#list
_(<<elements:' '>>)
#class_statement
(class <class_name>
<<methods>>)
#module_statement
(module <module_name>
<<elements>>)
================================================
FILE: syntaxes/pythonic.syntax
================================================
#if_statement
if <test>:
<true_branch>
else:
<else_branch>
#assign
<left> = <right>
#call
<function>(<<args:', '>>)
#attribute
<object>.<label>
#attribute_assign
<object>.<label> = <right>
#binary
<left> <operation> <right>
#list
[<<elements:', '>>]
#method_statement
method <method_name>(<<args:', '>>):
<<body>>
#class_statement
class <class_name>:
<<methods:''>>
#module_statement
module <module_name>:
<<elements>>
gitextract_mc_17_3g/
├── .gitignore
├── .travis.yml
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── bin/
│ └── hivemind
├── examples/
│ ├── a.hm
│ ├── a_paren.hm
│ ├── b.hm
│ ├── shape.hm
│ ├── shape_paren.hm
│ └── shape_pythonic.hm
├── hivemind.gemspec
├── lib/
│ ├── hivemind/
│ │ ├── code_viewer.rb
│ │ ├── combinators.rb
│ │ ├── environment.rb
│ │ ├── errors.rb
│ │ ├── renderer.rb
│ │ ├── runtime.rb
│ │ ├── syntax.rb
│ │ ├── universal_ast.rb
│ │ └── vm.rb
│ └── hivemind.rb
├── spec/
│ ├── hivemind/
│ │ ├── parser_spec.rb
│ │ ├── universal_ast_spec.rb
│ │ └── vm_spec.rb
│ └── spec_helper.rb
└── syntaxes/
├── lolcode.syntax
├── paren.syntax
└── pythonic.syntax
SYMBOL INDEX (149 symbols across 10 files)
FILE: lib/hivemind/combinators.rb
class Combinator (line 3) | class Combinator
method & (line 4) | def &(other)
method | (line 8) | def |(other)
class Lit (line 13) | class Lit < Combinator
method initialize (line 16) | def initialize(value)
method parse (line 20) | def parse(input, refs)
class Mat (line 29) | class Mat < Combinator
method initialize (line 32) | def initialize(regex)
method parse (line 36) | def parse(input, refs)
class Binary (line 46) | class Binary < Combinator
method initialize (line 49) | def initialize(first, second)
class And (line 54) | class And < Binary
method parse (line 55) | def parse(input, refs)
method combine (line 66) | def combine(first_result, second_result)
class Or (line 75) | class Or < Binary
method parse (line 76) | def parse(input, refs)
class Many (line 85) | class Many < Combinator
method initialize (line 88) | def initialize(parser, as: nil)
method parse (line 92) | def parse(input, refs)
class Join (line 104) | class Join < Combinator
method initialize (line 107) | def initialize(parser, separator, as: nil)
method parse (line 115) | def parse(input, refs)
class Ref (line 142) | class Ref < Combinator
method initialize (line 145) | def initialize(label, as: nil)
method parse (line 150) | def parse(input, refs)
class Maybe (line 156) | class Maybe < Combinator
method initialize (line 159) | def initialize(parser)
method parse (line 163) | def parse(input, refs)
class Apply (line 169) | class Apply < Combinator
method initialize (line 173) | def initialize(parser, &transformation)
method parse (line 177) | def parse(input, refs)
function literal (line 184) | def literal(value)
function many (line 188) | def many(combinator)
function maybe (line 192) | def maybe(combinator)
function apply (line 196) | def apply(combinator, &transformation)
function match (line 200) | def match(regex)
FILE: lib/hivemind/environment.rb
type Hivemind (line 3) | module Hivemind
class Environment (line 4) | class Environment
method initialize (line 8) | def initialize(parent, **values)
method [] (line 12) | def [](key)
method fetch (line 18) | def fetch(key)
method []= (line 27) | def []=(key, value)
FILE: lib/hivemind/errors.rb
type Hivemind (line 1) | module Hivemind
class HivemindMissingNameError (line 2) | class HivemindMissingNameError < StandardError
class HivemindAccessError (line 5) | class HivemindAccessError < StandardError
FILE: lib/hivemind/renderer.rb
type Hivemind (line 3) | module Hivemind
class Renderer (line 31) | class Renderer
method initialize (line 32) | def initialize(tree, syntax)
method render (line 37) | def render(depth = 0)
method offset (line 41) | def offset(depth = 0)
method render_element (line 45) | def render_element(element, depth = 0)
method render_template (line 56) | def render_template(plan, element, depth = 0)
FILE: lib/hivemind/runtime.rb
type Hivemind (line 3) | module Hivemind
type Runtime (line 4) | module Runtime
class HivemindObject (line 5) | class HivemindObject
method initialize (line 8) | def initialize(data, klass)
class HivemindClass (line 13) | class HivemindClass
method initialize (line 16) | def initialize(label, parent = nil, methods = {})
method define_hivemind_method (line 20) | def define_hivemind_method(label, &handler)
method dispatch_method (line 24) | def dispatch_method(label)
class HivemindModule (line 33) | class HivemindModule
method initialize (line 36) | def initialize(label, elements = [])
function hivemind_string (line 41) | def self.hivemind_string(value)
function hivemind_numbr (line 45) | def self.hivemind_numbr(value)
function hivemind_object (line 49) | def self.hivemind_object(data)
FILE: lib/hivemind/syntax.rb
type Hivemind (line 3) | module Hivemind
class Syntax (line 104) | class Syntax
method generate_syntax (line 105) | def self.generate_syntax(bidirectional_grammar)
method initialize (line 109) | def initialize(grammar)
method generate (line 113) | def generate
method parse_rule (line 126) | def parse_rule(rule, types)
method load_rules (line 230) | def self.load_rules(grammar)
FILE: lib/hivemind/universal_ast.rb
type Hivemind (line 1) | module Hivemind
type UniversalAST (line 2) | module UniversalAST
class Element (line 3) | class Element
method fields (line 4) | def self.fields(*labels)
method offset (line 13) | def offset(depth)
class IfStatement (line 18) | class IfStatement < Element
method render (line 26) | def render(depth = 0)
class Assign (line 32) | class Assign < Element
method render (line 37) | def render(depth = 0)
class Attribute (line 42) | class Attribute < Element
method render (line 47) | def render(depth = 0)
class AttributeAssign (line 52) | class AttributeAssign < Element
method render (line 57) | def render(depth = 0)
class Call (line 62) | class Call < Element
method render (line 67) | def render(depth = 0)
class List (line 72) | class List < Element
method render (line 77) | def render(depth = 0)
class Dictionary (line 82) | class Dictionary < Element
class Binary (line 88) | class Binary < Element
method render (line 93) | def render(depth = 0)
class MethodStatement (line 98) | class MethodStatement < Element
method render (line 104) | def render(depth = 0)
class ClassStatement (line 110) | class ClassStatement < Element
method render (line 116) | def render(depth = 0)
class Value (line 122) | class Value < Element
method render (line 125) | def render(depth = 0)
class Name (line 130) | class Name < Value
class String (line 133) | class String < Value
class Number (line 136) | class Number < Value
class Int (line 139) | class Int < Number
class Float (line 142) | class Float < Number
class Operation (line 145) | class Operation < Value
class ModuleStatement (line 148) | class ModuleStatement < Element
class Pair (line 155) | class Pair < Element
class Image (line 160) | class Image < Element
method render (line 163) | def render(depth = 0)
FILE: lib/hivemind/vm.rb
type Hivemind (line 4) | module Hivemind
class VM (line 5) | class VM
method initialize (line 6) | def initialize(ast)
method run (line 10) | def run(env)
class Runtime::HivemindObject (line 15) | class Runtime::HivemindObject
method call (line 16) | def call(function, args, env)
class Runtime::HivemindClass (line 30) | class Runtime::HivemindClass
method call (line 31) | def call(function, args, env)
type UniversalAST (line 48) | module UniversalAST
class Image (line 49) | class Image
method run (line 50) | def run(env)
class ModuleStatement (line 64) | class ModuleStatement
method run (line 65) | def run(env)
class If (line 75) | class If
method run (line 76) | def run(env)
class Assign (line 85) | class Assign
method run (line 86) | def run(env)
class Attribute (line 91) | class Attribute
method run (line 92) | def run(env)
class AttributeAssign (line 113) | class AttributeAssign
method run (line 114) | def run(env)
class Call (line 119) | class Call
method run (line 120) | def run(env)
class Binary (line 136) | class Binary
method run (line 137) | def run(env)
class List (line 142) | class List
method run (line 143) | def run(env)
class Dictionary (line 148) | class Dictionary
method run (line 149) | def run(env)
class Value (line 158) | class Value
method run (line 159) | def run(env)
class ClassStatement (line 164) | class ClassStatement
method run (line 165) | def run(env)
class MethodStatement (line 174) | class MethodStatement
method run (line 175) | def run(env)
class Name (line 180) | class Name
method run (line 181) | def run(env)
FILE: spec/hivemind/universal_ast_spec.rb
type Hivemind (line 3) | module Hivemind
type UniversalAST (line 4) | module UniversalAST
class A (line 7) | class A < Element
FILE: spec/hivemind/vm_spec.rb
type Hivemind (line 3) | module Hivemind
Condensed preview — 31 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (47K chars).
[
{
"path": ".gitignore",
"chars": 342,
"preview": "#Logs\napplication/logs/*.php\n\n# Content types\n/application/xml/types/*.xml\n\n# Custom builds and generated php files\n/cor"
},
{
"path": ".travis.yml",
"chars": 59,
"preview": "language: ruby\nrvm:\n - 2.2.3\nscript:\n - bundle exec rake\n"
},
{
"path": "Gemfile",
"chars": 122,
"preview": "source 'https://rubygems.org'\n\ngroup :development, :test do\n gem 'bundler'\n gem 'rspec'\n gem 'skeptic'\n gem 'rake'\ne"
},
{
"path": "LICENSE",
"chars": 1083,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2016 Alexander Ivanov\n\nPermission is hereby granted, free of charge, to any person "
},
{
"path": "README.md",
"chars": 2777,
"preview": "[](https://travis-ci.org/alehander42/hivemi"
},
{
"path": "Rakefile",
"chars": 415,
"preview": "require 'rubygems'\nrequire 'bundler'\nbegin\n Bundler.setup(:default, :development)\nrescue Bundler::BundlerError => e\n $"
},
{
"path": "bin/hivemind",
"chars": 1523,
"preview": "#!/usr/bin/env ruby\n\n$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))\n\nrequire 'hivemind'\n\nSYNTAXES_PA"
},
{
"path": "examples/a.hm",
"chars": 90,
"preview": "syntax: pythonic\n\nclass Object:\n method start(self):\n e = 2\n e.display()\n"
},
{
"path": "examples/a_paren.hm",
"chars": 166,
"preview": "syntax: paren\n\n(class Rectangle\n (method init (self a b)\n (update self.a a)\n (update self.b b))\n\n (m"
},
{
"path": "examples/b.hm",
"chars": 150,
"preview": "syntax: pythonic\n\nclass Rectangle:\n method init(self, a, b):\n self.a = a\n self.b = b\n\n method area(s"
},
{
"path": "examples/shape.hm",
"chars": 444,
"preview": "syntax: pythonic\n\nclass Rectangle:\n method init(self, a, b):\n self.a = a\n self.b = b\n\n method area(s"
},
{
"path": "examples/shape_paren.hm",
"chars": 520,
"preview": "syntax: paren\n\n(class Rectangle\n (method init (self a b)\n (update self.a a)\n (update self.b b))\n\n (m"
},
{
"path": "examples/shape_pythonic.hm",
"chars": 433,
"preview": "syntax: pythonic\n\nclass Rectangle:\n method init(self, a, b):\n self.a = a\n self.b = b\n\n method area(s"
},
{
"path": "hivemind.gemspec",
"chars": 1636,
"preview": "# Generated by jeweler\n# DO NOT EDIT THIS FILE DIRECTLY\n# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspe"
},
{
"path": "lib/hivemind/code_viewer.rb",
"chars": 1197,
"preview": "# 'universal_ast'\n\n# module Hivemind\n# class CodeViewer\n# def initialize(tree)\n# @tree = tree\n# end\n\n# "
},
{
"path": "lib/hivemind/combinators.rb",
"chars": 4076,
"preview": "require_relative 'universal_ast'\n\nclass Combinator\n def &(other)\n And.new(self, other)\n end\n\n def |(other)\n Or."
},
{
"path": "lib/hivemind/environment.rb",
"chars": 681,
"preview": "require_relative 'errors'\n\nmodule Hivemind\n class Environment\n attr_reader :parent, :values, :top\n attr_accessor "
},
{
"path": "lib/hivemind/errors.rb",
"chars": 126,
"preview": "module Hivemind\n class HivemindMissingNameError < StandardError\n end\n\n class HivemindAccessError < StandardError\n en"
},
{
"path": "lib/hivemind/renderer.rb",
"chars": 1991,
"preview": "require_relative 'syntax'\n\nmodule Hivemind\n \n BASE_RULES = {\n image: -> element, depth = 0 do\n element.stateme"
},
{
"path": "lib/hivemind/runtime.rb",
"chars": 2819,
"preview": "require_relative 'environment'\n\nmodule Hivemind\n module Runtime\n class HivemindObject\n attr_reader :data, :klas"
},
{
"path": "lib/hivemind/syntax.rb",
"chars": 11827,
"preview": "require_relative 'combinators'\n\nmodule Hivemind\n\n # BaseGrammar = Phoenix::Grammar.new\n # BaseGrammar.rules = {\n # "
},
{
"path": "lib/hivemind/universal_ast.rb",
"chars": 3554,
"preview": "module Hivemind\n module UniversalAST\n class Element\n def self.fields(*labels)\n define_method(:initialize"
},
{
"path": "lib/hivemind/vm.rb",
"chars": 4817,
"preview": "require_relative 'runtime'\nrequire_relative 'universal_ast'\n\nmodule Hivemind\n class VM\n def initialize(ast)\n @a"
},
{
"path": "lib/hivemind.rb",
"chars": 221,
"preview": "require_relative 'hivemind/universal_ast'\nrequire_relative 'hivemind/environment'\nrequire_relative 'hivemind/vm'\nrequire"
},
{
"path": "spec/hivemind/parser_spec.rb",
"chars": 0,
"preview": ""
},
{
"path": "spec/hivemind/universal_ast_spec.rb",
"chars": 469,
"preview": "require 'spec_helper'\n\nmodule Hivemind\n module UniversalAST\n describe Element do\n it 'fields initializes a clas"
},
{
"path": "spec/hivemind/vm_spec.rb",
"chars": 246,
"preview": "require 'spec_helper'\n\nmodule Hivemind\n describe VM do\n it 'should work for a program with a single number' do\n "
},
{
"path": "spec/spec_helper.rb",
"chars": 218,
"preview": "# well, really, no time for a lot of tests now\n# dirty fast prototyping\n\n$LOAD_PATH.unshift(File.join(File.dirname(__FIL"
},
{
"path": "syntaxes/lolcode.syntax",
"chars": 441,
"preview": "#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#m"
},
{
"path": "syntaxes/paren.syntax",
"chars": 461,
"preview": "#if_statement\n(if <test>\n <true_branch>\n <else_branch>)\n\n#assign\n(define <left> <right>)\n\n#method_statement\n(metho"
},
{
"path": "syntaxes/pythonic.syntax",
"chars": 449,
"preview": "#if_statement\nif <test>:\n <true_branch>\nelse:\n <else_branch>\n\n#assign\n<left> = <right>\n\n#call\n<function>(<<args:',"
}
]
About this extraction
This page contains the full source code of the alehander42/hivemind GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 31 files (42.3 KB), approximately 12.7k tokens, and a symbol index with 149 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.