Browse Source

Some improvements.

Beoran 5 years ago
parent
commit
ac4afe223f
6 changed files with 406 additions and 124 deletions
  1. 62 58
      ast.go
  2. 87 21
      builtin.go
  3. 10 15
      cmd/muesli/main.go
  4. 1 0
      parser.go
  5. 153 18
      value.go
  6. 93 12
      vm.go

+ 62 - 58
ast.go

@@ -66,7 +66,7 @@ func (astkind AstBasicMetaKind) String() string {
 	return string(astkind)
 }
 
-func (astkind AstBasicMetaKind) Run(vm *VM, ast Ast, val ListValue) Value {
+func (astkind AstBasicMetaKind) Run(vm *VM, ast Ast, val ...Value) Value {
 	return EmptyListValue()
 }
 
@@ -95,99 +95,102 @@ func (astkind AstMetaKindError) String() string       { return "AstError      "
 func (astkind AstMetaKindFlatten) String() string     { return "AstFlatten    " }
 
 
-func (astkind AstMetaKindNone) Run(vm *VM, ast Ast, val ListValue) Value {return EmptyListValue() }
+func (astkind AstMetaKindNone) Run(vm *VM, ast Ast, val ...Value) Value { return EmptyValue{} }
 
-func (astkind AstMetaKindProgram) Run(vm *VM, ast Ast, val ListValue) Value {
-	res := EmptyListValue()
-	for _, child := range ast.Children() {
-		res.Append(child.Run(vm, val))
-	}
-	return res
+func (astkind AstMetaKindProgram) Run(vm *VM, ast Ast, val ...Value) Value {
+	return vm.RunChildrenLastResult(ast, val...)
 }
 
-func (astkind AstMetaKindStatements) Run(vm *VM, ast Ast, val ListValue) Value {
-	res := EmptyListValue()
-	for _, child := range ast.Children() {
-		res.Append(child.Run(vm, val))
-	}
-	return res
+func (astkind AstMetaKindStatements) Run(vm *VM, ast Ast, val ...Value) Value {
+	return vm.RunChildrenLastResult(ast, val...)
 }
 
-func (astkind AstMetaKindStatement) Run(vm *VM, ast Ast, val ListValue) Value {
-	return vm.RunChildren(ast, val)
+func (astkind AstMetaKindStatement) Run(vm *VM, ast Ast, val ...Value) Value {
+	panic("AstMetaKindStatement")
+	return vm.RunChildren(ast, val...)
 }
 
-func (astkind AstMetaKindClosed) Run(vm *VM, ast Ast, val ListValue) Value {return EmptyListValue() }
-func (astkind AstMetaKindSet) Run(vm *VM, ast Ast, val ListValue) Value {
+func (astkind AstMetaKindClosed) Run(vm *VM, ast Ast, val ...Value) Value {return EmptyListValue() }
+func (astkind AstMetaKindSet) Run(vm *VM, ast Ast, val ...Value) Value {
 	varName := ast.Value()
-	value := vm.RunChildren(ast, val)
+	value := vm.RunChildren(ast, val...)
 	vm.Register(varName.String(), value)
 	return value
 }
 
-func (astkind AstMetaKindGet) Run(vm *VM, ast Ast, val ListValue) Value {
-	varName := ast.Value()
-	return NewListValue(vm.Lookup(varName.String()))
+func (astkind AstMetaKindGet) Run(vm *VM, ast Ast, val ...Value) Value {
+	target := vm.RunChildrenFirstResult(ast, val...).(ListValue)
+	return vm.Lookup(target.String())
 }
 
-func (astkind AstMetaKindTarget) Run(vm *VM, ast Ast, val ListValue) Value {
-	return NewListValue(ast.Value())
+func (astkind AstMetaKindTarget) Run(vm *VM, ast Ast, val ...Value) Value {
+	return ast.Value()
 }
-func (astkind AstMetaKindCommand) Run(vm *VM, ast Ast, val ListValue) Value {
+
+func (astkind AstMetaKindCommand) Run(vm *VM, ast Ast, val ...Value) Value {
 	commandName := ast.Value()	
-	arglist, _ := vm.RunChildren(ast, val).(ListValue)
-	arguments := arglist.First()
-	log.Printf("Command execute: %s %v", commandName.String(), arguments)
-	return vm.CallNamed(commandName.String(), arguments)
+	arguments := vm.RunChildrenFirstResult(ast, val...)
+	if argList, isList := arguments.(ListValue) ; isList {
+		log.Printf("Command execute: %s %v", commandName.String(), argList)
+		return vm.CallNamed(commandName.String(), argList)
+	} else {
+		return NewErrorValuef("Internal error when calling %s.", commandName.String())
+	}
 }
-func (astkind AstMetaKindArguments) Run(vm *VM, ast Ast, val ListValue) Value {	
-	return vm.RunChildren(ast, val)
+
+func (astkind AstMetaKindArguments) Run(vm *VM, ast Ast, val ...Value) Value {	
+	return vm.RunChildren(ast, val...)
 }
-func (astkind AstMetaKindArgument) Run(vm *VM, ast Ast, val ListValue) Value {
+
+func (astkind AstMetaKindArgument) Run(vm *VM, ast Ast, val ...Value) Value {
 	panic("AstMetaKindArgument")
-	vm.RunChildren(ast, val)
-	reslist, _ := vm.RunChildren(ast, val).(ListValue)
-	return reslist.First()
+	return vm.RunChildrenFirstResult(ast, val...)
 }
-func (astkind AstMetaKindExpression) Run(vm *VM, ast Ast, val ListValue) Value {
-	return vm.RunChildren(ast, val)
+
+func (astkind AstMetaKindExpression) Run(vm *VM, ast Ast, val ...Value) Value {
+	panic("AstMetaKindExpression")
+	return vm.RunChildrenLastResult(ast, val...)
 }
-func (astkind AstMetaKindBlock) Run(vm *VM, ast Ast, val ListValue) Value {
-	return vm.RunChildren(ast, val)
+
+func (astkind AstMetaKindBlock) Run(vm *VM, ast Ast, val ...Value) Value {
+	return vm.RunChildrenLastResult(ast, val...)
 }
-func (astkind AstMetaKindParenthesis) Run(vm *VM, ast Ast, val ListValue) Value {
-	return vm.RunChildren(ast, val)
+
+func (astkind AstMetaKindParenthesis) Run(vm *VM, ast Ast, val ...Value) Value {
+	return vm.RunChildrenLastResult(ast, val...)
 }
-func (astkind AstMetaKindList) Run(vm *VM, ast Ast, val ListValue) Value {
-	return vm.RunChildren(ast, val)
+
+func (astkind AstMetaKindList) Run(vm *VM, ast Ast, val ...Value) Value {
+	return vm.RunChildren(ast, val...)
 }
 
-func (astkind AstMetaKindCapture) Run(vm *VM, ast Ast, val ListValue) Value {
-	return vm.RunChildren(ast, val)
+func (astkind AstMetaKindCapture) Run(vm *VM, ast Ast, val ...Value) Value {
+	return vm.RunChildren(ast, val...)
 }
-func (astkind AstMetaKindWordValue) Run(vm *VM, ast Ast, val ListValue) Value {
+
+func (astkind AstMetaKindWordValue) Run(vm *VM, ast Ast, val ...Value) Value {
 	return ast.Value()
 }
 
-func (astkind AstMetaKindWord) Run(vm *VM, ast Ast, val ListValue) Value {
+func (astkind AstMetaKindWord) Run(vm *VM, ast Ast, val ...Value) Value {
 	return ast.Value()
 }
-func (astkind AstMetaKindType) Run(vm *VM, ast Ast, val ListValue) Value {
+func (astkind AstMetaKindType) Run(vm *VM, ast Ast, val ...Value) Value {
 	return ast.Value()
 }
-func (astkind AstMetaKindValue) Run(vm *VM, ast Ast, val ListValue) Value {
+func (astkind AstMetaKindValue) Run(vm *VM, ast Ast, val ...Value) Value {
 	return ast.Value()
 }
 
-func (astkind AstMetaKindEnd) Run(vm *VM, ast Ast, val ListValue) Value {
-	return EmptyListValue() 
+func (astkind AstMetaKindEnd) Run(vm *VM, ast Ast, val ...Value) Value {
+	return EmptyValue{}
 }
 
-func (astkind AstMetaKindError) Run(vm *VM, ast Ast, val ListValue) Value {
-	return NewListValue(ast.Value())
+func (astkind AstMetaKindError) Run(vm *VM, ast Ast, val ...Value) Value {
+	return ast.Value()
 }
 
-func (astkind AstMetaKindFlatten) Run(vm *VM, ast Ast, val ListValue) Value {
+func (astkind AstMetaKindFlatten) Run(vm *VM, ast Ast, val ...Value) Value {
 	return EmptyListValue()
 }
 
@@ -195,7 +198,7 @@ func (astkind AstMetaKindFlatten) Run(vm *VM, ast Ast, val ListValue) Value {
 
 type AstKind interface {
 	String() string
-	Run(vm *VM, ast Ast, val ListValue) Value
+	Run(vm *VM, ast Ast, val ...Value) Value
 }
 
 /*
@@ -340,11 +343,12 @@ func (ast Ast) Child(index int) *Ast {
 	return ast.children[index]
 }
 
-func (ast Ast) Run(vm *VM, val ListValue) Value {
+func (ast Ast) Run(vm *VM, val ...Value) Value {
+	res := ast.AstKind.Run(vm, ast, val...)
 	if vm != nil && vm.Tracer != nil {
-		vm.Trace(*vm, ast, val)
+		vm.Trace(*vm, ast, res)
 	}
-	return ast.AstKind.Run(vm, ast, val)
+	return res
 }
 
 func (ast *Ast) Walk(walker func(node *Ast) *Ast) *Ast {

+ 87 - 21
builtin.go

@@ -1,47 +1,113 @@
 package muesli
 
 import "fmt"
+import "log"
 
+type LogTracer struct {
+}
+
+func (t LogTracer) Trace(vm VM, ast Ast, val ... Value) bool {
+	log.Printf("Trace: %s -> %v", ast.String(), val)
+	return false
+}
+
+
+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 ")
+	return false
+}
 
-func printf(vm *VM, args ...Value) ListValue {
-	var form string
-	var rest = args[1:len(args)]
-	resri := ListFromList(rest)
-	err := From(args[0], &form)
+func printf(vm *VM, args ...Value) Value {
+	var format string
+	rest, err := ParseArgs(args, &format)
 	if err != nil {
-		fmt.Printf("Error: %s\n", err.Error())
-	} else {
-		fmt.Printf(form, resri...)
+		return ErrorValue{err}
 	}
-	return NewListValue()
+	fmt.Printf(format, rest...)
+	return EmptyValue{}
 }
 
-func println(vm *VM, args ...Value) ListValue {
+func println(vm *VM, args ...Value) Value {
 	var msg string
-	// resri := ListFromList(rest)
-	err := From(args[0], &msg)
+	_, err := ParseArgs(args, &msg)
 	if err != nil {
-		fmt.Printf("Error: %s\n", err.Error())
+		return ErrorValue{err}
+	} else {
+		fmt.Println(msg)
 	}
-	fmt.Println(msg)
-	return NewListValue()
+	return EmptyValue{}
 }
 
-func p(vm *VM, args ...Value) ListValue {
-	argi := ListFromList(args)
-	fmt.Println(argi...)
+func p(vm *VM, args ...Value) Value {	
 	for _, arg := range args {
 		fmt.Printf("%v\n", arg)
 	}	
-	return NewListValue()
+	return EmptyValue{}
+}
+
+func trace(vm *VM, args ...Value) Value {
+	var b bool = true
+	fmt.Printf("command trace: %v\n", args)
+	_, err := ParseArgs(args, &b)
+	if err != nil {
+		fmt.Printf("Error: %s\n", err.Error())
+		return ErrorValue{err}
+	}
+	fmt.Printf("command trace: bool: %v\n", b)
+	if b {
+		vm.Tracer = FmtTracer{}
+	} else {
+		vm.Tracer = nil
+	}
+	return BoolValue(b)
+}
+
+func addi(vm *VM, args ...Value) Value {
+	var i1, i2 int
+	_, err := ParseArgs(args, &i1, &i2)
+	if err != nil {
+		fmt.Printf("Error: %s\n", err.Error())
+		return ErrorValue{err}
+	}
+	return IntValue(i1 + i2)
+}
+
+func addf(vm *VM, args ...Value) Value {
+	var f1, f2 float64
+	_, err := ParseArgs(args, &f1, &f2)
+	if err != nil {
+		fmt.Printf("Error: %s\n", err.Error())
+		return ErrorValue{err}
+	}
+	return FloatValue(f1 + f2)
+}
+
+func val(vm *VM, args ...Value) Value {
+	if len(args) < 1 {
+		return NewErrorValuef("val requres one argument.")
+	}
+	return args[0]
 }
 
 
 func (vm *VM) RegisterBuiltins() {
+	vm.RegisterBuiltin("addi", addi)
+	vm.RegisterBuiltin("addf", addf)
+	// vm.RegisterCover("add")
 	vm.RegisterBuiltin("p", p)
-	vm.RegisterBuiltin("prinln", println)
+	vm.RegisterBuiltin("println", println)
 	vm.RegisterBuiltin("printf", printf)
+	vm.RegisterBuiltin("trace", trace)
+	vm.RegisterBuiltin("val", val)
 }
 
 
-

+ 10 - 15
cmd/muesli/main.go

@@ -1,7 +1,7 @@
 package main
 
 import (
-	"log"
+	"fmt"
 	"os"
 	"path/filepath"
 )
@@ -9,14 +9,6 @@ import (
 import "gitlab.com/beoran/muesli"
 import "github.com/peterh/liner"
 
-type LogTracer struct {
-}
-
-func (t * LogTracer) Trace(vm muesli.VM, ast muesli.Ast, val muesli.ListValue) bool {
-	log.Printf("Trace: %s %v", ast.String(), val)
-	return false
-}
-
 func runLine(vm *muesli.VM, in string) error {	
 	parser := muesli.NewParserFromString(in)
 	ast := parser.Parse()
@@ -24,7 +16,10 @@ func runLine(vm *muesli.VM, in string) error {
 	if err != nil {
 		return err
 	}
-	vm.RunAst(*ast, muesli.NewListValue())
+	result := vm.RunAst(*ast, muesli.NewListValue())
+	if result != nil { 
+		fmt.Printf(">>%s\n", result.String())
+	}
 	
 	return nil
 }
@@ -34,14 +29,14 @@ func runLines(vm *muesli.VM, line *liner.State) error {
 		if in, err := line.Prompt("> "); err == nil {
 			err = runLine(vm, in)
 			if err != nil { 
-				log.Print("Error %s: ", err)
+				fmt.Print("Error %s: \n", err)
 			}
 			line.AppendHistory(in)
 		} else if err == liner.ErrPromptAborted {
-			log.Print("Aborted")
+			fmt.Print("Aborted\n")
 			return nil
 		} else {
-			log.Print("Error reading line: ", err)
+			fmt.Print("Error reading line: %s\n", err)
 		}
 	}
 	return nil
@@ -49,7 +44,7 @@ func runLines(vm *muesli.VM, line *liner.State) error {
 
 func main() {
 	vm := muesli.NewVM()
-	vm.Tracer = &LogTracer{}
+	vm.Tracer = &muesli.FmtTracer{}
 	vm.RegisterBuiltins() 
 	line := liner.NewLiner()
 	defer line.Close()
@@ -76,7 +71,7 @@ func main() {
 	runLines(vm, line)
 	
 	if f, err := os.Create(historyName); err != nil {
-		log.Print("Error writing history file: ", err)
+		fmt.Print("Error writing history file: %s\n", err)
 	} else {
 		line.WriteHistory(f)
 		f.Close()

+ 1 - 0
parser.go

@@ -187,6 +187,7 @@ func (parser *Parser) ParseArguments() *Ast {
 		children = append(children, child)
 	}
 	ast.AppendChildren(children...)
+	fmt.Printf("ParseArguments: %v\n", children)
 	return ast
 }
 

+ 153 - 18
value.go

@@ -6,6 +6,10 @@ import "fmt"
 type Value interface {
 	String() string
 	Type() TypeValue
+	// Convert the value to a normal go value which must be passed 
+	// in as a pointer to which the value mmust be set, 
+	// or return an error if the concversion is not possible.
+	Convert(to interface{}) error
 }
 
 type IntValue int64
@@ -120,6 +124,10 @@ func (list *ListValue) AppendList(toAppend ListValue) {
 	list.List = append(list.List, toAppend.List...)
 }
 
+func (list ListValue) Length() int {
+	return len(list.List)
+}
+
 func (list *ListValue) Index(i int) Value {
 	if i >= len(list.List) {
 		return NilValue
@@ -132,6 +140,11 @@ func (list *ListValue) First() Value {
 	return list.Index(0)
 }
 
+func (list *ListValue) Last() Value {
+	return list.Index(list.Length()-1)
+}
+
+
 func EmptyListValue() ListValue {
 	return ListValue{make([]Value, 0)}
 }
@@ -144,27 +157,149 @@ func NewValueArray(elements ...Value) []Value {
 	return elements
 }
 
+
+func (from IntValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *string:
+			(*toPtr) = from.String()
+		case *int8:
+			(*toPtr) = int8(from)
+		case *int16:
+			(*toPtr) = int16(from)
+		case *int32:
+			(*toPtr) = int32(from)
+		case *int64:
+			(*toPtr) = int64(from)
+		case *int:
+			(*toPtr) = int(from)
+		case *bool:			 
+			(*toPtr) = (from != 0)
+		case *float32:
+			(*toPtr) = float32(from)
+		case *float64:
+			(*toPtr) = float64(from)
+		default:
+			return NewErrorValuef("Cannot convert value %v to %v", from, to)
+	}
+	return nil
+}
+
+func (from FloatValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *string:
+			(*toPtr) = from.String()
+		case *int8:
+			(*toPtr) = int8(from)
+		case *int16:
+			(*toPtr) = int16(from)
+		case *int32:
+			(*toPtr) = int32(from)
+		case *int64:
+			(*toPtr) = int64(from)
+		case *int:
+			(*toPtr) = int(from)
+		case *bool:			 
+			(*toPtr) = (from != 0) 		
+		case *float32:
+			(*toPtr) = float32(from)
+		case *float64:
+			(*toPtr) = float64(from)
+		default:
+			return NewErrorValuef("Cannot convert value %v to %v", from, to)
+	}
+	return nil
+}
+	
+func (from StringValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *string:
+			(*toPtr) = from.String()
+		default:
+			return NewErrorValuef("Cannot convert value %v to %v", from, to)
+	}
+	return nil
+}
+
+func (from WordValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *string:
+			(*toPtr) = from.String()
+		default:
+			return NewErrorValuef("Cannot convert value %v to %v", from, to)
+	}
+	return nil
+}
+
+
+func (from TypeValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *string:
+			(*toPtr) = from.String()
+		default:
+			return NewErrorValuef("Cannot convert value %v to %v", from, to)
+	}
+	return nil
+}
+
+
+func (from BoolValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *bool:			 
+			(*toPtr) = bool(from) 		
+		default:
+			return NewErrorValuef("Cannot convert value %v to %v", from, to)
+	}
+	return nil
+}
+
+func (from ErrorValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *string:
+			(*toPtr) = from.String()
+		case *error:
+			(*toPtr) = from.error
+		default:
+			return NewErrorValuef("Cannot convert value %v to %v", from, to)
+	}
+	return nil
+}
+
+func (from EmptyValue) Convert(to interface{}) error {
+	return NewErrorValuef("Cannot convert the empty value %v to %v", from, to)
+}
+
+func (from ListValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *[]Value:
+			(*toPtr) = from.List
+		default:
+			return NewErrorValuef("Cannot convert value %v to %v", from, to)
+	}
+	return nil
+}
+
+
 /* Helpers to easily convert Muesli values to "normal" Go values. */
 func From(from Value, to interface{}) error {
-	switch val := from.(type) {
-	case WordValue:
-		(*to.(*string)) = string(val)
-	case StringValue:
-		(*to.(*string)) = string(val)
-	case TypeValue:
-		(*to.(*string)) = string(val)
-	case IntValue:
-		(*to.(*int64)) = int64(val)
-	case FloatValue:
-		(*to.(*float64)) = float64(val)
-	case BoolValue:
-		(*to.(*bool)) = bool(val)
-	case ErrorValue:
-		return val.error
-	default:
-		return fmt.Errorf("Cannot convert value %v to %v", from, to)
+	return from.Convert(to)
+}
+
+/* Helpers to easily convert Muesli value lists to "normal" Go values. */
+func ParseArgs(args []Value, to...interface{}) ([]interface{}, error) {
+	if len(to) > len(args) {
+		return nil, NewErrorValuef("Too few arguments, expected %d, got %d", len(to), len(args))
 	}
-	return nil
+	i:= 0
+	for ; i < len(to) ; i ++ {
+		fromElt := args[i]
+		toElt 	:= to[i]
+		err := fromElt.Convert(toElt)
+		if err != nil {
+			return nil, err
+		}
+	}
+	rest := args[i:len(args)]
+	return ListFromList(rest), nil
 }
 
 /* Helpers to easily convert Muesli values from "normal" Go values. */

+ 93 - 12
vm.go

@@ -4,15 +4,15 @@ package muesli
 // import "fmt"
 
 // Handler function
-type Handler func(vm *VM, arguments ...Value) ListValue
+type Handler func(vm *VM, arguments ...Value) Value
 
-func (handler *Handler) Call(vm *VM, arguments ...Value) ListValue {
+func (handler *Handler) Call(vm *VM, arguments ...Value) Value {
 	return (*handler)(vm, arguments...)
 }
 
 // A callable Value must implement the Caller interface
 type Caller interface {
-	Call(vm *VM, arguments ...Value) ListValue
+	Call(vm *VM, arguments ...Value) Value
 }
 
 // Callable value types
@@ -24,7 +24,15 @@ func (val CallableValue) String() string {
 	return val.Name
 }
 
-func (val *CallableValue) Call(vm *VM, arguments ...Value) ListValue {
+func (val CallableValue) Type() TypeValue {
+	return TypeValue("Callable")
+}
+
+func (from CallableValue) Convert(to interface{}) error {
+	return NewErrorValuef("Cannot convert the callable value %v to %v", from, to)
+}
+
+func (val *CallableValue) Call(vm *VM, arguments ...Value) Value {
 	panic("Not implemented")
 }
 
@@ -122,7 +130,7 @@ func NewCoverValue(name string) CoverValue {
 	return result
 }
 
-func (cover *CoverValue) Call(vm *VM, arguments ...Value) ListValue {
+func (cover *CoverValue) Call(vm *VM, arguments ...Value) Value {
 	signature := CalculateSignature(arguments...)
 	if overload, ok := cover.Overloads[signature]; ok {
 		return overload.Call(vm, arguments...)
@@ -147,6 +155,21 @@ func (v CoverValue) Type() TypeValue   { return CoverTypeValue }
 func (v BuiltinValue) Type() TypeValue { return BuiltinTypeValue }
 func (v DefinedValue) Type() TypeValue { return DefinedTypeValue }
 
+func (from CoverValue) Convert(to interface{}) error {
+	return NewErrorValuef("Cannot convert the cover value %v to %v", from, to)
+}
+
+func (from BuiltinValue) Convert(to interface{}) error {
+	return NewErrorValuef("Cannot convert the builtin value %v to %v", from, to)
+}
+
+func (from DefinedValue) Convert(to interface{}) error {
+	return NewErrorValuef("Cannot convert the defined value %v to %v", from, to)
+}
+
+
+
+
 // Scope of symbols defined in the VM, hierarchical
 type Scope struct {
 	parent   *Scope
@@ -199,7 +222,7 @@ func NewFrame(parent *Frame) *Frame {
 }
 
 type Tracer interface {
-	Trace(vm VM, ast Ast, val ListValue) bool
+	Trace(vm VM, ast Ast, values ...Value) bool
 }
 
 // Virtual machine
@@ -306,21 +329,79 @@ func (vm *VM) Fail() {
 	vm.Frame.failed = true
 }
 
-func (vm *VM) RunChildren(ast Ast, args ListValue) Value {
+func (vm *VM) RunChildren(ast Ast, args ...Value) Value {	
+	if ast.CountChildren() < 1 {
+		return EmptyValue{}
+	}
+	/* if ast.CountChildren() == 1 {
+		return ast.Child(0).Run(vm, args)
+	}
+	*/	
 	result := NewListValue()
 	for _, child := range ast.Children() {
-		val := child.Run(vm, args)
-		reslist, isList := val.(ListValue)
-		if isList {
+		val := child.Run(vm, args...)
+		
+		// skip empty results
+		if _, isEmpty := val.(EmptyValue); isEmpty  {
+			continue
+		}
+		
+		// errors in the results take precendence and are propagated upwards.
+		if err, isErr := val.(ErrorValue); isErr  {			
+			return err
+		}	
+	
+		// Flatten lists
+		/*
+		if reslist, isList := val.(ListValue) ; isList && reslist.Length() > 0 {
 			result.AppendList(reslist)
 		}
+		*/ 
 		result.Append(val)
 	}
 	return result
 }
 
-func (vm *VM) RunAst(ast Ast, args ListValue) Value {
-	return ast.Run(vm, args)
+func (vm *VM) RunChildrenLastResult(ast Ast, args ...Value) Value {
+	var result Value = EmptyValue{}
+	for _, child := range ast.Children() {
+		val := child.Run(vm, args...)
+				
+		// skip empty results
+		if _, isEmpty := val.(EmptyValue); isEmpty  {
+			continue
+		}
+		
+		// errors in the results take precendence and are propagated upwards.
+		if err, isErr := val.(ErrorValue); isErr  {			
+			return err
+		}
+		result = val	
+	}
+	// The last non empty result is the result of this function.
+	return result
+}
+
+func (vm *VM) RunChildrenFirstResult(ast Ast, args ...Value) Value {
+	var result Value = EmptyValue{}
+	for _, child := range ast.Children() {
+		val := child.Run(vm, args...)
+				
+		// skip empty results
+		if _, isEmpty := val.(EmptyValue); isEmpty  {
+			continue
+		}
+		// otherwise if non empty return the result. 
+		return val
+	}
+	return result
+}
+
+
+
+
+func (vm *VM) RunAst(ast Ast, args ...Value) Value {
+	return ast.Run(vm, args...)
 }