Skip to content

(feat) AST->HIR Code prep #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 23 additions & 21 deletions optd-core/src/bridge/from_cir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub(crate) fn partial_logical_to_value(plan: &PartialLogicalPlan) -> Value {
match plan {
PartialLogicalPlan::UnMaterialized(group_id) => {
// For unmaterialized logical operators, we create a `Value` with the group ID.
Value(Logical(UnMaterialized(hir::GroupId(group_id.0))))
Value::new(Logical(UnMaterialized(hir::GroupId(group_id.0))))
}
PartialLogicalPlan::Materialized(node) => {
// For materialized logical operators, we create a `Value` with the operator data.
Expand All @@ -24,7 +24,7 @@ pub(crate) fn partial_logical_to_value(plan: &PartialLogicalPlan) -> Value {
children: convert_children_to_values(&node.children, partial_logical_to_value),
};

Value(Logical(Materialized(LogicalOp::logical(operator))))
Value::new(Logical(Materialized(LogicalOp::logical(operator))))
}
}
}
Expand All @@ -35,7 +35,7 @@ pub(crate) fn partial_physical_to_value(plan: &PartialPhysicalPlan) -> Value {
PartialPhysicalPlan::UnMaterialized(goal) => {
// For unmaterialized physical operators, we create a `Value` with the goal
let hir_goal = cir_goal_to_hir(goal);
Value(Physical(UnMaterialized(hir_goal)))
Value::new(Physical(UnMaterialized(hir_goal)))
}
PartialPhysicalPlan::Materialized(node) => {
// For materialized physical operators, we create a Value with the operator data
Expand All @@ -45,7 +45,7 @@ pub(crate) fn partial_physical_to_value(plan: &PartialPhysicalPlan) -> Value {
children: convert_children_to_values(&node.children, partial_physical_to_value),
};

Value(Physical(Materialized(PhysicalOp::physical(operator))))
Value::new(Physical(Materialized(PhysicalOp::physical(operator))))
}
}
}
Expand All @@ -54,9 +54,9 @@ pub(crate) fn partial_physical_to_value(plan: &PartialPhysicalPlan) -> Value {
/// Converts a [`PartialPhysicalPlan`] with its cost into a [`Value`].
pub(crate) fn costed_physical_to_value(plan: PartialPhysicalPlan, cost: Cost) -> Value {
let operator = partial_physical_to_value(&plan);
Value(Tuple(vec![
Value::new(Tuple(vec![
partial_physical_to_value(&plan),
Value(Literal(Float64(cost.0))),
Value::new(Literal(Float64(cost.0))),
]))
}

Expand All @@ -65,15 +65,15 @@ pub(crate) fn costed_physical_to_value(plan: PartialPhysicalPlan, cost: Cost) ->
pub(crate) fn logical_properties_to_value(properties: &LogicalProperties) -> Value {
match &properties.0 {
Some(data) => properties_data_to_value(data),
Option::None => Value(None),
Option::None => Value::new(None),
}
}

/// Converts [`PhysicalProperties`] into a [`Value`].
pub(crate) fn physical_properties_to_value(properties: &PhysicalProperties) -> Value {
match &properties.0 {
Some(data) => properties_data_to_value(data),
Option::None => Value(None),
Option::None => Value::new(None),
}
}

Expand Down Expand Up @@ -104,7 +104,7 @@ where
.map(|child| match child {
Child::Singleton(item) => converter(item),
Child::VarLength(items) => {
Value(Array(items.iter().map(|item| converter(item)).collect()))
Value::new(Array(items.iter().map(|item| converter(item)).collect()))
}
})
.collect()
Expand All @@ -118,32 +118,34 @@ fn convert_operator_data_to_values(data: &[OperatorData]) -> Vec<Value> {
/// Converts an [`OperatorData`] into a [`Value`].
fn operator_data_to_value(data: &OperatorData) -> Value {
match data {
OperatorData::Int64(i) => Value(Literal(Int64(*i))),
OperatorData::Float64(f) => Value(Literal(Float64(**f))),
OperatorData::String(s) => Value(Literal(String(s.clone()))),
OperatorData::Bool(b) => Value(Literal(Bool(*b))),
OperatorData::Struct(name, elements) => Value(Struct(
OperatorData::Int64(i) => Value::new(Literal(Int64(*i))),
OperatorData::Float64(f) => Value::new(Literal(Float64(**f))),
OperatorData::String(s) => Value::new(Literal(String(s.clone()))),
OperatorData::Bool(b) => Value::new(Literal(Bool(*b))),
OperatorData::Struct(name, elements) => Value::new(Struct(
name.clone(),
convert_operator_data_to_values(elements),
)),
OperatorData::Array(elements) => Value(Array(convert_operator_data_to_values(elements))),
OperatorData::Array(elements) => {
Value::new(Array(convert_operator_data_to_values(elements)))
}
}
}

/// Converts a [`PropertiesData`] into a [`Value`].
fn properties_data_to_value(data: &PropertiesData) -> Value {
match data {
PropertiesData::Int64(i) => Value(Literal(Int64(*i))),
PropertiesData::Float64(f) => Value(Literal(Float64(**f))),
PropertiesData::String(s) => Value(Literal(String(s.clone()))),
PropertiesData::Bool(b) => Value(Literal(Bool(*b))),
PropertiesData::Int64(i) => Value::new(Literal(Int64(*i))),
PropertiesData::Float64(f) => Value::new(Literal(Float64(**f))),
PropertiesData::String(s) => Value::new(Literal(String(s.clone()))),
PropertiesData::Bool(b) => Value::new(Literal(Bool(*b))),
PropertiesData::Struct(name, elements) => {
let values = elements.iter().map(properties_data_to_value).collect();
Value(Struct(name.clone(), values))
Value::new(Struct(name.clone(), values))
}
PropertiesData::Array(elements) => {
let values = elements.iter().map(properties_data_to_value).collect();
Value(Array(values))
Value::new(Array(values))
}
}
}
33 changes: 18 additions & 15 deletions optd-core/src/bridge/into_cir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::sync::Arc;
///
/// Panics if the [`Value`] is not a [`Logical`] variant.
pub(crate) fn value_to_partial_logical(value: &Value) -> PartialLogicalPlan {
match &value.0 {
match &value.data {
Logical(logical_op) => match logical_op {
UnMaterialized(group_id) => {
PartialLogicalPlan::UnMaterialized(hir_group_id_to_cir(group_id))
Expand All @@ -28,7 +28,7 @@ pub(crate) fn value_to_partial_logical(value: &Value) -> PartialLogicalPlan {
),
}),
},
_ => panic!("Expected Logical CoreData variant, found: {:?}", value.0),
_ => panic!("Expected Logical CoreData variant, found: {:?}", value.data),
}
}

Expand All @@ -38,7 +38,7 @@ pub(crate) fn value_to_partial_logical(value: &Value) -> PartialLogicalPlan {
///
/// Panics if the [`Value`] is not a [`Physical`] variant.
pub(crate) fn value_to_partial_physical(value: &Value) -> PartialPhysicalPlan {
match &value.0 {
match &value.data {
Physical(physical_op) => match physical_op {
UnMaterialized(hir_goal) => {
PartialPhysicalPlan::UnMaterialized(hir_goal_to_cir(hir_goal))
Expand All @@ -52,7 +52,10 @@ pub(crate) fn value_to_partial_physical(value: &Value) -> PartialPhysicalPlan {
),
}),
},
_ => panic!("Expected Physical CoreData variant, found: {:?}", value.0),
_ => panic!(
"Expected Physical CoreData variant, found: {:?}",
value.data
),
}
}

Expand All @@ -62,23 +65,23 @@ pub(crate) fn value_to_partial_physical(value: &Value) -> PartialPhysicalPlan {
///
/// Panics if the [`Value`] is not a [`Literal`] variant with a [`Float64`] value.
pub(crate) fn value_to_cost(value: &Value) -> Cost {
match &value.0 {
match &value.data {
Literal(Float64(f)) => Cost(*f),
_ => panic!("Expected Float64 literal, found: {:?}", value.0),
_ => panic!("Expected Float64 literal, found: {:?}", value.data),
}
}

/// Converts an HIR properties [`Value`] into a CIR [`LogicalProperties`].
pub(crate) fn value_to_logical_properties(properties_value: &Value) -> LogicalProperties {
match &properties_value.0 {
match &properties_value.data {
None => LogicalProperties(Option::None),
_ => LogicalProperties(Some(value_to_properties_data(properties_value))),
}
}

/// Convert an HIR properties [`Value`] into a CIR [`PhysicalProperties`].
fn value_to_physical_properties(properties_value: &Value) -> PhysicalProperties {
match &properties_value.0 {
match &properties_value.data {
None => PhysicalProperties(Option::None),
_ => PhysicalProperties(Some(value_to_properties_data(properties_value))),
}
Expand Down Expand Up @@ -108,7 +111,7 @@ pub(crate) fn hir_goal_to_cir(hir_goal: &hir::Goal) -> Goal {
/// Panics if the [`Value`] is not a [`Logical`] variant or if the [`Logical`] variant is not a
/// [`Materialized`] variant.
fn value_to_logical(value: &Value) -> LogicalPlan {
match &value.0 {
match &value.data {
Logical(logical_op) => match logical_op {
UnMaterialized(_) => {
panic!("Cannot convert UnMaterialized LogicalOperator to LogicalPlan")
Expand All @@ -119,7 +122,7 @@ fn value_to_logical(value: &Value) -> LogicalPlan {
children: convert_values_to_children(&log_op.operator.children, value_to_logical),
}),
},
_ => panic!("Expected Logical CoreData variant, found: {:?}", value.0),
_ => panic!("Expected Logical CoreData variant, found: {:?}", value.data),
}
}

Expand All @@ -132,7 +135,7 @@ where
{
values
.iter()
.map(|value| match &value.0 {
.map(|value| match &value.data {
Array(elements) => VarLength(
elements
.iter()
Expand Down Expand Up @@ -160,7 +163,7 @@ fn convert_values_to_properties_data(values: &[Value]) -> Vec<PropertiesData> {
///
/// Panics if the [`Value`] cannot be converted to [`OperatorData`], such as a [`Unit`] literal.
fn value_to_operator_data(value: &Value) -> OperatorData {
match &value.0 {
match &value.data {
Literal(constant) => match constant {
Int64(i) => OperatorData::Int64(*i),
Float64(f) => OperatorData::Float64((*f).into()),
Expand All @@ -172,7 +175,7 @@ fn value_to_operator_data(value: &Value) -> OperatorData {
Struct(name, elements) => {
OperatorData::Struct(name.clone(), convert_values_to_operator_data(elements))
}
_ => panic!("Cannot convert {:?} to OperatorData", value.0),
_ => panic!("Cannot convert {:?} to OperatorData", value.data),
}
}

Expand All @@ -182,7 +185,7 @@ fn value_to_operator_data(value: &Value) -> OperatorData {
///
/// Panics if the [`Value`] cannot be converted to [`PropertiesData`], such as a [`Unit`] literal.
fn value_to_properties_data(value: &Value) -> PropertiesData {
match &value.0 {
match &value.data {
Literal(constant) => match constant {
Int64(i) => PropertiesData::Int64(*i),
Float64(f) => PropertiesData::Float64((*f).into()),
Expand All @@ -194,6 +197,6 @@ fn value_to_properties_data(value: &Value) -> PropertiesData {
Struct(name, elements) => {
PropertiesData::Struct(name.clone(), convert_values_to_properties_data(elements))
}
_ => panic!("Cannot convert {:?} to PropertyData content", value.0),
_ => panic!("Cannot convert {:?} to PropertyData content", value.data),
}
}
18 changes: 9 additions & 9 deletions optd-dsl/src/analyzer/context.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::hir::Identifier;
use super::hir::{ExprMetadata, Identifier, NoMetadata};
use crate::analyzer::hir::Value;
use std::{collections::HashMap, sync::Arc};

Expand All @@ -12,15 +12,15 @@ use std::{collections::HashMap, sync::Arc};
/// The current (innermost) scope is mutable, while all previous scopes
/// are immutable and stored as Arc for efficient cloning.
#[derive(Debug, Clone, Default)]
pub struct Context {
pub struct Context<M: ExprMetadata = NoMetadata> {
/// Previous scopes (outer lexical scopes), stored as immutable Arc references
previous_scopes: Vec<Arc<HashMap<Identifier, Value>>>,
previous_scopes: Vec<Arc<HashMap<Identifier, Value<M>>>>,

/// Current scope (innermost) that can be directly modified
current_scope: HashMap<Identifier, Value>,
current_scope: HashMap<Identifier, Value<M>>,
}

impl Context {
impl<M: ExprMetadata> Context<M> {
/// Creates a new context with the given initial bindings as the global scope.
///
/// # Arguments
Expand All @@ -30,7 +30,7 @@ impl Context {
/// # Returns
///
/// A new `Context` instance with one scope containing the initial bindings
pub fn new(initial_bindings: HashMap<Identifier, Value>) -> Self {
pub fn new(initial_bindings: HashMap<Identifier, Value<M>>) -> Self {
Self {
previous_scopes: Vec::new(),
current_scope: initial_bindings,
Expand Down Expand Up @@ -59,7 +59,7 @@ impl Context {
/// # Returns
///
/// Some reference to the value if found, None otherwise
pub fn lookup(&self, name: &str) -> Option<&Value> {
pub fn lookup(&self, name: &str) -> Option<&Value<M>> {
// First check the current scope
if let Some(value) = self.current_scope.get(name) {
return Some(value);
Expand All @@ -84,7 +84,7 @@ impl Context {
/// # Arguments
///
/// * `other` - The context to merge from (consumed by this operation)
pub fn merge(&mut self, other: Context) {
pub fn merge(&mut self, other: Context<M>) {
// Move bindings from other's current scope into our current scope
for (name, val) in other.current_scope {
self.current_scope.insert(name, val);
Expand All @@ -100,7 +100,7 @@ impl Context {
///
/// * `name` - The name of the variable to bind
/// * `val` - The value to bind to the variable
pub fn bind(&mut self, name: String, val: Value) {
pub fn bind(&mut self, name: String, val: Value<M>) {
self.current_scope.insert(name, val);
}
}
Loading