5 src/builtins/guts.pir - subs that are part of the internals, not for users
11 =item !EXPORT(symbols, from :named('from') [, to :named('to')] )
13 Export symbols in namespace C<from> to the namespace given by C<to>.
14 If C<to> isn't given, then exports into the HLL global namespace.
15 This function differs somewhat from Parrot's C<Exporter> PMC in that
16 it understands how to properly merge C<MultiSub> PMCs.
23 .param pmc from :named('from')
24 .param pmc to :named('to') :optional
25 .param int has_to :opt_flag
27 if has_to goto have_to
28 to = get_hll_namespace
32 list = split ' ', symbols
34 unless list goto list_end
39 $I0 = isa value, 'MultiSub'
40 unless $I0 goto store_value
42 if null $P0 goto store_value
43 $I0 = isa $P0, 'MultiSub'
44 unless $I0 goto err_type_conflict
46 splice $P0, value, $I0, 0
55 $S0 = concat "Unable to add Multisub '", symbol
56 $S0 .= "' to existing value"
61 =item !OUTER(name [,'max'=>max])
63 Helper function to obtain the lexical C<name> from the
64 caller's outer scope. (Note that it never finds a lexical
65 in the caller's lexpad -- use C<find_lex> for that.) The
66 C<max> parameter specifies the maximum outer to search --
67 the default value of 1 will search the caller's immediate
68 outer scope and no farther. If the requested lexical is
69 not found, C<!OUTER> returns null.
75 .param int max :named('max') :optional
76 .param int has_max :opt_flag
78 if has_max goto have_max
85 ## the depth we use here is one more than the minimum,
86 ## because we want min/max to be relative to the caller's
87 ## context, not !OUTER itself.
90 .local pmc lexpad, value
94 unless max >= min goto done
96 lexpad = $P0['outer', depth]
97 unless lexpad goto next
99 unless null value goto done
113 Helper function for implementing the VAR and .VAR macros.
119 $I0 = isa variable, 'Perl6Scalar'
120 unless $I0 goto nothing
121 $P0 = new 'MutableVAR', variable
130 Checks that the value and the assignee are type-compatible and does the
139 $I0 = type.'ACCEPTS'(value)
144 =item !TYPECHECKPARAM
146 Checks the type of a parameter.
150 .sub '!TYPECHECKPARAM'
154 $P0 = $P0['lexpad';1]
155 if null $P0 goto no_match_to_copy
160 $I0 = type.ACCEPTS(value)
162 'die'('Parameter type check failed')
167 =item !SAMETYPE_EXACT
169 Takes two types and returns true if they match exactly (not accounting for any
170 subtyping relations, etc).
174 .sub '!SAMETYPE_EXACT'
178 # If they have equal address, obviously the same.
179 .local pmc t1meta, t2meta
182 eq_addr t1meta, t2meta, same
184 # If they are junctions, compare inside them recursively.
185 $I0 = isa t1, 'Junction'
186 unless $I0 goto not_junc
187 $I1 = isa t2, 'Junction'
188 unless $I0 == $I1 goto not_junc
196 if i >= max goto junc_loop_end
199 $I0 = '!SAMETYPE_EXACT'($P0, $P1)
200 unless $I0 goto not_same
213 =item !keyword_class(name)
215 Internal helper method to create a class.
219 .sub '!keyword_class'
221 .local pmc class, resolve_list, methods, iter
224 class = newclass name
226 # Set resolve list to include all methods of the class.
227 methods = inspect class, 'methods'
228 iter = new 'Iterator', methods
229 resolve_list = new 'ResizableStringArray'
231 unless iter goto resolve_loop_end
233 push resolve_list, $P0
236 class.resolve_method(resolve_list)
241 =item !keyword_role(name)
243 Internal helper method to create a role.
249 .local pmc info, role
251 # Need to make sure it ends up attached to the right
255 $P0 = new 'ResizablePMCArray'
257 info['namespace'] = $P0
260 role = new 'Role', info
262 # Stash in namespace.
263 $P0 = new 'ResizableStringArray'
264 set_hll_global $P0, name, role
269 =item !keyword_grammar(name)
271 Internal helper method to create a grammar.
275 .sub '!keyword_grammar'
277 .local pmc info, grammar
279 # Need to make sure it ends up attached to the right
283 $P0 = new 'ResizablePMCArray'
285 info['namespace'] = $P0
287 # Create grammar class..
288 grammar = new 'Class', info
293 =item !keyword_enum(name)
295 Internal helper method to create an enum class.
303 # Create an anonymous class and attach the role.
305 $P0 = get_class 'Any'
307 "!keyword_does"(class, role)
311 =item !keyword_does(class, role)
313 Internal helper method to implement the functionality of the does keyword.
321 # Get Parrot to compose the role for us (handles the methods).
324 # Parrot doesn't handle composing the attributes; we do that here for now.
325 .local pmc role_attrs, class_attrs, ra_iter
326 .local string cur_attr
327 role_attrs = inspect role, "attributes"
328 class_attrs = inspect class, "attributes"
329 ra_iter = iter role_attrs
331 unless ra_iter goto ra_iter_loop_end
332 cur_attr = shift ra_iter
334 # Check that this attribute doesn't conflict with one already in the class.
335 $I0 = exists class_attrs[cur_attr]
336 unless $I0 goto no_conflict
338 # We have a name conflict. Let's compare the types. If they match, then we
339 # can merge the attributes.
340 .local pmc class_attr_type, role_attr_type
341 $P0 = class_attrs[cur_attr]
342 if null $P0 goto conflict
343 class_attr_type = $P0['type']
344 if null class_attr_type goto conflict
345 $P0 = role_attrs[cur_attr]
346 if null $P0 goto conflict
347 role_attr_type = $P0['type']
348 if null role_attr_type goto conflict
349 $I0 = '!SAMETYPE_EXACT'(class_attr_type, role_attr_type)
353 $S0 = "Conflict of attribute '"
354 $S0 = concat cur_attr
355 $S0 = concat "' in composition of role '"
362 addattribute class, cur_attr
368 =item !keyword_has(class, attr_name, type)
370 Adds an attribute with the given name to the class or role.
376 .param string attr_name
378 class.'add_attribute'(attr_name, type)
382 =item !anon_enum(value_list)
384 Constructs a Mapping, based upon the values list.
391 # For now, we assume integer type, unless we have a first pair that says
397 # Iterate over values and make mapping.
398 .local pmc result, values_it, cur_item
399 result = new 'Mapping'
400 values_it = iter values
402 unless values_it goto values_loop_end
403 cur_item = shift values_it
404 $I0 = isa cur_item, 'Perl6Pair'
408 $P0 = 'postfix:++'(cur_val)
409 result[cur_item] = $P0
413 cur_val = cur_item.'value'()
414 $P0 = cur_item.'key'()
415 result[$P0] = cur_val
416 cur_val = clone cur_val
417 'postfix:++'(cur_val)
433 # vim: expandtab shiftwidth=4 ft=pir: