orbacle 0.1.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 +7 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +119 -0
- data/LICENSE +22 -0
- data/Makefile +57 -0
- data/README.md +53 -0
- data/circle.yml +82 -0
- data/exe/orbaclerun +6 -0
- data/index.html +106 -0
- data/lib/orbacle.rb +96 -0
- data/lib/orbacle/ast_utils.rb +35 -0
- data/lib/orbacle/bottom_type.rb +23 -0
- data/lib/orbacle/builder.rb +1414 -0
- data/lib/orbacle/builder/context.rb +71 -0
- data/lib/orbacle/builder/operator_assignment_processors.rb +80 -0
- data/lib/orbacle/class_type.rb +32 -0
- data/lib/orbacle/command_line_interface.rb +107 -0
- data/lib/orbacle/const_name.rb +33 -0
- data/lib/orbacle/const_ref.rb +53 -0
- data/lib/orbacle/constants_tree.rb +73 -0
- data/lib/orbacle/define_builtins.rb +139 -0
- data/lib/orbacle/engine.rb +74 -0
- data/lib/orbacle/find_definition_under_position.rb +76 -0
- data/lib/orbacle/generic_type.rb +35 -0
- data/lib/orbacle/global_tree.rb +280 -0
- data/lib/orbacle/graph.rb +126 -0
- data/lib/orbacle/indexer.rb +151 -0
- data/lib/orbacle/integer_id_generator.rb +13 -0
- data/lib/orbacle/lambda_type.rb +37 -0
- data/lib/orbacle/lang_server.rb +64 -0
- data/lib/orbacle/main_type.rb +23 -0
- data/lib/orbacle/nesting.rb +78 -0
- data/lib/orbacle/node.rb +23 -0
- data/lib/orbacle/nominal_type.rb +32 -0
- data/lib/orbacle/ruby_parser.rb +19 -0
- data/lib/orbacle/scope.rb +63 -0
- data/lib/orbacle/selfie.rb +41 -0
- data/lib/orbacle/type_pretty_printer.rb +24 -0
- data/lib/orbacle/typing_service.rb +816 -0
- data/lib/orbacle/union_type.rb +40 -0
- data/lib/orbacle/uuid_id_generator.rb +11 -0
- data/lib/orbacle/worklist.rb +51 -0
- data/orbacle.gemspec +33 -0
- metadata +258 -0
@@ -0,0 +1,139 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orbacle
|
4
|
+
class DefineBuiltins
|
5
|
+
def initialize(graph, tree, id_generator)
|
6
|
+
@graph = graph
|
7
|
+
@tree = tree
|
8
|
+
@id_generator = id_generator
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
add_object_klass
|
13
|
+
add_dir_klass
|
14
|
+
add_file_klass
|
15
|
+
add_integer_klass
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
attr_reader :id_generator
|
20
|
+
|
21
|
+
def add_object_klass
|
22
|
+
klass = @tree.add_klass(nil)
|
23
|
+
@tree.add_constant(
|
24
|
+
GlobalTree::Constant.new("Object", Scope.empty, nil, klass.id))
|
25
|
+
|
26
|
+
# BasicObject
|
27
|
+
template_just_bool(klass, "==")
|
28
|
+
template_just_bool(klass, "!")
|
29
|
+
template_just_bool(klass, "!=")
|
30
|
+
template_just_bool(klass, "equal?")
|
31
|
+
template_just_int(klass, "object_id")
|
32
|
+
template_just_int(klass, "__id__")
|
33
|
+
|
34
|
+
# Object
|
35
|
+
template_just_bool(klass, "!~")
|
36
|
+
template_maybe_int(klass, "<=>")
|
37
|
+
template_just_bool(klass, "===")
|
38
|
+
template_just_nil(klass, "display")
|
39
|
+
template_just_bool(klass, "eql?")
|
40
|
+
template_just_bool(klass, "frozen?")
|
41
|
+
template_just_bool(klass, "instance_of?")
|
42
|
+
template_just_bool(klass, "instance_variable_defined?")
|
43
|
+
template_just_bool(klass, "is_a?")
|
44
|
+
template_just_str(klass, "inspect")
|
45
|
+
template_just_bool(klass, "kind_of?")
|
46
|
+
template_just_bool(klass, "nil?")
|
47
|
+
template_just_bool(klass, "respond_to?")
|
48
|
+
template_just_bool(klass, "respond_to_missing?")
|
49
|
+
template_just_bool(klass, "tainted?")
|
50
|
+
template_just_bool(klass, "untrusted?")
|
51
|
+
template_just_str(klass, "to_s")
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_integer_klass
|
55
|
+
klass = @tree.add_klass(nil)
|
56
|
+
@tree.add_constant(
|
57
|
+
GlobalTree::Constant.new("Integer", Scope.empty, nil, klass.id))
|
58
|
+
|
59
|
+
template_just_int(klass, "succ")
|
60
|
+
template_just_int(klass, "+")
|
61
|
+
template_just_int(klass, "-")
|
62
|
+
template_just_int(klass, "*")
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_dir_klass
|
66
|
+
klass = @tree.add_klass(nil)
|
67
|
+
@tree.add_constant(
|
68
|
+
GlobalTree::Constant.new("Dir", Scope.empty, nil, klass.id))
|
69
|
+
eigenclass = @tree.get_eigenclass_of_definition(klass.id)
|
70
|
+
|
71
|
+
template_just_array_of_str(eigenclass, "glob")
|
72
|
+
end
|
73
|
+
|
74
|
+
def add_file_klass
|
75
|
+
klass = @tree.add_klass(nil)
|
76
|
+
@tree.add_constant(
|
77
|
+
GlobalTree::Constant.new("File", Scope.empty, nil, klass.id))
|
78
|
+
eigenclass = @tree.get_eigenclass_of_definition(klass.id)
|
79
|
+
|
80
|
+
template_just_str(eigenclass, "read")
|
81
|
+
end
|
82
|
+
|
83
|
+
def template_just_int(klass, name)
|
84
|
+
metod = template_args(klass, name)
|
85
|
+
int_node = Node.new(:int, {})
|
86
|
+
@graph.add_edge(int_node, @graph.get_metod_nodes(metod.id).result)
|
87
|
+
end
|
88
|
+
|
89
|
+
def template_maybe_int(klass, name)
|
90
|
+
metod = template_args(klass, name)
|
91
|
+
int_node = Node.new(:int, {})
|
92
|
+
nil_node = Node.new(:nil, {})
|
93
|
+
@graph.add_edge(int_node, @graph.get_metod_nodes(metod.id).result)
|
94
|
+
@graph.add_edge(nil_node, @graph.get_metod_nodes(metod.id).result)
|
95
|
+
end
|
96
|
+
|
97
|
+
def template_just_str(klass, name)
|
98
|
+
metod = template_args(klass, name)
|
99
|
+
str_node = Node.new(:str, {})
|
100
|
+
@graph.add_edge(str_node, @graph.get_metod_nodes(metod.id).result)
|
101
|
+
end
|
102
|
+
|
103
|
+
def template_just_bool(klass, name)
|
104
|
+
metod = template_args(klass, name)
|
105
|
+
str_node = Node.new(:bool, {})
|
106
|
+
@graph.add_edge(str_node, @graph.get_metod_nodes(metod.id).result)
|
107
|
+
end
|
108
|
+
|
109
|
+
def template_just_nil(klass, name)
|
110
|
+
metod = template_args(klass, name)
|
111
|
+
str_node = Node.new(:nil, {})
|
112
|
+
@graph.add_edge(str_node, @graph.get_metod_nodes(metod.id).result)
|
113
|
+
end
|
114
|
+
|
115
|
+
def template_just_array_of_str(klass, name)
|
116
|
+
metod = template_args(klass, name)
|
117
|
+
str_node = Node.new(:str, {})
|
118
|
+
array_node = Node.new(:array, {})
|
119
|
+
@graph.add_edge(str_node, array_node)
|
120
|
+
@graph.add_edge(array_node, @graph.get_metod_nodes(metod.id).result)
|
121
|
+
end
|
122
|
+
|
123
|
+
def template_args(klass, name)
|
124
|
+
metod = @tree.add_method(
|
125
|
+
generate_id,
|
126
|
+
klass.id,
|
127
|
+
name,
|
128
|
+
nil,
|
129
|
+
:public,
|
130
|
+
GlobalTree::ArgumentsTree.new([], []))
|
131
|
+
@graph.store_metod_nodes(metod.id, {})
|
132
|
+
metod
|
133
|
+
end
|
134
|
+
|
135
|
+
def generate_id
|
136
|
+
id_generator.call
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orbacle
|
4
|
+
class Engine
|
5
|
+
def initialize(logger)
|
6
|
+
@logger = logger
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :stats_recorder
|
10
|
+
|
11
|
+
def index(project_root)
|
12
|
+
@stats_recorder = Indexer::StatsRecorder.new
|
13
|
+
service = Indexer.new(logger, stats_recorder)
|
14
|
+
@state, @graph, @worklist = service.(project_root: project_root)
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_type_information(filepath, searched_position)
|
18
|
+
relevant_nodes = @graph
|
19
|
+
.vertices
|
20
|
+
.select {|n| n.location && n.location.uri.eql?(filepath) && n.location.position_range.include_position?(searched_position) }
|
21
|
+
.sort_by {|n| n.location.span }
|
22
|
+
|
23
|
+
pretty_print_type(@state.type_of(relevant_nodes.at(0)))
|
24
|
+
end
|
25
|
+
|
26
|
+
def locations_for_definition_under_position(file_path, file_content, position)
|
27
|
+
result = find_definition_under_position(file_content, position.line, position.character)
|
28
|
+
case result
|
29
|
+
when FindDefinitionUnderPosition::ConstantResult
|
30
|
+
constants = @state.solve_reference2(result.const_ref)
|
31
|
+
constants.map(&:location)
|
32
|
+
when FindDefinitionUnderPosition::MessageResult
|
33
|
+
caller_type = get_type_of_caller_from_message_send(file_path, result.position_range)
|
34
|
+
methods_definitions = get_methods_definitions_for_type(caller_type, result.name)
|
35
|
+
methods_definitions = @state.get_methods(result.name) if methods_definitions.empty?
|
36
|
+
methods_definitions.map(&:location).compact
|
37
|
+
else
|
38
|
+
[]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def get_type_of_caller_from_message_send(file_path, position_range)
|
44
|
+
message_send = @worklist
|
45
|
+
.message_sends
|
46
|
+
.find {|ms| ms.location && ms.location.uri.eql?(file_path) && ms.location.position_range.include_position?(position_range.start) }
|
47
|
+
@state.type_of(message_send.send_obj)
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_methods_definitions_for_type(type, method_name)
|
51
|
+
case type
|
52
|
+
when NominalType
|
53
|
+
@state.get_instance_methods_from_class_name(type.name, method_name)
|
54
|
+
when ClassType
|
55
|
+
@state.get_class_methods_from_class_name(type.name, method_name)
|
56
|
+
when UnionType
|
57
|
+
type.types_set.flat_map {|t| get_methods_definitions_for_type(t, method_name) }
|
58
|
+
else
|
59
|
+
[]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
attr_reader :logger
|
65
|
+
|
66
|
+
def find_definition_under_position(content, line, character)
|
67
|
+
FindDefinitionUnderPosition.new(RubyParser.new).process_file(content, Position.new(line, character))
|
68
|
+
end
|
69
|
+
|
70
|
+
def pretty_print_type(type)
|
71
|
+
TypePrettyPrinter.new.(type)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orbacle
|
4
|
+
class FindDefinitionUnderPosition < Parser::AST::Processor
|
5
|
+
include AstUtils
|
6
|
+
|
7
|
+
ConstantResult = Struct.new(:const_ref)
|
8
|
+
MessageResult = Struct.new(:name, :position_range)
|
9
|
+
|
10
|
+
def initialize(parser)
|
11
|
+
@parser = parser
|
12
|
+
end
|
13
|
+
|
14
|
+
def process_file(file_content, searched_position)
|
15
|
+
ast = parser.parse(file_content)
|
16
|
+
|
17
|
+
@current_nesting = Nesting.empty
|
18
|
+
@searched_position = searched_position
|
19
|
+
|
20
|
+
process(ast)
|
21
|
+
|
22
|
+
@result
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :parser
|
26
|
+
|
27
|
+
def process(ast)
|
28
|
+
new_ast = super
|
29
|
+
raise unless ast.equal?(new_ast)
|
30
|
+
new_ast
|
31
|
+
end
|
32
|
+
|
33
|
+
def on_const(ast)
|
34
|
+
if build_position_range_from_ast(ast).include_position?(@searched_position)
|
35
|
+
@result = ConstantResult.new(ConstRef.from_ast(ast, @current_nesting))
|
36
|
+
end
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def on_class(ast)
|
41
|
+
klass_name_ast, _ = ast.children
|
42
|
+
klass_name_ref = ConstRef.from_ast(klass_name_ast, @current_nesting)
|
43
|
+
with_new_nesting(@current_nesting.increase_nesting_const(klass_name_ref)) do
|
44
|
+
super
|
45
|
+
end
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def on_module(ast)
|
50
|
+
module_name_ast, _ = ast.children
|
51
|
+
module_name_ref = ConstRef.from_ast(module_name_ast, @current_nesting)
|
52
|
+
with_new_nesting(@current_nesting.increase_nesting_const(module_name_ref)) do
|
53
|
+
super
|
54
|
+
end
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
|
58
|
+
def on_send(ast)
|
59
|
+
if ast.loc.selector && build_position_range_from_parser_range(ast.loc.selector).include_position?(@searched_position)
|
60
|
+
message_name = ast.children.fetch(1).to_s
|
61
|
+
selector_position_range = build_position_range_from_parser_range(ast.loc.selector)
|
62
|
+
@result = MessageResult.new(message_name, selector_position_range)
|
63
|
+
else
|
64
|
+
super
|
65
|
+
end
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def with_new_nesting(new_nesting)
|
70
|
+
previous_nesting = @current_nesting
|
71
|
+
@current_nesting = new_nesting
|
72
|
+
yield
|
73
|
+
@current_nesting = previous_nesting
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orbacle
|
4
|
+
class GenericType
|
5
|
+
def initialize(name, parameters)
|
6
|
+
@name = name
|
7
|
+
@parameters = parameters
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :name, :parameters
|
11
|
+
|
12
|
+
def ==(other)
|
13
|
+
self.class == other.class &&
|
14
|
+
self.name == other.name &&
|
15
|
+
self.parameters == other.parameters
|
16
|
+
end
|
17
|
+
|
18
|
+
def hash
|
19
|
+
[
|
20
|
+
self.class,
|
21
|
+
self.name,
|
22
|
+
self.parameters,
|
23
|
+
].hash ^ BIG_VALUE
|
24
|
+
end
|
25
|
+
alias eql? ==
|
26
|
+
|
27
|
+
def each_possible_type
|
28
|
+
yield self
|
29
|
+
end
|
30
|
+
|
31
|
+
def bottom?
|
32
|
+
false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,280 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orbacle
|
4
|
+
class GlobalTree
|
5
|
+
class ArgumentsTree < Struct.new(:args, :kwargs, :blockarg)
|
6
|
+
Regular = Struct.new(:name)
|
7
|
+
Optional = Struct.new(:name)
|
8
|
+
Splat = Struct.new(:name)
|
9
|
+
Nested = Struct.new(:args)
|
10
|
+
end
|
11
|
+
|
12
|
+
class Method
|
13
|
+
def initialize(id, place_of_definition_id, name, location, visibility, args)
|
14
|
+
raise ArgumentError.new(visibility) if ![:public, :private, :protected].include?(visibility)
|
15
|
+
|
16
|
+
@id = id
|
17
|
+
@place_of_definition_id = place_of_definition_id
|
18
|
+
@name = name
|
19
|
+
@location = location
|
20
|
+
@visibility = visibility
|
21
|
+
@args = args
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :id, :name, :location, :args, :place_of_definition_id
|
25
|
+
attr_accessor :visibility
|
26
|
+
end
|
27
|
+
|
28
|
+
class Lambda
|
29
|
+
def initialize(id, args)
|
30
|
+
@id = id
|
31
|
+
@args = args
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :id, :args
|
35
|
+
end
|
36
|
+
|
37
|
+
class Klass
|
38
|
+
def initialize(id, parent_ref, eigenclass_id = nil)
|
39
|
+
@id = id
|
40
|
+
@parent_ref = parent_ref
|
41
|
+
@eigenclass_id = eigenclass_id
|
42
|
+
end
|
43
|
+
|
44
|
+
attr_reader :id, :parent_ref, :eigenclass_id
|
45
|
+
attr_writer :eigenclass_id
|
46
|
+
|
47
|
+
def ==(other)
|
48
|
+
@id == other.id &&
|
49
|
+
@parent_ref == other.parent_ref &&
|
50
|
+
@eigenclass_id == other.eigenclass_id
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Mod
|
55
|
+
def initialize(id, eigenclass_id = nil)
|
56
|
+
@id = id
|
57
|
+
@eigenclass_id = eigenclass_id
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_reader :id, :eigenclass_id
|
61
|
+
attr_writer :eigenclass_id
|
62
|
+
|
63
|
+
def ==(other)
|
64
|
+
@id == other.id &&
|
65
|
+
@eigenclass_id == other.eigenclass_id
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class Constant
|
70
|
+
def initialize(name, scope, location, definition_id = nil)
|
71
|
+
@name = name
|
72
|
+
@scope = scope
|
73
|
+
@location = location
|
74
|
+
@definition_id = definition_id
|
75
|
+
end
|
76
|
+
|
77
|
+
attr_reader :name, :scope, :location, :definition_id
|
78
|
+
|
79
|
+
def ==(other)
|
80
|
+
@name == other.name &&
|
81
|
+
@scope == other.scope &&
|
82
|
+
@location == other.location &&
|
83
|
+
@definition_id == other.definition_id
|
84
|
+
end
|
85
|
+
|
86
|
+
def full_name
|
87
|
+
[*scope.elems, @name].join("::")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def initialize(id_generator)
|
92
|
+
@id_generator = id_generator
|
93
|
+
@constants = ConstantsTree.new
|
94
|
+
@classes_by_id = {}
|
95
|
+
@modules_by_id = {}
|
96
|
+
@methods_by_class_id = Hash.new {|h,k| h[k] = Hash.new {|h2, k2| h2[k2] = [] } }
|
97
|
+
@methods_by_id = {}
|
98
|
+
@lambdas_by_id = {}
|
99
|
+
@type_mapping = Hash.new(BottomType.new)
|
100
|
+
end
|
101
|
+
|
102
|
+
### Methods
|
103
|
+
|
104
|
+
def add_method(id, place_of_definition_id, name, location, visibility, args)
|
105
|
+
metod = Method.new(id, place_of_definition_id, name, location, visibility, args)
|
106
|
+
@methods_by_class_id[metod.place_of_definition_id][metod.name] << metod
|
107
|
+
@methods_by_id[metod.id] = metod
|
108
|
+
return metod
|
109
|
+
end
|
110
|
+
|
111
|
+
def find_instance_method_from_class_name(class_name, method_name)
|
112
|
+
get_instance_methods_from_class_name(class_name, method_name).first
|
113
|
+
end
|
114
|
+
|
115
|
+
def find_instance_method_from_class_id(class_id, method_name)
|
116
|
+
get_instance_methods_from_class_id(class_id, method_name).first
|
117
|
+
end
|
118
|
+
|
119
|
+
def get_instance_methods_from_class_id(class_id, method_name)
|
120
|
+
@methods_by_class_id[class_id][method_name]
|
121
|
+
end
|
122
|
+
|
123
|
+
def get_instance_methods_from_class_name(class_name, method_name)
|
124
|
+
klass = find_class_by_name(class_name)
|
125
|
+
return [] if klass.nil?
|
126
|
+
get_instance_methods_from_class_id(klass.id, method_name)
|
127
|
+
end
|
128
|
+
|
129
|
+
def get_class_methods_from_class_name(class_name, method_name)
|
130
|
+
klass = find_class_by_name(class_name)
|
131
|
+
return [] if klass.nil?
|
132
|
+
eigenclass = get_eigenclass_of_definition(klass.id)
|
133
|
+
get_instance_methods_from_class_id(eigenclass.id, method_name)
|
134
|
+
end
|
135
|
+
|
136
|
+
def find_class_method_from_class_name(class_name, method_name)
|
137
|
+
get_class_methods_from_class_name(class_name, method_name).first
|
138
|
+
end
|
139
|
+
|
140
|
+
def get_methods(method_name)
|
141
|
+
@methods_by_id.values.select do |m|
|
142
|
+
m.name.eql?(method_name)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def find_super_method(method_id)
|
147
|
+
analyzed_method = @methods_by_id.fetch(method_id)
|
148
|
+
klass_of_this_method = get_class(analyzed_method.place_of_definition_id)
|
149
|
+
return nil if klass_of_this_method.nil? || klass_of_this_method.parent_ref.nil?
|
150
|
+
parent_klass = solve_reference(klass_of_this_method.parent_ref)
|
151
|
+
return nil if parent_klass.nil?
|
152
|
+
find_instance_method_from_class_name(parent_klass.full_name, analyzed_method.name)
|
153
|
+
end
|
154
|
+
|
155
|
+
def change_method_visibility(klass_id, name, new_visibility)
|
156
|
+
@methods_by_class_id[klass_id][name].each do |m|
|
157
|
+
m.visibility = new_visibility
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
### Definitions
|
162
|
+
|
163
|
+
def add_klass(parent_ref)
|
164
|
+
klass = Klass.new(id_generator.call, parent_ref)
|
165
|
+
@classes_by_id[klass.id] = klass
|
166
|
+
klass
|
167
|
+
end
|
168
|
+
|
169
|
+
def add_mod
|
170
|
+
mod = Mod.new(id_generator.call)
|
171
|
+
@modules_by_id[mod.id] = mod
|
172
|
+
mod
|
173
|
+
end
|
174
|
+
|
175
|
+
def get_class(class_id)
|
176
|
+
@classes_by_id[class_id]
|
177
|
+
end
|
178
|
+
|
179
|
+
def get_module(module_id)
|
180
|
+
@modules_by_id[module_id]
|
181
|
+
end
|
182
|
+
|
183
|
+
def get_definition(definition_id)
|
184
|
+
get_class(definition_id) || get_module(definition_id)
|
185
|
+
end
|
186
|
+
|
187
|
+
def get_eigenclass_of_definition(definition_id)
|
188
|
+
definition = get_definition(definition_id)
|
189
|
+
if definition.eigenclass_id
|
190
|
+
get_class(definition.eigenclass_id)
|
191
|
+
else
|
192
|
+
eigenclass = add_klass(nil)
|
193
|
+
definition.eigenclass_id = eigenclass.id
|
194
|
+
eigenclass
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
### Constants
|
199
|
+
|
200
|
+
def add_constant(constant)
|
201
|
+
@constants.add_element(constant.scope, constant.name, constant)
|
202
|
+
return constant
|
203
|
+
end
|
204
|
+
|
205
|
+
def solve_reference(const_ref)
|
206
|
+
@constants.find_by_const_ref(const_ref)
|
207
|
+
end
|
208
|
+
|
209
|
+
def solve_reference2(const_ref)
|
210
|
+
@constants.select_by_const_ref(const_ref)
|
211
|
+
end
|
212
|
+
|
213
|
+
### Lambdas
|
214
|
+
|
215
|
+
def add_lambda(args)
|
216
|
+
lamba = Lambda.new(id_generator.call, args)
|
217
|
+
@lambdas_by_id[lamba.id] = lamba
|
218
|
+
lamba
|
219
|
+
end
|
220
|
+
|
221
|
+
def get_lambda(lambda_id)
|
222
|
+
@lambdas_by_id[lambda_id]
|
223
|
+
end
|
224
|
+
|
225
|
+
### Other
|
226
|
+
|
227
|
+
def get_parent_of(class_name)
|
228
|
+
return nil if class_name.eql?("Object")
|
229
|
+
|
230
|
+
const = find_constant_by_name(class_name)
|
231
|
+
return "Object" if const.nil?
|
232
|
+
|
233
|
+
klass = get_class(const.definition_id)
|
234
|
+
return "Object" if klass.nil?
|
235
|
+
|
236
|
+
return "Object" if klass.parent_ref.nil?
|
237
|
+
parent_const = solve_reference(klass.parent_ref)
|
238
|
+
if parent_const
|
239
|
+
parent_const.full_name
|
240
|
+
else
|
241
|
+
klass.parent_ref.relative_name
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def find_class_by_name(full_name)
|
246
|
+
const = find_constant_by_name(full_name)
|
247
|
+
return nil if const.nil?
|
248
|
+
get_class(const.definition_id)
|
249
|
+
end
|
250
|
+
|
251
|
+
def find_module_by_name(full_name)
|
252
|
+
const = find_constant_by_name(full_name)
|
253
|
+
return nil if const.nil?
|
254
|
+
get_module(const.definition_id)
|
255
|
+
end
|
256
|
+
|
257
|
+
def find_constant_by_name(full_name)
|
258
|
+
@constants.find_by_const_name(ConstName.from_string(full_name))
|
259
|
+
end
|
260
|
+
|
261
|
+
def find_constant_for_definition(definition_id)
|
262
|
+
@constants.find do |constant|
|
263
|
+
constant.definition_id == definition_id
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
### Types
|
268
|
+
|
269
|
+
def type_of(node)
|
270
|
+
@type_mapping[node]
|
271
|
+
end
|
272
|
+
|
273
|
+
def set_type_of(node, new_type)
|
274
|
+
@type_mapping[node] = new_type
|
275
|
+
end
|
276
|
+
|
277
|
+
private
|
278
|
+
attr_reader :id_generator
|
279
|
+
end
|
280
|
+
end
|