tins 0.13.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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