Skip to content

Commit c9e1afd

Browse files
committed
[swift] Transpile int collections to Int32.
1 parent 2163efb commit c9e1afd

File tree

7 files changed

+350
-98
lines changed

7 files changed

+350
-98
lines changed

GenPySwift.fu

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// GenPySwift.fu - Python/Swift code generator
22
//
3-
// Copyright (C) 2020-2023 Piotr Fusik
3+
// Copyright (C) 2020-2025 Piotr Fusik
44
//
55
// This file is part of Fusion Transpiler,
66
// see https://github.com/fusionlanguage/fut
@@ -123,14 +123,19 @@ public abstract class GenPySwift : GenBase
123123
expr.Accept(this, parent);
124124
}
125125

126+
protected virtual void WriteElementCoerced!(FuType type, FuExpr value)
127+
{
128+
WriteCoerced(type, value, FuPriority.Argument);
129+
}
130+
126131
protected void WriteListAppend!(FuExpr obj, List<FuExpr#> args)
127132
{
128133
WritePostfix(obj, ".append(");
129134
FuType elementType = obj.Type.AsClassType().GetElementType();
130135
if (args.Count == 0)
131136
WriteNewStorage(elementType);
132137
else
133-
WriteCoerced(elementType, args[0], FuPriority.Argument);
138+
WriteElementCoerced(elementType, args[0]);
134139
WriteChar(')');
135140
}
136141

GenSwift.fu

Lines changed: 75 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,23 @@ public class GenSwift : GenPySwift
171171

172172
protected override void WriteLocalName!(FuSymbol symbol, FuPriority parent)
173173
{
174-
if (symbol.Parent is FuForeach forEach && forEach.Collection.Type is FuStringType) {
175-
Write("Int(");
176-
WriteCamelCaseNotKeyword(symbol.Name);
177-
Write(".value)");
174+
if (symbol.Parent is FuForeach loop) {
175+
assert loop.Collection.Type is FuClassType klass;
176+
if (klass.Class.Id == FuId.StringClass) {
177+
Write("Int(");
178+
WriteCamelCaseNotKeyword(symbol.Name);
179+
Write(".value)");
180+
return;
181+
}
182+
FuType elementType = symbol == loop.First ? klass.GetElementType() : klass.GetValueType();
183+
if (elementType.Id == FuId.IntType) {
184+
Write("Int(");
185+
WriteCamelCaseNotKeyword(symbol.Name);
186+
WriteChar(')');
187+
return;
188+
}
178189
}
179-
else
180-
base.WriteLocalName(symbol, parent);
190+
base.WriteLocalName(symbol, parent);
181191
}
182192

183193
protected override void WriteMemberOp!(FuExpr left, FuSymbolReference? symbol)
@@ -272,6 +282,8 @@ public class GenSwift : GenPySwift
272282
Write("UInt16");
273283
break;
274284
case FuId.IntType:
285+
Write("Int32");
286+
break;
275287
case FuId.NIntType:
276288
Write("Int");
277289
break;
@@ -310,12 +322,20 @@ public class GenSwift : GenPySwift
310322
}
311323
}
312324

325+
void WritePromotedType!(FuType type)
326+
{
327+
if (type.Id == FuId.IntType)
328+
Write("Int");
329+
else
330+
WriteType(type);
331+
}
332+
313333
protected override void WriteTypeAndName!(FuNamedValue value)
314334
{
315335
WriteName(value);
316336
if (!value.Type.IsFinal() || value.IsAssignableStorage()) {
317337
Write(" : ");
318-
WriteType(value.Type);
338+
WritePromotedType(value.Type);
319339
}
320340
}
321341

@@ -356,11 +376,21 @@ public class GenSwift : GenPySwift
356376
}
357377
}
358378

