reference 0.5

Sign up to get free protection for your applications and to get access to all the features.
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: []