From 431e8f9a662b6aa7f98f4ebec0e1a0936ad1d549 Mon Sep 17 00:00:00 2001 From: prod2 <95874442+prod2@users.noreply.github.com> Date: Wed, 9 Feb 2022 06:47:00 +0100 Subject: [PATCH] implicit return for functions --- src/ndspkg/compiler/functions.nim | 6 ------ src/ndspkg/compiler/scope.nim | 27 +++++++++++++------------- src/ndspkg/vm.nim | 14 ++++++-------- tests/break.nds | 10 +++++----- tests/closures.nds | 32 +++++++++++++++---------------- tests/collections.nds | 6 +++--- tests/precedence.nds | 8 ++++---- tests/sugar.nds | 8 ++++---- 8 files changed, 51 insertions(+), 60 deletions(-) diff --git a/src/ndspkg/compiler/functions.nim b/src/ndspkg/compiler/functions.nim index c60091c..f0347be 100644 --- a/src/ndspkg/compiler/functions.nim +++ b/src/ndspkg/compiler/functions.nim @@ -34,12 +34,6 @@ proc parseArgs(comp: Compiler): int = proc parseCall(comp: Compiler) = # ( consumed - # create the call env - # current stack before opCall: - # ... - # opCall converts it to this - # ... - let argcount = comp.parseArgs() # emit call diff --git a/src/ndspkg/compiler/scope.nim b/src/ndspkg/compiler/scope.nim index 63c8c58..fa34c1a 100644 --- a/src/ndspkg/compiler/scope.nim +++ b/src/ndspkg/compiler/scope.nim @@ -18,22 +18,17 @@ proc beginScope*(comp: Compiler, function: bool = false) = when debugCompiler: debugEcho &"Begin scope called for depth {comp.scopes.len} function? {function}" - if function: - scope.labels.add("result") - scope.labels.add("function") - else: + if not function: while comp.match(tkLabel): let label = comp.previous.text[1..^1] scope.labels.add(label) - - if function: - # if it's a function scope, the frame will move - # access to outside locals is also limited to upvalues and closures - comp.stackIndex = 0 - else: # only put the opNil if it's not a function scope, since # function scopes are initialized by the caller comp.writeChunk(1, opNil) + else: + # if it's a function scope, the frame will move + # access to outside locals is also limited to upvalues and closures + comp.stackIndex = 0 for label in scope.labels: comp.addLocal(&":{label}", delta = 0) @@ -48,12 +43,12 @@ proc restore*(comp: Compiler, scope: Scope) = debugEcho &"Restored scope: delta {delta}" proc restoreInFunct*(comp: Compiler, scope: Scope) = - let pops = comp.stackIndex - comp.writePops(pops) + #let pops = comp.stackIndex + #comp.writePops(pops) comp.stackIndex = scope.goalStackIndex - when debugCompiler: - debugEcho &"Restored function scope: delta {pops}; new stackindex: {comp.stackIndex}" + #when debugCompiler: + # debugEcho &"Restored function scope: delta {pops}; new stackindex: {comp.stackIndex}" proc jumpToEnd*(comp: Compiler, scope: Scope) = ## Jumps to the end of scope, does not affect stackIndex @@ -93,6 +88,10 @@ proc endScope*(comp: Compiler): Scope = comp.restore(popped) # patch jumps to after the scope (such jumps from breaks emit the pops before jumping) for jump in popped.jumps: + when assertionsCompiler: + if function: + # all jumps should only happen to named block expressions + comp.error("Assertion failed: jump attempt to end function.") comp.patchJump(jump, popped.goalStackIndex) if function: comp.writeChunk(0, opReturn) diff --git a/src/ndspkg/vm.nim b/src/ndspkg/vm.nim index 2ec3b52..f5f83ed 100644 --- a/src/ndspkg/vm.nim +++ b/src/ndspkg/vm.nim @@ -226,7 +226,12 @@ proc run*(chunk: Chunk): InterpretResult = if frames.len() == 1: break else: - ip = frames.pop().returnIp # remove frame that's over + let retval = stack.pop() + let oldframe = frames.pop() + ip = oldframe.returnIp # remove frame that's over + let length = stack.len() - oldframe.stackBottom + stack.deleteTopN(length) + stack.push(retval) of opTrue: stack.add(fromBool(true)) of opFalse: @@ -303,15 +308,8 @@ proc run*(chunk: Chunk): InterpretResult = runtimeError(&"Wrong number of arguments, expected {arity}, got {argcount}.") break of opCall: - # create the call env - # current stack before opCall: - # ... - # opCall converts it to this - # ... let argcount = ip.readUI8() let funct = stack.getIndexNeg(argcount) - - stack.setIndexNeg(argcount, fromNil()) # replace the function with nil: this is the return value slot funct.call(argcount): break of opCreateList: diff --git a/tests/break.nds b/tests/break.nds index 9fdfe2d..d12d12f 100644 --- a/tests/break.nds +++ b/tests/break.nds @@ -44,13 +44,13 @@ //expect:5.0 -var f = funct() { +var f = funct() { @result var y = 1; var z = 3; var p = 1; :result = y + (z + p); { - break @function; + break @result; }; :result = 10; }; @@ -60,7 +60,7 @@ print (f()); //expect:15.0 f = funct(m, n) - :result = m + n + m + n ; print (f(f(5, 5), 5)); @@ -69,7 +69,7 @@ print (f(f(5, 5), 5)); //expect:10.0 var g = funct() - :result = {@a + {@a :a = { @b :b = { @c :c = 10; @@ -83,7 +83,7 @@ print (g()); //expect:9.0 var h = funct() - :result = {@a + {@a :a = { @b :b = { @c :a = 3; diff --git a/tests/closures.nds b/tests/closures.nds index 4380965..4728db3 100644 --- a/tests/closures.nds +++ b/tests/closures.nds @@ -1,16 +1,16 @@ // cascade -var f1 = funct() { +var f1 = funct() { @result var x = 1; var y = 5; - :result = funct() { + :result = funct() { @result var z = 8; print (x); x = x + 1; - :result = funct() { + :result = funct() { @result print (x); x = x + 1; - :result = funct() { + :result = funct() { @result print (x); print (y); print (z); @@ -33,7 +33,7 @@ f1()()()()(); // capturing closures in lists: -var f = funct() { +var f = funct() { @result var y = 5; var x = @[ funct() print (y), @@ -52,7 +52,7 @@ inst[0](); // multiple different labels -var f2 = funct() { +var f2 = funct() { @result var x = { @a @b // this captures the internal value, not whatever it returns is assigned to :result = @{ @@ -73,7 +73,7 @@ inst2["get"](); // capturing args var argcap = funct(n) - :result = funct() print (n) + funct() print (n) ; //expect:8.1 @@ -82,12 +82,12 @@ argcap(8.1)(); // oop: constructors, getters, setters -var newAnimal = funct(species, color) { +var newAnimal = funct(species, color) { @result var species = species; // copy it so that it's mutable, if args ever get immutable var animal = @{ - ["getSpecies"] = funct() :result = species, + ["getSpecies"] = funct() species, ["setSpecies"] = funct(newSpecies) species = newSpecies, - ["getColor"] = funct() :result = color, // this captures an argument directly + ["getColor"] = funct() color, // this captures an argument directly }; :result = animal; }; @@ -116,7 +116,7 @@ print (turtle["getSpecies"]()); // 1: -var makeClosure = funct(value) { +var makeClosure = funct(value) { @result var closure = funct() { print (value); }; @@ -132,9 +132,9 @@ bagel(); // 2: (multi level closures) -var outer = funct() { +var outer = funct() { @result var x = "value"; - var middle = funct() { + var middle = funct() { @result var inner = funct() { print (x); }; @@ -157,7 +157,7 @@ in(); // 3: (mixed multi level closures) -outer = funct() { +outer = funct() { @result var a = 1; var b = 2; var result; @@ -170,7 +170,7 @@ outer = funct() { result = inner; }; middle(); - :result = funct() :result = result; + :result = funct() result; }; //expect:10.0 @@ -238,7 +238,7 @@ globalGet(); // bonus: the last one with a list twist -var bonus = funct() { +var bonus = funct() { @result var a = 1; var f = funct() { print (a); diff --git a/tests/collections.nds b/tests/collections.nds index 1b1c1b1..74ba376 100644 --- a/tests/collections.nds +++ b/tests/collections.nds @@ -1,8 +1,8 @@ // a test about collections, WIP -var returnlist = funct() { - :result = @[1, 2, 3, 4]; -}; +var returnlist = funct() + @[1, 2, 3, 4] +; //expect:3.0 print (returnlist()[2]); diff --git a/tests/precedence.nds b/tests/precedence.nds index b1b9932..2d423cf 100644 --- a/tests/precedence.nds +++ b/tests/precedence.nds @@ -15,7 +15,7 @@ print (-((3 + 2) * 2) + 1); // calls and indexes -var returnlist = funct() { +var returnlist = funct() { @result :result = @[]; :result[0] = 4; :result[1] = 6; @@ -27,9 +27,9 @@ var returnlist = funct() { print (returnlist()[2]); // priority over unary -var truesayer = funct() { - :result = true; -}; +var truesayer = funct() + true +; //expect:false print (!truesayer()); \ No newline at end of file diff --git a/tests/sugar.nds b/tests/sugar.nds index 71c14dc..ad75ba9 100644 --- a/tests/sugar.nds +++ b/tests/sugar.nds @@ -3,11 +3,11 @@ // :: piping function call -var double = funct(num) :result = num * 2; +var double = funct(num) num * 2; var four = 2 :: double(); -var multiply = funct(num, factor) :result = num * factor; +var multiply = funct(num, factor) num * factor; var six = 2 :: multiply(3); @@ -65,7 +65,7 @@ class->method; var multiplier = @{ multiple = 5, - do = funct(self, arg) :result = self.multiple * arg, + do = funct(self, arg) self.multiple * arg, }; multiplier->do(7) :: print; @@ -74,7 +74,7 @@ multiplier->do(7) :: print; // -> method call syntax with :: - check for precedence var returner = @{ - method = funct(self) :result = funct(n) :result = n * 2 + method = funct(self) funct(n) n * 2 }; 1.7 :: returner->method :: print;