feat(joinir): Phase 52-53 LoopFrontendBinding JSON + Statement Handlers
Phase 52: LoopFrontendBinding JSON generation fixes - Add receiver_to_json() for Field node structure (me.tokens) - Add needs_me_receiver() for instance method detection - Fix "condition" → "cond" key for JoinIR Frontend - Add me parameter propagation in loop_patterns.rs - Add JoinIR-compatible type fields in ast_json.rs - Variable → "type": "Var" - Literal → "type": "Int"/"Bool" (literal_to_joinir_json) - BinaryOp → "type": "Binary"/"Compare" (is_compare_op) - MethodCall → "type": "Method" Phase 53: Statement Handler module for loop body - NEW: stmt_handlers.rs with StatementEffect type - Support: Local, Assignment, Print, Method, If statements - If lowering: single variable update → Select instruction - Remove hardcoded assert in loop_patterns.rs - Replace with generic lower_statement() calls Test results: 56 JoinIR tests PASS, 7 loop_frontend_binding tests PASS 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -79,19 +79,36 @@ pub fn ast_to_json(ast: &ASTNode) -> Value {
|
||||
"static": is_static,
|
||||
"override": is_override,
|
||||
}),
|
||||
ASTNode::Variable { name, .. } => json!({"kind":"Variable","name":name}),
|
||||
ASTNode::Literal { value, .. } => json!({"kind":"Literal","value": lit_to_json(&value)}),
|
||||
// Phase 52: Variable → Var ノード(JoinIR Frontend 互換)
|
||||
ASTNode::Variable { name, .. } => json!({
|
||||
"kind": "Variable",
|
||||
"type": "Var", // JoinIR Frontend expects "type": "Var"
|
||||
"name": name
|
||||
}),
|
||||
// Phase 52: Literal → Int/Bool/String ノード(JoinIR Frontend 互換)
|
||||
ASTNode::Literal { value, .. } => literal_to_joinir_json(&value),
|
||||
// Phase 52: BinaryOp → Binary/Compare ノード(JoinIR Frontend 互換)
|
||||
ASTNode::BinaryOp {
|
||||
operator,
|
||||
left,
|
||||
right,
|
||||
..
|
||||
} => json!({
|
||||
"kind":"BinaryOp",
|
||||
"op": bin_to_str(&operator),
|
||||
"left": ast_to_json(&left),
|
||||
"right": ast_to_json(&right),
|
||||
}),
|
||||
} => {
|
||||
let op_str = bin_to_str(&operator);
|
||||
// JoinIR Frontend distinguishes between Binary (arithmetic) and Compare
|
||||
let type_str = if is_compare_op(&operator) { "Compare" } else { "Binary" };
|
||||
json!({
|
||||
"kind": "BinaryOp",
|
||||
"type": type_str,
|
||||
"op": op_str,
|
||||
// JoinIR Frontend expects "lhs"/"rhs" not "left"/"right"
|
||||
"lhs": ast_to_json(&left),
|
||||
"rhs": ast_to_json(&right),
|
||||
// Also keep "left"/"right" for backward compatibility
|
||||
"left": ast_to_json(&left),
|
||||
"right": ast_to_json(&right),
|
||||
})
|
||||
}
|
||||
ASTNode::UnaryOp {
|
||||
operator, operand, ..
|
||||
} => json!({
|
||||
@ -99,16 +116,22 @@ pub fn ast_to_json(ast: &ASTNode) -> Value {
|
||||
"op": un_to_str(&operator),
|
||||
"operand": ast_to_json(&operand),
|
||||
}),
|
||||
// Phase 52: MethodCall → Method ノード(JoinIR Frontend 互換)
|
||||
ASTNode::MethodCall {
|
||||
object,
|
||||
method,
|
||||
arguments,
|
||||
..
|
||||
} => json!({
|
||||
"kind":"MethodCall",
|
||||
"object": ast_to_json(&object),
|
||||
"kind": "MethodCall",
|
||||
"type": "Method", // JoinIR Frontend expects "type": "Method"
|
||||
// JoinIR Frontend expects "receiver" not "object"
|
||||
"receiver": ast_to_json(&object),
|
||||
"object": ast_to_json(&object), // Keep for backward compatibility
|
||||
"method": method,
|
||||
"arguments": arguments.into_iter().map(|a| ast_to_json(&a)).collect::<Vec<_>>()
|
||||
// JoinIR Frontend expects "args" not "arguments"
|
||||
"args": arguments.iter().map(|a| ast_to_json(a)).collect::<Vec<_>>(),
|
||||
"arguments": arguments.into_iter().map(|a| ast_to_json(&a)).collect::<Vec<_>>() // Keep for backward compatibility
|
||||
}),
|
||||
ASTNode::FunctionCall {
|
||||
name, arguments, ..
|
||||
@ -142,6 +165,28 @@ pub fn ast_to_json(ast: &ASTNode) -> Value {
|
||||
})).collect::<Vec<_>>(),
|
||||
"else": ast_to_json(&else_expr),
|
||||
}),
|
||||
// Phase 52: FieldAccess → Field ノード(JoinIR Frontend 互換)
|
||||
ASTNode::FieldAccess { object, field, .. } => json!({
|
||||
"kind": "FieldAccess",
|
||||
"type": "Field", // JoinIR Frontend expects "type": "Field"
|
||||
"object": ast_to_json(&object),
|
||||
"field": field
|
||||
}),
|
||||
// Phase 52: Me → Var("me") ノード(JoinIR Frontend 互換)
|
||||
ASTNode::Me { .. } => json!({
|
||||
"kind": "Me",
|
||||
"type": "Var", // JoinIR Frontend expects "type": "Var"
|
||||
"name": "me"
|
||||
}),
|
||||
// Phase 52: New → NewBox ノード(JoinIR Frontend 互換)
|
||||
ASTNode::New {
|
||||
class, arguments, ..
|
||||
} => json!({
|
||||
"kind": "New",
|
||||
"type": "NewBox", // JoinIR Frontend expects "type": "NewBox"
|
||||
"box_name": class,
|
||||
"args": arguments.into_iter().map(|a| ast_to_json(&a)).collect::<Vec<_>>()
|
||||
}),
|
||||
other => json!({"kind":"Unsupported","debug": format!("{:?}", other)}),
|
||||
}
|
||||
}
|
||||
@ -459,3 +504,55 @@ fn str_to_un(s: &str) -> Option<UnaryOperator> {
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Phase 52: Check if a binary operator is a comparison operator
|
||||
fn is_compare_op(op: &BinaryOperator) -> bool {
|
||||
matches!(
|
||||
op,
|
||||
BinaryOperator::Equal
|
||||
| BinaryOperator::NotEqual
|
||||
| BinaryOperator::Less
|
||||
| BinaryOperator::Greater
|
||||
| BinaryOperator::LessEqual
|
||||
| BinaryOperator::GreaterEqual
|
||||
)
|
||||
}
|
||||
|
||||
/// Phase 52: Convert a literal value to JoinIR-compatible JSON format
|
||||
///
|
||||
/// JoinIR Frontend expects:
|
||||
/// - Integer: {"type": "Int", "value": <number>}
|
||||
/// - Boolean: {"type": "Bool", "value": <bool>}
|
||||
/// - String: {"type": "String", "value": <string>}
|
||||
fn literal_to_joinir_json(v: &LiteralValue) -> Value {
|
||||
match v {
|
||||
LiteralValue::Integer(i) => json!({
|
||||
"kind": "Literal",
|
||||
"type": "Int", // JoinIR Frontend expects "type": "Int"
|
||||
"value": i
|
||||
}),
|
||||
LiteralValue::Bool(b) => json!({
|
||||
"kind": "Literal",
|
||||
"type": "Bool", // JoinIR Frontend expects "type": "Bool"
|
||||
"value": b
|
||||
}),
|
||||
LiteralValue::String(s) => json!({
|
||||
"kind": "Literal",
|
||||
"type": "String",
|
||||
"value": s
|
||||
}),
|
||||
LiteralValue::Float(f) => json!({
|
||||
"kind": "Literal",
|
||||
"type": "Float",
|
||||
"value": f
|
||||
}),
|
||||
LiteralValue::Null => json!({
|
||||
"kind": "Literal",
|
||||
"type": "Null"
|
||||
}),
|
||||
LiteralValue::Void => json!({
|
||||
"kind": "Literal",
|
||||
"type": "Void"
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user