Prof. Dr. Theo D'Hondt
Last revision: August 7th, 1996

Agora-S Definition


Agora-S Abstract Grammar

The abstract grammar of Agora-S is defined by the following EBNF productions.

  <Program>         ::= <µExpression>

<µExpression> ::= <µOperation> [ <µKeyword> <µExpression> ]

<µOperation> ::= <µUnary> [ <µOperator> <µOperation> ]

<µUnary> ::= <Expression> | <µUnary> <µName>

<Expression> ::= <Operation> [ <Keyword> <Expression> ]

<Operation> ::= <Unary> [ <Operator> <Operation> ]

<Unary> ::= <Factor> | <Unary> <Name>

<Factor> ::= <Name> | <Block> | <Literal> ) |

<µName> | '('<µExpression>')'

<Block> ::= '[' [ <<µExpressionList> ] ']'

<µExpressionList> ::= <µExpression> [ ';'<µExpressionList> ]

An Agora-S program is a meta-message (a message to the interpreter). Meta messages are like lisp's special forms. They are used to reify interpreter processes to the language level. In lisp or scheme this is done by (define...) and (macro...) 'procedure calls'. Of course, these are not really procedure calls because this would cause their arguments to be evaluated. Instead, they can be seen as calls of procedures of the interpreter. The calls to the interpreter are literally reified in the language.

In the same way, an Agora (be it an Agora94 or an Agora-S) program is a mixture of ordinary messages and reifier messages. Both kinds of messages are subdivided in unary messages, operator messages and keyword messages. As in Smalltalk, unary messages have the highest precedence and keyword messages have the lowest precedence. Furthermore, ordinary messages have precedence over reifier messages. The precedence rules of the Agora-S syntax are therefore (from highest to lowest precedence):

Of course, this is also reflected in the grammar rules.

Concrete Grammar and Semantics of Agora-S

Much of the semantics of Agora (and thus also Agora-S) is defined by the number and behaviour of the built in messages. The language itself is defined by the definition of the reifier messages. Built in ordinary messages should be seen as "standard messages defined on native objects". These are the ordinary messages such as addition for numbers, printing objects, etc. The really interesting part though, is the definition of the reifier messages, since they define the particular flavour of Agora at hand.

The currently implemented reifier messages in Agora-S are defined below:

<ident> µvar

defines a new variable. This is an example of a unary reifier message

<ident> µvar: <exp>

defines a new variable with initial value <exp>. This is an example of a keyword reifier message.

<ident> <unary> µmethod: <body>

defines a new unary method (e.g. size, abs,...) with <body>

<ident> <operator> <ident> µmethod: <body>

defines a new operator method (e.g. +,-,...) with <body>

<ident> <keyword>:<ident> ... µmethod: <body>

defines a new keyword method (e.g. at:put: ) with <body>

µself

In Agora-S programs, every method is annotated with by a name for its receiver, e.g.

theReceiver doSomething: arg µmethod [...]
Using 'theReceiver' in [...] precludes using stuff (e.g. methods) that is declared in [...] itself, because theReceiver does not contain that stuff. However, if a method is executed, a local extension of its receiver is created that contains all the declarations inside [...]. This local extension can be accessed by refering to µself. A consequence of returning µself is that the extended receiver is returned, which is precisely what mixin methods of Agora94 do.

<exp> µclone

clones the object <exp>.

<exp> µproto

<exp1> µ= <exp2>

checks if the receiver <exp1> is equal to <exp2>. This is an example of a reifier operator message.

<exp> µinspect

inspects the expression <exp>. For the moment, this is merely a pretty print of the object's internal state.

<string> µerror

shows the string as an error message.

<string> µdisplay

displays the receiver

<string> µscheme

executes the string as a scheme-expression

<exp> µnative

<exp> µnative: <string>

<ident> µload

load the file <ident> and substitute it at this place

<exp> µdump: <ident>

<block> µvalue

takes the block, evaluates it and returns the value returned by the block.

<ident> µ<- <exp>

assigns the <exp> to the variable <ident>

<boolExp> µthen: <expThen>

takes a boolean expression and a block. The block is executed if the expression is true. This is again an example of a keyword reifier message.

<boolExp> µthen: <expThen> µelse: <expElse>

When <boolExp> evaulates to true, the <expThen> is executed. Otherwise the <expElse> is executed.

<boolExp> µwhile: <expWhile>

executes <expWhile> while <boolExp> remains true.

<ident> µfrom: <expFrom> µto: <expTo> µdo: <expDo>

a for-loop with the usual semantics.

A simple Agora-S tutorial