tins 0.13.2 → 1.0.0

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Rakefile +1 -13
  4. data/VERSION +1 -1
  5. data/examples/add_one.png +0 -0
  6. data/examples/add_one.stm +13 -0
  7. data/examples/bb3.png +0 -0
  8. data/examples/bb3.stm +26 -0
  9. data/examples/bb3_19.stm +26 -0
  10. data/examples/concatenate_compare.mtm +31 -0
  11. data/examples/concatenate_compare.png +0 -0
  12. data/examples/concatenate_compare_19.mtm +31 -0
  13. data/examples/length_difference.mtm +17 -0
  14. data/examples/length_difference.png +0 -0
  15. data/examples/length_difference_19.mtm +17 -0
  16. data/examples/let.rb +62 -0
  17. data/examples/mail.rb +73 -0
  18. data/examples/minsky.rb +145 -0
  19. data/examples/multiply.reg +42 -0
  20. data/examples/null_pattern.rb +52 -0
  21. data/examples/ones_difference-mtm.png +0 -0
  22. data/examples/ones_difference-stm.png +0 -0
  23. data/examples/ones_difference.mtm +12 -0
  24. data/examples/ones_difference.stm +25 -0
  25. data/examples/ones_difference_19.mtm +12 -0
  26. data/examples/ones_difference_19.stm +25 -0
  27. data/examples/prefix-equals-suffix-reversed-with-infix.png +0 -0
  28. data/examples/prefix-equals-suffix-reversed-with-infix.stm +38 -0
  29. data/examples/prefix-equals-suffix-reversed-with-infix_19.stm +38 -0
  30. data/examples/recipe.rb +81 -0
  31. data/examples/recipe2.rb +82 -0
  32. data/examples/recipe_common.rb +97 -0
  33. data/examples/subtract.reg +9 -0
  34. data/examples/turing-graph.rb +17 -0
  35. data/examples/turing.rb +310 -0
  36. data/lib/dslkit.rb +2 -0
  37. data/lib/dslkit/polite.rb +1 -0
  38. data/lib/dslkit/rude.rb +1 -0
  39. data/lib/tins.rb +1 -0
  40. data/lib/tins/dslkit.rb +662 -0
  41. data/lib/tins/thread_local.rb +52 -0
  42. data/lib/tins/version.rb +1 -1
  43. data/lib/tins/xt.rb +1 -0
  44. data/lib/tins/xt/dslkit.rb +23 -0
  45. data/tests/concern_test.rb +24 -25
  46. data/tests/dslkit_test.rb +308 -0
  47. data/tests/dynamic_scope_test.rb +31 -0
  48. data/tests/from_module_test.rb +61 -0
  49. data/tests/scope_test.rb +31 -0
  50. data/tests/test_helper.rb +0 -1
  51. data/tins.gemspec +10 -10
  52. metadata +68 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 33e8a0b467a8afe09dfacf9d3e863095bbff4f62
4
- data.tar.gz: 705758796fb07e53051e10824e83f4e96470ac2d
3
+ metadata.gz: daf3b23e37e5aaede8874111788fe50b8cde092b
4
+ data.tar.gz: 9c1fc6a057ccc8f8fd1e453ce3192dd4c9be3cc9
5
5
  SHA512:
6
- metadata.gz: 44d8bab15a5bbd2970f846fce5151ec1556f2ee9e2f2b22193993da504af5590511bb266b39066874ad470198c6ad7112e77dab1b486eb49baf3cd687feab558
7
- data.tar.gz: 8e629177458dc5a6dc51ee109c929e0c70f677b2ec46db77b4c61da149ebfa17b0c4a5180e3c75146a0c28baafa84f1b87a0fac5d1fbb8fdf50bf2b426e4b900
6
+ metadata.gz: 13370cc1f4ade6e9e275dffd130ab27c8b60fa565aab1d191aad04eee63e449aba0a5a90edb1aba6c89cb4ac56794344530f03bc228758552d9a719b77da5d5e
7
+ data.tar.gz: 58c760d2cbcd53e2780364832df9ddf555bd755a73609741969bd813d17a2d368fefeec6ac083c6306cf2f2251f3b310fef7851a880a97078ca92330aa1de38d
data/.gitignore CHANGED
@@ -1,6 +1,7 @@
1
1
  .*.sw[pon]
2
2
  .AppleDouble
3
3
  .DS_Store
4
+ .bundle
4
5
  .rbx
5
6
  .rvmrc
