Skip to content

Latest commit

 

History

History
957 lines (767 loc) · 29.4 KB

File metadata and controls

957 lines (767 loc) · 29.4 KB

FROG logo

🐸 Reference Runtime — accept_contract_and_execute()

MVP runtime acceptance and execution pseudo-code for the non-normative FROG reference implementation
FROG — Free Open Graphical Language


Contents


1. Overview

This document defines the first detailed pseudo-code sketch for accept_contract_and_execute() in the FROG reference runtime. Its purpose is to consume a backend contract artifact, accept or reject it explicitly, and, if accepted, execute it through the first reference runtime family.

The runtime is the first private realization stage of the reference implementation. It is downstream from:

  • canonical source,
  • validation,
  • Execution IR derivation,
  • lowering,
  • backend contract emission.

The runtime therefore does not define language truth. It consumes a declared contract and realizes it privately.


2. Status and Boundary

This document is non-normative. It does not redefine:

  • the language,
  • the open Execution IR,
  • the lowering boundary,
  • the backend contract boundary.

It is an implementation sketch for one reference runtime family. If a runtime shortcut conflicts with the published contract boundary, the contract boundary wins.


3. MVP Scope

The first runtime slice covers:

  • one backend contract to one execution session,
  • public input and public output boundaries,
  • deterministic step execution,
  • ordinary core arithmetic computation for the MVP examples,
  • UI value binding for widget_value-derived cases,
  • UI reference resolution for widget_reference-derived cases,
  • standardized UI operations:
    • property_read
    • property_write
    • method_invoke
  • explicit local memory initialization, read, and commit for frog.core.delay-derived cases.

The first slice does not attempt to define:

  • a universal runtime scheduler,
  • a multi-process runtime,
  • a distributed runtime,
  • a standardized UI event loop model,
  • a universal debugger protocol.

4. Selected Runtime Family

The first runtime family is:

reference_host_runtime_ui_binding

This family assumes:

  • single-process host execution,
  • deterministic step execution,
  • optional UI value binding,
  • optional UI reference binding,
  • explicit local memory preservation when present,
  • no first-class standardized UI event execution model.

5. Input Contract

The runtime consumes a successful backend contract artifact conceptually equivalent to:

{
  "artifact_kind": "frog_backend_contract",
  "artifact_version": "0.1",
  "backend_family": "reference_host_runtime_ui_binding",
  "producer": "reference_contract_emitter",
  "compatibility": "family_specific",
  "source_ref": { ... },
  "assumptions": { ... },
  "units": [
    {
      "id": "main",
      "role": "entry_unit",
      "boundaries": [],
      "state": [],
      "operations": [],
      "attribution": { ... }
    }
  ],
  "unsupported": [],
  "diagnostics": []
}

The runtime assumes:

  • the contract was emitted from a semantically valid lowered basis,
  • the contract states all required assumptions explicitly,
  • the contract is family-compatible if it is to be accepted.

6. Output Contract

On success, the runtime returns an artifact conceptually equivalent to:

{
  "artifact_kind": "frog_runtime_result",
  "artifact_version": "0.1-dev",
  "backend_family": "reference_host_runtime_ui_binding",
  "contract_ref": {
    "unit_ids": ["main"]
  },
  "status": "ok",
  "execution_summary": {
    "mode": "deterministic_step_execution",
    "state_initialized": true,
    "ui_bound": false
  },
  "outputs": {
    "public": {},
    "ui": {}
  },
  "diagnostics": []
}

On rejection or failure, the runtime returns:

{
  "artifact_kind": "frog_runtime_result",
  "artifact_version": "0.1-dev",
  "backend_family": "reference_host_runtime_ui_binding",
  "status": "error",
  "error_code": "...",
  "diagnostics": [
    {
      "severity": "error",
      "message": "...",
      "source_anchor": { ... }
    }
  ]
}

The runtime must distinguish:

  • contract rejection — the contract is not acceptable for this runtime family,
  • execution failure — the contract was accepted but execution failed.

7. Runtime Strategy

The first runtime should use a strict staged strategy:

  1. confirm the contract is successful and family-compatible,
  2. check required assumptions,
  3. check unsupported declarations,
  4. create one execution session,
  5. bind public boundaries and UI boundaries,
  6. initialize explicit state,
  7. build an internal execution plan,
  8. execute one deterministic step or one simple run cycle depending on the example,
  9. collect outputs and diagnostics,
  10. return success or failure.

The first slice should prefer explicit runtime phases over aggressive optimization.


8. Runtime Phases

8.1 Contract gate

Reject the contract if:

  • the backend family does not match,
  • required assumptions are missing,
  • an unsupported feature is required for execution,
  • explicit state semantics are required but not representable,
  • a standardized UI event model is required.

8.2 Session creation

Create one runtime session for the accepted contract. This session owns:

  • boundary bindings,
  • UI bindings,
  • state cells,
  • operation table,
  • temporary values for the current deterministic step.

8.3 Boundary binding

Bind:

  • public inputs,
  • public outputs,
  • UI value inputs,
  • UI value outputs,
  • UI references.

8.4 State initialization

Create state cells for every explicit local-memory declaration and initialize them deterministically from the contract.

8.5 Plan construction

Build a simple execution plan for the first slice. For the MVP examples, a direct ordered operation list is sufficient.

8.6 Execution

Execute operations in deterministic order. For stateful examples, reads must observe the pre-step state and commits must update the next-step state only at the commit phase.

8.7 Output collection

Collect public outputs and UI-side effects into the runtime result artifact.


9. Helper Conventions

The pseudo-code below uses the following conventions:

  • ctx is a mutable runtime context.
  • ctx.errors stores hard runtime failures.
  • ctx.warnings stores optional non-fatal notes.
  • reject(...) produces an explicit contract rejection.
  • fail(...) produces an execution failure after acceptance.
  • session is the runtime execution session.
  • step_values stores transient values for the current deterministic step.

10. Pseudo-Code — Main Function

function accept_contract_and_execute(contract, runtime_inputs = {}):
    ctx = new RuntimeContext()

    ctx.backend_family = "reference_host_runtime_ui_binding"

    if contract.get("status") == "error":
        return build_runtime_error(
            ctx,
            "runtime_requires_successful_contract",
            "accept_contract_and_execute() requires a successful backend contract artifact."
        )

    if contract["backend_family"] != ctx.backend_family:
        return build_runtime_rejection(
            ctx,
            "unsupported_backend_family",
            "The contract backend family is not supported by this runtime."
        )

    acceptance = check_contract_acceptance(contract, ctx)
    if acceptance == "reject":
        return build_runtime_rejection_from_ctx(ctx, "contract_rejected")

    session = create_runtime_session(contract, runtime_inputs, ctx)
    if ctx.has_errors():
        return build_runtime_error_from_ctx(ctx, "session_creation_failed")

    initialize_state(session, contract, ctx)
    if ctx.has_errors():
        return build_runtime_error_from_ctx(ctx, "state_initialization_failed")

    bind_boundaries(session, contract, runtime_inputs, ctx)
    if ctx.has_errors():
        return build_runtime_error_from_ctx(ctx, "boundary_binding_failed")

    plan = build_execution_plan(session, contract, ctx)
    if ctx.has_errors():
        return build_runtime_error_from_ctx(ctx, "execution_plan_failed")

    execute_plan(session, plan, ctx)
    if ctx.has_errors():
        return build_runtime_error_from_ctx(ctx, "execution_failed")

    result = collect_runtime_result(session, contract, ctx)
    return result

11. Pseudo-Code — Phase Functions

11.1 Check contract acceptance

