maroon 0.7.1 → 0.8.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.
- checksums.yaml +4 -4
- data/README.md +26 -6
- data/Rakefile +3 -3
- data/Test/Context_test.rb +16 -16
- data/{Examples/Dijkstra → Test/Examples}/CalculateShortestDistance.rb +11 -13
- data/Test/Examples/MoneyTransfer_test.rb +76 -0
- data/{Examples/Dijkstra → Test/Examples}/calculate_shortest_path.rb +77 -89
- data/{Examples/Dijkstra → Test/Examples}/data.rb +0 -0
- data/{Examples/Dijkstra/dijkstra.rb → Test/Examples/dijkstra_test.rb} +34 -24
- data/Test/Examples/greeter_test.rb +48 -0
- data/{Examples/meter.rb → Test/Examples/meter_test.rb} +44 -30
- data/Test/abstract_syntax_tree_test.rb +17 -26
- data/Test/alltests.rb +1 -1
- data/Test/test_helper.rb +2 -0
- data/base/AbstractSyntaxTree.rb +24 -3
- data/base/ImmutableStack.rb +1 -1
- data/base/dependency_graph.rb +94 -0
- data/base/immutable_queue.rb +1 -1
- data/base/maroon_base.rb +50 -11
- data/base/transfomer.rb +196 -197
- data/generated/Tokens.rb +64 -2
- data/generated/build.rb +1 -3
- data/generated/maroon/kernel.rb +7 -0
- data/lib/AbstractSyntaxTree.rb +120 -0
- data/lib/AstRewritter.rb +53 -58
- data/lib/Context.rb +104 -126
- data/lib/DependencyGraph.rb +76 -0
- data/lib/ImmutableQueue.rb +28 -39
- data/lib/ImmutableStack.rb +20 -34
- data/lib/Tokens.rb +64 -2
- data/lib/Transformer.rb +125 -165
- data/lib/build.rb +2 -4
- data/lib/maroon/kernel.rb +1 -1
- data/lib/maroon/version.rb +1 -1
- metadata +13 -11
- data/Examples/MoneyTransfer.rb +0 -62
- data/Examples/greeter.rb +0 -46
- data/Test/Greeter_test_disabled.rb +0 -203
- data/lib/Production.rb +0 -149
File without changes
|
@@ -1,10 +1,14 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
require '
|
3
|
-
|
4
|
-
|
5
|
-
|
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 --
|
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
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
5
|
-
role :price_per_sec
|
12
|
+
role :price_per_sec do end
|
6
13
|
|
7
14
|
role :route do
|
8
|
-
price
|
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
|
15
|
-
|
21
|
+
def price
|
22
|
+
clock.duration * price_per_sec
|
16
23
|
end
|
17
24
|
end
|
18
25
|
|
19
|
-
current_total
|
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
|
30
|
+
def print_route
|
24
31
|
route.each_point { |x, y|
|
25
|
-
p
|
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
|
53
|
+
def price_from(prev)
|
56
54
|
return 0 unless prev
|
57
|
-
delta = Math.sqrt((prev.x-
|
58
|
-
road_type = @road_types[
|
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
|
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 +=
|
71
|
-
prev =
|
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
|
74
|
+
def update_position(new_position)
|
77
75
|
positions << new_position
|
78
76
|
end
|
79
|
-
calculate_price
|
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
|
13
|
-
|
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
|
-
|
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
|
-
|
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
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
data/Test/alltests.rb
CHANGED
@@ -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}") }
|
data/Test/test_helper.rb
CHANGED
data/base/AbstractSyntaxTree.rb
CHANGED
@@ -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
|
-
@
|
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
|
data/base/ImmutableStack.rb
CHANGED
@@ -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
|
+
|