Browse Source

Improve the lexer and work on the parser.

Beoran 5 years ago
parent
commit
969734636f
12 changed files with 778 additions and 298 deletions
  1. 285 196
      ast.go
  2. 21 0
      ast_test.go
  3. 20 26
      design_muesli.muesli
  4. 74 8
      lexer.go
  5. 22 0
      lexer_test.go
  6. 7 0
      logger.go
  7. 46 45
      parser.go
  8. 20 5
      parser_test.go
  9. 2 0
      token.go
  10. 98 0
      value.go
  11. 82 18
      vm.go
  12. 101 0
      vm_test.go

+ 285 - 196
ast.go

@@ -6,196 +6,294 @@ import (
 	"strings"
 )
 
-/*
-type AstKind int
-
+type AstBasicMetaKind string
+
+type AstMetaKindNone AstBasicMetaKind
+type AstMetaKindProgram AstBasicMetaKind
+type AstMetaKindStatements AstBasicMetaKind
+type AstMetaKindStatement AstBasicMetaKind
+type AstMetaKindSet AstBasicMetaKind
+type AstMetaKindGet AstBasicMetaKind
+type AstMetaKindTarget AstBasicMetaKind
+type AstMetaKindCommand AstBasicMetaKind
+type AstMetaKindArguments AstBasicMetaKind
+type AstMetaKindArgument AstBasicMetaKind
+type AstMetaKindExpression AstBasicMetaKind
+type AstMetaKindBlock AstBasicMetaKind
+type AstMetaKindParenthesis AstBasicMetaKind
+type AstMetaKindList AstBasicMetaKind
+type AstMetaKindCapture AstBasicMetaKind
+type AstMetaKindWordValue AstBasicMetaKind
+type AstMetaKindWord AstBasicMetaKind
+type AstMetaKindType AstBasicMetaKind
+type AstMetaKindValue AstBasicMetaKind
+type AstMetaKindEnd AstBasicMetaKind
+type AstMetaKindError AstBasicMetaKind
+
+/** The actual types are defined as constants, the meta types are used to be able to have different behavior for them.*/
 const (
-	AstKindProgram = AstKind(iota)
-	AstKindStatements
-	AstKindStatement
-	AstKindSet
-	AstKindGet
-	AstKindTarget
-	AstKindCommand
-	AstKindArguments
-	AstKindArgument
-	AstKindExpression
-	AstKindBlock
-	AstKindParenthesis
-	AstKindList
-	AstKindCapture
-	AstKindWordValue
-	AstKindWord
-	AstKindType
-	AstKindValue
-	AstKindEnd
-	AstKindError
+	AstKindNone        = AstMetaKindNone("None")
+	AstKindProgram     = AstMetaKindProgram("Program")
+	AstKindStatements  = AstMetaKindStatements("Statements")
+	AstKindStatement   = AstMetaKindStatement("Statement")
+	AstKindSet         = AstMetaKindSet("Set")
+	AstKindGet         = AstMetaKindGet("Get")
+	AstKindTarget      = AstMetaKindTarget("Target")
+	AstKindCommand     = AstMetaKindCommand("Command")
+	AstKindArguments   = AstMetaKindArguments("Arguments")
+	AstKindArgument    = AstMetaKindArgument("Argument")
+	AstKindExpression  = AstMetaKindExpression("Expression")
+	AstKindBlock       = AstMetaKindBlock("Block")
+	AstKindParenthesis = AstMetaKindParenthesis("Parenthesis")
+	AstKindList        = AstMetaKindList("List")
+	AstKindCapture     = AstMetaKindCapture("Capture")
+	AstKindWordValue   = AstMetaKindWordValue("WordValue")
+	AstKindWord        = AstMetaKindWord("Word")
+	AstKindType        = AstMetaKindType("Type")
+	AstKindValue       = AstMetaKindValue("Value")
+	AstKindEnd         = AstMetaKindEnd("End")
+	AstKindError       = AstMetaKindError("Error")
 )
-*/
 
-/*
-func (BasicAst Ast) String() string {
-	switch astkind {
-	case AstKindProgram:
-		return "AstKindProgram"
-	case AstKindStatements:
-		return "AstKindStatements"
-	case AstKindStatement:
-		return "AstKindStatement"
-	case AstKindSet:
-		return "AstKindSet"
-	case AstKindGet:
-		return "AstKindGet"
-	case AstKindTarget:
-		return "AstKindTarget"
-	case AstKindCommand:
-		return "AstKindCommand"
-	case AstKindArguments:
-		return "AstKindArguments"
-	case AstKindArgument:
-		return "AstKindArgument"
-	case AstKindExpression:
-		return "AstKindExpression"
-	case AstKindBlock:
-		return "AstKindBlock"
-	case AstKindParenthesis:
-		return "AstKindParenthesis"
-	case AstKindList:
-		return "AstKindList"
-	case AstKindCapture:
-		return "AstKindCapture"
-	case AstKindWordValue:
-		return "AstKindWordValue"
-	case AstKindWord:
-		return "AstKindWord"
-	case AstKindType:
-		return "AstKindType"
-	case AstKindValue:
-		return "AstKindValue"
-	case AstKindEnd:
-		return "AstKindEnd"
-	case AstKindError:
-		return "AstKindError"
-	default:
-		return "Unknown AstKind"
+func (astkind AstBasicMetaKind) String() string {
+	return string(astkind)
+}
+
+func (astkind AstBasicMetaKind) Run(vm *VM, ast Ast, val []Value) []Value {
+	return EmptyValueArray()
+}
+
+func (astkind AstMetaKindNone) String() string        { return "AstNone       " }
+func (astkind AstMetaKindProgram) String() string     { return "AstProgram    " }
+func (astkind AstMetaKindStatements) String() string  { return "AstStatements " }
+func (astkind AstMetaKindStatement) String() string   { return "AstStatement  " }
+func (astkind AstMetaKindSet) String() string         { return "AstSet        " }
+func (astkind AstMetaKindGet) String() string         { return "AstGet        " }
+func (astkind AstMetaKindTarget) String() string      { return "AstTarget     " }
+func (astkind AstMetaKindCommand) String() string     { return "AstCommand    " }
+func (astkind AstMetaKindArguments) String() string   { return "AstArguments  " }
+func (astkind AstMetaKindArgument) String() string    { return "AstArgument   " }
+func (astkind AstMetaKindExpression) String() string  { return "AstExpression " }
+func (astkind AstMetaKindBlock) String() string       { return "AstBlock      " }
+func (astkind AstMetaKindParenthesis) String() string { return "AstParenthesis" }
+func (astkind AstMetaKindList) String() string        { return "AstList       " }
+func (astkind AstMetaKindCapture) String() string     { return "AstCapture    " }
+func (astkind AstMetaKindWordValue) String() string   { return "AstWordValue  " }
+func (astkind AstMetaKindWord) String() string        { return "AstWord       " }
+func (astkind AstMetaKindType) String() string        { return "AstType       " }
+func (astkind AstMetaKindValue) String() string       { return "AstValue      " }
+func (astkind AstMetaKindEnd) String() string         { return "AstEnd        " }
+func (astkind AstMetaKindError) String() string       { return "AstError      " }
+
+func (astkind AstMetaKindNone) Run(vm *VM, ast Ast, val []Value) []Value { return EmptyValueArray() }
+
+func (astkind AstMetaKindProgram) Run(vm *VM, ast Ast, val []Value) []Value {
+	res := EmptyValueArray()
+	for _, child := range ast.Children() {
+		res = append(res, child.Run(vm, val)...)
 	}
+	return res
 }
-*/
 
