Skip to content

Spaghetti Syntax

Johannes Emerich edited this page Oct 13, 2015 · 25 revisions

Spaghetti modules define their interfaces using the Spaghetti Interface Definition Language (IDL). It's a simple language that borrows from C, Java, Haxe and TypeScript alike. An important difference compared to all of these is that Spaghetti IDL does not use semi-colons to separate clauses.

Language Elements

Types

Primitive Types

The following primitive types are available in the Spaghetti IDL, with mappings to JavaScript types:

  • bool -- boolean type, maps to boolean
  • int -- integer type, maps to number
  • float -- floating point type, maps to number
  • string -- string type, maps to String
  • any -- maps to any type

Void Type

The void type is available to signal no return value in method definitions and type chains.

Array

You can declare an array of any Spaghetti type where types are accepted.

Syntax:

{type}[]

For multi-dimensional arrays repeat the [] array qualifier the required number of times.

Example:

multiply(data: float[][], factor: float) float[][];

You can use array qualifiers in type chains and type arguments as well.

Function Types

Function types map an n-tuple of types to a type:

Syntax:

([{type}]*) -> {type}

Example:

(string) -> string
(int, int) -> int
() -> void

Type parameter

Interfaces, structs and methods can take type parameters. These work similar to generics in Haxe and TypeScript. There is no support for constraints on the values of type parameters (see #107).

Syntax:

<{type_parameter}[, {type_parameter}]*>

Metadata

Annotation

Some language elements in Spaghetti can take annotations. The usable annotations are listed at the definition of each element.

Syntax:

@{name}

Documentation

Some language elements can be documented in a Javadoc-like syntax.

Syntax:

/**
 * {documentation}
 */
{definition}

Comment

C-style line and block comments are accepted. Block comments cannot be nested.

Example:

// Line comment
/*
   block comment
*/

Module Elements

Module

(Documented, annotated)

Module definitions are blocks starting module name and alias. The module name is a hierarchy of lowercase names separated by periods. The alias is a single title-cased name. If no alias is specified, the default value is calculated by taking the last part of the module name capitalized, and adding a Module suffix.

A module block contains a list of import and extern declarations, and the definition of the module's types and methods.

Syntax:

module {module_name} [as {module_alias}] {
    {imports, externs, complex types and methods}
}

Example:

module com.example.test as TestComponent {

import org.spaghetti.Pasta;
import org.spaghetti.Sugo;
import org.spaghetti.Cheese;
import org.spaghetti.Dish;

interface Chef {
    cook(pasta: Pasta, sugo: Sugo, @optional cheese: Cheese): Dish;
}

createChef(): Chef;

Import

Similar to languages like Java, imports can be used to give a short alias to types declared in other modules. The alias by default is the same as the name of the imported type.

Syntax:

import {fully_qualified_name} [as {alias}];

Example:

import org.spaghetti.Pesto;
import org.spaghetti.Anchovies as Fish;

External Interface

Refers to an interface provided by the JavaScript runtime. External interfaces can be generic. Even though the names of the type parameters of a generic external interface are never referred to, a name must still be specified for them.

Syntax:

extern interface {fully_qualified_name}[<{type_parameters}>];

Example:

extern interface CanvasRenderingContext2D;

Complex Types

Types are named entities. Their fully qualified names are the concatenation of their module's name and their own name.

Interface

Interfaces can contain methods only. They can extend other interfaces. It is possible to extend multiple interfaces. When extending a generic interface, a list of type arguments must be specified that matches the number of type parameters of the extended interface.

Syntax:

interface <name>[<{type_parameters}>] [extends {interface}[<{type_arguments}>] {
    {interface_method}*
}

Example:

interface Carbonara extends Pasta, Delicious {
    consume(): StomachState;
}

Struct

Structs can hold properties and methods alike. They can extend maximum one other struct. When extending a generic struct, a list of type arguments must be specified that matches the number of type parameters of the extended struct. Structs are immutable by default and can be made mutable using the @mutable annotation.

Syntax:

struct {name}[<{type_parameters}>] [extends {super_struct}[<{type_parameters}>]] {
  [{property}|{method}]*
}

Example:

struct TodoItem<T> extends NamedItem {
    item: T;
    finished: bool;
}

Enum

An enum is a finite set of named constant values. This means that each value must be unique per enum.

Enum entry values can be either determined implicitly from the order in which the names appear, or explicitly by assignment of integer values. A mix of both styles within an enum is not allowed.

Syntax:

Either

enum {enum_name} {
    [{entry_name}]*
}

or

enum {enum_name} {
    [{entry_name} = {integer}]*
}

Example:

enum Utensils {
    KNIFE,
    FORK,
    SPOON
}

enum Fruit {
    APPLE = 1,
    ORANGE = 3,
    BANANA = 5
}

Constant

Constant types contain a list of named primitive values with optional type annotations.

Syntax:

const {name} {
    {constant_name} [: {type}] = {value};
}

Example:

const ExampleConstants {
    id: int = 1;
    name = "constant";
}

Method

Interfaces, structs and modules can define methods. Methods can take local type parameters that can be referred to as type arguments in the declaration of their return types and the types of their parameters. The @optional annotation can be used to mark optional parameters.

Method overloading is not possible (see #113).

Syntax:

{method_name}[{type_parameters}]({parameter_name}: {parameter_type}[, {parameter_name}: {parameter_type}]*): {return_type};

Example:

sayHello(user: string): void;
concatAsString<T>(elem1: T, elem2: T): string;

Formal definition

For more information see the ANLTR grammar of the Spaghetti IDL.