maroon 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +26 -6
  3. data/Rakefile +3 -3
  4. data/Test/Context_test.rb +16 -16
  5. data/{Examples/Dijkstra → Test/Examples}/CalculateShortestDistance.rb +11 -13
  6. data/Test/Examples/MoneyTransfer_test.rb +76 -0
  7. data/{Examples/Dijkstra → Test/Examples}/calculate_shortest_path.rb +77 -89
  8. data/{Examples/Dijkstra → Test/Examples}/data.rb +0 -0
  9. data/{Examples/Dijkstra/dijkstra.rb → Test/Examples/dijkstra_test.rb} +34 -24
  10. data/Test/Examples/greeter_test.rb +48 -0
  11. data/{Examples/meter.rb → Test/Examples/meter_test.rb} +44 -30
  12. data/Test/abstract_syntax_tree_test.rb +17 -26
  13. data/Test/alltests.rb +1 -1
  14. data/Test/test_helper.rb +2 -0
  15. data/base/AbstractSyntaxTree.rb +24 -3
  16. data/base/ImmutableStack.rb +1 -1
  17. data/base/dependency_graph.rb +94 -0
  18. data/base/immutable_queue.rb +1 -1
  19. data/base/maroon_base.rb +50 -11
  20. data/base/transfomer.rb +196 -197
  21. data/generated/Tokens.rb +64 -2
  22. data/generated/build.rb +1 -3
  23. data/generated/maroon/kernel.rb +7 -0
  24. data/lib/AbstractSyntaxTree.rb +120 -0
  25. data/lib/AstRewritter.rb +53 -58
  26. data/lib/Context.rb +104 -126
  27. data/lib/DependencyGraph.rb +76 -0
  28. data/lib/ImmutableQueue.rb +28 -39
  29. data/lib/ImmutableStack.rb +20 -34
  30. data/lib/Tokens.rb +64 -2
  31. data/lib/Transformer.rb +125 -165
  32. data/lib/build.rb +2 -4
  33. data/lib/maroon/kernel.rb +1 -1
  34. data/lib/maroon/version.rb +1 -1
  35. metadata +13 -11
  36. data/Examples/MoneyTransfer.rb +0 -62
  37. data/Examples/greeter.rb +0 -46
  38. data/Test/Greeter_test_disabled.rb +0 -203
  39. data/lib/Production.rb +0 -149
@@ -1,10 +1,14 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require './Lib/maroon.rb'
3
- require './Examples/Dijkstra/data.rb'
4
- require './Examples/Dijkstra/CalculateShortestDistance.rb'
5
- require './Examples/Dijkstra/Calculate_Shortest_Path.rb'
2
+ require 'test/unit'
3
+ require_relative '../test_helper'
4
+ require_relative 'data.rb'
5
+ require_relative 'CalculateShortestDistance.rb'
6
+ require_relative 'Calculate_Shortest_Path.rb'
7
+
8
+
9
+ class DijkstraTest < Test::Unit::TestCase
6
10
  #!/usr/bin/env ruby
7
- # Example in Ruby -- Dijkstra's algorithm in DCI
11
+ # Example in Ruby -- DijkstraTest's algorithm in DCI
8
12
  # Modified and simplified for a Manhattan geometry with 8 roles
9
13
  #
10
14
  #
@@ -59,27 +63,33 @@ require './Examples/Dijkstra/Calculate_Shortest_Path.rb'
59
63
 
60
64
  # --- Main Program: test driver
61
65
  #
62
- geometries = Geometry_1.new
63
- path = CalculateShortestPath.new(geometries.root, geometries.destination, geometries)
64
- print 'Path is: '
65
- path.each { |node| print "#{node.name} " }
66
- print "\n"
67
- puts "distance is #{CalculateShortestDistance.new(geometries.root, geometries).distance}"
66
+ def test_geometry_1
67
+ geometries = Geometry_1.new
68
+ path = []
69
+ CalculateShortestPath.new(geometries.root, geometries.destination, geometries,nil,nil,nil,nil).each { |node| path << "#{node.name} " }
70
+ distance = CalculateShortestDistance.new(geometries.root, geometries).distance
71
+ assert_equal(["'i' ","'h' ","'g' ","'d' ","'a' "], path)
72
+ assert_equal(6,distance)
73
+ end
68
74
 
69
- puts ''
70
75
 
