Safe Haskell | Safe |
---|---|
Language | Haskell98 |
This module represents a type-safe port of Erlang's general instructions. If this is your first exposure to BEAM, __I highly recommend Erik Stenman's book: https://happi.github.io/theBeamBook__. The documentation in this module point there derives directly from there, the Jerlang project, and Erlang's source code.
Synopsis
- label :: Label -> Op
- func_info :: Text -> Int -> Op
- on_load :: Op
- line :: Int -> Op
- call :: Int -> Label -> Op
- call_last :: Int -> Label -> Int -> Op
- call_only :: Int -> Label -> Op
- call_ext :: Import -> Op
- call_ext_last :: Import -> Int -> Op
- bif0 :: (Bif0 a1, NoGC a1, IsRegister a2) => a1 -> a2 -> Op
- bif1 :: (Bif1 a2, NoGC a2, IsSource a3, IsRegister a4) => Label -> a2 -> a3 -> a4 -> Op
- bif2 :: (Bif2 a2, NoGC a2, IsSource a3, IsSource a4, IsRegister a5) => Label -> a2 -> a3 -> a4 -> a5 -> Op
- call_ext_only :: Import -> Op
- apply :: Int -> Op
- apply_last :: Int -> Int -> Op
- gc_bif1 :: (Bif1 a3, IsSource a4, IsRegister a5) => Label -> Int -> a3 -> a4 -> a5 -> Op
- gc_bif2 :: (Bif2 a3, IsSource a4, IsSource a5, IsRegister a6) => Label -> Int -> a3 -> a4 -> a5 -> a6 -> Op
- gc_bif3 :: (Bif3 a3, IsSource a4, IsSource a5, IsSource a6, IsRegister a7) => Label -> Int -> a3 -> a4 -> a5 -> a6 -> a7 -> Op
- allocate :: Int -> Int -> Op
- allocate_heap :: Int -> Int -> Int -> Op
- allocate_zero :: Int -> Int -> Op
- allocate_heap_zero :: Int -> Int -> Int -> Op
- test_heap :: Int -> Int -> Op
- init' :: Y -> Op
- deallocate :: Int -> Op
- return' :: Op
- trim :: Int -> Int -> Op
- send :: Op
- remove_message :: Op
- timeout :: Op
- loop_rec :: Label -> X -> Op
- loop_rec_end :: Label -> Op
- wait :: Label -> Op
- wait_timeout :: IsSource a2 => Label -> a2 -> Op
- recv_mark :: Label -> Op
- recv_set :: Label -> Op
- is_lt :: (IsSource a2, IsSource a3) => Label -> a2 -> a3 -> Op
- is_ge :: (IsSource a2, IsSource a3) => Label -> a2 -> a3 -> Op
- is_eq :: (IsSource a2, IsSource a3) => Label -> a2 -> a3 -> Op
- is_ne :: (IsSource a2, IsSource a3) => Label -> a2 -> a3 -> Op
- is_eq_exact :: (IsSource a2, IsSource a3) => Label -> a2 -> a3 -> Op
- is_ne_exact :: (IsSource a2, IsSource a3) => Label -> a2 -> a3 -> Op
- is_integer :: IsSource a2 => Label -> a2 -> Op
- is_float :: IsSource a2 => Label -> a2 -> Op
- is_number :: IsSource a2 => Label -> a2 -> Op
- is_atom :: IsSource a2 => Label -> a2 -> Op
- is_pid :: IsSource a2 => Label -> a2 -> Op
- is_reference :: IsSource a2 => Label -> a2 -> Op
- is_port :: IsSource a2 => Label -> a2 -> Op
- is_nil :: IsSource a2 => Label -> a2 -> Op
- is_binary :: IsSource a2 => Label -> a2 -> Op
- is_list :: IsSource a2 => Label -> a2 -> Op
- is_nonempty_list :: IsSource a2 => Label -> a2 -> Op
- is_tuple :: IsSource a2 => Label -> a2 -> Op
- test_arity :: IsSource a2 => Label -> a2 -> Int -> Op
- is_boolean :: IsSource a2 => Label -> a2 -> Op
- is_function :: IsSource a2 => Label -> a2 -> Op
- is_function2 :: (IsSource a2, IsSource a3) => Label -> a2 -> a3 -> Op
- is_bitstr :: IsSource a2 => Label -> a2 -> Op
- is_map :: IsSource a2 => Label -> a2 -> Op
- is_tagged_tuple :: IsSource a2 => Label -> a2 -> Int -> Text -> Op
- select_val :: IsSource a1 => a1 -> Label -> [(Label, Source)] -> Op
- select_tuple_arity :: IsSource a1 => a1 -> Label -> [(Label, Source)] -> Op
- jump :: Label -> Op
- move :: (IsSource a1, IsRegister a2) => a1 -> a2 -> Op
- get_list :: (IsRegister a1, IsRegister a2, IsRegister a3) => a1 -> a2 -> a3 -> Op
- get_tuple_element :: (IsRegister a1, IsRegister a3) => a1 -> Int -> a3 -> Op
- set_tuple_element :: (IsSource a1, IsRegister a2) => a1 -> a2 -> Int -> Op
- put_list :: (IsSource a1, IsSource a2, IsRegister a3) => a1 -> a2 -> a3 -> Op
- put_tuple :: IsRegister a2 => Int -> a2 -> Op
- put :: IsSource a1 => a1 -> Op
- badmatch :: IsSource a1 => a1 -> Op
- if_end :: Op
- case_end :: IsSource a1 => a1 -> Op
- call_fun :: Int -> Op
- make_fun2 :: Lambda -> Op
- bs_start_match2 :: (IsSource a2, IsRegister a5) => Label -> a2 -> Int -> Int -> a5 -> Op
- bs_get_integer2 :: (IsSource a4, IsRegister a7) => Label -> X -> Int -> a4 -> Int -> Int -> a7 -> Op
- bs_get_float2 :: (IsSource a4, IsRegister a7) => Label -> X -> Int -> a4 -> Int -> Int -> a7 -> Op
- bs_get_binary2 :: (IsSource a4, IsRegister a7) => Label -> X -> Int -> a4 -> Int -> Int -> a7 -> Op
- bs_skip_bits2 :: IsSource a3 => Label -> X -> a3 -> Int -> Int -> Op
- bs_test_tail2 :: Label -> X -> Int -> Op
- bs_save2 :: IsRegister a1 => a1 -> Int -> Op
- bs_restore2 :: IsRegister a1 => a1 -> Int -> Op
- bs_context_to_binary :: IsRegister a1 => a1 -> Op
- bs_test_unit :: Label -> X -> Int -> Op
- bs_match_string :: Label -> X -> Int -> Int -> Op
- bs_append :: (IsSource a2, IsSource a6, IsRegister a8) => Label -> a2 -> Int -> Int -> Int -> a6 -> Int -> a8 -> Op
- bs_private_append :: (IsSource a2, IsSource a4, IsRegister a6) => Label -> a2 -> Int -> a4 -> Int -> a6 -> Op
- bs_init2 :: (IsSource a2, IsRegister a6) => Label -> a2 -> Int -> Int -> Int -> a6 -> Op
- bs_put_integer :: (IsSource a2, IsSource a5) => Label -> a2 -> Int -> Int -> a5 -> Op
- bs_put_binary :: (IsSource a2, IsSource a5) => Label -> a2 -> Int -> Int -> a5 -> Op
- bs_put_float :: (IsSource a2, IsSource a5) => Label -> a2 -> Int -> Int -> a5 -> Op
- bs_put_string :: Int -> Int -> Op
- bs_add :: (IsSource a2, IsSource a3, IsRegister a5) => Label -> a2 -> a3 -> Int -> a5 -> Op
- bs_init_writable :: Op
- bs_init_bits :: (IsSource a2, IsRegister a6) => Label -> a2 -> Int -> Int -> Int -> a6 -> Op
- bs_get_utf8 :: IsRegister a5 => Label -> X -> Int -> Int -> a5 -> Op
- bs_skip_utf8 :: Label -> X -> Int -> Int -> Op
- bs_get_utf16 :: IsRegister a5 => Label -> X -> Int -> Int -> a5 -> Op
- bs_skip_utf16 :: Label -> X -> Int -> Int -> Op
- bs_get_utf32 :: IsRegister a5 => Label -> X -> Int -> Int -> a5 -> Op
- bs_skip_utf32 :: Label -> X -> Int -> Int -> Op
- bs_utf8_size :: (IsSource a2, IsRegister a3) => Label -> a2 -> a3 -> Op
- bs_put_utf8 :: IsSource a3 => Label -> Int -> a3 -> Op
- bs_utf16_size :: (IsSource a2, IsRegister a3) => Label -> a2 -> a3 -> Op
- bs_put_utf16 :: IsSource a3 => Label -> Int -> a3 -> Op
- bs_put_utf32 :: IsSource a3 => Label -> Int -> a3 -> Op
- fclearerror :: Op
- fcheckerror :: Label -> Op
- fmove :: (IsSourceF a1, IsRegisterF a2) => a1 -> a2 -> Op
- fconv :: IsSource a1 => a1 -> F -> Op
- fadd :: F -> F -> F -> Op
- fsub :: F -> F -> F -> Op
- fmul :: F -> F -> F -> Op
- fdiv :: F -> F -> F -> Op
- fnegate :: F -> F -> Op
- try :: Y -> Label -> Op
- try_end :: Y -> Op
- try_case :: Y -> Op
- try_case_end :: IsSource a1 => a1 -> Op
- raise :: (IsSource a1, IsSource a2) => a1 -> a2 -> Op
- catch :: Y -> Label -> Op
- catch_end :: Y -> Op
- put_map_assoc :: (IsSource a2, IsRegister a3) => Label -> a2 -> a3 -> [(Source, Source)] -> Op
- put_map_exact :: (IsSource a2, IsRegister a3) => Label -> a2 -> a3 -> [(Source, Source)] -> Op
- has_map_fields :: IsSource a2 => Label -> a2 -> [Source] -> Op
- get_map_elements :: IsSource a2 => Label -> a2 -> [(Source, Register)] -> Op
Documentation
Label gives this code address a name and marks the start of a basic block.
Define a function M:F/A in the current module.
Function and BIF calls
Call the function at label. Save the next instruction as the return address in the CP register.
Deallocate and do a tail recursive call to the function at label. Do not update the CP register. Before the call deallocate Deallocate words of stack.
Do a tail recursive call to the function at Label. Do not update the CP register.
call_ext :: Import -> Op Source #
Call the function of arity pointed to by Destination. Save the next instruction as the return address in the CP register.
call_ext_last :: Import -> Int -> Op Source #
Deallocate and do a tail call to function pointed to by Destination. Do not update the CP register. Deallocate some words from the stack before the call.
bif0 :: (Bif0 a1, NoGC a1, IsRegister a2) => a1 -> a2 -> Op Source #
Call the bif and store the result in register.
bif1 :: (Bif1 a2, NoGC a2, IsSource a3, IsRegister a4) => Label -> a2 -> a3 -> a4 -> Op Source #
Call the bif with the source, and store the result in register. On failure jump to label.
bif2 :: (Bif2 a2, NoGC a2, IsSource a3, IsSource a4, IsRegister a5) => Label -> a2 -> a3 -> a4 -> a5 -> Op Source #
Call the bif with the sources, and store the result in register. On failure jump to label.
call_ext_only :: Import -> Op Source #
Do a tail recursive call to the function at label. Do not update the CP register.
Same as apply
but does not save the CP and deallocates words
:: (Bif1 a3, IsSource a4, IsRegister a5) | |
=> Label | jump here on failure |
-> Int | number of X-registers to save |
-> a3 | BIF, something like |
-> a4 | argument |
-> a5 | where to put the result |
-> Op |
Call the bif with the argument, and store the result in the register. On failure jump to label. Do a garbage collection if necessary to allocate space on the heap for the result.
gc_bif2 :: (Bif2 a3, IsSource a4, IsSource a5, IsRegister a6) => Label -> Int -> a3 -> a4 -> a5 -> a6 -> Op Source #
Same as gc_bif1
, but with two source arguments.
gc_bif3 :: (Bif3 a3, IsSource a4, IsSource a5, IsSource a6, IsRegister a7) => Label -> Int -> a3 -> a4 -> a5 -> a6 -> a7 -> Op Source #
Same as gc_bif1
, but with three source arguments.
Allocating, deallocating and returning
Allocate space for some words on the stack. If a GC is needed during allocation there are a number of live X registers. Also save the continuation pointer (CP) on the stack.
Allocate space for some words on the stack and ensure there is space for words on the heap. If a GC is needed save Live number of X registers. Also save the continuation pointer (CP) on the stack.
Allocate space for some words on the stack. If a GC is needed during allocation there are a number of live X registers. Clear the new stack words. (By writing NIL.) Also save the continuation pointer (CP) on the stack.
Allocate space for some words on the stack and ensure there is space for words on the heap. If a GC is needed save Live number of X registers. Clear the new stack words. (By writing NIL.) Also save the continuation pointer (CP) on the stack.
Ensure there is space for HeapNeed words on the heap. If a GC is needed save live number of X registers.
deallocate :: Int -> Op Source #
Restore the continuation pointer (CP) from the stack and deallocate N+1 words from the stack (the + 1 is for the CP).
Reduce the stack usage by some number of words, keeping the CP on the top of the stack.
Sending and receiving
Send argument in x(1) as a message to the destination process in x(0). The message in x(1) ends up as the result of the send in x(0).
remove_message :: Op Source #
Unlink the current message from the message queue and store a pointer to the message in x(0). Remove any timeout.
loop_rec_end :: Label -> Op Source #
Advance the save pointer to the next message and jump back to label.
Suspend the processes and set the entry point to the beginning of the receive loop at label.
wait_timeout :: IsSource a2 => Label -> a2 -> Op Source #
Sets up a timeout of source milliseconds and saves the address of the following instruction as the entry point if the timeout triggers.
recv_mark :: Label -> Op Source #
Save the end of the message queue and the address of the label so that a recv_set instruction can start | scanning the inbox from this position.
recv_set :: Label -> Op Source #
Check that the saved mark points to label and set the save pointer in the message queue to the last position of the message queue saved by the recv_mark instruction.
Comparision
is_lt :: (IsSource a2, IsSource a3) => Label -> a2 -> a3 -> Op Source #
Compare two terms and jump to label if first is not less than second.
is_ge :: (IsSource a2, IsSource a3) => Label -> a2 -> a3 -> Op Source #
Compare two terms and jump to label if first is less than second.
is_eq :: (IsSource a2, IsSource a3) => Label -> a2 -> a3 -> Op Source #
Compare two terms and jump to label if first is not (numerically) equal to second.
is_ne :: (IsSource a2, IsSource a3) => Label -> a2 -> a3 -> Op Source #
Compare two terms and jump to label if first is (numerically) equal to second.
is_eq_exact :: (IsSource a2, IsSource a3) => Label -> a2 -> a3 -> Op Source #
Compare two terms and jump to label if first is not exactly equal to second.
is_ne_exact :: (IsSource a2, IsSource a3) => Label -> a2 -> a3 -> Op Source #
Compare two terms and jump to label if first is exactly equal to second.
Type tests
is_integer :: IsSource a2 => Label -> a2 -> Op Source #
Test the type of source and jump to label if it is not an integer.
is_float :: IsSource a2 => Label -> a2 -> Op Source #
Test the type of source and jump to label if it is not a float.
is_number :: IsSource a2 => Label -> a2 -> Op Source #
Test the type of source and jump to label if it is not a number.
is_atom :: IsSource a2 => Label -> a2 -> Op Source #
Test the type of source and jump to label if it is not a atom.
is_pid :: IsSource a2 => Label -> a2 -> Op Source #
Test the type of source and jump to label if it is not a pid.
is_reference :: IsSource a2 => Label -> a2 -> Op Source #
Test the type of source and jump to label if it is not a reference.
is_port :: IsSource a2 => Label -> a2 -> Op Source #
Test the type of source and jump to label if it is not a port.
is_nil :: IsSource a2 => Label -> a2 -> Op Source #
Test the type of source and jump to label if it is not nil.
is_binary :: IsSource a2 => Label -> a2 -> Op Source #
Test the type of source and jump to label if it is not a binary.
is_list :: IsSource a2 => Label -> a2 -> Op Source #
Test the type of source and jump to label if it is not a cons or nil.
is_nonempty_list :: IsSource a2 => Label -> a2 -> Op Source #
Test the type of source and jump to label if it is not a cons.
is_tuple :: IsSource a2 => Label -> a2 -> Op Source #
Test the type of source and jump to label if it is not a tuple.
test_arity :: IsSource a2 => Label -> a2 -> Int -> Op Source #
Test the arity of (the tuple in) source and jump to label if it is not equal to arity.
is_boolean :: IsSource a2 => Label -> a2 -> Op Source #
Test the type of source and jump to label if it is not a boolean.
is_function :: IsSource a2 => Label -> a2 -> Op Source #
Test the type of the source and jump to label if it is not a function (i.e. fun or closure).
Test the type of the source and jump to label if it is not a function of the particular arity.
is_tagged_tuple :: IsSource a2 => Label -> a2 -> Int -> Text -> Op Source #
Test the type of source and jumps to label if it is not a tuple. Test the arity of Reg and jumps to label if it is not of the given size. Test the first element of the tuple and jumps to label if it is not given atom.
Indexing and jumping
select_val :: IsSource a1 => a1 -> Label -> [(Label, Source)] -> Op Source #
Jump to the destination label corresponding to source in the destinations list, if no arity matches, jump to fail label.
select_tuple_arity :: IsSource a1 => a1 -> Label -> [(Label, Source)] -> Op Source #
Check the arity of the source tuple and jump to the corresponding destination label, if no arity matches, jump to FailLabel.
Moving, extracting, modifying
move :: (IsSource a1, IsRegister a2) => a1 -> a2 -> Op Source #
Move the source (a literal or a register) to the destination register.
:: (IsRegister a1, IsRegister a2, IsRegister a3) | |
=> a1 | where to get the list |
-> a2 | where to put the head (car) |
-> a3 | where to put the tail (cdr) |
-> Op |
Get the head and tail (or car and cdr) parts of a list (a cons cell) from the initial register and put them into the registers.
:: (IsRegister a1, IsRegister a3) | |
=> a1 | where to get the tuple |
-> Int | target element index, 0-based |
-> a3 | where to put the element |
-> Op |
Get a particular element number from the tuple in source and put it in the destination register.
set_tuple_element :: (IsSource a1, IsRegister a2) => a1 -> a2 -> Int -> Op Source #
Update the element at position of the tuple in register with the new source element.
Building terms
:: (IsSource a1, IsSource a2, IsRegister a3) | |
=> a1 | the new head |
-> a2 | the new tail |
-> a3 | |
-> Op |
Build a list, from the front, and puts the resulting list in the register.
Just like Erlang's |
or Haskell's :
.
put_tuple :: IsRegister a2 => Int -> a2 -> Op Source #
Constructs an empty tuple on the heap (size+1 words)
and places its address into the Destination register.
No elements are set at this moment.
Put_tuple instruction is always followed by multiple
put
instructions which destructively set its elements one by one.
Raising errors
fun
support
Call fun
object (in x[Arity]) with args (in x[0..Arity-1])
Raises badarity
if the arity doesn’t match the function object.
Raises badfun
if a non-function is passed.
Binary matching
bs_start_match2 :: (IsSource a2, IsRegister a5) => Label -> a2 -> Int -> Int -> a5 -> Op Source #
bs_get_integer2 :: (IsSource a4, IsRegister a7) => Label -> X -> Int -> a4 -> Int -> Int -> a7 -> Op Source #
bs_get_float2 :: (IsSource a4, IsRegister a7) => Label -> X -> Int -> a4 -> Int -> Int -> a7 -> Op Source #
bs_get_binary2 :: (IsSource a4, IsRegister a7) => Label -> X -> Int -> a4 -> Int -> Int -> a7 -> Op Source #
bs_restore2 :: IsRegister a1 => a1 -> Int -> Op Source #
bs_context_to_binary :: IsRegister a1 => a1 -> Op Source #
bs_append :: (IsSource a2, IsSource a6, IsRegister a8) => Label -> a2 -> Int -> Int -> Int -> a6 -> Int -> a8 -> Op Source #
bs_private_append :: (IsSource a2, IsSource a4, IsRegister a6) => Label -> a2 -> Int -> a4 -> Int -> a6 -> Op Source #
Binary construction
bs_add :: (IsSource a2, IsSource a3, IsRegister a5) => Label -> a2 -> a3 -> Int -> a5 -> Op Source #
bs_init_bits :: (IsSource a2, IsRegister a6) => Label -> a2 -> Int -> Int -> Int -> a6 -> Op Source #
bs_get_utf8 :: IsRegister a5 => Label -> X -> Int -> Int -> a5 -> Op Source #
bs_get_utf16 :: IsRegister a5 => Label -> X -> Int -> Int -> a5 -> Op Source #
bs_get_utf32 :: IsRegister a5 => Label -> X -> Int -> Int -> a5 -> Op Source #
bs_utf8_size :: (IsSource a2, IsRegister a3) => Label -> a2 -> a3 -> Op Source #
bs_utf16_size :: (IsSource a2, IsRegister a3) => Label -> a2 -> a3 -> Op Source #
Floating point arithmetic
fclearerror :: Op Source #
fcheckerror :: Label -> Op Source #
Try, catch, raise
try_case_end :: IsSource a1 => a1 -> Op Source #
Maps
put_map_assoc :: (IsSource a2, IsRegister a3) => Label -> a2 -> a3 -> [(Source, Source)] -> Op Source #
put_map_exact :: (IsSource a2, IsRegister a3) => Label -> a2 -> a3 -> [(Source, Source)] -> Op Source #