Browse Source

Support operators, finally, if in a slightly roundabout way. Also support aliasing.

Beoran 4 years ago
parent
commit
1a81159c54
4 changed files with 105 additions and 31 deletions
  1. 20 0
      alias.go
  2. 26 10
      builtin.go
  3. 23 20
      lexer.go
  4. 36 1
      parser.go

+ 20 - 0
alias.go

@@ -0,0 +1,20 @@
+package muesli
+
+func (vm *VM) AliasUp(from, to string, level int) Value {
+    value := vm.Lookup(to)
+    if value == nil {
+        return value
+    }
+    return vm.RegisterUp(from, value, level)
+}
+
+func (vm *VM) Alias(from, to string) Value {
+    value := vm.Lookup(to)
+    if value == nil {
+        return value
+    }
+    return vm.Register(from, value)
+}
+
+
+

+ 26 - 10
builtin.go

@@ -204,6 +204,7 @@ func builtin_return(vm *VM, args ...Value) []Value {
 
 func to(vm *VM, args ...Value) []Value {
 	var name string	
+
 	rest, err := ParseArgs(args, &name)
 	if err != nil {
 		return Fail(err)
@@ -218,10 +219,10 @@ func to(vm *VM, args ...Value) []Value {
 	if ! isBlock {
 		return Fail(NewErrorValuef("Not a block: %v", last))
 	}
-	param := rest[0:len(rest)-1]
+	param := args[1:len(args)-1]
 	sign, err := NewSignatureWithNames(param...)
 	if err != nil {
-		return Fail(NewErrorValuef("Not a word value: %v", name))
+		return Fail(NewErrorValuef("Could not parse arguments: %v: %s", name, err))
 	}
 	
 	// To must register one level up.
@@ -465,7 +466,7 @@ func (vm *VM) RegisterBuiltins() {
 	vm.RegisterBuiltinTypes()
 	vm.RegisterBuiltinWithHelp("addl", addl, "adds an element to a list").Takes(ListType, AnyType).Returns(ListType)
 	vm.RegisterBuiltinWithHelp("addi", addi, `adds two integers together`).Takes(IntType, IntType).Returns(BoolType)
-	vm.RegisterBuiltinWithHelp("addf", addf, `adds two floats together`).Takes(IntType, IntType).Returns(IntType)
+	vm.RegisterBuiltinWithHelp("addf", addf, `adds two floats together`).Takes(FloatType, FloatType).Returns(FloatType)
 	vm.RegisterBuiltinWithHelp("andb", andb, `returns true if all it's arguments are true`).Takes(BoolType, BoolType).Returns(BoolType)
     vm.RegisterBuiltin(",", comma)
 
@@ -504,19 +505,34 @@ func (vm *VM) RegisterBuiltins() {
 			Over("muli", 0, IntType, IntType),
 			Over("mulf", 0, FloatType, IntType),
 			Over("mulf", 0, IntType, FloatType))
-
-	vm.AddOverloads("*", 
-			Over("mulf", 0, FloatType, FloatType),
-			Over("muli", 0, IntType, IntType),
-			Over("mulf", 0, FloatType, IntType),
-			Over("mulf", 0, IntType, FloatType))
-
 	
 	vm.AddOverloads("add", 
 			Over("addf", 0, FloatType, FloatType),
 			Over("addi", 0, IntType, IntType),
 			Over("addf", 0, FloatType, IntType),
 			Over("addf", 0, IntType, FloatType))
+
+	vm.AddOverloads("div", 
+			Over("divf", 0, FloatType, FloatType),
+			Over("divi", 0, IntType, IntType),
+			Over("divf", 0, FloatType, IntType),
+			Over("divf", 0, IntType, FloatType))
+
+	vm.AddOverloads("sub", 
+			Over("subf", 0, FloatType, FloatType),
+			Over("subi", 0, IntType, IntType),
+			Over("subf", 0, FloatType, IntType),
+			Over("subf", 0, IntType, FloatType))
+
+	vm.Alias("*", "mul")
+	vm.Alias("+", "add")
+    vm.Alias("/", "div")
+    vm.Alias("-", "sub")
+    vm.Alias("||", "orb")
+    vm.Alias("&&", "andb")
+
+
+
 	
 			
 	vm.SetHelp("mul", "	 Num: Multiplies two numbers. Cover for muli and mulf.")	

+ 23 - 20
lexer.go

@@ -375,39 +375,42 @@ func (lexer *Lexer) LexOperator() Token {
 func (lexer *Lexer) LexNumber() Token {
 	isFloat := false
 	maybeOperator := false
-	reallyOperator := false
 
 	// skip any first - or +
 	_, err := lexer.NextIf(func(r rune) bool {		
 		maybeOperator = (r == '-' || r == '+')  // it might also be an operator in stead.
 		return r == '-' || r == '+'
 	})
+    
+    if err != nil {
+        return lexer.MakeErrorfToken("Error during parsing of number prefix: %s", err)
+    }
+    
 
-	_, err = lexer.NextWhile(func(r rune) bool {
-		if unicode.IsDigit(r) {
-			return true
+    for {
+        r, err := lexer.Peek()
+        if err != nil {
+            return lexer.MakeErrorfToken("Error during parsing of number: %s", err)
+        }
+        
+        if unicode.IsDigit(r) {
+            maybeOperator = false
+			lexer.Next()
 		} else if r == '.' {
 			if isFloat {
-				return false // double point in floating point
+                lexer.Next()
+				return lexer.MakeErrorfToken("two points in floating point number")
 			} else {
 				isFloat = true
-				return true
+				lexer.Next()
 			}
 		} else if maybeOperator {
-			reallyOperator = true
-			return true
-		} else {
-			return false
-		}
-	})
-	
-	if err != nil {
-		return lexer.MakeErrorfToken("when parsing number: %s", err)
-	}
-	if maybeOperator && reallyOperator {
-		 return lexer.LexOperator()
-	}
-	
+            return lexer.LexOperator() 
+        } else {
+            break
+        }
+    }
+        
 	if isFloat {
 		return lexer.MakeToken(TokenKindFloat)
 	} else {

+ 36 - 1
parser.go

@@ -60,6 +60,33 @@ GETTER -> get ORIGIN .
 GETCALL -> comma COMMAND | .
 ORIGIN -> word | SETTER | GETTER .
 
+Note that the Muesli syntax description below is not strictly LL(1), 
+notably the optional operator after a getter, but the recursive descent parser 
+can parse it correctly.
+
+PROGRAM -> STATEMENTS.
+CLOSED -> BLOCK | LIST | PARENTHESIS .
+STATEMENTS -> STATEMENT STATEMENTS | .
+STATEMENT -> CLOSED | EXPRESSION eos | eos .
+COMMAND -> WORDVALUE DETAILS .
+DETAILS -> OPERATION | PARAMETERS .
+OPT_OPER -> OPERATION | .
+OPERATION -> operator COMMAND .
+PARAMETERS -> PARAMETER PARAMETERS | .
+PARAMETER -> WORDVALUE | GETTER | SETTER | CLOSED .
+EXPRESSION -> COMMAND | GETTER | SETTER.
+PARENTHESIS -> openparen EXPRESSION closeparen .
+BLOCK -> openblock STATEMENTS closeblock .
+LIST -> openlist PARAMETERS closelist .
+VALUE -> string | int | float | symbol | type .
+WORDVALUE -> word | VALUE.
+SETTER -> set TARGET . 
+TARGET -> word PARAMETER | GETTER PARAMETER .
+GETTER -> get ORIGIN OPT_OPER .
+GETCALL -> comma COMMAND | .
+ORIGIN -> word | SETTER | GETTER .
+
+
  *
  * program -> statements
  * statements -> statement+
@@ -372,7 +399,11 @@ func (parser *Parser) ParseSet() *Ast {
 	ast := NewAstWithToken(AstKindSet, set)
 	target := parser.ParseTarget()
 	ast.AppendChild(target)
-	return ast
+    if parser.NextIs(TokenKindOperator)  {
+        ast = parser.ParseOperator(ast)
+    }
+    
+    return ast
 }
 
 func (parser *Parser) ParseGet() *Ast {
@@ -382,6 +413,10 @@ func (parser *Parser) ParseGet() *Ast {
 	ast := NewAstWithToken(AstKindGet, get)
 	target := parser.ParseOrigin()
 	ast.AppendChild(target)
+    if parser.NextIs(TokenKindOperator)  {
+        ast = parser.ParseOperator(ast)
+    }
+    
 	return ast
 }