Browse Source

Adding selectors but they don't work correctly yet.

Beoran 4 years ago
parent
commit
133c77fb0a
7 changed files with 90 additions and 68 deletions
  1. 13 0
      ast.go
  2. 1 1
      builtin.go
  3. 13 11
      cmd/muesli/main.go
  4. 21 21
      lexer.go
  5. 34 28
      parser.go
  6. 4 6
      token.go
  7. 4 1
      vm.go

+ 13 - 0
ast.go

@@ -13,6 +13,7 @@ type AstMetaKindProgram AstBasicMetaKind
 type AstMetaKindStatements AstBasicMetaKind
 type AstMetaKindStatement AstBasicMetaKind
 type AstMetaKindOperation AstBasicMetaKind
+type AstMetaKindSelector AstBasicMetaKind
 type AstMetaKindSet AstBasicMetaKind
 type AstMetaKindGet AstBasicMetaKind
 type AstMetaKindTarget AstBasicMetaKind
@@ -41,6 +42,7 @@ const (
 	AstKindStatements  = AstMetaKindStatements("Statements")
 	AstKindStatement   = AstMetaKindStatement("Statement")
     AstKindOperation   = AstMetaKindOperation("Operation")
+    AstKindSelector    = AstMetaKindSelector("Selector")
  	AstKindSet         = AstMetaKindSet("Set")
 	AstKindGet         = AstMetaKindGet("Get")
 	AstKindTarget      = AstMetaKindTarget("Target")
@@ -71,6 +73,7 @@ func (astkind AstMetaKindProgram) String() string     { return "AstProgram    "
 func (astkind AstMetaKindStatements) String() string  { return "AstStatements " }
 func (astkind AstMetaKindStatement) String() string   { return "AstStatement  " }
 func (astkind AstMetaKindOperation) String() string   { return "AstOperation  " }
+func (astkind AstMetaKindSelector) String() string    { return "AstSelector   " }
 func (astkind AstMetaKindSet) String() string         { return "AstSet        " }
 func (astkind AstMetaKindGet) String() string         { return "AstGet        " }
 func (astkind AstMetaKindTarget) String() string      { return "AstTarget     " }
@@ -95,6 +98,7 @@ func (astkind AstMetaKindProgram) IsLeaf() bool     { return false }
 func (astkind AstMetaKindStatements) IsLeaf() bool  { return false }
 func (astkind AstMetaKindStatement) IsLeaf() bool   { return false }
 func (astkind AstMetaKindOperation) IsLeaf() bool   { return false }
+func (astkind AstMetaKindSelector) IsLeaf() bool    { return false }
 func (astkind AstMetaKindSet) IsLeaf() bool         { return false }
 func (astkind AstMetaKindGet) IsLeaf() bool         { return false }
 func (astkind AstMetaKindTarget) IsLeaf() bool      { return false }
@@ -152,6 +156,15 @@ func (astkind AstMetaKindOperation) Eval(vm *VM, ast Ast, val ...Value) []Value
     return res	
 }
 
+func (astkind AstMetaKindSelector) Eval(vm *VM, ast Ast, val ...Value) []Value {
+	selectorName := ast.Value()
+	arguments := val
+	vm.Trace("Selector execute: %s %v", selectorName.String(), arguments)
+	res := vm.CallNamed(selectorName.String(), arguments...)
+    return res	
+}
+
+
 // func (astkind AstMetaKindClosed) Eval(vm *VM, ast Ast, val ...Value) []Value {return ReturnEmpty() }
 func (astkind AstMetaKindSet) Eval(vm *VM, ast Ast, val ...Value) []Value {
 	values := val

+ 1 - 1
builtin.go

@@ -594,7 +594,7 @@ func (vm *VM) RegisterBuiltins() {
     vm.Alias("-", "sub")
     vm.Alias("||", "orb")
     vm.Alias("&&", "andb")
-
+	vm.Alias("'s", "of")
 
 
 	

+ 13 - 11
cmd/muesli/main.go

@@ -33,9 +33,9 @@ func runLine(vm *muesli.VM, in string) error {
 	if result != nil { 
 		for _, val := range result { 
 			if val != nil { 
-				fmt.Printf(">>%s\n", val.String())
+				vm.Printf(">>%s\n", val.String())
 			} else {
-				fmt.Printf(">>nil\n")
+				vm.Printf(">>nil\n")
 			}
 		}
 	}
@@ -48,16 +48,16 @@ func runLines(vm *muesli.VM, line *liner.State) error {
 		if in, err := line.Prompt("> "); err == nil {
 			err = runLine(vm, in)
 			if err != nil { 
-				vm.Errorf("Error %s: \n", err)
+				vm.Errf("Error %s: \n", err)
 			}
 			line.AppendHistory(in)
 		} else if err == liner.ErrPromptAborted {
-			vm.Errorf("Aborted\n")
+			vm.Errf("Aborted\n")
 			return nil
 		} else if err == io.EOF { 
             return nil
         } else {
-			vm.Errorf("Error reading line: %s\n", err)
+			vm.Errf("Error reading line: %s\n", err)
 		}
 	}
 	return nil
@@ -66,7 +66,7 @@ func runLines(vm *muesli.VM, line *liner.State) error {
 func runFile(vm *muesli.VM, name string) error {
 	parser, err := muesli.NewParserFromFilename(name)
 	if err != nil {
-        vm.Errorf("Error opening file %s: %s\n", name, err)
+        vm.Errf("Error opening file %s: %s\n", name, err)
 		return err
 	}
 	ast := parser.Parse()
@@ -74,18 +74,20 @@ func runFile(vm *muesli.VM, name string) error {
     if err == io.EOF { 
         return nil
     } else if err != nil {
-        vm.Errorf("Error opening file %s: %s\n", name, err)
+        vm.Errf("Error opening file %s: %s\n", name, err)
 		return err
 	}
 	vm.RunAst(*ast, muesli.NewListValue())
 	return nil
 }
 
-func main() {	
+func main() {
+    // console := muesli.NewStdConsole()	
 	vm := muesli.NewVM()
-	// defer func () { os.Exit(vm.ExitStatus) }()
+    // defer func () { os.Exit(vm.ExitStatus) }()
 	// vm.Tracer = &muesli.FmtTracer{}
-	vm.RegisterBuiltins() 
+	// vm.Console = console
+    vm.RegisterBuiltins() 
 	line := liner.NewLiner()
 	defer line.Close()
 
@@ -141,7 +143,7 @@ func main() {
 	runLines(vm, line)
 	
 	if f, err := os.Create(historyName); err != nil {
-		vm.Errorf("Error writing history file: %s\n", err)
+		vm.Errf("Error writing history file: %s\n", err)
 	} else {
 		line.WriteHistory(f)
 		f.Close()

+ 21 - 21
lexer.go

@@ -142,9 +142,7 @@ func (lexer *Lexer) MakeToken(kind TokenKind) Token {
 		return lexer.MakeWordValueToken(kind)
     case TokenKindOperator: 
         fallthrough
-    case TokenKindRedirect: 
-        fallthrough
-    case TokenKindMethod: 
+    case TokenKindSelector: 
 		return lexer.MakeWordValueToken(kind)
     case TokenKindNil:
         fallthrough
@@ -300,20 +298,12 @@ func isComment(r rune) bool {
 }
 
 func isOperator(r rune) bool {
-	return isPureOperator(r) || isRedirect(r) || isMethod(r)
-}
-
-func isPureOperator(r rune) bool {
 	return r == '+' || r == '-' || r == '*' || r == '/' || r == '^' ||
-           r == '%' || r == '~'
+           r == '%' || r == '~' || r == '|' || r == '&' || r == '>' || r == '<' || r == '@'
 }
 
-func isRedirect(r rune) bool {
-	return r == '|' || r == '&' || r == '>' || r == '<' || r == '@'
-}
-
-func isMethod(r rune) bool {
-	return r == ',' || r == ';'
+func isSelector(r rune) bool {
+	return r == ',' || r == ';' || r == '\''
 }
 
 
@@ -385,13 +375,19 @@ func (lexer *Lexer) LexOperator() Token {
 	if err != nil {
 		return lexer.MakeErrorfToken("when parsing operator: %s", err)
 	}
-    oper := lexer.buffer[0]
-    switch {
-        case isPureOperator(oper): return lexer.MakeToken(TokenKindOperator)
-        case isRedirect(oper): 	return lexer.MakeToken(TokenKindRedirect)
-        case isMethod(oper): return lexer.MakeToken(TokenKindMethod)    
-    }
-    return lexer.MakeToken(TokenKindOperator)
+	return lexer.MakeToken(TokenKindOperator)
+}
+
+func (lexer *Lexer) LexSelector() Token {
+    _, err := lexer.NextWhile(isSelector)
+    if err != nil {
+		return lexer.MakeErrorfToken("when parsing selector: %s", err)
+	}
+	_, err = lexer.NextWhile(unicode.IsLetter)
+	if err != nil {
+		return lexer.MakeErrorfToken("when parsing selector extension: %s", err)
+	}
+    return lexer.MakeToken(TokenKindSelector)
 }
 
 func (lexer *Lexer) LexNumber() Token {
@@ -723,6 +719,10 @@ func (lexer *Lexer) lex() Token {
 	if isOperator(r) {
 		return lexer.LexOperator()
 	}
+	
+	if isSelector(r) {
+		return lexer.LexSelector()
+	}
 
 	switch TokenKind(r) {
 	case TokenKindGet:

+ 34 - 28
parser.go

@@ -244,7 +244,7 @@ func (parser *Parser) ParseArgument() *Ast {
     parser.LogDebug("ParseArgument: %s\n", parser.current.String())
 
 	switch {
-			case parser.NextIsName(): return parser.ParseName()
+			case parser.NextIsName(): return parser.ParseField()
 			case parser.NextIsBlock(): return parser.ParseBlock()
 			case parser.NextIsSubstitution(): return parser.ParseSubstitution()
 			case parser.NextIsLiteral(): return parser.ParseLiteral()
@@ -393,6 +393,27 @@ func (parser *Parser) ParseOrigin() *Ast {
 	return target
 }
 
+func (parser *Parser) ParseSelector() *Ast {
+	parser.LogDebug("ParseSelector %s\n", parser.current.String())
+	selector := parser.Require(TokenKindSelector)
+	parameter := parser.ParseArgument()
+	ast := NewAstWithToken(AstKindSelector, selector)
+	ast.AppendChild(parameter)
+	return ast
+}
+
+// Parses a Field with it's optional selectors
+func (parser *Parser) ParseField() *Ast {
+	// FIELD -> NAME SELECTOR.
+	name := parser.ParseName()
+	if parser.NextIsSelector() {
+		selector := parser.ParseSelector()
+		// prepend name before selector
+		selector.children = append([]*Ast{name}, selector.children...)
+	}
+	// No selector, just return the name
+	return name
+}
 
 func (parser *Parser) ParseSet() *Ast {
     parser.LogDebug("ParseSet: %s\n", parser.current.String())
@@ -417,9 +438,10 @@ func (parser *Parser) ParseGet() *Ast {
 func (parser *Parser) ParseCommand() *Ast {
     parser.LogDebug("ParseCommand: %s\n", parser.current.String())
 
-	word := parser.Require(TokenKindWord, TokenKindType)
+	field := parser.ParseField()
 	arguments := parser.ParseArguments()
-	command := NewAstWithToken(AstKindCommand, word)
+    /// this is wrong...
+	command := NewAstWithToken(AstKindCommand, field.Token())
 	command.AppendChild(arguments)
 	return command
 }
@@ -519,7 +541,11 @@ func (parser Parser) NextIsName() bool {
 }
 
 func (parser Parser) NextIsOperator() bool {
-    return parser.NextIs(TokenKindOperator, TokenKindRedirect, TokenKindMethod)
+    return parser.NextIs(TokenKindOperator)
+}
+
+func (parser Parser) NextIsSelector() bool {
+    return parser.NextIs(TokenKindSelector)
 }
 
 func (parser Parser) NextIsArgument() bool {
@@ -569,15 +595,7 @@ func (parser *Parser) newMethodChain(oper Token, expr1, expr2 *Ast) *Ast {
 }
 
 func (parser *Parser) newChain(oper Token, expr1, expr2 *Ast) * Ast {
-    var astkind AstKind = AstKindParenthesis
-    
-    if oper.TokenKind == TokenKindRedirect {
-        parser.LogDebug("New redirect chain.")
-        astkind = AstKindStatements
-    } else if oper.TokenKind == TokenKindMethod {
-        return parser.newMethodChain(oper, expr1, expr2)
-    }
-
+    var astkind AstKind = AstKindParenthesis    
     subst1 := NewAstWithToken(astkind, oper)
     subst1.AppendChildren(expr1)
     subst2 := NewAstWithToken(astkind, oper)
@@ -588,20 +606,8 @@ func (parser *Parser) newChain(oper Token, expr1, expr2 *Ast) * Ast {
 }
 
 func (parser *Parser) composeChain(oper Token, chain, nextExpr *Ast) * Ast {
-    var astkind AstKind = AstKindParenthesis
-    
-    if oper.TokenKind == TokenKindRedirect {
-        parser.LogDebug("Composed redirect chain: %v", chain)
-        astkind = AstKindStatements
-    } else if oper.TokenKind == TokenKindMethod {
-        chain.AppendChild(NewAstWithToken(AstKindForToken(nextExpr.Token()), nextExpr.Token()))
-        chain.AppendChildren(nextExpr.Children()...)
-        parser.LogDebug("Composed method chain: %v", chain)
-        return chain
-    } else {
-        parser.LogDebug("Composed normal chain: %v", chain)
-    }
-
+    var astkind AstKind = AstKindParenthesis    
+    parser.LogDebug("Composed chain: %v", chain)
     subst := NewAstWithToken(astkind, oper)
     subst.AppendChildren(nextExpr)
     newChain := NewAstWithToken(AstKindOperation, oper)
@@ -618,7 +624,7 @@ func (parser *Parser) ParseChain() *Ast {
     var expressions = []*Ast{ expression }
     var operators = []Token {}
     for parser.NextIsOperator() {
-        oper := parser.Require(TokenKindOperator, TokenKindRedirect, TokenKindMethod)
+        oper := parser.Require(TokenKindOperator)
         expression := parser.ParseExpression()
         if expression == nil {
             parser.Panicf("Expected expression after operator.")

+ 4 - 6
token.go

@@ -28,9 +28,8 @@ const (
     TokenKindNil        = TokenKind('N')
 	TokenKindWord       = TokenKind('w')
 	TokenKindType       = TokenKind('t')
-	TokenKindOperator   = TokenKind('o')
-	TokenKindRedirect   = TokenKind('R')
-    TokenKindMethod     = TokenKind('M')	
+	TokenKindOperator   = TokenKind('+')
+	TokenKindSelector   = TokenKind(',')
     TokenKindGet        = TokenKind('$')
 	TokenKindSet        = TokenKind('=')
 	TokenKindOpenBlock  = TokenKind('{')
@@ -56,8 +55,7 @@ var TokenKindNames map[TokenKind]string = map[TokenKind]string{
 	TokenKindWord:       "Word",
 	TokenKindType:       "Type",
 	TokenKindOperator:   "Operator",   
-	TokenKindRedirect:   "Redirect",
-    TokenKindMethod:     "Method",
+	TokenKindSelector:   "Selector",
 	TokenKindGet:        "Get",
 	TokenKindSet:        "Set",
 	TokenKindOpenBlock:  "OpenBlock",
@@ -137,4 +135,4 @@ func (token Token) IsNone() bool {
 
 func (token Token) IsError() bool {
 	return token.TokenKind == TokenKindError
-}
+}

+ 4 - 1
vm.go

@@ -268,11 +268,14 @@ func (cv * CoverValue) AddOverload(name string, callable Callable, tv ... TypeVa
 	return nil
 }
 
+func (vm * VM) Errf(format string, args...interface{}) {
+    vm.Console.Errf(format, args...)
+}
+
 func (vm * VM) Errorf(format string, args...interface{}) error {
     return fmt.Errorf(format, args...)
 }
 
-
 func (vm * VM) AddOverloadCallable(from, target string, level int, callable Callable) error {
 	var cover *CoverValue
 	var ok bool