-type Ast interface {
-	Parent() Ast
-	Children() []Ast
+func (astkind AstMetaKindStatements) Run(vm *VM, ast Ast, val []Value) []Value {
+	return EmptyValueArray()
+}
+func (astkind AstMetaKindStatement) 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 []Value) []Value {
+	return EmptyValueArray()
+}
+func (astkind AstMetaKindArguments) Run(vm *VM, ast Ast, val []Value) []Value {
+	return EmptyValueArray()
+}
+func (astkind AstMetaKindArgument) Run(vm *VM, ast Ast, val []Value) []Value {
+	return EmptyValueArray()
+}
+func (astkind AstMetaKindExpression) Run(vm *VM, ast Ast, val []Value) []Value {
+	return EmptyValueArray()
+}
+func (astkind AstMetaKindBlock) Run(vm *VM, ast Ast, val []Value) []Value {
+	return EmptyValueArray()
+}
+func (astkind AstMetaKindParenthesis) Run(vm *VM, ast Ast, val []Value) []Value {
+	return EmptyValueArray()
+}
+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 AstMetaKindWordValue) Run(vm *VM, ast Ast, val []Value) []Value {
+	return EmptyValueArray()
+}
+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 AstMetaKindEnd) Run(vm *VM, ast Ast, val []Value) []Value { return EmptyValueArray() }
+func (astkind AstMetaKindError) Run(vm *VM, ast Ast, val []Value) []Value {
+	return EmptyValueArray()
+}
 
-	Run(vm *VM, val ListValue) ListValue
+type AstKind interface {
 	String() string
-	Token() Token
-	/* AppendChild(child Ast) Ast
-	NewChild(kind AstKind, token Token) Ast
-	*/
+	Run(vm *VM, ast Ast, val []Value) []Value
+}
 
-	/* Make(parent Ast, token Token) Ast */
+/*
+func (Ast Ast) String() string {
+	switch astkind {
+	case AstMetaKindProgram:
+		return "AstMetaKindProgram"
+	case AstMetaKindStatements:
+		return "AstMetaKindStatements"
+	case AstMetaKindStatement:
+		return "AstMetaKindStatement"
+	case AstMetaKindSet:
+		return "AstMetaKindSet"
+	case AstMetaKindGet:
+		return "AstMetaKindGet"
+	case AstMetaKindTarget:
+		return "AstMetaKindTarget"
+	case AstMetaKindCommand:
+		return "AstMetaKindCommand"
+	case AstMetaKindArguments:
+		return "AstMetaKindArguments"
+	case AstMetaKindArgument:
+		return "AstMetaKindArgument"
+	case AstMetaKindExpression:
+		return "AstMetaKindExpression"
+	case AstMetaKindBlock:
+		return "AstMetaKindBlock"
+	case AstMetaKindParenthesis:
+		return "AstMetaKindParenthesis"
+	case AstMetaKindList:
+		return "AstMetaKindList"
+	case AstMetaKindCapture:
+		return "AstMetaKindCapture"
+	case AstMetaKindWordValue:
+		return "AstMetaKindWordValue"
+	case AstMetaKindWord:
+		return "AstMetaKindWord"
+	case AstMetaKindType:
+		return "AstMetaKindType"
+	case AstMetaKindValue:
+		return "AstMetaKindValue"
+	case AstMetaKindEnd:
+		return "AstMetaKindEnd"
+	case AstMetaKindError:
+		return "AstMetaKindError"
+	default:
+		return "Unknown AstMetaKind"
+	}
 }
+*/
 
 /*
 func AstAppendChild(parent Ast, child Ast) Ast {
-	basicParent := parent.(*BasicAst)
+	basicParent := parent.(*Ast)
 	return basicParent.AppendChild(child)
 }
 
-func AstNewChild(parent Ast, kind AstKind, token Token) Ast {
-	basicParent := parent.(*BasicAst)
+func AstNewChild(parent Ast, kind AstMetaKind, token Token) Ast {
+	basicParent := parent.(*Ast)
 	return basicParent.NewChild(kind, token)
 }
 */
 
 /* AST node kind */
