36
17
load_bytecode 'PCT.pbc'
38
19
p6meta = get_hll_global ['Perl6Object'], '$!P6META'
39
p6meta.'new_class'('Signature', 'parent'=>'Any', 'attr'=>'@!params $!default_type')
20
p6meta.'new_class'('Signature', 'parent'=>'Any', 'attr'=>'$!ll_sig')
46
=item !add_param( $varname, *%attr )
48
Add the attributes given by C<%attr> as the entry for C<$var> in
53
.sub '!add_param' :method
55
.param pmc attr :slurpy :named
57
attr['name'] = varname
59
# If no multi_invocant value, set it to 1 (meaning it is one).
60
$I0 = exists attr['multi_invocant']
62
attr['multi_invocant'] = 1
65
# Work out any role type that the sigil implies. (Skip for slurpy, though.)
67
if $I0 goto sigil_done
70
sigil = substr varname, 0, 1
71
if sigil == '$' goto sigil_done
72
if sigil == '@' goto sigil_array
73
if sigil == '%' goto sigil_hash
74
if sigil == ':' goto sigil_done
77
role_type = get_hll_global 'Positional'
80
role_type = get_hll_global 'Associative'
83
role_type = get_hll_global 'Callable'
87
# Get constraints list, which may have class and role types as well as
88
# subset types. If we have no unique role or class type, they all become
89
# constraints; otherwise, we find the unique type. Finally, we turn the
90
# list of constraints into a junction.
91
.local pmc cur_list, cur_list_iter, constraints, type, test_item
92
constraints = root_new ['parrot';'ResizablePMCArray']
94
cur_list = attr["type"]
95
if null cur_list goto cur_list_loop_end
97
cur_list = cur_list.'eigenstates'()
98
cur_list_iter = iter cur_list
100
unless cur_list_iter goto cur_list_loop_end
101
test_item = shift cur_list_iter
102
$I0 = isa test_item, "Role"
104
$P0 = getprop "subtype_realtype", test_item
105
if null $P0 goto not_refinement
106
unless null type goto all_constraints
108
push constraints, test_item
111
$I0 = isa test_item, "P6protoobject"
113
push constraints, test_item
116
unless null type goto all_constraints
121
constraints = cur_list
124
# Set parametric type, if any.
125
unless null type goto have_type
127
if $I0 goto object_type
128
unless null role_type goto simple_role_type
129
type = getattribute self, '$!default_type'
130
unless null type goto done_role_type
132
type = get_hll_global 'Object'
138
if null role_type goto done_role_type
139
type = role_type.'!select'(type)
141
attr["nom_type"] = type
142
$I0 = elements constraints
143
if $I0 == 0 goto no_constraints
144
$P0 = 'infix:&'(type, constraints :flat)
146
constraints = 'infix:&'(constraints :flat)
152
attr["cons_type"] = constraints
154
# Add to parameters list.
156
params = self.'params'()
161
=item !set_default_param_type
163
Sets the default parameter type if none is supplied (since it differs for
164
blocks and routines).
168
.sub '!set_default_param_type' :method
170
setattribute self, '$!default_type', type
174
=item !add_implicit_self
176
Ensures that if there is no explicit invocant, we add one.
180
.sub '!add_implicit_self' :method
181
.param pmc type :optional
182
unless null type goto have_type
183
type = get_hll_global 'Object'
187
params = self.'params'()
188
$I0 = elements params
189
if $I0 == 0 goto add_implicit_self
191
$I0 = $P0['invocant']
192
if $I0 != 1 goto add_implicit_self
196
$P0 = root_new ['parrot';'Hash']
199
$P0['multi_invocant'] = 1
200
$P0['nom_type'] = type
205
=item !make_parameters_rw
207
Makes all parameters have readtype rw (used to implement e.g. <->).
211
.sub '!make_parameters_rw' :method
212
.local pmc params, it, param
213
params = self.'params'()
216
unless it goto it_loop_end
218
$P0 = param['readtype']
219
unless null $P0 goto it_loop
220
param['readtype'] = 'rw'
228
Get the array of parameter describing hashes.
30
Returns a C<List> of C<Parameter> descriptors.
232
34
.sub 'params' :method
233
$P0 = getattribute self, "@!params"
234
unless null $P0 goto done
235
$P0 = root_new ['parrot';'ResizablePMCArray']
236
setattribute self, "@!params", $P0
243
Gets a perl representation of the signature.
253
.local pmc params, param_iter, cur_param
254
.local int last_was_multi_inv, want_colon, first
255
last_was_multi_inv = 1
258
params = self.'params'()
259
param_iter = iter params
261
unless param_iter goto param_iter_loop_end
262
cur_param = shift param_iter
264
# If it's the first time, no separator.
265
if first goto first_time
266
if want_colon goto emit_colon
267
$P0 = cur_param["multi_invocant"]
268
if $P0 goto emit_comma
269
unless last_was_multi_inv goto emit_comma
271
last_was_multi_inv = 0
283
# First any nominal type.
284
$P0 = cur_param["nom_type"]
285
if null $P0 goto any_type
286
$I0 = isa $P0, 'Role'
287
unless $I0 goto type_as_is
288
$S0 = cur_param["name"]
289
$S0 = substr $S0, 0, 1
290
if $S0 == '$' goto type_as_is
297
$S1 = substr $S1, $I0, $I1
302
if $P0 == 'Positional' goto no_type
303
if $P0 == 'Associative' goto no_type
304
if $P0 == 'Callable' goto no_type
313
# If it's slurpy, the *.
314
$P0 = cur_param["slurpy"]
315
if null $P0 goto slurpy_done
316
unless $P0 goto slurpy_done
321
# If it's named, the :.
322
$S0 = cur_param['named']
323
if null $S0 goto named_done
324
if $S0 == '' goto named_done
329
$P0 = cur_param["name"]
332
# If it's optional, the ?.
333
$P0 = cur_param["optional"]
334
if null $P0 goto optional_done
335
unless $P0 goto optional_done
339
# Now any constraints.
340
$P0 = cur_param["cons_type"]
341
if null $P0 goto constraints_done
342
unless $P0 goto constraints_done
351
# If we just had an invocant, need the colon.
352
unless want_colon goto no_trailing_colon
361
=item !SIGNATURE_BIND
363
Analyze the signature of the caller, (re)binding the caller's
364
lexicals as needed and performing type checks.
369
.sub '!SIGNATURE_BIND'
370
.local pmc callersub, callerlex, callersig
372
callersub = $P0['sub';1]
373
callerlex = $P0['lexpad';1]
374
getprop callersig, '$!signature', callersub
375
if null callersig goto end
377
params = getattribute callersig, "@!params"
378
if null params goto end
37
result = new 'ResizablePMCArray'
39
# Grab low level signature we're wrapping.
41
signature = getattribute self, '$!ll_sig'
42
signature = descalarref signature
44
# And Parameter proto.
46
parameter = get_hll_global 'Parameter'
48
# Loop over parameters.
379
49
.local int cur_param, count
380
count = elements params
50
count = get_signature_size signature
384
54
unless cur_param < count goto param_done
386
param = params[cur_param]
387
.local string name, sigil
389
if name == 'self' goto param_loop
390
sigil = substr name, 0, 1
391
.local pmc type, optional, orig, var
393
optional = param['optional']
394
orig = callerlex[name]
395
if sigil == '@' goto param_array
396
if sigil == '%' goto param_hash
397
var = '!CALLMETHOD'('Scalar', orig)
398
## typecheck the argument unless it's undef (for optional parameter)
399
if null optional goto not_optional
401
unless $I0 goto param_val_done
403
if null type goto param_val_done
405
$P0 = type.'ACCEPTS'(var)
406
unless $P0 goto err_param_type
409
$P0 = type.'ACCEPTS'(orig)
410
unless $P0 goto err_param_type_non_scalar
411
var = descalarref orig
412
var = '!CALLMETHOD'('Array', var)
415
$P0 = type.'ACCEPTS'(orig)
416
unless $P0 goto err_param_type_non_scalar
417
var = descalarref orig
418
var = '!CALLMETHOD'('Hash', var)
421
## handle readonly/copy traits
422
$S0 = param['readtype']
423
if $S0 == 'rw' goto param_readtype_done
424
if $S0 == 'copy' goto param_readtype_copy
425
ne_addr orig, var, param_readtype_var
426
var = root_new ['parrot';'ObjectRef'], var
428
$P0 = get_hll_global ['Bool'], 'True'
429
setprop var, 'readonly', $P0
430
goto param_readtype_done
432
if sigil == '@' goto param_readtype_copy_array
433
if sigil == '%' goto param_readtype_copy_hash
435
goto param_readtype_done
436
param_readtype_copy_array:
437
$P0 = new ['Perl6Array']
440
goto param_readtype_done
441
param_readtype_copy_hash:
442
$P0 = new ['Perl6Hash']
446
## set any type properties
447
setprop var, 'type', type
448
## place the updated variable back into lex
449
callerlex[name] = var
56
# Get all curent parameter info.
57
.local pmc nom_type, cons_type, names, type_captures, default, sub_sig
58
.local int flags, optional, invocant, multi_invocant, slurpy, rw, ref, copy, named
60
get_signature_elem signature, cur_param, name, flags, nom_type, cons_type, names, type_captures, default, sub_sig
61
optional = flags & SIG_ELEM_IS_OPTIONAL
62
invocant = flags & SIG_ELEM_INVOCANT
63
multi_invocant = flags & SIG_ELEM_MULTI_INVOCANT
64
slurpy = flags & SIG_ELEM_SLURPY
65
rw = flags & SIG_ELEM_IS_RW
66
ref = flags & SIG_ELEM_IS_REF
67
copy = flags & SIG_ELEM_IS_COPY
69
# Make sure constraints is non-null.
70
unless null cons_type goto have_cons
71
cons_type = get_hll_global ['Bool'], 'True'
74
cons_type = 'infix:&'(cons_type :flat)
79
if null names goto no_names
81
names = 'list'(names :flat)
85
$I0 = flags & SIG_ELEM_SLURPY_NAMED
86
unless $I0 goto names_done
91
if null type_captures goto no_type_captures
92
type_captures = 'list'(type_captures :flat)
93
goto type_captures_done
95
type_captures = 'list'()
98
# Make sure default and sub-signature are non-null.
99
unless null default goto default_done
102
unless null sub_sig goto sub_sig_done
106
# Create parameter instance.
107
$P0 = parameter.'new'('name'=>name, 'type'=>nom_type, 'constraints'=>cons_type, 'optional'=>optional, 'slurpy'=>slurpy, 'invocant'=>invocant, 'multi_invocant'=>multi_invocant, 'rw'=>rw, 'ref'=>ref, 'copy'=>copy, 'named'=>named, 'named_names'=>names, 'type_captures'=>type_captures, 'default'=>default, 'signature'=>sub_sig)
455
# In theory we're done now, however we may be doing only a bindability check
456
# for the purposes of MMD. In that case, throw a resumable exception here.
457
$P0 = getprop '$!bind_check_only', callersub
458
if null $P0 goto done
459
die '__BIND_SUCCESSFUL__' # XXX A little fragile...think of something better
463
err_param_type_non_scalar:
466
# Is it a junctional parameter?
467
$I0 = isa var, 'Junction'
468
unless $I0 goto not_junctional
469
$P0 = '!DISPATCH_JUNCTION_SINGLE'(callersub, callerlex, callersig)
472
.local string errmsg, callername
473
errmsg = '!make_type_fail_message'('Parameter', orig, type)
474
callername = callersub
475
if callername goto have_callername
476
callername = '<anon>'
478
'die'(errmsg, ' for ', name, ' in call to ', callername)
113
.tailcall 'list'(result :flat)
487
120
# Local Variables:
489
122
# fill-column: 100