ua 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.settings/settings.json +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/lib/missing/erb.rb +720 -0
- data/lib/missing/ostruct.rb +284 -0
- data/lib/ua/uadb.rb +42 -0
- data/lib/ua/version.rb +3 -0
- data/lib/ua.rb +375 -0
- data/test/Hello.cpp +5 -0
- data/test/a.db +0 -0
- data/test/com.win32.cpp +39 -0
- data/test/m.html +88 -0
- data/test/temp.2.cpp +5 -0
- data/test/temp.4.cpp +5 -0
- data/test/test.js +13 -0
- data/test/test.rb +74 -0
- data/test/test2.rb +41 -0
- data/test/test3.rb +111 -0
- data/test/test4.rb +9 -0
- data/test/test5.rb +142 -0
- data/ua.gemspec +23 -0
- metadata +108 -0
@@ -0,0 +1,284 @@
|
|
1
|
+
#
|
2
|
+
# = ostruct.rb: OpenStruct implementation
|
3
|
+
#
|
4
|
+
# Author:: Yukihiro Matsumoto
|
5
|
+
# Documentation:: Gavin Sinclair
|
6
|
+
#
|
7
|
+
# OpenStruct allows the creation of data objects with arbitrary attributes.
|
8
|
+
# See OpenStruct for an example.
|
9
|
+
#
|
10
|
+
|
11
|
+
#
|
12
|
+
# An OpenStruct is a data structure, similar to a Hash, that allows the
|
13
|
+
# definition of arbitrary attributes with their accompanying values. This is
|
14
|
+
# accomplished by using Ruby's metaprogramming to define methods on the class
|
15
|
+
# itself.
|
16
|
+
#
|
17
|
+
# == Examples:
|
18
|
+
#
|
19
|
+
# require 'ostruct'
|
20
|
+
#
|
21
|
+
# person = OpenStruct.new
|
22
|
+
# person.name = "John Smith"
|
23
|
+
# person.age = 70
|
24
|
+
# person.pension = 300
|
25
|
+
#
|
26
|
+
# puts person.name # -> "John Smith"
|
27
|
+
# puts person.age # -> 70
|
28
|
+
# puts person.address # -> nil
|
29
|
+
#
|
30
|
+
# An OpenStruct employs a Hash internally to store the methods and values and
|
31
|
+
# can even be initialized with one:
|
32
|
+
#
|
33
|
+
# australia = OpenStruct.new(:country => "Australia", :population => 20_000_000)
|
34
|
+
# p australia # -> <OpenStruct country="Australia" population=20000000>
|
35
|
+
#
|
36
|
+
# Hash keys with spaces or characters that would normally not be able to use for
|
37
|
+
# method calls (e.g. ()[]*) will not be immediately available on the
|
38
|
+
# OpenStruct object as a method for retrieval or assignment, but can be still be
|
39
|
+
# reached through the Object#send method.
|
40
|
+
#
|
41
|
+
# measurements = OpenStruct.new("length (in inches)" => 24)
|
42
|
+
# measurements.send("length (in inches)") # -> 24
|
43
|
+
#
|
44
|
+
# data_point = OpenStruct.new(:queued? => true)
|
45
|
+
# data_point.queued? # -> true
|
46
|
+
# data_point.send("queued?=",false)
|
47
|
+
# data_point.queued? # -> false
|
48
|
+
#
|
49
|
+
# Removing the presence of a method requires the execution the delete_field
|
50
|
+
# method as setting the property value to +nil+ will not remove the method.
|
51
|
+
#
|
52
|
+
# first_pet = OpenStruct.new(:name => 'Rowdy', :owner => 'John Smith')
|
53
|
+
# first_pet.owner = nil
|
54
|
+
# second_pet = OpenStruct.new(:name => 'Rowdy')
|
55
|
+
#
|
56
|
+
# first_pet == second_pet # -> false
|
57
|
+
#
|
58
|
+
# first_pet.delete_field(:owner)
|
59
|
+
# first_pet == second_pet # -> true
|
60
|
+
#
|
61
|
+
#
|
62
|
+
# == Implementation:
|
63
|
+
#
|
64
|
+
# An OpenStruct utilizes Ruby's method lookup structure to and find and define
|
65
|
+
# the necessary methods for properties. This is accomplished through the method
|
66
|
+
# method_missing and define_method.
|
67
|
+
#
|
68
|
+
# This should be a consideration if there is a concern about the performance of
|
69
|
+
# the objects that are created, as there is much more overhead in the setting
|
70
|
+
# of these properties compared to using a Hash or a Struct.
|
71
|
+
#
|
72
|
+
class OpenStruct
|
73
|
+
#
|
74
|
+
# Creates a new OpenStruct object. By default, the resulting OpenStruct
|
75
|
+
# object will have no attributes.
|
76
|
+
#
|
77
|
+
# The optional +hash+, if given, will generate attributes and values
|
78
|
+
# (can be a Hash, an OpenStruct or a Struct).
|
79
|
+
# For example:
|
80
|
+
#
|
81
|
+
# require 'ostruct'
|
82
|
+
# hash = { "country" => "Australia", :population => 20_000_000 }
|
83
|
+
# data = OpenStruct.new(hash)
|
84
|
+
#
|
85
|
+
# p data # -> <OpenStruct country="Australia" population=20000000>
|
86
|
+
#
|
87
|
+
def initialize(hash=nil)
|
88
|
+
@table = {}
|
89
|
+
if hash
|
90
|
+
hash.each_pair do |k, v|
|
91
|
+
k = k.to_sym
|
92
|
+
@table[k] = v
|
93
|
+
new_ostruct_member(k)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Duplicate an OpenStruct object members.
|
99
|
+
def initialize_copy(orig)
|
100
|
+
super
|
101
|
+
@table = @table.dup
|
102
|
+
@table.each_key{|key| new_ostruct_member(key)}
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# Converts the OpenStruct to a hash with keys representing
|
107
|
+
# each attribute (as symbols) and their corresponding values
|
108
|
+
# Example:
|
109
|
+
#
|
110
|
+
# require 'ostruct'
|
111
|
+
# data = OpenStruct.new("country" => "Australia", :population => 20_000_000)
|
112
|
+
# data.to_h # => {:country => "Australia", :population => 20000000 }
|
113
|
+
#
|
114
|
+
def to_h
|
115
|
+
@table.dup
|
116
|
+
end
|
117
|
+
|
118
|
+
#
|
119
|
+
# Yields all attributes (as a symbol) along with the corresponding values
|
120
|
+
# or returns an enumerator if not block is given.
|
121
|
+
# Example:
|
122
|
+
#
|
123
|
+
# require 'ostruct'
|
124
|
+
# data = OpenStruct.new("country" => "Australia", :population => 20_000_000)
|
125
|
+
# data.each_pair.to_a # => [[:country, "Australia"], [:population, 20000000]]
|
126
|
+
#
|
127
|
+
def each_pair
|
128
|
+
return to_enum __method__ unless block_given?
|
129
|
+
@table.each_pair{|p| yield p}
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
# Provides marshalling support for use by the Marshal library.
|
134
|
+
#
|
135
|
+
def marshal_dump
|
136
|
+
@table
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
# Provides marshalling support for use by the Marshal library.
|
141
|
+
#
|
142
|
+
def marshal_load(x)
|
143
|
+
@table = x
|
144
|
+
@table.each_key{|key| new_ostruct_member(key)}
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
# Used internally to check if the OpenStruct is able to be
|
149
|
+
# modified before granting access to the internal Hash table to be modified.
|
150
|
+
#
|
151
|
+
def modifiable
|
152
|
+
begin
|
153
|
+
@modifiable = true
|
154
|
+
rescue
|
155
|
+
raise TypeError, "can't modify frozen #{self.class}", caller(3)
|
156
|
+
end
|
157
|
+
@table
|
158
|
+
end
|
159
|
+
protected :modifiable
|
160
|
+
|
161
|
+
#
|
162
|
+
# Used internally to defined properties on the
|
163
|
+
# OpenStruct. It does this by using the metaprogramming function
|
164
|
+
# define_singleton_method for both the getter method and the setter method.
|
165
|
+
#
|
166
|
+
def new_ostruct_member(name)
|
167
|
+
name = name.to_sym
|
168
|
+
unless respond_to?(name)
|
169
|
+
define_singleton_method(name) { @table[name] }
|
170
|
+
define_singleton_method("#{name}=") { |x| modifiable[name] = x }
|
171
|
+
end
|
172
|
+
name
|
173
|
+
end
|
174
|
+
protected :new_ostruct_member
|
175
|
+
|
176
|
+
def method_missing(mid, *args) # :nodoc:
|
177
|
+
mname = mid.id2name
|
178
|
+
len = args.length
|
179
|
+
if mname.chomp!('=')
|
180
|
+
if len != 1
|
181
|
+
raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
|
182
|
+
end
|
183
|
+
modifiable[new_ostruct_member(mname)] = args[0]
|
184
|
+
elsif len == 0
|
185
|
+
@table[mid]
|
186
|
+
else
|
187
|
+
raise NoMethodError, "undefined method `#{mid}' for #{self}", caller(1)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Returns the value of a member.
|
192
|
+
#
|
193
|
+
# person = OpenStruct.new('name' => 'John Smith', 'age' => 70)
|
194
|
+
# person[:age] # => 70, same as ostruct.age
|
195
|
+
#
|
196
|
+
def [](name)
|
197
|
+
@table[name.to_sym]
|
198
|
+
end
|
199
|
+
|
200
|
+
#
|
201
|
+
# Sets the value of a member.
|
202
|
+
#
|
203
|
+
# person = OpenStruct.new('name' => 'John Smith', 'age' => 70)
|
204
|
+
# person[:age] = 42 # => equivalent to ostruct.age = 42
|
205
|
+
# person.age # => 42
|
206
|
+
#
|
207
|
+
def []=(name, value)
|
208
|
+
modifiable[new_ostruct_member(name)] = value
|
209
|
+
end
|
210
|
+
|
211
|
+
#
|
212
|
+
# Remove the named field from the object. Returns the value that the field
|
213
|
+
# contained if it was defined.
|
214
|
+
#
|
215
|
+
# require 'ostruct'
|
216
|
+
#
|
217
|
+
# person = OpenStruct.new('name' => 'John Smith', 'age' => 70)
|
218
|
+
#
|
219
|
+
# person.delete_field('name') # => 'John Smith'
|
220
|
+
#
|
221
|
+
def delete_field(name)
|
222
|
+
sym = name.to_sym
|
223
|
+
singleton_class.__send__(:remove_method, sym, "#{name}=")
|
224
|
+
@table.delete sym
|
225
|
+
end
|
226
|
+
|
227
|
+
InspectKey = :__inspect_key__ # :nodoc:
|
228
|
+
|
229
|
+
#
|
230
|
+
# Returns a string containing a detailed summary of the keys and values.
|
231
|
+
#
|
232
|
+
def inspect
|
233
|
+
str = "#<#{self.class}"
|
234
|
+
|
235
|
+
ids = (Thread.current[InspectKey] ||= [])
|
236
|
+
if ids.include?(object_id)
|
237
|
+
return str << ' ...>'
|
238
|
+
end
|
239
|
+
|
240
|
+
ids << object_id
|
241
|
+
begin
|
242
|
+
first = true
|
243
|
+
for k,v in @table
|
244
|
+
str << "," unless first
|
245
|
+
first = false
|
246
|
+
str << " #{k}=#{v.inspect}"
|
247
|
+
end
|
248
|
+
return str << '>'
|
249
|
+
ensure
|
250
|
+
ids.pop
|
251
|
+
end
|
252
|
+
end
|
253
|
+
alias :to_s :inspect
|
254
|
+
|
255
|
+
attr_reader :table # :nodoc:
|
256
|
+
protected :table
|
257
|
+
|
258
|
+
#
|
259
|
+
# Compares this object and +other+ for equality. An OpenStruct is equal to
|
260
|
+
# +other+ when +other+ is an OpenStruct and the two objects' Hash tables are
|
261
|
+
# equal.
|
262
|
+
#
|
263
|
+
def ==(other)
|
264
|
+
return false unless other.kind_of?(OpenStruct)
|
265
|
+
@table == other.table
|
266
|
+
end
|
267
|
+
|
268
|
+
#
|
269
|
+
# Compares this object and +other+ for equality. An OpenStruct is eql? to
|
270
|
+
# +other+ when +other+ is an OpenStruct and the two objects' Hash tables are
|
271
|
+
# eql?.
|
272
|
+
#
|
273
|
+
def eql?(other)
|
274
|
+
return false unless other.kind_of?(OpenStruct)
|
275
|
+
@table.eql?(other.table)
|
276
|
+
end
|
277
|
+
|
278
|
+
# Compute a hash-code for this OpenStruct.
|
279
|
+
# Two hashes with the same content will have the same hash code
|
280
|
+
# (and will be eql?).
|
281
|
+
def hash
|
282
|
+
@table.hash
|
283
|
+
end
|
284
|
+
end
|
data/lib/ua/uadb.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Ua
|
2
|
+
class SQLite3Table
|
3
|
+
def initialize(db, table)
|
4
|
+
require 'SQLite3'
|
5
|
+
@db, @table = db, table
|
6
|
+
@database = ::SQLite3::Database.new(@db + ".db")
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](a)
|
10
|
+
case a
|
11
|
+
when lambda{|x| Integer(x) rescue false}
|
12
|
+
@database.execute "select * from #{@table} where id=?", a.to_i
|
13
|
+
when Hash
|
14
|
+
k = a.keys
|
15
|
+
x = k.map{|name| "#{name} = ?"}.join(" and ")
|
16
|
+
y = k.map{|name| a[name]}
|
17
|
+
@database.execute "select * from #{@table} where " + x, y
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class SQLite3DB
|
23
|
+
def initialize(name)
|
24
|
+
@name = name
|
25
|
+
end
|
26
|
+
def [](a)
|
27
|
+
SQLite3Table.new(@name, a)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class SQLite3
|
32
|
+
def [](a)
|
33
|
+
SQLite3DB.new(a)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
module SQLite3Support
|
38
|
+
def default_context
|
39
|
+
set "db3", SQLite3.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/ua/version.rb
ADDED
data/lib/ua.rb
ADDED
@@ -0,0 +1,375 @@
|
|
1
|
+
require "ua/version"
|
2
|
+
require 'erb'
|
3
|
+
require 'ostruct'
|
4
|
+
module Ua
|
5
|
+
module Commands
|
6
|
+
end
|
7
|
+
class Application
|
8
|
+
module UAClass; end
|
9
|
+
module Apply; end
|
10
|
+
def initialize
|
11
|
+
@store = {}
|
12
|
+
@context = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def default_context
|
16
|
+
that = self
|
17
|
+
context Array, :app do |arr|
|
18
|
+
arr.map{|a| context(a, :app)}.join
|
19
|
+
end
|
20
|
+
|
21
|
+
context Apply, :app do |arr|
|
22
|
+
get(arr.stream_).map{|a|that.app a}.join
|
23
|
+
end
|
24
|
+
|
25
|
+
context String, :app do |str|
|
26
|
+
str
|
27
|
+
end
|
28
|
+
|
29
|
+
context UAClass, :app do |element|
|
30
|
+
element.render
|
31
|
+
end
|
32
|
+
|
33
|
+
context Array, :stream_add do |arr, *a|
|
34
|
+
arr.concat a
|
35
|
+
""
|
36
|
+
end
|
37
|
+
context String, :get do |obj, *a|
|
38
|
+
context(get(obj), *a)
|
39
|
+
end
|
40
|
+
|
41
|
+
context UAClass, :stream_add do |obj, *a|
|
42
|
+
obj.stream_ ||= stream_generate
|
43
|
+
get(obj.stream_).concat a
|
44
|
+
obj.extend Apply
|
45
|
+
""
|
46
|
+
end
|
47
|
+
|
48
|
+
context UAClass, :append_add do |obj, *a|
|
49
|
+
obj.stream_ ||= stream_generate
|
50
|
+
get(obj.stream_).concat a
|
51
|
+
""
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def make_context(a, b)
|
56
|
+
a[0] = get(a[0]).class if String === a[0] && has?(a[0])
|
57
|
+
a[0] = a[0].class unless Module === a[0]
|
58
|
+
@context[a] = b
|
59
|
+
end
|
60
|
+
|
61
|
+
def tmpid(prefix = "temp")
|
62
|
+
r = get(count = "#{prefix}.id") || 0
|
63
|
+
r += 1
|
64
|
+
set count, r
|
65
|
+
"#{prefix}.#{r}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def output_by_context(a, b, *c)
|
69
|
+
r = a.singleton_class rescue a.class
|
70
|
+
r.ancestors.each{|i|
|
71
|
+
h = i.instance_method(:uacontext) rescue nil
|
72
|
+
catch(:continue){
|
73
|
+
return h.bind(a).call(b, *c) if h
|
74
|
+
}
|
75
|
+
}
|
76
|
+
r.ancestors.each{|i|
|
77
|
+
h = @context[[i, b]]
|
78
|
+
catch(:continue){
|
79
|
+
return a.instance_exec(a, *c, &h) if h
|
80
|
+
}
|
81
|
+
}
|
82
|
+
puts "Can't find a handler #{a.class} #{b}"
|
83
|
+
raise "Can't find a handler #{a.class} #{b}"
|
84
|
+
=begin
|
85
|
+
ensure
|
86
|
+
|
87
|
+
if $@
|
88
|
+
unless $@.index{|x| x=="UAException"}
|
89
|
+
$@.unshift("UAEnd")
|
90
|
+
$@.unshift("UAException")
|
91
|
+
end
|
92
|
+
l, r = $@.index("UAException"), $@.index("UAEnd")
|
93
|
+
u = $@.slice!(l..r)
|
94
|
+
u[-1, 0] = "context #{a.class} #{b}"
|
95
|
+
u += $@
|
96
|
+
$@.replace u
|
97
|
+
end
|
98
|
+
=end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
#
|
103
|
+
# setup an output variable
|
104
|
+
#
|
105
|
+
def _parent(a)
|
106
|
+
u = @store
|
107
|
+
col = ""
|
108
|
+
arr = a.split(".")
|
109
|
+
arr[0..-2].each{|x|
|
110
|
+
col << "." << x
|
111
|
+
if u[x] == nil
|
112
|
+
u[x] = {}
|
113
|
+
elsif !u[x].respond_to?(:[])
|
114
|
+
raise "#{col} is not valid"
|
115
|
+
end
|
116
|
+
u = u[x]
|
117
|
+
}
|
118
|
+
[u, arr[-1]]
|
119
|
+
end
|
120
|
+
|
121
|
+
def set(a, b)
|
122
|
+
path, val = _parent(a)
|
123
|
+
path[val] = b
|
124
|
+
b
|
125
|
+
end
|
126
|
+
|
127
|
+
def get(a)
|
128
|
+
path, val = _parent(a)
|
129
|
+
path[val]
|
130
|
+
end
|
131
|
+
|
132
|
+
TOPLEVEL = "com.ua.root"
|
133
|
+
def go!(name = TOPLEVEL)
|
134
|
+
puts app(name)
|
135
|
+
end
|
136
|
+
|
137
|
+
def app(name = TOPLEVEL)
|
138
|
+
context(get(name), :app)
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
def context(a, b = Ua::Application.top.context, *c, &bl)
|
143
|
+
if block_given?
|
144
|
+
make_context([a, b], bl)
|
145
|
+
else
|
146
|
+
output_by_context(a, b, *c)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
|
152
|
+
def make_uaclass(a, *ar, &block)
|
153
|
+
autoinit = false
|
154
|
+
block ||= begin
|
155
|
+
autoinit = true
|
156
|
+
lambda{
|
157
|
+
"<%= context(get(stream_), :app) %>"
|
158
|
+
}
|
159
|
+
end
|
160
|
+
that = self
|
161
|
+
code = block.call
|
162
|
+
codename = "proc.#{a}"
|
163
|
+
set codename, code
|
164
|
+
klass = Class.new(OpenStruct) do
|
165
|
+
include UAClass
|
166
|
+
include Enumerable
|
167
|
+
define_method(:initialize) do |*args|
|
168
|
+
begin
|
169
|
+
Ua::Application.push_app that
|
170
|
+
super(*args)
|
171
|
+
self.stream_ = that.stream_generate
|
172
|
+
self.id_ = that.tmpid("object")
|
173
|
+
that.set self.id_, self
|
174
|
+
ensure
|
175
|
+
Ua::Application.pop
|
176
|
+
end
|
177
|
+
end
|
178
|
+
def mapjoin
|
179
|
+
map{|x| yield x}.join
|
180
|
+
end
|
181
|
+
def each
|
182
|
+
get(stream_).each{|x|
|
183
|
+
yield x
|
184
|
+
}
|
185
|
+
end
|
186
|
+
define_method(:classid) do
|
187
|
+
a
|
188
|
+
end
|
189
|
+
define_method(:prototype) do
|
190
|
+
klass
|
191
|
+
end
|
192
|
+
define_method(:erb) do |text__|
|
193
|
+
begin
|
194
|
+
Ua::Application.push_app that
|
195
|
+
ERB.new(text__).result(binding)
|
196
|
+
ensure
|
197
|
+
Ua::Application.pop
|
198
|
+
end
|
199
|
+
end
|
200
|
+
define_method(:render) do
|
201
|
+
begin
|
202
|
+
Ua::Application.push_app that
|
203
|
+
erb get codename
|
204
|
+
ensure
|
205
|
+
Ua::Application.pop
|
206
|
+
end
|
207
|
+
end
|
208
|
+
define_singleton_method(:to_s) do
|
209
|
+
a
|
210
|
+
end
|
211
|
+
end
|
212
|
+
x = klass.new
|
213
|
+
klass.const_set :Singleton_, x
|
214
|
+
x
|
215
|
+
end
|
216
|
+
|
217
|
+
|
218
|
+
|
219
|
+
def stream_generate
|
220
|
+
u = tmpid
|
221
|
+
set u, []
|
222
|
+
u
|
223
|
+
end
|
224
|
+
|
225
|
+
def create(id, opt = {}, &b)
|
226
|
+
x = get(id).prototype.new
|
227
|
+
opt.each{|k, v| x.send "#{k}=", v }
|
228
|
+
x
|
229
|
+
end
|
230
|
+
|
231
|
+
def add(a = tmpid, *ar, &block)
|
232
|
+
set a, make_uaclass(a, *ar, &block)
|
233
|
+
get a
|
234
|
+
end
|
235
|
+
|
236
|
+
def delete(obj)
|
237
|
+
set obj.id_, nil
|
238
|
+
end
|
239
|
+
|
240
|
+
module ArgVoid; end
|
241
|
+
|
242
|
+
def self.push(app = ArgVoid, context = ArgVoid, controller = ArgVoid)
|
243
|
+
app = app == ArgVoid ? @app_stack.last.app : app
|
244
|
+
context = context == ArgVoid ? @app_stack.last.context : context
|
245
|
+
controller = controller == ArgVoid ? @app_stack.last.controller : controller
|
246
|
+
@app_stack.push StackFrame.new(app, context, controller)
|
247
|
+
end
|
248
|
+
|
249
|
+
def self.push_app(app)
|
250
|
+
self.push(app)
|
251
|
+
end
|
252
|
+
|
253
|
+
|
254
|
+
def self.pop
|
255
|
+
@app_stack.pop
|
256
|
+
end
|
257
|
+
def self.top
|
258
|
+
@app_stack.last
|
259
|
+
end
|
260
|
+
def self.top_app
|
261
|
+
top.app
|
262
|
+
end
|
263
|
+
|
264
|
+
app = SINGLETON_APP = new
|
265
|
+
|
266
|
+
StackFrame = Struct.new(:app, :context, :controller)
|
267
|
+
@app_stack = [StackFrame.new(app, :app, eval('self', TOPLEVEL_BINDING))]
|
268
|
+
|
269
|
+
def initialize
|
270
|
+
@store = {}
|
271
|
+
@context = {}
|
272
|
+
bootup
|
273
|
+
end
|
274
|
+
|
275
|
+
def bootup
|
276
|
+
default_context
|
277
|
+
add("com.ua.root").prototype.send :include, Ua::Application::Apply
|
278
|
+
end
|
279
|
+
|
280
|
+
app.bootup
|
281
|
+
|
282
|
+
def self.singleton
|
283
|
+
SINGLETON_APP
|
284
|
+
end
|
285
|
+
|
286
|
+
def stream(a, *b)
|
287
|
+
context(get(a), :stream_add, *b)
|
288
|
+
end
|
289
|
+
|
290
|
+
def append(a, *b)
|
291
|
+
context(get(a), :append_add, *b)
|
292
|
+
end
|
293
|
+
|
294
|
+
def self.export_commands(*names)
|
295
|
+
that = self
|
296
|
+
names.each{|name|
|
297
|
+
(Commands).send(:define_method, name) do |*a, &b|
|
298
|
+
that.top_app.send(name, *a, &b)
|
299
|
+
end
|
300
|
+
}
|
301
|
+
end
|
302
|
+
|
303
|
+
def has?(key)
|
304
|
+
get(key)
|
305
|
+
end
|
306
|
+
|
307
|
+
def stack_of(name)
|
308
|
+
stack = "stack.#{name}"
|
309
|
+
if has?(stack)
|
310
|
+
get(stack)
|
311
|
+
else
|
312
|
+
set stack, (a = [])
|
313
|
+
a
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
|
318
|
+
def get_local(name)
|
319
|
+
local = "local.#{name}"
|
320
|
+
return get local if has?(local)
|
321
|
+
add local
|
322
|
+
get local
|
323
|
+
end
|
324
|
+
|
325
|
+
def set_local(name, val)
|
326
|
+
local = "local.#{name}"
|
327
|
+
set local, val
|
328
|
+
val
|
329
|
+
end
|
330
|
+
|
331
|
+
def push_local(name, newval = add)
|
332
|
+
local = "local.#{name}"
|
333
|
+
stack_of(local).push get local
|
334
|
+
set local, newval
|
335
|
+
newval
|
336
|
+
end
|
337
|
+
|
338
|
+
def pop_local(name)
|
339
|
+
local = "local.#{name}"
|
340
|
+
r = get local
|
341
|
+
set local, stack_of(local).pop
|
342
|
+
r
|
343
|
+
end
|
344
|
+
|
345
|
+
|
346
|
+
export_commands :set, :go!, :add, :create,
|
347
|
+
:get, :stream, :append, :stream_generate,
|
348
|
+
:get_local, :set_local, :push_local, :pop_local, :delete
|
349
|
+
|
350
|
+
end
|
351
|
+
module Commands
|
352
|
+
def context(obj, ctxt = Ua::Application.top.context, &b)
|
353
|
+
Ua::Application.push(Ua::Application::ArgVoid,
|
354
|
+
ctxt,
|
355
|
+
self
|
356
|
+
)
|
357
|
+
Ua::Application.top_app.context(obj, ctxt, &b)
|
358
|
+
ensure
|
359
|
+
Ua::Application.pop
|
360
|
+
end
|
361
|
+
alias model add
|
362
|
+
alias view context
|
363
|
+
alias link stream
|
364
|
+
alias new create
|
365
|
+
end
|
366
|
+
|
367
|
+
end
|
368
|
+
|
369
|
+
|
370
|
+
require 'ua/uadb'
|
371
|
+
require 'ua/util'
|
372
|
+
if !(Ua.const_get(:NoConflict) rescue nil)
|
373
|
+
include Ua::Commands
|
374
|
+
include Ua::Util
|
375
|
+
end
|
data/test/Hello.cpp
ADDED
data/test/a.db
ADDED
Binary file
|