dslkit 0.2.6 → 0.2.7

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.
@@ -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