7.0.1685-testing

GreyCat Language Syntax

Special characters

Below find an overview of special characters defined in GreyCat:

Character Functionality Example Further explanation
; Code line delimiter println(“hello”); Statement terminator
// End-of-line comment println(“hello”); // hello Comments
:: Access static type, node functions and attributes and enum keys var t = time::now(); Static attributes
. Access normal (non static) attributes of types or nodes var hour = Date::fromTime(t, null).hour; Type attributes
&&,||, ! Logical and, or, not Logical operators
? Indicate nullable properties var t: time?; Nullable chapter
?? Providing default value in case of null var startTime = t??time::now(); Nullish coalescing operator
-> Shorthand to access attribute or function of a node Arrow operator
"${}" Template to stringify object withing curly braces “The time is: ${t}” // The time is: ‘2024-06-21T06:32:24.555669+00:00’ String template
?= Shorthand to assign value if variable is null myVar ?= 0; Non-null Assign

Variables and scopes

The var keywords is used to declare new variables.

  • Variables declared at the root of the file(neither in types nor in functions), also called module variables .
  • Variables declared inside a function are stateless.
var x : node<int?>; // module variable.

fn main() {
    var y = 1; // stateless local variable

    if(*x == null){
        x.set(0);
    }
    x.set(*x + 1);
}

Remember that GreyCat handles the database as a graph; and module variables can be seen as entrypoints to this graph.

Only nodes can be used in module variables

This means that we automatically generate the node at runtime.

var index: nodeIndex<String, String>;
var list: nodeList<String>;
var geoIndex: nodeGeo<String>;
var timeIndex: nodeTime<String>;

fn main(){
    list.add("foo");
}

You can see this in action in our Hello World example.

GreyCat leverages an Automatic Reference Counter (ARC) strategy to cleanup variables.
For performance reason, no Garbage Collector is used, and variables are available until all references from all scopes are clear

Functions

Like most imperative languages, GreyCat uses functions to encapsulate a compute unit Functions in GreyCat are defined by the keyword fn

fn add(x: int, y: int): int {
    return x + y;
}

fn main() {
    println(add(1, 2)); // prints 3
}

Function add takes 2 integers x and y as parameter, and returns an integer.

All Parameters in a function need to be typed, defining a return type is not necessary

So-called lambda functions are available too, and can be assigned to variables:

fn hello() {
    return "hello";
}

fn main() {
  // f_hello points to function hello:
  var f_hello = project::hello;
  println(f_hello()); // displays "hello"
}

Functions as values can therefore be used as function parameters, the following example illustrates function composition:

fn helloa() {
    return "helloa";
}

fn main() {
  var f_helloa = project::helloa;
  var f_len = fn (s: String): int { return s.size(); };

  var gof = fn (g: function, f: function): int { return f_len(f_helloa() as String ); };

  var l = gof(f_len, f_helloa);

  println("length of ${f_helloa()} is ${l}");
}

Statement Terminator

In GreyCat, every statement must end with a semicolon ; . This allows the compiler to understand where one statement ends and the next begins, ensuring proper execution and reducing ambiguity.


App Entrypoints

The entrypoint of GreyCat application is the main function.

fn main() {
    println("This is my application entrypoint");
}

Running the serve command will always execute main function and start the server

greycat serve
# INFO  2024-06-17T09:15:20.700959+00:00 GreyCat is serving on port: 8080
# This im my applications entrypoint

Or if you wish to execute a function without starting a server, you can execute the run command

greycat run
# This im my applications entrypoint

With the run command you can pass any function as argument to run instead of main

fn foo() {
    println("Hello from foo");
}

The syntax is always <module>::<function>

greycat run project::foo
# Hello from foo
Currently it's not possible to pass arguments to a function with `greycat run`

Comments

GreyCat supports single-line end-of-line comment and multi-line (block) comments:

// Single line comment
fn main() {

var a = 1; // End-of-line comment

/*
    Multi
    line
    comment
*/
}

It also support documentation comments preceding statements using triple-slashes (///):

/// This is a doc comment
fn my_function() {}

Typing

Types are declared with colon : followed by the type

var a: int; // is of type integer

for functions

// Takes an integer an return an integer
fn foo(arg: int): int {
    return arg;
}
Only function arguments and return types are checked at runtime, variable types are only for the lsp

This is valid code, GreyCat will compile and run, but the lsp will warn you.

fn foo() {
    var a: int = 0;
    a = "Hello";
}

Naming convention

Item Convention Example
Modules snake_case smart_city.gcl
Types / Class / Enum UpperCamelCase enum TransactionChannel
Primitive types camelCase nodeTime, nodeIndex, int
Functions camelCase / snake_case * fn getCities()
Variables / Attributes camelCase / snake_case * var cities_by_name: nodeIndex;
  • For functions and attributes we leave the freedom of camelCase/snake_case according to readability
  • Usually index names are more readable in snakecase: _city_by_location, city_by_name
  • Simple attributes or variable names are usually in camelCase: firstName, primaryContract