Skip to main content

voce_compiler_hybrid/
lib.rs

1//! Voce IR Hybrid Compiler — orchestrates DOM, WebGPU, and WASM compilers.
2//!
3//! Analyzes each IR node to determine the optimal compile target:
4//! - Layout nodes (Container, Surface, TextNode) → DOM
5//! - 3D nodes (Scene3D, MeshNode, ParticleSystem) → WebGPU
6//! - Compute-heavy nodes (complex StateMachine, ComputeNode) → WASM
7//!
8//! Produces a unified HTML output with embedded DOM + WebGPU canvas + WASM module.
9
10pub mod analysis;
11pub mod bundle;
12pub mod device;
13pub mod fallback;
14
15use anyhow::Result;
16
17/// Hybrid compilation options.
18#[derive(Debug, Clone)]
19pub struct HybridCompileOptions {
20    /// Device profile for target selection.
21    pub device: device::DeviceProfile,
22    /// Force a specific target for all nodes (overrides analysis).
23    pub force_target: Option<CompileTarget>,
24}
25
26impl Default for HybridCompileOptions {
27    fn default() -> Self {
28        Self {
29            device: device::DeviceProfile::desktop(),
30            force_target: None,
31        }
32    }
33}
34
35/// Possible compilation targets for a node.
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum CompileTarget {
38    Dom,
39    WebGpu,
40    Wasm,
41}
42
43/// Result of hybrid compilation.
44#[derive(Debug)]
45pub struct HybridCompileResult {
46    /// The unified HTML output.
47    pub html: String,
48    /// Size in bytes.
49    pub size_bytes: usize,
50    /// Per-target breakdown.
51    pub target_summary: TargetSummary,
52}
53
54/// Summary of what was compiled to each target.
55#[derive(Debug, Default)]
56pub struct TargetSummary {
57    pub dom_nodes: usize,
58    pub webgpu_nodes: usize,
59    pub wasm_functions: usize,
60}
61
62/// Compile IR with automatic per-component target selection.
63pub fn compile_hybrid(json: &str, options: &HybridCompileOptions) -> Result<HybridCompileResult> {
64    // Phase 1: Analyze each node's optimal target
65    let node_targets = analysis::analyze_targets(json, &options.device, options.force_target)?;
66
67    // Phase 2: Compile DOM nodes
68    let dom_result = voce_compiler_dom::compile(
69        json,
70        &voce_compiler_dom::CompileOptions::default(),
71    )?;
72
73    // Phase 3: Check for WebGPU/WASM nodes
74    let has_webgpu = node_targets.iter().any(|t| t.target == CompileTarget::WebGpu);
75    let has_wasm = node_targets.iter().any(|t| t.target == CompileTarget::Wasm);
76
77    let wasm_result = if has_wasm {
78        Some(voce_compiler_wasm::compile_to_wat(json)?)
79    } else {
80        None
81    };
82
83    let webgpu_result = if has_webgpu {
84        Some(voce_compiler_webgpu::compile_webgpu(
85            json,
86            &voce_compiler_webgpu::WebGpuCompileOptions::default(),
87        )?)
88    } else {
89        None
90    };
91
92    // Phase 4: Bundle into unified output
93    let html = bundle::bundle(
94        &dom_result.html,
95        webgpu_result.as_ref().map(|r| r.html.as_str()),
96        wasm_result.as_ref().map(|r| r.js_bridge.as_str()),
97    );
98
99    let size_bytes = html.len();
100
101    let target_summary = TargetSummary {
102        dom_nodes: node_targets.iter().filter(|t| t.target == CompileTarget::Dom).count(),
103        webgpu_nodes: node_targets.iter().filter(|t| t.target == CompileTarget::WebGpu).count(),
104        wasm_functions: wasm_result.as_ref().map_or(0, |r| r.function_count),
105    };
106
107    Ok(HybridCompileResult {
108        html,
109        size_bytes,
110        target_summary,
111    })
112}