function check_contract_acceptance(contract, ctx):
    if contract["artifact_kind"] != "frog_backend_contract":
        reject(ctx,
               code = "invalid_contract_kind",
               message = "Runtime expected artifact_kind = frog_backend_contract.")
        return "reject"

    required_assumptions = ["profiles_required", "scheduling", "ui_binding", "state_model"]
    for key in required_assumptions:
        if key not in contract["assumptions"]:
            reject(ctx,
                   code = "missing_contract_assumption",
                   message = "Missing required contract assumption: " + key)
            return "reject"

    if contract["assumptions"]["scheduling"].get("family_rule") != "deterministic_step_execution":
        reject(ctx,
               code = "unsupported_scheduling_rule",
               message = "The reference runtime supports only deterministic_step_execution.")
        return "reject"

    if contract["assumptions"]["ui_binding"].get("event_model") != "not_standardized":
        reject(ctx,
               code = "unsupported_ui_event_model",
               message = "The reference runtime does not support a standardized first-class UI event model.")
        return "reject"

    if len(contract.get("unsupported", [])) > 0:
        for entry in contract["unsupported"]:
            if is_required_for_execution(entry):
                reject(ctx,
                       code = "unsupported_required_feature",
                       message = "Contract requires an unsupported feature: " + summarize_unsupported(entry))
                return "reject"

    if len(contract.get("units", [])) != 1:
        reject(ctx,
               code = "unsupported_unit_count",
               message = "The reference runtime MVP supports exactly one contract unit.")
        return "reject"

    return "accept"

function is_required_for_execution(entry):
    return true

function summarize_unsupported(entry):
    return to_string(entry.get("kind", "unknown"))

11.2 Create runtime session

function create_runtime_session(contract, runtime_inputs, ctx):
    unit = contract["units"][0]

    session = {
        "contract": contract,
        "unit": unit,
        "public_inputs": {},
        "public_outputs": {},
        "ui_value_inputs": {},
        "ui_value_outputs": {},
        "ui_references": {},
        "state_cells": {},
        "step_values": {},
        "ui_effects": [],
        "operation_results": {}
    }

    return session

11.3 Initialize state

function initialize_state(session, contract, ctx):
    for state_entry in session["unit"].get("state", []):
        if state_entry["kind"] != "explicit_local_memory":
            fail(ctx,
                 code = "unsupported_state_kind",
                 message = "Unsupported state kind in MVP runtime: " + to_string(state_entry["kind"]),
                 anchor = {"state_id": state_entry.get("id")})
            continue

        session["state_cells"][state_entry["id"]] = {
            "current": state_entry["initial"],
            "next": state_entry["initial"]
        }

11.4 Bind boundaries

function bind_boundaries(session, contract, runtime_inputs, ctx):
    for boundary in session["unit"].get("boundaries", []):
        kind = boundary["kind"]

        if kind == "public_input":
            bind_public_input(session, boundary, runtime_inputs, ctx)
            continue

        if kind == "public_output":
            bind_public_output(session, boundary, ctx)
            continue

        if kind == "ui_value_input":
            bind_ui_value_input(session, boundary, runtime_inputs, ctx)
            continue

        if kind == "ui_value_output":
            bind_ui_value_output(session, boundary, ctx)
            continue

        if kind == "ui_reference":
            bind_ui_reference(session, boundary, runtime_inputs, ctx)
            continue

        fail(ctx,
             code = "unsupported_boundary_kind",
             message = "Unsupported boundary kind in MVP runtime: " + to_string(kind),
             anchor = {"boundary_id": boundary.get("id")})

function bind_public_input(session, boundary, runtime_inputs, ctx):
    name = boundary["name"]
    if name in runtime_inputs.get("public", {}):
        session["public_inputs"][name] = runtime_inputs["public"][name]
    else:
        session["public_inputs"][name] = null

function bind_public_output(session, boundary, ctx):
    session["public_outputs"][boundary["name"]] = null

function bind_ui_value_input(session, boundary, runtime_inputs, ctx):
    widget_id = boundary["widget_id"]
    if widget_id in runtime_inputs.get("ui", {}):
        session["ui_value_inputs"][widget_id] = runtime_inputs["ui"][widget_id]
    else:
        session["ui_value_inputs"][widget_id] = null

