Skip to content

Runestone

PucklaJ edited this page Dec 28, 2024 · 6 revisions

Runestone Documentation

A runestone is an intermediate language used to create an intermediate layer between two languages and therefore allow simpler bindings.

Table of Contents

  1. Example File
    Looking examples is always better than just looking at walls of text.
  2. File Syntax
    Overview over all the sections in a runestone file.
  3. Types Syntax
    Explaining the syntax of runestone types.

Example File

It is implemented as an ini-like file format that looks as follows:

This is a runestone generated from olive.c which is an amazing software rendering library created by Azozin

version = 0

os = Linux
arch = x86_64

[lib]
static = libolivec.a

[symbols]
func.olivec_canvas = Olivec_Canvas pixels #UInt32 #Attr Ptr 1 #AttrEnd width #UInt64 height #UInt64 stride #UInt64
func.olivec_subcanvas = Olivec_Canvas oc Olivec_Canvas x #SInt32 y #SInt32 w #SInt32 h #SInt32
func.olivec_in_bounds = #Bool8 oc Olivec_Canvas x #SInt32 y #SInt32
func.olivec_blend_color = #Untyped c1 #UInt32 #Attr Ptr 1 #AttrEnd c2 #UInt32
func.olivec_fill = #Untyped oc Olivec_Canvas color #UInt32
func.olivec_rect = #Untyped oc Olivec_Canvas x #SInt32 y #SInt32 w #SInt32 h #SInt32 color #UInt32
func.olivec_frame = #Untyped oc Olivec_Canvas x #SInt32 y #SInt32 w #SInt32 h #SInt32 thiccness #UInt64 color #UInt32
func.olivec_circle = #Untyped oc Olivec_Canvas cx #SInt32 cy #SInt32 r #SInt32 color #UInt32
func.olivec_ellipse = #Untyped oc Olivec_Canvas cx #SInt32 cy #SInt32 rx #SInt32 ry #SInt32 color #UInt32
func.olivec_line = #Untyped oc Olivec_Canvas x1 #SInt32 y1 #SInt32 x2 #SInt32 y2 #SInt32 color #UInt32
func.olivec_normalize_triangle = #Bool8 width #UInt64 height #UInt64 x1 #SInt32 y1 #SInt32 x2 #SInt32 y2 #SInt32 x3 #SInt32 y3 #SInt32 lx #SInt32 #Attr Ptr 1 #AttrEnd hx #SInt32 #Attr Ptr 1 #AttrEnd ly #SInt32 #Attr Ptr 1 #AttrEnd hy #SInt32 #Attr Ptr 1 #AttrEnd
func.olivec_barycentric = #Bool8 x1 #SInt32 y1 #SInt32 x2 #SInt32 y2 #SInt32 x3 #SInt32 y3 #SInt32 xp #SInt32 yp #SInt32 u1 #SInt32 #Attr Ptr 1 #AttrEnd u2 #SInt32 #Attr Ptr 1 #AttrEnd det #SInt32 #Attr Ptr 1 #AttrEnd
func.olivec_triangle = #Untyped oc Olivec_Canvas x1 #SInt32 y1 #SInt32 x2 #SInt32 y2 #SInt32 x3 #SInt32 y3 #SInt32 color #UInt32
func.olivec_triangle3c = #Untyped oc Olivec_Canvas x1 #SInt32 y1 #SInt32 x2 #SInt32 y2 #SInt32 x3 #SInt32 y3 #SInt32 c1 #UInt32 c2 #UInt32 c3 #UInt32
func.olivec_triangle3z = #Untyped oc Olivec_Canvas x1 #SInt32 y1 #SInt32 x2 #SInt32 y2 #SInt32 x3 #SInt32 y3 #SInt32 z1 #Float32 z2 #Float32 z3 #Float32
func.olivec_triangle3uv = #Untyped oc Olivec_Canvas x1 #SInt32 y1 #SInt32 x2 #SInt32 y2 #SInt32 x3 #SInt32 y3 #SInt32 tx1 #Float32 ty1 #Float32 tx2 #Float32 ty2 #Float32 tx3 #Float32 ty3 #Float32 z1 #Float32 z2 #Float32 z3 #Float32 texture Olivec_Canvas
func.olivec_triangle3uv_bilinear = #Untyped oc Olivec_Canvas x1 #SInt32 y1 #SInt32 x2 #SInt32 y2 #SInt32 x3 #SInt32 y3 #SInt32 tx1 #Float32 ty1 #Float32 tx2 #Float32 ty2 #Float32 tx3 #Float32 ty3 #Float32 z1 #Float32 z2 #Float32 z3 #Float32 texture Olivec_Canvas
func.olivec_text = #Untyped oc Olivec_Canvas text #String #Attr ReadOnly #AttrEnd x #SInt32 y #SInt32 font Olivec_Font size #UInt64 color #UInt32
func.olivec_sprite_blend = #Untyped oc Olivec_Canvas x #SInt32 y #SInt32 w #SInt32 h #SInt32 sprite Olivec_Canvas
func.olivec_sprite_copy = #Untyped oc Olivec_Canvas x #SInt32 y #SInt32 w #SInt32 h #SInt32 sprite Olivec_Canvas
func.olivec_sprite_copy_bilinear = #Untyped oc Olivec_Canvas x #SInt32 y #SInt32 w #SInt32 h #SInt32 sprite Olivec_Canvas
func.olivec_pixel_bilinear = #UInt32 sprite Olivec_Canvas nx #SInt32 ny #SInt32 w #SInt32 h #SInt32
func.olivec_normalize_rect = #Bool8 x #SInt32 y #SInt32 w #SInt32 h #SInt32 canvas_width #UInt64 canvas_height #UInt64 nr Olivec_Normalized_Rect #Attr Ptr 1 #AttrEnd

