The Muq assembler computes the number of arguments accepted
and returned by the function being assembled -- the
arity of the function -- and saves it in the
associated function
object.
Some languages allow the user to explicitly declare the arity, in which case it may make sense to supply this declared information to the assembler for cross-check purposes.
There may also be cases where the assembler is unable to compute the arity, or where you wish to override the computed arity with an explicitly specified one -- for example, when the function hasn't been written yet, and only a preliminary stub is being compiled.
Muq encodes the arity information for a function as a single integer, for speed of runtime checking. The arity has five logical components:
Where "Function type" is a catchall slot for indicating other information of interest about the function. It will currently be one of:
0 arityNormal A vanilla function. 1 arityExit This function never returns to caller. 2 arityBranch A bytecode that alters the program counter. 3 arityOther I'm not sure this is used. 4 arityCalli Special hack for JOB_OP_CALLI bytecode. 5 arityQ Function returns unpredictable number of args. 6 arityStartBlock Special hack for '[' operator. 7 arityEndBlock Special hack for '|' operator. 8 arityEatBlock Special hack for ']' operator. 9 arityCalla Special hack for JOB_OP_CALLA bytecode. 10 arityCallMethod Special hack for JOB_OP_CALL_METHOD bytecode.
The specific decimal values given are subject to change in future releases: Use the given symbolic constant names instead.
These constants are defined in `muq/muf/10-C-utils.t' and `muq/c/fun2.h', which also define the layout of an arity word:
/****************************************************/ /* The current layout looks like: */ /* */ /* MSB 33222222222211111111110000000000 LSB */ /* 10987654321098765432109876543210 */ /* S-----Ss-----sB----Bb----bt--tI */ /* */ /* where: */ /* I: 1-bit typetag identifying integers. */ /* t--t: 4-bit type (see FUN_ARITY_TYP_*). */ /* b----b: 6-bit count of stackblocks accepted. */ /* B----B: 6-bit count of stackblocks returned. */ /* s-----s: 7-bit count of scalar args accepted. */ /* S-----S: 7-bit count of scalar args returned. */ /****************************************************/
(Again, this layout is subject to change in future
release: Use implodeArity
to construct
arity values, rather than hardwiring assumptions
about the layout into your code.
See section `implodeArity' in implodeArity.)
Thus, if your function accepts two blocks and three normal arguments, and returns one block and zero normal arguments, you may construct an appropriate arity value for it via
2 3 1 0 arityNormal implodeArity -> arity
And the final argument to finishAssembly
?
It is an force flag which may be set non-NIL to force the assembler to accept the arity value you supply as valid, rather than conducting its own cross-check.
And what if you want to let the assembler compute the
function arity on its own, and ignore your value? In
this case, provide an arity of -1 and leave the
force
argument NIL.
Bottom-line take-home lesson for this section: 99% of
the time, you can supply NIL as the force
argument and -1 as the arity argument, and everything
will go fine.
Ok, enough discussion of how to assemble the trivial function: Let's assemble some functions which actually things!
Go to the first, previous, next, last section, table of contents.