function bind_ui_value_output(session, boundary, ctx):
    session["ui_value_outputs"][boundary["widget_id"]] = null

function bind_ui_reference(session, boundary, runtime_inputs, ctx):
    widget_id = boundary["widget_id"]
    session["ui_references"][widget_id] = make_widget_handle(widget_id)

function make_widget_handle(widget_id):
    return {
        "widget_id": widget_id,
        "handle_kind": "reference_runtime_widget_handle"
    }

11.5 Build execution plan

function build_execution_plan(session, contract, ctx):
    plan = {
        "mode": "deterministic_step_execution",
        "operations": session["unit"].get("operations", [])
    }

    return plan

For the first slice, the contract-visible operation order is assumed to be executable in order. That is a family-specific simplification, not a universal runtime rule.

11.6 Execute plan

function execute_plan(session, plan, ctx):
    for op in plan["operations"]:
        execute_single_operation(session, op, ctx)

    commit_all_state(session, ctx)

function execute_single_operation(session, op, ctx):
    kind = op["kind"]

    if kind == "core_compute":
        execute_core_compute(session, op, ctx)
        return

    if kind == "ui_operation":
        execute_ui_operation(session, op, ctx)
        return

    if kind == "state_access":
        execute_state_access(session, op, ctx)
        return

    fail(ctx,
         code = "unsupported_contract_operation",
         message = "Unsupported contract operation in MVP runtime: " + to_string(kind),
         anchor = {"operation_id": op.get("id")})

11.7 Execute core compute

function execute_core_compute(session, op, ctx):
    if op["operation"] != "frog.core.add":
        fail(ctx,
             code = "unsupported_core_compute_operation",
             message = "Unsupported core compute operation: " + to_string(op["operation"]),
             anchor = {"operation_id": op.get("id")})
        return

    inputs = resolve_add_inputs(session, ctx)
    if inputs is null:
        fail(ctx,
             code = "missing_add_inputs",
             message = "Could not resolve inputs for frog.core.add.",
             anchor = {"operation_id": op.get("id")})
        return

    result = inputs["a"] + inputs["b"]
    session["operation_results"][op["id"]] = {
        "result": result
    }

function resolve_add_inputs(session, ctx):
    # MVP example-oriented resolution:
    # - Example 01: public inputs a, b
    # - Example 02: UI value inputs ctrl_a, ctrl_b
    # - Example 04: public input x + state_read result
    #
    # The first runtime may use a simple example-compatible resolver.
    #
    # In a later iteration this should be replaced by a wire-aware local dataflow evaluator.

    if "a" in session["public_inputs"] and "b" in session["public_inputs"]:
        return {
            "a": default_zero_if_null(session["public_inputs"]["a"]),
            "b": default_zero_if_null(session["public_inputs"]["b"])
        }

    if "ctrl_a" in session["ui_value_inputs"] and "ctrl_b" in session["ui_value_inputs"]:
        return {
            "a": default_zero_if_null(session["ui_value_inputs"]["ctrl_a"]),
            "b": default_zero_if_null(session["ui_value_inputs"]["ctrl_b"])
        }

    if "x" in session["public_inputs"] and "state:last_read" in session["step_values"]:
        return {
            "a": default_zero_if_null(session["public_inputs"]["x"]),
            "b": session["step_values"]["state:last_read"]
        }

    return null

function default_zero_if_null(v):
    if v is null:
        return 0
    return v

11.8 Execute UI operations

function execute_ui_operation(session, op, ctx):
    operation = op["operation"]

    if operation == "property_write":
        execute_ui_property_write(session, op, ctx)
        return

    if operation == "property_read":
        execute_ui_property_read(session, op, ctx)
        return

    if operation == "method_invoke":
        execute_ui_method_invoke(session, op, ctx)
        return

    fail(ctx,
         code = "unsupported_ui_operation",
         message = "Unsupported UI operation: " + to_string(operation),
         anchor = {"operation_id": op.get("id")})

