Lynxer

Documentation

Codeblocks in Lynxer

This document describes the codeblock feature in Lynxer, which allows storing and executing blocks of code dynamically. Codeblocks are a powerful tool for implementing callbacks, higher-order functions, and dynamic behavior.


Table of Contents

  1. Introduction
  2. Syntax
  3. Storing Codeblocks
  4. Executing Codeblocks
  5. Parameterized Codeblocks
  6. Inline Execution
  7. Named Codeblocks
  8. Limitations
  9. Examples
  10. See Also

Introduction

Codeblocks in Lynxer allow you to store executable blocks of code in variables and execute them dynamically. They are useful for implementing callbacks, higher-order functions, and dynamic behavior where the logic is determined at runtime.


Syntax

Codeblocks are defined using the codeblock type. They can be stored in variables, passed as arguments, and executed using the exec() function.


Storing Codeblocks

You can store a block of code in a variable using the codeblock type:

codeblock helloWorld = {
    println("Hello world!");
};

Executing Codeblocks

To execute a stored codeblock, use the exec() function:

exec(){{helloWorld}}

Parameterized Codeblocks

Codeblocks can declare parameters and their types. These parameters are checked against the provided values when the codeblock is executed.

Declaring Parameters

codeblock example = {
    println(name, age);
}[str name, int age]

Executing with Parameters

exec("Alice", 30){{example}}

Inline Execution

You can execute a codeblock inline using the exec() function with a parameter list:

str text = "left";
exec(str text) {
    println(text);
}

Named Codeblocks

Codeblocks can be passed as arguments to functions and executed dynamically:

Example: Passing Codeblocks to Functions

global setup() {
    codeblock code1 = {
        println("A");
    };
}

global something(){handler} {
    exec(){{handler}}
}

global main() {
    global.something(){{code1}}
}

Caller-Supplied Blocks on Any Function Form

The {...} block list is not specific to global. A func or local declaration takes caller-supplied blocks the same way: the list follows the () parameter list and precedes the body, and the parser does not distinguish the three forms when reading it.

global setup(){}

global runTwice(){first}{second}{
    exec(){{first}}
    exec(){{second}}
}

func applyTwice(int value){apply}{
    exec(value){{apply}}
    exec(value){{apply}}
}

global main(){
    runTwice(){
        println("one");
    }{
        println("two");
    }

    codeblock triple = {
        println(value * 3);
    };
    applyTwice(4){{triple}}   // 12 printed twice

    local notify(){block}{
        exec(){{block}}
    }
    notify(){
        println("done");
    }
}

See functions for the three declaration forms and their calling conventions.


Inferred Parameters

If the parameter list is omitted, the names and types are inferred from the variables referenced in the codeblock:

codeblock example = {
    println(text);
};

exec("Hello!"){{example}}

Limitations

  1. No Nested Scopes: Codeblocks do not introduce nested scopes. Variables declared inside a codeblock are not visible outside of it, and vice versa.
  2. No Block Expressions: Codeblocks cannot be used as expressions (e.g., returning their result directly). Use explicit return statements.
  3. Unique Identifiers: Codeblock identifiers must be unique across the entire source file.
  4. No Async/Await: Codeblocks cannot be used with async/await syntax.
  5. Old Syntax: The old exec({name}) form is replaced by exec(){{name}}.

Examples

Example 1: Basic Codeblock

codeblock greet = {
    println("Hello, " + name + "!");
}[str name] // requires a user provided parameter named "name"

exec("Alice"){{greet}}

Example 2: Inline Execution

str message = "World";
exec(str message) {
    println("Hello, " + message + "!");
}

Example 3: Passing Codeblocks to Functions

global runCode(){code} {
    exec(){{code}}
}

global main() {
    codeblock task = {
        println("Executing task...");
    };
    global.runCode(){{task}}
}

Example 4: Inferred Parameters

codeblock printValues = {
    println(x, y);
};

exec(10, 20){{printValues}}

See Also