@@ -4103,6 +4103,16 @@ class JSCodeGen()(using genCtx: Context) {
4103
4103
js.UnaryOp (js.UnaryOp .UnwrapFromThrowable ,
4104
4104
js.UnaryOp (js.UnaryOp .CheckNotNull , genArgs1))
4105
4105
4106
+ case LINKTIME_IF =>
4107
+ // LinkingInfo.linkTimeIf(cond, thenp, elsep)
4108
+ val cond = genLinkTimeExpr(args(0 ))
4109
+ val thenp = genExpr(args(1 ))
4110
+ val elsep = genExpr(args(2 ))
4111
+ val tpe =
4112
+ if (isStat) jstpe.VoidType
4113
+ else toIRType(tree.tpe)
4114
+ js.LinkTimeIf (cond, thenp, elsep)(tpe)
4115
+
4106
4116
case UNION_FROM | UNION_FROM_TYPE_CONSTRUCTOR =>
4107
4117
/* js.|.from and js.|.fromTypeConstructor
4108
4118
* We should not have to deal with those. They have a perfectly valid
@@ -4128,6 +4138,91 @@ class JSCodeGen()(using genCtx: Context) {
4128
4138
}
4129
4139
}
4130
4140
4141
+ private def genLinkTimeExpr (tree : Tree ): js.Tree = {
4142
+ import dotty .tools .backend .ScalaPrimitivesOps .*
4143
+
4144
+ import primitives .*
4145
+
4146
+ implicit val pos = tree.span
4147
+
4148
+ def invalid (): js.Tree = {
4149
+ report.error(
4150
+ " Illegal expression in the condition of a linkTimeIf. " +
4151
+ " Valid expressions are: boolean and int primitives; " +
4152
+ " references to link-time properties; " +
4153
+ " primitive operations on booleans; " +
4154
+ " and comparisons on ints." ,
4155
+ tree.sourcePos)
4156
+ js.BooleanLiteral (false )
4157
+ }
4158
+
4159
+ tree match {
4160
+ case Literal (c) =>
4161
+ import Constants .*
4162
+ c.tag match {
4163
+ case BooleanTag => js.BooleanLiteral (c.booleanValue)
4164
+ case IntTag => js.IntLiteral (c.intValue)
4165
+ case _ => invalid()
4166
+ }
4167
+
4168
+ case Apply (fun, args) =>
4169
+ fun.symbol.getAnnotation(jsdefn.LinkTimePropertyAnnot ) match {
4170
+ case Some (annotation) =>
4171
+ val propName = annotation.argumentConstantString(0 ).get
4172
+ js.LinkTimeProperty (propName)(toIRType(tree.tpe))
4173
+
4174
+ case None if isPrimitive(fun.symbol) =>
4175
+ val code = getPrimitive(fun.symbol)
4176
+ val receiver = (fun : @ unchecked) match {
4177
+ case fun : Select => fun.qualifier
4178
+ case fun : Ident => desugarIdent(fun).get.qualifier
4179
+ }
4180
+
4181
+ def genLhs : js.Tree = genLinkTimeExpr(receiver)
4182
+ def genRhs : js.Tree = genLinkTimeExpr(args.head)
4183
+
4184
+ def unaryOp (op : js.UnaryOp .Code ): js.Tree =
4185
+ js.UnaryOp (op, genLhs)
4186
+ def binaryOp (op : js.BinaryOp .Code ): js.Tree =
4187
+ js.BinaryOp (op, genLhs, genRhs)
4188
+
4189
+ toIRType(receiver.tpe) match {
4190
+ case jstpe.BooleanType =>
4191
+ (code : @ switch) match {
4192
+ case ZNOT => unaryOp(js.UnaryOp .Boolean_! )
4193
+ case EQ => binaryOp(js.BinaryOp .Boolean_== )
4194
+ case NE | XOR => binaryOp(js.BinaryOp .Boolean_!= )
4195
+ case OR => binaryOp(js.BinaryOp .Boolean_| )
4196
+ case AND => binaryOp(js.BinaryOp .Boolean_& )
4197
+ case ZOR => js.LinkTimeIf (genLhs, js.BooleanLiteral (true ), genRhs)(jstpe.BooleanType )
4198
+ case ZAND => js.LinkTimeIf (genLhs, genRhs, js.BooleanLiteral (false ))(jstpe.BooleanType )
4199
+ case _ => invalid()
4200
+ }
4201
+
4202
+ case jstpe.IntType =>
4203
+ (code : @ switch) match {
4204
+ case EQ => binaryOp(js.BinaryOp .Int_== )
4205
+ case NE => binaryOp(js.BinaryOp .Int_!= )
4206
+ case LT => binaryOp(js.BinaryOp .Int_< )
4207
+ case LE => binaryOp(js.BinaryOp .Int_<= )
4208
+ case GT => binaryOp(js.BinaryOp .Int_> )
4209
+ case GE => binaryOp(js.BinaryOp .Int_>= )
4210
+ case _ => invalid()
4211
+ }
4212
+
4213
+ case _ =>
4214
+ invalid()
4215
+ }
4216
+
4217
+ case None => // if !isPrimitive
4218
+ invalid()
4219
+ }
4220
+
4221
+ case _ =>
4222
+ invalid()
4223
+ }
4224
+ }
4225
+
4131
4226
/** Gen the SJSIR for a reflective call.
4132
4227
*
4133
4228
* Reflective calls are calls to a structural type field or method that
0 commit comments