function execute_ui_property_write(session, op, ctx):
    ref = resolve_first_ui_reference(session)
    value = resolve_ui_property_write_value(session)

    if ref is null:
        fail(ctx,
             code = "missing_ui_reference_for_property_write",
             message = "No UI reference is available for property_write.",
             anchor = {"operation_id": op.get("id")})
        return

    session["ui_effects"].append({
        "kind": "property_write",
        "widget_id": ref["widget_id"],
        "member": op["member"],
        "value": value
    })

function execute_ui_property_read(session, op, ctx):
    ref = resolve_first_ui_reference(session)
    if ref is null:
        fail(ctx,
             code = "missing_ui_reference_for_property_read",
             message = "No UI reference is available for property_read.",
             anchor = {"operation_id": op.get("id")})
        return

    session["operation_results"][op["id"]] = {
        "value": null
    }

function execute_ui_method_invoke(session, op, ctx):
    ref = resolve_first_ui_reference(session)
    if ref is null:
        fail(ctx,
             code = "missing_ui_reference_for_method_invoke",
             message = "No UI reference is available for method_invoke.",
             anchor = {"operation_id": op.get("id")})
        return

    session["ui_effects"].append({
        "kind": "method_invoke",
        "widget_id": ref["widget_id"],
        "method": op["method"]
    })

function resolve_first_ui_reference(session):
    for widget_id in session["ui_references"]:
        return session["ui_references"][widget_id]
    return null

function resolve_ui_property_write_value(session):
    if "status" in session["public_inputs"]:
        return session["public_inputs"]["status"]
    return null

11.9 Execute state access

function execute_state_access(session, op, ctx):
    state_id = op["state_id"]

    if state_id not in session["state_cells"]:
        fail(ctx,
             code = "unknown_state_id",
             message = "Unknown state cell in runtime execution: " + state_id,
             anchor = {"operation_id": op.get("id")})
        return

    if op["operation"] == "read":
        session["step_values"]["state:last_read"] = session["state_cells"][state_id]["current"]
        return

    if op["operation"] == "commit":
        next_value = resolve_state_commit_value(session)
        session["state_cells"][state_id]["next"] = next_value
        return

    fail(ctx,
         code = "unsupported_state_access_operation",
         message = "Unsupported state access operation: " + to_string(op["operation"]),
         anchor = {"operation_id": op.get("id")})

function resolve_state_commit_value(session):
    for op_id in session["operation_results"]:
        if "result" in session["operation_results"][op_id]:
            return session["operation_results"][op_id]["result"]
    return 0

11.10 Commit state and publish outputs

function commit_all_state(session, ctx):
    for state_id in session["state_cells"]:
        session["state_cells"][state_id]["current"] = session["state_cells"][state_id]["next"]

function publish_outputs(session, ctx):
    for op_id in session["operation_results"]:
        result_record = session["operation_results"][op_id]

        if "result" in result_record:
            if "result" in session["public_outputs"]:
                session["public_outputs"]["result"] = result_record["result"]
            if "y" in session["public_outputs"]:
                session["public_outputs"]["y"] = result_record["result"]
            if "ind_result" in session["ui_value_outputs"]:
                session["ui_value_outputs"]["ind_result"] = result_record["result"]

11.11 Collect runtime result

