feat(joinir): Phase 51 Field access / NewBox 式タイプ拡張
JoinIR Frontend の式タイプを拡張し、Field access と NewBox のパースと MIR 変換をサポート。 ## 新機能 ### Field access (me.tokens 等) - expr.rs に "Field" タイプハンドラ追加 - JoinInst::FieldAccess バリアント追加 - MIR 変換: FieldAccess → BoxCall (getter pattern) ### NewBox (new ArrayBox() 等) - expr.rs に "NewBox" タイプハンドラ追加 - JoinInst::NewBox バリアント追加 - MIR 変換: NewBox → MirInstruction::NewBox ## 修正ファイル - src/mir/join_ir/mod.rs: JoinInst 拡張 - src/mir/join_ir/frontend/ast_lowerer/expr.rs: パース対応 - src/mir/join_ir_vm_bridge/convert.rs: MIR 変換 - src/mir/join_ir_runner.rs: ハンドラ追加 - src/mir/join_ir/json.rs: JSON シリアライズ ## 注意 print_tokens/array_filter の JoinIR 完走には Phase 52 で JSON 生成側 (LoopFrontendBinding) の修正が必要。 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Submodule docs/private updated: 905e8521c9...bd16c39e69
@ -187,6 +187,65 @@ impl AstToJoinIrLowerer {
|
|||||||
(dst, insts)
|
(dst, insts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Phase 51: フィールドアクセス対応(me.tokens 等)
|
||||||
|
"Field" => {
|
||||||
|
let object_expr = &expr["object"];
|
||||||
|
let field_name = expr["field"]
|
||||||
|
.as_str()
|
||||||
|
.expect("Field must have 'field' string");
|
||||||
|
|
||||||
|
// object を再帰的に extract_value
|
||||||
|
let (object_var, object_insts) = self.extract_value(object_expr, ctx);
|
||||||
|
|
||||||
|
// 結果変数を割り当て
|
||||||
|
let dst = ctx.alloc_var();
|
||||||
|
|
||||||
|
// FieldAccess 命令を生成
|
||||||
|
let field_inst = JoinInst::FieldAccess {
|
||||||
|
dst,
|
||||||
|
object: object_var,
|
||||||
|
field: field_name.to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut insts = object_insts;
|
||||||
|
insts.push(field_inst);
|
||||||
|
|
||||||
|
(dst, insts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phase 51: NewBox 対応(new ArrayBox() 等)
|
||||||
|
"NewBox" => {
|
||||||
|
let box_name = expr["box_name"]
|
||||||
|
.as_str()
|
||||||
|
.expect("NewBox must have 'box_name' string");
|
||||||
|
let empty_args = vec![];
|
||||||
|
let args_array = expr["args"].as_array().unwrap_or(&empty_args);
|
||||||
|
|
||||||
|
// args を再帰的に extract_value
|
||||||
|
let mut arg_vars = Vec::new();
|
||||||
|
let mut arg_insts = Vec::new();
|
||||||
|
for arg_expr in args_array {
|
||||||
|
let (arg_var, arg_inst) = self.extract_value(arg_expr, ctx);
|
||||||
|
arg_vars.push(arg_var);
|
||||||
|
arg_insts.extend(arg_inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 結果変数を割り当て
|
||||||
|
let dst = ctx.alloc_var();
|
||||||
|
|
||||||
|
// NewBox 命令を生成
|
||||||
|
let newbox_inst = JoinInst::NewBox {
|
||||||
|
dst,
|
||||||
|
box_name: box_name.to_string(),
|
||||||
|
args: arg_vars,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut insts = arg_insts;
|
||||||
|
insts.push(newbox_inst);
|
||||||
|
|
||||||
|
(dst, insts)
|
||||||
|
}
|
||||||
|
|
||||||
_ => panic!("Unsupported expr type: {}", expr_type),
|
_ => panic!("Unsupported expr type: {}", expr_type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -231,6 +231,33 @@ fn write_inst<W: Write>(inst: &JoinInst, out: &mut W) -> std::io::Result<()> {
|
|||||||
}
|
}
|
||||||
write!(out, "}}")?;
|
write!(out, "}}")?;
|
||||||
}
|
}
|
||||||
|
// Phase 51: FieldAccess instruction JSON serialization
|
||||||
|
JoinInst::FieldAccess { dst, object, field } => {
|
||||||
|
write!(out, "{{\"type\":\"field_access\"")?;
|
||||||
|
write!(out, ",\"dst\":{}", dst.0)?;
|
||||||
|
write!(out, ",\"object\":{}", object.0)?;
|
||||||
|
write!(out, ",\"field\":\"{}\"", escape_json_string(field))?;
|
||||||
|
write!(out, "}}")?;
|
||||||
|
}
|
||||||
|
// Phase 51: NewBox instruction JSON serialization
|
||||||
|
JoinInst::NewBox {
|
||||||
|
dst,
|
||||||
|
box_name,
|
||||||
|
args,
|
||||||
|
} => {
|
||||||
|
write!(out, "{{\"type\":\"new_box\"")?;
|
||||||
|
write!(out, ",\"dst\":{}", dst.0)?;
|
||||||
|
write!(out, ",\"box_name\":\"{}\"", escape_json_string(box_name))?;
|
||||||
|
write!(out, ",\"args\":[")?;
|
||||||
|
for (i, arg) in args.iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
write!(out, ",")?;
|
||||||
|
}
|
||||||
|
write!(out, "{}", arg.0)?;
|
||||||
|
}
|
||||||
|
write!(out, "]")?;
|
||||||
|
write!(out, "}}")?;
|
||||||
|
}
|
||||||
JoinInst::Compute(mir_like) => {
|
JoinInst::Compute(mir_like) => {
|
||||||
write!(out, "{{\"type\":\"compute\",\"op\":")?;
|
write!(out, "{{\"type\":\"compute\",\"op\":")?;
|
||||||
write_mir_like_inst(mir_like, out)?;
|
write_mir_like_inst(mir_like, out)?;
|
||||||
|
|||||||
@ -322,6 +322,24 @@ pub enum JoinInst {
|
|||||||
args: Vec<VarId>,
|
args: Vec<VarId>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Phase 51: フィールドアクセス
|
||||||
|
/// object.field の構造を JoinIR で表現
|
||||||
|
/// MIR 変換時に Load 命令に変換
|
||||||
|
FieldAccess {
|
||||||
|
dst: VarId,
|
||||||
|
object: VarId,
|
||||||
|
field: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Phase 51: Box インスタンス生成
|
||||||
|
/// new BoxName(args...) の構造を JoinIR で表現
|
||||||
|
/// MIR 変換時に NewBox 命令に変換
|
||||||
|
NewBox {
|
||||||
|
dst: VarId,
|
||||||
|
box_name: String,
|
||||||
|
args: Vec<VarId>,
|
||||||
|
},
|
||||||
|
|
||||||
/// Phase 41-4: 深いネスト if の複数変数 merge(else なし)
|
/// Phase 41-4: 深いネスト if の複数変数 merge(else なし)
|
||||||
///
|
///
|
||||||
/// # Pattern
|
/// # Pattern
|
||||||
|
|||||||
@ -225,6 +225,22 @@ fn execute_function(
|
|||||||
"NestedIfMerge is not supported in JoinIR Runner (use JoinIR→MIR→VM bridge instead)"
|
"NestedIfMerge is not supported in JoinIR Runner (use JoinIR→MIR→VM bridge instead)"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
// Phase 51: FieldAccess instruction execution
|
||||||
|
JoinInst::FieldAccess { .. } => {
|
||||||
|
// Phase 51: FieldAccess は JoinIR Runner では未対応
|
||||||
|
// JoinIR → MIR 変換経由で VM が実行する
|
||||||
|
return Err(JoinRuntimeError::new(
|
||||||
|
"FieldAccess is not supported in JoinIR Runner (use JoinIR→MIR→VM bridge instead)"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
// Phase 51: NewBox instruction execution
|
||||||
|
JoinInst::NewBox { .. } => {
|
||||||
|
// Phase 51: NewBox は JoinIR Runner では未対応
|
||||||
|
// JoinIR → MIR 変換経由で VM が実行する
|
||||||
|
return Err(JoinRuntimeError::new(
|
||||||
|
"NewBox is not supported in JoinIR Runner (use JoinIR→MIR→VM bridge instead)"
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -217,6 +217,33 @@ pub(crate) fn convert_join_function_to_mir(
|
|||||||
};
|
};
|
||||||
current_instructions.push(mir_inst);
|
current_instructions.push(mir_inst);
|
||||||
}
|
}
|
||||||
|
// Phase 51: FieldAccess → MIR BoxCall (getter pattern)
|
||||||
|
JoinInst::FieldAccess { dst, object, field } => {
|
||||||
|
// object.field を BoxCall(object, field, []) に変換
|
||||||
|
// フィールドアクセスはメソッド呼び出しとして扱う(getter pattern)
|
||||||
|
let mir_inst = MirInstruction::BoxCall {
|
||||||
|
dst: Some(*dst),
|
||||||
|
box_val: *object,
|
||||||
|
method: field.clone(),
|
||||||
|
method_id: None,
|
||||||
|
args: vec![],
|
||||||
|
effects: EffectMask::PURE,
|
||||||
|
};
|
||||||
|
current_instructions.push(mir_inst);
|
||||||
|
}
|
||||||
|
// Phase 51: NewBox → MIR NewBox
|
||||||
|
JoinInst::NewBox {
|
||||||
|
dst,
|
||||||
|
box_name,
|
||||||
|
args,
|
||||||
|
} => {
|
||||||
|
let mir_inst = MirInstruction::NewBox {
|
||||||
|
dst: *dst,
|
||||||
|
box_type: box_name.clone(),
|
||||||
|
args: args.clone(),
|
||||||
|
};
|
||||||
|
current_instructions.push(mir_inst);
|
||||||
|
}
|
||||||
JoinInst::Call {
|
JoinInst::Call {
|
||||||
func,
|
func,
|
||||||
args,
|
args,
|
||||||
|
|||||||
Reference in New Issue
Block a user