Skip to content

Commit ee172df

Browse files
committed
Refactor LibModules and CFunctionBindingGenerator to be simpler
1 parent 783c825 commit ee172df

File tree

4 files changed

+137
-136
lines changed

4 files changed

+137
-136
lines changed
Lines changed: 57 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,52 @@
11
package fr.hammons.slinc
22

3-
import java.lang.invoke.MethodHandle
43
import scala.quoted.*
54
import scala.annotation.nowarn
6-
import fr.hammons.slinc.modules.TransitionModule
5+
import fr.hammons.slinc.CFunctionRuntimeInformation.{
6+
InputTransition,
7+
ReturnTransition
8+
}
9+
import fr.hammons.slinc.CFunctionBindingGenerator.VariadicTransition
710

8-
type InputTransition = (Allocator, Any) => Any
9-
type OutputTransition = (Object | Null) => AnyRef
1011
trait CFunctionBindingGenerator:
1112
def generate(
1213
methodHandler: MethodHandler,
13-
inputTransitions: IArray[InputTransition],
14-
variadicTransition: TransitionModule,
15-
outputTransition: OutputTransition,
16-
scope: Scope,
17-
allocatingReturn: Boolean,
18-
variadic: Boolean
14+
transitionSet: CFunctionRuntimeInformation,
15+
variadicTransition: VariadicTransition,
16+
scope: Scope
1917
): AnyRef
2018

2119
object CFunctionBindingGenerator:
22-
private case class LambdaInputs(
23-
normalArgs: List[Expr[Any]],
24-
varArgs: Option[Expr[Seq[Variadic]]]
25-
)
26-
27-
private def getVariadicExprs(
28-
s: Seq[Variadic],
29-
variadicTransition: TransitionModule,
30-
allocator: Allocator
31-
): Seq[Any] =
32-
s.map: vararg =>
33-
vararg.use[DescriptorOf](dc ?=>
34-
d => variadicTransition.methodArgument(dc.descriptor, d, allocator)
35-
)
20+
type VariadicTransition = (Allocator, Seq[Variadic]) => Seq[Any]
21+
22+
private enum LambdaInputs:
23+
case Standard(args: List[Expr[Any]])
24+
case VariadicInputs(args: List[Expr[Any]], varArgs: Expr[Seq[Variadic]])
3625

26+
private object LambdaInputs:
27+
def choose(args: List[Expr[Any]], isVariadic: Boolean)(
28+
variadicInput: => Expr[Seq[Variadic]]
29+
) = if isVariadic then
30+
LambdaInputs.VariadicInputs(args, varArgs = variadicInput)
31+
else LambdaInputs.Standard(args)
32+
33+
@nowarn("msg=unused implicit parameter")
3734
private def invokation(
38-
vTransition: Expr[TransitionModule],
35+
variadicTransition: Expr[VariadicTransition],
3936
mh: Expr[MethodHandler]
4037
)(using Quotes) =
41-
(alloc: Expr[Allocator], args: LambdaInputs) =>
42-
args.varArgs match
43-
case None =>
38+
(alloc: Expr[Allocator], inputs: LambdaInputs) =>
39+
inputs match
40+
case LambdaInputs.Standard(args) =>
4441
MethodHandleTools.invokeArguments(
4542
'{ $mh.nonVariadic },
46-
args.normalArgs
43+
args
4744
)
48-
case Some(varArgs) =>
45+
case LambdaInputs.VariadicInputs(args, varArgs) =>
4946
'{
5047
MethodHandleFacade.callVariadic(
5148
$mh.variadic($varArgs),
52-
${ Expr.ofList(args.normalArgs) } ++ getVariadicExprs(
53-
$varArgs,
54-
$vTransition,
55-
$alloc
56-
)*
49+
${ Expr.ofList(args) } ++ $variadicTransition($alloc, $varArgs)*
5750
)
5851
}
5952

@@ -63,11 +56,12 @@ object CFunctionBindingGenerator:
6356
applyImpl[L]('name)
6457
}
6558

