dslkit 0.2.6 → 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,310 @@
1
+ require 'term/ansicolor'
2
+ require 'dslkit/polite'
3
+
4
+ module Turing
5
+ class Tape
6
+ def initialize(*initials)
7
+ @left = []
8
+ @head = 'B'
9
+ @right = []
10
+ c = 0
11
+ first = true
12
+ for initial in initials
13
+ if first
14
+ c += 1
15
+ first = false
16
+ else
17
+ @left.push 'B'
18
+ c += 1
19
+ end
20
+ for s in initial.split(//)
21
+ @left.push s
22
+ c += 1
23
+ end
24
+ end
25
+ c.times { left }
26
+ end
27
+
28
+ def read
29
+ @head
30
+ end
31
+
32
+ def write(symbol)
33
+ @head = symbol
34
+ self
35
+ end
36
+
37
+ def left
38
+ @right.push @head
39
+ @head = @left.pop || 'B'
40
+ self
41
+ end
42
+
43
+ def right
44
+ @left.push @head
45
+ @head = @right.pop || 'B'
46
+ self
47
+ end
48
+
49
+ def clear
50
+ @left.clear
51
+ @right.clear
52
+ @head = 'B'
53
+ self
54
+ end
55
+
56
+ def to_s
57
+ "#{@left.join}#{Term::ANSIColor.red(@head)}#{@right.join.reverse}"
58
+ end
59
+
60
+ alias inspect to_s
61
+ end
62
+
63
+ module States
64
+ class State
65
+ attr_accessor :tape
66
+ end
67
+
68
+ class Cond < State
69
+ def initialize(opts = {})
70
+ @if, @then, @else = opts.values_at :if, :then, :else
71
+ end
72
+
73
+ def execute
74
+ tape.read == @if ? @then : @else
75
+ end
76
+
77
+ def to_s
78
+ "if #@if then #@then else #@else"
79
+ end
80
+
81
+ def to_graphviz(stateno, tapeno = nil)
82
+ %{#{stateno} [ shape=diamond label="#{tapeno && "#{tapeno}: "}#@if" ];
83
+ #{stateno} -> #@then [ taillabel="+" ];
84
+ #{stateno} -> #@else [ taillabel="-" ];
85
+ #{stateno} -> #{stateno} [ label="#{stateno}" weight=4.0 color=transparent ];}
86
+ end
87
+ end
88
+
89
+ class Left < State
90
+ def initialize(opts = {})
91
+ @goto = opts[:goto]
92
+ end
93
+
94
+ def execute
95
+ tape.left
96
+ @goto
97
+ end
98
+
99
+ def to_s
100
+ "left, goto #@goto"
101
+ end
102
+
103
+ def to_graphviz(stateno, tapeno = nil)
104
+ %{#{stateno} [ shape=rect label="#{tapeno && "#{tapeno}: "}L" ];
105
+ #{stateno} -> #@goto;
106
+ #{stateno} -> #{stateno} [ label="#{stateno}" weight=4.0 color=transparent ];}
107
+ end
108
+ end
109
+
110
+ class Right < State
111
+ def initialize(opts = {})
112
+ @goto = opts[:goto]
113
+ end
114
+
115
+ def execute
116
+ tape.right
117
+ @goto
118
+ end
119
+
120
+ def to_s
121
+ "right, goto #@goto"
122
+ end
123
+
124
+ def to_graphviz(stateno, tapeno = nil)
125
+ %{#{stateno} [ shape=rect label="#{tapeno && "#{tapeno}: "}R" ];
126
+ #{stateno} -> #@goto;
127
+ #{stateno} -> #{stateno} [ label="#{stateno}" weight=4.0 color=transparent ];}
128
+ end
129
+ end
130
+
131
+ class Write < State
132
+ def initialize(opts = {})
133
+ @symbol, @goto = opts.values_at :symbol, :goto
134
+ end
135
+
136
+ def execute
137
+ tape.write @symbol
138
+ @goto
139
+ end
140
+
141
+ def to_s
142
+ "write #@symbol, goto #@goto"
143
+ end
144
+
145
+ def to_graphviz(stateno, tapeno = nil)
146
+ %{#{stateno} [ shape=rect label="#{tapeno && "#{tapeno}: "}#@symbol" ];
147
+ #{stateno} -> #@goto;
148
+ #{stateno} -> #{stateno} [ label="#{stateno}" weight=4.0 color=transparent ];}
149
+ end
150
+ end
151
+
152
+ class Halt < State
153
+ def initialize(opts = {})
154
+ end
155
+
156
+ def execute
157
+ -1
158
+ end
159
+
160
+ def to_s
161
+ 'halt'
162
+ end
163
+
164
+ def to_graphviz(stateno, tapeno = nil)
165
+ %{#{stateno} [ shape=rect label="HALT" ];
166
+ #{stateno} -> #{stateno} [ label="#{stateno}" weight=4.0 color=transparent ];}
167
+ end
168
+ end
169
+ end
170
+
171
+ class BaseMachine
172
+ def initialize(program = nil)
173
+ @states = []
174
+ if program
175
+ block_given? and raise "use either program source string or a block"
176
+ interpret program
177
+ else
178
+ instance_eval(&Proc.new)
179
+ end
180
+ end
181
+
182
+ def step(*tapes)
183
+ @stepping = true
184
+ run(*tapes)
185
+ end
186
+ end
187
+
188
+ class SingleTapeMachine < BaseMachine
189
+ include DSLKit::Deflect
190
+ include DSLKit::Interpreter
191
+
192
+ def initialize(program = nil)
193
+ deflector = Deflector.new do |number, id, name, *args|
194
+ opts = Hash === args.last ? args.pop : {}
195
+ state = States.const_get(name.to_s.capitalize).new(opts)
196
+ @states[number] = state
197
+ end
198
+ deflect_start(Integer, :method_missing, deflector)
199
+ super
200
+ ensure
201
+ deflect_stop(Integer, :method_missing) if deflect?(Integer, :method_missing)
202
+ end
203
+
204
+ def run(*tape)
205
+ @tape = Tape.new(*tape)
206
+ @states.each { |s| s and s.tape = @tape }
207
+ goto_state = -1
208
+ @states.any? { |s| goto_state += 1; s }
209
+ begin
210
+ printf "%3u: %s", goto_state, @tape
211
+ @stepping ? STDIN.gets : puts
212
+ goto_state = @states[goto_state].execute
213
+ end until goto_state < 0
214
+ end
215
+
216
+ def to_s
217
+ result = ''
218
+ @states.each_with_index do |state, i|
219
+ result << "%3u. %s\n" % [ i, state ]
220
+ end
221
+ result
222
+ end
223
+
224
+ def to_graphviz
225
+ result = "digraph {\n"
226
+ start_edge = false
227
+ @states.each_with_index do |state, stateno|
228
+ state or next
229
+ unless start_edge
230
+ result << "start [ fontcolor=transparent color=transparent ];"
231
+ result << "start -> #{stateno};"
232
+ start_edge = true
233
+ end
234
+ result << state.to_graphviz(stateno) << "\n"
235
+ end
236
+ result << "}\n"
237
+ end
238
+ end
239
+
240
+ class MultiTapeMachine < BaseMachine
241
+ include DSLKit::Deflect
242
+ include DSLKit::Interpreter
243
+
244
+ def initialize(program = nil)
245
+ deflector = Deflector.new do |number, id, name, *args|
246
+ opts = Hash === args.last ? args.pop : {}
247
+ tape, = *args
248
+ state = States.const_get(name.to_s.capitalize).new(opts)
249
+ @states[number] = [ tape, state ]
250
+ end
251
+ deflect_start(Integer, :method_missing, deflector)
252
+ super
253
+ ensure
254
+ deflect_stop(Integer, :method_missing) if deflect?(Integer, :method_missing)
255
+ end
256
+
257
+ def run(*tapes)
258
+ tapes.unshift ''
259
+ @tapes = tapes.map { |tape| Tape.new(tape) }
260
+ goto_state = -1
261
+ @states.any? { |s| goto_state += 1; s }
262
+ begin
263
+ printf "%3u: %s", goto_state, @tapes * ' '
264
+ @stepping ? STDIN.gets : puts
265
+ tape, state = @states[goto_state]
266
+ state.tape = tape ? @tapes[tape] : nil
267
+ goto_state = state.execute
268
+ end until goto_state < 0
269
+ end
270
+
271
+ def to_s
272
+ result = ''
273
+ @states.each_with_index do |(tape, state), i|
274
+ result << "%3u. %1u: %s\n" % [ i, tape, state ]
275
+ end
276
+ result
277
+ end
278
+
279
+ def to_graphviz
280
+ result = "digraph {\n"
281
+ start_edge = false
282
+ @states.each_with_index do |(tapeno,state), stateno|
283
+ state or next
284
+ unless start_edge
285
+ result << "start [ fontcolor=transparent color=transparent ];"
286
+ result << "start -> #{stateno};"
287
+ start_edge = true
288
+ end
289
+ result << state.to_graphviz(stateno, tapeno) << "\n"
290
+ end
291
+ result << "}\n"
292
+ end
293
+ end
294
+ end
295
+
296
+ if $0 == __FILE__ and ARGV.any?
297
+ include Turing
298
+ filename, *tapes = ARGV
299
+ machine_type =
300
+ case ext = File.extname(filename)
301
+ when '.stm'
302
+ SingleTapeMachine
303
+ when '.mtm'
304
+ MultiTapeMachine
305
+ else
306
+ raise "unknown turing machine suffix: #{ext}, use .stm or .mtm"
307
+ end
308
+ tm = machine_type.new(File.read(filename))
309
+ $DEBUG ? tm.step(*tapes) : tm.run(*tapes)
310
+ end
data/lib/dslkit/polite.rb CHANGED
@@ -303,13 +303,15 @@ module DSLKit
303
303
  if args.empty?
304
304
  result = instance_variable_get(variable)
305
305
  if result.nil?
306
- if default.empty?
306
+ result = if default.empty?
307
307
  block && instance_eval(&block)
308
308
  elsif default.size == 1
309
309
  default.first
310
310
  else
311
311
  default
312
312
  end
313
+ instance_variable_set(variable, result)
314
+ result
313
315
  else
314
316
  result
315
317
  end
@@ -1,6 +1,6 @@
1
1
  module DSLKit
2
2
  # DSLKit version
3
- VERSION = '0.2.6'
3
+ VERSION = '0.2.7'
4
4
  VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
data/tests/test_polite.rb CHANGED
@@ -1,5 +1,3 @@
1
- $:.unshift '../lib'
2
- $:.unshift 'tests'
3
1
  require 'dslkit/polite'
4
2
 
5
3
  class TL
@@ -107,4 +105,203 @@ end
107
105
  class D3 < DSLKit::MethodMissingDelegator::DelegatorClass
108
106
  end
109
107
 
110
- require 'test_common'
108
+ require 'test/unit'
109
+ require 'tempfile'
110
+
111
+ class TC_DSLKit < Test::Unit::TestCase
112
+ def setup
113
+ @tl = TL.new
114
+ @tl2 = TL.new
115
+ @ie = IE.new { foo }
116
+ @c = C.new
117
+ @da = DA.new
118
+ @i = I.new
119
+ end
120
+
121
+ def test_version
122
+ assert_equal DSLKit::VERSION_ARRAY * '.', DSLKit::VERSION
123
+ end
124
+
125
+ def test_thread_local
126
+ assert_nil @tl.foo
127
+ @tl.foo = 1
128
+ assert_equal 1, @tl.foo
129
+ new_foo = nil
130
+ thread = Thread.new do
131
+ @tl.foo = 2
132
+ new_foo = @tl.foo
133
+ end
134
+ thread.join
135
+ assert_equal 2, new_foo
136
+ assert_equal 1, @tl.foo
137
+ assert_equal @tl.baz, @tl2.baz
138
+ end
139
+
140
+ def test_instance_thread_local
141
+ assert_nil @tl.baz
142
+ @tl.baz = 1
143
+ assert_equal 1, @tl.baz
144
+ new_foo = nil
145
+ thread = Thread.new do
146
+ @tl.baz = 2
147
+ new_foo = @tl.baz
148
+ end
149
+ thread.join
150
+ assert_equal 2, new_foo
151
+ assert_equal 1, @tl.baz
152
+ assert_not_equal @tl.baz, @tl2.baz
153
+ end
154
+
155
+ def test_thread_global
156
+ assert_nil @tl.bar
157
+ @tl.bar = 1
158
+ assert_equal 1, @tl.bar
159
+ new_bar = nil
160
+ thread = Thread.new do
161
+ @tl.bar = 2
162
+ new_bar = @tl.bar
163
+ end
164
+ thread.join
165
+ assert_equal 2, new_bar
166
+ assert_equal 2, @tl.bar
167
+ end
168
+
169
+ def test_instance_exec
170
+ assert_equal :foo, @ie.foo
171
+ assert_equal :foo, @ie.exec
172
+ @ie.freeze
173
+ assert_equal :foo, @ie.foo
174
+ assert_equal :foo, @ie.exec
175
+ end
176
+
177
+ def test_constant
178
+ assert_equal :foo, @c.foo
179
+ assert_equal :baz, @c.bar
180
+ end
181
+
182
+ def test_dsl_accessor
183
+ assert_nil @da.foo
184
+ assert_equal :bar, @da.bar
185
+ assert_equal :baz, @da.baz
186
+ assert_equal [:qu, :ux], @da.quux
187
+ @da.foo 1
188
+ @da.bar 2
189
+ @da.baz 3
190
+ assert_equal 1, @da.foo
191
+ assert_equal 2, @da.bar
192
+ assert_equal 3, @da.baz
193
+ end
194
+
195
+ def test_dsl_reader
196
+ assert_equal true, @da.on
197
+ assert_equal false, @da.off
198
+ assert_raises(ArgumentError) do
199
+ @da.on false
200
+ end
201
+ assert_equal [ @da.on, @da.off ], @da.states
202
+ assert_equal %w[a b c], @da.abc
203
+ @da.abc << 'd'
204
+ assert_equal %w[a b c d], @da.abc
205
+ @da.instance_variable_set :@abc, %w[a b c]
206
+ assert_equal %w[a b c], @da.abc
207
+ end
208
+
209
+ def test_dsl_accessor_multiple
210
+ assert_nil @da.foo
211
+ assert_equal :bar, @da.bar
212
+ @da.foo 1, 2
213
+ @da.bar [1, 2]
214
+ assert_equal [1, 2], @da.foo
215
+ assert_equal [1, 2], @da.bar
216
+ @da.bar [1, 2, *@da.bar]
217
+ assert_equal [1, 2] * 2, @da.bar
218
+ end
219
+
220
+ def test_interpreter
221
+ assert_equal :foo, @i.interpret('foo')
222
+ temp = Tempfile.new('foo')
223
+ temp.write 'foo'
224
+ temp.rewind
225
+ assert_equal :foo, @i.interpret(temp)
226
+ end
227
+
228
+ def test_interpreter_with_args
229
+ assert_equal 3, @i.interpret('|x| x + y', 1)
230
+ temp = Tempfile.new('foo')
231
+ temp.write '|x| x + y'
232
+ temp.rewind
233
+ assert_equal 3, @i.interpret(temp, 1)
234
+ end
235
+
236
+ def test_symbol_maker
237
+ s = S.new
238
+ assert_equal(:foo, s.instance_exec { foo })
239
+ assert_raises(NoMethodError) { s.instance_exec { foo 1 }}
240
+ end
241
+
242
+ def test_constant_maker
243
+ assert_equal(:FOO, K::FOO)
244
+ end
245
+
246
+ def test_deflect_block
247
+ assert_raises(NoMethodError) { 1.foo }
248
+ assert !D.deflect?(Integer, :foo)
249
+ D.deflect(Integer, :foo, DSLKit::Deflect::Deflector.new { :foo }) do
250
+ assert_equal :foo, 1.foo
251
+ assert D.deflect?(Integer, :foo)
252
+ end
253
+ assert !D.deflect?(Integer, :foo)
254
+ assert_raises(NoMethodError) { 1.foo }
255
+ end
256
+
257
+ def test_deflect
258
+ assert_raises(NoMethodError) { 1.foo }
259
+ assert !D.deflect?(Integer, :foo)
260
+ D.deflect_start(Integer, :foo, DSLKit::Deflect::Deflector.new { :foo })
261
+ assert_equal :foo, 1.foo
262
+ assert D.deflect?(Integer, :foo)
263
+ t = Thread.new do
264
+ assert !D.deflect?(Integer, :foo)
265
+ assert_raises(NoMethodError) { 1.foo }
266
+ end
267
+ t.join
268
+ D.deflect_stop(Integer, :foo)
269
+ assert !D.deflect?(Integer, :foo)
270
+ assert_raises(NoMethodError) { 1.foo }
271
+ end
272
+
273
+ def test_deflect_method_missing
274
+ assert_raises(NoMethodError) { 1.foo }
275
+ assert !D.deflect?(Integer, :method_missing)
276
+ D.deflect_start(Integer, :method_missing, DSLKit::Deflect::Deflector.new { :foo })
277
+ assert_equal :foo, 1.foo
278
+ assert D.deflect?(Integer, :method_missing)
279
+ t = Thread.new do
280
+ assert !D.deflect?(Integer, :method_missing)
281
+ assert_raises(NoMethodError) { 1.foo }
282
+ end
283
+ t.join
284
+ D.deflect_stop(Integer, :method_missing)
285
+ assert !D.deflect?(Integer, :method_missing)
286
+ assert_raises(NoMethodError) { 1.foo }
287
+ end
288
+
289
+ def test_delegate
290
+ d = D2.new
291
+ assert_equal 3, d.my_size1
292
+ assert_equal 3, d.my_size2
293
+ assert_equal 3, d.size
294
+ assert_equal 3, d.length
295
+ end
296
+
297
+ def test_delegate_d3
298
+ d = D3.new []
299
+ assert_equal 0, d.size
300
+ d.push 1
301
+ assert_equal [1], d.map { |x| x }
302
+ d.push 2
303
+ assert_equal [1, 2], d.map { |x| x }
304
+ d.push 3
305
+ assert_equal [1, 2, 3], d.map { |x| x }
306
+ end
307
+ end
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dslkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ hash: 25
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 7
10
+ version: 0.2.7
5
11
  platform: ruby
6
12
  authors:
7
13
  - Florian Frank
@@ -9,10 +15,55 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2009-07-23 00:00:00 +02:00
18
+ date: 2011-07-16 00:00:00 +02:00
13
19
  default_executable:
14
- dependencies: []
15
-
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: gem_hadar
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 27
30
+ segments:
31
+ - 0
32
+ - 0
33
+ - 2
34
+ version: 0.0.2
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: term-ansicolor
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 15
46
+ segments:
47
+ - 1
48
+ - 0
49
+ version: "1.0"
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: spruz
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 15
61
+ segments:
62
+ - 0
63
+ - 2
64
+ version: "0.2"
65
+ type: :runtime
66
+ version_requirements: *id003
16
67
  description: This library contains recurring patterns, that are useful in the creation of internal Domain Specific Languages (DSL) in Ruby.
17
68
  email: flori@ping.de
18
69
  executables: []
@@ -20,61 +71,89 @@ executables: []
20
71
  extensions: []
21
72
 
22
73
  extra_rdoc_files:
23
- - doc-main.txt
74
+ - README.rdoc
24
75
  files:
76
+ - .gitignore
25
77
  - CHANGES
26
78
  - COPYING
79
+ - Gemfile
80
+ - README.rdoc
27
81
  - Rakefile
28
82
  - TODO
29
83
  - VERSION
30
84
  - dslkit.gemspec
85
+ - examples/add_one.pdf
86
+ - examples/add_one.stm
87
+ - examples/bb3.pdf
88
+ - examples/bb3.stm
89
+ - examples/bb3_19.stm
90
+ - examples/concatenate_compare.mtm
91
+ - examples/concatenate_compare.pdf
92
+ - examples/concatenate_compare_19.mtm
93
+ - examples/length_difference.mtm
94
+ - examples/length_difference.pdf
95
+ - examples/length_difference_19.mtm
31
96
  - examples/let.rb
32
97
  - examples/mail.rb
33
- - examples/mm.rb
98
+ - examples/minsky.rb
34
99
  - examples/multiply.reg
35
100
  - examples/null_pattern.rb
101
+ - examples/ones_difference-mtm.pdf
102
+ - examples/ones_difference-stm.pdf
103
+ - examples/ones_difference.mtm
104
+ - examples/ones_difference.stm
105
+ - examples/ones_difference_19.mtm
106
+ - examples/ones_difference_19.stm
107
+ - examples/prefix-equals-suffix-reversed-with-infix.pdf
108
+ - examples/prefix-equals-suffix-reversed-with-infix.stm
109
+ - examples/prefix-equals-suffix-reversed-with-infix_19.stm
36
110
  - examples/recipe.rb
37
111
  - examples/recipe2.rb
38
112
  - examples/recipe_common.rb
39
113
  - examples/subtract.reg
40
- - install.rb
114
+ - examples/turing-graph.rb
115
+ - examples/turing.rb
41
116
  - lib/dslkit.rb
42
117
  - lib/dslkit/polite.rb
43
118
  - lib/dslkit/rude.rb
44
119
  - lib/dslkit/version.rb
45
- - tests/runner.rb
46
- - tests/test_common.rb
47
120
  - tests/test_polite.rb
48
- - tests/test_rude.rb
49
- - doc-main.txt
50
121
  has_rdoc: true
51
- homepage: http://dslkit.rubyforge.org
122
+ homepage: http://flori.github.com/dslkit
52
123
  licenses: []
53
124
 
54
125
  post_install_message:
55
126
  rdoc_options:
127
+ - --title
128
+ - Dslkit - Kit for building DSLs in Ruby
56
129
  - --main
57
- - doc-main.txt
130
+ - README.rdoc
58
131
  require_paths:
59
132
  - lib
60
133
  required_ruby_version: !ruby/object:Gem::Requirement
134
+ none: false
61
135
  requirements:
62
136
  - - ">="
63
137
  - !ruby/object:Gem::Version
138
+ hash: 3
139
+ segments:
140
+ - 0
64
141
  version: "0"
65
- version:
66
142
  required_rubygems_version: !ruby/object:Gem::Requirement
143
+ none: false
67
144
  requirements:
68
145
  - - ">="
69
146
  - !ruby/object:Gem::Version
147
+ hash: 3
148
+ segments:
149
+ - 0
70
150
  version: "0"
71
- version:
72
151
  requirements: []
73
152
 
74
- rubyforge_project: dslkit
75
- rubygems_version: 1.3.2
153
+ rubyforge_project:
154
+ rubygems_version: 1.6.2
76
155
  signing_key:
77
156
  specification_version: 3
78
157
  summary: Kit for building DSLs in Ruby
79
158
  test_files:
80
- - tests/runner.rb
159
+ - tests/test_polite.rb