Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions core/src/fr/hammons/slinc/Alias.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,12 @@ trait Alias[T] extends DescriptorOf[T]:
val name: String
val aliases: PartialFunction[(OS, Arch), RealTypeDescriptor]
lazy val descriptor: TypeDescriptor { type Inner >: T <: T } =
new AliasDescriptor[T](
AliasDescriptor[T](
aliases.applyOrElse(
os -> arch,
_ =>
throw new Error(
s"Alias for $name is not defined on platform $os - $arch"
)
)
):

val reader = (rwm, _) ?=> (mem, bytes) => rwm.readAlias(mem, bytes, real)
val writer = (rwm, _) ?=>
(mem, bytes, a) => rwm.writeAlias(mem, bytes, real, a)
)
2 changes: 2 additions & 0 deletions core/src/fr/hammons/slinc/Bytes.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fr.hammons.slinc

import scala.quoted.{ToExpr, Quotes}
import types.SizeT

opaque type Bytes = Long

Expand All @@ -15,6 +16,7 @@ object Bytes:
inline def -(b: Bytes): Bytes = a - b
inline def toLong: Long = a
inline def toBits: Long = a * 8
def sizeT = SizeT.maybe(a).get

given Numeric[Bytes] = Numeric.LongIsIntegral
given ToExpr[Bytes] with
Expand Down
6 changes: 4 additions & 2 deletions core/src/fr/hammons/slinc/CFunctionBindingGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,17 @@ object CFunctionBindingGenerator:
(sym, inputs) =>
def inputExprs(alloc: Expr[Allocator])(using q: Quotes) =
val prefix = if allocatingReturn then List(alloc.asTerm) else Nil
val toTransform = if varArg then inputs.init else inputs
val toTransform =
if varArg && inputs.nonEmpty then inputs.init
else inputs
LambdaInputs.choose(
prefix
.concat(toTransform)
.map(_.asExpr)
.zipWithIndex
.map: (exp, i) =>
'{ $inputTransitions(${ Expr(i) })($alloc, $exp) },
varArg
varArg && inputs.nonEmpty
)(inputs.last.asExprOf[Seq[Variadic]])

'{
Expand Down
4 changes: 2 additions & 2 deletions core/src/fr/hammons/slinc/CFunctionDescriptor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ object CFunctionDescriptor:
s"C Function analog ${methodSymbol.fullName} has unsupported type ${t.show}"
)

val isVariadic = argumentTypes.last match
case typ if typ =:= TypeRepr.of[Seq[Variadic]] =>
val isVariadic = argumentTypes.lastOption match
case Some(typ) if typ =:= TypeRepr.of[Seq[Variadic]] =>
true
case _ => false

Expand Down
14 changes: 11 additions & 3 deletions core/src/fr/hammons/slinc/TypeDescriptor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -146,15 +146,23 @@ trait StructDescriptor(
val transform: Tuple => Product
) extends RealTypeDescriptor

trait AliasDescriptor[A](val real: RealTypeDescriptor) extends TypeDescriptor:
case class AliasDescriptor[A](val real: RealTypeDescriptor)
extends TypeDescriptor:
type Inner = A
type RealInner = real.Inner

given bkwd: Conversion[Inner, real.Inner] with
given bkwd: Conversion[Inner, RealInner] with
def apply(x: Inner): real.Inner = x.asInstanceOf[real.Inner]

given fwd: Conversion[real.Inner, Inner] with
given fwd: Conversion[RealInner, Inner] with
def apply(x: real.Inner): Inner = x.asInstanceOf[Inner]

val reader: (ReadWriteModule, DescriptorModule) ?=> Reader[Inner] =
(rwm, _) ?=> (mem, bytes) => rwm.readAlias(mem, bytes, real)

val writer: (ReadWriteModule, DescriptorModule) ?=> Writer[Inner] =
(rwm, _) ?=> (mem, bytes, a) => rwm.writeAlias(mem, bytes, real, a)

override def size(using dm: DescriptorModule): Bytes = dm.sizeOf(real)
override def alignment(using dm: DescriptorModule): Bytes =
dm.alignmentOf(real)
Expand Down
5 changes: 2 additions & 3 deletions core/src/fr/hammons/slinc/types/CLong.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ object CLong:
case i: Int => IntegralAlias.transform[CLong](i)

def maybe(maybeFits: Long): Option[CLong] =
if (maybeFits <= Int.MaxValue && maybeFits >= Int.MinValue) || IntegralAlias
.range[CLong]
.contains(maybeFits)
if (maybeFits <= Int.MaxValue && maybeFits >= Int.MinValue) || (IntegralAlias
.min[CLong] <= maybeFits && maybeFits <= IntegralAlias.max[CLong])
then Some(IntegralAlias.transform[CLong](maybeFits))
else None

