dol 0.8.1

DOL (Design Ontology Language) - A declarative specification language for ontology-first development
// Effect System Prelude Test: Messaging Functions Available
// ==========================================================
//
// What this test validates:
//   - All standard messaging prelude functions are available
//   - Messaging functions are correctly typed and callable
//   - Msg effect is properly attributed to prelude functions
//   - Actor communication primitives are covered
//
// Expected effect inference results:
//   - All @msg.* functions should be Effectful(Msg)

gene Prelude.Msg.Test @0.1.0 {
    """
    Tests availability and effect inference of messaging prelude functions.
    """

    // Test: @msg.send - send message to actor
    fn test_send(target: ActorId, message: Any) -> Unit {
        @msg.send(target, message)
    }

    // Test: @msg.recv - receive next message (blocking)
    fn test_recv() -> Any {
        @msg.recv()
    }

    // Test: @msg.try_recv - non-blocking receive
    fn test_try_recv() -> Option[Any] {
        @msg.try_recv()
    }

    // Test: @msg.recv_timeout - receive with timeout
    fn test_recv_timeout(timeout_ms: Int) -> Option[Any] {
        @msg.recv_timeout(timeout_ms)
    }

    // Test: @msg.pending - check for pending messages
    fn test_pending() -> Bool {
        @msg.pending()
    }

    // Test: @msg.self - get own actor ID
    fn test_self() -> ActorId {
        @msg.self()
    }

    // Test: @msg.broadcast - send to all actors
    fn test_broadcast(message: Any) -> Unit {
        @msg.broadcast(message)
    }

    // Test: @msg.spawn - create new actor
    fn test_spawn(gene_ref: Gene) -> ActorId {
        @msg.spawn(gene_ref)
    }

    // Test: @msg.spawn_link - spawn and link
    fn test_spawn_link(gene_ref: Gene) -> ActorId {
        @msg.spawn_link(gene_ref)
    }

    // Test: @msg.link - link to existing actor
    fn test_link(target: ActorId) -> Unit {
        @msg.link(target)
    }

    // Test: @msg.unlink - remove link
    fn test_unlink(target: ActorId) -> Unit {
        @msg.unlink(target)
    }

    // Test: @msg.monitor - monitor actor
    fn test_monitor(target: ActorId) -> MonitorRef {
        @msg.monitor(target)
    }

    // Test: @msg.demonitor - stop monitoring
    fn test_demonitor(ref: MonitorRef) -> Unit {
        @msg.demonitor(ref)
    }

    // Test: @msg.exit - terminate actor
    fn test_exit(reason: Any) -> Never {
        @msg.exit(reason)
    }

    // Test: @msg.subscribe - subscribe to topic
    fn test_subscribe(topic: String) -> Unit {
        @msg.subscribe(topic)
    }

    // Test: @msg.unsubscribe - unsubscribe from topic
    fn test_unsubscribe(topic: String) -> Unit {
        @msg.unsubscribe(topic)
    }

    // Test: @msg.publish - publish to topic
    fn test_publish(topic: String, message: Any) -> Unit {
        @msg.publish(topic, message)
    }

    // Combined usage test - request/response pattern
    fn test_request_response(target: ActorId, request: Any) -> Any {
        let my_id = @msg.self();
        @msg.send(target, { from: my_id, payload: request });
        loop {
            let response = @msg.recv();
            if response.to == my_id {
                return response.payload
            }
        }
    }

    // Combined usage test - selective receive
    fn test_selective_recv(msg_type: String) -> Any {
        loop {
            let msg = @msg.recv();
            if msg.type == msg_type {
                return msg
            }
            // Requeue non-matching messages
            @msg.requeue(msg)
        }
    }

    // Test: @msg.requeue - put message back in queue
    fn test_requeue(message: Any) -> Unit {
        @msg.requeue(message)
    }

    // Test: @msg.current_sender - get sender of current message
    fn test_current_sender() -> ActorId {
        @msg.current_sender()
    }

    // Test: @msg.registered - get registered name
    fn test_registered(name: String) -> Option[ActorId] {
        @msg.registered(name)
    }

    // Test: @msg.register - register with name
    fn test_register(name: String) -> Unit {
        @msg.register(name)
    }

    // Test: @msg.unregister - remove registration
    fn test_unregister(name: String) -> Unit {
        @msg.unregister(name)
    }
}

// Test assertions for prelude availability and effects
test prelude_msg {
    // Core messaging - all Effectful(Msg)
    assert_effectful(Prelude.Msg.Test.test_send, Msg);
    assert_effectful(Prelude.Msg.Test.test_recv, Msg);
    assert_effectful(Prelude.Msg.Test.test_try_recv, Msg);
    assert_effectful(Prelude.Msg.Test.test_recv_timeout, Msg);
    assert_effectful(Prelude.Msg.Test.test_pending, Msg);
    assert_effectful(Prelude.Msg.Test.test_self, Msg);
    assert_effectful(Prelude.Msg.Test.test_broadcast, Msg);

    // Actor lifecycle - all Effectful(Msg)
    assert_effectful(Prelude.Msg.Test.test_spawn, Msg);
    assert_effectful(Prelude.Msg.Test.test_spawn_link, Msg);
    assert_effectful(Prelude.Msg.Test.test_link, Msg);
    assert_effectful(Prelude.Msg.Test.test_unlink, Msg);
    assert_effectful(Prelude.Msg.Test.test_monitor, Msg);
    assert_effectful(Prelude.Msg.Test.test_demonitor, Msg);
    assert_effectful(Prelude.Msg.Test.test_exit, Msg);

    // Pub/sub - all Effectful(Msg)
    assert_effectful(Prelude.Msg.Test.test_subscribe, Msg);
    assert_effectful(Prelude.Msg.Test.test_unsubscribe, Msg);
    assert_effectful(Prelude.Msg.Test.test_publish, Msg);

    // Combined patterns - all Effectful(Msg)
    assert_effectful(Prelude.Msg.Test.test_request_response, Msg);
    assert_effectful(Prelude.Msg.Test.test_selective_recv, Msg);
    assert_effectful(Prelude.Msg.Test.test_requeue, Msg);
    assert_effectful(Prelude.Msg.Test.test_current_sender, Msg);

    // Registration - all Effectful(Msg)
    assert_effectful(Prelude.Msg.Test.test_registered, Msg);
    assert_effectful(Prelude.Msg.Test.test_register, Msg);
    assert_effectful(Prelude.Msg.Test.test_unregister, Msg);

    // Type signatures
    assert_signature(@msg.send, Fn(ActorId, Any) -> Unit);
    assert_signature(@msg.recv, Fn() -> Any);
    assert_signature(@msg.try_recv, Fn() -> Option[Any]);
    assert_signature(@msg.pending, Fn() -> Bool);
    assert_signature(@msg.self, Fn() -> ActorId);
    assert_signature(@msg.spawn, Fn(Gene) -> ActorId);
}