Skip to content
This repository has been archived by the owner on Mar 10, 2022. It is now read-only.

Latest commit

 

History

History
202 lines (155 loc) · 4.4 KB

spec.md

File metadata and controls

202 lines (155 loc) · 4.4 KB

Elara Language Specification

This uses ANTLR4 Grammar Syntax to describe elements of the Elara Language.

Names and conventions

Types have names in PascalCase, and should be short and simple, eg Int, String, Person

Identifiers are the names used for variables and parameters. Identifiers can be any unicode character, with the exceptions of ,, ., :, #, [], (), {} ", and whitespace as these symbols are all reserved for other tokens. For longer identifiers, kebab-case should be used, eg print-values, for-each, add-1

Types

Type refers to an element in the type system. Currently, this is either a Struct, or a Function Type

Struct refers to the element defined with the struct syntax. Structs are data-only types composed of multiple properties

Function Types are the types used for first class functions. They follow the format

LPAREN (type (COMMA type)*)? RPAREN ARROW type;

for example (Int) => String

Simple Syntax

Variable Declaration:

let [name] = [value]

LET identifer EQUAL expression;

Variable Declaration with Explicit Type:

let [name]: [Type] = value

LET identifer COLON type EQUAL expression;

Function Literals: ([Type] [name], [Type2] [name2], etc) => ReturnType? {}

functionLiteral:
    LPAREN (param (COMMA param)*)? RPAREN ARROW type? BLOCK
    ;

param: 
    type identifier
    ;

Single Expression Functions:

let [name] => [expression]

LET identifier ARROW expression;

Function Calling:

Simple function calling is the same as most languages: function-name()

For functions with arguments, parentheses can commas can be omitted:

function-name(arg1, arg2) function-name arg1 arg2

Receiver functions can also be invoked as if they were methods:

receiver-function param1 param2
param1 receiver-function param2
receiver-function(param1, param2)
param1.receiver-function(param2)

These are all functionally identical

Structs

Struct declaration is simple:

struct [StructName] {
    Type property-name
} 

For example:

struct Person {
    String name
    mut Int age
    Sex sex
}
structDeclaration: 
    STRUCT identifier LCPAREN structBody RCPAREN
    ;

structBody:
    structPropertyDeclaration*
    ;

structPropertyDeclaration:
    identifier identifier (EQUAL expression)?
    ;

Struct extending can be done anywhere in any file:

extend [StructName] {
    [let] | [struct]
}
structExtension:
    EXTEND identifier LCPAREN extensionBody RCPAREN
    ;
extensionBody:
    (variableDeclaration | structDeclaration)+
    ;

Generics

Generics will probably only be applicable to functions, with the following syntax:

<T>
let func-name = () => {}

This creates a single, unbound type parameter named T

Bound parameters are simple: <T: Int>

Parameters can also be bound by contract, eg:

<T { add(T) => Unit }>

will only accept types that define a function named add with the signature T => Unit

We can of course combine the two:

<T: Number { add(T) => Unit }> 
typeParameters:
    LANGLE_BRACKET typeParameter+ RANGLE_BRACKET
    ;

typeParameter
    : unboundTypeParameter
    | boundTypeParameter
    ;

unboundTypeParameter:
    identifier
    ;

boundTypeParameter
    : upperBoundTypeParameter
    | contractBoundTypeParameter
    | fullyBoundTypeParameter
    ;

upperBoundTypeParameter:
    identifier COLON identifer
    ;
 
contractBoundTypeParameter: 
    identifer LCPAREN contractSpec+ RCPAREN
    ;

contractSpec: 
    identifier LPAREN (identifier)* RPAREN ARROW identifier
    ;

fullyBoundTypeParameter:
   upperBoundTypeParameter LCPAREN contractSpec+ RCPAREN
    ;

Glossary

Variable - A piece of data scoped to either a file or a function Property - A piece of data scoped to a struct Struct - A data-only structure composed of multiple other properties, with a type, name, and optional default value. Function - A repeatable procedure of code, ideally representing a pure transformation between input and output.

Runtime

Simple Types

  • Int - represents a single integer, implementation will probably be 64-bit
  • Float - a floating-point number, probably 64-bit again
  • Number - any number
  • Char - a single Unicode character
  • String - a string of characters
  • Any - any type