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
@@ -0,0 +1,42 @@
1
+ # vim: set filetype=ruby:
2
+
3
+ # Multiplication: C = A * B, A >= 0 and B >= 0
4
+ register.A = 3
5
+ register.B = 7
6
+
7
+ # Save A in T
8
+ label(SaveA) { decrement A, MoveS1, IncT }
9
+ label(IncT) { increment T, IncS1 }
10
+ label(IncS1) { increment S, SaveA }
11
+
12
+ label(MoveS1) { decrement S, SaveB, IncA1 }
13
+ label(IncA1) { increment A, MoveS1 }
14
+
15
+ # Save B in U
16
+ label(SaveB) { decrement B, MoveS2, IncU }
17
+ label(IncU) { increment U, IncS2 }
18
+ label(IncS2) { increment S, SaveB }
19
+
20
+ label(MoveS2) { decrement S, Mul, IncB1 }
21
+ label(IncB1) { increment B, MoveS2 }
22
+
23
+ # Multiply A * B
24
+ label(Mul) { decrement A, MoveT, DecB }
25
+
26
+ # Add B to C
27
+ label(DecB) { decrement B, MoveU, IncC }
28
+ label(IncC) { increment C, DecB }
29
+
30
+ # Move U back to B
31
+ label(MoveU) { decrement U, SaveB, IncB2 }
32
+ label(IncB2) { increment B, MoveU }
33
+
34
+ # Move T back to A
35
+ label(MoveT) { decrement T, ClearU, IncA2 }
36
+ label(IncA2) { increment A, MoveT }
37
+
38
+ # Clear U
39
+ label(ClearU) { decrement U, Stop, ClearU }
40
+
41
+ # Stop
42
+ label(Stop) { halt }
@@ -0,0 +1,52 @@
1
+ require 'tins'
2
+ $:.unshift 'examples'
3
+
4
+ include Tins::Deflect
5
+
6
+ puts "Example 1"
7
+ deflect(NilClass, :method_missing, Deflector.new { nil }) do
8
+ begin
9
+ p "foo".bar.baz
10
+ rescue NoMethodError
11
+ p "caught 1"
12
+ end
13
+ p nil.bar.baz
14
+ t = Thread.new do
15
+ begin
16
+ p nil.bar.baz
17
+ rescue NoMethodError
18
+ p "caught 2"
19
+ end
20
+ end
21
+ t.join if t.alive?
22
+ p nil.bar.baz
23
+ end
24
+ begin
25
+ p nil.bar.baz
26
+ rescue NoMethodError
27
+ p "caught 3"
28
+ end
29
+
30
+ puts "-" * 70, "Example 2"
31
+ deflect_start(NilClass, :method_missing, Deflector.new { nil })
32
+ begin
33
+ p "foo".bar.baz
34
+ rescue NoMethodError
35
+ p "caught 1"
36
+ end
37
+ p nil.bar.baz
38
+ t = Thread.new do
39
+ begin
40
+ p nil.bar.baz
41
+ rescue NoMethodError
42
+ p "caught 2"
43
+ end
44
+ end
45
+ t.join if t.alive?
46
+ p nil.bar.baz
47
+ deflect_stop(NilClass, :method_missing)
48
+ begin
49
+ p nil.bar.baz
50
+ rescue NoMethodError
51
+ p "caught 3"
52
+ end
@@ -0,0 +1,12 @@
1
+ # vim: ts=2 sw=2 et ft=ruby
2
+ # Call with two strings of ones on the tape:
3
+ # $ turing.rb ones_difference.mtm 1111 11
4
+
5
+ 0. right 1, :goto => 1
6
+ 1. right 2, :goto => 2
7
+ 2. cond 1, :if => '1', :then => 3, :else => 4
8
+ 3. cond 2, :if => '1', :then => 0, :else => 5
9
+ 4. cond 2, :if => '1', :then => 5, :else => 7
10
+ 5. write 0, :symbol => '1', :goto => 6
11
+ 6. left 0, :goto => 0
12
+ 7. halt
@@ -0,0 +1,25 @@
1
+ # vim: ts=2 sw=2 et ft=ruby
2
+ # Call with two strings of ones on the tape:
3
+ # $ turing.rb ones_difference.stm 1111 11
4
+
5
+ 1. right :goto => 2
6
+ 2. cond :if => '1', :then => 1, :else => 3
7
+ 3. right :goto => 4
8
+ 4. cond :if => '1', :then => 5, :else => 17
9
+ 5. right :goto => 6
10
+ 6. cond :if => '1', :then => 5, :else => 7
11
+ 7. left :goto => 8
12
+ 8. write :symbol => 'B', :goto => 9
13
+ 9. left :goto => 10
14
+ 10. cond :if => '1', :then => 9, :else => 11
15
+ 11. left :goto => 12
16
+ 12. cond :if => '1', :then => 11, :else => 13
17
+ 13. right :goto => 14
18
+ 14. cond :if => '1', :then => 15, :else => 16
19
+ 15. write :symbol => 'B', :goto => 1
20
+ 16. write :symbol => '1', :goto => 18
21
+ 17. left :goto => 20
22
+ 18. right :goto => 19
23
+ 19. cond :if => '1', :then => 18, :else => 21
24
+ 20. halt
25
+ 21. halt
@@ -0,0 +1,12 @@
1
+ # vim: ts=2 sw=2 et ft=ruby
2
+ # Call with two strings of ones on the tape:
3
+ # $ turing.rb ones_difference.mtm 1111 11
4
+
5
+ 0. right 1, goto: 1
6
+ 1. right 2, goto: 2
7
+ 2. cond 1, if: '1', then: 3, else: 4
8
+ 3. cond 2, if: '1', then: 0, else: 5
9
+ 4. cond 2, if: '1', then: 5, else: 7
10
+ 5. write 0, symbol: '1', goto: 6
11
+ 6. left 0, goto: 0
12
+ 7. halt
@@ -0,0 +1,25 @@
1
+ # vim: ts=2 sw=2 et ft=ruby
2
+ # Call with two strings of ones on the tape:
3
+ # $ turing.rb ones_difference.stm 1111 11
4
+
5
+ 1. right goto: 2
6
+ 2. cond if: '1', then: 1, else: 3
7
+ 3. right goto: 4
8
+ 4. cond if: '1', then: 5, else: 17
9
+ 5. right goto: 6
10
+ 6. cond if: '1', then: 5, else: 7
11
+ 7. left goto: 8
12
+ 8. write symbol: 'B', goto: 9
13
+ 9. left goto: 10
14
+ 10. cond if: '1', then: 9, else: 11
15
+ 11. left goto: 12
16
+ 12. cond if: '1', then: 11, else: 13
17
+ 13. right goto: 14
18
+ 14. cond if: '1', then: 15, else: 16
19
+ 15. write symbol: 'B', goto: 1
20
+ 16. write symbol: '1', goto: 18
21
+ 17. left goto: 20
22
+ 18. right goto: 19
23
+ 19. cond if: '1', then: 18, else: 21
24
+ 20. halt
25
+ 21. halt
@@ -0,0 +1,38 @@
1
+ # vim: ts=2 sw=2 et ft=ruby
2
+ # Call with a binary number on the tape:
3
+ # $ turing.rb prefix-equals-suffix-reversed-with-infix.stm 100101001
4
+
5
+ 0. right :goto => 1
6
+ 1. cond :if => '0', :then => 2, :else => 13
7
+ 2. write :symbol => 'O', :goto => 3
8
+ 3. right :goto => 4
9
+ 4. cond :if => 'B', :then => 21, :else => 5
10
+ 5. right :goto => 6
11
+ 6. cond :if => 'B', :then => 7, :else => 5
12
+ 7. left :goto => 8
13
+ 8. cond :if => '0', :then => 9, :else => 21
14
+ 9. write :symbol => 'B', :goto => 10
15
+ 10. left :goto => 11
16
+ 11. cond :if => '0', :then => 10, :else => 12
17
+ 12. cond :if => '1', :then => 10, :else => 0
18
+ 13. cond :if => '1', :then => 14, :else => 31
19
+ 14. write :symbol => 'I', :goto => 15
20
+ 15. right :goto => 16
21
+ 16. cond :if => 'B', :then => 21, :else => 17
22
+ 17. right :goto => 18
23
+ 18. cond :if => 'B', :then => 19, :else => 17
24
+ 19. left :goto => 20
25
+ 20. cond :if => '1', :then => 9, :else => 21
26
+ 21. write :symbol => 'B', :goto => 22
27
+ 22. left :goto => 23
28
+ 23. cond :if => '0', :then => 21, :else => 24
29
+ 24. cond :if => '1', :then => 21, :else => 25
30
+ 25. write :symbol => 'B', :goto => 26
31
+ 26. left :goto => 27
32
+ 27. cond :if => 'O', :then => 29, :else => 28
33
+ 28. cond :if => 'I', :then => 30, :else => 32
34
+ 29. write :symbol => '0', :goto => 26
35
+ 30. write :symbol => '1', :goto => 26
36
+ 31. halt
37
+ 32. right :goto => 33
38
+ 33. cond :if => 'B', :then => 31, :else => 32
@@ -0,0 +1,38 @@
1
+ # vim: ts=2 sw=2 et ft=ruby
2
+ # Call with a binary number on the tape:
3
+ # $ turing.rb prefix-equals-suffix-reversed-with-infix.stm 100101001
4
+
5
+ 0. right goto: 1
6
+ 1. cond if: '0', then: 2, else: 13
7
+ 2. write symbol: 'O', goto: 3
8
+ 3. right goto: 4
9
+ 4. cond if: 'B', then: 21, else: 5
10
+ 5. right goto: 6
11
+ 6. cond if: 'B', then: 7, else: 5
12
+ 7. left goto: 8
13
+ 8. cond if: '0', then: 9, else: 21
14
+ 9. write symbol: 'B', goto: 10
15
+ 10. left goto: 11
16
+ 11. cond if: '0', then: 10, else: 12
17
+ 12. cond if: '1', then: 10, else: 0
18
+ 13. cond if: '1', then: 14, else: 31
19
+ 14. write symbol: 'I', goto: 15
20
+ 15. right goto: 16
21
+ 16. cond if: 'B', then: 21, else: 17
22
+ 17. right goto: 18
23
+ 18. cond if: 'B', then: 19, else: 17
24
+ 19. left goto: 20
25
+ 20. cond if: '1', then: 9, else: 21
26
+ 21. write symbol: 'B', goto: 22
27
+ 22. left goto: 23
28
+ 23. cond if: '0', then: 21, else: 24
29
+ 24. cond if: '1', then: 21, else: 25
30
+ 25. write symbol: 'B', goto: 26
31
+ 26. left goto: 27
32
+ 27. cond if: 'O', then: 29, else: 28
33
+ 28. cond if: 'I', then: 30, else: 32
34
+ 29. write symbol: '0', goto: 26
35
+ 30. write symbol: '1', goto: 26
36
+ 31. halt
37
+ 32. right goto: 33
38
+ 33. cond if: 'B', then: 31, else: 32
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tins/xt'
4
+ $:.unshift 'examples'
5
+ require 'recipe_common'
6
+
7
+ class Cup < Unit; end
8
+ class Teaspoon < Unit; end
9
+ class Tablespoon < Unit; end
10
+
11
+ class Flour < Ingredient; end
12
+ class Bakingpowder < Ingredient; end
13
+ class Salt < Ingredient; end
14
+ class Egg < Ingredient; end
15
+ class Milk < Ingredient; end
16
+ class Butter < Ingredient; end
17
+
18
+ class Recipe < Tins::BlankSlate.with(:respond_to?, :instance_exec, :inspect, /^deflect/)
19
+ include Tins::Deflect
20
+
21
+ def initialize(&block)
22
+ @ingredients = []
23
+ deflector = Deflector.new do |number, id, name|
24
+ if unit = Unit.unit(name, number)
25
+ unit
26
+ else
27
+ ingredient = Ingredient.ingredient(name, number)
28
+ @ingredients << ingredient
29
+ end
30
+ end
31
+ deflect(Numeric, :method_missing, deflector) do
32
+ instance_exec(&block)
33
+ end
34
+ end
35
+
36
+ attr_reader :ingredients
37
+
38
+ def to_a
39
+ @ingredients
40
+ end
41
+ alias to_ary to_a
42
+
43
+ def to_s
44
+ to_a * "\n"
45
+ end
46
+ alias inspect to_s
47
+
48
+ def method_missing(name, *args)
49
+ name = name.to_s.gsub(/_/, '').capitalize
50
+ @ingredients << Object.const_get(name).new(*args)
51
+ end
52
+ end
53
+
54
+ class RecipeInterpreter
55
+ def recipe(&block)
56
+ Recipe.new(&block)
57
+ end
58
+ end
59
+
60
+ recipe_source = <<EOT
61
+ pancakes = recipe do
62
+ flour 2.cups
63
+ baking_powder 2.5.teaspoons
64
+ salt 0.5.teaspoon
65
+ egg 1
66
+ milk 1.5.cups
67
+ butter 2.tablespoons
68
+ end
69
+ EOT
70
+
71
+ pancakes = RecipeInterpreter.new.interpret(recipe_source)
72
+ puts pancakes
73
+
74
+ puts
75
+
76
+ def recipe(&block)
77
+ Recipe.new(&block)
78
+ end
79
+
80
+ pancakes = eval recipe_source
81
+ puts pancakes
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tins/xt'
4
+ $:.unshift 'examples'
5
+ require 'recipe_common'
6
+
7
+ class Cup < Unit; end
8
+ class Teaspoon < Unit; end
9
+ class Tablespoon < Unit; end
10
+
11
+ class Flour < Ingredient; end
12
+ class Bakingpowder < Ingredient; end
13
+ class Salt < Ingredient; end
14
+ class Egg < Ingredient; end
15
+ class Milk < Ingredient; end
16
+ class Butter < Ingredient; end
17
+
18
+ class Recipe < Tins::BlankSlate.with(:respond_to?, :instance_exec, :inspect, /^deflect/)
19
+ include Tins::Deflect
20
+
21
+ def initialize(&block)
22
+ @ingredients = []
23
+ deflector = Deflector.new do |number, id, name|
24
+ if unit = Unit.unit(name, number)
25
+ unit
26
+ else
27
+ ingredient = Ingredient.ingredient(name, number)
28
+ @ingredients << ingredient
29
+ end
30
+ end
31
+ deflect_start(Numeric, :method_missing, deflector)
32
+ deflector2 = Deflector.new do |unit, id, name|
33
+ ingredient = Ingredient.ingredient(name, unit)
34
+ @ingredients << ingredient
35
+ end
36
+ deflect_start(Unit, :method_missing, deflector2)
37
+ instance_exec(&block)
38
+ ensure
39
+ deflect_stop(Numeric, :method_missing) if deflect?(Numeric, :method_missing)
40
+ deflect_stop(Unit, :method_missing) if deflect?(Unit, :method_missing)
41
+ end
42
+
43
+ attr_reader :ingredients
44
+
45
+ def to_a
46
+ @ingredients
47
+ end
48
+ alias to_ary to_a
49
+
50
+ def to_s
51
+ to_a * "\n"
52
+ end
53
+ end
54
+
55
+ class RecipeInterpreter
56
+ def recipe(&block)
57
+ Recipe.new(&block)
58
+ end
59
+ end
60
+
61
+ recipe_source = <<EOT
62
+ pancakes = recipe do
63
+ 2.cups. flour
64
+ 2.5.teaspoons. baking_powder
65
+ 0.5.teaspoon. salt
66
+ 1. egg
67
+ 1.5.cups. milk
68
+ 2.tablespoons. butter
69
+ end
70
+ EOT
71
+
72
+ pancakes = RecipeInterpreter.new.interpret(recipe_source)
73
+ puts pancakes
74
+
75
+ puts
76
+
77
+ def recipe(&block)
78
+ Recipe.new(&block)
79
+ end
80
+
81
+ pancakes = eval recipe_source
82
+ puts pancakes
@@ -0,0 +1,97 @@
1
+ class Ingredient
2
+ class << self
3
+ def inherited(klass)
4
+ ingredients << klass
5
+ end
6
+
7
+ attr_accessor :ingredients
8
+
9
+ def ingredient(name, amount)
10
+ name = name.to_s.gsub(/_/, '').capitalize
11
+ if klass = ingredients.find { |n| n.to_s == name }
12
+ klass.new(amount)
13
+ else
14
+ raise "unknown ingredient #{name}"
15
+ end
16
+ end
17
+ end
18
+ self.ingredients = []
19
+
20
+ def initialize(amount = 1)
21
+ @amount = amount
22
+ end
23
+
24
+ def name
25
+ self.class.name.downcase
26
+ end
27
+
28
+ attr_reader :amount
29
+
30
+ def to_s
31
+ "#@amount #{name}"
32
+ end
33
+ end
34
+
35
+ class Unit
36
+ class << self
37
+ def inherited(klass)
38
+ units << klass
39
+ end
40
+
41
+ attr_accessor :units
42
+
43
+ def unit(name, amount)
44
+ name = name.to_s.gsub(/s$/, '').capitalize
45
+ if klass = units.find { |n| n.to_s == name }
46
+ klass.new(amount)
47
+ end
48
+ end
49
+ end
50
+ self.units = []
51
+
52
+ def initialize(n = 1)
53
+ @n = n
54
+ end
55
+
56
+ def name
57
+ self.class.name.downcase
58
+ end
59
+
60
+ attr_reader :n
61
+
62
+ def to_s
63
+ "#@n #{name}#{@n > 1 ? 's' : ''}"
64
+ end
65
+ end
66
+
67
+ class Unit
68
+ class << self
69
+ def inherited(klass)
70
+ units << klass
71
+ end
72
+
73
+ attr_accessor :units
74
+
75
+ def unit(name, amount)
76
+ name = name.to_s.gsub(/s$/, '').capitalize
77
+ if klass = units.find { |n| n.to_s == name }
78
+ klass.new(amount)
79
+ end
80
+ end
81
+ end
82
+ self.units = []
83
+
84
+ def initialize(n = 1)
85
+ @n = n
86
+ end
87
+
88
+ def name
89
+ self.class.name.downcase
90
+ end
91
+
92
+ attr_reader :n
93
+
94
+ def to_s
95
+ "#@n #{name}#{@n > 1 ? 's' : ''}"
96
+ end
97
+ end