stitcher 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/README.md +107 -0
- data/Rakefile +7 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/docs/matome.md +57 -0
- data/docs/stitcher.md +208 -0
- data/docs/type.md +212 -0
- data/docs/typed.md +15 -0
- data/example/core_ex.rb +23 -0
- data/example/register.rb +33 -0
- data/example/simple.rb +66 -0
- data/example/type.rb +24 -0
- data/lib/stitcher.rb +40 -0
- data/lib/stitcher/accessor.rb +21 -0
- data/lib/stitcher/concepts.rb +6 -0
- data/lib/stitcher/core.rb +31 -0
- data/lib/stitcher/core_ext.rb +7 -0
- data/lib/stitcher/define_method.rb +52 -0
- data/lib/stitcher/operators.rb +37 -0
- data/lib/stitcher/register.rb +31 -0
- data/lib/stitcher/require.rb +27 -0
- data/lib/stitcher/stitch.rb +22 -0
- data/lib/stitcher/type.rb +107 -0
- data/lib/stitcher/type/core_ext.rb +11 -0
- data/lib/stitcher/variadic_argument.rb +12 -0
- data/lib/stitcher/version.rb +3 -0
- data/stitcher.gemspec +25 -0
- metadata +117 -0
data/docs/typed.md
ADDED
data/example/core_ex.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# original source code
|
2
|
+
# http://melborne.github.io/2013/08/30/monkey-patching-for-prudent-rubyists/
|
3
|
+
require "stitcher"
|
4
|
+
|
5
|
+
using Stitcher
|
6
|
+
|
7
|
+
class Array
|
8
|
+
stitcher_require +[Fixnum, Fixnum]
|
9
|
+
def at *indices
|
10
|
+
at(indices.shift).at(*indices)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
p [1,2,3].at(1)
|
15
|
+
# => 1
|
16
|
+
p [[1,2,3], [4,5,6], [7,8,9]].at(1, 2)
|
17
|
+
# => 6
|
18
|
+
p [
|
19
|
+
[[1,2,3],[4,5,6],[7,8,9]],
|
20
|
+
[[10,11,12],[13,14,15],[16,17,18]],
|
21
|
+
[[19,20,21],[22,23,24],[25,26,27]]
|
22
|
+
].at(1, 2, 0)
|
23
|
+
# => 16
|
data/example/register.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require "stitcher"
|
2
|
+
|
3
|
+
class X
|
4
|
+
extend Stitcher::Register
|
5
|
+
|
6
|
+
def initialize value
|
7
|
+
@value = value
|
8
|
+
end
|
9
|
+
# Register method argument types.
|
10
|
+
stitcher_register :initialize, [Fixnum]
|
11
|
+
|
12
|
+
# Define multi methods.
|
13
|
+
def plus a
|
14
|
+
@value + a
|
15
|
+
end
|
16
|
+
stitcher_register :plus, [Fixnum]
|
17
|
+
|
18
|
+
def plus a
|
19
|
+
@value + a.to_i
|
20
|
+
end
|
21
|
+
stitcher_register :plus, [String]
|
22
|
+
end
|
23
|
+
|
24
|
+
x = X.new 10
|
25
|
+
# x = X.new "10" # Error: No match method.
|
26
|
+
|
27
|
+
# Call X#plus(Fixnum)
|
28
|
+
p x.plus -3
|
29
|
+
# => 7
|
30
|
+
|
31
|
+
# Call X#plus(String)
|
32
|
+
p x.plus "42"
|
33
|
+
# => 57
|
data/example/simple.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require "stitcher"
|
2
|
+
|
3
|
+
# Using stitcher library.
|
4
|
+
using Stitcher
|
5
|
+
|
6
|
+
class Person
|
7
|
+
# Define accessor with variable type(Class).
|
8
|
+
stitcher_accessor name: String, age: Integer
|
9
|
+
|
10
|
+
def set name, age
|
11
|
+
self.name = name
|
12
|
+
self.age = age
|
13
|
+
end
|
14
|
+
# Register set method with Argument types(Classes).
|
15
|
+
stitch :set, [String, Integer]
|
16
|
+
|
17
|
+
# Register for next define method.
|
18
|
+
stitcher_require [Hash]
|
19
|
+
def set hash
|
20
|
+
set hash[:name], hash[:age]
|
21
|
+
end
|
22
|
+
|
23
|
+
# Define "set" method with Argument types.
|
24
|
+
# set(Integer, String)
|
25
|
+
stitcher_define_method(:set, age: Integer, name: String){
|
26
|
+
self.name = name
|
27
|
+
self.age = age
|
28
|
+
}
|
29
|
+
|
30
|
+
# Other define method
|
31
|
+
stitch.set(ary: [String, Integer]){
|
32
|
+
set *ary
|
33
|
+
}
|
34
|
+
|
35
|
+
def print
|
36
|
+
p "name:#{name} age:#{age}"
|
37
|
+
end
|
38
|
+
|
39
|
+
# Require format with block object.
|
40
|
+
stitcher_require [String] & Stitcher::Concepts.blockable
|
41
|
+
def print fmt
|
42
|
+
printf(fmt, *yield(name, age))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
x = X.new
|
47
|
+
x.name = "homu"
|
48
|
+
x.age = 14
|
49
|
+
# x.age = 14.0 # Error: No match method.
|
50
|
+
|
51
|
+
x.set "mami", 15
|
52
|
+
x.print
|
53
|
+
# => "name:mami age:15"
|
54
|
+
|
55
|
+
x.set({ name: "saya", age: 14 })
|
56
|
+
x.print
|
57
|
+
# => "name:saya age:14"
|
58
|
+
|
59
|
+
x.set 14, "mado"
|
60
|
+
x.print("%s-%s\n"){ |name, age| [name, age] }
|
61
|
+
# => mado-14
|
62
|
+
|
63
|
+
x.set ["homu", 14]
|
64
|
+
x.print("%s-%s\n"){ |name, age| [age, name] }
|
65
|
+
# => 14-homu
|
66
|
+
|
data/example/type.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require "stitcher"
|
2
|
+
using Stitcher::Refinements::Type
|
3
|
+
|
4
|
+
# Object to Type.
|
5
|
+
# Type is Class object.
|
6
|
+
1.type # => Fixnum Type
|
7
|
+
"homu".type # => String Type
|
8
|
+
Numeric.type # => Numeric Type
|
9
|
+
|
10
|
+
|
11
|
+
# Operator is like Class object operators.
|
12
|
+
1.type == Fixnum # => true
|
13
|
+
1.type == Numeric # => false
|
14
|
+
1.type <= Numeric # => true
|
15
|
+
|
16
|
+
|
17
|
+
# Using | operator.
|
18
|
+
# Example: Define Boolean type
|
19
|
+
Boolean = TrueClass | FalseClass
|
20
|
+
|
21
|
+
Boolean == true # => true
|
22
|
+
Boolean == false # => true
|
23
|
+
Boolean == nil # => false
|
24
|
+
Boolean == 0 # => false
|
data/lib/stitcher.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative "./stitcher/version"
|
2
|
+
# require_relative "./stitcher/type"
|
3
|
+
require_relative "./stitcher/define_method"
|
4
|
+
require_relative "./stitcher/accessor"
|
5
|
+
require_relative "./stitcher/stitch"
|
6
|
+
require_relative "./stitcher/operators"
|
7
|
+
require_relative "./stitcher/require"
|
8
|
+
require_relative "./stitcher/variadic_argument"
|
9
|
+
require_relative "./stitcher/core"
|
10
|
+
require_relative "./stitcher/concepts"
|
11
|
+
|
12
|
+
module Stitcher
|
13
|
+
include Accessor
|
14
|
+
include Stitch
|
15
|
+
include Require
|
16
|
+
|
17
|
+
refine Module do
|
18
|
+
include Stitcher
|
19
|
+
end
|
20
|
+
|
21
|
+
refine Class do
|
22
|
+
prepend Operators
|
23
|
+
end
|
24
|
+
|
25
|
+
refine Array do
|
26
|
+
prepend Operators
|
27
|
+
end
|
28
|
+
|
29
|
+
refine Proc do
|
30
|
+
prepend Operators
|
31
|
+
end
|
32
|
+
|
33
|
+
refine Array do
|
34
|
+
include VariadicArgument
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Module
|
39
|
+
include Stitcher::Core
|
40
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative "./register"
|
2
|
+
require_relative "./define_method"
|
3
|
+
|
4
|
+
using Stitcher
|
5
|
+
|
6
|
+
module Stitcher module Accessor
|
7
|
+
include Register
|
8
|
+
|
9
|
+
def stitcher_writer **opt
|
10
|
+
opt.each { |name, type|
|
11
|
+
Register.register(self, "#{name}=", [type], (DefineMethod.as_instance_executable do |var|
|
12
|
+
instance_variable_set "@#{name}", var
|
13
|
+
end))
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def stitcher_accessor **opt
|
18
|
+
attr_reader *opt.keys
|
19
|
+
Accessor.instance_method(:stitcher_writer).bind(self).(opt)
|
20
|
+
end
|
21
|
+
end end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative "./variadic_argument"
|
2
|
+
|
3
|
+
module StitcherArrayEx
|
4
|
+
refine Array do
|
5
|
+
include Stitcher::VariadicArgument
|
6
|
+
end
|
7
|
+
end
|
8
|
+
using StitcherArrayEx
|
9
|
+
|
10
|
+
module Stitcher module Core
|
11
|
+
def stitcher_method_table name
|
12
|
+
instance_eval { @stitcher_method_table ||= {}; @stitcher_method_table[name] ||= {} }
|
13
|
+
end
|
14
|
+
|
15
|
+
def stitcher_method_table_all name
|
16
|
+
mtable = stitcher_method_table(name) unless superclass
|
17
|
+
return stitcher_method_table_all(superclass, name).merge(mtable) if superclass
|
18
|
+
mtable
|
19
|
+
end
|
20
|
+
|
21
|
+
def stitcher_add name, sig, method
|
22
|
+
sig = (method.arity < 0 ? +([Object] * method.arity.abs) : [Object] * method.arity.abs) unless sig
|
23
|
+
stitcher_method_table(name)[sig] = method
|
24
|
+
end
|
25
|
+
|
26
|
+
def stitcher_method_detecting name, *args, &block
|
27
|
+
mtable = stitcher_method_table(name).to_a.reverse
|
28
|
+
_, method = mtable.find {|sig, _| sig.=== args, &block }
|
29
|
+
method
|
30
|
+
end
|
31
|
+
end end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative "./register"
|
2
|
+
require_relative "./accessor"
|
3
|
+
|
4
|
+
|
5
|
+
module Stitcher module DefineMethod
|
6
|
+
include Stitcher::Register
|
7
|
+
|
8
|
+
def self.as_instance_executable &block
|
9
|
+
Object.new.instance_eval do
|
10
|
+
define_singleton_method :stitcher_bind do |obj|
|
11
|
+
proc do |*args, &block_|
|
12
|
+
self_ = obj
|
13
|
+
self_.instance_exec *args, block, &block
|
14
|
+
end
|
15
|
+
end
|
16
|
+
self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def stitcher_define_method name, **opt, &block
|
21
|
+
obj = DefineMethod.as_instance_executable do |*args|
|
22
|
+
_ = args.pop # block object
|
23
|
+
self_ = self
|
24
|
+
obj = Object.new
|
25
|
+
obj.extend(Module.new{
|
26
|
+
private
|
27
|
+
attr_reader *opt.keys
|
28
|
+
})
|
29
|
+
obj.instance_eval do
|
30
|
+
opt.each_with_index { |data, index|
|
31
|
+
name, type = data
|
32
|
+
instance_variable_set "@#{name}", args[index]
|
33
|
+
}
|
34
|
+
|
35
|
+
# define_singleton_method :[] do |name|
|
36
|
+
# self_.instance_eval "@#{ name }"
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# define_singleton_method :[]= do |name, var|
|
40
|
+
# obj.instance_eval { self_.instance_variable_set "@#{name}", var }
|
41
|
+
# end
|
42
|
+
|
43
|
+
define_singleton_method :method_missing do |name, *args, &block|
|
44
|
+
self_.__send__ name, *args, &block
|
45
|
+
end
|
46
|
+
|
47
|
+
instance_eval &block
|
48
|
+
end
|
49
|
+
end
|
50
|
+
Register.register self, name, opt.values, obj
|
51
|
+
end
|
52
|
+
end end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative "./core_ext"
|
2
|
+
|
3
|
+
using StitcherArrayEx
|
4
|
+
|
5
|
+
module Stitcher
|
6
|
+
module Operators
|
7
|
+
def self.require_other other
|
8
|
+
Proc === other || Class === other
|
9
|
+
end
|
10
|
+
|
11
|
+
def & other
|
12
|
+
return super(other) unless Operators.require_other other
|
13
|
+
proc { |it, &block| self.===(it, &block) && other.===(it, &block) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def | other
|
17
|
+
return super(other) unless Operators.require_other other
|
18
|
+
proc { |it, &block| self.===(it, &block) || other.===(it, &block) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def !
|
22
|
+
proc { |it, &block| !(self.===(it, &block)) }
|
23
|
+
end
|
24
|
+
|
25
|
+
refine Class do
|
26
|
+
prepend Operators
|
27
|
+
end
|
28
|
+
|
29
|
+
refine Array do
|
30
|
+
prepend Operators
|
31
|
+
end
|
32
|
+
|
33
|
+
refine Proc do
|
34
|
+
prepend Operators
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative "./core_ext"
|
2
|
+
require_relative "./register"
|
3
|
+
|
4
|
+
using StitcherArrayEx
|
5
|
+
|
6
|
+
|
7
|
+
class UnboundMethod
|
8
|
+
alias_method :stitcher_bind, :bind
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
module Stitcher module Register
|
13
|
+
def self.define_call_method self_, name
|
14
|
+
self_.__send__ :define_method, name do |*args, &block|
|
15
|
+
method = self_.stitcher_method_detecting name, *args, &block
|
16
|
+
|
17
|
+
return super(*args, &block) unless method
|
18
|
+
method = method.stitcher_bind(self) if method.respond_to? :stitcher_bind
|
19
|
+
method.call *args, &block
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.register self_, name, sig = nil, method = self_.instance_method(name)
|
24
|
+
self_.stitcher_add name, sig, method
|
25
|
+
Register.define_call_method self_, name
|
26
|
+
end
|
27
|
+
|
28
|
+
def stitcher_register name, sig, &block
|
29
|
+
Register.register(self, name, sig, block_given? ? block : instance_method(name))
|
30
|
+
end
|
31
|
+
end end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative "./register"
|
2
|
+
# require_relative "../stitcher"
|
3
|
+
|
4
|
+
|
5
|
+
module Stitcher module Require
|
6
|
+
include Register
|
7
|
+
|
8
|
+
def stitcher_require concept
|
9
|
+
@stitcher_require_concept = concept
|
10
|
+
@stitcher_require_methods = instance_methods.map { |name| instance_method name }
|
11
|
+
|
12
|
+
return if methods.include? :method_added
|
13
|
+
def self.method_added name
|
14
|
+
return unless @stitcher_require_concept
|
15
|
+
concept = @stitcher_require_concept
|
16
|
+
@stitcher_require_concept = nil
|
17
|
+
|
18
|
+
method = @stitcher_require_methods.find{ |it| it.name == name }
|
19
|
+
if method && stitcher_method_table(name).empty?
|
20
|
+
# Don't wrap method.
|
21
|
+
stitcher_add name, nil, method
|
22
|
+
end
|
23
|
+
|
24
|
+
Register.register self, name, concept
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative "./register"
|
2
|
+
require_relative "./define_method"
|
3
|
+
|
4
|
+
module Stitcher module Stitch
|
5
|
+
include Register
|
6
|
+
include DefineMethod
|
7
|
+
|
8
|
+
class Definer < BasicObject
|
9
|
+
def initialize obj
|
10
|
+
@obj = obj
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_missing name, sig, &block
|
14
|
+
DefineMethod.instance_method(:stitcher_define_method).bind(@obj).(name, sig, &block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def stitch *args, &block
|
19
|
+
return Definer.new self if args.empty?
|
20
|
+
Register.register self, *args, &block
|
21
|
+
end
|
22
|
+
end end
|