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