71
- geometries = ManhattanGeometry2.new
72
- path = CalculateShortestPath.new(geometries.root, geometries.destination, geometries)
73
- print 'Path is: '
74
- last_node = nil
75
- path.each do |node|
76
- if last_node != nil;
77
- print " - #{geometries.distances[Edge.new(node, last_node)]} - "
76
+ def test_geometry_2
77
+ geometries = ManhattanGeometry2.new
78
+ path = CalculateShortestPath.new(geometries.root, geometries.destination, geometries,nil,nil,nil,nil)
79
+
80
+ last_node = nil
81
+ res = []
82
+ result = []
83
+ path.each do |node|
84
+ if last_node != nil;
85
+ result << geometries.distances[Edge.new(node, last_node)]
86
+ end
87
+ res << "#{node.name}"
88
+ last_node = node
89
+ end
90
+ assert_equal([1,1,3,2], result)
91
+ assert_equal(["'k'", "'j'", "'c'", "'b'", "'a'"], res)
78
92
  end
79
- print "#{node.name}"
80
- last_node = node
81
93
  end
82
- print "\n"
83
94
 
84
- geometries = ManhattanGeometry2.new
85
- puts "distance is #{CalculateShortestDistance.new(geometries.root, geometries).distance }"
95
+
@@ -0,0 +1,48 @@
1
+ #Thanks to Ted Milken for updating the original example
2
+ require 'test/unit'
3
+ require_relative '../test_helper'
4
+
5
+ class Person
6
+ attr_accessor :name
7
+ attr_accessor :greeting
8
+ end
9
+
10
+ class GreeterTest < Test::Unit::TestCase
11
+ def test_greet
12
+ Context.generate_dependency_graph = true
13
+ Context.generate_code = true
14
+ ctx = Context.define :Greet_Someone do
15
+ role :greeter do
16
+ def welcome
17
+ greeter.greeting
18
+ end
19
+ end
20
+
21
+ role :greeted do
22
+ end
23
+
24
+ def greet
25
+ greeter.name.to_s + ': ' + greeter.welcome.to_s + ' ' + greeted.name.to_s + '!'
26
+ end
27
+
28
+ def initialize(greeter, greeted)
29
+ @greeter = greeter
30
+ @greeted = greeted
31
+ end
32
+ end
33
+
34
+ p1 = Person.new
35
+ p1.name = 'Bob'
36
+ p1.greeting = 'Hello'
37
+
38
+ p2 = Person.new
39
+ p2.name = 'World'
40
+ p2.greeting = 'Greetings'
41
+
42
+ res = Greet_Someone.new(p1, p2).greet
43
+ assert_equal("Bob: Hello World!",res)
44
+ puts ""
45
+ p ctx.dependencies.to_dot
46
+ end
47
+
48
+ end
@@ -1,41 +1,39 @@
1
+ require 'test/unit'
2
+ require_relative '../test_helper'
1
3
 
2
- require './lib/maroon/kernel'
4
+ context :Meter do
5
+ def initialize(clock, start_pos)
6
+ @clock = clock
7
+ @route = Route.new({0 => {1 => 1.25}}, Road_types.new)
8
+ route.update_position start_pos
9
+ @price_per_sec = 0.05
10
+ end
3
11
 
4
- context :Meter, :current_total do
5
- role :price_per_sec
12
+ role :price_per_sec do end
6
13
 
7
14
  role :route do
8
- price do
15
+ def price
9
16
  route.calculate_price clock.start
10
17
  end
11
18
  end
12
19
 
13
20
  role :clock do
14
- price do
15
- self.duration * price_per_sec
21
+ def price
22
+ clock.duration * price_per_sec
16
23
  end
17
24
  end
18
25
 
19
- current_total do |current_position|
26
+ def current_total(current_position)
20
27
  route.update_position current_position
21
28
  clock.price + route.price
22
29
  end
23
- print_route do
30
+ def print_route
24
31
  route.each_point { |x, y|
25
- p "#{x},#{y}"
32
+ p x.to_s + ' ' + y.to_s
26
33
  }
27
34
  end
28
35
  end
29
36
 
30
- class Meter
31
- def initialize(start, start_pos)
32
- @clock = Clock.new start
33
- @route = Route.new({0 => {1 => 1.25}}, Road_types.new)
34
- route.update_position start_pos
35
- @price_per_sec = 0.05
36
- end
37
- end
38
-
39
37
  class Clock
40
38
  attr_reader :start
41
39
 
@@ -52,37 +50,34 @@ context :Route do
52
50
  role :prices do
53
51
  end
54
52
  role :payable_position do
55
- price_from do |prev|
53
+ def price_from(prev)
56
54
  return 0 unless prev
57
- delta = Math.sqrt((prev.x-self.x)**2 + (prev.y-self.y)**2 + (prev.z-self.z)**2)
58
- road_type = @road_types[self]
55
+ delta = Math.sqrt((prev.x-payable_position.x)**2 + (prev.y-payable_position.y)**2 + (prev.z-payable_position.z)**2)
56
+ road_type = @road_types[payable_position]
59
57
  price = prices[road_type]
60
58
  delta * price
61
59
  end
62
60
  end
63
61
 
64
62
  role :positions do
