chore: Phase 25.1 完了 - LoopForm v2/Stage1 CLI/環境変数削減 + Phase 26-D からの変更
Phase 25.1 完了成果: - ✅ LoopForm v2 テスト・ドキュメント・コメント完備 - 4ケース(A/B/C/D)完全テストカバレッジ - 最小再現ケース作成(SSAバグ調査用) - SSOT文書作成(loopform_ssot.md) - 全ソースに [LoopForm] コメントタグ追加 - ✅ Stage-1 CLI デバッグ環境構築 - stage1_cli.hako 実装 - stage1_bridge.rs ブリッジ実装 - デバッグツール作成(stage1_debug.sh/stage1_minimal.sh) - アーキテクチャ改善提案文書 - ✅ 環境変数削減計画策定 - 25変数の完全調査・分類 - 6段階削減ロードマップ(25→5、80%削減) - 即時削除可能変数特定(NYASH_CONFIG/NYASH_DEBUG) Phase 26-D からの累積変更: - PHI実装改善(ExitPhiBuilder/HeaderPhiBuilder等) - MIRビルダーリファクタリング - 型伝播・最適化パス改善 - その他約300ファイルの累積変更 🎯 技術的成果: - SSAバグ根本原因特定(条件分岐内loop変数変更) - Region+next_iパターン適用完了(UsingCollectorBox等) - LoopFormパターン文書化・テスト化完了 - セルフホスティング基盤強化 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: ChatGPT <noreply@openai.com> Co-Authored-By: Task Assistant <task@anthropic.com>
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
use nyash_rust::ast::{ASTNode, BinaryOperator, LiteralValue, Span, UnaryOperator};
|
||||
use serde_json::{json, Value};
|
||||
use nyash_rust::ast::{ASTNode, LiteralValue, BinaryOperator, UnaryOperator, Span};
|
||||
|
||||
pub fn ast_to_json(ast: &ASTNode) -> Value {
|
||||
match ast.clone() {
|
||||
@ -7,7 +7,9 @@ pub fn ast_to_json(ast: &ASTNode) -> Value {
|
||||
"kind": "Program",
|
||||
"statements": statements.into_iter().map(|s| ast_to_json(&s)).collect::<Vec<_>>()
|
||||
}),
|
||||
ASTNode::Loop { condition, body, .. } => json!({
|
||||
ASTNode::Loop {
|
||||
condition, body, ..
|
||||
} => json!({
|
||||
"kind": "Loop",
|
||||
"condition": ast_to_json(&condition),
|
||||
"body": body.into_iter().map(|s| ast_to_json(&s)).collect::<Vec<_>>()
|
||||
@ -27,18 +29,32 @@ pub fn ast_to_json(ast: &ASTNode) -> Value {
|
||||
"target": ast_to_json(&target),
|
||||
"value": ast_to_json(&value),
|
||||
}),
|
||||
ASTNode::Local { variables, initial_values, .. } => json!({
|
||||
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::<Vec<_>>()
|
||||
}),
|
||||
ASTNode::If { condition, then_body, else_body, .. } => json!({
|
||||
ASTNode::If {
|
||||
condition,
|
||||
then_body,
|
||||
else_body,
|
||||
..
|
||||
} => json!({
|
||||
"kind": "If",
|
||||
"condition": ast_to_json(&condition),
|
||||
"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<_>>()),
|
||||
}),
|
||||
ASTNode::TryCatch { try_body, catch_clauses, finally_body, .. } => json!({
|
||||
ASTNode::TryCatch {
|
||||
try_body,
|
||||
catch_clauses,
|
||||
finally_body,
|
||||
..
|
||||
} => json!({
|
||||
"kind": "TryCatch",
|
||||
"try": try_body.into_iter().map(|s| ast_to_json(&s)).collect::<Vec<_>>(),
|
||||
"catch": catch_clauses.into_iter().map(|cc| json!({
|
||||
@ -48,7 +64,14 @@ pub fn ast_to_json(ast: &ASTNode) -> Value {
|
||||
})).collect::<Vec<_>>(),
|
||||
"cleanup": finally_body.map(|v| v.into_iter().map(|s| ast_to_json(&s)).collect::<Vec<_>>())
|
||||
}),
|
||||
ASTNode::FunctionDeclaration { name, params, body, is_static, is_override, .. } => json!({
|
||||
ASTNode::FunctionDeclaration {
|
||||
name,
|
||||
params,
|
||||
body,
|
||||
is_static,
|
||||
is_override,
|
||||
..
|
||||
} => json!({
|
||||
"kind": "FunctionDeclaration",
|
||||
"name": name,
|
||||
"params": params,
|
||||
@ -58,24 +81,38 @@ pub fn ast_to_json(ast: &ASTNode) -> Value {
|
||||
}),
|
||||
ASTNode::Variable { name, .. } => json!({"kind":"Variable","name":name}),
|
||||
ASTNode::Literal { value, .. } => json!({"kind":"Literal","value": lit_to_json(&value)}),
|
||||
ASTNode::BinaryOp { operator, left, right, .. } => json!({
|
||||
ASTNode::BinaryOp {
|
||||
operator,
|
||||
left,
|
||||
right,
|
||||
..
|
||||
} => json!({
|
||||
"kind":"BinaryOp",
|
||||
"op": bin_to_str(&operator),
|
||||
"left": ast_to_json(&left),
|
||||
"right": ast_to_json(&right),
|
||||
}),
|
||||
ASTNode::UnaryOp { operator, operand, .. } => json!({
|
||||
ASTNode::UnaryOp {
|
||||
operator, operand, ..
|
||||
} => json!({
|
||||
"kind":"UnaryOp",
|
||||
"op": un_to_str(&operator),
|
||||
"operand": ast_to_json(&operand),
|
||||
}),
|
||||
ASTNode::MethodCall { object, method, arguments, .. } => json!({
|
||||
ASTNode::MethodCall {
|
||||
object,
|
||||
method,
|
||||
arguments,
|
||||
..
|
||||
} => json!({
|
||||
"kind":"MethodCall",
|
||||
"object": ast_to_json(&object),
|
||||
"method": method,
|
||||
"arguments": arguments.into_iter().map(|a| ast_to_json(&a)).collect::<Vec<_>>()
|
||||
}),
|
||||
ASTNode::FunctionCall { name, arguments, .. } => json!({
|
||||
ASTNode::FunctionCall {
|
||||
name, arguments, ..
|
||||
} => json!({
|
||||
"kind":"FunctionCall",
|
||||
"name": name,
|
||||
"arguments": arguments.into_iter().map(|a| ast_to_json(&a)).collect::<Vec<_>>()
|
||||
@ -88,7 +125,12 @@ pub fn ast_to_json(ast: &ASTNode) -> Value {
|
||||
"kind":"Map",
|
||||
"entries": entries.into_iter().map(|(k,v)| json!({"k":k,"v":ast_to_json(&v)})).collect::<Vec<_>>()
|
||||
}),
|
||||
ASTNode::MatchExpr { scrutinee, arms, else_expr, .. } => json!({
|
||||
ASTNode::MatchExpr {
|
||||
scrutinee,
|
||||
arms,
|
||||
else_expr,
|
||||
..
|
||||
} => json!({
|
||||
"kind":"MatchExpr",
|
||||
"scrutinee": ast_to_json(&scrutinee),
|
||||
"arms": arms.into_iter().map(|(lit, body)| json!({
|
||||
@ -108,45 +150,163 @@ pub fn json_to_ast(v: &Value) -> Option<ASTNode> {
|
||||
let k = v.get("kind")?.as_str()?;
|
||||
Some(match k {
|
||||
"Program" => {
|
||||
let stmts = v.get("statements")?.as_array()?.iter().filter_map(json_to_ast).collect::<Vec<_>>();
|
||||
ASTNode::Program { statements: stmts, span: Span::unknown() }
|
||||
let stmts = v
|
||||
.get("statements")?
|
||||
.as_array()?
|
||||
.iter()
|
||||
.filter_map(json_to_ast)
|
||||
.collect::<Vec<_>>();
|
||||
ASTNode::Program {
|
||||
statements: stmts,
|
||||
span: Span::unknown(),
|
||||
}
|
||||
}
|
||||
"Loop" => ASTNode::Loop {
|
||||
condition: Box::new(json_to_ast(v.get("condition")?)?),
|
||||
body: v.get("body")?.as_array()?.iter().filter_map(json_to_ast).collect::<Vec<_>>(),
|
||||
body: v
|
||||
.get("body")?
|
||||
.as_array()?
|
||||
.iter()
|
||||
.filter_map(json_to_ast)
|
||||
.collect::<Vec<_>>(),
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"Print" => ASTNode::Print { expression: Box::new(json_to_ast(v.get("expression")?)?), span: Span::unknown() },
|
||||
"Return" => ASTNode::Return { value: v.get("value").and_then(json_to_ast).map(Box::new), span: Span::unknown() },
|
||||
"Break" => ASTNode::Break { span: Span::unknown() },
|
||||
"Continue" => ASTNode::Continue { span: Span::unknown() },
|
||||
"Assignment" => ASTNode::Assignment { target: Box::new(json_to_ast(v.get("target")?)?), value: Box::new(json_to_ast(v.get("value")?)?), span: Span::unknown() },
|
||||
"Local" => {
|
||||
let vars = v.get("variables")?.as_array()?.iter().filter_map(|s| s.as_str().map(|x| x.to_string())).collect();
|
||||
let inits = v.get("inits")?.as_array()?.iter().map(|initv| {
|
||||
if initv.is_null() { None } else { json_to_ast(initv).map(Box::new) }
|
||||
}).collect();
|
||||
ASTNode::Local { variables: vars, initial_values: inits, span: Span::unknown() }
|
||||
"Print" => ASTNode::Print {
|
||||
expression: Box::new(json_to_ast(v.get("expression")?)?),
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"Return" => ASTNode::Return {
|
||||
value: v.get("value").and_then(json_to_ast).map(Box::new),
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"Break" => ASTNode::Break {
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"Continue" => ASTNode::Continue {
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"Assignment" => ASTNode::Assignment {
|
||||
target: Box::new(json_to_ast(v.get("target")?)?),
|
||||
value: Box::new(json_to_ast(v.get("value")?)?),
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"Local" => {
|
||||
let vars = v
|
||||
.get("variables")?
|
||||
.as_array()?
|
||||
.iter()
|
||||
.filter_map(|s| s.as_str().map(|x| x.to_string()))
|
||||
.collect();
|
||||
let inits = v
|
||||
.get("inits")?
|
||||
.as_array()?
|
||||
.iter()
|
||||
.map(|initv| {
|
||||
if initv.is_null() {
|
||||
None
|
||||
} else {
|
||||
json_to_ast(initv).map(Box::new)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
ASTNode::Local {
|
||||
variables: vars,
|
||||
initial_values: inits,
|
||||
span: Span::unknown(),
|
||||
}
|
||||
}
|
||||
"If" => ASTNode::If {
|
||||
condition: Box::new(json_to_ast(v.get("condition")?)?),
|
||||
then_body: v
|
||||
.get("then")?
|
||||
.as_array()?
|
||||
.iter()
|
||||
.filter_map(json_to_ast)
|
||||
.collect::<Vec<_>>(),
|
||||
else_body: v.get("else").and_then(|a| {
|
||||
a.as_array()
|
||||
.map(|arr| arr.iter().filter_map(json_to_ast).collect::<Vec<_>>())
|
||||
}),
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"If" => ASTNode::If { condition: Box::new(json_to_ast(v.get("condition")?)?), then_body: v.get("then")?.as_array()?.iter().filter_map(json_to_ast).collect::<Vec<_>>(), else_body: v.get("else").and_then(|a| a.as_array().map(|arr| arr.iter().filter_map(json_to_ast).collect::<Vec<_>>())), span: Span::unknown() },
|
||||
"FunctionDeclaration" => ASTNode::FunctionDeclaration {
|
||||
name: v.get("name")?.as_str()?.to_string(),
|
||||
params: v.get("params")?.as_array()?.iter().filter_map(|s| s.as_str().map(|x| x.to_string())).collect(),
|
||||
body: v.get("body")?.as_array()?.iter().filter_map(json_to_ast).collect(),
|
||||
params: v
|
||||
.get("params")?
|
||||
.as_array()?
|
||||
.iter()
|
||||
.filter_map(|s| s.as_str().map(|x| x.to_string()))
|
||||
.collect(),
|
||||
body: v
|
||||
.get("body")?
|
||||
.as_array()?
|
||||
.iter()
|
||||
.filter_map(json_to_ast)
|
||||
.collect(),
|
||||
is_static: v.get("static").and_then(|b| b.as_bool()).unwrap_or(false),
|
||||
is_override: v.get("override").and_then(|b| b.as_bool()).unwrap_or(false),
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"Variable" => ASTNode::Variable { name: v.get("name")?.as_str()?.to_string(), span: Span::unknown() },
|
||||
"Literal" => ASTNode::Literal { value: json_to_lit(v.get("value")?)?, span: Span::unknown() },
|
||||
"BinaryOp" => ASTNode::BinaryOp { operator: str_to_bin(v.get("op")?.as_str()?)?, left: Box::new(json_to_ast(v.get("left")?)?), right: Box::new(json_to_ast(v.get("right")?)?), span: Span::unknown() },
|
||||
"UnaryOp" => ASTNode::UnaryOp { operator: str_to_un(v.get("op")?.as_str()?)?, operand: Box::new(json_to_ast(v.get("operand")?)?), span: Span::unknown() },
|
||||
"MethodCall" => ASTNode::MethodCall { object: Box::new(json_to_ast(v.get("object")?)?), method: v.get("method")?.as_str()?.to_string(), arguments: v.get("arguments")?.as_array()?.iter().filter_map(json_to_ast).collect(), span: Span::unknown() },
|
||||
"FunctionCall" => ASTNode::FunctionCall { name: v.get("name")?.as_str()?.to_string(), arguments: v.get("arguments")?.as_array()?.iter().filter_map(json_to_ast).collect(), span: Span::unknown() },
|
||||
"Array" => ASTNode::ArrayLiteral { elements: v.get("elements")?.as_array()?.iter().filter_map(json_to_ast).collect(), span: Span::unknown() },
|
||||
"Map" => ASTNode::MapLiteral { entries: v.get("entries")?.as_array()?.iter().filter_map(|e| {
|
||||
Some((e.get("k")?.as_str()?.to_string(), json_to_ast(e.get("v")?)?))
|
||||
}).collect(), span: Span::unknown() },
|
||||
"Variable" => ASTNode::Variable {
|
||||
name: v.get("name")?.as_str()?.to_string(),
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"Literal" => ASTNode::Literal {
|
||||
value: json_to_lit(v.get("value")?)?,
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"BinaryOp" => ASTNode::BinaryOp {
|
||||
operator: str_to_bin(v.get("op")?.as_str()?)?,
|
||||
left: Box::new(json_to_ast(v.get("left")?)?),
|
||||
right: Box::new(json_to_ast(v.get("right")?)?),
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"UnaryOp" => ASTNode::UnaryOp {
|
||||
operator: str_to_un(v.get("op")?.as_str()?)?,
|
||||
operand: Box::new(json_to_ast(v.get("operand")?)?),
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"MethodCall" => ASTNode::MethodCall {
|
||||
object: Box::new(json_to_ast(v.get("object")?)?),
|
||||
method: v.get("method")?.as_str()?.to_string(),
|
||||
arguments: v
|
||||
.get("arguments")?
|
||||
.as_array()?
|
||||
.iter()
|
||||
.filter_map(json_to_ast)
|
||||
.collect(),
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"FunctionCall" => ASTNode::FunctionCall {
|
||||
name: v.get("name")?.as_str()?.to_string(),
|
||||
arguments: v
|
||||
.get("arguments")?
|
||||
.as_array()?
|
||||
.iter()
|
||||
.filter_map(json_to_ast)
|
||||
.collect(),
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"Array" => ASTNode::ArrayLiteral {
|
||||
elements: v
|
||||
.get("elements")?
|
||||
.as_array()?
|
||||
.iter()
|
||||
.filter_map(json_to_ast)
|
||||
.collect(),
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"Map" => ASTNode::MapLiteral {
|
||||
entries: v
|
||||
.get("entries")?
|
||||
.as_array()?
|
||||
.iter()
|
||||
.filter_map(|e| {
|
||||
Some((e.get("k")?.as_str()?.to_string(), json_to_ast(e.get("v")?)?))
|
||||
})
|
||||
.collect(),
|
||||
span: Span::unknown(),
|
||||
},
|
||||
"MatchExpr" => {
|
||||
let scr = json_to_ast(v.get("scrutinee")?)?;
|
||||
let arms_json = v.get("arms")?.as_array()?.iter();
|
||||
@ -166,18 +326,47 @@ pub fn json_to_ast(v: &Value) -> Option<ASTNode> {
|
||||
}
|
||||
}
|
||||
"TryCatch" => {
|
||||
let try_b = v.get("try")?.as_array()?.iter().filter_map(json_to_ast).collect::<Vec<_>>();
|
||||
let try_b = v
|
||||
.get("try")?
|
||||
.as_array()?
|
||||
.iter()
|
||||
.filter_map(json_to_ast)
|
||||
.collect::<Vec<_>>();
|
||||
let mut catches = Vec::new();
|
||||
if let Some(arr) = v.get("catch").and_then(|x| x.as_array()) {
|
||||
for c in arr.iter() {
|
||||
let exc_t = match c.get("type") { Some(t) if !t.is_null() => t.as_str().map(|s| s.to_string()), _ => None };
|
||||
let var = match c.get("var") { Some(vv) if !vv.is_null() => vv.as_str().map(|s| s.to_string()), _ => None };
|
||||
let body = c.get("body")?.as_array()?.iter().filter_map(json_to_ast).collect::<Vec<_>>();
|
||||
catches.push(nyash_rust::ast::CatchClause { exception_type: exc_t, variable_name: var, body, span: Span::unknown() });
|
||||
let exc_t = match c.get("type") {
|
||||
Some(t) if !t.is_null() => t.as_str().map(|s| s.to_string()),
|
||||
_ => None,
|
||||
};
|
||||
let var = match c.get("var") {
|
||||
Some(vv) if !vv.is_null() => vv.as_str().map(|s| s.to_string()),
|
||||
_ => None,
|
||||
};
|
||||
let body = c
|
||||
.get("body")?
|
||||
.as_array()?
|
||||
.iter()
|
||||
.filter_map(json_to_ast)
|
||||
.collect::<Vec<_>>();
|
||||
catches.push(nyash_rust::ast::CatchClause {
|
||||
exception_type: exc_t,
|
||||
variable_name: var,
|
||||
body,
|
||||
span: Span::unknown(),
|
||||
});
|
||||
}
|
||||
}
|
||||
let cleanup = v.get("cleanup").and_then(|cl| cl.as_array().map(|arr| arr.iter().filter_map(json_to_ast).collect::<Vec<_>>()));
|
||||
ASTNode::TryCatch { try_body: try_b, catch_clauses: catches, finally_body: cleanup, span: Span::unknown() }
|
||||
let cleanup = v.get("cleanup").and_then(|cl| {
|
||||
cl.as_array()
|
||||
.map(|arr| arr.iter().filter_map(json_to_ast).collect::<Vec<_>>())
|
||||
});
|
||||
ASTNode::TryCatch {
|
||||
try_body: try_b,
|
||||
catch_clauses: catches,
|
||||
finally_body: cleanup,
|
||||
span: Span::unknown(),
|
||||
}
|
||||
}
|
||||
_ => return None,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user