@@ -783,6 +783,146 @@ let verify_cmd =
783783 let info = Cmd. info " verify" ~doc ~man in
784784 Cmd. v info Term. (ret (const verify_file $ face_arg $ path_arg))
785785
786+ (* * {1 Stage 10: typed-wasm interface extraction subcommand} *)
787+
788+ (* * Print the ownership-annotated export interface of a generated bridge module.
789+
790+ Generates the selected module ([tea-bridge] or [router]) in-memory, extracts
791+ its [affinescript.ownership] section, and prints the per-export ownership
792+ contract: which parameters are [own] (Linear), [ref] (SharedBorrow), [mut]
793+ (ExclBorrow), or plain [val] (Unrestricted).
794+
795+ This is the machine-readable boundary contract that any caller (JS bridge,
796+ another Wasm module, or a future Wasm-to-Wasm linker) must honour to preserve
797+ the typed-wasm Level 7/10 guarantees across the module boundary.
798+
799+ Usage: affinescript interface [--which tea-bridge|router|all] *)
800+ let interface_cmd_fn which =
801+ let show_for name m =
802+ let iface = Affinescript.Tw_interface. extract_exports m in
803+ Format. printf " === %s ===@." name;
804+ Affinescript.Tw_interface. pp_interface Format. std_formatter iface;
805+ Format. printf " @."
806+ in
807+ (match which with
808+ | `TeaBridge ->
809+ show_for " tea-bridge" (Affinescript.Tea_bridge. generate () )
810+ | `Router ->
811+ show_for " router" (Affinescript.Tea_router. generate () )
812+ | `All ->
813+ show_for " tea-bridge" (Affinescript.Tea_bridge. generate () );
814+ show_for " router" (Affinescript.Tea_router. generate () ));
815+ `Ok ()
816+
817+ (* * {1 Stage 10: typed-wasm cross-module boundary verifier subcommand} *)
818+
819+ (* * Build a synthetic well-formed caller module that imports a single
820+ function (type: [i32 → ()]) at import slot 0 and calls it exactly once
821+ from its sole local function.
822+
823+ This is the minimal "correct caller" used to demonstrate that the
824+ cross-module verifier accepts a Linear-param import called once per path.
825+ The import is named [fn_name] and sourced from module [mod_name]. *)
826+ let make_linear_caller mod_name fn_name : Affinescript.Wasm.wasm_module =
827+ let import = Affinescript.Wasm. {
828+ i_module = mod_name;
829+ i_name = fn_name;
830+ i_desc = ImportFunc 0 ;
831+ } in
832+ let caller_fn = Affinescript.Wasm. {
833+ f_type = 0 ;
834+ f_locals = [] ;
835+ f_body = [ I32Const 0l ; Call 0 ];
836+ } in
837+ { (Affinescript.Wasm. empty_module () ) with
838+ Affinescript.Wasm. types = [{ ft_params = [I32 ]; ft_results = [] }];
839+ Affinescript.Wasm. imports = [import];
840+ Affinescript.Wasm. funcs = [caller_fn];
841+ }
842+
843+ (* * Verify typed-wasm Level 7/10 cross-module boundary constraints.
844+
845+ Generates the selected callee module, extracts its ownership-annotated
846+ export interface, then verifies a synthetic caller module against it.
847+ The synthetic caller imports each Linear-param export and calls it exactly
848+ once — this is the correct usage pattern that the verifier must accept.
849+
850+ For the [router] callee, additionally verifies that [fn_push]'s explicit
851+ else-drop (Stage 9 fix) is reflected cleanly in the interface.
852+
853+ Exit 0 = no violations. Exit 1 = violations found.
854+
855+ Usage: affinescript verify-bridge [--which tea-bridge|router|all] *)
856+ let verify_boundary_fn which =
857+ let verify_one name callee_mod fn_name =
858+ let iface = Affinescript.Tw_interface. extract_exports callee_mod in
859+ let caller = make_linear_caller name fn_name in
860+ Format. printf " === %s — boundary check for '%s' ===@." name fn_name;
861+ (match Affinescript.Tw_interface. verify_cross_module iface caller with
862+ | Ok () ->
863+ Affinescript.Tw_interface. pp_cross_report Format. std_formatter [] ;
864+ | Error errs ->
865+ Affinescript.Tw_interface. pp_cross_report Format. std_formatter errs)
866+ in
867+ (match which with
868+ | `TeaBridge ->
869+ verify_one " tea-bridge"
870+ (Affinescript.Tea_bridge. generate () )
871+ " affinescript_tea_update"
872+ | `Router ->
873+ verify_one " router"
874+ (Affinescript.Tea_router. generate () )
875+ " affinescript_router_push"
876+ | `All ->
877+ verify_one " tea-bridge"
878+ (Affinescript.Tea_bridge. generate () )
879+ " affinescript_tea_update" ;
880+ verify_one " router"
881+ (Affinescript.Tea_router. generate () )
882+ " affinescript_router_push" );
883+ `Ok ()
884+
885+ let which_arg =
886+ let which = Arg. enum [
887+ (" tea-bridge" , `TeaBridge );
888+ (" router" , `Router );
889+ (" all" , `All );
890+ ] in
891+ Arg. (value & opt which `All & info [" which" ]
892+ ~docv: " MODULE"
893+ ~doc: " Which bridge module to operate on: $(b,tea-bridge), $(b,router), or $(b,all) (default)." )
894+
895+ let interface_cmd =
896+ let doc = " Print the ownership-annotated export interface of a generated bridge module" in
897+ let man = [
898+ `S " DESCRIPTION" ;
899+ `P " Extracts the $(b,affinescript.ownership) custom section from the selected \
900+ generated Wasm module and prints the per-export ownership contract." ;
901+ `P " Parameters are annotated: $(b,own) = Linear (consumed exactly once), \
902+ $(b,ref) = SharedBorrow (read-only), $(b,mut) = ExclBorrow (exclusive \
903+ mutable reference), $(b,val) = Unrestricted (unconstrained)." ;
904+ `P " This is the typed-wasm boundary contract that any caller — JS bridge, \
905+ a Wasm linker, or a future multi-module composition tool — must honour \
906+ to preserve Level 7/10 guarantees across the module boundary." ;
907+ ] in
908+ let info = Cmd. info " interface" ~doc ~man in
909+ Cmd. v info Term. (ret (const interface_cmd_fn $ which_arg))
910+
911+ let verify_bridge_cmd =
912+ let doc = " Verify cross-module typed-wasm boundary constraints" in
913+ let man = [
914+ `S " DESCRIPTION" ;
915+ `P " Generates the selected bridge module, extracts its ownership-annotated \
916+ export interface, and verifies that a well-formed synthetic caller module \
917+ (one that imports a Linear-param export and calls it exactly once per \
918+ execution path) passes Level 7/10 cross-module boundary checking." ;
919+ `P " This complements the intra-module $(b,verify) subcommand by checking the \
920+ boundary between the AffineScript-generated module and its callers." ;
921+ `P " Exit 0 = boundary clean. Exit 1 = violations found." ;
922+ ] in
923+ let info = Cmd. info " verify-bridge" ~doc ~man in
924+ Cmd. v info Term. (ret (const verify_boundary_fn $ which_arg))
925+
786926let repl_cmd =
787927 let doc = " Start the interactive REPL" in
788928 let info = Cmd. info " repl" ~doc in
@@ -994,6 +1134,7 @@ let default_cmd =
9941134 lex_cmd; parse_cmd; check_cmd; eval_cmd; repl_cmd; compile_cmd;
9951135 fmt_cmd; lint_cmd;
9961136 tea_bridge_cmd; router_bridge_cmd; verify_cmd;
1137+ interface_cmd; verify_bridge_cmd;
9971138 hover_cmd; goto_def_cmd; complete_cmd; server_cmd;
9981139 preview_python_cmd; preview_js_cmd; preview_pseudocode_cmd
9991140 ]
0 commit comments