Hello world (stateless)

Create a folder called hello and open it in your editor (preferably VSCode with plugin)

Create a file named project.gcl, add the following content to it and save it:

fn main() {
    println("Hello world");
}

in a terminal execute the following command to get the first Hello World message:

greycat run
# Hello world

Hello world (stateful)

Now we will add a bit of data storage to our script:

var counter: int?;

fn main() {
    counter = (counter ?? 0) + 1;
    println("Hello world, ${counter}");
}

the first time we execute that script, the counter will be null therefore, we set its value to 1, then on the second execution 2, etc:

greycat run
# Hello world, 1

greycat run
# Hello world, 2

greycat run
# Hello world, 3

Hello world (server)

We can also create a server from this persistent counter. We slightly modify our project.gcl by adding two annotations and rename the function.

var counter: int?;

@expose
@write
fn count(): String {
    counter = (counter ?? 0) + 1;
    return "Hello world, ${counter}";
}

using the same executable we can now run the following command:

greycat serve --user=1
# INFO  2023-09-18T20:19:49.813204+00:00 GreyCat is serving on port: 8080
# WARN  2023-09-18T20:19:49.813312+00:00 Impersonate mode with user 1

this blocking command runs until ctrl-c is pressed. In another terminal we can now request this count api such as:

curl -X POST -d '[]' http://localhost:8080/project::count
# "Hello world, 4"
curl -X POST -d '[]' http://localhost:8080/project::count
# "Hello world, 5"
curl -X POST -d '[]' http://localhost:8080/project::count
# "Hello world, 6"

Why not starting from zero? Well, the code evolved but we managed to recompile the code and keep the data.

As we said GreyCat is here to work on an agile way, increasing graph by new processing is our daily job!

This is a toy example but there is more !

What is the catch for the program evolution, is GreyCat interpreted?

No. GreyCat is a bytecode compiled language.

Now you can use the build command

greycat build

this will result in a project.gcp which is the intermediate format GreyCat relies on.

This artefact can be sent to a remote GreyCat server to trigger an evolution such as the one you just tested in the console.

You talk about Graph, where are the nodes?

You’re right, storing integer values is not so impressive, let’s create some nodes.

In a nutshell, GreyCat can create nodes like persistent variables, which can be represented as a disk address, and handle fields like a backref to a previous node.

This backref can be navigated using a resolve function

var counter: int?;
var last: node?;

fn main() {
    var nb = 100_000_000;
    while (nb != 0) {
        last = node::new(last);
        nb--;
    }
    println(last.resolve()!!.resolve()!!.resolve());
}

now in the console execute the following:

time greycat run --cache=100 --store=10000
# {"_type":"core.node","ref":"fba1d71700000000"}
# greycat run --cache=100 --store=10000  12.98s user 0.37s system 96% cpu 13.786 total
du -h gcdata/store/data.bin 
# 193M    gcdata/store/data.bin

What’s the catch here?

GreyCat is configured to use only 100MB RAM memory while we configure the store to scale up to 10GB.

However we created 100 millions nodes chained together, this is almost 200MB of data!

The full data does not fit in requested memory but GreyCat has done its magic to handle it within the bounds in a bit more than 10 seconds.

GreyCat offers many node types that reflects common collection types, to cite a few: nodeTime (timeseries), nodeIndex (dictionnary) and nodeGeo (geoseries).