65
- price_for_route do |price_table|
63
+ def price_for_route(price_table)
66
64
  prev = nil
67
65
  sum = 0
68
66
  positions.each do |pos|
69
- bind pos => :payable_position, price_table => :prices
70
- sum += pos.price_from prev
71
- prev = pos
67
+ bind :pos => :payable_position, :price_table => :prices
68
+ sum += payable_position.price_from prev
69
+ prev = payable_position
72
70
  end
73
71
  sum
74
72
  end
75
73
  end
76
- update_position do |new_position|
74
+ def update_position(new_position)
77
75
  positions << new_position
78
76
  end
79
- calculate_price do |start_time|
77
+ def calculate_price(start_time)
80
78
  price_table = prices[start_time.hour / (24/prices.length)]
81
79
  positions.price_for_route price_table
82
80
  end
83
- end
84
-
85
- class Route
86
81
  def initialize(prices, road_types)
87
82
  @positions = []
88
83
  @prices = prices
@@ -123,3 +118,22 @@ class Position
123
118
  @z = z
124
119
  end
125
120
  end
121
+
122
+ class MeterTest < Test::Unit::TestCase
123
+ class TestClock
124
+ def initialize(duration)
125
+ @duration = duration
126
+
127
+ end
128
+ def start
129
+ Time.now
130
+ end
131
+ attr_reader :duration
132
+ end
133
+
134
+ def test_run
135
+ meter = Meter.new(TestClock.new(100),Position.new(0,0,0))
136
+ price = meter.current_total Position.new(10,4,5)
137
+ assert_equal(19,price.to_i)
138
+ end
139
+ end
@@ -4,44 +4,35 @@ require_relative '../generated/AbstractSyntaxTree'
4
4
  require_relative 'test_helper'
5
5
 
6
6
  class AbstractSyntaxTreeTest < Test::Unit::TestCase
7
- def get_method_call &b
8
- exp = get_sexp &b
9
- exp[3]
10
- end
11
7
 
12
- def get_context(roles={},contracts={},role_aliases={},defining=nil,private_interactions= {})
13
- InterpretationContext.new(roles, contracts, role_aliases,defining,private_interactions)
8
+ def get_type_of_production(&b)
9
+ contracts ={}
10
+ roles = {:foo => {:bar => []}}
11
+ interpretation_context = InterpretationContext.new(roles, contracts, nil,nil,nil)
12
+
13
+ exp = get_sexp &b
14
+ method_call = exp[3]
15
+ production = AbstractSyntaxTree.new(method_call, interpretation_context )
16
+ production.type
14
17
  end
15
18
 
16
19
  def test_rolemethod
17
- method_call = get_method_call { foo.bar }
18
-
19
- production = get_production(method_call)
20
- type = production.type
20
+ type = get_type_of_production { foo.bar }
21
21
  assert_equal(Tokens::rolemethod_call, type)
22
22
  end
23
23
 
24
- def get_production(method_call)
25
- contracts ={}
26
- roles = {:foo => {:bar => []}}
27
- AbstractSyntaxTree.new(method_call, get_context(roles, contracts))
28
- end
29
-
30
24
  def test_call
31
- method_call = get_method_call { foo.baz }
32
-
33
- production = get_production(method_call)
34
- type = production.type
35
-
25
+ type = get_type_of_production { foo.baz }
36
26
  assert_equal(Tokens::call, type)
37
27
  end
38
28
 
39
- def test_indexer
40
- method_call = get_method_call { foo[0] }
41
-
42
- production = get_production(method_call)
43
- type = production.type
29
+ def test_initializer
30
+ type = get_type_of_production { AbstractSyntaxTreeTest.new(nil) }
31
+ assert_equal(Tokens::initializer, type)
32
+ end
44
33
 
34
+ def test_indexer
35
+ type = get_type_of_production { foo[0] }
45
36
  assert_equal(Tokens::indexer, type)
46
37
  end
47
38
  end
@@ -1 +1 @@
1
- `git ls-files`.split($/).grep(%r{(test|spec|features).rb}).select { |f| p f; require_relative("../#{f}") }
1
+ `git ls-files`.split($/).grep(%r{(test|spec|features).rb}).select { |f| p f; require_relative("../#{f}") }
@@ -2,6 +2,8 @@ require 'minitest/autorun'
2
2
  require 'sourcify'
3
3
  require_relative 'assertions'
4
4
  require_relative '../generated/build'
5
+ require_relative '../generated/maroon/kernel'
6
+
5
7
  #require 'debugger'
6
8
 
7
9
  def get_sexp &b
@@ -9,7 +9,7 @@ context :AbstractSyntaxTree do
9
9
 
10
10
  case
11
11
  when production.is_call? && (interpretation_context.roles.has_key?(production[2]))
12
- @date = [production[2]]
12
+ @data = [production[2]]
13
13
  return true
