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,6 +1,11 @@
1
1
  class Tokens
2
2
  def self.define_token(name)
3
- class_eval("@@#{name} = Tokens.new :#{name};def Tokens.#{name};@@#{name};end")
3
+ class_eval %{
4
+ @#{name} = Tokens.new :#{name};
5
+ def Tokens.#{name}
6
+ @#{name}
7
+ end
8
+ }
4
9
  end
5
10
 
6
11
  def to_s
@@ -21,4 +26,61 @@ class Tokens
21
26
  define_token :indexer
22
27
  define_token :block
23
28
  define_token :block_with_bind
24
- end
29
+ define_token :initializer
30
+ define_token :const
31
+ end
32
+
33
+ class DependencyGraphModel
34
+
35
+ def initialize(dependencies)
36
+ @dependencies = dependencies
37
+ end
38
+
39
+ def to_hash
40
+ @dependecies
41
+ end
42
+
43
+ def to_s
44
+ print_dependencies @dependencies,0
45
+ end
46
+
47
+ def to_dot
48
+ res = ''
49
+ dependencies = denormalize @dependencies
50
+ dependencies.each{|d| res << d.reverse.join('->') << '
51
+ '}
52
+ 'digraph g{
53
+ ' + res + '}'
54
+ end
55
+
56
+ private
57
+ def print_dependencies(dependencies,indent)
58
+ res = ''
59
+ dependencies.each do |key,value|
60
+ res << key.to_s
61
+ if value.instance_of? Hash
62
+ res << '->' << (print_dependencies value,indent != nil ? indent+4 : nil)
63
+ elsif
64
+ res << ':' << value.to_s + '
65
+ '
66
+ indent.times {res << ' '} unless indent == nil
67
+ end
68
+ res << '
69
+ '
70
+ end
71
+ res
72
+ end
73
+
74
+ def denormalize(dependencies)
75
+ res = []
76
+ dependencies.each do |key,value|
77
+ if value.instance_of? Hash
78
+ res = denormalize value
79
+ res.each{|a| a << key}
80
+ else
81
+ res << [key]
82
+ end
83
+ end
84
+ res
85
+ end
86
+ end
@@ -9,6 +9,4 @@ require_relative './interpretation_context'
9
9
  require_relative './AbstractSyntaxTree'
10
10
  require_relative './AstRewritter'
11
11
  require_relative './Transformer'
