Advanced Types

Pointers

When a pointer (besides char *) is passed to ObjectiveScript code, the runtime wraps it in a JXPointer type.

Dereferencing

A pointer's underlying value can be accessed using ObjectiveScript's dereference operator. The syntax for this is *pointer, where pointer is the JXPointer that you wish to dereference.

In order to correctly dereference the pointer, the runtime needs to know the type of the underlying value. In some situations (such as during some Objective-C method calls), the runtime might not be able to infer this itself. Therefore, unless you have explicitly declared a function's signature (read on for more on functions), you should use @cast to convert the pointer to the correct type before dereferencing it. The syntax for this is

@cast(<type>)pointer

Refer to Type Syntax for the syntax of <type>.

pointee

JXPointer<Pointee>.pointee: Pointee

A property on JXPointer which returns the underlying value. Equivalent to dereferencing the pointer.

advancedBy

JXPointer.advancedBy(offset: number): JXPointer

Advances the pointer by offset times the size of pointee (similar to this + offset in C).

distanceTo

JXPointer.distanceTo(other: JXPointer): number

Returns the distance from other to this pointer (similar to other - this in C).

Precondition: other must have the same pointee type as the callee.

Subscripting

A JXPointer can be subscripted with a numerical index.

pointer[offset] === pointer.advancedBy(offset).pointee

Arrays

In most situations, C "arrays" are syntactic sugar for pointers. When an array is contained in a struct, however, type[n] is equivalent to n values of type stored contiguously within the struct. Accordingly, accessing an array on a JXStruct returns a JXArray type.

JXArray is a subclass of JXPointer, and if you were to pass it directly to a function it would be equivalent to passing a pointer to the array. The key difference is that JXArray also has a length property. In combination with the subscript operator which already exists on JXPointer, this makes JXArray "Array-like".

Structs

ObjectiveScript converts C structs to the JXStruct type.

Note: If a struct's member types are unknown while dereferencing a pointer, the runtime does not have adequate information to create the JXStruct and will thus crash. You can specify the struct's type by @casting the pointer.

Accessing Fields by Index

A guaranteed way to access a JXStruct's fields is via numeric subscripting. To get a field's value, simply subscript the struct with the field's index. For example, person[0] returns the first element of the struct referenced by the person variable.

Accessing Fields by Name

If the runtime has extended type information about a struct, it's possible to subscript via the field name using simple dot syntax (e.g. person.name).

Extended Type Information

The runtime tries to locate extended type information about a struct when it's passed to ObjectiveScript. There are a few ways in which this is done.

  • Some Objective-C methods have the extended type information present in their encoding. The runtime attempts to locate and use this type information.
  • Other times, the struct's type information has the struct's name but not the field names. In such a situation, one can use @struct at the top level to define the field names of a struct, and these will be looked up at runtime.
  • When manually declaring an Objective-C method, C function, symbol, etc, the transpiler requires that any structs involved have their full definition provided at the top-level with @struct.
  • When @casting to a struct, the full definition must be provided at the top-level with @struct.

See Type Syntax for the @struct syntax.

Functions

ObjectiveScript code can call C functions. The function prototype must first be declared, however. This is done using the @function keyword.

@function <type> <name>(<type>, <type>, <more types...>);

Additionally, a function can be made variadic by adding ... to the end of the argument list.

A few examples of @function are:

@function void *calloc(unsigned long, unsigned long);
@function int strcmp(char *, char *);
@function int printf(char *, ...);

Functions declared with @function are called just like normal JavaScript functions.

strcmp("hello", "hello") === 0 // true

Note that when calling a variadic function, while the type system tries to infer as much type information as it can, some fidelity is lost due to JavaScript's weaker type system. This can be resolved by @casting the variable to the desired type. For example,

printf("One plus one equals %u\n", @cast(unsigned int)(1 + 1));

Symbols

ObjectiveScript has the ability to access symbols which are accessible to dlsym. Use the following syntax to declare the symbol:

@extern <type> <name>;

For example,

@extern char **environ;

After this, you can treat the symbol like a normal writeable JavaScript global variable.

NSLog(environ[0])

Additionally, it is also possible to get the address of the symbol itself. This is done using the address-of operator, &. For example, &environ yields a JXPointer to environ. Note that this is currently the only supported use case for the address-of operator in ObjectiveScript.

Miscellaneous Utilities

@encode

@encode(<type>)

Returns the Objective-C type encoding for <type>. Similar to the @encode compiler directive in Objective-C.

@sizeof

@sizeof(<type>)

Returns the size of <type>. Similar to sizeof in C.