Browse Source

Fix returns.

Beoran 4 years ago
parent
commit
5b9bb25e4b
3 changed files with 72 additions and 23 deletions
  1. 3 2
      ast.go
  2. 8 11
      builtin.go
  3. 61 10
      vm.go

+ 3 - 2
ast.go

@@ -190,7 +190,8 @@ func (astkind AstMetaKindCommand) Eval(vm *VM, ast Ast, val ...Value) []Value {
 	commandName := ast.Value()	
 	arguments := val
 	// log.Printf("Command execute: %s %v", commandName.String(), arguments)
-	return vm.CallNamed(commandName.String(), arguments...)
+	res := vm.CallNamed(commandName.String(), arguments...)	
+	return res
 }
 
 func (astkind AstMetaKindArguments) Eval(vm *VM, ast Ast, val ...Value) []Value {	
@@ -406,7 +407,7 @@ func (ast Ast) Child(index int) *Ast {
 func (ast Ast) Eval(vm *VM, val ...Value) []Value {
 	res := ast.AstKind.Eval(vm, ast, val...)
 	if vm != nil && vm.Tracer != nil {
-		vm.Trace(*vm, ast, res...)
+		vm.Trace("%v: Eval: %v", ast, res)
 	}
 	return res
 }

+ 8 - 11
builtin.go

@@ -9,8 +9,9 @@ import "sort"
 type LogTracer struct {
 }
 
-func (t LogTracer) Trace(vm VM, ast Ast, val ... Value) bool {
-	log.Printf("Trace: %s -> %v", ast.String(), val)
+func (t LogTracer) Trace(vm VM, fmt string, args ... interface{}) bool {
+	args = append([]interface{}{vm.BackTrace()}, args...)	
+	log.Printf("%s: " + fmt,  args...)
 	return false
 }
 
@@ -18,14 +19,9 @@ func (t LogTracer) Trace(vm VM, ast Ast, val ... Value) bool {
 type FmtTracer struct {
 }
 
-func (t FmtTracer) Trace(vm VM, ast Ast, args ... Value) bool {
-	arg  := args[0]
-	rest := args[1:len(args)]
-	fmt.Printf("Trace: %s: %v -> ", ast.String(), arg)
-	for _, v := range rest {
-		fmt.Printf("%v, ", v)
-	}
-	fmt.Printf("<-\n ")
+func (t FmtTracer) Trace(vm VM, fm string, args ... interface{}) bool {
+	args = append([]interface{}{vm.BackTrace()}, args...)	
+	fmt.Printf("%s: " + fm + "\n",  args...)
 	return false
 }
 
@@ -202,9 +198,10 @@ func val(vm *VM, args ...Value) []Value {
 	return args
 }
 
-func builtin_return(vm *VM, args ...Value) []Value {
+func builtin_return(vm *VM, args ...Value) []Value {	
 	vm.Frame.returned = true
 	vm.Frame.results = args
+	vm.Trace("Returning... %v", vm.Frame)
 	return args
 }
 

+ 61 - 10
vm.go

@@ -1,7 +1,11 @@
 // vm, the virtual low level machine that runs MUESLI.
 package muesli
 
-import "fmt"
+import (
+	"fmt"
+	"strings"
+)
+
 
 // Handler function
 type Handler func(vm *VM, arguments ...Value) []Value
@@ -514,7 +518,7 @@ func NewFrame(parent *Frame, position *Position) *Frame {
 }
 
 type Tracer interface {
-	Trace(vm VM, ast Ast, values ...Value) bool
+	Trace(vm VM, fmt string, args ... interface{}) bool
 }
 
 // Virtual machine
@@ -534,8 +538,15 @@ func NewVM() *VM {
 	return vm
 }
 
-func (vm *VM) PushNewFrame(position *Position) *Frame {
+func (vm *VM) Trace(fm string, args ... interface{}) {
+	if vm.Tracer != nil {
+		vm.Tracer.Trace(*vm, fm, args...)
+	}
+}
+
+func (vm *VM) PushNewFrame(position *Position) *Frame {	
 	frame := NewFrame(vm.Frame, position)
+	vm.Trace("PushFrame %v->%v\n", vm.Frame, frame)
 	vm.Frame = frame
 	return frame
 }
@@ -552,9 +563,15 @@ func (vm *VM) Return(results ...Value) []Value {
 
 
 func (vm *VM) PopFrame() *Frame {
+	oldFrame := vm.Frame
+	vm.Trace("PopFrame %v->%v\n", vm.Frame, vm.Frame.parent)
 	if (vm.Frame != vm.TopFrame) && (vm.Frame.parent != nil) {
 		frame := vm.Frame
 		vm.Frame = frame.parent
+		// Copy frame results up.
+		vm.Frame.returned = oldFrame.returned
+		vm.Frame.failed = oldFrame.failed
+		vm.Frame.results = oldFrame.results
 		return frame
 	}
 	return nil
@@ -624,15 +641,11 @@ func (vm *VM) AddTrace(err error) error {
 }
 
 func (vm *VM) CallCallable(callable Callable, arguments ...Value) []Value {
-	defer vm.PopFrame()
 	defer vm.PopScope()
+	defer vm.PopFrame()
 	vm.PushNewFrame(callable.Position())
 	vm.PushNewScope()
 	result := callable.Call(vm, arguments...)
-	
-		
-	
-	
 	return result
 }
 
@@ -657,7 +670,7 @@ func (vm * VM) CallNamedFramed(name string, arguments ...) []Value {
 */
 
 // ScopeUp Returns the levelth scope up from the current one where 0 is the 
-// current scope. Returns the toplevel scope if l is greather than the current 
+// current scope. Returns the toplevel scope if l is greater than the current
 // scope stack depth.
 func (vm * VM) ScopeUp(level int) *Scope {
 	scope := vm.Scope
@@ -814,13 +827,16 @@ func (vm *VM) RunAst(ast Ast, args ...Value) []Value {
         result = ast.Eval(vm)
         if vm.Frame.returned || vm.Frame.failed {
             result = vm.Frame.results
+            vm.Frame.returned = false
+            vm.Frame.failed = false
         }
     } else {
         var subResult = []Value{}
         // Depth first recursion.
-        for _, child := range ast.Children() {
+        for i, child := range ast.Children() {
             sub := vm.RunAst(*child)
             subResult = append(subResult, sub...)
+            vm.Trace("RunAst: %d %v %v %v\n", i, child, sub, vm.Frame)
             /*
             if frame.failed && frame.parent != nil {
                 // failures are like panics and propagate up the call tree
@@ -831,6 +847,8 @@ func (vm *VM) RunAst(ast Ast, args ...Value) []Value {
 
             if vm.Frame.returned || vm.Frame.failed {
                 subResult = vm.Frame.results
+                vm.Frame.returned = false
+                vm.Frame.failed = false
                 break;
             }
         }
@@ -846,6 +864,39 @@ func (vm *VM) DefinedHelpers() []Helper {
 	return vm.Scope.DefinedHelpers()
 }
 
+func (vm * VM) BackTraceFrames() []*Frame {
+	bt := []*Frame{}
+		
+	for frame := vm.Frame ; frame.parent != nil ; frame = frame.parent	 {
+		bt = append(bt, frame)
+	}
+			
+	return bt
+}
+
+func (vm * VM) BackTracePositions() []*Position {
+	bt := []*Position{}
+		
+	for frame := vm.Frame ; frame.parent != nil ; frame = frame.parent	 {
+		bt = append(bt, frame.position)
+	}
+			
+	return bt
+}
+
+func (vm * VM) BackTraceStrings() []string {
+	bt := []string{}
+		
+	for frame := vm.Frame ; frame.parent != nil ; frame = frame.parent	 {
+		bt = append(bt, frame.position.String())
+	}
+			
+	return bt
+}
+
+func (vm * VM) BackTrace() string {
+	return strings.Join(vm.BackTraceStrings(), "\n")
+}
 
 
 /*