1
1
package fr .hammons .slinc
2
2
3
- import java .lang .invoke .MethodHandle
4
3
import scala .quoted .*
5
4
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
7
10
8
- type InputTransition = (Allocator , Any ) => Any
9
- type OutputTransition = (Object | Null ) => AnyRef
10
11
trait CFunctionBindingGenerator :
11
12
def generate (
12
13
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
19
17
): AnyRef
20
18
21
19
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 ]])
36
25
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" )
37
34
private def invokation (
38
- vTransition : Expr [TransitionModule ],
35
+ variadicTransition : Expr [VariadicTransition ],
39
36
mh : Expr [MethodHandler ]
40
37
)(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) =>
44
41
MethodHandleTools .invokeArguments(
45
42
' { $mh.nonVariadic },
46
- args.normalArgs
43
+ args
47
44
)
48
- case Some ( varArgs) =>
45
+ case LambdaInputs . VariadicInputs (args, varArgs) =>
49
46
' {
50
47
MethodHandleFacade .callVariadic(
51
48
$mh.variadic($varArgs),
52
- $ { Expr .ofList(args.normalArgs) } ++ getVariadicExprs(
53
- $varArgs,
54
- $vTransition,
55
- $alloc
56
- )*
49
+ $ { Expr .ofList(args) } ++ $variadicTransition($alloc, $varArgs)*
57
50
)
58
51
}
59
52
@@ -63,11 +56,12 @@ object CFunctionBindingGenerator:
63
56
applyImpl[L ](' name )
64
57
}
65
58
66
- private def lambda2 (
59
+ @ nowarn(" msg=unused implicit parameter" )
60
+ private def lambda (
67
61
argNumbers : Int ,
68
62
scope : Expr [Scope ],
69
63
inputTransitions : Expr [IArray [InputTransition ]],
70
- outputTransition : Expr [OutputTransition ],
64
+ outputTransition : Expr [ReturnTransition ],
71
65
allocatingReturn : Boolean ,
72
66
varArg : Boolean
73
67
)(
@@ -95,15 +89,15 @@ object CFunctionBindingGenerator:
95
89
def inputExprs (alloc : Expr [Allocator ])(using q : Quotes ) =
96
90
val prefix = if allocatingReturn then List (alloc.asTerm) else Nil
97
91
val toTransform = if varArg then inputs.init else inputs
98
- LambdaInputs (
92
+ LambdaInputs .choose (
99
93
prefix
100
94
.concat(toTransform)
101
95
.map(_.asExpr)
102
96
.zipWithIndex
103
97
.map: (exp, i) =>
104
98
' { $inputTransitions($ { Expr (i) })($alloc, $exp) },
105
- Option .unless( ! varArg)(inputs.last.asExprOf[ Seq [ Variadic ]])
106
- )
99
+ varArg
100
+ )(inputs.last.asExprOf[ Seq [ Variadic ]])
107
101
108
102
' {
109
103
$scope { alloc ?=>
@@ -132,28 +126,29 @@ object CFunctionBindingGenerator:
132
126
new CFunctionBindingGenerator :
133
127
def generate (
134
128
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 ))
151
143
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
+ }
157
153
}
158
- }
159
154
}
0 commit comments