ソースを参照

Let the VM walk the AST, not the AST run itself. Make the AST more passive.

Beoran 5 年 前
コミット
11f93ac5d6
2 ファイル変更117 行追加56 行削除
  1. 81 41
      ast.go
  2. 36 15
      vm.go

+ 81 - 41
ast.go

@@ -65,7 +65,7 @@ func (astkind AstBasicMetaKind) String() string {
 	return string(astkind)
 }
 
-func (astkind AstBasicMetaKind) Run(vm *VM, ast Ast, val ...Value) []Value {
+func (astkind AstBasicMetaKind) Eval(vm *VM, ast Ast, val ...Value) []Value {
 	return []Value{}
 }
 
@@ -93,24 +93,63 @@ func (astkind AstMetaKindEnd) String() string         { return "AstEnd        "
 func (astkind AstMetaKindError) String() string       { return "AstError      " }
 func (astkind AstMetaKindFlatten) String() string     { return "AstFlatten    " }
 
+func (astkind AstMetaKindNone) IsLeaf() bool        { return false }
+func (astkind AstMetaKindProgram) IsLeaf() bool     { return false }
+func (astkind AstMetaKindStatements) IsLeaf() bool  { return false }
+func (astkind AstMetaKindStatement) IsLeaf() bool   { return false }
+func (astkind AstMetaKindClosed) IsLeaf() bool      { return false }
+func (astkind AstMetaKindSet) IsLeaf() bool         { return false }
+func (astkind AstMetaKindGet) IsLeaf() bool         { return false }
+func (astkind AstMetaKindTarget) IsLeaf() bool      { return false }
+func (astkind AstMetaKindCommand) IsLeaf() bool     { return false }
+func (astkind AstMetaKindArguments) IsLeaf() bool   { return false }
+func (astkind AstMetaKindArgument) IsLeaf() bool    { return false }
+func (astkind AstMetaKindExpression) IsLeaf() bool  { return false }
+func (astkind AstMetaKindBlock) IsLeaf() bool       { return true  }
+func (astkind AstMetaKindParenthesis) IsLeaf() bool { return false }
+func (astkind AstMetaKindList) IsLeaf() bool        { return false }
+func (astkind AstMetaKindCapture) IsLeaf() bool     { return false }
+func (astkind AstMetaKindWordValue) IsLeaf() bool   { return true  }
+func (astkind AstMetaKindWord) IsLeaf() bool        { return true  }
+func (astkind AstMetaKindType) IsLeaf() bool        { return true  }
+func (astkind AstMetaKindValue) IsLeaf() bool       { return true  }
+func (astkind AstMetaKindEnd) IsLeaf() bool         { return true  }
+func (astkind AstMetaKindError) IsLeaf() bool       { return true  }
+func (astkind AstMetaKindFlatten) IsLeaf() bool     { return false }
 
-func (astkind AstMetaKindNone) Run(vm *VM, ast Ast, val ...Value) []Value { return ReturnEmpty() }
 
-func (astkind AstMetaKindProgram) Run(vm *VM, ast Ast, val ...Value) []Value {
-	return []Value{vm.RunChildrenLastResult(ast, val...)}
+func lastValue(val []Value) []Value {
+    if len(val) < 1 {
+        return ReturnEmpty()
+    }    
+    return []Value{val[len(val) - 1]}
 }
 
-func (astkind AstMetaKindStatements) Run(vm *VM, ast Ast, val ...Value) []Value {
-	return []Value{vm.RunChildrenLastResult(ast, val...)}
+func firstValue(val []Value) []Value {
+    if len(val) < 1 {
+        return ReturnEmpty()
+    }    
+    return []Value{val[0]}
 }
 
-func (astkind AstMetaKindStatement) Run(vm *VM, ast Ast, val ...Value) []Value {
-	return vm.RunChildren(ast, val...)
+
+func (astkind AstMetaKindNone) Eval(vm *VM, ast Ast, val ...Value) []Value { return ReturnEmpty() }
+
+func (astkind AstMetaKindProgram) Eval(vm *VM, ast Ast, val ...Value) []Value {
+    return lastValue(val)
+}
+
+func (astkind AstMetaKindStatements) Eval(vm *VM, ast Ast, val ...Value) []Value {
+    return lastValue(val)
 }
 
-func (astkind AstMetaKindClosed) Run(vm *VM, ast Ast, val ...Value) []Value {return ReturnEmpty() }
-func (astkind AstMetaKindSet) Run(vm *VM, ast Ast, val ...Value) []Value {
-	values := vm.RunChildren(ast, val...)
+func (astkind AstMetaKindStatement) Eval(vm *VM, ast Ast, val ...Value) []Value {
+	return val
+}
+
+func (astkind AstMetaKindClosed) Eval(vm *VM, ast Ast, val ...Value) []Value {return ReturnEmpty() }
+func (astkind AstMetaKindSet) Eval(vm *VM, ast Ast, val ...Value) []Value {
+	values := val
 	if len(values) < 2 { 
 		return Fail(fmt.Errorf("set needs at least 2 arguments: received %v", values)) 
 	}
@@ -128,8 +167,8 @@ func (astkind AstMetaKindSet) Run(vm *VM, ast Ast, val ...Value) []Value {
 	return Ok(value)
 }
 
-func (astkind AstMetaKindGet) Run(vm *VM, ast Ast, val ...Value) []Value {
-	targets := vm.RunChildren(ast, val...)
+func (astkind AstMetaKindGet) Eval(vm *VM, ast Ast, val ...Value) []Value {
+	targets := val
 	target := targets[0].String() 
 	if target == "(" || target == "$" {
 		if len(targets) < 2 {
@@ -141,76 +180,75 @@ func (astkind AstMetaKindGet) Run(vm *VM, ast Ast, val ...Value) []Value {
 	return Ok(vm.Lookup(target))
 }
 
-func (astkind AstMetaKindTarget) Run(vm *VM, ast Ast, val ...Value) []Value {
-	values := vm.RunChildren(ast, val...)
+func (astkind AstMetaKindTarget) Eval(vm *VM, ast Ast, val ...Value) []Value {
+	values := val
 	values = append([]Value{ast.Value()}, values...)  
 	return values
 }
 
-func (astkind AstMetaKindCommand) Run(vm *VM, ast Ast, val ...Value) []Value {
+func (astkind AstMetaKindCommand) Eval(vm *VM, ast Ast, val ...Value) []Value {
 	commandName := ast.Value()	
-	arguments := vm.RunChildren(ast, val...)
+	arguments := val
 	// log.Printf("Command execute: %s %v", commandName.String(), arguments)
 	return vm.CallNamed(commandName.String(), arguments...)
 }
 
-func (astkind AstMetaKindArguments) Run(vm *VM, ast Ast, val ...Value) []Value {	
-	return vm.RunChildren(ast, val...)
+func (astkind AstMetaKindArguments) Eval(vm *VM, ast Ast, val ...Value) []Value {	
+	return val
 }
 
-func (astkind AstMetaKindArgument) Run(vm *VM, ast Ast, val ...Value) []Value {
+func (astkind AstMetaKindArgument) Eval(vm *VM, ast Ast, val ...Value) []Value {
 	panic("AstMetaKindArgument")
-	return []Value{vm.RunChildrenFirstResult(ast, val...)}
+	return ReturnEmpty()
 }
 
-func (astkind AstMetaKindExpression) Run(vm *VM, ast Ast, val ...Value) []Value {
+func (astkind AstMetaKindExpression) Eval(vm *VM, ast Ast, val ...Value) []Value {
 	panic("AstMetaKindExpression")
-	return []Value{vm.RunChildrenLastResult(ast, val...)}
+	return ReturnEmpty()
 }
 
-func (astkind AstMetaKindBlock) Run(vm *VM, ast Ast, val ...Value) []Value {
+func (astkind AstMetaKindBlock) Eval(vm *VM, ast Ast, val ...Value) []Value {
 	// A block encountered in the AST is not executed. 
     // It results in an anonymous runnable with a clone of the AST embedded.
 	return Ok(NewBlockValue(&ast))
 }
 
-func (astkind AstMetaKindParenthesis) Run(vm *VM, ast Ast, val ...Value) []Value {
-	return []Value{vm.RunChildrenLastResult(ast, val...)}
+func (astkind AstMetaKindParenthesis) Eval(vm *VM, ast Ast, val ...Value) []Value {
+    return lastValue(val)
 }
 
-func (astkind AstMetaKindList) Run(vm *VM, ast Ast, val ...Value) []Value {	
-	result := vm.RunChildren(ast, val...)
-	list := &ListValue{List:result}
+func (astkind AstMetaKindList) Eval(vm *VM, ast Ast, val ...Value) []Value {	
+	list := &ListValue{List:val}
 	return []Value{list}
 }
 
-func (astkind AstMetaKindCapture) Run(vm *VM, ast Ast, val ...Value) []Value {
-	return vm.RunChildren(ast, val...)
+func (astkind AstMetaKindCapture) Eval(vm *VM, ast Ast, val ...Value) []Value {
+	return val
 }
 
-func (astkind AstMetaKindWordValue) Run(vm *VM, ast Ast, val ...Value) []Value {
+func (astkind AstMetaKindWordValue) Eval(vm *VM, ast Ast, val ...Value) []Value {
 	return []Value{ast.Value()}
 }
 
-func (astkind AstMetaKindWord) Run(vm *VM, ast Ast, val ...Value) []Value {
+func (astkind AstMetaKindWord) Eval(vm *VM, ast Ast, val ...Value) []Value {
 	return []Value{ast.Value()}
 }
-func (astkind AstMetaKindType) Run(vm *VM, ast Ast, val ...Value) []Value {
+func (astkind AstMetaKindType) Eval(vm *VM, ast Ast, val ...Value) []Value {
 	return []Value{ast.Value()}
 }
-func (astkind AstMetaKindValue) Run(vm *VM, ast Ast, val ...Value) []Value {
+func (astkind AstMetaKindValue) Eval(vm *VM, ast Ast, val ...Value) []Value {
 	return []Value{ast.Value()}
 }
 
-func (astkind AstMetaKindEnd) Run(vm *VM, ast Ast, val ...Value) []Value {
+func (astkind AstMetaKindEnd) Eval(vm *VM, ast Ast, val ...Value) []Value {
 	return []Value{EmptyValue{}}
 }
 
-func (astkind AstMetaKindError) Run(vm *VM, ast Ast, val ...Value) []Value {
+func (astkind AstMetaKindError) Eval(vm *VM, ast Ast, val ...Value) []Value {
 	return []Value{ast.Value()}
 }
 
-func (astkind AstMetaKindFlatten) Run(vm *VM, ast Ast, val ...Value) []Value {
+func (astkind AstMetaKindFlatten) Eval(vm *VM, ast Ast, val ...Value) []Value {
 	return ReturnEmpty()
 }
 
@@ -218,7 +256,9 @@ func (astkind AstMetaKindFlatten) Run(vm *VM, ast Ast, val ...Value) []Value {
 
 type AstKind interface {
 	String() string
-	Run(vm *VM, ast Ast, val ...Value) []Value
+	Eval(vm *VM, ast Ast, val ...Value) []Value
+    IsLeaf() bool
+    
 }
 
 /*
@@ -363,8 +403,8 @@ func (ast Ast) Child(index int) *Ast {
 	return ast.children[index]
 }
 
-func (ast Ast) Run(vm *VM, val ...Value) []Value {
-	res := ast.AstKind.Run(vm, ast, val...)
+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...)
 	}

+ 36 - 15
vm.go

@@ -553,11 +553,6 @@ func (vm *VM) Return(results ...Value) []Value {
 func (vm *VM) PopFrame() *Frame {
 	if (vm.Frame != vm.TopFrame) && (vm.Frame.parent != nil) {
 		frame := vm.Frame
-		if frame.failed && frame.parent != nil {
-           // failures are like panics and propagate up the call tree
-           frame.parent.failed = true
-           frame.parent.results = frame.results 
-		}
 		vm.Frame = frame.parent
 		return frame
 	}
@@ -575,7 +570,7 @@ func (vm *VM) PopScope() *Scope {
 
 func (block * BlockValue) Call(vm *VM, arguments ...Value) []Value {
 	ast := block.Ast
-	arr := vm.RunChildren(*ast, arguments...)
+	arr := vm.RunAst(*ast, arguments...)
 	return arr
 }
 
@@ -713,14 +708,11 @@ func (vm *VM) Fail() {
 	vm.Frame.failed = true
 }
 
+/*
 func (vm *VM) RunChildren(ast Ast, args ...Value) []Value {	
 	if ast.CountChildren() < 1 {
 		return ReturnEmpty()
 	}
-	/* if ast.CountChildren() == 1 {
-		return ast.Child(0).Run(vm, args)
-	}
-	*/	
 	result := []Value{}
 	for _, child := range ast.Children() {
         position := ast.Token().Position
@@ -802,7 +794,6 @@ func (vm *VM) RunChildrenFirstResult(ast Ast, args ...Value) Value {
 			res := vm.Frame.results
 			return res[0]
 		}
-		/*				
 		// skip empty results
 		if len(val) < 1  {
 			continue
@@ -811,18 +802,48 @@ func (vm *VM) RunChildrenFirstResult(ast Ast, args ...Value) Value {
 		first := val[0]
 		if _, isEmpty := first.(EmptyValue); isEmpty  {
 			continue
-		}*/
+		}
 		// otherwise if non empty return the result. 
 		return val[0]
 	}
 	return result
 }
-
-
+*/
 
 
 func (vm *VM) RunAst(ast Ast, args ...Value) []Value {
-	return ast.Run(vm, args...)
+    var result []Value
+    pos := ast.Token().Position
+    vm.PushNewFrame(&pos)
+    defer vm.PopFrame()
+    // Leaf nodes, both declared and in practice are self evaluating.
+    if ast.Kind().IsLeaf() || ast.CountChildren() < 1 {
+        result = ast.Eval(vm)
+        if vm.Frame.returned || vm.Frame.failed {
+            result = vm.Frame.results
+        }
+    } else {
+        var subResult = []Value{}
+        // Depth first recursion.
+        for _, child := range ast.Children() {
+            sub := vm.RunAst(*child)
+            subResult = append(subResult, sub...)
+            /*
+            if frame.failed && frame.parent != nil {
+                // failures are like panics and propagate up the call tree
+                frame.parent.failed = true
+                frame.parent.results = frame.results 
+            }
+            */
+
+            if vm.Frame.returned || vm.Frame.failed {
+                subResult = vm.Frame.results
+                break;
+            }
+        }
+        result = ast.Eval(vm, subResult...)
+    }
+	return result
 }