Phase 8.4: Complete AST→MIR Lowering - Basic object operations implemented
Co-authored-by: moe-charm <217100418+moe-charm@users.noreply.github.com>
This commit is contained in:
@ -122,6 +122,18 @@ impl MirBuilder {
|
|||||||
self.build_variable_access(name.clone())
|
self.build_variable_access(name.clone())
|
||||||
},
|
},
|
||||||
|
|
||||||
|
ASTNode::Me { .. } => {
|
||||||
|
self.build_me_expression()
|
||||||
|
},
|
||||||
|
|
||||||
|
ASTNode::MethodCall { object, method, arguments, .. } => {
|
||||||
|
self.build_method_call(*object.clone(), method.clone(), arguments.clone())
|
||||||
|
},
|
||||||
|
|
||||||
|
ASTNode::FromCall { parent, method, arguments, .. } => {
|
||||||
|
self.build_from_expression(parent.clone(), method.clone(), arguments.clone())
|
||||||
|
},
|
||||||
|
|
||||||
ASTNode::Assignment { target, value, .. } => {
|
ASTNode::Assignment { target, value, .. } => {
|
||||||
// Check if target is a field access for RefSet
|
// Check if target is a field access for RefSet
|
||||||
if let ASTNode::FieldAccess { object, field, .. } = target.as_ref() {
|
if let ASTNode::FieldAccess { object, field, .. } = target.as_ref() {
|
||||||
@ -186,12 +198,20 @@ impl MirBuilder {
|
|||||||
self.build_local_statement(variables.clone(), initial_values.clone())
|
self.build_local_statement(variables.clone(), initial_values.clone())
|
||||||
},
|
},
|
||||||
|
|
||||||
// Handle static box Main declarations
|
ASTNode::BoxDeclaration { name, methods, is_static, fields, .. } => {
|
||||||
ASTNode::BoxDeclaration { name, methods, is_static, .. } => {
|
|
||||||
if is_static && name == "Main" {
|
if is_static && name == "Main" {
|
||||||
self.build_static_main_box(methods.clone())
|
self.build_static_main_box(methods.clone())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("BoxDeclaration support is currently limited to static box Main"))
|
// Support user-defined boxes - handle as statement, return void
|
||||||
|
self.build_box_declaration(name.clone(), methods.clone(), fields.clone())?;
|
||||||
|
|
||||||
|
// Return a void value since this is a statement
|
||||||
|
let void_val = self.value_gen.next();
|
||||||
|
self.emit_instruction(MirInstruction::Const {
|
||||||
|
dst: void_val,
|
||||||
|
value: ConstValue::Void,
|
||||||
|
})?;
|
||||||
|
Ok(void_val)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -815,6 +835,113 @@ impl MirBuilder {
|
|||||||
|
|
||||||
Ok(result_id)
|
Ok(result_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Build me expression: me
|
||||||
|
fn build_me_expression(&mut self) -> Result<ValueId, String> {
|
||||||
|
// For now, return a reference to the current instance
|
||||||
|
// In a full implementation, this would resolve to the actual instance reference
|
||||||
|
let me_value = self.value_gen.next();
|
||||||
|
|
||||||
|
// For simplicity, emit a constant representing "me"
|
||||||
|
// In practice, this should resolve to the current instance context
|
||||||
|
self.emit_instruction(MirInstruction::Const {
|
||||||
|
dst: me_value,
|
||||||
|
value: ConstValue::String("__me__".to_string()),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(me_value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build method call: object.method(arguments)
|
||||||
|
fn build_method_call(&mut self, object: ASTNode, method: String, arguments: Vec<ASTNode>) -> Result<ValueId, String> {
|
||||||
|
// Build the object expression
|
||||||
|
let object_value = self.build_expression(object)?;
|
||||||
|
|
||||||
|
// Build argument expressions
|
||||||
|
let mut arg_values = Vec::new();
|
||||||
|
for arg in arguments {
|
||||||
|
arg_values.push(self.build_expression(arg)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create result value
|
||||||
|
let result_id = self.value_gen.next();
|
||||||
|
|
||||||
|
// Emit a BoxCall instruction
|
||||||
|
self.emit_instruction(MirInstruction::BoxCall {
|
||||||
|
dst: Some(result_id),
|
||||||
|
box_val: object_value,
|
||||||
|
method,
|
||||||
|
args: arg_values,
|
||||||
|
effects: EffectMask::READ.add(Effect::ReadHeap), // Method calls may have side effects
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(result_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build from expression: from Parent.method(arguments)
|
||||||
|
fn build_from_expression(&mut self, parent: String, method: String, arguments: Vec<ASTNode>) -> Result<ValueId, String> {
|
||||||
|
// Build argument expressions
|
||||||
|
let mut arg_values = Vec::new();
|
||||||
|
for arg in arguments {
|
||||||
|
arg_values.push(self.build_expression(arg)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a synthetic "parent reference" value
|
||||||
|
let parent_value = self.value_gen.next();
|
||||||
|
self.emit_instruction(MirInstruction::Const {
|
||||||
|
dst: parent_value,
|
||||||
|
value: ConstValue::String(parent),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Create result value
|
||||||
|
let result_id = self.value_gen.next();
|
||||||
|
|
||||||
|
// Emit a BoxCall instruction for delegation
|
||||||
|
self.emit_instruction(MirInstruction::BoxCall {
|
||||||
|
dst: Some(result_id),
|
||||||
|
box_val: parent_value,
|
||||||
|
method,
|
||||||
|
args: arg_values,
|
||||||
|
effects: EffectMask::READ.add(Effect::ReadHeap),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(result_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build box declaration: box Name { fields... methods... }
|
||||||
|
fn build_box_declaration(&mut self, name: String, methods: std::collections::HashMap<String, ASTNode>, fields: Vec<String>) -> Result<(), String> {
|
||||||
|
// For Phase 8.4, we'll emit metadata instructions to register the box type
|
||||||
|
// In a full implementation, this would register type information for later use
|
||||||
|
|
||||||
|
// Create a type registration constant
|
||||||
|
let type_id = self.value_gen.next();
|
||||||
|
self.emit_instruction(MirInstruction::Const {
|
||||||
|
dst: type_id,
|
||||||
|
value: ConstValue::String(format!("__box_type_{}", name)),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// For each field, emit metadata about the field
|
||||||
|
for field in fields {
|
||||||
|
let field_id = self.value_gen.next();
|
||||||
|
self.emit_instruction(MirInstruction::Const {
|
||||||
|
dst: field_id,
|
||||||
|
value: ConstValue::String(format!("__field_{}_{}", name, field)),
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process methods - now methods is a HashMap
|
||||||
|
for (method_name, method_ast) in methods {
|
||||||
|
if let ASTNode::FunctionDeclaration { .. } = method_ast {
|
||||||
|
let method_id = self.value_gen.next();
|
||||||
|
self.emit_instruction(MirInstruction::Const {
|
||||||
|
dst: method_id,
|
||||||
|
value: ConstValue::String(format!("__method_{}_{}", name, method_name)),
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper enum for binary operator classification
|
/// Helper enum for binary operator classification
|
||||||
|
|||||||
32
test_delegation_basic.nyash
Normal file
32
test_delegation_basic.nyash
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
box Parent {
|
||||||
|
init { name }
|
||||||
|
|
||||||
|
pack(n) {
|
||||||
|
me.name = n
|
||||||
|
}
|
||||||
|
|
||||||
|
greet() {
|
||||||
|
return "Hello " + me.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box Child from Parent {
|
||||||
|
init { age }
|
||||||
|
|
||||||
|
pack(n, a) {
|
||||||
|
from Parent.pack(n)
|
||||||
|
me.age = a
|
||||||
|
}
|
||||||
|
|
||||||
|
override greet() {
|
||||||
|
local base = from Parent.greet()
|
||||||
|
return base + " (age " + me.age + ")"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static box Main {
|
||||||
|
main() {
|
||||||
|
local c = new Child("Alice", 25)
|
||||||
|
return c.greet()
|
||||||
|
}
|
||||||
|
}
|
||||||
19
test_field_operations.nyash
Normal file
19
test_field_operations.nyash
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
box Counter {
|
||||||
|
init { count }
|
||||||
|
|
||||||
|
pack() {
|
||||||
|
me.count = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
increment() {
|
||||||
|
me.count = me.count + 1
|
||||||
|
return me.count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static box Main {
|
||||||
|
main() {
|
||||||
|
local c = new Counter()
|
||||||
|
return c.increment()
|
||||||
|
}
|
||||||
|
}
|
||||||
5
test_static_main_compatibility.nyash
Normal file
5
test_static_main_compatibility.nyash
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
static box Main {
|
||||||
|
main() {
|
||||||
|
return 42
|
||||||
|
}
|
||||||
|
}
|
||||||
14
test_user_defined_box.nyash
Normal file
14
test_user_defined_box.nyash
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
box DataBox {
|
||||||
|
init { value }
|
||||||
|
|
||||||
|
pack(v) {
|
||||||
|
me.value = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static box Main {
|
||||||
|
main() {
|
||||||
|
local obj = new DataBox(42)
|
||||||
|
return obj.value
|
||||||
|
}
|
||||||
|
}
|
||||||
19
test_wasm_box_integration.nyash
Normal file
19
test_wasm_box_integration.nyash
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
box SimpleData {
|
||||||
|
init { x, y }
|
||||||
|
|
||||||
|
pack(a, b) {
|
||||||
|
me.x = a
|
||||||
|
me.y = b
|
||||||
|
}
|
||||||
|
|
||||||
|
sum() {
|
||||||
|
return me.x + me.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static box Main {
|
||||||
|
main() {
|
||||||
|
local data = new SimpleData(10, 20)
|
||||||
|
return data.sum()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user