function collect_runtime_result(session, contract, ctx):
    publish_outputs(session, ctx)

    ui_bound = (
        len(session["ui_value_inputs"]) > 0 or
        len(session["ui_value_outputs"]) > 0 or
        len(session["ui_references"]) > 0
    )

    state_initialized = len(session["state_cells"]) > 0
    state_updated = len(session["state_cells"]) > 0

    ui_outputs = {}
    for widget_id in session["ui_value_outputs"]:
        ui_outputs[widget_id] = session["ui_value_outputs"][widget_id]

    for effect in session["ui_effects"]:
        if effect["kind"] == "property_write":
            ui_outputs[effect["widget_id"] + "." + effect["member"]["part"] + "." + effect["member"]["member"]] = effect["value"]
        if effect["kind"] == "method_invoke":
            ui_outputs[effect["widget_id"] + ".method:" + effect["method"]] = "invoked"

    return {
        "artifact_kind": "frog_runtime_result",
        "artifact_version": "0.1-dev",
        "backend_family": "reference_host_runtime_ui_binding",
        "contract_ref": {
            "unit_ids": [unit["id"] for unit in contract["units"]]
        },
        "status": "ok",
        "execution_summary": {
            "mode": "deterministic_step_execution",
            "state_initialized": state_initialized,
            "state_updated": state_updated,
            "ui_bound": ui_bound
        },
        "outputs": {
            "public": session["public_outputs"],
            "ui": ui_outputs
        },
        "diagnostics": ctx.warnings
    }

11.12 Utility helpers

function reject(ctx, code, message):
    ctx.errors.append({
        "severity": "error",
        "kind": "rejection",
        "code": code,
        "message": message
    })

function fail(ctx, code, message, anchor = {}):
    ctx.errors.append({
        "severity": "error",
        "kind": "execution_failure",
        "code": code,
        "message": message,
        "source_anchor": anchor
    })

function build_runtime_rejection(ctx, code, message):
    return {
        "artifact_kind": "frog_runtime_result",
        "artifact_version": "0.1-dev",
        "backend_family": "reference_host_runtime_ui_binding",
        "status": "error",
        "error_code": code,
        "diagnostics": [
            {
                "severity": "error",
                "kind": "rejection",
                "message": message
            }
        ]
    }

function build_runtime_rejection_from_ctx(ctx, code):
    return {
        "artifact_kind": "frog_runtime_result",
        "artifact_version": "0.1-dev",
        "backend_family": "reference_host_runtime_ui_binding",
        "status": "error",
        "error_code": code,
        "diagnostics": ctx.errors + ctx.warnings
    }

function build_runtime_error(ctx, code, message):
    return {
        "artifact_kind": "frog_runtime_result",
        "artifact_version": "0.1-dev",
        "backend_family": "reference_host_runtime_ui_binding",
        "status": "error",
        "error_code": code,
        "diagnostics": [
            {
                "severity": "error",
                "kind": "execution_failure",
                "message": message
            }
        ]
    }

function build_runtime_error_from_ctx(ctx, code):
    return {
        "artifact_kind": "frog_runtime_result",
        "artifact_version": "0.1-dev",
        "backend_family": "reference_host_runtime_ui_binding",
        "status": "error",
        "error_code": code,
        "diagnostics": ctx.errors + ctx.warnings
    }

12. MVP Acceptance Rules

The first runtime must enforce at least the following acceptance rules:

  • the contract must belong to reference_host_runtime_ui_binding,
  • required assumptions must be declared explicitly,
  • deterministic step execution must be the scheduling rule,
  • a first-class standardized UI event model must not be required,
  • explicit local-memory state must be representable when declared,
  • UI reference and UI operation distinctions must not have been collapsed,
  • public boundaries and UI boundaries must remain explicit enough for binding.

13. Example Expectations

For the initial example corpus, the first runtime should handle at minimum:

  • 01_pure_addition — bind public inputs a and b, compute result, publish public output,
  • 02_ui_value_roundtrip — bind UI value inputs ctrl_a and ctrl_b, compute result, publish UI value output ind_result,
  • 03_ui_property_write — bind public input status, resolve UI reference ctrl_gain, emit property-write UI side effect for label.text,
  • 04_stateful_feedback_delay — initialize explicit state, read state, compute result, commit next state, publish public output y.

These example behaviors are sufficient to prove the end-to-end executable slice of the first reference family.


14. Summary

This document provides a directly codable MVP pseudo-code sketch for accept_contract_and_execute() in the FROG reference runtime. It closes the first executable vertical slice: backend contract in, explicit acceptance or rejection, private deterministic execution, explicit UI binding where declared, explicit state handling where required, and a runtime result artifact out.