stitcher 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+
2
+
3
+
4
+ ```ruby
5
+ class X
6
+ let name: String, age: Numeric
7
+ end
8
+ x = X.new
9
+ x.name = "homu" # OK
10
+ x.age = 13 # OK
11
+ x.name 13 # Error
12
+ ```
13
+
14
+
15
+
@@ -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
@@ -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
@@ -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
+
@@ -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
@@ -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,6 @@
1
+ module Stitcher module Concepts
2
+ def blockable
3
+ proc { |*args, &block| !!block }
4
+ end
5
+ module_function :blockable
6
+ 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,7 @@
1
+ module StitcherArrayEx
2
+ refine Array do
3
+ def === other
4
+ size == other.size && zip(other).all? { |a, b| a === b }
5
+ end
6
+ end
7
+ 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