expand closures test

This commit is contained in:
prod2 2022-02-05 12:56:07 +01:00
parent 9b3b1056ba
commit c04d520561
3 changed files with 213 additions and 66 deletions

View File

@ -397,6 +397,7 @@ proc addUpvalue(comp: Compiler, index: int): int =
## and creates an upvalue in every function up until the one
## including this local so that all of the function scopes in between
## have the right upvalue in them (compile time)
comp.error("addupvalue not implemented yet")
discard
proc resolveLocal(comp: Compiler, name: string): tuple[index: int, upvalue: bool] =

212
tests/closures.nds Normal file
View File

@ -0,0 +1,212 @@
// capturing closures in lists:
var f = funct() {
var y = 5;
var x = @[
funct() print y,
funct() y = y + 1
];
:result = x;
};
//expect:5.0
f()[0]();
f()[1]();
//expect:6.0
f()[0]();
// capturing the result of a function:
var f2 = funct() {
var x = { @f2
:result = funct() {
print :f2;
};
};
x = 5;
};
//expect:5.0
f2()();
// oop: constructors, getters, setters
var newAnimal = funct(species, color) {
var species = species; // copy it so that it's mutable, if args ever get immutable
var animal = @{
"getSpecies" = funct() :result = species,
"setSpecies" = funct(newSpecies) species = newSpecies,
"getColor" = funct() :result = color, // this captures an argument directly
};
:result = animal;
};
var horse1 = newAnimal("horse", "brown");
var horse2 = newAnimal("horse", "white");
var turtle = newAnimal("turtle", "brown");
//expect:horse
print horse1["getSpecies"]();
horse1["setSpecies"]("zebra");
//expect:zebra
print horse1["getSpecies"]();
//expect:brown
print horse1["getColor"]();
//expect:horse
print horse2["getSpecies"]();
//expect:white
print horse2["getColor"]();
//expect:turtle
print turtle["getSpecies"]();
// closure examples from craftinginterpreters
// 1:
var makeClosure = funct(value) {
var closure = funct() {
print value;
};
:result = closure;
};
var doughnut = makeClosure("doughnut");
var bagel = makeClosure("bagel");
//expect:doughnut
doughnut();
//expect:bagel
bagel();
// 2: (multi level closures)
var outer = funct() {
var x = "value";
var middle = funct() {
var inner = funct() {
print x;
};
print "create inner closure";
:result = inner;
};
print "return from outer";
:result = middle;
};
//expect:return from outer
var mid = outer();
//expect:create inner closure
var in = mid();
//expect:value
in();
// 3: (mixed multi level closures)
outer = funct() {
var a = 1;
var b = 2;
var result;
var middle = funct() {
var c = 3;
var d = 4;
var inner = funct() {
print a + c + b + d;
};
result = inner;
};
:result = result;
};
//expect:10.0
outer()();
// 4: manipulation of vals from closures
outer = funct() {
var x = "before";
var inner = funct() {
x = "assigned";
};
inner();
print x;
};
//expect:assigned
outer();
// 5: get/setters using globals
var globalSet;
var globalGet;
var main5 = funct() {
var a = "initial";
var set = funct() { a = "updated"; };
var get = funct() { print a; };
globalSet = set;
globalGet = get;
};
main();
globalGet();
//expect:initial
globalSet();
globalGet();
//expect:updated
// 6: multiple upvalues in a simple scope
{
var a = 1;
f = funct() {
print a;
};
var b = 2;
g = funct() {
print b;
};
var c = 3;
h = funct() {
print c;
};
print f();
print g();
print h();
//expect:1
//expect:2
//expect:3
};
// bonus: the last one with a list twist
var bonus = funct() {
var a = 1;
f = funct() {
print a;
};
var b = 2;
g = funct() {
print b;
};
var c = 3;
h = funct() {
print c;
};
:result = @[f, g, h];
};
bonus = bonus();
bonus[2]();
bonus[0]();
bonus[1]();
//expect:3
//expect:1
//expect:2

View File

@ -1,66 +0,0 @@
//_d so the test doesn't run yet
// capturing closures in lists:
var f = funct() {
var y = 5;
var x = @[
funct() print y,
funct() y = y + 1
];
:result = x;
};
//expect:5.0
f()[0]();
f()[1]();
//expect:6.0
f()[0]();
// capturing the result of a function:
var f2 = funct() {
var x = { @f2
:result = funct() {
print :f2;
};
};
x = 5;
};
//expect:5.0
f2()();
// oop: constructors, getters, setters
var newAnimal = funct(species, color) {
var species = species; // copy it so that it's mutable, if args ever get immutable
var animal = @{
"getSpecies" = funct() :result = species,
"setSpecies" = funct(newSpecies) species = newSpecies,
"getColor" = funct() :result = color, // this captures an argument directly
};
:result = animal;
};
var horse1 = newAnimal("horse", "brown");
var horse2 = newAnimal("horse", "white");
var turtle = newAnimal("turtle", "brown");
//expect:horse
print horse1["getSpecies"]();
horse1["setSpecies"]("zebra");
//expect:zebra
print horse1["getSpecies"]();
//expect:brown
print horse1["getColor"]();
//expect:horse
print horse2["getSpecies"]();
//expect:white
print horse2["getColor"]();
//expect:turtle
print turtle["getSpecies"]();
// TODO: tests for enclosing upvalues multiple levels up