12
-
13
-
14
-
12
+ require_relative './DependencyGraph'
@@ -0,0 +1,7 @@
1
+ require_relative '../Context'
2
+
3
+ unless Kernel::methods.detect { |m| m== :context }
4
+ def context(*args, &b)
5
+ Context.define *args, &b
6
+ end
7
+ end
@@ -0,0 +1,120 @@
1
+ class AbstractSyntaxTree
2
+ def initialize(ast,interpretation_context) rebind(ImmutableQueue.empty.push(ast), interpretation_context) end
3
+ def type() case
4
+ when (nil == production) then
5
+ nil
6
+ when self_production_is_block_with_bind? then
7
+ Tokens.block_with_bind
8
+ when self_production_is_block? then
9
+ Tokens.block
10
+ when (production.instance_of?(Fixnum) or production.instance_of?(Symbol)) then
11
+ Tokens.terminal
12
+ when self_production_is_rolemethod_call? then
13
+ Tokens.rolemethod_call
14
+ when self_production_is_role? then
15
+ Tokens.role
16
+ when self_production_is_indexer? then
17
+ Tokens.indexer
18
+ when self_production_is_const? then
19
+ Tokens.const
20
+ when self_production_is_initializer? then
21
+ Tokens.initializer
22
+ when self_production_is_call? then
23
+ Tokens.call
24
+ else
25
+ Tokens.other
26
+ end end
27
+ def [](i) @production[i] end
28
+ def []=(i,v) @production[i] = v end
29
+ def length() @production.length end
30
+ def last() @production.last end
31
+ def first() @production.first end
32
+ def data() return @data if @data
33
+ @data = case
34
+ when self_production_is_call? then
35
+ @production[2]
36
+ else
37
+ @production
38
+ end
39
+ end
40
+ def each_production() yield(self)
41
+ if production.instance_of?((Sexp or production.instance_of?(Array))) then
42
+ @queue = @queue.push_array(production)
43
+ end
44
+ while @queue.!=(ImmutableQueue.empty) do
45
+ rebind(@queue, @interpretation_context)
46
+ yield(self)
47
+ if production.instance_of?((Sexp or production.instance_of?(Array))) then
48
+ @queue = @queue.push_array(production)
49
+ end
50
+ end
51
+ end
52
+ private
53
+ def rebind(queue,ctx) @data = nil
54
+ @production, @queue = queue.pop
55
+ @interpretation_context = ctx
56
+ end
57
+ def self_production_is_role?() case
58
+ when (self_production_is_call? and interpretation_context.roles.has_key?(production[2])) then
59
+ @data = [production[2]]
60
+ return true
61
+ when (((production == :self) or ((self_production_is_indexer? and ((production[1] == nil) or (production[1] == :self))) or (production and ((production.instance_of?(Sexp) or production.instance_of?(Array)) and (production[0] == :self))))) and @interpretation_context.defining_role) then
62
+ @data = @interpretation_context.defining_role
63
+ return true
64
+ else
65
+ false
66
+ end end
67
+ def self_production_is_indexer?() self_production_is_call? and ((production[2] == :[]) or (production[2] == :[]=)) end
68
+ def self_production_is_call?() production and ((production.instance_of?(Sexp) or production.instance_of?(Array)) and (production[0] == :call)) end
69
+ def self_production_is_block?() production and ((production.instance_of?(Sexp) or production.instance_of?(Array)) and (production[0] == :iter)) end
70
+ def self_production_is_block_with_bind?() if self_production_is_block? then
71
+ body = @production.last
72
+ if body and exp = body[1] then
73
+ bind = AbstractSyntaxTree.new(exp, @interpretation_context)
74
+ if (bind.type == Tokens.call) and (bind.data == :bind) then
75
+ aliases = {}
76
+ list = exp.last[(1..-1)]
77
+ (list.length / 2).times do |i|
78
+ local = list[(i * 2)].last
79
+ role_name = list[((i * 2) + 1)].last
80
+ raise("Local in bind should be a symbol") unless local.instance_of?(Symbol)
81
+ unless role_name.instance_of?(Symbol) then
82
+ raise("Role name in bind should be a symbol")
83
+ end
84
+ aliases[local] = role_name
85
+ end
86
+ @data = aliases
87
+ true
88
+ end
89
+ end
90
+ end end
91
+ def self_production_is_const?() if production.instance_of?(Sexp) and ((production.length == 2) and ((production[0] == :const) and production[1].instance_of?(Symbol))) then
92
+ @data = [production[1]]
93
+ true
94
+ else
95
+ false
96
+ end end
97
+ def self_production_is_initializer?() if self_production_is_call? then
98
+ if (AbstractSyntaxTree.new(production[1], @interpretation_context).type == Tokens.const) then
99
+ return true if (production[2] == :new)
100
+ end
101
+ end
102
+ false
103
+ end
104
+ def self_production_is_rolemethod_call?() can_be = self_production_is_call?
105
+ if can_be then
106
+ instance = AbstractSyntaxTree.new(production[1], @interpretation_context)
107
+ can_be = (instance.type == Tokens.role)
108
+ if can_be then
109
+ instance_data = instance.data[0]
110
+ role = @interpretation_context.roles[instance_data]
111
+ data = production[2]
112
+ can_be = role.has_key?(data)
113
+ @data = [data, instance_data]
114
+ end
115
+ end
116
+ can_be
117
+ end
118
+ attr_reader :interpretation_context, :queue, :production
119
+
120
+ end
@@ -1,65 +1,60 @@
1
1
  class AstRewritter
