Skip to content
← Back

src/semantic/function_caller.ghul

1
namespace Semantic is
2
use IO.Std
3
4
use Logging
5
6
use Types.Type
7
8
use IR.Values
9
10
@suppress("field-definite-assignment")
11
class FUNCTION_CALLER(
12
_symbol_table: SYMBOL_TABLE,
13
_value_boxer: IR.VALUE_BOXER
14
) is
15
// public so container can initialize it to break a
16
// circular dependency:
17
loader: SYMBOL_LOADER public
18
19
super()
20
21
call_innate_function(
22
function: Symbols.INNATE_FUNCTION,
23
arguments: Collections.List[Value],
24
argument_types: Collections.List[Type],
25
type: Type?
26
) -> Value =>
27
Call.INNATE(
28
function,
29
null,
30
arguments,
31
type
32
)
33
34
call_innate_function(
35
function: Symbols.INNATE_METHOD,
36
from: Value?,
37
arguments: Collections.List[Value],
38
argument_types: Collections.List[Type],
39
type: Type?
40
) -> Value =>
41
Call.INNATE(
42
function,
43
from,
44
arguments,
45
type
46
)
47
48
call_global_function(
49
function: Symbols.Function,
50
arguments: Collections.List[Value],
51
argument_types: Collections.List[Type],
52
type: Type?
53
) -> Value =>
54
Call.GLOBAL(
55
function,
56
_value_boxer.box_arguments(arguments, function.arguments),
57
type
58
)
59
60
call_instance_method(
61
location: Source.LOCATION,
62
from: Value? mut,
63
function: Symbols.Function,
64
arguments: Collections.List[Value],
65
argument_types: Collections.List[Type],
66
type: Type?
67
) -> Value is
68
if !from? then
69
from = loader.load_self(location)
70
fi
71
72
if from.type!.is_type_variable then
73
from = CONSTRAINED(from)
74
fi
75
76
return
77
Call.INSTANCE(
78
_value_boxer.box_if_value(from),
79
function,
80
_value_boxer.box_arguments(arguments, function.arguments),
81
type
82
)
83
si
84
85
call_struct_method(
86
location: Source.LOCATION,
87
from: Value? mut,
88
function: Symbols.Function,
89
arguments: Collections.List[Value],
90
argument_types: Collections.List[Type],
91
type: Type?
92
) -> Value is
93
if !from? then
94
from = loader.load_self(location)
95
else
96
from = ADDRESS(from)
97
fi
98
99
return
100
Call.STRUCT(
101
from,
102
function,
103
_value_boxer.box_arguments(arguments, function.arguments),
104
type
105
)
106
si
107
108
call_abstract_method(
109
location: Source.LOCATION,
110
from: Value? mut,
111
function: Symbols.Function,
112
arguments: Collections.List[Value],
113
argument_types: Collections.List[Type],
114
type: Type?
115
) -> Value is
116
// A super call names the base implementation directly, and
117
// an abstract member has none: the emitted non-virtual call
118
// points at a row with no body.
119
if isa Load.SUPER(from) /\ !function.throws_unimplemented then
120
IoC.CONTAINER.instance.logger.error(
121
location,
122
"cannot call abstract method {function} through super",
123
function.location,
124
"declared with no body here")
125
fi
126
127
if !from? then
128
from = loader.load_self(location)
129
elif from.is_value_type then
130
// Don't believe this is possible in practice except
131
// for calls to IDisposable.Dispose() generated by the
132
// compiler for `let use` statements.
133
from = CONSTRAINED(from)
134
elif let variable = from.type?.type_variable_side then
135
// The receiver is a type variable narrowed to the trait
136
// declaring the member. The load puts a `!!N` on the
137
// stack, which an interface call cannot dispatch on
138
// directly, so constrain it to the variable.
139
from = CONSTRAINED(from, variable)
140
fi
141
142
return
143
Call.INSTANCE(
144
from,
145
function,
146
_value_boxer.box_arguments(arguments, function.arguments),
147
type
148
)
149
si
150
151
call_static_method(
152
function: Symbols.Function,
153
arguments: Collections.List[Value],
154
argument_types: Collections.List[Type],
155
type: Type?
156
) -> Value =>
157
Call.STATIC(
158
function,
159
_value_boxer.box_arguments(arguments, function.arguments),
160
type,
161
null
162
)
163
164
// A static virtual/abstract interface member, reached through
165
// a bound type parameter - .NET's generic-math mechanism - or
166
// at a concrete instantiation of the declaring interface.
167
// `receiver` is the type dispatched through, needed to emit the
168
// `constrained.` prefix the CLR requires to dispatch such a
169
// call.
170
call_static_interface_method(
171
function: Symbols.Function,
172
receiver: Type,
173
arguments: Collections.List[Value],
174
argument_types: Collections.List[Type],
175
type: Type?
176
) -> Value =>
177
Call.STATIC(
178
function,
179
_value_boxer.box_arguments(arguments, function.arguments),
180
type,
181
receiver
182
)
183
184
// A function-typed value invoked as a callee has no Function
185
// symbol, so the closure path in COMPILE_CALLS applies the
186
// same slot-boundary coercions against the function type's
187
// formal types.
188
box_arguments(
189
arguments: Collections.List[Value],
190
formal_types: Collections.List[Type]
191
) -> Collections.List[Value] =>
192
_value_boxer.box_arguments(arguments, formal_types)
193
194
call_constructor(
195
function: Symbols.Function,
196
arguments: Collections.List[Value],
197
type: Type
198
) -> Value =>
199
NEW(
200
type,
201
function,
202
_value_boxer.box_arguments(arguments, function.arguments)
203
)
204
si
205
si