[types]
Olivec_Font = #Struct width #UInt64 height #UInt64 glyphs #String #Attr ReadOnly #AttrEnd
Olivec_Canvas = #Struct pixels #UInt32 #Attr Ptr 1 #AttrEnd width #UInt64 height #UInt64 stride #UInt64
Olivec_Normalized_Rect = #Struct x1 #SInt32 x2 #SInt32 y1 #SInt32 y2 #SInt32 ox1 #SInt32 ox2 #SInt32 oy1 #SInt32 oy2 #SInt32

[constants]
OLIVEC_AA_RES = 2 #Untyped
OLIVEC_DEFAULT_FONT_HEIGHT = 6 #Untyped
OLIVEC_DEFAULT_FONT_WIDTH = 6 #Untyped

As you can see it specifies a platform (os and arch), a library (lib.static) and a bunch of types and symbols. As you would expected the symbols refer to the symbols contained inside the library file while the types are basically a way to access those symbols properly.

File Syntax

Section Description Required
global -
lib Library with which the runestone is associated with
constants Constant values that are known at compile time
types Custom types of the library
extern Custom types of that come from another library
symbols Symbols that are visible in the library and can be linked against
remap Different names that are used when linking a certain symbol
alias Aliases of symbols to make them available by multiple names

lib

Key Value
static static library
shared dynamimc library

Libraries can be specified either as looking it up on the system or from a specific location. If the value does not contain a directory (just a file name) it is loaded from the system. If it contains a path is loaded from said path. Relative paths are relative to the runestone file. To refer to a file in the same directory it needs to specified like this ./libfoo.a (libfoo.a would mean that is loaded from system paths). You can specify both static and dynamic libraries at the same time. Meaning that (if the to.language supports) lib.static will be linked when linking statically and lib.shared will be linked when linking dynamically.

constants

Key Value
NAME_OF_CONSTANT i64/f64/string Type

Usually the type of a constant is #Untyped.

types

Key Value
NAME_OF_TYPE Type

Types can not be recursive. Meaning that #Struct, #Union, #Enum and #FuncPtr and not be part #Struct, #Union or #FuncPtr.

extern

Key Value
NAME_OF_EXTERN_TYPE "SOURCE" Type

Every extern type will be added to the runestone just in case no source has been defined (or even exists for the to.language). The source can be an arbitrary string and shall be interpreted based on the from.language. In c the source is the path to the include file.

symbols

