feat(joinir): Phase 54 AST→JSON JoinIR-compatible statement fields
Add JoinIR-compatible fields to statement JSON output in ast_json.rs: - Assignment: "type": "Assignment", "target" (string), "expr" alias - Print: "type": "Print", "expr" alias - Local: "type": "Local", "name", "expr" (for single-variable case) - If: "type": "If", "cond" alias - Loop: "type": "Loop", "cond" alias - Return: "type": "Return" This enables the stmt_handlers.rs (Phase 53) to correctly parse statements from control_flow.rs loop body JSON. Test results: JoinIR 56 PASS, loop_frontend_binding 7 PASS 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -7,37 +7,78 @@ pub fn ast_to_json(ast: &ASTNode) -> Value {
|
|||||||
"kind": "Program",
|
"kind": "Program",
|
||||||
"statements": statements.into_iter().map(|s| ast_to_json(&s)).collect::<Vec<_>>()
|
"statements": statements.into_iter().map(|s| ast_to_json(&s)).collect::<Vec<_>>()
|
||||||
}),
|
}),
|
||||||
|
// Phase 54: Loop with JoinIR-compatible fields
|
||||||
ASTNode::Loop {
|
ASTNode::Loop {
|
||||||
condition, body, ..
|
condition, body, ..
|
||||||
} => json!({
|
} => json!({
|
||||||
"kind": "Loop",
|
"kind": "Loop",
|
||||||
|
"type": "Loop", // JoinIR Frontend expects "type"
|
||||||
"condition": ast_to_json(&condition),
|
"condition": ast_to_json(&condition),
|
||||||
|
"cond": ast_to_json(&condition), // JoinIR expects "cond"
|
||||||
"body": body.into_iter().map(|s| ast_to_json(&s)).collect::<Vec<_>>()
|
"body": body.into_iter().map(|s| ast_to_json(&s)).collect::<Vec<_>>()
|
||||||
}),
|
}),
|
||||||
|
// Phase 54: Print with JoinIR-compatible fields
|
||||||
ASTNode::Print { expression, .. } => json!({
|
ASTNode::Print { expression, .. } => json!({
|
||||||
"kind": "Print",
|
"kind": "Print",
|
||||||
|
"type": "Print", // JoinIR Frontend expects "type"
|
||||||
"expression": ast_to_json(&expression),
|
"expression": ast_to_json(&expression),
|
||||||
|
"expr": ast_to_json(&expression), // JoinIR expects "expr"
|
||||||
}),
|
}),
|
||||||
|
// Phase 54: Return with JoinIR-compatible fields
|
||||||
ASTNode::Return { value, .. } => json!({
|
ASTNode::Return { value, .. } => json!({
|
||||||
"kind": "Return",
|
"kind": "Return",
|
||||||
|
"type": "Return", // JoinIR Frontend expects "type"
|
||||||
"value": value.as_ref().map(|v| ast_to_json(v)),
|
"value": value.as_ref().map(|v| ast_to_json(v)),
|
||||||
}),
|
}),
|
||||||
ASTNode::Break { .. } => json!({"kind":"Break"}),
|
ASTNode::Break { .. } => json!({"kind":"Break"}),
|
||||||
ASTNode::Continue { .. } => json!({"kind":"Continue"}),
|
ASTNode::Continue { .. } => json!({"kind":"Continue"}),
|
||||||
ASTNode::Assignment { target, value, .. } => json!({
|
// 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",
|
"kind": "Assignment",
|
||||||
"target": ast_to_json(&target),
|
"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),
|
"value": ast_to_json(&value),
|
||||||
}),
|
"expr": ast_to_json(&value), // JoinIR expects "expr"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// Phase 54: Local with JoinIR-compatible fields
|
||||||
ASTNode::Local {
|
ASTNode::Local {
|
||||||
variables,
|
variables,
|
||||||
initial_values,
|
initial_values,
|
||||||
..
|
..
|
||||||
} => json!({
|
} => {
|
||||||
|
// 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",
|
"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,
|
"variables": variables,
|
||||||
"inits": initial_values.into_iter().map(|opt| opt.map(|v| ast_to_json(&v))).collect::<Vec<_>>()
|
"inits": inits
|
||||||
}),
|
})
|
||||||
|
}
|
||||||
|
// Phase 54: If with JoinIR-compatible fields
|
||||||
ASTNode::If {
|
ASTNode::If {
|
||||||
condition,
|
condition,
|
||||||
then_body,
|
then_body,
|
||||||
@ -45,7 +86,9 @@ pub fn ast_to_json(ast: &ASTNode) -> Value {
|
|||||||
..
|
..
|
||||||
} => json!({
|
} => json!({
|
||||||
"kind": "If",
|
"kind": "If",
|
||||||
|
"type": "If", // JoinIR Frontend expects "type"
|
||||||
"condition": ast_to_json(&condition),
|
"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::<Vec<_>>(),
|
"then": then_body.into_iter().map(|s| ast_to_json(&s)).collect::<Vec<_>>(),
|
||||||
"else": else_body.map(|v| v.into_iter().map(|s| ast_to_json(&s)).collect::<Vec<_>>()),
|
"else": else_body.map(|v| v.into_iter().map(|s| ast_to_json(&s)).collect::<Vec<_>>()),
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user