Skip to content

Commit 1b6455f

Browse files
authored
docs: Update documentation (#115)
* C library definitions should allow naming overrides based on platform Fixes #91 * Updates the documentation for the 0.2.0 release.
1 parent 50de1f4 commit 1b6455f

File tree

6 files changed

+108
-66
lines changed

6 files changed

+108
-66
lines changed

README.md

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,43 @@ It's designed to make use of Scala's type system, macros, and runtime multi-stag
1111

1212
## Quickstart
1313

14-
Slinc is published to Maven Central for Scala 3. It is built to take advantage of the cutting edge of Scala functionality and features, so your project will most certainly need to track the latest Scala version if you want to use the latest version of Slinc. Currently, the Scala version in use is `3.2.0`.
14+
Slinc is published to Maven Central for Scala 3. It is built to take advantage of the cutting edge of Scala functionality and features, so your project will most certainly need to track the latest Scala version if you want to use the latest version of Slinc. Currently, the Scala version in use is `3.3.0-RC3`.
1515

16-
In order to test Slinc quick, one can use scala-cli:
16+
### SBT setup
17+
18+
In your `build.sbt`:
19+
20+
```scala
21+
libraryDependencies += "fr.hammons" %% "slinc-runtime" % "0.2.0"
22+
//if forking and on Java 17
23+
javaOptions ++= Seq("--add-modules=jdk.incubator.foreign", "--enable-native-access=ALL-UNNAMED")
24+
```
25+
26+
in .jvmopts in the root of your build:
27+
```
28+
--add-modules=jdk.incubator.foreign
29+
--enable-native-access=ALL-UNNAMED
30+
```
31+
32+
For additional setup instructions, please refer to the configuration page.
33+
34+
Once you have your build system set up, you can create a new file and write the following code:
1735

18-
### test.scala
1936
```scala
20-
using lib "fr.hammons::slinc-runtime:0.1.1-72-1cedff"
37+
import fr.hammons.slinc.runtime.given
2138

22-
import fr.hammons.slinc.runtime.{*,given}
39+
case class div_t(quot: CInt, rem: CInt) derives Struct
2340

24-
case class div_t(quot: CInt, rem: CInt) derives Struct
41+
trait MyLib derives Lib:
42+
def div(numer: CInt, denom: CInt): div_t
2543

26-
object MyLib derives Library:
27-
def abs(i: CInt): CInt = Library.binding
28-
def div(numer: CInt, denom: CInt): div_t = Library.binding
44+
val myLib = Lib.instance[MyLib]
2945

30-
@main def program =
31-
println(MyLib.abs(-5)) // prints 5
32-
println(MyLib.div(5,2)) // prints div_t(2,1)
46+
@main def calc =
47+
val (quot, rem) = Tuple.fromProduct(myLib.div(5,2))
48+
println(s"Got a quotient of $quot and a remainder of $rem")
3349
```
3450

35-
You can run this program with Java 19 via `scala-cli -j 19 -J --enable-native-access=ALL-UNNAMED test.scala` or with Java 17 via `scala-cli -j 17 -J --enable-native-access=ALL-UNNAMED -J --add-modules=jdk.incubator.foreign test.scala`.
51+
This library relies on the user importing the runtime from `fr.hammons.slinc.runtime`.
3652

3753
To learn more about the library, refer to the documentation website for Slinc [here](https://slinc.hammons.fr/docs/index.html)

core/docs/_docs/index.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ It's designed to make use of Scala's type system, macros, and runtime multi-stag
88

99
## Quickstart
1010

11-
Slinc is published to Maven Central for Scala 3. It is built to take advantage of the cutting edge of Scala functionality and features, so your project will most certainly need to track the latest Scala version if you want to use the latest version of Slinc. Currently, the Scala version in use is `3.2.1`.
11+
Slinc is published to Maven Central for Scala 3. It is built to take advantage of the cutting edge of Scala functionality and features, so your project will most certainly need to track the latest Scala version if you want to use the latest version of Slinc. Currently, the Scala version in use is `3.3.0-RC3`.
1212

1313
### SBT setup
1414

1515
In your `build.sbt`:
1616

1717
```scala
18-
libraryDependencies += "fr.hammons" %% "slinc-runtime" % "0.1.1-66-a2fa26-DIRTYd1a2c450"
18+
libraryDependencies += "fr.hammons" %% "slinc-runtime" % "0.2.0"
1919
//if forking and on Java 17
2020
javaOptions ++= Seq("--add-modules=jdk.incubator.foreign", "--enable-native-access=ALL-UNNAMED")
2121
```
@@ -31,15 +31,17 @@ For additional setup instructions, please refer to the configuration page.
3131
Once you have your build system set up, you can create a new file and write the following code:
3232

3333
```scala
34-
import fr.hammons.slinc.runtime.{*,given}
34+
import fr.hammons.slinc.runtime.given
3535

36-
case class div_t(quot: Int, rem: Int) derives Struct
36+
case class div_t(quot: CInt, rem: CInt) derives Struct
3737

38-
object MyLib derives Library:
39-
def div(numer: Int, denom: Int): div_t = Library.binding
38+
trait MyLib derives Lib:
39+
def div(numer: CInt, denom: CInt): div_t
40+
41+
val myLib = Lib.instance[MyLib]
4042

4143
@main def calc =
42-
val (quot, rem) = Tuple.fromProduct(MyLib.div(5,2))
44+
val (quot, rem) = Tuple.fromProduct(myLib.div(5,2))
4345
println(s"Got a quotient of $quot and a remainder of $rem")
4446
```
4547

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
title: "Library Modules"
3+
---
4+
5+
Library modules are groupings of functions in Slinc. Each can be configured in a number of ways.
6+
7+
A library module is a Scala `trait` that derives the `Lib` type class. Method declarations within it are used as a template for the bindings to C that the Slinc runtime will generate.
8+
9+
## Module Declarations
10+
11+
Module declarations are declarations of C library bindings without any entanglement in runtime details. This means that a module declaration only requires the use of the Slinc core library, and does not effect the runtime requirements of users of the module.
12+
13+
### Module naming
14+
15+
The type name of the module does not matter to Slinc.
16+
17+
### Method naming
18+
19+
The name of method declarations within a library module should reflect the name of the C function you wish to bind to. If a method name is not found in the C namespace, this will cause a runtime error when you try to summon the module implementation.
20+
21+
Example:
22+
23+
```scala
24+
trait L derives Lib:
25+
def abs(i: CInt): CInt
26+
```
27+
28+
This library module `L` has a binding to `abs` in the C standard library namespace.
29+
30+
#### Naming overrides
31+
32+
You can override the C name lookup for a method declaration on a host dependent basis with the `@NameOverride` annotation. You provide the `@NameOverride` annotation with the alternative name, and an OS and architecture tuple where the name should be used. An example follows:
33+
34+
```scala
35+
trait L derives Lib:
36+
@NameOverride("_time64", OS.Windows -> Arch.X64)
37+
def time(timer: Ptr[TimeT]): TimeT
38+
```
39+
40+
This function is helpful when you have a function symbol that should be present on a platform, but has an alternative name for some reason. In the case with Windows, the `time` function in the C standard library is a macro that points to `_time64` on 64-bit platforms, and `_time32` on 32-bit platforms. Since macros do not exist as symbols in the C standard library namespace, this `NameOverride` makes the Slinc platform choose the right function name on Windows X64.
41+
42+
## Summoning Module Implementations
43+
44+
Module declarations have been shown above, but they are not useable without being summoned. Doing so requires the Slinc runtime on your classpath, and makes the JAR and class files generated dependent on a specific JVM.
45+
46+
To summon a module implementation, you use the `Lib.instance[?]` method as shown in the following example:
47+
48+
```scala
49+
import fr.hammons.slinc.types.CInt
50+
import fr.hammons.slinc.Lib
51+
import fr.hammons.slinc.runtime.given
52+
53+
trait L derives Lib:
54+
def abs(i: CInt): CInt
55+
56+
val l = Lib.instance[L]
57+
58+
@main def program = println(l.abs(4))
59+
```
60+
61+
Note the assignment of the instance to a `val`. This is not strictly necessary, and `Lib.instance` will always return the same module instance, but re-summoning is more expensive than storing the summoned module implementation.

core/docs/_docs/reference/usage.md

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ title: Usage
44

55
## Introduction to Library Definitions
66

7-
All bindings by Slinc take place in library objects, groups of like methods that reflect C functions. When defining a library object, name is not particularly important. One merely defines an object that derives `Library`. Method bindings are done via a method binding with a name matching the C function in question, and parameters with types that match the C function in question.
7+
All bindings by Slinc take place in library traits, groups of like methods that reflect C functions. When defining a library trait, name is not particularly important. One merely defines an object that derives `Lib`. Method bindings are done via a method binding with a name matching the C function in question, and parameters with types that match the C function in question.
88

99
```scala
10-
object StdLib derives Library:
11-
def abs(i: Int): Int = Library.binding
10+
trait StdLib derives Lib:
11+
def abs(i: CInt): CInt
1212
```
1313

14-
The above defines a binding to the C standard library's `abs` method. Since the C definition of `abs` is defined like `int abs(int i)`, the scala version of the method is defined with a single input that has the type `Int` and the return type `Int`. The method is defined with `Library.binding` which is a macro that connects the inputs and outputs to the C world.
14+
The above defines a binding to the C standard library's `abs` method. Since the C definition of `abs` is defined like `int abs(int i)`, the scala version of the method is defined with a single input that has the type `CInt` and the return type `CInt`.
1515

1616
## Types
1717

@@ -45,52 +45,13 @@ Using the built in JVM primitives for a binding is quick and easy if you know th
4545
|TimeT|time_t|
4646

4747

48-
Since these types are only guaranteed to be defined at runtime, interacting with them can be difficult. There are three ways at present to interact with these types:
49-
50-
* Assured Conversion
51-
* Potential Conversion
52-
* Platform focus
53-
54-
### Assured Conversion
55-
56-
Assured conversion is done via the `.as` extension method on a compatible type, or to a compatible type. This method is generally available when there's some baseline guarantee about the kind and width of the type in question. For example, `CLong` is at minimum a 32-bit wide integer type, so `Int.as[CLong]` exists. It is also (for now) at maximum a 64-bit wide integer type, so `CLong.as[Long]` exists.
57-
58-
### Potential Conversion
59-
60-
Potential conversion is generally more available than the assured conversions. Potential conversion is done via the `maybeAs` extension method that will return an `Option` result indicating whether the conversion is valid on the current host.
61-
62-
As an example, `Long.maybeAs[CLong]` will return `Some(l: CLong)` on X64 Linux, but `None` on X64 Windows.
63-
64-
### Platform Focus
65-
66-
The `platformFocus` method takes a platform instance and a section of code where the host dependent types have automatic conversions to and from their definitions on the host platform. As an example:
67-
68-
```scala
69-
def labs(l: CLong): CLong = Library.binding
70-
71-
platformFocus(x64.Linux){
72-
//this line works here
73-
labs(-13l) == -13l //true
74-
}
75-
76-
//this line doesn't work here, cause outside of the above zone
77-
// CLong isn't equivalent to Long
78-
labs(-13l) == -13l
79-
```
80-
81-
The `platformFocus` method returns `Option[A]` where `A` is the return type of the platform focus zone. The method returns `None` if the platform selected for the zone doesn't match the host. This allows you to chain together platform specific code via `.orElse`.
82-
83-
The C types are meant to be analogues to the primitive types defined for C. In the table above, a number have equivalents to JVM types right now, but that may change in future versions of Slinc. If your wish is to write platform independent bindings to C libraries, then you should use the C types and forgo the standard JVM primitives. Usage of the standard JVM primitives will make your bindings brittle and platform specific at some point.
48+
Since these types are only guaranteed to be defined at runtime, interacting with them can be difficult.
8449

8550
## Pointers
8651

8752
Pointers are represented in Slinc with the `Ptr` type. For example, `Ptr[Int]` is a pointer to native memory that should be readable as a JVM Int.
8853

89-
The pointer class' operations are powered by three type classes:
90-
91-
* `LayoutOf` - this type class provides layout information about the type in question, if it exists.
92-
* `Send` - this type class shows how to copy data of type `A` from the JVM into native memory.
93-
* `Receive` - this type class shows how to copy data of type `A` from native memory into the JVM heap.
54+
The pointer class' operations are powered by the `DescriptorOf` typeclass.
9455

9556
The list of operations available on a `Ptr[A]`:
9657

@@ -110,4 +71,4 @@ The analog for C structs in Slinc are case classes that derive the `Struct` type
11071
case class div_t(quot: Int, rem: Int) derives Struct
11172
```
11273

113-
These struct analogs can be composed with any type that has a Send and/or Receive defined for it.
74+
These struct analogs can be composed with any type that has a `DescriptorOf` defined for it.

core/docs/sidebar.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ subsection:
66
subsection:
77
- page: reference/usage.md
88
- page: reference/jdk-support.md
9+
- page: reference/library-modules.md
910
- title: Contributing
1011
directory: docs/contributing
1112
page: contributing/contributing.md

core/src/fr/hammons/slinc/types/Basic.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ type CShort = Short
55
type CInt = Int
66
type CFloat = Float
77
type CDouble = Double
8+
type CLongLong = Long

0 commit comments

Comments
 (0)