reference 0.5

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.
Files changed (2) hide show
  1. data/reference.rb +210 -0
  2. metadata +37 -0
@@ -0,0 +1,210 @@
1
+ #!/bin/env ruby
2
+ # Author:: Eric Mahurin
3
+ # License:: Ruby license
4
+
5
+ # These base references are defined simply by get and set procs. The
6
+ # dereferencing methods [] (get) and []= (set) will just call these procs.
7
+ #
8
+ # require 'reference'
9
+ #
10
+ # # multiple ways to make a reference to lines in stdin/stdout
11
+ # lineref = Reference.new(method(:gets),method(:puts))
12
+ # lineref = Reference.new(proc{gets},proc{|v|puts(v)})
13
+ # line = lineref[] # line = gets
14
+ # lineref[]="hello world!" # puts("hello world!")
15
+ class Reference
16
+
17
+ # Create a reference given get and set procs.
18
+ def initialize(getter,setter)
19
+ @getter = getter
20
+ @setter = setter
21
+ end
22
+ # Get the value of the referenced thing. Optional arguments may modify
23
+ # the meaning of what is referenced.
24
+ # Will simply call the get proc for the base class.
25
+ def [](*args)
26
+ @getter[*args]
27
+ end
28
+ # Set the value of the referenced thing. The last argument (required)
29
+ # is taken as the value. Optional preceding arguments may modify the
30
+ # meaning of what is referenced.
31
+ # Will simply call the set proc for the base class.
32
+ def []=(*args)
33
+ @setter[*args]
34
+ end
35
+
36
+ end
37
+
38
+ class Binding
39
+
40
+ # Do an eval in the binding context
41
+ def eval(s,*file_line)
42
+ Kernel.eval(s,self,*file_line)
43
+ end
44
+ # Get a variable/expression (Symbol or String) in the binding context.
45
+ def variable_get(var)
46
+ eval(var.to_s)
47
+ end
48
+ # Set a variable/expression (Symbol or String) in the binding context.
49
+ def variable_set(var,value)
50
+ eval("proc{|_v| #{var} = _v}")[value]
51
+ end
52
+ # Create a reference to an assignable variable or expression that is
53
+ # accessible within the binding context.
54
+ def variable_reference(var)
55
+ Reference.new(
56
+ eval("proc { #{var} }"),
57
+ eval("proc {|_v| #{var} = _v }")
58
+ );
59
+ end
60
+ # Provide access to the object of the binding context.
61
+ def self()
62
+ eval("self")
63
+ end
64
+ # Return a Proc for the given method (Symbol or String) of the binding
65
+ # context.
66
+ def method(meth)
67
+ eval("proc{|*_a,&_b| #{meth}(*_a,&_b)}")
68
+ end
69
+ # Call the method in the binding context for anything else.
70
+ def method_missing(meth,*args,&block)
71
+ eval("proc{|*_a,&_b| #{meth}(*_a,&_b)}").call(*args,&block)
72
+ end
73
+
74
+ end
75
+
76
+ class Object
77
+
78
+ # This class serves dual purposes. It can act as an object Reference or
79
+ # a Reference maker (for attribute like methods of this object)
80
+ class ObjectReference < Reference
81
+
82
+ # Create an ObjectReference
83
+ def initialize(obj)
84
+ @obj = obj
85
+ end
86
+ # With no arguments, this will dereference returning the object. With
87
+ # arguments, it will create a Reference using method_missing.
88
+ def [](*args)
89
+ if args.size==0
90
+ @obj
91
+ else
92
+ method_missing(:"[]",*args)
93
+ end
94
+ end
95
+ # Deferencing set. To set the object it will use the <tt>replace</tt>
96
+ # method of the object if available or try the <tt>become</tt> method
97
+ # (see evil.rb). This will not work on immediate objects.
98
+ def []=(obj)
99
+ if @obj.respond_to?:replace
100
+ @obj.replace(obj)
101
+ else
102
+ @obj.become(obj) # need evil.rb
103
+ end
104
+ @obj
105
+ end
106
+ # Create a reference from this method (get) and this method + "=" (set).
107
+ # <i>args</i> will start the argument list. [] and []= calls from the
108
+ # reference will fill out the remainder of the argument list for these
109
+ # methods.
110
+ def method_missing(method,*args)
111
+ get = @obj.method(method)
112
+ set = @obj.method(method.to_s<<"=")
113
+ if args.size>0
114
+ getter = proc { |*a| get[*(args+a)] }
115
+ setter = proc { |*a| set[*(args+a)] }
116
+ else
117
+ getter = get
118
+ setter = set
119
+ end
120
+ Reference.new(getter,setter)
121
+ end
122
+
123
+ end
124
+ # Provides an easy way to create a Reference. There are several ways to do
125
+ # it:
126
+ #
127
+ # * ref { <i>symbol</i> }
128
+ # * ref { <i>expression-string</i> }
129
+ # * <i>obj</i>.ref
130
+ # * <i>obj</i>.ref.<i>method</i>(<i>arguments</i>)
131
+ # * <i>obj</i>.ref(<i>getsymbol</i>,<i>putsymbol</i>,<i>arguments</i>)
132
+ # * <i>obj</i>.ref([<i>getsymbol</i>,<i>getargs</i>],[<i>putsymbol</i>,<i>putargs</i>],<i>more-args</i>)
133
+ #
134
+ # Here are some examples:
135
+ #
136
+ # require 'reference'
137
+ # a = ("a".."h").to_a # ["a", "b", "c", "d", "e", "f", "g", "h"]
138
+ # b = a # b and a have the same object
139
+ # p = ref{:a} # reference to the variable :a
140
+ # q = a.ref # reference to the object in a
141
+ # r = ref{"a[4]"} # reference to the assignable expression a[4]
142
+ # s = a.ref[4] # reference to the [4] attribute of a
143
+ # t = a.ref.[](4) # same
144
+ # u = a.ref(:"[]",:"[]=",4) # same except set/get method names are explicit
145
+ # v = a.ref([:"[]",4],[:"[]=",4]) # same except arguments are explicit
146
+ # p[] # ["a", "b", "c", "d", "e", "f", "g", "h"]
147
+ # p[] = (0..7).to_a # [0, 1, 2, 3, 4, 5, 6, 7]
148
+ # a # [0, 1, 2, 3, 4, 5, 6, 7]
149
+ # b # ["a", "b", "c", "d", "e", "f", "g", "h"]
150
+ # q[] # ["a", "b", "c", "d", "e", "f", "g", "h"]
151
+ # q[] = (-7..0).to_a # [-7, -6, -5, -4, -3, -2, -1, 0]
152
+ # a # [0, 1, 2, 3, 4, 5, 6, 7]
153
+ # b # [-7, -6, -5, -4, -3, -2, -1, 0]
154
+ # r[] # 4
155
+ # r[] = "r" # "r"
156
+ # a # [0, 1, 2, 3, "r", 5, 6, 7]
157
+ # b # [-7, -6, -5, -4, -3, -2, -1, 0]
158
+ # # extra arg is slice length
159
+ # s[2] # [-3, -2]
160
+ # s[2] = ["s"] # ["s"]
161
+ # a # [0, 1, 2, 3, "r", 5, 6, 7]
162
+ # b # [-7, -6, -5, -4, "s", -1, 0]
163
+ # t[] # "s"
164
+ # t[] = "t" # "t"
165
+ # a # [0, 1, 2, 3, "r", 5, 6, 7]
166
+ # b # [-7, -6, -5, -4, "t", -1, 0]
167
+ # u[] # "t"
168
+ # u[] = "t" # "u"
169
+ # a # [0, 1, 2, 3, "r", 5, 6, 7]
170
+ # b # [-7, -6, -5, -4, "u", -1, 0]
171
+ # v[] # "t"
172
+ # v[] = "t" # "v"
173
+ # a # [0, 1, 2, 3, "r", 5, 6, 7]
174
+ # b # [-7, -6, -5, -4, "v", -1, 0]
175
+ #
176
+ def reference(*args,&block)
177
+ if block
178
+ args.size==0 or raise(ArgumentError,"no arguments allowed when block given")
179
+ block.binding.variable_reference(block[])
180
+ elsif args.size>0
181
+ get,set,*args = *args
182
+ if get.kind_of?Array
183
+ get,*getargs = *(get+args)
184
+ else
185
+ getargs = args
186
+ end
187
+ set ||= get.to_s<<"="
188
+ if set.kind_of?Array
189
+ set,*setargs = *(set+args)
190
+ else
191
+ setargs = args
192
+ end
193
+ get = self.method(get)
194
+ set = self.method(set)
195
+ if getargs.size>0 then getter = proc { |*a| get[*(getargs+a)] }
196
+ else getter = get
197
+ end
198
+ if setargs.size>0 then setter = proc { |*a| set[*(setargs+a)] }
199
+ else setter = set
200
+ end
201
+ Reference.new(getter,setter)
202
+ else
203
+ ObjectReference.new(self)
204
+ end
205
+ end
206
+ alias ref reference
207
+
208
+ end
209
+
210
+
metadata ADDED
@@ -0,0 +1,37 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.10
3
+ specification_version: 1
4
+ name: reference
5
+ version: !ruby/object:Gem::Version
6
+ version: "0.5"
7
+ date: 2005-05-08
8
+ summary: provides reference/pointer functionality of other languages
9
+ require_paths:
10
+ - "."
11
+ email:
12
+ homepage:
13
+ rubyforge_project: reference
14
+ description:
15
+ autorequire: reference
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ -
22
+ - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
25
+ version:
26
+ platform: ruby
27
+ authors:
28
+ - Eric Mahurin
29
+ files:
30
+ - reference.rb
31
+ test_files: []
32
+ rdoc_options: []
33
+ extra_rdoc_files: []
34
+ executables: []
35
+ extensions: []
36
+ requirements: []
37
+ dependencies: []