|
6 | 6 | "go/ast" |
7 | 7 | "go/token" |
8 | 8 | gtypes "go/types" |
| 9 | + "strconv" |
9 | 10 |
|
10 | 11 | gstypes "github.com/paralin/goscript/types" |
11 | 12 | ) |
@@ -383,21 +384,62 @@ func (c *GoToTSCompiler) WriteCallExpr(exp *ast.CallExpr) error { |
383 | 384 | case "string": |
384 | 385 | // Handle string() conversion, specifically for rune to string |
385 | 386 | if len(exp.Args) == 1 { |
386 | | - // Check if the argument is a rune (int32) |
387 | | - if tv, ok := c.pkg.TypesInfo.Types[exp.Args[0]]; ok { |
| 387 | + // Check if the argument is a rune (int32) or a call to rune() |
| 388 | + arg := exp.Args[0] |
| 389 | + innerCall, isCallExpr := arg.(*ast.CallExpr) |
| 390 | + |
| 391 | + if isCallExpr { |
| 392 | + // Check if it's a call to rune() |
| 393 | + if innerFunIdent, innerFunIsIdent := innerCall.Fun.(*ast.Ident); innerFunIsIdent && innerFunIdent.String() == "rune" { |
| 394 | + // Translate string(rune(val)) to String.fromCharCode(val) |
| 395 | + if len(innerCall.Args) == 1 { |
| 396 | + c.tsw.WriteLiterally("String.fromCharCode(") |
| 397 | + if err := c.WriteValueExpr(innerCall.Args[0]); err != nil { |
| 398 | + return fmt.Errorf("failed to write argument for string(rune) conversion: %w", err) |
| 399 | + } |
| 400 | + c.tsw.WriteLiterally(")") |
| 401 | + return nil // Handled string(rune) |
| 402 | + } |
| 403 | + } |
| 404 | + } |
| 405 | + |
| 406 | + // Handle direct string(int32) conversion |
| 407 | + // This assumes 'rune' is int32 |
| 408 | + if tv, ok := c.pkg.TypesInfo.Types[arg]; ok { |
388 | 409 | if basic, isBasic := tv.Type.Underlying().(*gtypes.Basic); isBasic && basic.Kind() == gtypes.Int32 { |
389 | 410 | // Translate string(rune_val) to String.fromCharCode(rune_val) |
390 | 411 | c.tsw.WriteLiterally("String.fromCharCode(") |
391 | | - if err := c.WriteValueExpr(exp.Args[0]); err != nil { |
392 | | - return fmt.Errorf("failed to write argument for string(rune) conversion: %w", err) |
| 412 | + if err := c.WriteValueExpr(arg); err != nil { |
| 413 | + return fmt.Errorf("failed to write argument for string(int32) conversion: %w", err) |
393 | 414 | } |
394 | 415 | c.tsw.WriteLiterally(")") |
395 | | - return nil // Handled string(rune) |
| 416 | + return nil // Handled string(int32) |
396 | 417 | } |
397 | 418 | } |
398 | 419 | } |
399 | 420 | // Return error for other unhandled string conversions |
400 | 421 | return fmt.Errorf("unhandled string conversion: %s", exp.Fun) |
| 422 | + case "append": |
| 423 | + // Translate append(slice, elements...) to goscript.append(slice, elements...) |
| 424 | + if len(exp.Args) >= 1 { |
| 425 | + c.tsw.WriteLiterally("goscript.append(") |
| 426 | + // The first argument is the slice |
| 427 | + if err := c.WriteValueExpr(exp.Args[0]); err != nil { |
| 428 | + return fmt.Errorf("failed to write slice in append call: %w", err) |
| 429 | + } |
| 430 | + // The remaining arguments are the elements to append |
| 431 | + for i, arg := range exp.Args[1:] { |
| 432 | + if i > 0 || len(exp.Args) > 1 { // Add comma before elements if there are any |
| 433 | + c.tsw.WriteLiterally(", ") |
| 434 | + } |
| 435 | + if err := c.WriteValueExpr(arg); err != nil { |
| 436 | + return fmt.Errorf("failed to write argument %d in append call: %w", i+1, err) |
| 437 | + } |
| 438 | + } |
| 439 | + c.tsw.WriteLiterally(")") |
| 440 | + return nil // Handled append |
| 441 | + } |
| 442 | + return errors.New("unhandled append call with incorrect number of arguments") |
401 | 443 | default: |
402 | 444 | // Not a special built-in, treat as a regular function call |
403 | 445 | if err := c.WriteValueExpr(expFun); err != nil { |
@@ -480,7 +522,20 @@ func (c *GoToTSCompiler) WriteBinaryExprValue(exp *ast.BinaryExpr) error { |
480 | 522 |
|
481 | 523 | // WriteBasicLitValue writes a basic literal value. |
482 | 524 | func (c *GoToTSCompiler) WriteBasicLitValue(exp *ast.BasicLit) { |
483 | | - c.tsw.WriteLiterally(exp.Value) |
| 525 | + if exp.Kind == token.CHAR { |
| 526 | + // Go char literal 'x' is a rune (int32). Translate to its numeric code point. |
| 527 | + // Use strconv.UnquoteChar to handle escape sequences correctly. |
| 528 | + val, _, _, err := strconv.UnquoteChar(exp.Value[1:len(exp.Value)-1], '\'') |
| 529 | + if err != nil { |
| 530 | + c.tsw.WriteCommentInline(fmt.Sprintf("error parsing char literal %s: %v", exp.Value, err)) |
| 531 | + c.tsw.WriteLiterally("0") // Default to 0 on error |
| 532 | + } else { |
| 533 | + c.tsw.WriteLiterally(fmt.Sprintf("%d", val)) |
| 534 | + } |
| 535 | + } else { |
| 536 | + // Other literals (INT, FLOAT, STRING, IMAG) |
| 537 | + c.tsw.WriteLiterally(exp.Value) |
| 538 | + } |
484 | 539 | } |
485 | 540 |
|
486 | 541 | /* |
|
0 commit comments