Key Value
func.NAME_OF_FUNCTION ReturnType List[NAME_OF_PARAMETER Type]
var.NAME_OF_VARIABLE Type

remap

Key Value
REMAP_NAME SYMBOL_NAME

The symbols specified by SYMBOL_NAME will be linked as REMAP_NAME.

alias

Key Value
ALIAS_NAME SYMBOL_NAME

The symbol specified by SYMBOL_NAME will also be accessable by ALIAS_NAME either directly or through a function that returns the variable if the language does not support making direct aliases.

Types Syntax

The syntax is meant to be as easy as possible to parse therefore every builtin type and keyword is prefixed by a # and recursive types are illegal (meaning that #Struct, #Union, #Enum and #FuncPtr can not be part of #Struct, #Union, #FuncPtr or a function in the symbols section).

Builtin Types

Keyword Description Size C Equivalent
#Untyped the type is either invalid, does not exist or there is simply no type - void
#RawPtr a pointer without a specific underlying type 8 (64-Bit), 4 (32-Bit) void*
#SInt8 signed 8-bit integer 1 int8_t
#SInt16 signed 16-bit integer 2 int16_t
#SInt32 signed 32-bit integer 4 int32_t
#SInt64 signed 64-bit integer 8 int64_t
#SInt128 signed 128-bit integer 16 __int128
#UInt8 unsigned 8-bit integer 1 uint8_t
#UInt16 unsigned 16-bit integer 2 uint16_t
#UInt32 unsigned 32-bit integer 4 uint32_t
#UInt64 unsigned 64-bit integer 8 uint64_t
#UInt128 unsigned 128-bit integer 16 unsigned __int128
#Float32 32-bit floating point number 4 float
#Float64 64-bit floating point number 8 double
#Float128 128-bit floating point number 16 long double
#String pointer to a null-terminated array of bytes 8 (64-Bit), 4 (32-Bit) char*, const char*
#Bool8 8-bit boolean 1 _Bool
#Bool16 16-bit boolean 2 -
#Bool32 32-bit boolean 4 -
#Bool64 64-bit boolean 8 -
#Opaque a type of which the implementation is hidden - struct foo;, union bar;

As you can see there are no platform dependent integer types (like int in odin). The reason is again to make the runestone simpler and also to associate it closer with its library.

Complex Types

Keyword Description Syntax
#Struct structure type consisting of multiple members List[NAME_OF_MEMBER Type]
#Union type that allows to access the same memory as different types List[NAME_OF_MEMBER Type]
#Enum enumeration List[NAME_OF_ENTRY i64/string]
#FuncPtr function pointer ReturnType List[NAME_OF_PARAM Type]
#Extern references a type that is from other libraries NAME_OF_TYPE
#Unknown references a type of which the implementation is unexpectedly unknown NAME_OF_TYPE

Attributes

Keyword Description Syntax
#Attr begin an attributes list List[Attribute] #AttrEnd
#AttrEnd end an attributes list -
Ptr declares a pointer u64
Arr declares an array 0/u64/string
ReadOnly declares that the last element can not be written to -
WriteOnly declares that the last element can not be read from -

Every type can have certain attributes. These attributes are declared within the keywords #Attr and #AttrEnd. Notice how all keywords that are used inside an attributes list are not prefixed with a #. The reason is that there are no custom identifiers. Look at this example:

foo = #SInt64 #Attr Ptr 1 #AttrEnd

This is how you define a pointer using runestone types. This equates to the following C code:

int64_t *foo;

To look at a more complicated example look at this:

foo = #SInt64 #Attr ReadOnly Ptr 2 Arr 5 #AttrEnd

This equates to the following C code (an array of 5 elements where each element is a pointer to a pointer to an integer where the underlying integer is read-only):

const int64_t **foo[5];

The attributes always apply to the element left to them (which means to understand what the type is, you need to read it from right to left). Look at this example to clarify this:

foo = #SInt64 #Attr ReadOnly Arr 5 Ptr 2 #AttrEnd

This equates to the following C code (a pointer that points to a pointer that points to an array of 5 elements where each element is an integer that can not be modified):

const int64_t (**foo)[5];