Semantics of the dodo language
A continuation is an executable piece of code which can accept parameters.
Example:
12 -> a
a + 3;
A function is a continuation which has at least one continuation as parameter. Arguments of this continuation become return values. A dodo function has an implicit context parameter which is used for closures, genericity etc. By default, a dodo function takes a return and a throw continuation.
Example:
fun (int x -> return(int):
return(x * a).
)
A generator is a function which returns a generator and optionally other values. It usually makes use of a second continuation to signal that there is nothing left to return.
Example:
fun (-> return(yield int), done():
return(5) ->
return(8) ->
done().
)
A structure, also known as a tuple or a record, is a structured set of values accessed by name. A structure can be seen as a memory region holding the values, with a mapping function which associates each known name with a value in memory. Alternatively, a structure can be seen as a function which returns the value associated with a specified name. In the latter case, changing a value boils down to altering the function so that it returns a new value for the selected name.
Example:
new struct:
int x, y.
An attribute is a named value in a structure. It can be accessed using dot notation.
A member function is a function which is declared in a structure. It can be called using dot notation. In dodo, a member function is not actually part of the structure. The function has a hidden parameter called self which value is the structure it is applied to.
Examples:
tree.left
tree.rotate_right()
A prototype is a variable which is used as model for a new variable. The new variable can have different values for the attributes defined in the prototype.
A variable extends a prototype if it adds new definitions to it.
Example:
new tree(left: f, right: g):
int weight = 50.
A type is a structure associated with each variable which defines its general properties such as size, member functions and memory location of attributes. It is shared between a prototype and variables modeled from it as long as they do not add new definitions. A dodo type has a hidden attribute called instance which is by definition associated with it.
Example:
def House:
int windowCount = 2
Drawing draw(Canvas canvas)
{
return canvas.drawSquares(windowCount)
}.
A type extends another type if it uses it as prototype and adds new definitions to it.
Example:
def KansasHouse = new House:
String KansasHouse.state = "Kansas".
A type inherits from another type if it uses it as prototype and modifies the attributes defined in the prototype, such as the general properties of the associated variables.
Example:
def ColoredHouse = new House:
Color wallColor = white, roofColor = red.
An interface is a set of functions associated with a type which maps variables and names to concrete values. For example, an attribute name and a variable can be mapped to the memory location of this attribute within the variable.
An interface extends another interface if it uses it as model and augments the mapping functions to map new names. Note that an interface can extend several interfaces.
In the dodo language, a type definition also defines an interface.
An abstract state is a property of a variable which, depending on a tag or on validation rules, defines which are some of the general properties of the variable. This allows to split a type into subtypes, each with a different set of attributes and member functions.
Example:
def Tree is Tagged:
int value
__State__ node
Tree left, right.
An object is a structure variable which has a hidden tag attribute Class which refers to its interface. This interface is used to access attributes and call member functions of the variable, without a need for the caller to know the exact type of the variable.
Example:
object1.draw(paper)
A class is a type associated with an object instance.
Example:
class Person:
String name
int age.
A function template, also known as generic or parameterized function, is a function with parameters such as types or interfaces which returns a new function specialized for a given value of these parameters.
Example:
template(houseType: $H)
Map addOnMap(H house)
A guard is a condition attached to a function template which limits it to or allows to define a separate return function for particular values of the parameters.
Example:
template(houseType: $H)[where H ~ House]
Map addOnMap(H house)
A qualifier, also known as a trait or a mixin, is a function template which has a hidden Class parameter and which function returns an interface. It is used to modify or extend a type or an interface.
Example:
qualifier Colorful:
Color[Place area] colors.
A capability is a variable issued by a service which contains a secret known to the service. The secret could be a cryptographic key or simply an ID. In dodo there is a hidden master capability which unlocks other capabilities.
A message is a variable which can be sent between the client code and the service. This often means the variable must be serializable.
Example:
capability Beeper:
message Beep
{
char beepSound = \u0007
}.
A promise is a message attribute. A promise may or may not have a value at a given instant. The processing of a message can incur delays, or the message sender can deliberately delay giving a value to an attribute. A synchronized message recipient waits for promises to be fulfilled before proceeding.
Example:
msg.beepSound
A proxy is an entity which represents the service, and knows how to leverage the secret of a capability to exchange messages with the service. The proxy generally fulfills a routing or caching role between the client code and the service.
Example:
sounds!beeper.Beep()
A constructor is a function of a type which takes the master capability and a copy of the type instance attribute as hidden argument. It initializes the attributes of the new instance. Because the constructor has the master capability, it can call other constructors and obtain more capabilities. Unlike other dodo functions a constructor is allowed to modify variables defined outside its own body.
Example:
House:
int windowCount
House(int windows)
{
.windowCount = windows
}.
A wrapper is a function which intercepts function calls which match a pattern. It can replace the intercepted function with its own, or add extra instructions around the intercepted function. A wrapper defined in a type or a qualifier becomes part of its interface.
Example:
wrap (selector: $f):
_(args*)
{
return f.call(self, args)
catch:
console!out.Puts("Caught event").
}.
A macro is a function called by the compiler which transforms input code which match a pattern into new code. The compiler gives a value to variables defined in the pattern. The match fails if the input does not evaluate to a value of the appropriate type. A macro can be defined in a type or qualifier. When an expression evaluates to an instance of a type which defines a macro, the macro is called to match its pattern. Only the formal type is taken into account if the expression evaluates to an object since the exact type of an object is unknown to the compiler.
Example:
wrap:
/times $n/
{
return addNtimes(self, n)
}.