itssamuelrowe/Zen

Implement closures

itssamuelrowe opened this issue · 0 comments

Zen can encourage functional programming with closures. Given Zen does not treat functions as expressions, mostly due to the limitations imposed by indentation based blocks, local functions can be used to simulate closures.

Consider the following example which makes use of a closure.

// Test.zen

define makeCounter()
    var count = 1
    define next()
        count = count + 1
        return count
    return next

define main(...arguments)
    var next = makeCounter()
    var value = next()
    print(value)

In the background, the compiler treats the above example as if it were of the following form.

// Test.zen

class Test$Closure1 extends Closure
    
    var counter

    define new(counter0)
        counter = counter0
    
    define invoke()
        counter = counter + 1
        return counter

define makeCounter()
    var counter = 1
    var next = new Test$Closure1(counter)
    return next

define main(...arguments)
    var next = makeCounter()
    var value = next.invoke()
    print(value)
  • Are closures really necessary in Zen?
  • When a local variable or local field is treated as a function, the compiler
    translates it to reference.invoke(...). Initially, the target method can be invoked via invoke_dynamic. Once inheritance is implemented, such invocations can be done via the invoke_virtual instruction.
  • How is object.field() handled? The bootstrap method is a good place to load the
    target method.
bootstrap(...) {
    ...
    zen_Object_t* self = ...;
    zen_Function_t* function = ...;
    ...
    if (function == NULL) {
        zen_Field_t* field = ...;
        if (field != NULL) {
            zen_Class_t* class0 = zen_Object_getClass(field);
            function = zen_Class_getFunction(class0, "invoke", ...);
             ...
        }
    }
    return function;
}