6
7
  Gemfile.lock
data/Rakefile CHANGED
@@ -12,23 +12,11 @@ GemHadar do
12
12
  test_dir 'tests'
13
13
  test_files.concat Dir["#{test_dir}/*_test.rb"]
14
14
  ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', '.rvmrc', 'coverage', '.rbx',
15
- '.AppleDouble', '.DS_Store', 'tags'
15
+ '.AppleDouble', '.DS_Store', 'tags', '.bundle'
16
16
 
17
17
  readme 'README.rdoc'
18
18
  licenses << 'MIT'
19
19
 
20
20
  development_dependency 'test-unit', '~>2.5'
21
21
  development_dependency 'utils'
22
-
23
- install_library do
24
- libdir = CONFIG["sitelibdir"]
25
- cd 'lib' do
26
- for file in Dir['**/*.rb']
27
- dst = File.join(libdir, file)
28
- mkdir_p File.dirname(dst)
29
- install file, dst
30
- end
31
- end
32
- install 'bin/enum', File.join(CONFIG['bindir'], 'enum')
33
- end
34
22
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.13.2
1
+ 1.0.0
Binary file
@@ -0,0 +1,13 @@
1
+ # vim: ts=2 sw=2 et ft=ruby
2
+ # Call with a binary number on the tape:
3
+ # $ turing.rb add_one.stm 1111010101
4
+
5
+ 0. right :goto => 1
6
+ 1. cond :if => 'B', :then => 2, :else => 0
7
+ 2. left :goto => 3
8
+ 3. cond :if => '1', :then => 4, :else => 5
9
+ 4. write :symbol => '0', :goto => 2
10
+ 5. write :symbol => '1', :goto => 6
11
+ 6. right :goto => 7
12
+ 7. cond :if => 'B', :then => 8, :else => 6
13
+ 8. halt
Binary file
@@ -0,0 +1,26 @@
1
+ # vim: ts=2 sw=2 et ft=ruby
2
+ # Call with an empty tape
3
+ # $ turing.rb bb3.stm ''
4
+
5
+ # Busy Beaver: 3-state, 2-symbol
6
+
7
+ # state A
8
+ 1. cond :if => 'B', :then => 2, :else => 4
9
+ 2. write :symbol => '1', :goto => 3
10
+ 3. right :goto => 6
11
+ 4. write :symbol => '1', :goto => 5
12
+ 5. right :goto => 16
13
+ # state B
14
+ 6. cond :if => 'B', :then => 7, :else => 9
15
+ 7. write :symbol => 'B', :goto => 8
16
+ 8. right :goto => 11
17
+ 9. write :symbol => '1', :goto => 10
18
+ 10. right :goto => 6
19
+ # state C
20
+ 11. cond :if => 'B', :then => 12, :else => 14
21
+ 12. write :symbol => '1', :goto => 13
22
+ 13. left :goto => 11
23
+ 14. write :symbol => '1', :goto => 15
24
+ 15. left :goto => 1
25
+ # halt
26
+ 16. halt
@@ -0,0 +1,26 @@
1
+ # vim: ts=2 sw=2 et ft=ruby
2
+ # Call with an empty tape
3
+ # $ turing.rb bb3.stm ''
4
+
5
+ # Busy Beaver: 3-state, 2-symbol
6
+
7
+ # state A
8
+ 1. cond if: 'B', then: 2, else: 4
9
+ 2. write symbol: '1', goto: 3
10
+ 3. right goto: 6
11
+ 4. write symbol: '1', goto: 5
12
+ 5. right goto: 16
13
+ # state B
14
+ 6. cond if: 'B', then: 7, else: 9
15
+ 7. write symbol: 'B', goto: 8
16
+ 8. right goto: 11
17
+ 9. write symbol: '1', goto: 10
18
+ 10. right goto: 6
19
+ # state C
20
+ 11. cond if: 'B', then: 12, else: 14
21
+ 12. write symbol: '1', goto: 13
22
+ 13. left goto: 11
23
+ 14. write symbol: '1', goto: 15
24
+ 15. left goto: 1
25
+ # halt
26
+ 16. halt
@@ -0,0 +1,31 @@
1
+ # vim: ts=2 sw=2 et ft=ruby
2
+ # Call with four binary numbers on the tape:
3
+ # $ turing.rb concatenate_compare.mtm 110 1 11 01
4
+
5
+ 1. right 1, :goto => 2
6
+ 2. cond 1, :if => 'B', :then => 3, :else => 1
7
+ 3. right 2, :goto => 4
8
+ 4. cond 2, :if => '0', :then => 7, :else => 5
9
+ 5. cond 2, :if => '1', :then => 6, :else => 9
10
+ 6. write 1, :symbol => '1', :goto => 8
11
+ 7. write 1, :symbol => '0', :goto => 8
12
+ 8. right 1, :goto => 3
13
+ 9. right 3, :goto => 10
14
+ 10. cond 3, :if => 'B', :then => 11, :else => 9
15
+ 11. right 4, :goto => 12
16
+ 12. cond 4, :if => '0', :then => 14, :else => 13
17
+ 13. cond 4, :if => '1', :then => 15, :else => 17
18
+ 14. write 3, :symbol => '0', :goto => 16
19
+ 15. write 3, :symbol => '1', :goto => 16
20
+ 16. right 3, :goto => 11
21
+ 17. left 3, :goto => 18
22
+ 18. left 1, :goto => 19
23
+ 19. cond 3, :if => '0', :then => 20, :else => 22
24
+ 20. cond 1, :if => '0', :then => 17, :else => 24
25
+ 21. cond 1, :if => '1', :then => 17, :else => 24
26
+ 22. cond 3, :if => '1', :then => 21, :else => 23
27
+ 23. cond 1, :if => 'B', :then => 25, :else => 24
28
+ 24. write 0, :symbol => '0', :goto => 26
29
+ 25. write 0, :symbol => '1', :goto => 26
30
+ 26. right 0, :goto => 27
31
+ 27. halt
@@ -0,0 +1,31 @@
1
+ # vim: ts=2 sw=2 et ft=ruby
2
+ # Call with four binary numbers on the tape:
3
+ # $ turing.rb concatenate_compare.mtm 110 1 11 01
4
+
5
+ 1. right 1, goto: 2
6
+ 2. cond 1, if: 'B', then: 3, else: 1
7
+ 3. right 2, goto: 4
8
+ 4. cond 2, if: '0', then: 7, else: 5
9
+ 5. cond 2, if: '1', then: 6, else: 9
10
+ 6. write 1, symbol: '1', goto: 8
11
+ 7. write 1, symbol: '0', goto: 8
12
+ 8. right 1, goto: 3
13
+ 9. right 3, goto: 10
14
+ 10. cond 3, if: 'B', then: 11, else: 9
15
+ 11. right 4, goto: 12
16
+ 12. cond 4, if: '0', then: 14, else: 13
17
+ 13. cond 4, if: '1', then: 15, else: 17
18
+ 14. write 3, symbol: '0', goto: 16
19
+ 15. write 3, symbol: '1', goto: 16
20
+ 16. right 3, goto: 11
21
+ 17. left 3, goto: 18
22
+ 18. left 1, goto: 19
23
+ 19. cond 3, if: '0', then: 20, else: 22
24
+ 20. cond 1, if: '0', then: 17, else: 24
25
+ 21. cond 1, if: '1', then: 17, else: 24
26
+ 22. cond 3, if: '1', then: 21, else: 23
27
+ 23. cond 1, if: 'B', then: 25, else: 24
28
+ 24. write 0, symbol: '0', goto: 26
29
+ 25. write 0, symbol: '1', goto: 26
30
+ 26. right 0, goto: 27
31
+ 27. halt
@@ -0,0 +1,17 @@
1
+ # vim: ts=2 sw=2 et ft=ruby
2
+ # Call with two [ab]* strings on the tapes:
3
+ # $ turing.rb prefix-equals-suffix-reversed-with-infix.stm ab ababab
4
+
5
+ 1. right 1, :goto => 2
6
+ 2. right 2, :goto => 3
7
+ 3. cond 1, :if => 'B', :then => 5, :else => 4
8
+ 4. cond 2, :if => 'B', :then => 9, :else => 1
9
+ 5. cond 2, :if => 'B', :then => 13, :else => 6
10
+ 6. write 0, :symbol => 'b', :goto => 7
11
+ 7. right 0, :goto => 8
12
+ 8. right 2, :goto => 5
13
+ 9. write 0, :symbol => 'a', :goto => 10
14
+ 10. right 0, :goto => 11
15
+ 11. right 1, :goto => 12
16
+ 12. cond 1, :if => 'B', :then => 13, :else => 9
17
+ 13. halt
@@ -0,0 +1,17 @@
1
+ # vim: ts=2 sw=2 et ft=ruby
2
+ # Call with two [ab]* strings on the tapes:
3
+ # $ turing.rb prefix-equals-suffix-reversed-with-infix.stm ab ababab
4
+
5
+ 1. right 1, goto: 2
6
+ 2. right 2, goto: 3
7
+ 3. cond 1, if: 'B', then: 5, else: 4
8
+ 4. cond 2, if: 'B', then: 9, else: 1
9
+ 5. cond 2, if: 'B', then: 13, else: 6
10
+ 6. write 0, symbol: 'b', goto: 7
11
+ 7. right 0, goto: 8
12
+ 8. right 2, goto: 5
13
+ 9. write 0, symbol: 'a', goto: 10
14
+ 10. right 0, goto: 11
15
+ 11. right 1, goto: 12
16
+ 12. cond 1, if: 'B', then: 13, else: 9
17
+ 13. halt
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tins'
4
+
5
+ LetScope = Tins::BlankSlate.with :instance_eval, :to_s, :inspect, :extend
6
+ class LetScope
7
+ include Tins::MethodMissingDelegator::DelegatorModule
8
+ include Tins::BlockSelf
9
+
10
+ def initialize(my_self, bindings = {}, outer_scope = nil)
11
+ super(my_self)
12
+ @outer_scope = outer_scope
13
+ @bindings = bindings
14
+ extend Tins::Eigenclass
15
+ eigenclass_eval { extend Tins::Constant }
16
+ each_binding do |name, value|
17
+ eigenclass_eval { constant name, value }
18
+ end
19
+ end
20
+
21
+ def each_binding(&block)
22
+ if @outer_scope
23
+ @outer_scope.each_binding(&block)
24
+ end
25
+ @bindings.each(&block)
26
+ end
27
+
28
+ def let(bindings = {}, &block)
29
+ ls = LetScope.new(block_self(&block), bindings, self)
30
+ ls.instance_eval(&block)
31
+ end
32
+
33
+ # Including this module into your current namespace defines the let method.
34
+ module Include
35
+ include Tins::BlockSelf
36
+
37
+ def let(bindings = {}, &block)
38
+ ls = LetScope.new(block_self(&block), bindings)
39
+ ls.instance_eval(&block)
40
+ end
41
+ end
42
+ end
43
+
44
+ if $0 == __FILE__
45
+ class Foo
46
+ include LetScope::Include
47
+
48
+ def twice(x)
49
+ 2 * x
50
+ end
51
+
52
+ def test
53
+ let :x => 1, :y => twice(1) do
54
+ let :z => twice(x) do
55
+ puts "#{x} * #{y} == #{z} # => #{x * y == twice(x)}"
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ Foo.new.test
62
+ end
@@ -0,0 +1,73 @@
1
+ require 'tins'
2
+ require 'net/smtp'
3
+ require 'time'
4
+
5
+ class Mail
6
+ extend Tins::DSLAccessor
7
+ include Tins::InstanceExec
8
+ include Tins::MethodMissingDelegator::DelegatorModule
9
+ include Tins::BlockSelf
10
+
11
+ def initialize(&block)
12
+ super block_self(&block)
13
+ instance_exec(&block)
14
+ end
15
+
16
+ dsl_accessor :mail_server, ENV['MAILSERVER'] || 'mail'
17
+
18
+ dsl_accessor :body
19
+
20
+ if ENV['USER']
21
+ dsl_accessor :from, ENV['USER'] + '@' + (ENV['MAILSERVER'] || 'mail')
22
+ else
23
+ dsl_accessor :from, 'joe@doe.com'
24
+ end
25
+
26
+ dsl_accessor :to, 'flori@ping.de'
27
+
28
+ dsl_accessor :subject, 'Test Email'
29
+
30
+ dsl_accessor :date do Time.now.rfc2822 end
31
+
32
+ def message_id
33
+ key = [ ENV['HOSTNAME'] || 'localhost', $$ , Time.now ].join
34
+ (::Digest::MD5.new << key).to_s
35
+ end
36
+
37
+ def msg
38
+ [
39
+ "From: #{from}",
40
+ "To: #{to}",
41
+ "Subject: #{subject}",
42
+ "Date: #{date}",
43
+ "Message-Id: <#{message_id}@#{mail_server}>",
44
+ '',
45
+ body
46
+ ] * "\n"
47
+ end
48
+
49
+ def send
50
+ ::Net::SMTP.start(mail_server, 25) do |smtp|
51
+ smtp.send_message msg, from, to
52
+ end
53
+ end
54
+ end
55
+
56
+ def mail(&block)
57
+ Mail.new(&block)
58
+ end
59
+
60
+ def prompt
61
+ STDOUT.print "Send to? "
62
+ STDOUT.flush
63
+ STDIN.gets.strip
64
+ end
65
+
66
+ m = mail do
67
+ subject subject + ': Hi!'
68
+ if rcpt = prompt
69
+ to rcpt
70
+ end
71
+ body "Hello, world!\n"
72
+ end
73
+ m.send
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tins'
4
+
5
+ # A small Minsky (register) machine
6
+ module Minsky
7
+ class InterpreterError < StandardError; end
8
+
9
+ class ::Proc
10
+ attr_accessor :interpreter
11
+
12
+ attr_accessor :name
13
+
14
+ def execute
15
+ interpreter.display_registers(self)
16
+ call
17
+ end
18
+ end
19
+
20
+ class Registers
21
+ def initialize
22
+ @registers = Hash.new(0)
23
+ end
24
+
25
+ def [](name)
26
+ @registers[name]
27
+ end
28
+
29
+ def []=(name, value)
30
+ @registers[name] = value
31
+ end
32
+
33
+ def to_s
34
+ "[" + @registers.sort_by { |r,| r.to_s }.map { |r,v| "#{r}: #{v}" } *
35
+ "|" + "]"
36
+ end
37
+
38
+ def method_missing(name, value)
39
+ name = name.to_s
40
+ if name[-1] == ?=
41
+ name = name[0..-2].intern
42
+ value >= 0 or raise InterpreterError,
43
+ "only non-negative numbers can be stored in register #{name}"
44
+ @registers[name] = value
45
+ else
46
+ super
47
+ end
48
+ end
49
+ end
50
+
51
+ class Interpreter
52
+ include Tins::Interpreter
53
+ extend Tins::ConstantMaker
54
+
55
+ def initialize(source)
56
+ @source = source
57
+ @labels = []
58
+ @registers = Registers.new
59
+ end
60
+
61
+ attr_writer :stepping
62
+
63
+ def run
64
+ interpret_with_binding(@source, binding)
65
+ cont = @labels.first
66
+ while cont
67
+ cont = cont.execute
68
+ end
69
+ self
70
+ end
71
+
72
+ def display_registers(label)
73
+ @format ||= "%#{@labels.map { |l| l.name.to_s.size }.max}s"
74
+ STDOUT.puts "#{@format % label.name}: #{@registers}"
75
+ if @stepping
76
+ STDOUT.print "? "
77
+ STDOUT.flush
78
+ STDIN.gets
79
+ end
80
+ end
81
+
82
+ private
83
+
84
+ def label(name, &block)
85
+ @labels.find { |l| l.name == name } and
86
+ raise InterpreterError, "label named '#{name}' was already defined"
87
+ block.interpreter, block.name = self, name
88
+ @labels << block
89
+ end
90
+
91
+ def register_fetch(register)
92
+ @registers[register]
93
+ end
94
+
95
+ def register_decrement(register)
96
+ @registers[register] -= 1
97
+ end
98
+
99
+ def register_increment(register)
100
+ @registers[register] += 1
101
+ end
102
+
103
+ def label_fetch(name)
104
+ label = @labels.find { |l| l.name == name }
105
+ label or raise InterpreterError, "label named '#{name}' was not defined"
106
+ end
107
+
108
+ def increment(register, label)
109
+ label = label_fetch label
110
+ register_increment(register)
111
+ label
112
+ end
113
+
114
+ def decrement(register, zero_label, else_label)
115
+ register_value = register_fetch register
116
+ zero_label = label_fetch zero_label
117
+ else_label = label_fetch else_label
118
+ if register_value.zero?
119
+ zero_label
120
+ else
121
+ register_decrement(register)
122
+ else_label
123
+ end
124
+ end
125
+
126
+ def register
127
+ @registers
128
+ end
129
+
130
+ def halt
131
+ STDOUT.puts " *** machine halted"
132
+ nil
133
+ end
134
+ end
135
+ end
136
+
137
+ if $0 == __FILE__
138
+ if ARGV.empty?
139
+ Minsky::Interpreter.new(STDIN.read).run
140
+ else
141
+ interpreter = Minsky::Interpreter.new(File.read(ARGV.shift))
142
+ interpreter.stepping = !ARGV.empty?
143
+ interpreter.run
144
+ end
145
+ end