diff --git a/src/macro/ast_json.rs b/src/macro/ast_json.rs index 321ddb8c..ac8af02e 100644 --- a/src/macro/ast_json.rs +++ b/src/macro/ast_json.rs @@ -7,37 +7,78 @@ pub fn ast_to_json(ast: &ASTNode) -> Value { "kind": "Program", "statements": statements.into_iter().map(|s| ast_to_json(&s)).collect::>() }), + // Phase 54: Loop with JoinIR-compatible fields ASTNode::Loop { condition, body, .. } => json!({ "kind": "Loop", + "type": "Loop", // JoinIR Frontend expects "type" "condition": ast_to_json(&condition), + "cond": ast_to_json(&condition), // JoinIR expects "cond" "body": body.into_iter().map(|s| ast_to_json(&s)).collect::>() }), + // Phase 54: Print with JoinIR-compatible fields ASTNode::Print { expression, .. } => json!({ "kind": "Print", + "type": "Print", // JoinIR Frontend expects "type" "expression": ast_to_json(&expression), + "expr": ast_to_json(&expression), // JoinIR expects "expr" }), + // Phase 54: Return with JoinIR-compatible fields ASTNode::Return { value, .. } => json!({ "kind": "Return", + "type": "Return", // JoinIR Frontend expects "type" "value": value.as_ref().map(|v| ast_to_json(v)), }), ASTNode::Break { .. } => json!({"kind":"Break"}), ASTNode::Continue { .. } => json!({"kind":"Continue"}), - ASTNode::Assignment { target, value, .. } => json!({ - "kind": "Assignment", - "target": ast_to_json(&target), - "value": ast_to_json(&value), - }), + // Phase 54: Assignment with JoinIR-compatible fields + ASTNode::Assignment { target, value, .. } => { + // Extract variable name if target is a simple Variable + let target_str = match target.as_ref() { + ASTNode::Variable { name, .. } => name.clone(), + _ => "complex".to_string(), // FieldAccess or other complex target + }; + json!({ + "kind": "Assignment", + "type": "Assignment", // JoinIR Frontend expects "type" + "target": target_str, // JoinIR expects string variable name + "lhs": ast_to_json(&target), // Keep full AST for complex cases + "value": ast_to_json(&value), + "expr": ast_to_json(&value), // JoinIR expects "expr" + }) + } + // Phase 54: Local with JoinIR-compatible fields ASTNode::Local { variables, initial_values, .. - } => json!({ - "kind": "Local", - "variables": variables, - "inits": initial_values.into_iter().map(|opt| opt.map(|v| ast_to_json(&v))).collect::>() - }), + } => { + // For single-variable declarations, add "name" and "expr" for JoinIR compatibility + let (name, expr) = if variables.len() == 1 { + let n = variables[0].clone(); + let e = initial_values.get(0) + .and_then(|opt| opt.as_ref()) + .map(|v| ast_to_json(v)); + (Some(n), e) + } else { + (None, None) + }; + + let inits: Vec<_> = initial_values.into_iter() + .map(|opt| opt.map(|v| ast_to_json(&v))) + .collect(); + + json!({ + "kind": "Local", + "type": "Local", // JoinIR Frontend expects "type" + "name": name, // Single variable name for JoinIR (null if multiple) + "expr": expr, // Single variable init for JoinIR (null if multiple) + "variables": variables, + "inits": inits + }) + } + // Phase 54: If with JoinIR-compatible fields ASTNode::If { condition, then_body, @@ -45,7 +86,9 @@ pub fn ast_to_json(ast: &ASTNode) -> Value { .. } => json!({ "kind": "If", + "type": "If", // JoinIR Frontend expects "type" "condition": ast_to_json(&condition), + "cond": ast_to_json(&condition), // JoinIR expects "cond" "then": then_body.into_iter().map(|s| ast_to_json(&s)).collect::>(), "else": else_body.map(|v| v.into_iter().map(|s| ast_to_json(&s)).collect::>()), }),