Kite Language Specification
***************************

Syntax
======

Kite has a simple, functional syntax, similar to other object-oriented languages.

Basics
------

General
.......

All statements in Kite end with a semicolon. For instance:

     "Hello world"|print;

Whitespace also does not matter, for the most part. "hello world" | print ; is equivalent to the first line above. Brackets are used to delineate blocks.

Representation of Built-In Types
................................

Numbers are represented as in other languages (integers have no periods, while floating-point numbers have one). Strings are surrounded by double quotes, and have the normal escapes:

\n
     Newline

\r
     Carriage return

\\
     Literal "\"

\"
     Literal "

\t
     Tab

\b
     Backspace

\f
     Form feed

\[0-7][0-7]?[0-7]?
     ASCII character, represented in octal

\x[0-F][0-F]?
     ASCII character, represented in hexadecimal

Strings can also span multiple lines without the need for any escape character. Lists are surrounded by [ and ] characters, with each element separated by commas: [1,2,3]. All built-in types are immutable, except for lists. Boolean values are true and false (for true and false, respectively).

As of 1.0b8, it's also possible to specify a range of integers by using the following construct: from:to(:step). This will instantiate a System.math.range object (see kdoc documentation) that represents all the numbers from one integer to another (possibly skipping numbers along the way).

Regular expressions are also built-into the language syntax as of 1.0.1. Regular expressions begin with "r/" and end with either "/" (case-sensitive) or "/i" (case-insensitive). This is equivalent to creating a new System.regex object with the appropriate parameters.

Declarations
------------

Required Version
................

A module can specify the minimum required version in order to run. This can be done by using the version keyword, as shown below:

     version "1.2.0";
     "hello world"|print;

If a user attempts to run the above code on a version of Kite lower than 1.2.0, an exception will be thrown. The minimum supported version that can be specified here is 1.0.0. Only two of the version components are required--the third one will default to being 0 if not specified:

     version "1.2";
     "hello world"|print;

Classes
.......

The class is the fundamental unit in Kite. All objects, whether built-in or user-created, are instances of classes. To declare a class, use the class keyword:

     class Hello from System.object [
        ...
     ];

The from System.object is optional, as all classes inherit from System.object by default. If specified, your class will inherit from the class specified. This allows for single inheritance:

     class Greetings [
         ...
     ];

     class Hello from Greetings [
         ...
     ];

All declarations inside of a class are delimited by commas, instead of semicolons.

Properties/variables
....................

Properties and variables are the same in Kite. To declare, use the property keyword:

     class Greeting [
         property text,
         global property number_given
     ];

     property desired;

global is an optional keyword that goes before property that indicates that the property is to be shared amongst all instances of the class. This is equivalent to static members in C++ and similar languages.

Properties can also have a value assigned to them on first creation, as seen here:

     class Greeting [
         property text = "Hello!",
         global property number_given = 1
     ];

Methods
.......

Methods work in a similar way as in other languages, and are declared using the method keyword:

     class Hello from Greeting [
         method sendGreeting(string) [
             string|print;
         ];
     ];

     method greetings() [
         (make Hello())|sendGreeting("hello");
     ];

Unlike in other languages, there is no concept of static vs. instance methods; however, this will be set to the class object inside of methods called without an instance and not called inside of a class. Methods can take any number of parameters, and method overloading is possible:

     class Hello from Greeting [
         method sendGreeting() [
             this|sendGreeting("hello");
         ],
         method sendGreeting(greeting) [
             greeting|print;
         ]
     ];

The return value of any method is the return value of the last executed statement in the method. In the example above, sendGreeting() will return whatever print returns.

Anonymous methods are also possible, by removing the method name from the declaration. Example:

     x = method(a) [
         (a + 1);
     ];
     (x(1))|print;

Any references to variables/properties inside a method call will search for the property down the call stack. That is, x inside the method will change the declaration outside the method unless a property declaration is included:

     property x;
     method y() [
         x = 3;
     ];

     x = 2;
     x|print;
     y();
     x|print;

