@@ -16,18 +16,28 @@ object Translator {
16
16
.flatMap(gen => file.typeDefs.map(td => (gen.decl(td), gen.impl(td))))
17
17
.unzip
18
18
val (fnDecls, fnImpls) = file.fns.map(helper.fnToC).unzip
19
+ val ctorDecls = file.typeDefs.flatMap(typ =>
20
+ typ.cases.map(variant => s " ${ctorSig(typ, variant)}; " )
21
+ )
22
+ val ctorImpls = file.typeDefs.flatMap { typ =>
23
+ typ.cases.map { variant =>
24
+ s " ${ctorSig(typ, variant)} { \n ${indent(1 )(ctorImpl(typ, variant))}\n } "
25
+ }
26
+ }
19
27
val generated =
20
28
file.typeDefs.map(helper.translateType).mkString(" " , " \n " , " \n " )
21
29
+ genDecls.mkString(" " , " \n " , " \n " )
30
+ + ctorDecls.mkString(" " , " \n " , " \n " )
22
31
+ fnDecls.mkString(" " , " \n " , " \n " )
23
32
+ genImpls.mkString(" " , " \n " , " \n " )
33
+ + ctorImpls.mkString(" " , " \n " , " \n " )
24
34
+ fnImpls.mkString(" " , " \n " , " \n " )
25
35
" #include \" runtime.h\"\n\n " + generated
26
36
.replaceAll(raw " \n(\s|\n)*\n " , " \n " )
27
37
.strip() + " \n "
28
38
}
29
39
30
- trait GeneratedFn (unmangledName : String ) {
40
+ private trait GeneratedFn (unmangledName : String ) {
31
41
def returnType : String
32
42
33
43
def body (typ : TypeDef )(using Bindings , Cycles ): String
@@ -269,6 +279,39 @@ object Translator {
269
279
}
270
280
}
271
281
282
+ private def ctorName (variant : EnumCase ): String =
283
+ s " new $$ ${variant.name.value}"
284
+
285
+ private def ctorSig (typ : TypeDef , variant : EnumCase ): String = {
286
+ val params = variant.fields.toSeq
287
+ .sortBy(_.name.value)
288
+ .map(field => s " ${typeRefToC(field.typ.name)} ${field.name.value}" )
289
+ .mkString(" , " )
290
+ s " ${typeRefToC(typ.name)} ${ctorName(variant)}( $params) "
291
+ }
292
+
293
+ private def ctorImpl (typ : TypeDef , variant : EnumCase )(using
294
+ bindings : Bindings
295
+ ): String = {
296
+ val resVar = " $res"
297
+ val setFields = variant.fields
298
+ .map { field =>
299
+ val fieldAccess =
300
+ s " $resVar-> ${cFieldName(field.name.value, typ, variant)}"
301
+ s """ | $fieldAccess = ${field.name.value};
302
+ | ${incrRc(fieldAccess, bindings.getType(field.typ))}""" .stripMargin
303
+ }
304
+ .mkString(" \n " )
305
+ s """ | ${typeRefToC(typ.name)} $resVar = malloc(sizeof (struct ${typ.name}));
306
+ | $resVar->rc = 0;
307
+ | $resVar->color = kBlack;
308
+ | $resVar->addedPCR = 0;
309
+ | $resVar->print = ${Printer .name(typ)};
310
+ | $resVar->kind = ${tagName(variant.name.value)};
311
+ | $setFields
312
+ |return $resVar; """ .stripMargin
313
+ }
314
+
272
315
private def switch (expr : String , typ : TypeDef )(
273
316
createArm : EnumCase => String
274
317
): String = {
@@ -544,36 +587,17 @@ object Translator {
544
587
s " ${mangleFnName(fnName.value)}( ${argsToC.mkString(" , " )}) " ,
545
588
teardowns.mkString(" \n " )
546
589
)
547
- case CtorCall (ctorName, values, span) =>
548
- val (typ, variant) = bindings.ctors(ctorName.value)
549
- val resVar = newVar(" ctorres" )
550
- val valueSetups = values
551
- .map { case (fieldName, value) =>
552
- val fieldType = bindings.types(
553
- variant.fields
554
- .find(_.name.value == fieldName.value)
555
- .get
556
- .typ
557
- .name
558
- )
559
- val (valueSetup, valueToC, valueTeardown) = exprToC(value)
560
- val fieldAccess =
561
- s " $resVar-> ${cFieldName(fieldName.value, typ, variant)}"
562
- s """ | $valueSetup
563
- | $fieldAccess = $valueToC;
564
- | ${incrRc(fieldAccess, fieldType)}
565
- | $valueTeardown""" .stripMargin
566
- }
567
- .mkString(" \n " )
568
- val setup =
569
- s """ | ${typeRefToC(typ.name)} $resVar = malloc(sizeof (struct ${typ.name}));
570
- | $resVar->rc = 0;
571
- | $resVar->color = kBlack;
572
- | $resVar->addedPCR = 0;
573
- | $resVar->print = ${Printer .name(typ)};
574
- | $resVar->kind = ${tagName(ctorName.value)};
575
- | $valueSetups""" .stripMargin
576
- (setup, resVar, " " )
590
+ case CtorCall (ctorNameSpanned, values, span) =>
591
+ val (typ, variant) = bindings.ctors(ctorNameSpanned.value)
592
+ val (setups, args, teardowns) = values.toSeq
593
+ .sortBy((fieldName, _) => fieldName.value)
594
+ .map((_, value) => exprToC(value))
595
+ .unzip3
596
+ (
597
+ setups.mkString(" \n " ),
598
+ s " ${ctorName(variant)}( ${args.mkString(" , " )}) " ,
599
+ teardowns.mkString(" \n " )
600
+ )
577
601
case matchExpr @ MatchExpr (obj, arms, _) =>
578
602
val (objSetup, objToC, objTeardown) = exprToC(obj)
579
603
val objType = typer.types(obj).asInstanceOf [TypeDef ]
0 commit comments