stitcher 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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