Expand Down
48 changes: 44 additions & 4 deletions core/src/fr/hammons/slinc/types/IntegralAlias.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,59 @@ import fr.hammons.slinc.ShortDescriptor
import fr.hammons.slinc.IntDescriptor

object IntegralAlias:
def min[T](using a: Alias[T]): Long = a.aliases.applyOrElse(
(os, arch),
_ => throw new Error(s"Alias for ${a.name} not defined for this platform")
) match
case ByteDescriptor => Byte.MinValue.toLong
case ShortDescriptor => Short.MinValue.toLong
case IntDescriptor => Int.MinValue.toLong
case LongDescriptor => Long.MinValue
case _ =>
throw new Error(
s"${a.name} is not an alias for an integral type on $os $arch"
)

def max[T](using a: Alias[T]): Long = a.aliases.applyOrElse(
(os, arch),
_ => throw new Error(s"Alias for ${a.name} not defined for this platform")
) match
case ByteDescriptor => Byte.MaxValue.toLong
case ShortDescriptor => Short.MaxValue.toLong
case IntDescriptor => Int.MaxValue.toLong
case LongDescriptor => Long.MaxValue
case _ =>
throw new Error(
s"${a.name} is not an alias for an integral type on $os $arch"
)

def range[T](using a: Alias[T]) = a.aliases.applyOrElse(
(os, arch),
_ => throw new Error(s"Alias for ${a.name} not defined for this platform")
) match
case ByteDescriptor => Byte.MinValue to Byte.MaxValue
case ShortDescriptor => Short.MinValue to Short.MaxValue
case IntDescriptor => Int.MinValue to Int.MaxValue
case LongDescriptor => Long.MinValue to Long.MaxValue
case ByteDescriptor => Range.Long.inclusive(Byte.MinValue, Byte.MaxValue, 1)
case ShortDescriptor =>
Range.Long.inclusive(Short.MinValue, Short.MaxValue, 1)
case IntDescriptor => Range.Long.inclusive(Int.MinValue, Int.MaxValue, 1)
case LongDescriptor => Long.MinValue to Long.MaxValue
case _ =>
throw new Error(
s"${a.name} is not an alias for an integral type on $os $arch"
)

def toLong[T](value: T)(using a: Alias[T]) = a.aliases.applyOrElse(
(os, arch),
_ => throw new Error(s"Alias for ${a.name} not defined for this platform")
) match
case ByteDescriptor => value.asInstanceOf[Byte].toLong
case ShortDescriptor => value.asInstanceOf[Short].toLong
case IntDescriptor => value.asInstanceOf[Int].toLong
case LongDescriptor => value.asInstanceOf[Long].toLong
case _ =>
throw new Error(
s"${a.name} is not an alias for an integral type on $os - $arch"
)

def transform[T]: Transform[T] = Transform[T]
class Transform[T]:
def apply[U](value: U)(using a: Alias[T], n: Numeric[U]) =
Expand Down
12 changes: 6 additions & 6 deletions core/src/fr/hammons/slinc/types/SizeT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@ import fr.hammons.slinc.LongDescriptor

opaque type SizeT = AnyVal

given Alias[SizeT] with
val name = "SizeT"
val aliases = { case (OS.Linux | OS.Darwin | OS.Windows, Arch.X64) =>
LongDescriptor
}

object SizeT:
def apply(value: Short | Byte): SizeT = value match
case s: Short => IntegralAlias.transform[SizeT](s)
Expand All @@ -24,3 +18,9 @@ object SizeT:
if value < 65536 || IntegralAlias.range[SizeT].contains(value) then
Some(IntegralAlias.transform[SizeT](value))
else None

given Alias[SizeT] with
val name = "SizeT"
val aliases = { case (OS.Linux | OS.Darwin | OS.Windows, Arch.X64) =>
LongDescriptor
}
12 changes: 6 additions & 6 deletions core/src/fr/hammons/slinc/types/TimeT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@ import fr.hammons.slinc.LongDescriptor

opaque type TimeT = Any

given Alias[TimeT] with
val name: String = "TimeT"
val aliases = { case (OS.Windows | OS.Linux | OS.Darwin, Arch.X64) =>
LongDescriptor
}

object TimeT:
def maybe(value: Byte | Short | Int | Long): Option[TimeT] =
val upcast = value match
Expand All @@ -22,3 +16,9 @@ object TimeT:
if IntegralAlias.range[TimeT].contains(upcast) then
Some(IntegralAlias.transform[TimeT](upcast))
else None

given Alias[TimeT] with
val name: String = "TimeT"
val aliases = { case (OS.Windows | OS.Linux | OS.Darwin, Arch.X64) =>
LongDescriptor
}
Loading