Browse Source

Starting to become runnable.

Beoran 4 years ago
parent
commit
5e6a17f72a
12 changed files with 405 additions and 122 deletions
  1. 123 48
      ast.go
  2. 47 0
      builtin.go
  3. 86 0
      cmd/muesli/main.go
  4. 13 14
      design_muesli.muesli
  5. 3 1
      go.mod
  6. 4 0
      go.sum
  7. 38 27
      parser.go
  8. 6 5
      parser_test.go
  9. 6 3
      token.go
  10. 19 0
      value.go
  11. 48 14
      vm.go
  12. 12 10
      vm_test.go

+ 123 - 48
ast.go

@@ -4,6 +4,7 @@ package muesli
 import (
 	"fmt"
 	"strings"
+	"log"
 )
 
 type AstBasicMetaKind string
@@ -39,21 +40,21 @@ const (
 	AstKindProgram     = AstMetaKindProgram("Program")
 	AstKindStatements  = AstMetaKindStatements("Statements")
 	AstKindStatement   = AstMetaKindStatement("Statement")
-    AstKindClosed      = AstMetaKindSet("Closed")
+    // AstKindClosed      = AstMetaKindClosed("Closed")
 	AstKindSet         = AstMetaKindSet("Set")
 	AstKindGet         = AstMetaKindGet("Get")
 	AstKindTarget      = AstMetaKindTarget("Target")
 	AstKindCommand     = AstMetaKindCommand("Command")
 	AstKindArguments   = AstMetaKindArguments("Arguments")
-	AstKindArgument    = AstMetaKindArgument("Argument")
-	AstKindExpression  = AstMetaKindExpression("Expression")
+	// AstKindArgument    = AstMetaKindArgument("Argument")
+	// AstKindExpression  = AstMetaKindExpression("Expression")
 	AstKindBlock       = AstMetaKindBlock("Block")
 	AstKindParenthesis = AstMetaKindParenthesis("Parenthesis")
 	AstKindList        = AstMetaKindList("List")
-	AstKindCapture     = AstMetaKindCapture("Capture")
+	// AstKindCapture     = AstMetaKindCapture("Capture")
 	AstKindWordValue   = AstMetaKindWordValue("WordValue")
 	AstKindWord        = AstMetaKindWord("Word")
-	AstKindType        = AstMetaKindType("Type")
+	// AstKindType        = AstMetaKindType("Type")
 	AstKindValue       = AstMetaKindValue("Value")
 	AstKindEnd         = AstMetaKindEnd("End")
 	AstKindError       = AstMetaKindError("Error")
@@ -65,8 +66,8 @@ func (astkind AstBasicMetaKind) String() string {
 	return string(astkind)
 }
 
-func (astkind AstBasicMetaKind) Run(vm *VM, ast Ast, val []Value) []Value {
-	return EmptyValueArray()
+func (astkind AstBasicMetaKind) Run(vm *VM, ast Ast, val ListValue) Value {
+	return EmptyListValue()
 }
 
 func (astkind AstMetaKindNone) String() string        { return "AstNone       " }
@@ -94,71 +95,107 @@ func (astkind AstMetaKindError) String() string       { return "AstError      "
 func (astkind AstMetaKindFlatten) String() string     { return "AstFlatten    " }
 
 
-func (astkind AstMetaKindNone) Run(vm *VM, ast Ast, val []Value) []Value { return EmptyValueArray() }
+func (astkind AstMetaKindNone) Run(vm *VM, ast Ast, val ListValue) Value {return EmptyListValue() }
 
-func (astkind AstMetaKindProgram) Run(vm *VM, ast Ast, val []Value) []Value {
-	res := EmptyValueArray()
+func (astkind AstMetaKindProgram) Run(vm *VM, ast Ast, val ListValue) Value {
+	res := EmptyListValue()
 	for _, child := range ast.Children() {
-		res = append(res, child.Run(vm, val)...)
+		res.Append(child.Run(vm, val))
 	}
 	return res
 }
 
-func (astkind AstMetaKindStatements) Run(vm *VM, ast Ast, val []Value) []Value {
-	return EmptyValueArray()
+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 AstMetaKindStatement) Run(vm *VM, ast Ast, val ListValue) Value {
+	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 {
+	varName := ast.Value()
+	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 AstMetaKindStatement) Run(vm *VM, ast Ast, val []Value) []Value {
-	return EmptyValueArray()
+
+func (astkind AstMetaKindTarget) Run(vm *VM, ast Ast, val ListValue) Value {
+	return NewListValue(ast.Value())
 }
-func (astkind AstMetaKindClosed) Run(vm *VM, ast Ast, val []Value) []Value { return EmptyValueArray() }
-func (astkind AstMetaKindSet) Run(vm *VM, ast Ast, val []Value) []Value { return EmptyValueArray() }
-func (astkind AstMetaKindGet) Run(vm *VM, ast Ast, val []Value) []Value { return EmptyValueArray() }
-func (astkind AstMetaKindTarget) Run(vm *VM, ast Ast, val []Value) []Value {
-	return EmptyValueArray()
+func (astkind AstMetaKindCommand) Run(vm *VM, ast Ast, val ListValue) 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)
 }
-func (astkind AstMetaKindCommand) Run(vm *VM, ast Ast, val []Value) []Value {
-	return EmptyValueArray()
+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 EmptyValueArray()
+func (astkind AstMetaKindArgument) Run(vm *VM, ast Ast, val ListValue) Value {
+	panic("AstMetaKindArgument")
+	vm.RunChildren(ast, val)
+	reslist, _ := vm.RunChildren(ast, val).(ListValue)
+	return reslist.First()
 }
-func (astkind AstMetaKindArgument) Run(vm *VM, ast Ast, val []Value) []Value {
-	return EmptyValueArray()
+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 {
-	return EmptyValueArray()
+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 EmptyValueArray()
+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 EmptyValueArray()
+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 EmptyValueArray() }
-func (astkind AstMetaKindCapture) Run(vm *VM, ast Ast, val []Value) []Value {
-	return EmptyValueArray()
+
+func (astkind AstMetaKindCapture) Run(vm *VM, ast Ast, val ListValue) Value {
+	return vm.RunChildren(ast, val)
 }
-func (astkind AstMetaKindWordValue) Run(vm *VM, ast Ast, val []Value) []Value {
-	return EmptyValueArray()
+func (astkind AstMetaKindWordValue) Run(vm *VM, ast Ast, val ListValue) Value {
+	return ast.Value()
 }
-func (astkind AstMetaKindWord) Run(vm *VM, ast Ast, val []Value) []Value { return EmptyValueArray() }
-func (astkind AstMetaKindType) Run(vm *VM, ast Ast, val []Value) []Value { return EmptyValueArray() }
-func (astkind AstMetaKindValue) Run(vm *VM, ast Ast, val []Value) []Value {
-	return EmptyValueArray()
+
+func (astkind AstMetaKindWord) Run(vm *VM, ast Ast, val ListValue) Value {
+	return ast.Value()
 }
-func (astkind AstMetaKindEnd) Run(vm *VM, ast Ast, val []Value) []Value { return EmptyValueArray() }
-func (astkind AstMetaKindError) Run(vm *VM, ast Ast, val []Value) []Value {
-	return EmptyValueArray()
+func (astkind AstMetaKindType) Run(vm *VM, ast Ast, val ListValue) Value {
+	return ast.Value()
 }
-func (astkind AstMetaKindFlatten) Run(vm *VM, ast Ast, val []Value) []Value {
-	return EmptyValueArray()
+func (astkind AstMetaKindValue) Run(vm *VM, ast Ast, val ListValue) Value {
+	return ast.Value()
+}
+
+func (astkind AstMetaKindEnd) Run(vm *VM, ast Ast, val ListValue) Value {
+	return EmptyListValue() 
+}
+
+func (astkind AstMetaKindError) Run(vm *VM, ast Ast, val ListValue) Value {
+	return NewListValue(ast.Value())
+}
+
+func (astkind AstMetaKindFlatten) Run(vm *VM, ast Ast, val ListValue) Value {
+	return EmptyListValue()
 }
 
 
 
 type AstKind interface {
 	String() string
-	Run(vm *VM, ast Ast, val []Value) []Value
+	Run(vm *VM, ast Ast, val ListValue) Value
 }
 
 /*
@@ -230,6 +267,10 @@ type Ast struct {
 	token    Token
 }
 
+func (ast Ast) Value() Value {
+	return ast.token.Value
+}
+
 func NewAst(kind AstKind, parent *Ast, children []*Ast, token Token) *Ast {
 	ast := &Ast{AstKind: kind, parent: parent, token: token}
     return ast.AppendChildren(children...)
@@ -299,7 +340,10 @@ func (ast Ast) Child(index int) *Ast {
 	return ast.children[index]
 }
 
-func (ast Ast) Run(vm *VM, val []Value) []Value {
+func (ast Ast) Run(vm *VM, val ListValue) Value {
+	if vm != nil && vm.Tracer != nil {
+		vm.Trace(*vm, ast, val)
+	}
 	return ast.AstKind.Run(vm, ast, val)
 }
 
@@ -332,6 +376,22 @@ func (ast Ast) Display() {
 	})
 }
 
+func (ast Ast) Dump() string {
+	result := ""
+	ast.Walk(func(node *Ast) *Ast {
+		depth := node.Depth()
+		result += fmt.Sprintf("%s", strings.Repeat("--", depth))
+		if node != nil {
+			result += fmt.Sprintf("Ast: %s\n", node.String())
+		} else {
+			result += fmt.Sprintf("Ast: nil node\n")
+		}
+		return nil
+	})
+	return result
+}
+
+
 func (ast Ast) Depth() int {
 	var depth int = 0
 	parent := ast.Parent()
@@ -377,6 +437,21 @@ func NewAstWithToken(astkind AstKind, token Token) *Ast {
 	return NewAst(astkind, nil, EmptyAstArray(), token)
 }
 
+// If AST has errors, return it as a merged error, otherwise returns nil 
+func (ast *Ast) ToError() error {
+	errlist := ast.Errors()
+	if len(errlist) < 1 {
+		return nil
+	} 
+	sep := ""
+	res := ""
+	for _, err := range errlist {
+		res = fmt.Sprintf("%s%s%s", res, sep, err)
+		sep = "\n"
+	}
+	return fmt.Errorf("%s", res)
+}
+
 /*
 type AstProgram struct{ Ast }
 type AstStatements struct{ Ast }

+ 47 - 0
builtin.go

@@ -0,0 +1,47 @@
+package muesli
+
+import "fmt"
+
+
+func printf(vm *VM, args ...Value) ListValue {
+	var form string
+	var rest = args[1:len(args)]
+	resri := ListFromList(rest)
+	err := From(args[0], &form)
+	if err != nil {
+		fmt.Printf("Error: %s\n", err.Error())
+	} else {
+		fmt.Printf(form, resri...)
+	}
+	return NewListValue()
+}
+
+func println(vm *VM, args ...Value) ListValue {
+	var msg string
+	// resri := ListFromList(rest)
+	err := From(args[0], &msg)
+	if err != nil {
+		fmt.Printf("Error: %s\n", err.Error())
+	}
+	fmt.Println(msg)
+	return NewListValue()
+}
+
+func p(vm *VM, args ...Value) ListValue {
+	argi := ListFromList(args)
+	fmt.Println(argi...)
+	for _, arg := range args {
+		fmt.Printf("%v\n", arg)
+	}	
+	return NewListValue()
+}
+
+
+func (vm *VM) RegisterBuiltins() {
+	vm.RegisterBuiltin("p", p)
+	vm.RegisterBuiltin("prinln", println)
+	vm.RegisterBuiltin("printf", printf)
+}
+
+
+

+ 86 - 0
cmd/muesli/main.go

@@ -0,0 +1,86 @@
+package main
+
+import (
+	"log"
+	"os"
+	"path/filepath"
+)
+
+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()
+	err := ast.ToError()
+	if err != nil {
+		return err
+	}
+	vm.RunAst(*ast, muesli.NewListValue())
+	
+	return nil
+}
+
+func runLines(vm *muesli.VM, line *liner.State) error {
+	for { 	
+		if in, err := line.Prompt("> "); err == nil {
+			err = runLine(vm, in)
+			if err != nil { 
+				log.Print("Error %s: ", err)
+			}
+			line.AppendHistory(in)
+		} else if err == liner.ErrPromptAborted {
+			log.Print("Aborted")
+			return nil
+		} else {
+			log.Print("Error reading line: ", err)
+		}
+	}
+	return nil
+}
+
+func main() {
+	vm := muesli.NewVM()
+	vm.Tracer = &LogTracer{}
+	vm.RegisterBuiltins() 
+	line := liner.NewLiner()
+	defer line.Close()
+
+	line.SetCtrlCAborts(true)
+	home, _ := os.UserHomeDir()	
+	historyName := filepath.Join(home, ".muesli_history")
+
+	/* line.SetCompleter(func(line string) (c []string) {
+		for _, n := range names {
+			if strings.HasPrefix(n, strings.ToLower(line)) {
+				c = append(c, n)
+			}
+		}
+		return
+	})
+	*/
+
+	if f, err := os.Open(historyName); err == nil {
+		line.ReadHistory(f)
+		f.Close()
+	} 
+	
+	runLines(vm, line)
+	
+	if f, err := os.Create(historyName); err != nil {
+		log.Print("Error writing history file: ", err)
+	} else {
+		line.WriteHistory(f)
+		f.Close()
+	}
+}
+
+

+ 13 - 14
design_muesli.muesli

@@ -15,7 +15,7 @@
 but the {} pairs must match. 
 }
 
- 
+
 
 # Empty lines are ignored.
 
@@ -48,11 +48,11 @@ p -7.000005
 # The [ ] must be space separated. 
 # The type is Any[] if heterogenous,  
 
-# p [ foo "bar" ] 
+p [ foo "bar" ]
 
 # The type is Int[]  below
 
-# p [ 1 2 3 ] 
+p [ 1 2 3 ]
 
 
 # A sequence of a lower case letter followed by anything that is not whitespace.
@@ -87,12 +87,12 @@ command {
     print "second block"
 }
 
-# In Muesli all values are typed. Types can be defined by the built type command.
+# In Muesli all values are typed. Types can be defined by the builtin type command.
 type Door ( object locked Bool keys Item[] )
 
 # Commands can be defined by the built in 'to' command. 
 # They can have many arguments and many results.
-to open [door Door key Item]  Bool {
+to open[door Door key Item]  Bool {
     if (contains (member door key) key) {
         set (member door open) true
     }
@@ -109,8 +109,13 @@ to open [door Door key Item]  Bool {
 # and for primitive types <Bool|Int|String|Float|Word|Type>, Primitive, Any
 # You can override commands with more specific ones but not existing ones 
 # that have the same specificity.
-# Variables are nor part of the language but of the built in commands
-# Variables are set in the current scope with
+# To create such an overload you should create a "cover" with the builtin 
+# cover command. Covers are commands that dispatch to other commands based on 
+# the types of the arguments. 
+cover open open[door Door key Item]
+
+# Variables are not part of the language but there arebuiltin commands
+# to define them. Variables are set in the current scope with
 set a 10
 # And fetched in the current scope with get
 print (get a 10) 
@@ -121,7 +126,6 @@ upset a 10
 # =foo bar gets mapped to (set foo bar)
 =a 10
 
-
 # $foo means (get foo)  
 print $a
 
@@ -135,8 +139,7 @@ print $a
 # Or indirect getters
 print $$indirect
 
-
-# Control structures are merely built in functions.
+# Control structures are merely builtin functions.
 
 if (less a 10) {
     print "Less"
@@ -149,7 +152,6 @@ if (less a 10) {
 # embedded commands.
 # Do note that MUESLI uses dynamic scoping for ease of implementation
 
-
 #{
 
 BLOCK
@@ -166,8 +168,5 @@ PUSHW a
 CALL less
 CALL if
 
-
-
-
 }
 

+ 3 - 1
go.mod

@@ -1,3 +1,5 @@
-module muesli
+module gitlab.com/beoran/muesli
 
 go 1.12
+
+require github.com/peterh/liner v1.1.0

+ 4 - 0
go.sum

@@ -0,0 +1,4 @@
+github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
+github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/peterh/liner v1.1.0 h1:f+aAedNJA6uk7+6rXsYBnhdo4Xux7ESLe+kcuVUF5os=
+github.com/peterh/liner v1.1.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=

+ 38 - 27
parser.go

@@ -56,21 +56,25 @@ type Parser struct {
 type ParserError struct {
     *Parser
     *Token 
-    Error error
+    Chain error
+}
+
+func (pe ParserError) Error() string {
+	return fmt.Sprintf("%s %s", pe.Token.String(), pe.Chain.Error())
 }
 
 func (parser *Parser) SetLogger(logger Logger) {
 	parser.LoggerWrapper = LoggerWrapper{logger}
 }
 
-func (parser *Parser) Errorf(message string, args ...string) ParserError {
-	err := fmt.Errorf(message+" at token "+parser.current.String(), args)
-    pe := ParserError { Parser: parser, Token:&parser.current, Error: err }
+func (parser *Parser) Errorf(message string, args ...interface{}) ParserError {
+	err := fmt.Errorf(message, args...)
+    pe := ParserError { Parser: parser, Token:&parser.current, Chain: err }
     parser.Errors = append(parser.Errors, pe)
     return pe
 }
 
-func (parser *Parser) Panicf(message string, args ...string)  {
+func (parser *Parser) Panicf(message string, args ...interface{})  {
     pe := parser.Errorf(message, args...)
     panic(pe)
 }
@@ -81,8 +85,8 @@ func (parser *Parser) Advance() {
 	parser.LogDebug("Next token: %s\n", token.String())
 }
 
-/* Skips tokens until a closer ) } ] OEX or EOF is found, to skip parse errors,
- * and to be able to continue parsing despite errors.. */
+/* Skips tokens until a closer, namely ), }, ], EOX or EOF is found, 
+ * to skip parse errors, and to be able to continue parsing despite errors. */
 func (parser *Parser) SkipError() Token {
     parser.Advance()
     for {
@@ -99,13 +103,15 @@ func (parser *Parser) SkipError() Token {
 
 /* Looks at the current token and advances the lexer if the token is of any of
 the token kinds given in kinds. In this case it will return the accepted
-token and advance the parser. Otherwise, it will call panicf with ann
-* "Suntax error unexpected <token>".*/
+token and advance the parser. Otherwise, it will call parser.Panicf with a
+* "Syntax error unexpected <token>".*/
 func (parser *Parser) Require(kinds ...TokenKind) Token {
 	if parser.current.IsNone() {
 		parser.Advance()
 	}
-	    
+	
+	expected := ""
+	sep := ""    
 	for _, kind := range kinds {
 		if kind == parser.current.TokenKind {
 			accepted := parser.current
@@ -113,8 +119,10 @@ func (parser *Parser) Require(kinds ...TokenKind) Token {
             parser.LogDebug("Require: Accepted token: %s\n", accepted.String())
 			return accepted
 		}
+		expected = fmt.Sprintf("%s%s%s", expected, sep, kind.String())
 	}
-	parser.Panicf("error: unexpected token %s", parser.current.String())
+	
+	parser.Panicf("error: expected one of the following: %s", expected)
 	return Token{}
 }
 
@@ -123,6 +131,7 @@ func (parser *Parser) NewAstError(message string, args ...interface{}) *Ast {
 	sv := StringValue(fmt.Sprintf(message+" at token "+parser.current.String(), args))
 	pos := parser.current.Position
 	tok := NewToken(TokenKindError, sv, pos)
+	parser.Errorf(message, args...)
 	return NewAst(AstKindError, nil, EmptyAstArray(), tok)
 }
 
@@ -163,7 +172,7 @@ func (parser *Parser) ParseArgument() *Ast {
 			case parser.NextIsSet(): return parser.ParseSet()
 			case parser.NextIsClosed(): return parser.ParseClosed()
 			case parser.NextIsWordValue(): return parser.ParseWordValue()
-			default: parser.Panicf("error: in argument: unexpected %s", parser.current.String())
+			default: parser.Panicf("error: in argument: expected $, =, }, word or value")
 			return nil
 	}
 }
@@ -270,7 +279,7 @@ func (parser *Parser) ParseTarget() *Ast {
 			target = NewAstWithToken(AstKindTarget, parser.current)
 			target.AppendChild(parser.ParseClosed())
 		default: 
-			parser.Panicf("Malformed setter: %s", parser.current.String())
+			parser.Panicf("Malformed setter.")
 			return nil
 	} 	
 	
@@ -302,7 +311,7 @@ func (parser *Parser) ParseOrigin() *Ast {
 			target = NewAstWithToken(AstKindTarget, parser.current)
 			target.AppendChild(parser.ParseClosed())
 		default: 
-			parser.Panicf("Malformed getter: %s", parser.current.String())
+			parser.Panicf("Malformed getter")
 			return nil
 	} 	
 	
@@ -347,7 +356,7 @@ func (parser *Parser) ParseClosed() *Ast {
 		case parser.NextIs(TokenKindOpenParen): return parser.ParseParenthesis()
 		case parser.NextIs(TokenKindOpenList): return parser.ParseList()
 		default:
-			parser.Panicf("Syntax error in closed, unexpected: %s", parser.current.String())
+			parser.Panicf("Syntax error in closed, expected {, (, [")
 			return nil
 	}
 }
@@ -361,7 +370,7 @@ func (parser *Parser) ParseExpression() *Ast {
 		case parser.NextIsGet(): return parser.ParseGet()
 		case parser.NextIsValue(): return parser.ParseValue()
 		default: 
-			parser.Panicf("Syntax error in expression, unexpected: %s", parser.current.String())
+			parser.Panicf("Syntax error in expression, expected word, $, =, value")
 			return nil
     }
 }
@@ -373,8 +382,8 @@ func (parser *Parser) ParseExpressionStatement() *Ast {
         return NewAstNone()
     }
     
-    // Expression statements must end on EOX
-    if eox := parser.Require(TokenKindEOX); eox.IsError() {
+    // Expression statements must end on EOX or EOF
+    if eox := parser.Require(TokenKindEOX, TokenKindEOF); eox.IsError() {
 		return parser.NewAstError("expected end of statement")
 	}
     
@@ -384,7 +393,7 @@ func (parser *Parser) ParseExpressionStatement() *Ast {
 
 func (parser *Parser) ParseEmptyStatement() *Ast {
     parser.LogDebug("ParseEmptyStatement: %s\n", parser.current.String())
-	if eox := parser.Require(TokenKindEOX); eox.IsError() {
+	if eox := parser.Require(TokenKindEOX, TokenKindEOF); eox.IsError() {
 		return parser.NewAstError("expected end of statement")
 	}
     return NewAstWithToken(AstKindStatement, parser.current)
@@ -442,7 +451,6 @@ func (parser Parser) NextIsErrorSkipped() bool {
     TokenKindEOX, TokenKindEOF)
 }
 
-
 func (parser Parser) NextIsEOX() bool {
     return parser.NextIs(TokenKindEOX)
 }
@@ -451,7 +459,6 @@ func (parser Parser) NextIsEOF() bool {
     return parser.NextIs(TokenKindEOF)
 }
 
-
 func (parser Parser) NextIsExpression() bool {
     return parser.NextIs(TokenKindWord,
                     TokenKindGet,
@@ -476,8 +483,8 @@ func (parser *Parser) ParseStatement() *Ast {
         case parser.NextIsExpression(): return parser.ParseExpressionStatement()
         case parser.NextIsEOX(): return parser.ParseEmptyStatement()
         default:
-        parser.Panicf("Unexpected token in statement")
-        return parser.NewAstError("Unexpected token in statement")
+        parser.Panicf("Expected closed, expression, or EOX in statement")
+        return parser.NewAstError("Expected closed, expression, or EOX in statement")
     }
 }
 
@@ -509,14 +516,18 @@ func (parser *Parser) ParseProgram() *Ast {
 	return NewAst(AstKindProgram, nil, children, NoToken())
 }
 
-func (parser *Parser) Parse() *Ast {
-	defer func() {		
+func (parser *Parser) Parse() (ast *Ast) {
+	defer func() {
 		if err := recover() ; err != nil {
-			fmt.Printf("Parse error, recovered: %s %s\n", err, parser.current.String())
+			if perr, ok := err.(ParserError) ; ok{ 
+				ast = parser.NewAstError("Parse error, recovered: %s\n", perr)
+			} else {
+				panic(err)
+			}
 		}
 	} ()
 	parser.Advance()
-	ast := parser.ParseProgram()
+	ast = parser.ParseProgram()
 	return ast
 }
 

+ 6 - 5
parser_test.go

@@ -11,7 +11,7 @@ func HelperFailOnErrors(ast * Ast, expected int, test *testing.T) {
 		return
 	}	
 	if ast.IsNone() {
-		test.Errorf("Parse failed, %d parse errors expected", expected)
+		test.Logf("Parse failed, %d parse errors expected", expected)
 	}
 	errors := ast.Errors()
 	if len(errors) != expected {
@@ -25,12 +25,13 @@ func HelperFailOnErrors(ast * Ast, expected int, test *testing.T) {
 
 func HelperParseAndFailOnErrors(prog string, expected int,
 	parsefunc func(*Parser) *Ast, test *testing.T) {
-		defer func(){
+	/*	defer func(){
 			err := recover()
 			if err != nil {
 				test.Errorf("Parse error: %s", err)
 			}
 		}()
+	*/
 	
 	parser := NewParserFromString(prog)
 	parser.SetLogger(&testLogger{"", 0, test})
@@ -38,11 +39,11 @@ func HelperParseAndFailOnErrors(prog string, expected int,
 	HelperFailOnErrors(ast, expected, test)
 	if ast != nil { 
 		test.Logf("AST OK")
-		// ast.Display()
+		test.Logf("\nAst: %s\n",  ast.Dump())		
 	}
 }
 
-func TestParser(test *testing.T) {
+func TestParser1(test *testing.T) {
 	com := `puts "hello" 
 	say ( add 5 10 ) .`
 	parser := NewParserFromString(com)
@@ -89,7 +90,7 @@ func TestParseDesignFile(test *testing.T) {
     ast := parser.Parse()
     if ast != nil { 
 		test.Logf("Ast OK.")
-		// ast.Display()
+		test.Logf("\nAst: %s\n",  ast.Dump())
 	}
     
 }

+ 6 - 3
token.go

@@ -11,6 +11,10 @@ type Position struct {
 	Column   int
 }
 
+func (p Position) String() string {
+	return fmt.Sprintf("%s:%d:%d", p.FileName, p.Line, p.Column)
+}
+
 /* Token Kind. Uses a rune to easily handle single character tokens. */
 type TokenKind rune
 
@@ -78,11 +82,10 @@ type Token struct {
 
 func (token Token) String() string {
 	if token.Value == nil {
-		return fmt.Sprintf("<%s:nil:%v>", token.TokenKind.String(), token.Position)
+		return fmt.Sprintf("%s:%s:nil", token.Position.String(), token.TokenKind.String())
 
 	}
-	return fmt.Sprintf("<%s:%q:%v>", token.TokenKind.String(),
-		token.Value.String(), token.Position)
+	return fmt.Sprintf("%s:%s:%v", token.Position.String(), token.TokenKind.String(), token.Value)
 }
 
 func (token Token) Error() string {

+ 19 - 0
value.go

@@ -14,11 +14,14 @@ type StringValue string
 type BoolValue bool
 type WordValue string
 type TypeValue string
+
 type ErrorValue struct {
 	error
 }
+
 type EmptyValue struct {
 }
+
 type ListValue struct {
 	List []Value
 }
@@ -113,6 +116,22 @@ func (list *ListValue) Append(elements ...Value) {
 	list.List = append(list.List, elements...)
 }
 
+func (list *ListValue) AppendList(toAppend ListValue) {
+	list.List = append(list.List, toAppend.List...)
+}
+
+func (list *ListValue) Index(i int) Value {
+	if i >= len(list.List) {
+		return NilValue
+	}
+	return list.List[i]
+}
+
+
+func (list *ListValue) First() Value {
+	return list.Index(0)
+}
+
 func EmptyListValue() ListValue {
 	return ListValue{make([]Value, 0)}
 }

+ 48 - 14
vm.go

@@ -4,15 +4,15 @@ package muesli
 // import "fmt"
 
 // Handler function
-type Handler func(vm *VM, arguments ...Value) []Value
+type Handler func(vm *VM, arguments ...Value) ListValue
 
-func (handler *Handler) Call(vm *VM, arguments ...Value) []Value {
+func (handler *Handler) Call(vm *VM, arguments ...Value) ListValue {
 	return (*handler)(vm, arguments...)
 }
 
 // A callable Value must implement the Caller interface
 type Caller interface {
-	Call(vm *VM, arguments ...Value) []Value
+	Call(vm *VM, arguments ...Value) ListValue
 }
 
 // Callable value types
@@ -45,7 +45,7 @@ func NewBuiltinValue(name string, handler Handler) BuiltinValue {
 	return result
 }
 
-func (builtin *BuiltinValue) Call(vm *VM, arguments ...Value) []Value {
+func (builtin *BuiltinValue) Call(vm *VM, arguments ...Value) Value {
 	return vm.CallBuiltin(builtin.Handler, arguments...)
 }
 
@@ -62,7 +62,7 @@ func NewDefinedValue(name string, definition *Ast) DefinedValue {
 	return result
 }
 
-func (defined *DefinedValue) Call(vm *VM, arguments ...Value) []Value {
+func (defined *DefinedValue) Call(vm *VM, arguments ...Value) Value {
 	return vm.CallDefined(defined.Definition, arguments...)
 }
 
@@ -115,6 +115,13 @@ type CoverValue struct {
 	Overloads map[Signature]Overload
 }
 
+func NewCoverValue(name string) CoverValue {
+	result := CoverValue{}
+	result.Name = name
+	result.Overloads = make(map[Signature]Overload)
+	return result
+}
+
 func (cover *CoverValue) Call(vm *VM, arguments ...Value) ListValue {
 	signature := CalculateSignature(arguments...)
 	if overload, ok := cover.Overloads[signature]; ok {
@@ -191,16 +198,21 @@ func NewFrame(parent *Frame) *Frame {
 	return &Frame{parent, EmptyValueArray(), EmptyValueArray(), false}
 }
 
+type Tracer interface {
+	Trace(vm VM, ast Ast, val ListValue) bool
+}
+
 // Virtual machine
 type VM struct {
 	TopScope *Scope // Top level scope
 	TopFrame *Frame // Top level scope
 	*Scope          // Current Scope
 	*Frame          // Current frame
+	Tracer			// Tracer to emit tracing info to, could be used for logging or debugging
 }
 
 func NewVM() *VM {
-	vm := &VM{NewScope(nil), NewFrame(nil), nil, nil}
+	vm := &VM{NewScope(nil), NewFrame(nil), nil, nil, nil}
 	vm.Scope = vm.TopScope
 	vm.Frame = vm.TopFrame
 	return vm
@@ -236,23 +248,31 @@ func (vm *VM) PopScope() *Scope {
 	return nil
 }
 
-func (vm *VM) CallDefined(ast *Ast, arguments ...Value) []Value {
-	return ast.Run(vm, arguments)
+func (vm *VM) CallDefined(ast *Ast, arguments ...Value) Value {
+	arr := ast.Run(vm, NewListValue(arguments...))
+	return arr
 }
 
-func (vm *VM) CallBuiltin(handler Handler, arguments ...Value) []Value {
+func (vm *VM) CallBuiltin(handler Handler, arguments ...Value) Value {
 	return handler.Call(vm, arguments...)
 }
 
-func (vm *VM) CallNamed(name string, arguments ...Value) []Value {
+func (vm *VM) CallCover(cover CoverValue, arguments ...Value) Value {
+	return cover.Call(vm, arguments...)
+}
+
+
+func (vm *VM) CallNamed(name string, arguments ...Value) Value {
 	value := vm.Lookup(name)
 	switch toCall := value.(type) {
 	case BuiltinValue:
 		return vm.CallBuiltin(toCall.Handler, arguments...)
 	case DefinedValue:
 		return vm.CallDefined(toCall.Definition, arguments...)
+	case CoverValue:
+		return vm.CallCover(toCall, arguments...)
 	default:
-		return NewValueArray(NewErrorValuef("Cannot call %s: %v", name, value))
+		return NewListValue(NewErrorValuef("Cannot call %s: %v", name, value))
 	}
 }
 
@@ -267,6 +287,11 @@ func (vm *VM) Register(name string, value Value) Value {
 	return vm.Scope.Register(name, value)
 }
 
+func (vm *VM) RegisterCover(name string) Value {
+	value := NewCoverValue(name)
+	return vm.Register(name, value)
+}
+
 func (vm *VM) RegisterBuiltin(name string, handler Handler) Value {
 	value := NewBuiltinValue(name, handler)
 	return vm.Register(name, value)
@@ -281,15 +306,24 @@ func (vm *VM) Fail() {
 	vm.Frame.failed = true
 }
 
-func (vm *VM) RunChildren(ast Ast, args ...Value) []Value {
-	result := NewValueArray()
+func (vm *VM) RunChildren(ast Ast, args ListValue) Value {
+	result := NewListValue()
 	for _, child := range ast.Children() {
 		val := child.Run(vm, args)
-		result = append(result, val...)
+		reslist, isList := val.(ListValue)
+		if isList {
+			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) RunProgram(ast *BasicAst) ListValue {

+ 12 - 10
vm_test.go

@@ -7,9 +7,9 @@ import (
 
 func TestVm1(test *testing.T) {
 	vm := NewVM()
-	bi := vm.RegisterBuiltin("foo", func(vm *VM, args ...Value) []Value {
+	bi := vm.RegisterBuiltin("foo", func(vm *VM, args ...Value) ListValue {
 		fmt.Printf("I am foo. See me foo?")
-		return EmptyValueArray()
+		return NewListValue()
 	})
 
 	if vm == nil {
@@ -32,9 +32,9 @@ func TestVm1(test *testing.T) {
 
 func ExampleVm1() {
 	vm := NewVM()
-	vm.RegisterBuiltin("foo", func(vm *VM, args ...Value) []Value {
+	vm.RegisterBuiltin("foo", func(vm *VM, args ...Value) ListValue {
 		fmt.Printf("I am foo. See me foo?")
-		return EmptyValueArray()
+		return NewListValue()
 	})
 
 	foo := vm.Lookup("foo")
@@ -50,11 +50,11 @@ func ExampleVm1() {
 
 func ExampleVm2() {
 	vm := NewVM()
-	vm.RegisterBuiltin("foo", func(vm *VM, args ...Value) []Value {
+	vm.RegisterBuiltin("foo", func(vm *VM, args ...Value) ListValue {
 		var s string
 		From(args[0], &s)
 		fmt.Printf("I am foo. See me %s?", s)
-		return EmptyValueArray()
+		return NewListValue()
 	})
 
 	//Output: I am foo. See me bar?
@@ -64,7 +64,7 @@ func ExampleVm2() {
 
 func ExampleVm3() {
 	vm := NewVM()
-	vm.RegisterBuiltin("multi", func(vm *VM, args ...Value) []Value {
+	vm.RegisterBuiltin("multi", func(vm *VM, args ...Value) ListValue {
 		var one string
 		var two int64
 		err := ListFrom(args, &one, &two)
@@ -72,7 +72,7 @@ func ExampleVm3() {
 			fmt.Printf("Error: %s", err.Error())
 		}
 		fmt.Printf("I am multi. See me %s, %d?", one, two)
-		return EmptyValueArray()
+		return NewListValue()
 	})
 
 	//Output: I am multi. See me bar, 7?
@@ -82,7 +82,7 @@ func ExampleVm3() {
 
 func ExampleVm4() {
 	vm := NewVM()
-	vm.RegisterBuiltin("printf", func(vm *VM, args ...Value) []Value {
+	vm.RegisterBuiltin("printf", func(vm *VM, args ...Value) ListValue {
 		var form string
 		var rest = args[1:len(args)]
 		resri := ListFromList(rest)
@@ -92,10 +92,12 @@ func ExampleVm4() {
 		} else {
 			fmt.Printf(form, resri...)
 		}
-		return EmptyValueArray()
+		return NewListValue()
 	})
 
 	//Output: printf 7
 	vm.CallNamed("printf", ListTo("printf %d", 7)...)
 
 }
+
+