Skip to content

Commit 7084793

Browse files
fcouryclaude
andcommitted
fix: transpilation of multi-field Option/Result variants
- Fix Option::Some and Result::Ok/Err to use values array for multiple arguments - Update pattern matching to extract all bindings from _matched.values - Maintain backward compatibility for single-value variants - Update test outputs to reflect fixed transpilation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 42627c8 commit 7084793

File tree

3 files changed

+94
-29
lines changed

3 files changed

+94
-29
lines changed

src/transpiler.rs

Lines changed: 93 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,23 @@ impl JsTranspiler {
487487
)
488488
}
489489
"Some" => {
490-
if let Some(Expr::Identifier(bind_name, _)) = args.first() {
490+
if args.len() > 1 {
491+
// Multiple bindings - extract from values array
492+
let mut bindings = String::new();
493+
for (i, arg) in args.iter().enumerate() {
494+
if let Expr::Identifier(bind_name, _) = arg {
495+
bindings.push_str(&format!(
496+
"const {} = _matched.values[{}];\n",
497+
bind_name, i
498+
));
499+
}
500+
}
501+
return (
502+
"(_matched && _matched.type === 'Some')".to_string(),
503+
bindings,
504+
);
505+
} else if let Some(Expr::Identifier(bind_name, _)) = args.first() {
506+
// Single binding - maintain backward compatibility
491507
return (
492508
"(_matched && _matched.type === 'Some')".to_string(),
493509
format!("const {} = _matched.value;\n", bind_name),
@@ -506,26 +522,58 @@ impl JsTranspiler {
506522
if type_name == "Result" {
507523
match call.as_str() {
508524
"Ok" => {
509-
if let Some(Expr::Identifier(bind_name, _)) = args.first() {
525+
if args.len() > 1 {
526+
// Multiple bindings - extract from values array
527+
let mut bindings = String::new();
528+
for (i, arg) in args.iter().enumerate() {
529+
if let Expr::Identifier(bind_name, _) = arg {
530+
bindings.push_str(&format!(
531+
"const {} = _matched.values[{}];\n",
532+
bind_name, i
533+
));
534+
}
535+
}
536+
return (
537+
"(_matched && _matched.type === 'Ok')".to_string(),
538+
bindings,
539+
);
540+
} else if let Some(Expr::Identifier(bind_name, _)) = args.first() {
541+
// Single binding - maintain backward compatibility
510542
return (
511-
"(_matched && typeof _matched === 'object' && 'Ok' in _matched)".to_string(),
512-
format!("const {} = _matched.Ok;\n", bind_name),
543+
"(_matched && _matched.type === 'Ok')".to_string(),
544+
format!("const {} = _matched.value;\n", bind_name),
513545
);
514546
}
515547
return (
516-
"(_matched && typeof _matched === 'object' && 'Ok' in _matched)".to_string(),
548+
"(_matched && _matched.type === 'Ok')".to_string(),
517549
String::new(),
518550
);
519551
}
520552
"Err" => {
521-
if let Some(Expr::Identifier(bind_name, _)) = args.first() {
553+
if args.len() > 1 {
554+
// Multiple bindings - extract from values array
555+
let mut bindings = String::new();
556+
for (i, arg) in args.iter().enumerate() {
557+
if let Expr::Identifier(bind_name, _) = arg {
558+
bindings.push_str(&format!(
559+
"const {} = _matched.values[{}];\n",
560+
bind_name, i
561+
));
562+
}
563+
}
522564
return (
523-
"(_matched && typeof _matched === 'object' && 'Err' in _matched)".to_string(),
524-
format!("const {} = _matched.Err;\n", bind_name),
565+
"(_matched && _matched.type === 'Err')".to_string(),
566+
bindings,
567+
);
568+
} else if let Some(Expr::Identifier(bind_name, _)) = args.first() {
569+
// Single binding - maintain backward compatibility
570+
return (
571+
"(_matched && _matched.type === 'Err')".to_string(),
572+
format!("const {} = _matched.value;\n", bind_name),
525573
);
526574
}
527575
return (
528-
"(_matched && typeof _matched === 'object' && 'Err' in _matched)".to_string(),
576+
"(_matched && _matched.type === 'Err')".to_string(),
529577
String::new(),
530578
);
531579
}
@@ -1092,7 +1140,18 @@ impl AstVisitor<String> for JsTranspiler {
10921140
match call {
10931141
"None" => return Ok("{ type: 'None', value: null }".to_string()),
10941142
"Some" => {
1095-
if !args.is_empty() {
1143+
if args.len() > 1 {
1144+
// Multiple values - use values array
1145+
let arg_strs: Vec<String> = args
1146+
.iter()
1147+
.map(|arg| self.visit_expr(arg))
1148+
.collect::<Result<Vec<_>>>()?;
1149+
return Ok(format!(
1150+
"{{ type: 'Some', values: [{}] }}",
1151+
arg_strs.join(", ")
1152+
));
1153+
} else if args.len() == 1 {
1154+
// Single value - maintain backward compatibility
10961155
let arg_str = self.visit_expr(&args[0])?;
10971156
return Ok(format!("{{ type: 'Some', value: {} }}", arg_str));
10981157
} else {
@@ -1107,15 +1166,37 @@ impl AstVisitor<String> for JsTranspiler {
11071166
if target_str == "Result" {
11081167
match call {
11091168
"Ok" => {
1110-
if !args.is_empty() {
1169+
if args.len() > 1 {
1170+
// Multiple values - use values array
1171+
let arg_strs: Vec<String> = args
1172+
.iter()
1173+
.map(|arg| self.visit_expr(arg))
1174+
.collect::<Result<Vec<_>>>()?;
1175+
return Ok(format!(
1176+
"{{ type: 'Ok', values: [{}] }}",
1177+
arg_strs.join(", ")
1178+
));
1179+
} else if args.len() == 1 {
1180+
// Single value - maintain backward compatibility
11111181
let arg_str = self.visit_expr(&args[0])?;
11121182
return Ok(format!("{{ type: 'Ok', value: {} }}", arg_str));
11131183
} else {
11141184
return Ok("{ type: 'Ok', value: undefined }".to_string());
11151185
}
11161186
}
11171187
"Err" => {
1118-
if !args.is_empty() {
1188+
if args.len() > 1 {
1189+
// Multiple values - use values array
1190+
let arg_strs: Vec<String> = args
1191+
.iter()
1192+
.map(|arg| self.visit_expr(arg))
1193+
.collect::<Result<Vec<_>>>()?;
1194+
return Ok(format!(
1195+
"{{ type: 'Err', values: [{}] }}",
1196+
arg_strs.join(", ")
1197+
));
1198+
} else if args.len() == 1 {
1199+
// Single value - maintain backward compatibility
11191200
let arg_str = self.visit_expr(&args[0])?;
11201201
return Ok(format!("{{ type: 'Err', value: {} }}", arg_str));
11211202
} else {
Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +0,0 @@
1-
[stdin]:411
2-
return console.log(`Name: ${name} age: ${age}`);
3-
^
4-
5-
ReferenceError: age is not defined
6-
at [stdin]:411:46
7-
at main ([stdin]:413:3)
8-
at [stdin]:415:1
9-
at runScriptInThisContext (node:internal/vm:218:10)
10-
at node:internal/process/execution:456:12
11-
at [stdin]-wrapper:6:24
12-
at runScriptInContext (node:internal/process/execution:454:60)
13-
at evalFunction (node:internal/process/execution:286:30)
14-
at evalTypeScript (node:internal/process/execution:298:3)
15-
at node:internal/main/eval_stdin:51:5
16-
17-
Node.js v24.2.0
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Name: Hello age: 18

0 commit comments

Comments
 (0)