Skip to content
This repository was archived by the owner on Mar 15, 2019. It is now read-only.

Language reference

Martin Angers edited this page Sep 6, 2013 · 19 revisions

This document will evolve to eventually be a complete language reference, with a formal grammar definition. For this early release, it will remain an informal yet thorough coverage of the language's syntax and features.

Source code representation

The source code files must be encoded in UTF-8.

Lexical elements

Comments

Agora supports two forms of comments:

  • Line comments start with // and end at the end of the line
  • Block comments start with /* and end at the next */

Semicolons

Statements are terminated with a semicolon, but the may be omitted in the source code. The scanner stage of the compiler automatically inserts the semicolons if the last token on the line is:

  • an identifier
  • a literal value
  • one of the keywords return, debug, break or continue
  • one of ++, --, ), ] or }

Identifiers

An identifier is a sequence of letters, underscores and numbers. It must start with a letter.

The following identifiers are keywords in the language and may not be used as identifiers:

  • if
  • else
  • for
  • func
  • return
  • debug
  • break
  • continue

Additionally, the following identifiers are reserved and may not be used as variables:

  • true
  • false
  • nil
  • import
  • panic
  • recover
  • len
  • this
  • args

Operators and delimiters

The following symbols represent operators and delimiters in the language:

  • ( ) [ ] { }
  • . , ; :
        • / % ! && || ?
  • == != < <= > >=
  • = := += -= *= /= %=
  • ++ --

Number literals

Number literals can be represented as integers or floats. At the moment there is an inconsistency between what is accepted by the compiler and what can be used. Only base-10 notation should be used for now, i.e. 42, and floating-points should use the integer-decimal point-fraction notationm i.e. 3.1415.

String literals

At the moment there is an inconsistency between what is accepted by the compiler and what can be used. Only string literals within double quotes should be used, i.e. "this is a string". It may not contain newlines, but escape characters can be used (i.e. \n for newline).

Boolean literals

Booleans are represented with the true and false literal values.

Nil literal

The nil value is represented with nil.

Object literal

Objects are represented using the {key: value, otherkey: value} notation, which may be used recursively.

Functions

A function prototype is introduced using the func keyword. It can be used as a statement and as an expression:

// Statement
func myFunc() { return "statement" }
// Expression
myVar := func() { return "expression" }

In statement form, the "name" of the function is in fact a variable in the scope of the parent of the function being declared. The above example is equivalent to this:

myFunc := func() { return "statement" }

The expression form is self-explanatory.

Functions are first-class values and can be stored in variables and passed around in function arguments and return values, or in object fields. It is possible to declare a function within a function, although closures are not supported at the moment (returning a function from a function will not close over the variables of the parent function). This is a feature that will be added eventually.

Functions declare expected arguments by giving a list of identifiers within the parentheses of its definition. It can't declare a return value variable. Functions always return a single value, which is nil if there is no explicitly returned value.

func Add(x, y) {
    return x + y
}

Functions may receive more or less arguments than expected. In the former case, the extra argument variables have the nil value. In the latter case, the extra arguments can be retrieved via the args reserved identifier, which is an array-like object that holds all arguments passed to the function, at keys 0 to len(args)-1.

If the function was assigned to an object's field, and was called with the object notation, then its this reserved identifier is set to the object.

obj := {name: "Martin"}
obj.MyFunc = func() {
    return this.name
}
obj.MyFunc()

If the same function is stored in a variable and called not with the object notation, the this identifier is nil.

noThis := obj.MyFunc
noThis() // Error

Scopes

All variables are declared in the scope of the function where they are defined, using the := operator, or the arguments and function names. All module-level variables are scoped in the top-level function (the module).

Clone this wiki locally