Syntax Details

Syntax:

Twilight is a curly bracket and
parenthesis language, blocks including conditionals, loops,
subroutines, and classes are all enclosed with braces { } Subroutines
include parenthesis () to surround arguments in the definition and
parenthesis are used to define what is to be evaluated for
conditionals and loops. Expressions terminate with “;”
There are few reserved words in Twilight, a non-exhaustive (but
close) list of some you will find are:

use – a convenience for
shortening NamePath references (more on that later)
class – declare a class
singleton – declare a singleton
sub – declare a subroutine
(method)
var – declare an untyped variable

if, else, elif, while, loop, for,
foreach, break – looping and conditionals

class declarations begin with the
keyword class or singleton, followed by the name or NamePath,
followed by optional parenthesis with parent class, followed by
braces including member and subroutine definitions.

class SomeClass {
   var someMember;

   sub someSub(anArg) @Bool { 
      return(true);
   }
}

The above class descends from
System:Object, has an untyped member named someMember, a subroutine
named someSub which takes one argument of any type and returns a
boolean.

Any number of classes and singletons
may be defined in a given file and there are no requirements
regarding packaging, naming, etc, specific to file contents. As the
Twilight build system does incremental builds based on file
modification time, it is often most efficient to use a file per class
while in an active development mode to reduce generation and
compilation time, but this is not required.

Objects are constructed using the
special method "new" with a NamePath and any required
arguments. This will construct the object, call it's appropriate
"new" method, and assign the returned result (normally the
created instance).

var myvariable = new(System:Object);

Methods are called by referencing the invocation target, period,
method name and arguments in parenthesis. Like so:

myTarget.myCall(myArg1, myArg2);

The “special” reference to
the instance of an object on which a method is being executed is
“self”. References to other methods for the same object
do not need to be prefixed by “self” but are signified by
not providing a call target, e.g.

myCall();

and

self.myCall();

are equivalent

To access overriden functionality use the “super” call
target, e.g.

super.myCall();

would execute the myCall function as defined in the nearest ancestor
class to the one in which the call is defined.

Object members may be accessed with or
without reference to self, but in this case the two operations are
not equivalent. The access prefixed by "self." will
exercise an Accessor if defined, the access prefixed without "self."
directly references the member regardless of accessor definition. For
details, see the accessor tutorial.

Scope:

Variables have two possible scopes,
object level or subroutine level. A variable defined as part of a
class declaration outside of any subroutine is object scoped and
becomes a member definition. A variable declared within a subroutine
is scoped for that subroutine. It is available everywhere within the
subroutine, even before the declaration itself. Variables must be
declared, it is an error to declare the same variable more than once
in a subroutine or to use a variable which is never declared. A
variable may be declared at an object level and in a subroutine for
that object, the most local scope where the variable is defined will
determine the scope to which it applies. There is a third scope, the
global, but it is not accomplished through a variable declaration,
but can be accomplished as a side-effect of a singleton definition.

Conventions:

Reserved words are all lowercase,
variable and subroutine names begin with lower case and may use upper
case letters to distinguish contained words. Classes begin with
capital letters and may use capitals to distinguish additional words
in the name, e.g. SomeCoolClass. (Camel Case)
Classes are named hierarchically using
a single colon to separate steps. This will be referred to as a
NamePath and is like package naming or name spaces in other
languages, Logic:Bool refers to the class Bool in Logic, there could
be an Illogical:Bool class as well without conflict

Variables are declared as dynamically
typed using the keyword var,

var avariable;

is a dynamically typed variable, the same syntax is used at the class
level for members and within subroutines for local variables.
Variables may only be declared at the class level, all initialization
or assignment must occur within subroutines, including the
constructor, new Variables are declared as typed variables by
prefixing the namepath with @.
@Int anInt;
declares a statically typed variable anInt which must be of "Int"
type (this assumes a "use Math:Int;" declaration before the
class definition)
There is no need to import a class
before use, any reference to it in a type declaration or construction
call (new) is sufficient to cause it's inclusion during compilation.
However, it can become tedious typing long NamePaths all the time,
e.g. @Container:Array:Iterator i = myArray.iterator; So, you can use
use to shorten it:

use Container:Array:Iterator;
use Container:LinkedList:Iterator as LIterator;

Now @Iterator x will refer to an
Array:Iterator and @LIterator y to a LinkedList iterator

The optional "as" allows you
to define the local label which will refer to the used NamePath, if
omitted it defaults to the last step in the path.

"use" statements occur
outside of any class definition in a file and apply to all classes
within the file. They apply to class declarations as well as
arguments to the new method for construction and to typed variable
declarations.

Every action in Twilight is ultimately
a method call on an object. In line with the desire to keep Twilight
practical accommodations are made for other paradigms where they
better fit the problem to be addressed. For example, for a more
structural style problem where the binding of data to operation is
not strong or needs to be global in scope a singleton class type is
provided.

If a class is defined as a singleton
only one instance of this class will be created per executing process
and members of that object are effectively global. To create a
singleton class simply declare with the keyword “singleton”
instead of “class”. The characteristic of being a
singleton is not transmitted or constrained by inheritance,
singletons may inherit from multi-instance classes and vice versa.

Twilight supports single inheritance
with an ancestor to all classes of System:Object. All members and
methods of a class flow down the inheritance tree, including the
special constructor method “new”.

Defining a method of the same name and
number of arguments as an ancestor class will override the definition
in the parent for instances of the child. A member cannot be
redefined in an inheriting class, to do so will result in a compile
time error.

craig_welch2 – Sat, 2006 – 09 – 02 06:35