feat(joinir): Phase 50 Loop Frontend Binding layer
Phase 50 implements the Loop Frontend Binding layer that maps actual loop variables to JoinIR Frontend's expected names (i, acc, n). ## Changes - Add loop_frontend_binding.rs module with: - LoopFrontendBinding struct for variable mapping - for_print_tokens() and for_array_filter() factory methods - generate_local_declarations() for JSON v0 format - rename_body_variables() for out → acc renaming - Integrate binding with cf_loop_joinir_impl: - Create binding based on function name - Inject i/acc/n Local declarations into JSON v0 - Use correct JoinIR Frontend type names (Int/Var/Method) ## Limitations Found JoinIR Frontend doesn't support: - Field access (me.tokens) - blocks print_tokens - NewBox (new ArrayBox()) - blocks array_filter These will be addressed in Phase 51. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -132,17 +132,50 @@ impl super::MirBuilder {
|
||||
func_name: &str,
|
||||
debug: bool,
|
||||
) -> Result<Option<ValueId>, String> {
|
||||
use super::loop_frontend_binding::LoopFrontendBinding;
|
||||
use crate::r#macro::ast_json::ast_to_json;
|
||||
use crate::mir::join_ir::frontend::{AstToJoinIrLowerer, JoinFuncMetaMap};
|
||||
use crate::mir::join_ir_vm_bridge::convert_join_module_to_mir_with_meta;
|
||||
use crate::mir::types::ConstValue;
|
||||
|
||||
// Phase 50: Create appropriate binding based on function name
|
||||
let binding = match func_name {
|
||||
"JsonTokenizer.print_tokens/0" => LoopFrontendBinding::for_print_tokens(),
|
||||
"ArrayExtBox.filter/2" => LoopFrontendBinding::for_array_filter(),
|
||||
_ => {
|
||||
if debug {
|
||||
eprintln!(
|
||||
"[cf_loop/joinir] No binding defined for {}, falling back",
|
||||
func_name
|
||||
);
|
||||
}
|
||||
return Ok(None);
|
||||
}
|
||||
};
|
||||
|
||||
if debug {
|
||||
eprintln!(
|
||||
"[cf_loop/joinir] Using binding: counter={}, acc={:?}, pattern={:?}",
|
||||
binding.counter_var,
|
||||
binding.accumulator_var,
|
||||
binding.pattern
|
||||
);
|
||||
}
|
||||
|
||||
// Step 1: Convert condition and body to JSON
|
||||
let condition_json = ast_to_json(condition);
|
||||
let body_json: Vec<serde_json::Value> = body.iter().map(|s| ast_to_json(s)).collect();
|
||||
let mut body_json: Vec<serde_json::Value> =
|
||||
body.iter().map(|s| ast_to_json(s)).collect();
|
||||
|
||||
// Phase 50: Rename variables in body (e.g., "out" → "acc" for filter)
|
||||
binding.rename_body_variables(&mut body_json);
|
||||
|
||||
// Phase 50: Generate Local declarations from binding
|
||||
let (i_local, acc_local, n_local) = binding.generate_local_declarations();
|
||||
|
||||
// Step 2: Construct JSON v0 format with "defs" array
|
||||
// The function is named "simple" to match JoinIR Frontend's pattern matching
|
||||
// Phase 50: Include i/acc/n Local declarations to satisfy JoinIR Frontend expectations
|
||||
let program_json = serde_json::json!({
|
||||
"defs": [
|
||||
{
|
||||
@ -151,16 +184,19 @@ impl super::MirBuilder {
|
||||
"body": {
|
||||
"type": "Block",
|
||||
"body": [
|
||||
// Placeholder locals (JoinIR Frontend will infer from loop)
|
||||
// Phase 50: Inject i/acc/n Local declarations
|
||||
i_local,
|
||||
acc_local,
|
||||
n_local,
|
||||
{
|
||||
"type": "Loop",
|
||||
"condition": condition_json,
|
||||
"body": body_json
|
||||
},
|
||||
// Placeholder return
|
||||
// Return the accumulator (or null for side-effect loops)
|
||||
{
|
||||
"type": "Return",
|
||||
"value": null
|
||||
"value": { "kind": "Variable", "name": "acc" }
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user