Sign in

    marianoguerra/tutuca/core does not have a README file

    Ctx

    pub(open) trait Ctx {
    fn path(Self) -> DispatchPath = _
    fn target_path(Self) -> DispatchPath = _
    fn name(Self) -> String? = _
    fn send(Self, name : String, args : Array[Value]) -> Unit = _
    fn bubble(Self, name : String, args : Array[Value]) -> Unit = _
    fn send_at_path(Self, path : DispatchPath, name : String, args : Array[Value]) -> Unit = _
    fn bubble_at_path(Self, path : DispatchPath, name : String, args : Array[Value]) -> Unit = _
    fn request(Self, name : String, args : Array[Value], opts : RequestOpts) -> Unit = _
    fn stop_propagation(Self) -> Unit = _
    fn at(Self) -> PathChanges = _
    fn walk_path(Self, callback : (Int, Value) -> Bool) -> Unit = _
    }

    What a handler can do besides transforming its leaf (JS EventContext). Defined here so Handler can carry it without depending on the transactor; every method defaults to a no-op so tests and Path::update can run handlers without a dispatcher. The transactor implements the real thing.

    Obj

    pub(open) trait Obj {
    fn component_id(Self) -> Int? = _
    fn obj_field(Self, name : String) -> Value? = _
    fn obj_with_field(Self, name : String, v : Value) -> Value? = _
    fn obj_item(Self, key : PathKey) -> Value? = _
    fn obj_with_item(Self, key : PathKey, v : Value) -> Value? = _
    fn obj_seq_entries(Self) -> Array[(PathKey, Value)]? = _
    fn obj_render_handler(Self, name : String, ns : HandlerNamespace) -> Value = _
    fn obj_handler(Self, bucket : HandlerBucket, name : String) -> Handler? = _
    fn obj_eq(Self, other : &Obj) -> Bool = _
    fn obj_debug(Self) -> String = _
    }

    Component-instance protocol (the port of JS's runtime Records tagged with a hidden component symbol). ONE trait serves both hybrid representations: the Value-backed Instance (component package) and user-defined typed structs. Instances live INSIDE Value so they flow through every Value-typed seam (binds, handler args, dynamic lookups, iterated seqs). Fns returned by obj_field / obj_render_handler and the Handler returned by obj_handler are SELF-PRE-BOUND (they close over the concrete Self — the no-downcast analogue of JS late this) and ignore args element 0. Every method defaults to an empty/None answer.

    PathNode

    pub(open) trait PathNode {
    fn field(Self, name : String) -> &PathNode? = _
    fn item(Self, key : PathKey) -> &PathNode? = _
    fn with_field(Self, name : String, v : &PathNode) -> &PathNode? = _
    fn with_item(Self, key : PathKey, v : &PathNode) -> &PathNode? = _
    fn as_key(Self) -> PathKey? = _
    fn as_value(Self) -> Value? = _
    fn handler(Self, bucket : HandlerBucket, name : String) -> Handler? = _
    }

    A node in the component/state tree addressable by path steps: given one addressing move it yields another node or an empty result. Every method defaults to None so implementations provide only what they support (the Stack trait precedent): pure data implements traversal only, component instances add handler.

    Contract for with_field/with_item: return a NEW instance with that child replaced; self must not be mutated; untouched siblings must be shared (copy-on-write or a persistent structure — the property suite tests this contract, not the representation).

    Stack

    pub(open) trait Stack {
    fn lookup_name(Self, String) -> Value = _
    fn lookup_bind(Self, String) -> Value = _
    fn lookup_dynamic(Self, String) -> Value = _
    fn lookup_field_raw(Self, String) -> Value = _
    fn lookup_method(Self, String) -> Value = _
    fn lookup_type(Self, String) -> Value = _
    fn get_handler_for(Self, String, HandlerNamespace) -> Value = _
    }

    Evaluation environment (JS stack). Every method defaults to Null so implementations (and test mocks) provide only the lookups they use. lookup_method returns the RESULT of the no-arg call — the stack invokes. get_handler_for returns Null when no handler is registered.

    DispatchPath

    pub(all) struct DispatchPath {
    items : Array[DispatchStep]
    } derive(Eq,
    Debug
    )

    A path that still knows which component contributed each hop. Bubbling pops one hop per component; converting to a transaction Path teleports every Dyn marker so mutations land on the data's real location.

    DispatchPath::compact

    fn DispatchPath::compact(self : DispatchPath) -> DispatchPath

    DispatchPath::concat

    fn DispatchPath::concat(self : DispatchPath, steps : Array[Step]) -> DispatchPath

    DispatchPath::new

    DispatchPath::of_steps

    fn DispatchPath::of_steps(steps : Array[Step]) -> DispatchPath

    DispatchPath::pop_step

    fn DispatchPath::pop_step(self : DispatchPath) -> DispatchPath

    DispatchPath::to_transaction_path

    fn DispatchPath::to_transaction_path(self : DispatchPath) -> Path

    DispatchStep

    pub(all) enum DispatchStep {
    Plain(step~ : Step, origin~ : Int?)
    Dyn(producer~ : Int, steps~ : Array[Step], interior~ : Array[Int])
    DynEach(producer~ : Int, steps~ : Array[Step], interior~ : Array[Int], key~ : PathKey)
    } derive(Eq,
    Debug
    )

    One hop of a dispatch path — the component-boundary projection of an event path. Plain wraps an addressing step with its origin (the id of the component that contributed it — teleport provenance); Dyn marks a dynamic variable (*dyn) used as a render target: the rendered data lives at the PRODUCER component (where the dynamic was defined), not at the consumer that wrote <x render="*dyn">, so interior lists the component ids crossed between producer and consumer, and steps is the producer's own path to the data. DynEach is its iterated form (the item lives at the producer's sequence field, keyed by key).

    Handler

    pub(all) struct Handler((Array[Value], &Ctx) -> &PathNode?)

    A leaf-update handler, resolved ON the leaf so self is pre-bound (the JS handler.apply(instance, args) binds this at call time; binding at resolution time is equivalent — same instance either way). Receives its args and the dispatch Ctx (JS appends ctx as the last handler argument). Returns the new leaf, or None for "no change" (the explicit port of the JS newLeaf !== curLeaf identity check: coercing into a trait object boxes, so returning Some(self) cannot preserve physical identity — answer None instead and the traversal skips the spine rebuild entirely).

    HandlerBucket

    pub(all) enum HandlerBucket {
    Receive
    Input
    Bubble
    Response
    } derive(Eq,
    Debug
    )

    Dispatch buckets a handler can live in (semantics.md §6). Alter is render-time only and never dispatched, so it is not a bucket here.

    HandlerNamespace

    pub(all) enum HandlerNamespace {
    Input
    Alter
    } derive(Eq,
    Debug
    )

    Handler namespaces are a fixed enumeration (JS passes "input"/"alter" strings)

    HandlerParse

    pub(all) struct HandlerParse {
    handler : Val
    args : Array[Val]
    } derive(Eq,
    Debug
    )

    Handler reference plus parsed args for @on.

    Issue

    pub(all) struct Issue {
    kind : IssueKind
    role : IssueRole
    value : String
    } derive(Eq,
    Debug
    )

    A parse issue, collected on the ParseCtx (JS px.onParseIssue callback)

    IssueKind

    pub(all) enum IssueKind {
    BadValue
    } derive(Eq,
    Debug
    )

    JS onParseIssue kind — only "bad-value" occurs in value.js; other kinds (x-op, x-attr, …) join this enum when their modules are ported.

    IssueRole

    pub(all) enum IssueRole {
    BadMacroVar
    BadHandlerName
    BadHandlerArg
    UnknownPredicate
    PredicateArity(Pred)
    BadPredicateArg
    } derive(Eq,
    Debug
    )

    What was malformed (JS info.role)

    Lit

    pub(all) enum Lit {
    LNull
    LBool(Bool)
    LNum(Double)
    LStr(String)
    } derive(Eq,
    Debug
    )

    Literal constant payload (JS ConstVal.val: string | number | boolean | null)

    NullCtx

    pub(all) struct NullCtx {
    }

    A Ctx that dispatches nothing (JS eval(null) analogue for handlers).
    impl Ctx for NullCtx

    NullStack

    pub(all) struct NullStack {
    }

    Stand-in for JS eval(null) on values that touch no stack
    impl Stack for NullStack

    ParseCtx

    pub struct ParseCtx {
    macro_vars : Map[String, String]
    issues : Array[Issue]
    }

    Parse context (JS px): macro variables in scope plus collected issues

    ParseCtx::new

    fn ParseCtx::new(macro_vars? : Map[String, String]) -> ParseCtx

    Path

    pub(all) struct Path {
    steps : Array[Step]
    } derive(Eq,
    Debug
    )

    An address into the component/state tree: a sequence of steps root→leaf.

    Path::compact

    fn Path::compact(self : Path) -> Path

    Path::concat

    fn Path::concat(self : Path, steps : Array[Step]) -> Path

    Path::lookup

    fn Path::lookup(self : Path, root : &PathNode) -> &PathNode?

    Path::new

    fn Path::new(steps? : Array[Step]) -> Path

    Path::pin_keys

    fn Path::pin_keys(self : Path, root : &PathNode) -> Path

    Path::pop_step

    fn Path::pop_step(self : Path) -> Path

    Path::resolve_chain

    fn Path::resolve_chain(self : Path, root : &PathNode) -> Array[&PathNode]

    Path::set_value

    fn Path::set_value(self : Path, root : &PathNode, v : &PathNode) -> &PathNode

    Path::to_keys

    fn Path::to_keys(self : Path) -> Array[StepKey]

    Path::update

    fn Path::update(self : Path, root : &PathNode, bucket : HandlerBucket, name : String, args : Array[Value]) -> &PathNode

    PathChanges

    pub struct PathChanges {
    ctx : &Ctx
    steps : Array[Step]
    }

    PathChanges::bubble

    fn PathChanges::bubble(self : PathChanges, name : String, args : Array[Value]) -> Unit

    Bubble name from the built path (JS PathChanges.bubble: skipSelf + bubbles).

    PathChanges::build_path

    fn PathChanges::build_path(self : PathChanges) -> DispatchPath

    The absolute dispatch path this builder addresses: the ctx's path with the accumulated steps appended (JS PathChanges.buildPath).

    PathChanges::field

    fn PathChanges::field(self : PathChanges, name : String) -> PathChanges

    Descend into field name (JS PathBuilder.field).

    PathChanges::index

    fn PathChanges::index(self : PathChanges, name : String, i : Int) -> PathChanges

    Descend into element i of sequence field name (JS PathBuilder.index).

    PathChanges::key

    fn PathChanges::key(self : PathChanges, name : String, key : String) -> PathChanges

    Descend into keyed element key of map field name (JS PathBuilder.key).

    PathChanges::of

    fn PathChanges::of(ctx : &Ctx) -> PathChanges

    A builder rooted at ctx's dispatch path (JS get at). Usually reached through Ctx::at, exposed for callers holding a &Ctx directly.

    PathChanges::send

    fn PathChanges::send(self : PathChanges, name : String, args : Array[Value]) -> Unit

    Send name at the built path (JS PathChanges.send).

    PathKey

    pub(all) enum PathKey {
    KInt(Int)
    KStr(String)
    } derive(Eq,
    Debug
    )

    A concrete sequence key: list index or map key (JS SeqStep.key is int|string)

    Pred

    pub(all) enum Pred {
    IsEmpty
    IsTruthy
    IsFalsy
    IsNull
    Equals
    } derive(Eq,
    Debug
    )

    Boolean predicates usable in conditional slots (JS PREDICATES table)

    Pred::apply

    fn Pred::apply(self : Pred, args : Array[Value]) -> Bool

    Pred::arity

    fn Pred::arity(self : Pred) -> Int

    Pred::name

    fn Pred::name(self : Pred) -> String

    Pred::of_name

    fn Pred::of_name(name : String) -> Pred?

    RequestOpts

    pub(all) struct RequestOpts {
    on_ok_name : String?
    on_error_name : String?
    on_res_name : String?
    live_path : Bool
    } derive(Eq,
    Debug
    )

    Options for Ctx::request (JS pushRequest opts): response-handler routing (on_ok_name / on_error_name / on_res_name) and live_path, which opts out of pinning field-resolved keys at request time.

    RequestOpts::new

    fn RequestOpts::new(on_ok_name? : String, on_error_name? : String, on_res_name? : String, live_path? : Bool) -> RequestOpts

    Step

    pub(all) enum Step {
    FieldStep(String)
    SeqStep(field~ : String, key~ : PathKey)
    SeqAccessStep(seq_field~ : String, key_field~ : String)
    EachRenderItStep(field~ : String, key~ : PathKey)
    BindStep(binds~ : Map[String, Value])
    ScopeBindStep(val~ : Val)
    EachBindStep(val~ : Val, when_val~ : Val?, enrich_with_val~ : Val?, loop_with_val~ : Val?, key~ : PathKey)
    } derive(Eq,
    Debug
    )

    Path steps (src/path.js). FieldStep/SeqAccessStep are what values address (Val::to_path_item); SeqStep is a field + concrete key (also the pinned form of SeqAccessStep); EachRenderItStep is an iterated render target that compacts to a SeqStep; Bind/ScopeBind/EachBind are frame-only (stack rebuild). Dynamic-var markers live on DispatchStep in the path package.

    StepKey

    pub(all) struct StepKey {
    field : String
    key : PathKey?
    } derive(Eq,
    Debug
    )

    A generic {field, key?} descriptor of an addressing step (JS Step.toKey), so tooling can introspect a path without matching on Step.

    Val

    pub(all) enum Val {
    Const(lit~ : Lit, from_macro~ : Bool)
    StrTpl(Array[Val?])
    Predicate(pred~ : Pred, args~ : Array[Val])
    Name(String)
    HandlerName(name~ : String, ns~ : HandlerNamespace)
    TypeName(String)
    Bind(String)
    BindMember(name~ : String, prop~ : String)
    Dyn(String)
    Field(String)
    Method(String)
    SeqAccess(seq~ : String, key~ : String)
    } derive(Eq,
    Debug
    )

    Parsed value AST. One variant per JS BaseVal subclass. from_macro ports ConstVal.fromMacroVar: set when a ^name macro var resolves to a constant, which makes an enclosing template non-literal. StrTpl parts alternate text constants and placeholder expressions; a None part is a placeholder whose inner expression failed to parse (JS keeps null there).
    impl Show for Val

    Val::eval

    fn Val::eval(self : Val, stack : &Stack) -> Value

    Val::eval_as_handler

    fn Val::eval_as_handler(self : Val, stack : &Stack) -> Value

    Val::is_literal

    fn Val::is_literal(self : Val) -> Bool

    Val::render

    fn Val::render(self : Val, stack : &Stack) -> Value?

    Val::to_path_item

    fn Val::to_path_item(self : Val) -> Step?

    Value

    pub(all) enum Value {
    Null
    Bool(Bool)
    Num(Double)
    Str(String)
    List(Array[Value])
    Map(Map[String, Value])
    Fn((Array[Value]) -> Value)
    Obj(&Obj)
    }

    Dynamic runtime value: what eval(stack) reads and returns.
    impl PathNode for Value
    impl Eq for Value
    impl ToJson for Value
    impl FromJson for Value

    Value::bool

    fn Value::bool(self : Value, default? : Bool) -> Bool

    Value::entries

    fn Value::entries(self : Value) -> Map[String, Value]

    The map payload; empty for non-maps.

    Value::field

    fn Value::field(self : Value, name : String) -> Value

    Field access that works on Map values and Obj instances alike; Null for anything else (including missing fields).

    Value::from_json

    fn Value::from_json(j : Json) -> Value

    Build a Value from parsed JSON. Lossless: every JSON shape has a Value.

    Value::int

    fn Value::int(self : Value, default? : Int) -> Int

    Value::is_truthy

    fn Value::is_truthy(self : Value) -> Bool

    JS truthiness: Null/false/0/NaN/"" are false; lists, maps and functions are always true (like JS objects). The truthy? predicate differs on purpose: it treats empty collections as falsy (see pred_truthy).

    Value::list

    fn Value::list(self : Value) -> Array[Value]

    The list payload; [] for non-lists (shared empty NOT returned — fresh).

    Value::num

    fn Value::num(self : Value, default? : Double) -> Double

    Value::str

    fn Value::str(self : Value, default? : String) -> String

    Value::to_display_string

    fn Value::to_display_string(self : Value) -> String

    JS ${v} template-interpolation semantics. Approximations: List joins elements with ","; Map and Fn render as opaque markers (JS "[object Object]" / function source are not worth mirroring).

    Value::to_json

    fn Value::to_json(self : Value) -> Json

    Json shape of a Value. Fn/Obj have no JSON form and become null (JS structured clone would throw on a function too).

    parse_alter_handler

    fn parse_alter_handler(s : String, ctx : ParseCtx) -> Val?

    parse_bool

    fn parse_bool(s : String, ctx : ParseCtx) -> Val?

    parse_component

    fn parse_component(s : String, ctx : ParseCtx) -> Val?

    parse_field

    fn parse_field(s : String, ctx : ParseCtx) -> Val?

    parse_handler_arg

    fn parse_handler_arg(s : String, ctx : ParseCtx) -> Val?

    parse_input_handler

    fn parse_input_handler(s : String, ctx : ParseCtx) -> HandlerParse?

    parse_macro_attr

    fn parse_macro_attr(s : String, ctx : ParseCtx) -> Val?

    parse_provide

    fn parse_provide(s : String, ctx : ParseCtx) -> Val?

    parse_sequence

    fn parse_sequence(s : String, ctx : ParseCtx) -> Val?

    parse_text

    fn parse_text(s : String, ctx : ParseCtx) -> Val?

    parse_token

    fn parse_token(s : String, ctx : ParseCtx) -> Val?

    size_of

    fn size_of(v : Value) -> Int?

    JS sizeOf: .size (immutable collections) or .length (string/array).

    step_get

    fn step_get(node : &PathNode, step : Step) -> &PathNode?

    step_put

    fn step_put(node : &PathNode, step : Step, child : &PathNode) -> &PathNode?

    step_with_key

    fn step_with_key(step : Step, key : PathKey) -> Step

    Key a step with the si/sk an §Each§ meta carried (JS Step.withIndex / withKey, used by event reconstruction's applyKey): a plain field access under a keyed meta addresses the keyed item. Steps that carry their own key (or no field) are returned unchanged.

    tokenize_value

    fn tokenize_value(s : String) -> Array[String]

    The single value tokenizer: a $'…' template run, a plain '…' literal (escapes kept in the token), or a maximal non-whitespace run. Quoted alternatives win only at their start; an unterminated quote falls back to the plain run (mirrors the JS regex alternation).

    warn

    fn warn(msg : String) -> Unit

    Report a runtime warning through warn_hook.

    warn_hook

    let warn_hook :
    Ref
    [(String) -> Unit]

    Where runtime warnings go. Defaults to println (the closest portable analogue of JS console.warn); a host can redirect it — e.g. into an error pane or the browser console — without threading a context through eval.

    with_value_stash

    fn[T] with_value_stash(f : () -> T) -> T

    Run f with an active Value stash: within it, the ToJson/FromJson trait impls for Value carry Obj/Fn values through Json losslessly (encoded as {STASH_KEY: index} markers into a side array). Strictly synchronous; nesting saves and restores the outer stash.