# various NQP-related PAST hacks and experiments can go here
.namespace ['PAST';'Node']
.sub '' :anon :load :init
.local pmc p6meta, base
p6meta = new 'P6metaclass'
base = get_hll_global ['PAST'], 'Node'
p6meta.'new_class'('PAST::Want', 'parent'=>base)
p6meta.'new_class'('PAST::QAST', 'parent'=>base)
# add the nqp:: opcode map
.const 'Sub' nqpmap = 'nqpmap'
base.'map_add'('nqp', nqpmap)
.end
=head2 PAST::Want
A C<PAST::Want> node selects one of its children based on the
rtype (context) in which it's being evaluated. The first
child is the default PAST to be evaluated. The subsequent
children consist of (signature,past) pairs, the signature is
a string of rtypes, and the subsequent past node is the one
to be used if the caller's rtype matches any of the ones
listed in the signature.
Exactly one of the node's children will be selected. It's
okay for a single PAST node to appear within multiple children,
as only one of the children will be selected.
=cut
=item as_post(PAST::Want)
Select a single past child based on rtype.
=cut
.namespace ['PAST';'Compiler']
.sub 'as_post' :method :multi(_, ['PAST';'Want'])
.param pmc node
.param pmc options :slurpy :named
.local string rtype
rtype = options['rtype']
.local pmc it, cpast, cpost
it = node.'iterator'()
cpast = shift it
unless rtype goto child_done
child_loop:
unless it goto child_done
$S0 = shift it # get the signature
$P0 = shift it # get the past to use
$I0 = index $S0, rtype
if $I0 < 0 goto child_loop
cpast = $P0
child_done:
cpost = self.'as_post'(cpast, options :flat :named)
.return (cpost)
.end
=item lexotic(PAST::Op node)
Establish a lexotic label (continuation) that can be invoked
via a lexical lookup. The C<name> attribute gives the name of
the lexical to be used to hold the continuation. The result
of this node is any argument passed when invoking the continuation,
or the result of the last child node if the continuation isn't
invoked.
=cut
.sub 'lexotic' :method :multi(_, ['PAST';'Op'])
.param pmc node
.param pmc options :slurpy :named
.local pmc label1, label2
$P0 = get_hll_global ['POST'], 'Label'
label1 = $P0.'new'('name'=>'lexotic_')
label2 = $P0.'new'('name'=>'lexotic_')
.local string lexname
lexname = node.'name'()
lexname = self.'escape'(lexname)
.local pmc ops, handler, cpost
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
handler = self.'uniquereg'('P')
ops.'push_pirop'('root_new', handler, "['parrot';'Continuation']")
ops.'push_pirop'('set_label', handler, label1)
ops.'push_pirop'('.lex', lexname, handler)
.local pmc cpost
cpost = self.'stmts'(node, 'rtype'=>'P')
ops.'push'(cpost)
ops.'result'(cpost)
.local string result
ops.'push_pirop'('goto', label2)
ops.'push'(label1)
result = ops.'result'()
$S0 = concat '(', result
$S0 = concat $S0, ')'
ops.'push_pirop'('.get_results', $S0)
ops.'push'(label2)
.return (ops)
.end
=item hash(PAST::Op node)
Create a hash from the children. The type of hash constructed
is determined by the C<returns> attribute, which defaults to
C<Hash> if not set.
=cut
.sub 'hash' :method :multi(_, ['PAST';'Op'])
.param pmc node
.param pmc options :slurpy :named
.local pmc ops, posargs
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local pmc returns
returns = node.'returns'()
if returns goto have_returns
returns = box 'Hash'
have_returns:
.local pmc hashpost, it
hashpost = self.'as_vivipost'(returns, 'rtype'=>'P')
ops.'result'(hashpost)
ops.'push'(hashpost)
it = node.'iterator'()
iter_loop:
unless it goto iter_done
.local pmc kpast, kpost, vpast, vpost
kpast = shift it
kpost = self.'as_post'(kpast, 'rtype'=>'~')
vpast = shift it
vpost = self.'as_post'(vpast, 'rtype'=>'*')
$S0 = hashpost
$S0 = concat $S0, '['
$S1 = kpost
$S0 = concat $S0, $S1
$S0 = concat $S0, ']'
ops.'push'(vpost)
ops.'push'(kpost)
ops.'push_pirop'('set', $S0, vpost)
goto iter_loop
iter_done:
.return (ops)
.end
=item xor_nqp(PAST::Op node)
A short-circuiting exclusive-or operation. Essentially the
same as C<xor> in Parrot, but a named child of 'false' determines
the value to be returned if two children are true.
=cut
.sub 'xor_nqp' :method :multi(_,['PAST';'Op'])
.param pmc node
.param pmc options :slurpy :named
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
$S0 = self.'unique'('$P')
ops.'result'($S0)
.local pmc labelproto, endlabel, falselabel
labelproto = get_hll_global ['POST'], 'Label'
falselabel = labelproto.'new'('name'=>'xor_false')
endlabel = labelproto.'new'('name'=>'xor_end')
.local pmc childlist, fpast, fpost, apast, apost, iter
childlist = new ['ResizablePMCArray']
iter = node.'iterator'()
child_loop:
unless iter goto child_done
apast = shift iter
$P0 = apast.'named'()
if $P0 == 'false' goto child_false
push childlist, apast
goto child_loop
child_false:
fpast = apast
goto child_loop
child_done:
.local pmc i, t, u
i = self.'unique'('$I')
t = self.'unique'('$I')
u = self.'unique'('$I')
apast = shift childlist
apost = self.'as_post'(apast, 'rtype'=>'P')
ops.'push'(apost)
ops.'push_pirop'('set', ops, apost)
ops.'push_pirop'('istrue', t, apost)
middle_child:
.local pmc bpast, bpost
bpast = shift childlist
bpost = self.'as_post'(bpast, 'rtype'=>'P')
ops.'push'(bpost)
ops.'push_pirop'('istrue', u, bpost)
ops.'push_pirop'('and', i, t, u)
ops.'push_pirop'('if', i, falselabel)
unless childlist goto last_child
.local pmc truelabel
truelabel = labelproto.'new'('name'=>'xor_true')
ops.'push_pirop'('if', t, truelabel)
ops.'push_pirop'('set', ops, bpost)
ops.'push_pirop'('set', t, u)
ops.'push'(truelabel)
goto middle_child
last_child:
ops.'push_pirop'('if', t, endlabel)
ops.'push_pirop'('set', ops, bpost)
ops.'push_pirop'('goto', endlabel)
ops.'push'(falselabel)
unless null fpast goto false_node
ops.'push_pirop'('new', ops, '["Undef"]')
goto done
false_node:
fpost = self.'as_post'(fpast, 'rtype'=>'P')
ops.'push'(fpost)
ops.'push_pirop'('set', ops, fpost)
done:
ops.'push'(endlabel)
.return (ops)
.end
=item nqpdebug(PAST::Op node)
Generate debugging code using nqpdebskip and nqpevent. The first
child is evaluated as an integer flag, used to skip over the
evaluation and logging of the second child.
=cut
.sub 'nqpdebug' :method :multi(_, ['PAST';'Op'])
.param pmc node
.param pmc options :slurpy :named
.local pmc debskip
$P0 = get_hll_global ['POST'], 'Label'
debskip = $P0.'new'('name'=>'nqpdeb_')
.local pmc flagpost, strpost, ops
$P0 = node[0]
flagpost = self.'as_post'($P0, 'rtype'=>'i')
flagpost = self.'coerce'(flagpost, 'i')
$P1 = node[1]
strpost = self.'as_post'($P1, 'rtype'=>'s')
strpost = self.'coerce'(strpost, 's')
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
ops.'push'(flagpost)
ops.'push_pirop'('nqpdebskip', flagpost, debskip)
ops.'push'(strpost)
ops.'push_pirop'('nqpevent', strpost)
ops.'push'(debskip)
ops.'result'(flagpost)
.return (ops)
.end
=item as_post(PAST::QAST)
Shim that lets us embed QAST:: nodes inside of a PAST tree.
=cut
.sub 'as_post' :method :multi(_, ['PAST';'QAST'])
.param pmc node
.param pmc options :slurpy :named
.lex '$*PASTCOMPILER', self
$P0 = get_hll_global ['QAST'], 'Compiler'
$P1 = node[0]
$P2 = $P0.'as_post'($P1)
.return ($P2)
.end
=item map_add(mapid, [hash])
Add entries from any C<hash> arguments to the pseudo-opcode table
with identifier C<mapid>. Slurpy named arguments are also added to
the hash (after all hash arguments have been processed). The
resulting pseudo-opcode table hash for C<mapid> is returned.
The hash entries being added consist of pseudo-opcode (key, spec)
pairs describing the pseudo-opcode name and node type to be
constructed. If C<spec> is a plain string, it's assumed to be
a Parrot C<pirop> opcode name. (A future version may allow
strings of the form 'mapid::opcode' to reference an entry of
another map table.)
If C<spec> is a hash, it contains
attributes used to build a PAST node. For example, the following
pseudo-code would cause the 'ifelse' pseudo-op in the 'nqp'
mapping space to to translate to a PAST::Op node with 'pasttype'
set to 'if':
$x := hash( 'WHAT' => PAST::Op, 'pasttype'=>'if' );
PAST::Node.map_add('nqp', 'ifelse' => $x );
The 'WHAT' entry of such a hash defaults to PAST::Op if not specified.
=item map_node([args], 'map'=>mapid, 'op'=>opname, [options])
Create a node based on the mapping specification for C<opname>
from the pseudo-op mapping table given by C<mapid>. The
C<args> and C<options> are combined with the mapping table
entry to produce the node to be returned.
=cut
.namespace ['PAST';'Node']
.sub 'map_add' :method
.param string mapid
.param pmc args :slurpy
.param pmc opt_hash :slurpy :named
.local pmc maptables, maphash
maptables = get_global '%!maptables'
unless null maptables goto have_maptables
maptables = new ['Hash']
set_global '%!maptables', maptables
have_maptables:
maphash = maptables[mapid]
unless null maphash goto have_maphash
maphash = new ['Hash']
maptables[mapid] = maphash
have_maphash:
args_loop:
unless args goto args_done
.local pmc hash_it
$P0 = shift args
hash_it = iter $P0
args_merge_loop:
unless hash_it goto args_loop
$P0 = shift hash_it
$S1 = $P0.'key'()
$P1 = $P0.'value'()
maphash[$S1] = $P1
goto args_merge_loop
args_done:
hash_it = iter opt_hash
opts_loop:
unless hash_it goto opts_done
$P0 = shift hash_it
$S1 = $P0.'key'()
$P1 = $P0.'value'()
maphash[$S1] = $P1
goto opts_loop
opts_done:
.return (maphash)
.end
.namespace ['PAST';'Node']
.sub 'map_node' :method
.param pmc args :slurpy
.param string mapid :named('map')
.param string opcode :named('op')
.param pmc options :slurpy :named
.local pmc maphash, ophash, past
$P0 = get_global '%!maptables'
maphash = $P0[mapid]
if null maphash goto fail
ophash = maphash[opcode]
if null ophash goto fail
$I0 = isa ophash, ['Hash']
if $I0 goto have_ophash
# handle case where the opspec is a simple (pirop) string
$P0 = get_hll_global ['PAST'], 'Op'
past = $P0.'new'(args :flat, 'pirop'=>ophash, options :named :flat)
.return (past)
have_ophash:
# merge the ophash entries into options
.local pmc ophash_it, key, value
ophash_it = iter ophash
ophash_loop:
unless ophash_it goto ophash_done
$P0 = shift ophash_it
$S1 = $P0.'key'()
$P1 = $P0.'value'()
# don't overwrite an existing option
$I0 = exists options[$S1]
if $I0 goto ophash_loop
options[$S1] = $P1
goto ophash_loop
ophash_done:
# determine the 'what' value to use
.local pmc what
what = get_hll_global ['PAST'], 'Op'
$I0 = exists options['WHAT']
unless $I0 goto have_what
what = options['WHAT']
delete options['WHAT']
have_what:
past = what.'new'(args :flat, options :named :flat)
.return (past)
fail:
$P0 = new ['Undef']
.return ($P0)
.end
.sub 'nqpmap' :immediate :subid('nqpmap')
.local pmc maphash
maphash = new ['Hash']
# See also docs/nqp-opcode.txt before adding opcodes to this list.
# Opcodes marked (?) may be rejected at some point.
# Explicitly rejected opcodes. See also docs/nqp-opcode.txt.
# Use the pir:: form of these Parrot-specific operations.
# maphash['new'] # or use nqp::create
# maphash['does']
# maphash['isa'] # or use nqp::istype
# maphash['typeof'] # or use nqp::what
maphash['defined'] = 'defined__IP' # or use nqp::isconcrete
# I/O opcodes
maphash['print'] = 'print'
maphash['say'] = 'say'
maphash['stat'] = 'stat__Isi' # (?)
maphash['open'] = 'open__Pss' # (?)
# terms
maphash['time_i'] = 'time__I'
maphash['time_n'] = 'time__N'
# arithmetic opcodes
maphash['add_i'] = 'add__Iii'
maphash['add_I'] = 'nqp_bigint_add__PPPP'
maphash['add_n'] = 'add__Nnn'
maphash['sub_i'] = 'sub__Iii'
maphash['sub_I'] = 'nqp_bigint_sub__PPPP'
maphash['sub_n'] = 'sub__Nnn'
maphash['mul_i'] = 'mul__Iii'
maphash['mul_I'] = 'nqp_bigint_mul__PPPP'
maphash['mul_n'] = 'mul__Nnn'
maphash['div_i'] = 'div__Iii'
maphash['div_I'] = 'nqp_bigint_div__PPPP'
maphash['div_In'] = 'nqp_bigint_div_num__NPP'
maphash['div_n'] = 'div__Nnn'
maphash['mod_i'] = 'mod__Iii'
maphash['mod_I'] = 'nqp_bigint_mod__PPPP'
maphash['expmod_I'] = 'nqp_bigint_exp_mod__PPPPP'
maphash['mod_n'] = 'mod__Nnn'
maphash['pow_n'] = 'pow__Nnn'
maphash['pow_I'] = 'nqp_bigint_pow__PPPPP'
maphash['neg_i'] = 'neg__Ii'
maphash['neg_I'] = 'nqp_bigint_neg__PPP'
maphash['neg_n'] = 'neg__Nn'
maphash['abs_i'] = 'abs__Ii'
maphash['abs_I'] = 'nqp_bigint_abs__PPP'
maphash['abs_n'] = 'abs__Nn'
maphash['gcd_i'] = 'gcd__Ii'
maphash['gcd_I'] = 'nqp_bigint_gcd__PPP'
maphash['lcm_i'] = 'lcm__Ii'
maphash['lcm_I'] = 'nqp_bigint_lcm__PPP'
maphash['ceil_n'] = 'ceil__Nn'
maphash['floor_n'] = 'floor__NN'
maphash['ln_n'] = 'ln__Nn'
maphash['sqrt_n'] = 'sqrt__Nn'
maphash['radix'] = 'nqp_radix__Pisii'
maphash['radix_I'] = 'nqp_bigint_radix__PisiiP'
maphash['log_n'] = 'ln__NN'
maphash['exp_n'] = 'exp__Nn'
maphash['isnanorinf'] = 'is_inf_or_nan__In'
# trig opcodes
maphash['sin_n'] = 'sin__NN'
maphash['asin_n'] = 'asin__NN'
maphash['cos_n'] = 'cos__NN'
maphash['acos_n'] = 'acos__NN'
maphash['tan_n'] = 'tan__NN'
maphash['atan_n'] = 'atan__NN'
maphash['atan2_n'] = 'atan__NNN'
maphash['sec_n'] = 'sec__NN'
maphash['asec_n'] = 'asec__NN'
maphash['sin_n'] = 'sin__NN'
maphash['asin_n'] = 'asin__NN'
maphash['sinh_n'] = 'sinh__NN'
maphash['cosh_n'] = 'cosh__NN'
maphash['tanh_n'] = 'tanh__NN'
maphash['sech_n'] = 'sech__NN'
# bitwise ops
maphash['bitor_i'] = 'bor__II'
maphash['bitor_I'] = 'nqp_bigint_bor__PPPP'
maphash['bitxor_i'] = 'bxor__II'
maphash['bitxor_I'] = 'nqp_bigint_bxor__PPPP'
maphash['bitand_i'] = 'band__II'
maphash['bitand_I'] = 'nqp_bigint_band__PPPP'
maphash['bitneg_i'] = 'bnot__II'
maphash['bitneg_I'] = 'nqp_bigint_bnot__PP'
maphash['bitshiftl_i'] = 'shl__III'
maphash['bitshiftl_I'] = 'nqp_bigint_shl__PPIP'
maphash['bitshiftr_i'] = 'shr__III'
maphash['bitshiftr_I'] = 'nqp_bigint_shr__PPIP'
maphash['bitor_s'] = 'bors__SS'
maphash['bitxor_s'] = 'bxors__SS'
maphash['bitand_s'] = 'bands__SS'
# string opcodes
maphash['chars'] = 'length__Is'
maphash['concat'] = 'concat' # allow either P or S form
maphash['concat_s'] = 'concat__Sss' # force S form
maphash['join'] = 'join__SsP'
maphash['split'] = 'split__Pss'
maphash['index'] = 'index__Issi'
maphash['rindex'] = 'rindex__ISSI'
maphash['chr'] = 'chr__Si'
maphash['ord'] = 'ord__Isi'
maphash['lc'] = 'downcase__Ss'
maphash['uc'] = 'upcase__Ss'
maphash['tclc'] = 'titlecase__Ss'
maphash['substr'] = 'substr__Ssii'
maphash['x'] = 'repeat__Ssi'
maphash['iscclass'] = 'is_cclass__Iisi' # (?)
maphash['findnotcclass'] = 'find_not_cclass__Iisii' # (?)
maphash['sprintf'] = 'sprintf__SsP'
# relational opcodes
maphash['cmp_i'] = 'cmp__Iii'
maphash['iseq_i'] = 'iseq__Iii'
maphash['isne_i'] = 'isne__Iii'
maphash['islt_i'] = 'islt__Iii'
maphash['isle_i'] = 'isle__Iii'
maphash['isgt_i'] = 'isgt__Iii'
maphash['isge_i'] = 'isge__Iii'
maphash['bool_I'] = 'nqp_bigint_bool__iP'
maphash['cmp_I'] = 'nqp_bigint_cmp__IPP'
maphash['iseq_I'] = 'nqp_bigint_eq__IPP'
maphash['isne_I'] = 'nqp_bigint_ne__IPP'
maphash['islt_I'] = 'nqp_bigint_lt__IPP'
maphash['isle_I'] = 'nqp_bigint_le__IPP'
maphash['isgt_I'] = 'nqp_bigint_gt__IPP'
maphash['isge_I'] = 'nqp_bigint_ge__IPP'
maphash['cmp_n'] = 'cmp__Inn'
maphash['iseq_n'] = 'iseq__Inn'
maphash['isne_n'] = 'isne__Inn'
maphash['islt_n'] = 'islt__Inn'
maphash['isle_n'] = 'isle__Inn'
maphash['isgt_n'] = 'isgt__Inn'
maphash['isge_n'] = 'isge__Inn'
maphash['cmp_s'] = 'cmp__Iss'
maphash['iseq_s'] = 'iseq__Iss'
maphash['isne_s'] = 'isne__Iss'
maphash['islt_s'] = 'islt__Iss'
maphash['isle_s'] = 'isle__Iss'
maphash['isgt_s'] = 'isgt__Iss'
maphash['isge_s'] = 'isge__Iss'
# bigint ops
maphash['fromstr_I'] = 'nqp_bigint_from_str__PsP'
maphash['tostr_I'] = 'nqp_bigint_to_str__SP'
maphash['base_I'] = 'nqp_bigint_to_str_base__SPI'
maphash['isbig_I'] = 'nqp_bigint_is_big__IP'
maphash['fromnum_I'] = 'nqp_bigint_from_num__PNP'
maphash['tonum_I'] = 'nqp_bigint_to_num__NP'
# native call ops
maphash['buildnativecall'] = 'nqp_native_call_build__vPsssPP'
maphash['nativecall'] = 'nqp_native_call__PPPP'
# boolean opcodes
maphash['not_i'] = 'not__Ii'
# aggregate opcodes, mapping to the Parrot v-table functions
maphash['atkey'] = 'set__PQs'
maphash['atpos'] = 'set__PQi'
maphash['atpos_i'] = 'set__IQi'
maphash['atpos_n'] = 'set__NQi'
maphash['atpos_s'] = 'set__SQi'
maphash['bindkey'] = 'set__1QsP'
maphash['bindpos'] = 'set__1QiP'
maphash['bindpos_i'] = 'set__1Qii'
maphash['bindpos_n'] = 'set__1Qin'
maphash['bindpos_s'] = 'set__1Qis'
maphash['deletekey'] = 'delete__0Qs'
maphash['deletepos'] = 'delete__0Qi'
maphash['existskey'] = 'exists__IQs'
maphash['existspos'] = 'exists__IQi'
maphash['elems'] = 'elements__IP'
maphash['islist'] = 'nqp_islist__IP'
maphash['iterator'] = 'iter__PP'
maphash['push'] = 'push__0PP'
maphash['push_s'] = 'push__0Ps'
maphash['push_i'] = 'push__0Pi'
maphash['push_n'] = 'push__0Pn'
maphash['pop'] = 'pop__PP'
maphash['pop_s'] = 'pop__sP'
maphash['pop_i'] = 'pop__iP'
maphash['pop_n'] = 'pop__nP'
maphash['shift'] = 'shift__PP'
maphash['shift_s'] = 'shift__sP'
maphash['shift_i'] = 'shift__iP'
maphash['shift_n'] = 'shift__nP'
maphash['unshift'] = 'unshift__0PP'
maphash['unshift_s'] = 'unshift__0Ps'
maphash['unshift_i'] = 'unshift__0Pi'
maphash['unshift_n'] = 'unshift__0Pn'
maphash['splice'] = 'splice__0PPii'
$P0 = new ['Hash']
$P0['pasttype'] = 'list'
maphash['list'] = $P0
$P0 = new ['Hash']
$P0['pasttype'] = 'hash'
maphash['hash'] = $P0
# nqp::qlist is a temporary operation for creating QRPA lists
# instead of RPA lists. Eventually we expect nqp::list to do the same,
# at which point nqp::qlist can go away.
$P0 = new ['Hash']
$P0['pasttype'] = 'list'
$P0['returns'] = 'QRPA'
maphash['qlist'] = $P0
# repr-level aggregate operations
maphash['r_atpos'] = 'repr_at_pos_obj__PPi'
maphash['r_atpos_i'] = 'repr_at_pos_int__IPi'
maphash['r_atpos_n'] = 'repr_at_pos_num__NPi'
maphash['r_bindpos'] = 'repr_bind_pos_obj__2PiP'
maphash['r_bindpos_i'] = 'repr_bind_pos_int__2Pii'
maphash['r_bindpos_n'] = 'repr_bind_pos_num__2Pin'
# object opcodes
maphash['bindattr'] = 'setattribute__3PPsP'
maphash['bindattr_i'] = 'repr_bind_attr_int__3PPsi'
maphash['bindattr_n'] = 'repr_bind_attr_num__3PPsn'
maphash['bindattr_s'] = 'repr_bind_attr_str__3PPss'
maphash['getattr'] = 'getattribute__PPPs'
maphash['getattr_i'] = 'repr_get_attr_int__IPPs'
maphash['getattr_n'] = 'repr_get_attr_num__NPPs'
maphash['getattr_s'] = 'repr_get_attr_str__SPPs'
maphash['create'] = 'repr_instance_of__PP'
maphash['clone'] = 'clone__PP'
maphash['isconcrete'] = 'repr_defined__IP'
maphash['iscont'] = 'is_container__IP'
maphash['isnull'] = 'isnull__IP'
maphash['isnull_s'] = 'isnull__IS'
maphash['istrue'] = 'istrue__IP'
maphash['istype'] = 'type_check__IPP'
maphash['null'] = 'null__P'
maphash['unbox_i'] = 'repr_unbox_int__IP'
maphash['unbox_n'] = 'repr_unbox_num__NP'
maphash['unbox_s'] = 'repr_unbox_str__SP'
maphash['box_i'] = 'repr_box_int__PiP'
maphash['box_n'] = 'repr_box_num__PnP'
maphash['box_s'] = 'repr_box_str__PsP'
maphash['where'] = 'get_id__IP'
maphash['can'] = 'can__IPs'
maphash['findmethod'] = 'find_method__PPs'
maphash['newtype'] = 'repr_type_object_for__PPs'
maphash['setwho'] = 'set_who__0PP'
# serialization context related opcodes
maphash['sha1'] = 'nqp_sha1__Ss'
# control opcodes
$P0 = new ['Hash']
$P0['pasttype'] = 'if'
maphash['if'] = $P0
$P0 = new ['Hash']
$P0['pasttype'] = 'unless'
maphash['unless'] = $P0
$P0 = new ['Hash']
$P0['pasttype'] = 'while'
maphash['while'] = $P0
$P0 = new ['Hash']
$P0['pasttype'] = 'nqpdebug'
maphash['deb'] = $P0
maphash['die'] = 'die__vP'
maphash['exit'] = 'exit__vi'
maphash['sleep'] = 'sleep__vn'
maphash['throw'] = 'throw__0P'
maphash['rethrow'] = 'rethrow__0P'
.return (maphash)
.end