Phase 7.1: Add MIR instructions for async operations (FutureNew, FutureSet, Await)

Co-authored-by: moe-charm <217100418+moe-charm@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-08-13 11:46:01 +00:00
parent 3ebb30221b
commit b59f0ee419
3 changed files with 109 additions and 1 deletions

View File

@ -41,6 +41,7 @@ pub enum VMValue {
Float(f64),
Bool(bool),
String(String),
Future(crate::boxes::future::FutureBox),
Void,
}
@ -52,6 +53,7 @@ impl VMValue {
VMValue::Float(f) => Box::new(StringBox::new(&f.to_string())), // Simplified for now
VMValue::Bool(b) => Box::new(BoolBox::new(*b)),
VMValue::String(s) => Box::new(StringBox::new(s)),
VMValue::Future(f) => Box::new(f.clone()),
VMValue::Void => Box::new(VoidBox::new()),
}
}
@ -63,6 +65,7 @@ impl VMValue {
VMValue::Float(f) => f.to_string(),
VMValue::Bool(b) => b.to_string(),
VMValue::String(s) => s.clone(),
VMValue::Future(f) => f.to_string_box().value,
VMValue::Void => "void".to_string(),
}
}
@ -83,6 +86,23 @@ impl VMValue {
_ => Err(VMError::TypeError(format!("Expected bool, got {:?}", self))),
}
}
/// Convert from NyashBox to VMValue
pub fn from_nyash_box(nyash_box: Box<dyn crate::box_trait::NyashBox>) -> VMValue {
// Try to downcast to known types
if let Some(int_box) = nyash_box.as_any().downcast_ref::<IntegerBox>() {
VMValue::Integer(int_box.value)
} else if let Some(bool_box) = nyash_box.as_any().downcast_ref::<BoolBox>() {
VMValue::Bool(bool_box.value)
} else if let Some(string_box) = nyash_box.as_any().downcast_ref::<StringBox>() {
VMValue::String(string_box.value.clone())
} else if let Some(future_box) = nyash_box.as_any().downcast_ref::<crate::boxes::future::FutureBox>() {
VMValue::Future(future_box.clone())
} else {
// For any other type, convert to string representation
VMValue::String(nyash_box.to_string_box().value)
}
}
}
impl From<&ConstValue> for VMValue {
@ -439,6 +459,43 @@ impl VM {
// In a real implementation, this would ensure memory ordering
Ok(ControlFlow::Continue)
},
// Phase 7: Async/Future Operations
MirInstruction::FutureNew { dst, value } => {
let initial_value = self.get_value(*value)?;
let future = crate::boxes::future::FutureBox::new();
// Convert VMValue to NyashBox and set it in the future
future.set_result(initial_value.to_nyash_box());
self.values.insert(*dst, VMValue::Future(future));
Ok(ControlFlow::Continue)
},
MirInstruction::FutureSet { future, value } => {
let future_val = self.get_value(*future)?;
let new_value = self.get_value(*value)?;
if let VMValue::Future(ref future_box) = future_val {
future_box.set_result(new_value.to_nyash_box());
Ok(ControlFlow::Continue)
} else {
Err(VMError::TypeError(format!("Expected Future, got {:?}", future_val)))
}
},
MirInstruction::Await { dst, future } => {
let future_val = self.get_value(*future)?;
if let VMValue::Future(ref future_box) = future_val {
// This blocks until the future is ready
let result = future_box.get();
// Convert NyashBox back to VMValue
let vm_value = VMValue::from_nyash_box(result);
self.values.insert(*dst, vm_value);
Ok(ControlFlow::Continue)
} else {
Err(VMError::TypeError(format!("Expected Future, got {:?}", future_val)))
}
},
}
}

View File

@ -250,6 +250,29 @@ pub enum MirInstruction {
BarrierWrite {
ptr: ValueId,
},
// === Phase 7: Async/Future Operations ===
/// Create a new Future with initial value
/// `%dst = future_new %value`
FutureNew {
dst: ValueId,
value: ValueId,
},
/// Set Future value and mark as ready
/// `future_set %future = %value`
FutureSet {
future: ValueId,
value: ValueId,
},
/// Wait for Future completion and get value
/// `%dst = await %future`
Await {
dst: ValueId,
future: ValueId,
},
}
/// Constant values in MIR
@ -304,6 +327,7 @@ pub enum MirType {
String,
Box(String), // Box type with name
Array(Box<MirType>),
Future(Box<MirType>), // Future containing a type
Void,
Unknown,
}
@ -360,6 +384,11 @@ impl MirInstruction {
MirInstruction::WeakLoad { .. } => EffectMask::READ, // Loading weak ref has read effects
MirInstruction::BarrierRead { .. } => EffectMask::READ.add(Effect::Barrier), // Memory barrier with read
MirInstruction::BarrierWrite { .. } => EffectMask::WRITE.add(Effect::Barrier), // Memory barrier with write
// Phase 7: Async/Future Operations
MirInstruction::FutureNew { .. } => EffectMask::PURE.add(Effect::Alloc), // Creating future may allocate
MirInstruction::FutureSet { .. } => EffectMask::WRITE, // Setting future has write effects
MirInstruction::Await { .. } => EffectMask::READ.add(Effect::Async), // Await blocks and reads
}
}
@ -380,7 +409,9 @@ impl MirInstruction {
MirInstruction::RefNew { dst, .. } |
MirInstruction::RefGet { dst, .. } |
MirInstruction::WeakNew { dst, .. } |
MirInstruction::WeakLoad { dst, .. } => Some(*dst),
MirInstruction::WeakLoad { dst, .. } |
MirInstruction::FutureNew { dst, .. } |
MirInstruction::Await { dst, .. } => Some(*dst),
MirInstruction::Call { dst, .. } |
MirInstruction::BoxCall { dst, .. } => *dst,
@ -396,6 +427,7 @@ impl MirInstruction {
MirInstruction::RefSet { .. } |
MirInstruction::BarrierRead { .. } |
MirInstruction::BarrierWrite { .. } |
MirInstruction::FutureSet { .. } |
MirInstruction::Safepoint |
MirInstruction::Nop => None,
@ -463,6 +495,11 @@ impl MirInstruction {
MirInstruction::WeakLoad { weak_ref, .. } => vec![*weak_ref],
MirInstruction::BarrierRead { ptr } => vec![*ptr],
MirInstruction::BarrierWrite { ptr } => vec![*ptr],
// Phase 7: Async/Future Operations
MirInstruction::FutureNew { value, .. } => vec![*value],
MirInstruction::FutureSet { future, value } => vec![*future, *value],
MirInstruction::Await { future, .. } => vec![*future],
}
}
}

View File

@ -347,6 +347,19 @@ impl MirPrinter {
MirInstruction::BarrierWrite { ptr } => {
format!("barrier_write {}", ptr)
},
// Phase 7: Async/Future Operations
MirInstruction::FutureNew { dst, value } => {
format!("{} = future_new {}", dst, value)
},
MirInstruction::FutureSet { future, value } => {
format!("future_set {} = {}", future, value)
},
MirInstruction::Await { dst, future } => {
format!("{} = await {}", dst, future)
},
}
}
@ -359,6 +372,7 @@ impl MirPrinter {
super::MirType::String => "str".to_string(),
super::MirType::Box(name) => format!("box<{}>", name),
super::MirType::Array(elem_type) => format!("[{}]", self.format_type(elem_type)),
super::MirType::Future(inner_type) => format!("future<{}>", self.format_type(inner_type)),
super::MirType::Void => "void".to_string(),
super::MirType::Unknown => "?".to_string(),
}