Permalink
Browse files

Initial commit

  • Loading branch information...
0 parents commit fcc79112b0bf93d6b8f59a9eae892996331496b5 @rkh committed Jan 26, 2011
Showing with 265 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +83 −0 README.md
  3. +10 −0 convinius.gemspec
  4. +1 −0 lib/convinius.rb
  5. +38 −0 lib/convinius/asm.rb
  6. +12 −0 lib/convinius/generator.rb
  7. +20 −0 lib/convinius/to_class.rb
  8. +32 −0 spec/asm_spec.rb
  9. +17 −0 spec/generator_spec.rb
  10. +3 −0 spec/spec_helper.rb
  11. +48 −0 spec/to_class_spec.rb
@@ -0,0 +1 @@
+.rvmrc
@@ -0,0 +1,83 @@
+Convinius
+=========
+
+Convenience library for Rubinius-only projects.
+Use `require 'convinius'` to get all features.
+
+Installation:
+
+ gem install convinius
+
+Running tests:
+
+ gem install rspec
+ rspec spec
+
+Subclassing from arbitrary Objects
+----------------------------------
+in: `convinius/to_class`
+
+If you subclass from an object, first call `to_class` on that object and
+subclass the result instead:
+
+ RandomClass = Object.new
+
+ def RandomClass.to_class
+ [Hash, Object, Set].at rand(3)
+ end
+
+ class Foo < RandomClass
+ puts superclass
+ end
+
+A more realistic example:
+
+ module Awesome
+ def self.to_class
+ Class.new { include Awesome }
+ end
+ end
+
+ class Foo < Awesome
+ end
+
+ class Bar < Something
+ include Awesome
+ end
+
+Convenience for Rubinius::Generator
+-----------------------------------
+in: `convinius/generator`
+
+Method for generating tuples (like `make_array`):
+
+ class MyNode < Rubinius::AST::Node
+ def bytecode(g)
+ (1..5).each { |i| g.push i }
+ g.make_tuple 5
+ end
+ end
+
+Byte Code Generator DSL
+-----------------------
+in: `convinius/asm`
+
+Example:
+
+ include Convinius::ASM
+
+ compiled = asm do
+ push 1
+ push 2
+ send :+, 1
+ end
+
+ p compiled.call
+
+If block takes an argument, it won't use `instance_eval`:
+
+ Convinius::ASM.new do |g|
+ g.push 1
+ g.push 2
+ g.send :+, 1
+ end
@@ -0,0 +1,10 @@
+Gem::Specification.new do |s|
+ s.name = 'convinius'
+ s.version = '0.1.0'
+ s.date = '2011-01-26'
+ s.description = 'Convenience library for Rubinius-only projects.'
+ s.summary = s.description
+ s.authors = ['Konstantin Haase']
+ s.email = 'k.haase@finn.de'
+ s.files = `git ls-files`.split("\n")
+end
@@ -0,0 +1 @@
+require 'convinius/to_class'
@@ -0,0 +1,38 @@
+module Convinius
+ module ASM
+ extend self
+
+ def asm(file = "(asm)", line = 1, method = :call, &block)
+ g = Rubinius::Generator.new
+ g.name = method.to_sym
+ g.file = file.to_sym
+ g.set_line line
+
+ g.required_args = 0
+ g.total_args = 0
+ g.splat_index = nil
+
+ g.local_count = 0
+ g.local_names = []
+
+ block.arity > 0 ? yield(g) : g.instance_eval(&block)
+
+ g.ret
+ g.close
+
+ g.encode
+ cm = g.package Rubinius::CompiledMethod
+ puts cm.decode if $DEBUG
+
+ code = Object.new
+ ss = Rubinius::StaticScope.new Object
+ Rubinius.attach_method g.name, cm, ss, code
+
+ code
+ end
+
+ class << self
+ alias new asm
+ end
+ end
+end
@@ -0,0 +1,12 @@
+module Convinius
+ module Generator
+ append_features Rubinius::Generator
+
+ def make_tuple(count)
+ push_rubinius
+ find_const :Tuple
+ move_down count
+ send :[], count
+ end
+ end
+end
@@ -0,0 +1,20 @@
+module Convinius
+ module ToClass
+ module ClassMethods
+ extend_object Class
+
+ def new(sclass = Object, *args)
+ sclass = sclass.to_class if sclass.respond_to? :to_class
+ super(sclass, *args)
+ end
+ end
+
+ module InstanceMethods
+ append_features Class
+
+ def to_class
+ self
+ end
+ end
+ end
+end
@@ -0,0 +1,32 @@
+require 'convinius/asm'
+require 'spec_helper'
+
+describe Convinius::ASM do
+ context 'asm with instance_eval' do
+ include Convinius::ASM
+
+ subject do
+ asm do
+ push 1
+ push 2
+ send :+, 1
+ end
+ end
+
+ it { should respond_to(:call) }
+ it { should evaluate_to(3) }
+ end
+
+ context 'new without instance_eval' do
+ subject do
+ Convinius::ASM.new do |g|
+ g.push 1
+ g.push 2
+ g.send :+, 1
+ end
+ end
+
+ it { should respond_to(:call) }
+ it { should evaluate_to(3) }
+ end
+end
@@ -0,0 +1,17 @@
+require 'convinius/asm'
+require 'convinius/generator'
+require 'spec_helper'
+
+describe Convinius::Generator do
+ context 'make_tuple' do
+ subject do
+ Convinius::ASM.new do
+ push 1
+ push 2
+ make_tuple 2
+ end
+ end
+
+ it { should evaluate_to(Rubinius::Tuple[1, 2]) }
+ end
+end
@@ -0,0 +1,3 @@
+RSpec::Matchers.define(:evaluate_to) do |result|
+ match { |cm| cm.call.should == result }
+end
@@ -0,0 +1,48 @@
+require 'convinius/to_class'
+
+describe Convinius::ToClass do
+ subject do
+ class_loop = Object.new
+
+ class << class_loop
+ attr_accessor :pos
+ attr_accessor :list
+
+ def to_class
+ sclass = list.at(pos % list.size)
+ self.pos += 1
+ sclass
+ end
+ end
+
+ class_loop
+ end
+
+ before do
+ subject.pos = 0
+ end
+
+ it 'should not break normal subclassing' do
+ class Foo; end
+ class Bar < Foo; end
+ Foo.superclass.should == Object
+ Bar.superclass.should == Foo
+ end
+
+ it 'should allow custom subclassing logic' do
+ subject.list = [Object, Array, Hash]
+ Class.new(subject).superclass == Object
+ Class.new(subject).superclass == Array
+ Class.new(subject).superclass == Hash
+ end
+
+ it 'should work with subclassing syntax' do
+ subject.list = [Object, Array, Hash]
+ class FromObject < subject; end
+ class FromArray < subject; end
+ class FromHash < subject; end
+ FromObject.superclass.should == Object
+ FromArray.superclass.should == Array
+ FromHash.superclass.should == Hash
+ end
+end

0 comments on commit fcc7911

Please sign in to comment.