66-
private def lambda2(
59+
@nowarn("msg=unused implicit parameter")
60+
private def lambda(
6761
argNumbers: Int,
6862
scope: Expr[Scope],
6963
inputTransitions: Expr[IArray[InputTransition]],
70-
outputTransition: Expr[OutputTransition],
64+
outputTransition: Expr[ReturnTransition],
7165
allocatingReturn: Boolean,
7266
varArg: Boolean
7367
)(
@@ -95,15 +89,15 @@ object CFunctionBindingGenerator:
9589
def inputExprs(alloc: Expr[Allocator])(using q: Quotes) =
9690
val prefix = if allocatingReturn then List(alloc.asTerm) else Nil
9791
val toTransform = if varArg then inputs.init else inputs
98-
LambdaInputs(
92+
LambdaInputs.choose(
9993
prefix
10094
.concat(toTransform)
10195
.map(_.asExpr)
10296
.zipWithIndex
10397
.map: (exp, i) =>
10498
'{ $inputTransitions(${ Expr(i) })($alloc, $exp) },
105-
Option.unless(!varArg)(inputs.last.asExprOf[Seq[Variadic]])
106-
)
99+
varArg
100+
)(inputs.last.asExprOf[Seq[Variadic]])
107101

108102
'{
109103
$scope { alloc ?=>
@@ -132,28 +126,29 @@ object CFunctionBindingGenerator:
132126
new CFunctionBindingGenerator:
133127
def generate(
134128
methodHandler: MethodHandler,
135-
inputTransitions: IArray[InputTransition],
136-
variadicTransition: TransitionModule,
137-
outputTransition: OutputTransition,
138-
scope: Scope,
139-
allocatingReturn: Boolean,
140-
variadic: Boolean
141-
): AnyRef = ${
142-
val lamdaGen = (allocatingReturn: Boolean, variadic: Boolean) =>
143-
lambda2(
144-
methodSymbol.paramSymss.map(_.size).sum,
145-
'scope,
146-
'inputTransitions,
147-
'outputTransition,
148-
allocatingReturn,
149-
variadic
150-
)(invokation('variadicTransition, 'methodHandler))
129+
functionInformation: CFunctionRuntimeInformation,
130+
variadicTransition: VariadicTransition,
131+
scope: Scope
132+
): AnyRef =
133+
${
134+
def lambdaGen(allocatingReturn: Boolean, variadic: Boolean) =
135+
lambda(
136+
methodSymbol.paramSymss.map(_.size).sum,
137+
'scope,
138+
'{ functionInformation.inputTransitions },
139+
'{ functionInformation.returnTransition },
140+
allocatingReturn,
141+
variadic
142+
)(invokation('variadicTransition, 'methodHandler))
151143

152-
'{
153-
if allocatingReturn && variadic then ${ lamdaGen(true, true) }
154-
else if allocatingReturn then ${ lamdaGen(true, false) }
155-
else if variadic then ${ lamdaGen(false, true) }
156-
else ${ lamdaGen(false, false) }
144+
'{
145+
if functionInformation.isVariadic && functionInformation.returnAllocates
146+
then ${ lambdaGen(allocatingReturn = true, variadic = true) }
147+
else if functionInformation.isVariadic then
148+
${ lambdaGen(allocatingReturn = false, variadic = true) }
149+
else if functionInformation.returnAllocates then
150+
${ lambdaGen(allocatingReturn = true, variadic = false) }
151+
else ${ lambdaGen(allocatingReturn = false, variadic = false) }
152+
}
157153
}
158-
}
159154
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package fr.hammons.slinc
2+
3+
import fr.hammons.slinc.modules.TransitionModule
4+
import fr.hammons.slinc.CFunctionRuntimeInformation.InputTransition
5+
import fr.hammons.slinc.CFunctionRuntimeInformation.ReturnTransition
6+
7+
final case class CFunctionRuntimeInformation(
8+
name: String,
9+
inputDescriptors: Seq[TypeDescriptor],
10+
inputTransitions: IArray[InputTransition],
11+
returnDescriptor: Option[TypeDescriptor],
12+
returnTransition: ReturnTransition,
13+
isVariadic: Boolean,
14+
returnAllocates: Boolean
15+
)
16+
17+
object CFunctionRuntimeInformation:
18+
def apply(functionDescriptor: CFunctionDescriptor)(using
19+
transitionModule: TransitionModule
20+
) =
21+
val allocatingReturn = functionDescriptor.returnDescriptor
22+
.map:
23+
case ad: AliasDescriptor[?] => ad.real
24+
case a => a
25+
.exists:
26+
case _: StructDescriptor => true
27+
case _ => false
28+
29+
val allocationTransition: Seq[InputTransition] =
30+
if allocatingReturn then
31+
Seq((allocator, _) => transitionModule.methodArgument(allocator))
32+
else Seq.empty
33+
34+
val inputTransitions: Seq[InputTransition] =
35+
functionDescriptor.inputDescriptors.map: typeDescriptor =>
36+
(allocator, input) =>
37+
transitionModule.methodArgument(typeDescriptor, input, allocator)
38+
val outputTransition: ReturnTransition =
39+
functionDescriptor.returnDescriptor match
40+
case None => _ => ().asInstanceOf[Object]
41+
case Some(descriptor) =>
42+
returnValue =>
43+
transitionModule.methodReturn[Object](descriptor, returnValue.nn)
44+
45+
new CFunctionRuntimeInformation(
46+
functionDescriptor.name,
47+
functionDescriptor.inputDescriptors,
48+
IArray.from(allocationTransition ++ inputTransitions),
49+
functionDescriptor.returnDescriptor,
50+
outputTransition,
51+
functionDescriptor.isVariadic,
52+
allocatingReturn
53+
)
54+
55+
type InputTransition = (Allocator, Any) => Any
56+
type ReturnTransition = (Object | Null) => AnyRef

j17/src/fr/hammons/slinc/modules/LibModule17.scala

Lines changed: 13 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
package fr.hammons.slinc.modules
22

33
import fr.hammons.slinc.LibBacking
4-
import fr.hammons.slinc.Allocator
54
import java.util.concurrent.atomic.AtomicReference
65
import fr.hammons.slinc.CFunctionBindingGenerator
7-
import fr.hammons.slinc.OutputTransition
86
import fr.hammons.slinc.CFunctionDescriptor
97
import fr.hammons.slinc.MethodHandler
108
import fr.hammons.slinc.Variadic
11-
import fr.hammons.slinc.AliasDescriptor
12-
import fr.hammons.slinc.StructDescriptor
9+
import fr.hammons.slinc.CFunctionRuntimeInformation
10+
import fr.hammons.slinc.DescriptorOf
1311

1412
given libraryModule17: LibModule with
1513
val runtimeVersion = 17
@@ -28,44 +26,20 @@ given libraryModule17: LibModule with
2826
getDowncall(cfd, v).bindTo(addr).nn
2927
)
3028