14
14
  when (production == :self ||
15
15
  (production.is_indexer? && (production[1] == nil || production[1] == :self)) ||
@@ -54,14 +54,31 @@ context :AbstractSyntaxTree do
54
54
  end
55
55
  end
56
56
  end
57
-
57
+ def is_const?
58
+ if production.instance_of?(Sexp) && production.length == 2 && production[0] == :const && (production[1].instance_of? Symbol)
59
+ @data = [production[1]]
60
+ true
61
+ else
62
+ false
63
+ end
64
+ end
65
+ def is_initializer?
66
+ if production.is_call?
67
+ if AbstractSyntaxTree.new(production[1], @interpretation_context).type == Tokens::const
68
+ if production[2] == :new
69
+ return true
70
+ end
71
+ end
72
+ end
73
+ false
74
+ end
58
75
  def is_rolemethod_call?
59
76
  can_be = production.is_call?
60
77
  if can_be
61
78
  instance = AbstractSyntaxTree.new(production[1], @interpretation_context)
62
79
  can_be = instance.type == Tokens::role
63
80
  if can_be
64
- instance_data = instance.data
81
+ instance_data = instance.data[0]
65
82
  role = @interpretation_context.roles[instance_data]
66
83
  data = production[2]
67
84
  can_be = role.has_key?(data)
@@ -93,6 +110,10 @@ context :AbstractSyntaxTree do
93
110
  Tokens::role
94
111
  when production.is_indexer?
95
112
  Tokens::indexer
113
+ when production.is_const?
114
+ Tokens::const
115
+ when production.is_initializer?
116
+ Tokens::initializer
96
117
  when production.is_call?
97
118
  Tokens::call
98
119
  else
@@ -13,7 +13,7 @@ context :ImmutableStack do
13
13
  end
14
14
 
15
15
  def self.empty
16
- @@empty ||= self.new(nil, nil)
16
+ @empty ||= self.new(nil, nil)
17
17
  end
18
18
 
19
19
  def each
@@ -0,0 +1,94 @@
1
+ context :DependencyGraph do
2
+
3
+ def initialize(context_name, roles, interactions, dependencies)
4
+ @context_name = context_name
5
+
6
+ @roles = roles
7
+ @interactions = interactions
8
+ @dependencies = dependencies
9
+ end
10
+
11
+ role :roles do
12
+ def dependencies
13
+ roles.each do |r, methods|
14
+ bind :r => :role_name
15
+ role_dependencies = (dependencies[r] ||= {})
16
+ methods.each do |name, method_sources|
17
+ bind :method_sources => :method, :role_dependencies => :dependency
18
+ method.get_dependencies
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ role :interactions do
25
+ def dependencies
26
+ interactions.each do |name, interact|
27
+ role_dependencies = ((dependencies[:interactions] ||= {})[name] ||= {})
28
+ interact.each do |m|
29
+ bind :m => :method, :role_dependencies => :dependency
30
+ method.get_dependencies
31
+ end
32
+ end
33
+ end
34
+ end
35
+ role :dependencies do end
36
+ role :dependency do
37
+ def add(dependent_role_name,method_name)
38
+ if dependent_role_name && dependent_role_name != role_name
39
+ dependency[dependent_role_name] ||= {}
40
+
41
+ unless dependency[dependent_role_name].has_key? method_name
42
+ dependency[dependent_role_name][method_name] = 0
43
+ end
44
+ dependency[dependent_role_name][method_name] += 1
45
+ end
46
+ end
47
+ end
48
+ role :role_name do end
49
+ role :method do
50
+ def body
51
+ args = method.definition.detect { |d| d[0] == :args }
52
+ index = method.definition.index(args) + 1
53
+ if method.definition.length > index+1
54
+ body = method.definition[index..-1]
55
+ body.insert(0, :block)
56
+ body
57
+ else
58
+ method.definition[index]
59
+ end
60
+ end
61
+
62
+ def ast
63
+ AbstractSyntaxTree.new(method.body, InterpretationContext.new(roles,{},{},role_name,{}))
64
+ end
65
+ def definition
66
+ (method.instance_of? Array) ? method[0] : method
67
+ end
68
+ def get_dependencies
69
+ method.ast.each_production do |production|
70
+ name = nil
71
+ method_name = nil
72
+ case production.type
73
+ when Tokens.rolemethod_call
74
+ data = production.data
75
+ name = data[1]
76
+ method_name = data[0]
77
+ when Tokens.role
78
+ name = production.data[0]
79
+ else
80
+ end
81
+ dependency.add(name,method_name) if name != nil
82
+ end
83
+ end
84
+ end
85
+
86
+ def create!
87
+ roles.dependencies
88
+ interactions.dependencies
89
+ dependencies
90
+ end
91
+
92
+
93
+ end
94
+