-type BasicAst struct {
-	parent   Ast
+type Ast struct {
+	AstKind
+	parent   *Ast
 	children []Ast
 	token    Token
 }
 
-var _ Ast = &BasicAst{}
-
-func NewAst(kind AstKind, parent Ast, children []Ast, token Token) Ast {
-	ast := kind(parent, children, token)
-	return ast
+func NewAst(kind AstKind, parent *Ast, children []Ast, token Token) Ast {
+	return Ast{kind, parent, children, token}
 }
 
-/*
-func (ast *BasicAst) AppendChild(child Ast) Ast {
+func (ast *Ast) AppendChild(child Ast) Ast {
 	ast.children = append(ast.children, child)
 	return child
 }
 
-func (ast *BasicAst) NewChild(kind AstKind, token Token) Ast {
-	child := NewAst(kind, ast, token)
+func (ast *Ast) NewChild(kind AstKind, token Token) Ast {
+	child := NewAst(kind, ast, make([]Ast, 0), token)
 	ast.AppendChild(child)
 	return child
 }
-*/
 
-func (ast BasicAst) IsError() bool {
-	return false
+func (ast Ast) IsKind(astkind AstKind) bool {
+	return ast.AstKind == astkind
+}
+
+func (ast Ast) IsError() bool {
+	return ast.AstKind == AstKindError
 }
 
-func (ast AstError) IsError() bool {
-	return true
+func (ast Ast) IsNone() bool {
+	return ast.AstKind == AstKindNone
 }
 
-func (ast BasicAst) Token() Token {
+func (ast Ast) Token() Token {
 	return ast.token
 }
 
-func (ast BasicAst) Parent() Ast {
+func (ast Ast) Parent() *Ast {
 	return ast.parent
 }
 
-func (ast BasicAst) Children() []Ast {
+func (ast Ast) Children() []Ast {
 	return ast.children
 }
 
-func (ast *BasicAst) SetParent(parent Ast) {
+func (ast Ast) Kind() AstKind {
+	return ast.AstKind
+}
+
+func (ast *Ast) SetParent(parent *Ast) {
 	ast.parent = parent
 }
 
-func (ast BasicAst) Child(index int) Ast {
+func (ast Ast) Child(index int) *Ast {
 	count := ast.CountChildren()
 	if index < 0 || index > count {
 		return nil
 	}
-	return ast.children[index]
+	return &ast.children[index]
 }
 
-func (ast BasicAst) Run(vm *VM, val ListValue) ListValue {
-	panic("Please implement Run for this node.")
-	return ListValue{}
+func (ast Ast) Run(vm *VM, val []Value) []Value {
+	return ast.AstKind.Run(vm, ast, val)
 }
 
-func (ast *BasicAst) Walk(walker func(node Ast) Ast) Ast {
+func (ast *Ast) Walk(walker func(node *Ast) *Ast) *Ast {
 	if found := walker(ast); found != nil {
 		return found
 	}
 	for _, child := range ast.children {
-		if found := child.(*BasicAst).Walk(walker); found != nil {
+		if found := child.Walk(walker); found != nil {
 			return found
 		}
 	}
 	return nil
 }
 
-func (ast BasicAst) String() string {
-	if ast.Token == nil {
-		return fmt.Sprintf("BasicAst %s nil", ast.token.String())
-	}
-	return fmt.Sprintf("BasicAst %v", ast.token.String())
+func (ast Ast) String() string {
+	return fmt.Sprintf("Ast %s: %s", ast.AstKind.String(), ast.token.String())
 }
 
-func (ast BasicAst) Display() {
-	ast.Walk(func(node Ast) Ast {
-		bast := node.(*BasicAst)
-		depth := bast.Depth()
-		fmt.Printf(strings.Repeat("--", depth))
+func (ast Ast) Display() {
+	ast.Walk(func(node *Ast) *Ast {
+		depth := ast.Depth()
+		fmt.Printf("%s", strings.Repeat("--", depth))
 		if node != nil {
 			fmt.Printf("Ast: %s\n", node.String())
 		} else {
@@ -205,7 +303,7 @@ func (ast BasicAst) Display() {
 	})
 }
 
-func (ast BasicAst) Depth() int {
+func (ast Ast) Depth() int {
 	var depth int = 0
 	parent := ast.parent
 	for parent != nil {
@@ -215,18 +313,17 @@ func (ast BasicAst) Depth() int {
 	return depth
 }
 
-func (ast BasicAst) CountChildren() int {
+func (ast Ast) CountChildren() int {
 	return len(ast.children)
 }
 
 func AstIsError(ast Ast) bool {
-	_, isError := ast.(*AstError)
-	return isError
+	return ast.IsError()
 }
 
-func (ast BasicAst) Errors() []Ast {
-	res := make([]Ast, 0)
-	ast.Walk(func(node Ast) Ast {
+func (ast Ast) Errors() []*Ast {
+	res := make([]*Ast, 0)
+	ast.Walk(func(node *Ast) *Ast {
 		if node != nil && ast.IsError() {
 			res = append(res, node)
 		}
@@ -239,60 +336,51 @@ func EmptyAstArray() []Ast {
 	return make([]Ast, 0)
 }
 
-type AstProgram struct{ BasicAst }
-type AstStatements struct{ BasicAst }
-type AstStatement struct{ BasicAst }
-type AstSet struct{ BasicAst }
-type AstGet struct{ BasicAst }
-type AstTarget struct{ BasicAst }
-type AstCommand struct{ BasicAst }
-type AstArguments struct{ BasicAst }
-type AstArgument struct{ BasicAst }
-type AstExpression struct{ BasicAst }
-type AstBlock struct{ BasicAst }
-type AstParenthesis struct{ BasicAst }
-type AstList struct{ BasicAst }
-type AstCapture struct{ BasicAst }
-type AstWordValue struct{ BasicAst }
-type AstWord struct{ BasicAst }
-type AstType struct{ BasicAst }
-type AstValue struct{ BasicAst }
-type AstEnd struct{ BasicAst }
-type AstError struct{ BasicAst }
-
-func (ast AstProgram) String() string     { return "AstProgram    " }
-func (ast AstStatements) String() string  { return "AstStatements " }
-func (ast AstStatement) String() string   { return "AstStatement  " }
-func (ast AstSet) String() string         { return "AstSet        " }
-func (ast AstGet) String() string         { return "AstGet        " }
-func (ast AstTarget) String() string      { return "AstTarget     " }
-func (ast AstCommand) String() string     { return "AstCommand    " }
-func (ast AstArguments) String() string   { return "AstArguments  " }
-func (ast AstArgument) String() string    { return "AstArgument   " }
-func (ast AstExpression) String() string  { return "AstExpression " }
-func (ast AstBlock) String() string       { return "AstBlock      " }
-func (ast AstParenthesis) String() string { return "AstParenthesis" }
-func (ast AstList) String() string        { return "AstList       " }
-func (ast AstCapture) String() string     { return "AstCapture    " }
-func (ast AstWordValue) String() string   { return "AstWordValue  " }
-func (ast AstWord) String() string        { return "AstWord       " }
-func (ast AstType) String() string        { return "AstType       " }
-func (ast AstValue) String() string       { return "AstValue      " }
-func (ast AstEnd) String() string         { return "AstEnd        " }
-func (ast AstError) String() string       { return "AstError      " }
-
-var _ Ast = AstProgram{}
-
-func NewBasicAst(parent Ast, children []Ast, token Token) BasicAst {
-	return BasicAst{parent, children, token}
+func NewEmptyAst(astkind AstKind) Ast {
+	return NewAst(astkind, nil, EmptyAstArray(), NoToken())
+}
+
+func NewAstNone() Ast {
+	return NewEmptyAst(AstKindNone)
 }
 
+func NewAstWithToken(astkind AstKind, token Token) Ast {
+	return NewAst(astkind, nil, EmptyAstArray(), token)
+}
+
+/*
+type AstProgram struct{ Ast }
+type AstStatements struct{ Ast }
+type AstStatement struct{ Ast }
+type AstSet struct{ Ast }
+type AstGet struct{ Ast }
+type AstTarget struct{ Ast }
+type AstCommand struct{ Ast }
+type AstArguments struct{ Ast }
+type AstArgument struct{ Ast }
+type AstExpression struct{ Ast }
+type AstBlock struct{ Ast }
+type AstParenthesis struct{ Ast }
+type AstList struct{ Ast }
+type AstCapture struct{ Ast }
+type AstWordValue struct{ Ast }
+type AstWord struct{ Ast }
+type AstType struct{ Ast }
+type AstValue struct{ Ast }
+type AstEnd struct{ Ast }
+type AstError struct{ Ast }
+*/
+
+var _ Ast = Ast{}
+
 /* The kind of an AST is also it's constructor function. This is so deep I'm almost
 getting scared. :) */
 // The type is defined as a constructor
-type AstKind func(parent Ast, children []Ast, token Token) Ast
 
-type AstKind2 interface {
+/*
+type AstMetaKind func(parent Ast, children []Ast, token Token) Ast
+
+type AstMetaKind2 interface {
 	New(parent Ast, children []Ast, token Token) Ast
 }
 
@@ -306,66 +394,67 @@ func NewAstProgram(parent Ast, children []Ast, token Token) Ast {
 	return AstProgram{NewBasicAst(parent, children, token)}
 }
 
-var AstKindBasic = AstKind(func(parent Ast, children []Ast, token Token) Ast { return NewBasicAst(parent, children, token) })
+var AstMetaKindBasic = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast { return NewBasicAst(parent, children, token) })
 
-var AstKindProgram = AstKind(NewAstProgram)
-var AstKindProgram2 = AstKind2(AstTypeProgramImp{})
+var AstMetaKindProgram = AstMetaKind(NewAstProgram)
+var AstMetaKindProgram2 = AstMetaKind2(AstTypeProgramImp{})
 
-var AstKindStatements = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindStatements = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstStatements{NewBasicAst(parent, children, token)}
 })
 
-var AstKindStatement = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindStatement = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstStatement{NewBasicAst(parent, children, token)}
 })
-var AstKindSet = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindSet = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstSet{NewBasicAst(parent, children, token)}
 })
-var AstKindGet = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindGet = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstGet{NewBasicAst(parent, children, token)}
 })
-var AstKindTarget = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindTarget = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstTarget{NewBasicAst(parent, children, token)}
 })
-var AstKindCommand = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindCommand = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstCommand{NewBasicAst(parent, children, token)}
 })
-var AstKindArguments = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindArguments = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstArguments{NewBasicAst(parent, children, token)}
 })
-var AstKindArgument = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindArgument = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstArgument{NewBasicAst(parent, children, token)}
 })
-var AstKindExpression = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindExpression = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstExpression{NewBasicAst(parent, children, token)}
 })
-var AstKindBlock = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindBlock = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstBlock{NewBasicAst(parent, children, token)}
 })
-var AstKindParenthesis = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindParenthesis = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstParenthesis{NewBasicAst(parent, children, token)}
 })
-var AstKindList = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindList = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstList{NewBasicAst(parent, children, token)}
 })
-var AstKindCapture = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindCapture = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstCapture{NewBasicAst(parent, children, token)}
 })
-var AstKindWordValue = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindWordValue = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstWordValue{NewBasicAst(parent, children, token)}
 })
-var AstKindWord = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindWord = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstWord{NewBasicAst(parent, children, token)}
 })
-var AstKindType = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindType = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstType{NewBasicAst(parent, children, token)}
 })
-var AstKindValue = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindValue = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstValue{NewBasicAst(parent, children, token)}
 })
-var AstKindEnd = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindEnd = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstEnd{NewBasicAst(parent, children, token)}
 })
-var AstKindError = AstKind(func(parent Ast, children []Ast, token Token) Ast {
+var AstMetaKindError = AstMetaKind(func(parent Ast, children []Ast, token Token) Ast {
 	return &AstError{NewBasicAst(parent, children, token)}
 })
+*/

+ 21 - 0
ast_test.go

@@ -0,0 +1,21 @@
+package muesli
+
+import "testing"
+
+func TestAstKind(test *testing.T) {
+	var kind AstKind = AstKindError
+	errast := NewEmptyAst(AstKindError)
+	astnone := NewAstNone()
+
+	if kind != AstKindError {
+		test.Errorf("Error is not error: %v", kind)
+	}
+
+	if !errast.IsError() {
+		test.Errorf("Error is not error: %v", errast)
+	}
+
+	if !astnone.IsNone() {
+		test.Errorf("None is not none: %v", astnone)
+	}
+}

+ 20 - 26
design_muesli.muesli

@@ -1,4 +1,4 @@
-# Muesli is a Multi Use Embeddable Scripting Language Indeed. 
+# Muesli is a Multi Use Embeddable Scripting Language Interpreter. 
 # It is a scripting language with a TCL or shell like syntax, but somewhat 
 # OOP and LISP like semantics.
 # First it will be an embeddable scripting language implemented in Go.
@@ -8,8 +8,7 @@
 # line. MUESLI does not execute comments but they are collected 
 # for documentation purposes. More on that topic later
 # Muesli is a line based language.
-# A newline preceded by a \ is ignored, even after a comment so \
-this is still comment
+#
 # Muesli consists of newline separated statements, however, a newline 
 # after { or the do keyword is ignored and does not count as a separator.
 #{ This is a block comment, it nests 
@@ -21,40 +20,35 @@ but the {} pairs must match.
 
 # ... 
 # Muesli supports integer constants with type Int
-1
-2
-378
-+108
--878
-
-# ... Character constants with escapes with type Rune
-# This may also be unicode code points if above ascii range.
-
-'a'
+p 1
+p 2
+p 378
+p +108
+p -878
 
 # It also supports multi line string constants with escapes, with type String
-"Hello world\"
+p "Hello world\"
 " 
 
 # and multi line strings without escapes
-`
+p `
 "Pop" goes the 
 weasel's tail.
 `
 
-# And booleans constants of type Bool
-!true !false
+# Built in identfiers for type Bool or nil
+p !true !false !nil
 
 # And simple floating point constants, but no exponential notation, with type Float
-+0.5
--7.000005
+p +0.5
+p -7.000005
 
 # Lists can be created between [ ] and may be heterogenous or homogenous. 
 # The [ ] must be space separated. 
 # The type is Any[] if heterogenous,  
-[ foo "bar" ] 
-# The type is Int@  below
-[ 1 2 3 ] 
+p [ foo "bar" ] 
+# The type is Int[]  below
+p [ 1 2 3 ] 
 
 
 # A sequence of a lower case letter followed by anything that is not whitespace.
@@ -91,11 +85,10 @@ type Door ( object locked Bool keys Item[] )
 # They can have many arguments and many results.
 to open [door Door key Item]  Bool {
     if (contains (member door key) key) {
-        set 
+        set (member door open) true
     }
 }
 
-
 # Unlike TCL, MUESLI values are typed, and commands
 # can be overloaded based on the types the types of their arguments.
 # Types are much like words, but they begin with an upper case letter, up to the
@@ -139,8 +132,9 @@ if (less a 10) {
 # That's all there is to the syntax. Apart from the built in commands, 
 # the semantics are up to you to implement as 
 # embedded commands.
+# Do note that MUESLI uses dynamic scoping for ease of implementation
 
-/*
+#{
 
 BLOCK
 PUSHS "More"
@@ -159,5 +153,5 @@ CALL if
 
 
 
-*/
+}
 

+ 74 - 8
lexer.go

@@ -63,8 +63,34 @@ func (lexer *Lexer) MakeFloatToken() Token {
 }
 
 func (lexer *Lexer) MakeBooleanToken(b bool) Token {
-	lexer.ClearBuffer()
-	return NewToken(TokenKindBoolean, BoolValue(b), lexer.Position)
+    lexer.ClearBuffer()
+    if b { 
+        return NewToken(TokenKindBoolean, TrueValue, lexer.Position)
+    } else { 
+        return NewToken(TokenKindBoolean, FalseValue, lexer.Position)
+    }
+}
+
+func (lexer *Lexer) MakeNilToken() Token {
+    lexer.ClearBuffer()
+    return NewToken(TokenKindNil, NilValue, lexer.Position)
+}
+
+
+
+func (lexer *Lexer) MakeBuiltinToken() Token {
+	var sbuffer = string(lexer.buffer)
+    lexer.ClearBuffer()
+	if sbuffer == "true" {
+    	lexer.ClearBuffer()
+        return NewToken(TokenKindBoolean, TrueValue, lexer.Position)
+    } else if sbuffer == "false" {
+        return NewToken(TokenKindBoolean, FalseValue, lexer.Position)
+    } else if sbuffer == "nil" {
+        return NewToken(TokenKindNil, NilValue, lexer.Position)
+    } else {
+        return lexer.MakeErrorfToken("Not a builtin: %s", sbuffer)
+    }
 }
 
 func (lexer *Lexer) MakeStringValueToken(kind TokenKind) Token {
@@ -88,8 +114,10 @@ func (lexer *Lexer) MakeToken(kind TokenKind) Token {
 		fallthrough
 	case TokenKindWord:
 		return lexer.MakeStringValueToken(kind)
+    case TokenKindNil:
+        fallthrough
 	case TokenKindBoolean:
-		fallthrough
+		return lexer.MakeBuiltinToken()
 	case TokenKindGet:
 		fallthrough
 	case TokenKindSet:
@@ -296,9 +324,9 @@ func (lexer *Lexer) handleError(err error) Token {
 func (lexer *Lexer) LexNumber() Token {
 	isFloat := false
 
-	// skip any first -
+	// skip any first - or +
 	_, err := lexer.NextIf(func(r rune) bool {
-		return r == '-'
+		return r == '-' || r == '+'
 	})
 
 	_, err = lexer.NextWhile(func(r rune) bool {
@@ -482,6 +510,8 @@ func (lexer *Lexer) LexWordOrType(kind TokenKind) Token {
 		return lexer.MakeBooleanToken(true)
 	case "false":
 		return lexer.MakeBooleanToken(false)
+    case "nil":
+        return lexer.MakeNilToken()
 	default:
 	}
 
@@ -515,6 +545,26 @@ func (lexer *Lexer) LexSymbol() Token {
 	return lexer.MakeToken(TokenKindSymbol)
 }
 
+
+func (lexer *Lexer) LexBuiltin() Token {
+	var err error
+
+	_, err = lexer.Skip()
+	if err != nil {
+		return lexer.handleError(err)
+	}
+
+	_, err = lexer.NextWhile(func(r rune) bool {
+		return !unicode.IsSpace(r)
+	})
+
+	if err != nil {
+		return lexer.handleError(err)
+	}
+    
+	return lexer.MakeBuiltinToken()
+}
+
 func (lexer *Lexer) skipSpaceAndCommentAndPeek() (rune, error) {
 	r, err := lexer.Peek()
 	if err != nil {
@@ -548,7 +598,7 @@ func (lexer *Lexer) lex() Token {
 		return lexer.handleError(err)
 	}
 
-	if unicode.IsDigit(r) || r == '-' {
+	if unicode.IsDigit(r) || r == '-' || r == '+' {
 		return lexer.LexNumber()
 	}
 
@@ -564,6 +614,10 @@ func (lexer *Lexer) lex() Token {
 	if r == '`' {
 		return lexer.LexLongString()
 	}
+    
+    if r == '!' {
+		return lexer.LexBuiltin()
+	}
 
 	if r == ':' {
 		return lexer.LexSymbol()
@@ -631,17 +685,29 @@ func NewLexer(scanner io.RuneScanner, filename string) *Lexer {
 	return lexer
 }
 
+func (lexer * Lexer) Report() {
+    if lexer == nil {
+        fmt.Printf("Lexer: is nil\n") 
+    } else {
+        fmt.Printf("Lexer: %s:%d:%d\n", 
+        lexer.Position.FileName,
+        lexer.Position.Column,
+        lexer.Position.Line)
+    }
+}
+
 func NewLexerFromString(input string) *Lexer {
 	reader := strings.NewReader(input)
 	return NewLexer(reader, "<input>")
 }
 
-func NewLexerFromFileName(filename string) (*Lexer, error) {
+func NewLexerFromFilename(filename string) (*Lexer, error) {
 	read, err := os.Open(filename)
-	if err != nil {
+	if err == nil {
 		bread := bufio.NewReader(read)
 		lex := NewLexer(bread, filename)
 		return lex, nil
 	}
 	return nil, err
 }
+

+ 22 - 0
lexer_test.go

@@ -116,3 +116,25 @@ def increment variable by value {
 `
 	// HelperTryLexText(input, test)
 }
+
+
+func TestLexDesignFile(test *testing.T) {
+	lexer, err := NewLexerFromFilename("design_muesli.muesli")
+	if err != nil { 
+        test.Errorf("Error parsing file : %s", err)
+        return
+    }
+    if lexer == nil {
+        test.Errorf("Error: lexer is nil.")
+        return
+    }
+    defer lexer.Report()
+    tokens := lexer.LexAll()
+	for i := 0; i < len(tokens); i++ {
+		test.Logf("%d: %s", i, tokens[i].String())
+	}
+}
+
+
+
+

+ 7 - 0
logger.go

@@ -2,6 +2,7 @@ package muesli
 
 import (
 	"fmt"
+	"reflect"
 	"runtime"
 	"strings"
 )
@@ -50,6 +51,7 @@ func (lw LoggerWrapper) LogError(format string, args ...interface{}) {
 	lw.WriteLog(3, "ERROR:", format, args...)
 }
 
+/* Logger used internally in Muesli for tests. */
 type testLogger struct {
 	last   string
 	repeat int
@@ -74,3 +76,8 @@ func (tl *testLogger) Log(level string, file string, line int, format string, ar
 		fmt.Printf("%s", out)
 	}
 }
+
+/* Useful when logging. */
+func GetFunctionName(i interface{}) string {
+	return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
+}

+ 46 - 45
parser.go

@@ -4,7 +4,7 @@ import (
 	_ "bufio"
 	_ "bytes"
 	_ "errors"
-	_ "fmt"
+	"fmt"
 	_ "io"
 	_ "os"
 	_ "reflect"
@@ -23,14 +23,14 @@ PROGRAM -> STATEMENTS.
 STATEMENTS -> STATEMENT STATEMENTS | .
 STATEMENT -> EXPRESSION eos | BLOCK .
 WORDOPS -> WORDOP WORDOPS | .
-EXPRESSION -> SETTER | GETTER | COMMAND.
+EXPRESSION -> SETTER | GETTER | COMMAND | VALUE.
 COMMAND -> WORDVALUE PARAMETERS.
 PARAMETERS -> PARAMETER PARAMETERS | .
 PARAMETER -> WORDVALUE | PARENTHESIS | GETTER | ARRARY | BLOCK .
 PARENTHESIS -> '(' EXPRESSION ')' .
 BLOCK -> '{' STATEMENTS '}' .
 WORDVALUE -> word | VALUE.
-VALUE -> string | integer | float | symbol.
+VALUE -> string | integer | float | symbol | boolean | nil.
 SETTER -> set word PARAMETERS .
 GETTER -> get word .
 
@@ -76,38 +76,38 @@ func (parser *Parser) Accept(kinds ...TokenKind) Token {
 	return NoToken()
 }
 
-func (parser *Parser) ParseMany(kind AstKind, parent Ast, parsefunc func(*Parser) Ast) Ast {
+func (parser *Parser) ParseMany(kind AstKind, parent *Ast, parsefunc func(*Parser) Ast) Ast {
 	children := make([]Ast, 0)
-	for sub := parsefunc(parser); sub != nil && !AstIsError(sub); sub = parsefunc(parser) {
+	for sub := parsefunc(parser); !sub.IsNone() && !sub.IsError(); sub = parsefunc(parser) {
 		children = append(children, sub)
 	}
 	return NewAst(kind, parent, children, NoToken())
-	return ast
 }
 
-func (parser *Parser) NewAstError(message string) Ast {
-	sv := StringValue(message + " at token " + parser.current.String())
+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)
 	return NewAst(AstKindError, nil, EmptyAstArray(), tok)
 }
 
 func (parser *Parser) ParseAny(astkind AstKind, parsefuncs ...(func(*Parser) Ast)) Ast {
-	ast := NewAst(astkind, nil, NoToken())
+	ast := NewEmptyAst(astkind)
 	for _, parsefunc := range parsefuncs {
+		parser.LogDebug("ParseAny: trying: %s", GetFunctionName(parsefunc))
 		sub := parsefunc(parser)
-		if sub != nil {
+		if !sub.IsNone() {
 			ast.AppendChild(sub)
 			return ast
 		}
 	}
-	return nil
+	return NewAstNone()
 }
 
 func (parser *Parser) ParseRequireAny(astkind AstKind, parsefuncs ...(func(*Parser) Ast)) Ast {
 	ast := parser.ParseAny(astkind, parsefuncs...)
-	if ast == nil {
-		err := parser.NewAstError("Unexpected token")
+	if ast.IsNone() {
+		err := parser.NewAstError("Unexpected token in %v", parsefuncs)
 		return err
 	}
 	return ast
@@ -115,11 +115,11 @@ func (parser *Parser) ParseRequireAny(astkind AstKind, parsefuncs ...(func(*Pars
 
 func (parser *Parser) ParseValue() Ast {
 	value := parser.Accept(TokenKindInteger, TokenKindString,
-		TokenKindBoolean, TokenKindFloat, TokenKindSymbol)
+		TokenKindBoolean, TokenKindNil, TokenKindFloat, TokenKindSymbol)
 	if value.IsNone() {
-		return nil
+		return NewAstNone()
 	}
-	return NewAst(AstKindValue, nil, value)
+	return NewAst(AstKindValue, nil, EmptyAstArray(), value)
 }
 
 func (parser *Parser) ParseWordValue() Ast {
@@ -127,9 +127,9 @@ func (parser *Parser) ParseWordValue() Ast {
 		TokenKindBoolean, TokenKindFloat, TokenKindSymbol,
 		TokenKindType, TokenKindWord)
 	if value.IsNone() {
-		return nil
+		return NewAstNone()
 	}
-	return NewAst(AstKindWordValue, nil, value)
+	return NewAst(AstKindWordValue, nil, EmptyAstArray(), value)
 }
 
 func (parser *Parser) ParseArgument() Ast {
@@ -143,16 +143,16 @@ func (parser *Parser) ParseArgument() Ast {
 }
 
 func (parser *Parser) ParseArguments() Ast {
-	return parser.ParseMany(AstKindArguments, (*Parser).ParseArgument)
+	return parser.ParseMany(AstKindArguments, nil, (*Parser).ParseArgument)
 }
 
 func (parser *Parser) ParseList() Ast {
 	op := parser.Accept(TokenKindOpenList)
 	if op.IsNone() {
-		return nil
+		return NewAstNone()
 	}
 
-	ast := NewAst(AstKindList, nil, op)
+	ast := NewAstWithToken(AstKindList, op)
 	args := parser.ParseArguments()
 	if AstIsError(args) {
 		return args
@@ -169,12 +169,12 @@ func (parser *Parser) ParseParenthesis() Ast {
 	op := parser.Accept(TokenKindOpenParen)
 
 	if op.IsNone() {
-		return nil
+		return NewAstNone()
 	}
 
-	ast := NewAst(AstKindParenthesis, nil, op)
+	ast := NewAstWithToken(AstKindParenthesis, op)
 	expr := parser.ParseExpression()
-	if expr == nil {
+	if expr.IsNone() {
 		return parser.NewAstError("expected expression")
 	}
 	if AstIsError(expr) {
@@ -191,12 +191,12 @@ func (parser *Parser) ParseParenthesis() Ast {
 func (parser *Parser) ParseBlock() Ast {
 	op := parser.Accept(TokenKindOpenBlock)
 	if op.IsNone() {
-		return nil
+		return NewAstNone()
 	}
 
-	ast := NewAst(AstKindBlock, nil, op)
+	ast := NewAstWithToken(AstKindBlock, op)
 	stats := parser.ParseStatements()
-	if stats == nil {
+	if stats.IsNone() {
 		return parser.NewAstError("expected expression")
 	}
 	if AstIsError(stats) {
@@ -213,11 +213,11 @@ func (parser *Parser) ParseBlock() Ast {
 /* Parses the target of a set or get expression */
 func (parser *Parser) ParseTarget() Ast {
 	target := parser.Accept(TokenKindWord, TokenKindType, TokenKindSymbol)
-	ast := NewAst(AstKindTarget, nil, target)
+	ast := NewAstWithToken(AstKindTarget, target)
 
 	if target.IsNone() {
 		paren := parser.ParseParenthesis()
-		if paren == nil {
+		if paren.IsNone() {
 			return parser.NewAstError("expected word, symbol or parenthesis")
 		}
 		ast.AppendChild(paren)
@@ -229,15 +229,15 @@ func (parser *Parser) ParseTarget() Ast {
 func (parser *Parser) ParseSet() Ast {
 	set := parser.Accept(TokenKindSet)
 	if set.IsNone() {
-		return nil
+		return NewAstNone()
 	}
 
-	ast := NewAst(AstKindSet, nil, set)
+	ast := NewAstWithToken(AstKindSet, set)
 	target := parser.ParseTarget()
 	ast.AppendChild(target)
 
 	argument := parser.ParseArgument()
-	if argument == nil {
+	if argument.IsNone() {
 		return parser.NewAstError("Expected argument to set")
 	}
 	ast.AppendChild(argument)
@@ -247,9 +247,9 @@ func (parser *Parser) ParseSet() Ast {
 func (parser *Parser) ParseGet() Ast {
 	get := parser.Accept(TokenKindGet)
 	if get.IsNone() {
-		return nil
+		return NewAstNone()
 	}
-	ast := NewAst(AstKindGet, nil, get)
+	ast := NewAstWithToken(AstKindGet, get)
 	target := parser.ParseTarget()
 	ast.AppendChild(target)
 	return ast
@@ -258,31 +258,31 @@ func (parser *Parser) ParseGet() Ast {
 func (parser *Parser) ParseCommand() Ast {
 	word := parser.Accept(TokenKindWord, TokenKindType)
 	if word.IsNone() {
-		return nil
+		return NewAstNone()
 	}
 	arguments := parser.ParseArguments()
-	command := NewAst(AstKindCommand, nil, word)
+	command := NewAstWithToken(AstKindCommand, word)
 	command.AppendChild(arguments)
 	return command
 }
 
 func (parser *Parser) ParseExpression() Ast {
 	exp := parser.ParseRequireAny(AstKindExpression, (*Parser).ParseSet,
-		(*Parser).ParseGet, (*Parser).ParseCommand)
+		(*Parser).ParseGet, (*Parser).ParseCommand, (*Parser).ParseValue )
 	return exp
 }
 
 func (parser *Parser) ParseEmptyStatement() Ast {
 	eox := parser.Accept(TokenKindEOX)
 	if eox.IsNone() {
-		return nil
+		return NewAstNone()
 	}
-	ast := NewAst(AstKindEnd, nil, eox)
+	ast := NewAstWithToken(AstKindEnd, eox)
 	return ast
 }
 
 func (parser *Parser) ParseStatement() Ast {
-	ast := parser.ParseAny(AstKindStatement,
+	ast := parser.ParseRequireAny(AstKindStatement,
 		(*Parser).ParseBlock,
 		(*Parser).ParseSet,
 		(*Parser).ParseGet,
@@ -295,14 +295,15 @@ func (parser *Parser) ParseStatement() Ast {
 }
 
 func (parser *Parser) ParseStatements() Ast {
-	return parser.ParseMany(AstKindStatements, (*Parser).ParseStatement)
+	return parser.ParseMany(AstKindStatements, nil, (*Parser).ParseStatement)
 }
 
 func (parser *Parser) ParseProgram() Ast {
 	eof := parser.Accept(TokenKindEOF)
-	aeof := NewAst(AstKindEnd, nil, eof)
-	// be lenient with missing EOF for now...
-	children := append(stats, aeof)
+	aeof := NewAstWithToken(AstKindEnd, eof)
+	stats := parser.ParseStatements()
+	// Be lenient with missing EOF for now...
+	children := []Ast{stats, aeof}
 	return NewAst(AstKindProgram, nil, children, NoToken())
 }
 
@@ -322,7 +323,7 @@ func NewParserFromString(input string) *Parser {
 }
 
 func NewParserFromFilename(filename string) (*Parser, error) {
-	lexer, err := NewLexerFromFileName(filename)
+	lexer, err := NewLexerFromFilename(filename)
 	if err != nil {
 		return nil, err
 	}

+ 20 - 5
parser_test.go

@@ -5,8 +5,8 @@ import (
 	"testing"
 )
 
-func HelperFailOnErrors(ast *BasicAst, expected int, test *testing.T) {
-	if ast == nil {
+func HelperFailOnErrors(ast Ast, expected int, test *testing.T) {
+	if ast.IsNone() {
 		test.Errorf("Parse failed, %d parse errors expected", expected)
 	}
 	errors := ast.Errors()
@@ -20,11 +20,12 @@ func HelperFailOnErrors(ast *BasicAst, expected int, test *testing.T) {
 }
 
 func HelperParseAndFailOnErrors(prog string, expected int,
-	parsefunc func(*Parser) *BasicAst, test *testing.T) {
+	parsefunc func(*Parser) Ast, test *testing.T) {
 	parser := NewParserFromString(prog)
-	/* parser.SetLogger(testLogger{}) */
+	parser.SetLogger(&testLogger{})
 	ast := parsefunc(parser)
 	HelperFailOnErrors(ast, expected, test)
+	ast.Display()
 }
 
 func TestParser(test *testing.T) {
@@ -42,5 +43,19 @@ func TestParser2(test *testing.T) {
 }
 
 func TestParenthesis(test *testing.T) {
-	HelperParseAndFailOnErrors(`( add 5 10 )`, 0, (*Parser).ParseParenthesis, test)
+	HelperParseAndFailOnErrors(`( add 5 10 ) `, 0, (*Parser).Parse, test)
+	// HelperParseAndFailOnErrors(`( add 5 10 ) `, 0, (*Parser).ParseParenthesis, test)
+	// HelperParseAndFailOnErrors(`add 5 10 `, 0, (*Parser).ParseCommand, test)
+}
+
+func TestParseLexerDesignFile(test *testing.T) {
+	parser, err := NewParserFromFilename("design_muesli.muesli")
+	if err != nil { 
+        test.Errorf("Error parsingfile : %s", err)
+        return
+    } 
+    parser.SetLogger(&testLogger{})
+    ast := parser.Parse()
+    ast.Display()
 }
+

+ 2 - 0
token.go

@@ -21,6 +21,7 @@ const (
 	TokenKindString     = TokenKind('s')
 	TokenKindSymbol     = TokenKind('S')
 	TokenKindBoolean    = TokenKind('b')
+    TokenKindNil        = TokenKind('N')
 	TokenKindWord       = TokenKind('w')
 	TokenKindType       = TokenKind('t')
 	TokenKindGet        = TokenKind('$')
@@ -44,6 +45,7 @@ var TokenKindNames map[TokenKind]string = map[TokenKind]string{
 	TokenKindSymbol:     "Symbol",
 	TokenKindString:     "String",
 	TokenKindBoolean:    "Boolean",
+    TokenKindNil:        "?il",
 	TokenKindWord:       "Word",
 	TokenKindType:       "Type",
 	TokenKindGet:        "Get",

+ 98 - 0
value.go

@@ -23,6 +23,9 @@ type ListValue struct {
 	List []Value
 }
 
+// Values is simply a shorthand alias for []Value
+type Values = []Value
+
 const (
 	TrueValue       = BoolValue(true)
 	FalseValue      = BoolValue(false)
@@ -109,3 +112,98 @@ func NewListValue(elements ...Value) ListValue {
 func (list *ListValue) Append(elements ...Value) {
 	list.List = append(list.List, elements...)
 }
+
+func EmptyListValue() ListValue {
+	return ListValue{make([]Value, 0)}
+}
+
+func EmptyValueArray() []Value {
+	return make([]Value, 0)
+}
+
+func NewValueArray(elements ...Value) []Value {
+	return elements
+}
+
+/* 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 nil
+}
+
+/* Helpers to easily convert Muesli values from "normal" Go values. */
+func To(from interface{}) Value {
+	switch val := from.(type) {
+	case string:
+		return StringValue(val)
+	case int8:
+		return IntValue(val)
+	case int16:
+		return IntValue(val)
+	case int32:
+		return IntValue(val)
+	case int64:
+		return IntValue(val)
+	case int:
+		return IntValue(val)
+	case bool:
+		return BoolValue(val)
+	case float32:
+		return FloatValue(val)
+	case float64:
+		return FloatValue(val)
+	case error:
+		return ErrorValue{val}
+	case Value:
+		return val
+	default:
+		return NewErrorValuef("Cannot convert value %v", from)
+	}
+}
+
+func ListTo(froms ...interface{}) []Value {
+	list := make([]Value, 0)
+	for _, from := range froms {
+		val := To(from)
+		list = append(list, val)
+	}
+	return list
+}
+
+func ListFrom(froms []Value, tos ...interface{}) error {
+	for i, from := range froms {
+		if i >= len(tos) {
+			break
+		}
+		err := From(from, tos[i])
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func ListFromList(froms []Value) []interface{} {
+	res := make([]interface{}, len(froms))
+	for i, from := range froms {
+		res[i] = from
+	}
+	return res
+}

+ 82 - 18
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
@@ -45,24 +45,24 @@ func NewBuiltinValue(name string, handler Handler) BuiltinValue {
 	return result
 }
 
-func (builtin *BuiltinValue) Call(vm *VM, arguments ...Value) ListValue {
+func (builtin *BuiltinValue) Call(vm *VM, arguments ...Value) []Value {
 	return vm.CallBuiltin(builtin.Handler, arguments...)
 }
 
 // A script defined function
 type DefinedValue struct {
 	CallableValue
-	Definition *BasicAst
+	Definition *Ast
 }
 
-func NewDefinedValue(name string, definition *BasicAst) DefinedValue {
+func NewDefinedValue(name string, definition *Ast) DefinedValue {
 	result := DefinedValue{}
 	result.Name = name
 	result.Definition = definition
 	return result
 }
 
-func (defined *DefinedValue) Call(vm *VM, arguments ...Value) ListValue {
+func (defined *DefinedValue) Call(vm *VM, arguments ...Value) []Value {
 	return vm.CallDefined(defined.Definition, arguments...)
 }
 
@@ -174,16 +174,21 @@ func (scope *Scope) Lookup(name string) Value {
 	return NilValue
 }
 
+func (scope *Scope) Register(name string, value Value) Value {
+	scope.symbols[name] = value
+	return value
+}
+
 // Frame of execution of a function
 type Frame struct {
 	parent    *Frame
-	arguments ListValue
-	results   ListValue
+	arguments []Value
+	results   []Value
 	failed    bool
 }
 
 func NewFrame(parent *Frame) *Frame {
-	return &Frame{parent, NewListValue(), NewListValue(), false}
+	return &Frame{parent, EmptyValueArray(), EmptyValueArray(), false}
 }
 
 // Virtual machine
@@ -201,27 +206,86 @@ func NewVM() *VM {
 	return vm
 }
 
-func (vm *VM) CallDefined(ast *BasicAst, arguments ...Value) ListValue {
-	return NewListValue()
+func (vm *VM) PushNewFrame() *Frame {
+	frame := NewFrame(vm.Frame)
+	vm.Frame = frame
+	return frame
 }
 
-func (vm *VM) CallBuiltin(handler Handler, arguments ...Value) ListValue {
-	return NewListValue()
+func (vm *VM) PushNewScope() *Scope {
+	scope := NewScope(vm.Scope)
+	vm.Scope = scope
+	return scope
+}
+
+func (vm *VM) PopFrame() *Frame {
+	if (vm.Frame != vm.TopFrame) && (vm.Frame.parent != nil) {
+		frame := vm.Frame
+		vm.Frame = frame.parent
+		return frame
+	}
+	return nil
 }
 
-func (vm *VM) Register(name string, value Value) {
+func (vm *VM) PopScope() *Scope {
+	if (vm.Scope != vm.TopScope) && (vm.Scope.parent != nil) {
+		scope := vm.Scope
+		vm.Scope = scope.parent
+		return scope
+	}
+	return nil
+}
+
+func (vm *VM) CallDefined(ast *Ast, arguments ...Value) []Value {
+	return ast.Run(vm, arguments)
+}
+
+func (vm *VM) CallBuiltin(handler Handler, arguments ...Value) []Value {
+	return handler.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...)
+	default:
+		return NewValueArray(NewErrorValuef("Cannot call %s: %v", name, value))
+	}
+}
+
+/*
+func (vm * VM) CallNamedFramed(name string, arguments ...) []Value {
+	frame := vm.PushNewFrame()
+
+}
+*/
+
+func (vm *VM) Register(name string, value Value) Value {
+	return vm.Scope.Register(name, value)
+}
+
+func (vm *VM) RegisterBuiltin(name string, handler Handler) Value {
+	value := NewBuiltinValue(name, handler)
+	return vm.Register(name, value)
+}
 
+func (vm *VM) RegisterDefined(name string, ast *Ast) Value {
+	value := NewDefinedValue(name, ast)
+	return vm.Register(name, value)
 }
 
 func (vm *VM) Fail() {
 	vm.Frame.failed = true
 }
 
-func (vm *VM) RunChildren(ast Ast, args ListValue) ListValue {
-	result := NewListValue()
+func (vm *VM) RunChildren(ast Ast, args ...Value) []Value {
+	result := NewValueArray()
 	for _, child := range ast.Children() {
 		val := child.Run(vm, args)
-		result.Append(val)
+		result = append(result, val...)
 	}
 	return result
 }

+ 101 - 0
vm_test.go

@@ -0,0 +1,101 @@
+package muesli
+
+import (
+	"fmt"
+	"testing"
+)
+
+func TestVm1(test *testing.T) {
+	vm := NewVM()
+	bi := vm.RegisterBuiltin("foo", func(vm *VM, args ...Value) []Value {
+		fmt.Printf("I am foo. See me foo?")
+		return EmptyValueArray()
+	})
+
+	if vm == nil {
+		test.Errorf("Could not construct VM")
+	}
+
+	if _, ok := bi.(BuiltinValue); !ok {
+		test.Errorf("Could not construct register a builtin function.")
+	}
+
+	foo := vm.Lookup("foo")
+	biv, ok := foo.(BuiltinValue)
+	if foo == nil || !ok {
+		test.Errorf("Could not look up foo.")
+	}
+
+	biv.Handler(vm)
+
+}
+
+func ExampleVm1() {
+	vm := NewVM()
+	vm.RegisterBuiltin("foo", func(vm *VM, args ...Value) []Value {
+		fmt.Printf("I am foo. See me foo?")
+		return EmptyValueArray()
+	})
+
+	foo := vm.Lookup("foo")
+	biv, ok := foo.(BuiltinValue)
+	if foo == nil || !ok {
+		fmt.Println("Could not look up foo.")
+	}
+
+	//Output: I am foo. See me foo?
+	biv.Handler(vm)
+
+}
+
+func ExampleVm2() {
+	vm := NewVM()
+	vm.RegisterBuiltin("foo", func(vm *VM, args ...Value) []Value {
+		var s string
+		From(args[0], &s)
+		fmt.Printf("I am foo. See me %s?", s)
+		return EmptyValueArray()
+	})
+
+	//Output: I am foo. See me bar?
+	vm.CallNamed("foo", To("bar"))
+
+}
+
+func ExampleVm3() {
+	vm := NewVM()
+	vm.RegisterBuiltin("multi", func(vm *VM, args ...Value) []Value {
+		var one string
+		var two int64
+		err := ListFrom(args, &one, &two)
+		if err != nil {
+			fmt.Printf("Error: %s", err.Error())
+		}
+		fmt.Printf("I am multi. See me %s, %d?", one, two)
+		return EmptyValueArray()
+	})
+
+	//Output: I am multi. See me bar, 7?
+	vm.CallNamed("multi", ListTo("bar", 7)...)
+
+}
+
+func ExampleVm4() {
+	vm := NewVM()
+	vm.RegisterBuiltin("printf", func(vm *VM, args ...Value) []Value {
+		var form string
+		var rest = args[1:len(args)]
+		resri := ListFromList(rest)
+		err := From(args[0], &form)
+		if err != nil {
+			fmt.Printf("Error: %s", err.Error())
+		} else {
+			fmt.Printf(form, resri...)
+		}
+		return EmptyValueArray()
+	})
+
+	//Output: printf 7
+	vm.CallNamed("printf", ListTo("printf %d", 7)...)
+
+}