31-
val allocatingReturn = cfd.returnDescriptor
32-
.map:
33-
case ad: AliasDescriptor[?] => ad.real
34-
case a => a
35-
.exists:
36-
case _: StructDescriptor => true
37-
case _ => false
38-
39-
val prefixTransition =
40-
if allocatingReturn then
41-
List((a: Allocator, _: Any) =>
42-
transitionModule17.methodArgument(a)
43-
)
44-
else Nil
45-
46-
val regularTransitions =
47-
cfd.inputDescriptors
48-
.map: td =>
49-
(a: Allocator) ?=> transitionModule17.methodArgument(td, _, a)
50-
.map: fn =>
51-
(a: Allocator, b: Any) => fn(using a)(b)
52-
53-
val retTransition: OutputTransition = cfd.returnDescriptor
54-
.map: td =>
55-
(o: Object | Null) =>
56-
transitionModule17.methodReturn[AnyRef](td, o.nn)
57-
.getOrElse: (_: Object | Null) =>
58-
().asInstanceOf[Object]
59-
6029
val fn =
6130
generator.generate(
6231
mh,
63-
IArray.from(prefixTransition ++ regularTransitions),
64-
transitionModule17,
65-
retTransition,
66-
tempScope(),
67-
allocatingReturn,
68-
cfd.isVariadic
32+
CFunctionRuntimeInformation(cfd),
33+
(allocator, varArgs) =>
34+
varArgs.map: varArg =>
35+
varArg.use[DescriptorOf]: descriptorOf ?=>
36+
data =>
37+
transitionModule17.methodArgument(
38+
descriptorOf.descriptor,
39+
data,
40+
allocator
41+
),
42+
tempScope()
6943
)
7044

7145
AtomicReference(fn)

j19/src/fr/hammons/slinc/modules/LibModule19.scala

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -22,44 +22,20 @@ given libModule19: LibModule with
2222
getDowncall(cfd, v).bindTo(addr).nn
2323
)
2424

25-
val allocatingReturn = cfd.returnDescriptor
26-
.map:
27-
case ad: AliasDescriptor[?] => ad.real
28-
case a => a
29-
.exists:
30-
case _: StructDescriptor => true
31-
case _ => false
32-
33-
val prefixTransition =
34-
if allocatingReturn then
35-
List((a: Allocator, _: Any) =>
36-
transitionModule19.methodArgument(a)
37-
)
38-
else Nil
39-
40-
val regularTransitions =
41-
cfd.inputDescriptors
42-
.map: td =>
43-
(a: Allocator) ?=> transitionModule19.methodArgument(td, _, a)
44-
.map: fn =>
45-
(a: Allocator, b: Any) => fn(using a)(b)
46-
47-
val retTransition: OutputTransition = cfd.returnDescriptor
48-
.map: td =>
49-
(o: Object | Null) =>
50-
transitionModule19.methodReturn[Object](td, o.nn)
51-
.getOrElse: (_: Object | Null) =>
52-
().asInstanceOf[Object]
53-
5425
val fn =
5526
generator.generate(
5627
mh,
57-
IArray.from(prefixTransition.concat(regularTransitions)),
58-
transitionModule19,
59-
retTransition,
60-
tempScope(),
61-
allocatingReturn,
62-
cfd.isVariadic
28+
CFunctionRuntimeInformation(cfd),
29+
(allocator, varArgs) =>
30+
varArgs.map: varArg =>
31+
varArg.use[DescriptorOf]: descriptorOf ?=>
32+
data =>
33+
transitionModule19.methodArgument(
34+
descriptorOf.descriptor,
35+
data,
36+
allocator
37+
),
38+
tempScope()
6339
)
6440

6541
AtomicReference(fn)

0 commit comments

Comments
 (0)