379+
static bool IsIntIndexing(FuExpr expr)
380+
{
381+
if (expr.Type.Id != FuId.IntType)
382+
return false;
383+
if (expr is FuUnaryExpr unary && (unary.Op == FuToken.Increment || unary.Op == FuToken.Decrement))
384+
expr = unary.Inner;
385+
return expr.IsIndexing();
386+
}
387+
359388
protected override void WriteCoercedInternal!(FuType type, FuExpr expr, FuPriority parent)
360389
{
361390
if (type is FuNumericType && !(expr is FuLiteral)
362-
&& GetTypeId(type, false) != GetTypeId(expr.Type, expr is FuBinaryExpr binary && binary.Op != FuToken.LeftBracket)) {
363-
WriteType(type);
391+
&& (GetTypeId(type, false) != GetTypeId(expr.Type, expr is FuBinaryExpr && !expr.IsIndexing()))
392+
|| IsIntIndexing(expr)) {
393+
WritePromotedType(type);
364394
WriteChar('(');
365395
if (type is FuIntegerType && expr is FuCallExpr call && call.Method.Symbol.Id == FuId.MathTruncate)
366396
call.Arguments[0].Accept(this, FuPriority.Argument);
@@ -432,6 +462,17 @@ public class GenSwift : GenPySwift
432462
WriteAdd(startIndex, length); // FIXME: side effect
433463
}
434464

465+
protected override void WriteElementCoerced!(FuType type, FuExpr value)
466+
{
467+
if (type.Id == FuId.IntType && !IsIntIndexing(value)) {
468+
Write("Int32(");
469+
value.Accept(this, FuPriority.Argument);
470+
WriteChar(')');
471+
}
472+
else
473+
WriteCoerced(type, value, FuPriority.Argument);
474+
}
475+
435476
bool AddVar!(string name)
436477
{
437478
HashSet<string>! vars = this.VarsAtIndent[this.Indent];
@@ -574,8 +615,9 @@ public class GenSwift : GenPySwift
574615
WriteChar(')');
575616
}
576617
else {
577-
Write(".fill");
578-
WriteCoercedArgsInParentheses(method, args);
618+
Write(".fill(");
619+
WriteElementCoerced(obj.Type.AsClassType().GetElementType(), args[0]);
620+
WriteChar(')');
579621
}
580622
break;
581623
case FuId.ArrayFillPart:
@@ -591,8 +633,13 @@ public class GenSwift : GenPySwift
591633
else {
592634
obj.Accept(this, FuPriority.Primary);
593635
WriteMemberOp(obj, null);
594-
Write("fill");
595-
WriteCoercedArgsInParentheses(method, args);
636+
Write("fill(");
637+
WriteElementCoerced(obj.Type.AsClassType().GetElementType(), args[0]);
638+
Write(", ");
639+
WriteCoerced(this.System.IntType, args[1], FuPriority.Argument);
640+
Write(", ");
641+
WriteCoerced(this.System.IntType, args[2], FuPriority.Argument);
642+
WriteChar(')');
596643
}
597644
break;
598645
case FuId.ArraySortAll:
@@ -960,7 +1007,7 @@ public class GenSwift : GenPySwift
9601007
case FuToken.ShiftRight when expr == binary.Left:
9611008
if (!(expr is FuLiteral)) {
9621009
FuType type = this.System.PromoteNumericTypes(binary.Left.Type, binary.Right.Type);
963-
if (type != expr.Type) {
1010+
if (type != expr.Type || IsIntIndexing(expr)) {
9641011
WriteCoerced(type, expr, parent);
9651012
return;
9661013
}
@@ -1009,7 +1056,16 @@ public class GenSwift : GenPySwift
10091056
WriteChar(' ');
10101057
Write(expr.GetOpString());
10111058
WriteChar(' ');
1012-
if (right is FuLiteralNull
1059+
if (IsIntIndexing(expr.Left)) {
1060+
if (IsIntIndexing(right))
1061+
right.Accept(this, FuPriority.Argument);
1062+
else {
1063+
Write("Int32(");
1064+
right.Accept(this, FuPriority.Argument);
1065+
WriteChar(')');
1066+
}
1067+
}
1068+
else if (right is FuLiteralNull
10131069
&& expr.Left is FuBinaryExpr leftBinary
10141070
&& leftBinary.Op == FuToken.LeftBracket
10151071
&& leftBinary.Left.Type is FuClassType dict
@@ -1418,7 +1474,7 @@ public class GenSwift : GenPySwift
14181474
protected override void WriteResultVar!()
14191475
{
14201476
Write("let result : ");
1421-
WriteType(this.CurrentMethod.Type);
1477+
WritePromotedType(this.CurrentMethod.Type);
14221478
}
14231479

14241480
void WriteSwiftCaseValue!(FuSwitch statement, FuExpr value)
@@ -1432,7 +1488,7 @@ public class GenSwift : GenPySwift
14321488
Write("let ");
14331489
WriteCamelCaseNotKeyword(def.Name);
14341490
Write(" as ");
1435-
WriteType(def.Type);
1491+
WritePromotedType(def.Type);
14361492
break;
14371493
case FuBinaryExpr when1 when when1.Op == FuToken.When:
14381494
WriteSwiftCaseValue(statement, when1.Left);
@@ -1516,7 +1572,7 @@ public class GenSwift : GenPySwift
15161572
else
15171573
WriteName(param);
15181574
Write(" : ");
1519-
WriteType(param.Type);
1575+
WritePromotedType(param.Type);
15201576
}
15211577

15221578
internal override void VisitEnumValue!(FuConst konst, FuConst? previous)
@@ -1695,7 +1751,7 @@ public class GenSwift : GenPySwift
16951751
Write(" throws");
16961752
if (method.Type.Id != FuId.VoidType) {
16971753
Write(" -> ");
1698-
WriteType(method.Type);
1754+
WritePromotedType(method.Type);
16991755
}
17001756
}
17011757
WriteNewLine();

0 commit comments

Comments
 (0)