Skip to main content

Module beam_mapping

Module beam_mapping 

Source
Expand description

BEAM / OTP concepts mapped to Byteflow flows, Caps, and Atomic Hop.

§BEAM → Byteflow (mental model)

Guide for Erlang/Elixir developers reading this codebase. Byteflow is not BEAM — but many ideas rhyme once you map terminology.

§Units

BEAMByteflowNotes
processflowFlowId, FlowHandle, FlowOutcome
pid()hop_sender(msg)Identity inside a delivered hop
pid() as addressValue::CapSelfPid / Spawn return Caps, not Pids
registered nameRuntime::register_name / whereisStores a Cap, not a FlowId. Swept on exit.

Key difference: on BEAM, a Pid is both identity and delivery address. In Byteflow, Cap = address, Pid = identity inside Message.sender.

BEAM:     send(Pid, Term)
Byteflow: send(Cap, Message)   // Message envelope required

See atomic-hop.md and security.md (S1, S6).

§Messaging

BEAMByteflow APIOpcode / host
spawn(fun)Fn::spawn(fn, argc)Spawn → Cap
Pid ! MsgFn::send(cap, hop)Send
receiveFn::receive()Receive
selective receive (pattern)Fn::receive_match_imm(tag)ReceiveMatchImmtag u16 only
gen_server:callFn::ask(cap, hop) / Fn::ask_timeoutAsk / AskTimeout
gen_server:castFn::send(cap, hop)fire-and-forget
reply to callerFn::send_reply(req, tag, payload)uses msg_reply_cap
build messageFn::hop(req_id, tag, payload)scheduler stamps sender
unpack messageFn::hop_payload(msg) etc.std natives

§Message shape

BEAM messages are arbitrary terms. Byteflow Atomic Hop is a fixed envelope:

Message { sender, reply_cap, request_id, tag, payload }
  • payload is a single u64 today — encode richer data via tags + natives.
  • sender is authenticated by the runtime on bytecode Send / Ask. Do not forge it with make_msg (see samples::forged_sender_send).

§Typical server loop (BEAM-style)

use byteflow::{Program, samples::TAG_REQ, samples::TAG_REP};

let mut p = Program::new("server");
let server = p.function("server", 0, |f| {
    let loop_lbl = f.label();
    f.bind(loop_lbl);
    let req = f.receive_match_imm(TAG_REQ as u16);
    let payload = f.hop_payload(req);
    f.add_imm(payload, 1);
    f.send_reply(req, TAG_REP, payload);
    f.jump(loop_lbl);
});

Sample: samples::server_loop.

§Lifecycle (mapped)

BEAM / OTPByteflow today
linksRuntime::link / Fn::link — abnormal exit kills the peer
monitors {'DOWN', ...}Runtime::monitor / Fn::monitorTAG_SYS_DOWN hop
OTP supervisor strategiesHost Supervisor + RestartStrategy (OneForOne / OneForAll / RestForOne)
register / whereisRuntime::register_name / whereis (Cap, not FlowId)
exit(Pid, kill)Runtime::kill (cooperative)

§What BEAM has that Byteflow does not (yet)

BEAM / OTPByteflow today
distributionSingle process, in-memory
pattern matching receiveTag-based selective receive only
process dictionaryNo
ETSNo
trap_exitNo — links always kill on abnormal exit

Failures surface as FlowOutcome::Failed on join, not as mailbox messages.

§Backpressure

PathMailbox full + Reject
Runtime::send(FlowId, …)Err(SendError::MailboxFull)
bytecode Send / Asksender parks (WAITING_SEND); one waiter per freed slot

§Host Rust vs bytecode

TaskWhere
spawn top-level flowsRuntime::spawn
trusted host sendRuntime::send(FlowId, Value::Message)
restart policySupervisor (Rust)
protocol in flowsProgram / Fn bytecode

Supervisor trees are not expressed as bytecode flows today — plan host Rust for OTP-style supervision.

§Quick equivalence cheat sheet

self()              →  hop_sender on received msg; self_address() for Cap
!                   →  send(cap, hop(...))
receive             →  receive() / receive_match_imm(TAG)
call                →  ask(cap, hop(...)) / ask_timeout(cap, hop, ms)
reply               →  send_reply(req, TAG_REP, payload)
spawn               →  spawn(fn) → Cap
register/whereis    →  Runtime::register_name / whereis; ChildSpec.name also registers
link/monitor        →  Fn::link / Fn::monitor; DOWN via TAG_SYS_DOWN

§Further reading