2
- def initialize(ast, interpretation_context)
3
- @ast = Production.new(ast, interpretation_context)
4
- @roles = interpretation_context.roles
5
- end
6
-
7
- def rewrite!()
8
- ast.each do |production|
9
- case production.type
10
- when Tokens.rolemethod_call then
11
- data = production.data
12
- production[2] = ((("self_" + data[1].to_s) + "_") + data[0].to_s).to_sym
13
- production[1] = nil
14
- when Tokens.block_with_bind then
15
- block = production.last
16
- block.delete_at(1)
17
- production.data.each do |local, aliased_role|
18
- must_b_sym = "aliased_role must be a Symbol".to_sym
19
- local_must_b_sym = "local must be a Symbol".to_sym
20
- raise(must_b_sym) unless aliased_role.instance_of?(Symbol)
21
- raise(local_must_b_sym) unless local.instance_of?(Symbol)
22
- unless @roles.has_key?(aliased_role) then
23
- role_names = []
24
- @interpretation_context.each { |k, v| (role_names << k.to_s) }
25
- raise(((aliased_role.to_s + " is not a role. Available roles are ") + role_names.join(",")))
26
- end
27
- aliased_field = ("@" + aliased_role.to_s).to_sym
28
- temp_symbol = ("temp____" + aliased_role.to_s).to_sym
29
- assignment = Sexp.new
30
- assignment[0] = :iasgn
31
- assignment[1] = aliased_field
32
- load_arg = Sexp.new
33
- load_arg[0] = :lvar
34
- load_arg[1] = local
35
- assignment[2] = load_arg
36
- block.insert(1, assignment)
37
- assignment = Sexp.new
38
- assignment[0] = :lasgn
39
- assignment[1] = temp_symbol
40
- load_field = Sexp.new
41
- load_field[0] = :ivar
42
- load_field[1] = aliased_field
43
- assignment[2] = load_field
44
- block.insert(1, assignment)
45
- assignment = Sexp.new
46
- assignment[0] = :iasgn
47
- assignment[1] = aliased_field
48
- load_temp = Sexp.new
49
- load_temp[0] = :lvar
50
- load_temp[1] = temp_symbol
51
- assignment[2] = load_temp
52
- block[block.length] = assignment
53
- end
54
- else
55
- # do nothing
2
+ def initialize(ast,interpretation_context) @ast = AbstractSyntaxTree.new(ast, interpretation_context)
3
+ @roles = interpretation_context.roles
4
+ end
5
+ def rewrite!() ast.each_production do |production|
6
+ case production.type
7
+ when Tokens.rolemethod_call then
8
+ data = production.data
9
+ production[2] = ((("self_" + data[1].to_s) + "_") + data[0].to_s).to_sym
10
+ production[1] = nil
11
+ when Tokens.block_with_bind then
12
+ block = production.last
13
+ block.delete_at(1)
14
+ production.data.each do |local, aliased_role|
15
+ must_b_sym = "aliased_role must be a Symbol".to_sym
16
+ local_must_b_sym = "local must be a Symbol".to_sym
17
+ raise(must_b_sym) unless aliased_role.instance_of?(Symbol)
18
+ raise(local_must_b_sym) unless local.instance_of?(Symbol)
19
+ unless @roles.has_key?(aliased_role) then
20
+ role_names = []
21
+ @interpretation_context.each { |k, v| (role_names << k.to_s) }
22
+ raise(((aliased_role.to_s + " is not a role. Available roles are ") + role_names.join(",")))
56
23
  end
24
+ aliased_field = ("@" + aliased_role.to_s).to_sym
25
+ temp_symbol = ("temp____" + aliased_role.to_s).to_sym
26
+ assignment = Sexp.new
27
+ assignment[0] = :iasgn
28
+ assignment[1] = aliased_field
29
+ load_arg = Sexp.new
30
+ load_arg[0] = :lvar
31
+ load_arg[1] = local
32
+ assignment[2] = load_arg
33
+ block.insert(1, assignment)
34
+ assignment = Sexp.new
35
+ assignment[0] = :lasgn
36
+ assignment[1] = temp_symbol
37
+ load_field = Sexp.new
38
+ load_field[0] = :ivar
39
+ load_field[1] = aliased_field
40
+ assignment[2] = load_field
41
+ block.insert(1, assignment)
42
+ assignment = Sexp.new
43
+ assignment[0] = :iasgn
44
+ assignment[1] = aliased_field
45
+ load_temp = Sexp.new
46
+ load_temp[0] = :lvar
47
+ load_temp[1] = temp_symbol
48
+ assignment[2] = load_temp
49
+ block[block.length] = assignment
57
50
  end
51
+ else
52
+ # do nothing
58
53
  end
59
-
60
- private
54
+ end end
55
+ private
61
56
 
62
57
 
63
- attr_reader :ast
58
+ attr_reader :ast
64
59
 
65
- end
60
+ end
@@ -1,133 +1,111 @@
1
1
  class Context