To exit out of a method early, simply use the return keyword:

     method x(y)
     [
         return;
         "should not reach here"|print;
     ];
     x(1);

Operators
.........

Kite also supports operator overloading using the operator keyword. Overloadable operators are below:

plus
     Addition (+)

minus
     Subtraction (-)

multiply
     Multiplication (*)

divide
     Division (/)

mod
     Modulus (%)

unplus
     Unary plus (+)

unminus
     Unary minus (-)

map
     Map (<-)

reduce
     Reduce (<|)

array
     Array dereference ([])

array_set
     Array set ([]=)

lt
     Less than (<)

gt
     Greater than (>)

leq
     Less than or equal to (<=)

geq
     Greater than or equal to (>=)

and
     Logical/bitwise AND (and)

or
     Logical/bitwise OR (or)

not
     Logical/bitwise NOT (not)

xor
     Logical/bitwise XOR (xor)

lshift
     Left shift (<<)

rshift
     Right shift (>>)

call
     Method call. Caution: the array passed in as the argument contains the method name for the first element (as a string) and a list containing the arguments as the second element. This operator is also called only if said method does not exist.

All operator methods above only take a single argument, the right hand side of the operation (if any). For the unary operators, this argument will be null. The left hand side is always this. Example:

     class Widget [
         property number,
         operator add(rhs) [
             property ret;
             ret = make Widget;
             ret.number = this.number + rhs.number;
             ret;
         ]
     ];

Constructors and Destructors
............................

Constructors and destructors are created using the construct and destruct keywords:

     construct (param1, param2, ...) [
         ...
     ];
     destruct [
         ...
     ];

Constructors can also be overloaded, as appropriate. To call a base class's constructor, use base|__construct__(...) (base also works in any class method to call parent's version of said method). Any return value from the constructor is ignored.

Package importation
...................

Packages are imported using the import keyword, with the name of the package in quotes:

     import "System.vm.thread";

Each component of the package is separated by a period and corresponds to an element of the path (see Extending Kite for more information).

Caution: import instructions are executed before any other code is run. This can interfere with proper operation if the package you're looking for is not in the standard Kite lookup path. Use eval (see Dynamic code evaluation) as a workaround.

Object creation
---------------

Explicit creation
.................

Objects are created using the make keyword:

     var = make Class(param1, param2, ...);

make returns the object itself, which can be used in method calls. The parameters passed into make will be passed to the constructor.

Please note: As of 1.0a2, parent class constructors are not called (but any constructors in the given class matching the number of parameters are). Constructors that need to call parent constructors can use parent|__construct__(...), where parent is the name of one of the parent classes.

Implicit creation
.................

Objects are implicitly created when operators are run upon them (for instance, adding two numbers). The supported operators are listed under the Operators section above.

Map/Reduce
..........

Kite has built-in support for the map and reduce operators (<- and <|, respectively). Map applies a method to each element of an object (by default, any object that implements the iterator methods), while reduce constructs a single new object from another object using a method. For example:

     method mapping(a) [
         (a + 1);
     ];
     method reducing(a, b) [
         (a + b);
     ];

     ([1,2,3]<-mapping)|print;
     ([1,2,3]<|reducing)|print;

which outputs:

     [2,3,4]
     6

Method calls and dereferencing
------------------------------

Unlike in other languages, there is a syntactic difference between dereferencing an object and calling a method on an object. The dot (.) operator dereferences a class and returns the contents:

     x = class.property;

The pipe (|), on the other hand, dereferences the method and then calls it with the arguments and object given:

     x|doWork();

Any arguments passed to the method are within the parenthesis (which are optional if no arguments are being passed). For methods not defined in a class, the parenthesis are required for Kite to determine whether you want the method object or to call the method.

