/
fix_missing_types.cr
91 lines (75 loc) · 1.86 KB
/
fix_missing_types.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
require "../semantic"
class Crystal::FixMissingTypes < Crystal::Visitor
@program : Program
@fixed : Set(UInt64)
def initialize(mod)
@program = mod
@fixed = Set(typeof(object_id)).new
end
def visit(node : Def)
node.hook_expansions.try &.each &.accept self
false
end
def visit(node : ClassDef)
node.hook_expansions.try &.each &.accept self
true
end
def visit(node : Include)
node.hook_expansions.try &.each &.accept self
false
end
def visit(node : Extend)
node.hook_expansions.try &.each &.accept self
false
end
def visit(node : Macro)
false
end
def visit(node : ProcLiteral)
node.def.body.accept self
unless node.def.type?
node.def.type = @program.no_return
end
false
end
def visit(node : ProcPointer)
node.call?.try &.accept self
false
end
def end_visit(node : ProcPointer)
if !node.type? && node.call?
arg_types = node.call.args.map &.type
arg_types.push @program.no_return
node.type = node.call.type = @program.proc_of(arg_types)
end
end
def visit(node : ExpandableNode)
node.expanded.try &.accept self
false
end
def end_visit(node : Call)
if expanded = node.expanded
expanded.accept self
end
# If the block doesn't have a type, it's a no-return.
block = node.block
if block && !block.type?
block.type = @program.no_return
end
node.target_defs.try &.each do |target_def|
unless @fixed.includes?(target_def.object_id)
@fixed.add(target_def.object_id)
target_def.type = @program.no_return unless target_def.type?
target_def.accept_children self
end
end
end
def visit(node : TypeOf)
node.expressions.each &.accept self
node.type = @program.no_return.metaclass unless node.type?
false
end
def visit(node : ASTNode)
true
end
end