2
- def self.define(*args, &block)
3
- name, base_class, default_interaction = *args
4
- if default_interaction and (not base_class.instance_of?(Class)) then
5
- base_class = eval(base_class.to_s)
6
- end
7
- if base_class and ((not default_interaction) and (not base_class.instance_of?(Class))) then
8
- base_class, default_interaction = default_interaction, base_class
9
- end
10
- @@with_contracts ||= nil
11
- @@generate_file_path ||= nil
12
- ctx = self.send(:create_context_factory, name, base_class, default_interaction, block)
13
- transformer = Transformer.new(name, ctx.roles, ctx.interactions, ctx.private_interactions, base_class, default_interaction)
14
- return transformer.transform(@@generate_file_path, @@with_contracts)
15
- end
16
-
17
- def self.generate_files_in(*args, &b)
18
- @@generate_file_path = args[0]
19
- end
20
-
21
- def roles()
22
- @roles
23
- end
24
-
25
- def interactions()
26
- @interactions
27
- end
28
-
29
- def private_interactions()
30
- @private_interactions
31
- end
32
-
33
- private
34
- def get_definitions(b)
35
- sexp = b.to_sexp
36
- unless is_definition?(sexp[3]) then
37
- sexp = sexp[3]
38
- sexp = sexp.select { |exp| is_definition?(exp) } if sexp
39
- sexp ||= []
40
- end
41
- sexp.select { |exp| is_definition?(exp) }
42
- end
43
-
44
- def self.create_context_factory(name, base_class, default_interaction, block)
45
- ctx = Context.new(name, base_class, default_interaction)
46
- ctx.instance_eval do
47
- sexp = block.to_sexp
48
- temp_block = sexp[3]
49
- i = 0
50
- while (i < temp_block.length) do
51
- exp = temp_block[i]
52
- unless temp_block[(i - 2)] and ((temp_block[(i - 2)][0] == :call) and (temp_block[(i - 1)] and (temp_block[(i - 1)][0] == :args))) then
53
- if ((exp[0] == :defn) or (exp[0] == :defs)) then
54
- add_method(exp)
55
- temp_block.delete_at(i)
56
- i = (i - 1)
57
- else
58
- if (exp[0] == :call) and ((exp[1] == nil) and (exp[2] == :private)) then
59
- @private = true
60
- end
61
- end
2
+ def self.define(*args,&block) name, base_class, default_interaction = *args
3
+ if default_interaction and (not base_class.instance_of?(Class)) then
4
+ base_class = eval(base_class.to_s)
5
+ end
6
+ if base_class and ((not default_interaction) and (not base_class.instance_of?(Class))) then
7
+ base_class, default_interaction = default_interaction, base_class
8
+ end
9
+ @with_contracts ||= nil
10
+ ctx = self.send(:create_context_factory, name, base_class, default_interaction, block)
11
+ if self.generate_dependency_graph then
12
+ dependencies = {}
13
+ ctx.dependencies = DependencyGraphModel.new(DependencyGraph.new(name, ctx.roles, ctx.interactions, dependencies).create!)
14
+ end
15
+ transformer = Transformer.new(name, ctx.roles, ctx.interactions, ctx.private_interactions, base_class, default_interaction)
16
+ ctx.generated_class = transformer.transform(generate_files_in, @with_contracts)
17
+ ctx
18
+ end
19
+ def self.generate_files_in() @generate_files_in end
20
+ def self.generate_files_in=(folder) @generate_files_in = folder end
21
+ def self.generate_code=(value) @generate_code = value end
22
+ def self.generate_dependency_graph=(value) @generate_dependency_graph = value end
23
+ def self.generate_code() (@generate_code or ((not generate_dependency_graph) or generate_files_in)) end
24
+ def self.generate_dependency_graph() @generate_dependency_graph end
25
+ def dependencies() @dependencies end
26
+ def generated_class() @generated_class end
27
+ def dependencies=(value) @dependencies = value end
28
+ def generated_class=(value) @generated_class = value end
29
+ def roles() @roles end
30
+ def interactions() @interactions end
31
+ def private_interactions() @private_interactions end
32
+ private
33
+ def get_definitions(b) sexp = b.to_sexp
34
+ unless is_definition?(sexp[3]) then
35
+ sexp = sexp[3]
36
+ sexp = sexp.select { |exp| is_definition?(exp) } if sexp
37
+ sexp ||= []
38
+ end
39
+ sexp.select { |exp| is_definition?(exp) }
40
+ end
41
+ def self.create_context_factory(name,base_class,default_interaction,block) ctx = Context.new(name, base_class, default_interaction)
42
+ ctx.instance_eval do
43
+ sexp = block.to_sexp
44
+ temp_block = sexp[3]
45
+ i = 0
46
+ while (i < temp_block.length) do
47
+ exp = temp_block[i]
48
+ unless temp_block[(i - 2)] and ((temp_block[(i - 2)][0] == :call) and (temp_block[(i - 1)] and (temp_block[(i - 1)][0] == :args))) then
49
+ if ((exp[0] == :defn) or (exp[0] == :defs)) then
50
+ add_method(exp)
51
+ temp_block.delete_at(i)
52
+ i = (i - 1)
53
+ else
54
+ if (exp[0] == :call) and ((exp[1] == nil) and (exp[2] == :private)) then
55
+ @private = true
62
56
  end