Inside of a class, if you wish to call the version of a function that is inside a parent class, you may do so by prepending the parent class's name. For example:

     class a [
         method x() [ ... ]
     ];

     class b from a [
         method x() [ ...; a|x(); ... ]
     ];

     y = make b();
     y|x;

The special __construct__ method can also be used to reference parent (or your own) constructors.

Documentation strings
---------------------

Kite has built-in support for documentation strings.

How to write
............

Documentation strings begin with /[ and end with /]. The string can span multiple lines. Example:

     /[Top of file]/

     class Test /[A class.]/ [
         property prop /[A property.]/,

         construct() /[A constructor.]/ [
             ...
         ],

         destruct() /[A destructor.]/ [
             ...
         ],

         operator plus(rhs)
         [
             ...
         ],

         method x(
             arg /[A method argument.]/
         ) /[A method.]/
         [
             ...
         ]
     ];

Generating documentation
........................

To generate documentation, use System.doc|generate_doc():

     import "System.doc";
     import "your.package";

     out = make System.doc.outputters.html_outputter();
     doc = System.doc|generate_doc(your.package);
     doc|output(out);

An example of kdoc documentation (generated from System.doc) can be found at http://www.kite-language.org/kdoc-test/System.doc.html.

Supported constructs
....................

The following constructs can have documentation strings:

  * Beginning of files

  * class

  * property

  * method

  * construct

  * destruct

  * method arguments

  * operator

Object type determination
-------------------------

The type of an object can be surmised in several ways:

  * object|type

  * is/isof operators

object|type
...........

Every object contains a method called type. This method returns the name of the class as a string. This example will return System.string as the output:

     x = "string";
     x|type|print;

is/isof operators
.................

The other method is through the use of the is/isof operators. The difference between the two is how far they search. is only determines if the current instance is of type x, while isof determines whether the current instance is of type x, or any child class of x. Example:

     import System.string;
     class x from System.string [
     ];

     ((make x) is x)|print;
     ((make x) is System.string)|print;
     ((make x) isof x)|print;
     ((make x) isof System.string)|print;

returns the following:

     true
     false
     true
     true

Decisions
---------

Kite uses the decide construct (analogous to C/C++'s switch statement) to allow developers to conditionally execute code. Example:

     decide [
         condition1 [ ... ],
         condition2 [ ... ],
         ...
         true       [ ... ]
     ];

Each condition is separated by a comma, where condition is any statement that evaluates to a Boolean value. true is used to denote code that should be executed when none of the other conditions match. Each condition is evaluated one-by-one, with the rest short-circuited once the first matching condition is found (no falling through like in C/C++).

Loops
-----

Kite has two types of loops: while and until. while loops execute code while the condition evaluates to true, while until loops execute code until the condition evaluates to true:

     i = 0;
     while (i < 10) [
         i = i + 1;
     ];
     until (i == 0) [
         i = i - 1;
     ];

To break out of the loop early, use the break statement. To jump back to the top of the loop, use continue.

Exceptions
----------

Kite supports exceptions through run/catch:

     run [
         ...
     ] catch [
         ...
     ];

When Kite throws an exception, control passes to the first statement within the catch block. The exception itself is placed in the __exc variable. To throw an exception, the System.exceptions.exception|throw method is used. This method is implemented by all exceptions.

Dynamic code evaluation
-----------------------

Kite supports the eval construct, which allows one to dynamically execute code:

     eval "\"Hello, human.\"|print";

The parameter after eval can be any valid Kite construct that evaluates into a string. Of course, an exception will be thrown if the string cannot be parsed.

Standard Library
================

The Kite standard library consists of several important libraries. All of these libraries should be part of an implementation of Kite.

The documentation for these can be generated by executing:

     import "System.doc";
     out = make System.doc.outputters.html_outputter();
     doc = System.doc|generate_doc(__root);
     doc|output(out);

You can also view the documentation online by going to http://www.kite-language.org/docs/kdoc-[version]/__root.html, where [version] is the version of your copy of the interpreter (starting from 1.0b4 on).