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.
- data/reference.rb +210 -0
- metadata +37 -0
data/reference.rb
ADDED
@@ -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: []
|