63
- i = (i + 1)
64
57
  end
65
- ctx.instance_eval(&block)
66
- end
67
- ctx
68
- end
69
-
70
- def self.with_contracts(*args)
71
- return @@with_contracts if (args.length == 0)
72
- value = args[0]
73
- if @@with_contracts and (not value) then
74
- raise("make up your mind! disabling contracts during execution will result in undefined behavior")
75
- end
76
- @@with_contracts = value
77
- end
78
-
79
- def is_definition?(exp)
80
- exp and ((exp[0] == :defn) or (exp[0] == :defs))
81
- end
82
-
83
- def role(*args, &b)
84
- role_name = args[0]
85
- @defining_role = role_name
86
- @roles = {} unless @roles
87
- @roles[role_name] = Hash.new
88
- if block_given? then
89
- definitions = get_definitions(b)
90
- definitions.each { |exp| add_method(exp) }
91
- end
92
- end
93
-
94
- def get_methods(*args, &b)
95
- name = args[0]
96
- sources = (@defining_role ? (@roles[@defining_role]) : (@interactions))[name]
97
- if @defining_role and (not sources) then
98
- @roles[@defining_role][name] = []
99
- else
100
- @private_interactions[name] = true if @private
101
- @interactions[name] = []
102
58
  end
59
+ i = (i + 1)
103
60
  end
61
+ ctx.instance_eval(&block)
62
+ end
63
+ ctx
64
+ end
65
+ def self.with_contracts(*args) return @with_contracts if (args.length == 0)
66
+ value = args[0]
67
+ if @with_contracts and (not value) then
68
+ raise("make up your mind! disabling contracts during execution will result in undefined behavior")
69
+ end
70
+ @with_contracts = value
71
+ end
72
+ def is_definition?(exp) exp and ((exp[0] == :defn) or (exp[0] == :defs)) end
73
+ def role(*args,&b) role_name = args[0]
74
+ @defining_role = role_name
75
+ @roles = {} unless @roles
76
+ @roles[role_name] = Hash.new
77
+ if block_given? then
78
+ definitions = get_definitions(b)
79
+ definitions.each { |exp| add_method(exp) }
80
+ end
81
+ end
82
+ def get_methods(*args,&b) name = args[0]
83
+ sources = (@defining_role ? (@roles[@defining_role]) : (@interactions))[name]
84
+ if @defining_role and (not sources) then
85
+ @roles[@defining_role][name] = []
86
+ else
87
+ @private_interactions[name] = true if @private
88
+ @interactions[name] = []
89
+ end
90
+ end
91
+ def add_method(definition) name = if definition[1].instance_of?(Symbol) then
92
+ definition[1]
93
+ else
94
+ ((definition[1].select { |e| e.instance_of?(Symbol) }.map { |e| e.to_s }.join(".") + ".") + definition[2].to_s).to_sym
95
+ end
96
+ sources = get_methods(name)
97
+ (sources << definition)
98
+ end
99
+ def private() @private = true end
100
+ def initialize(name,base_class,default_interaction) @roles = {}
101
+ @interactions = {}
102
+ @private_interactions = {}
103
+ @role_alias = {}
104
+ @name = name
105
+ @base_class = base_class
106
+ @default_interaction = default_interaction
107
+ end
104
108
 
105
- def add_method(definition)
106
- name = if definition[1].instance_of?(Symbol) then
107
- definition[1]
108
- else
109
- ((definition[1].select { |e| e.instance_of?(Symbol) }.map { |e| e.to_s }.join(".") + ".") + definition[2].to_s).to_sym
110
- end
111
- sources = get_methods(name)
112
- (sources << definition)
113
- end
114
-
115
- def private()
116
- @private = true
117
- end
118
-
119
- def initialize(name, base_class, default_interaction)
120
- @roles = {}
121
- @interactions = {}
122
- @private_interactions = {}
123
- @role_alias = {}
124
- @name = name
125
- @base_class = base_class
126
- @default_interaction = default_interaction
127
- end
128
-
129
- attr_reader :name
130
- attr_reader :base_class
131
- attr_reader :default_interaction
109
+ attr_reader :name, :base_class, :default_interaction
132
110
 
133
- end
111
+ end