Skip to main content

parallax_puir/
lib.rs

1//! Parallax Universal Intermediate Representation (PUIR).
2//!
3//! PUIR represents **language-neutral program semantics** (intent), not syntax.
4//! Distinct from PIR (values), PCIR (suspended control), and UES (execution state).
5
6#![deny(unsafe_code)]
7#![warn(missing_docs)]
8
9mod expr;
10mod item;
11mod stmt;
12mod types;
13mod version;
14
15pub use expr::Expr;
16pub use item::{Function, Module, Parameter, PuirItem, TypeDef, Visibility};
17pub use stmt::Stmt;
18pub use types::{PuirType, TypeEvidence, TypeInferenceBundle, TypeInferenceReport};
19pub use version::{check_puir_schema, PUIR_SCHEMA_VERSION};
20
21use indexmap::IndexMap;
22use parallax_core::{ErrorCode, ParallaxError};
23use serde::{Deserialize, Serialize};
24
25/// Source location preserved for diagnostics and `.plxmap` origin lookup.
26#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
27pub struct SourceSpan {
28    /// Path relative to project root.
29    pub file: String,
30    /// 1-based start line.
31    pub line: u32,
32    /// 1-based start column.
33    pub column: u32,
34    /// Optional end line.
35    pub end_line: Option<u32>,
36    /// Optional end column.
37    pub end_column: Option<u32>,
38}
39
40impl SourceSpan {
41    /// Construct a point span.
42    pub fn new(file: impl Into<String>, line: u32, column: u32) -> Self {
43        Self {
44            file: file.into(),
45            line,
46            column,
47            end_line: None,
48            end_column: None,
49        }
50    }
51}
52
53/// Confidence attached to a translated region.
54#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
55#[serde(rename_all = "snake_case")]
56pub enum Confidence {
57    /// Bit-for-bit or proven-equivalent semantics.
58    Exact,
59    /// High confidence idiomatic translation.
60    High,
61    /// Plausible but not fully verified.
62    Medium,
63    /// Ambiguous; needs review.
64    Low,
65    /// Cannot be represented.
66    Unsupported,
67}
68
69impl Confidence {
70    /// Numeric score in `[0.0, 1.0]` for aggregation (Unsupported = 0).
71    pub fn score(self) -> f64 {
72        match self {
73            Self::Exact => 1.0,
74            Self::High => 0.95,
75            Self::Medium => 0.75,
76            Self::Low => 0.45,
77            Self::Unsupported => 0.0,
78        }
79    }
80
81    /// Compact label.
82    pub fn label(self) -> &'static str {
83        match self {
84            Self::Exact => "EXACT",
85            Self::High => "HIGH",
86            Self::Medium => "MEDIUM",
87            Self::Low => "LOW",
88            Self::Unsupported => "UNSUPPORTED",
89        }
90    }
91}
92
93/// A complete PUIR program (one or more modules).
94#[derive(Clone, Debug, Serialize, Deserialize)]
95pub struct PuirProgram {
96    /// Schema version.
97    pub version: u32,
98    /// Modules keyed by stable module id / path.
99    pub modules: IndexMap<String, Module>,
100    /// Free-form metadata.
101    pub metadata: IndexMap<String, serde_json::Value>,
102}
103
104impl PuirProgram {
105    /// Empty program at current schema version.
106    pub fn new() -> Self {
107        Self {
108            version: PUIR_SCHEMA_VERSION,
109            modules: IndexMap::new(),
110            metadata: IndexMap::new(),
111        }
112    }
113
114    /// Validate schema version.
115    pub fn validate(&self) -> Result<(), ParallaxError> {
116        check_puir_schema(self.version)
117    }
118}
119
120impl Default for PuirProgram {
121    fn default() -> Self {
122        Self::new()
123    }
124}
125
126/// Stable node id within a PUIR graph (for source maps / repair).
127#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
128#[serde(transparent)]
129pub struct NodeId(pub u64);
130
131impl NodeId {
132    /// Create from raw.
133    pub const fn new(id: u64) -> Self {
134        Self(id)
135    }
136}
137
138/// Effect flags for functions / regions.
139#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
140pub struct Effects {
141    /// May perform I/O.
142    pub io: bool,
143    /// May await async operations.
144    pub async_: bool,
145    /// May throw / return error.
146    pub throws: bool,
147    /// May read environment / config.
148    pub env: bool,
149    /// May access filesystem.
150    pub fs: bool,
151    /// May perform network.
152    pub network: bool,
153}
154
155/// Helper to build a schema error.
156pub fn schema_error(msg: impl Into<String>) -> ParallaxError {
157    ParallaxError::new(ErrorCode::InvalidArgument, msg)
158        .with_source("parallax-puir")
159        .with_operation("validate")
160}