Browse Source

Various improvements

Beoran 4 years ago
parent
commit
a387df4660
7 changed files with 306 additions and 56 deletions
  1. 1 1
      ast.go
  2. 103 20
      builtin.go
  3. 34 10
      lexer.go
  4. 37 0
      parser.go
  5. 1 1
      token.go
  6. 83 8
      value.go
  7. 47 16
      vm.go

+ 1 - 1
ast.go

@@ -180,7 +180,7 @@ func (astkind AstMetaKindParenthesis) Run(vm *VM, ast Ast, val ...Value) []Value
 
 func (astkind AstMetaKindList) Run(vm *VM, ast Ast, val ...Value) []Value {	
 	result := vm.RunChildren(ast, val...)
-	list := ListValue{List:result}
+	list := &ListValue{List:result}
 	return []Value{list}
 }
 

+ 103 - 20
builtin.go

@@ -168,7 +168,6 @@ func divi(vm *VM, args ...Value) []Value {
 	return IntOk(v1 / v2)
 }
 
-
 func divf(vm *VM, args ...Value) []Value {
 	var v1, v2 float64
 	_, err := ParseArgs(args, &v1, &v2)
@@ -178,6 +177,23 @@ func divf(vm *VM, args ...Value) []Value {
 	return FloatOk(v1 / v2)
 }
 
+func andb(vm * VM, args ...Value) []Value {
+	var v1, v2 bool
+	_, err := ParseArgs(args, &v1, &v2)
+	if err != nil {
+		return Fail(err)
+	}	
+	return BoolOk(v1 && v2)
+}
+
+func orb(vm * VM, args ...Value) []Value {
+	var v1, v2 bool
+	_, err := ParseArgs(args, &v1, &v2)
+	if err != nil {
+		return Fail(err)
+	}	
+	return BoolOk(v1 || v2)
+}
 
 func val(vm *VM, args ...Value) []Value {
 	if len(args) < 1 {
@@ -284,6 +300,65 @@ func get(vm *VM, val ...Value) []Value {
 	return Ok(vm.Lookup(target))
 }
 
+func fetchl(vm *VM, args ...Value) []Value {
+	var index int
+	var list *ListValue
+	_, err := ParseArgs(args, &list, &index)
+	if err != nil {
+		return Fail(err)
+	}
+	return Ok(list.List[index])	
+}
+
+func storel(vm *VM, args ...Value) []Value {
+	var index int
+	var list *ListValue
+	rest, err := ParseArgs(args, &list, &index)
+	if err != nil {
+		return Fail(err)
+	}
+	if len (rest) < 1 {
+		return Fail(fmt.Errorf("fetch: need 3 arguments")) 
+	}	
+	list.List[index] = rest[0]
+	return Ok(list.List[index])	
+}
+
+
+func fetchm(vm *VM, args ...Value) []Value {
+	var index Value
+	var hmap *MapValue
+	_, err := ParseArgs(args, &hmap, &index)
+	if err != nil {
+		return Fail(err)
+	}
+	return Ok(hmap.Map[index])	
+}
+
+func storem(vm *VM, args ...Value) []Value {
+	var index Value
+	var hmap *MapValue
+	rest, err := ParseArgs(args, &hmap, &index)
+	if err != nil {
+		return Fail(err)
+	}
+	if len (rest) < 1 {
+		return Fail(fmt.Errorf("fetch: need 3 arguments")) 
+	}	
+	hmap.Map[index] = rest[0]
+	return Ok(hmap.Map[index])	
+}
+
+func newmap(vm *VM, args ...Value) []Value {
+	result := make(map[Value] Value)
+	for i := 1; i < len(args) ; i+=2 {
+		result[args[i-1]] = args[i]
+	}
+	return Ok(NewMapValue(result))
+}
+
+
+
 func help(vm *VM, val ...Value) [] Value {
 	if len(val) < 1 {
 		fmt.Printf("help <callable> will display help on the callable\n\nThe following commands are available:\n")
@@ -340,36 +415,26 @@ func exit(vm *VM, val ...Value) [] Value {
 func (vm *VM) RegisterBuiltins() {
 	vm.RegisterBuiltinWithHelp("addi", addi, `[Int Int] -> Int: adds two integers together`)
 	vm.RegisterBuiltinWithHelp("addf", addf, `[Int Int] -> Int: adds two floats together`)
+	vm.RegisterBuiltinWithHelp("andb", andb, `[Bool Bool] -> Bool: returns true if all it's arguments are true`)
 	vm.RegisterBuiltin("cover", cover)
+	vm.RegisterBuiltin("fetchl", fetchl)
+	vm.RegisterBuiltin("fetchm", fetchm)
 	vm.RegisterBuiltin("sumi", sumi)
 	vm.RegisterBuiltin("sumf", sumf)
 	vm.RegisterBuiltin("subi", subi)
 	vm.RegisterBuiltin("subf", subf)
 	vm.RegisterBuiltin("divi", divi)
 	vm.RegisterBuiltin("divf", divf)
+	vm.RegisterBuiltin("map", newmap)
 	vm.RegisterBuiltin("muli", muli)
 	vm.RegisterBuiltin("mulf", mulf)
-	err := vm.AddOverload("mul", "mulf", FloatTypeValue, FloatTypeValue)
-	if err != nil {
-		fmt.Printf("Errror registering overload: %s", err)
-	}
-	err = vm.AddOverload("mul", "muli", IntTypeValue, IntTypeValue)
-	if err != nil {
-		fmt.Printf("Errror registering overload: %s", err)
-	}
-	err = vm.AddOverload("mul", "mulf", FloatTypeValue, IntTypeValue)
-	if err != nil {
-		fmt.Printf("Errror registering overload: %s", err)
-	}
-	err = vm.AddOverload("mul", "mulf", IntTypeValue, FloatTypeValue)
-	if err != nil {
-		fmt.Printf("Errror registering overload: %s", err)
-	}
-	
+	vm.RegisterBuiltinWithHelp("orb", orb, `[Bool Bool] -> Bool: returns true if on of it's arguments is true`)
 	// vm.RegisterCover("add")
 	vm.RegisterBuiltin("p", p)
 	vm.RegisterBuiltin("println", println)
-	vm.RegisterBuiltin("printf", printf)
+	vm.RegisterBuiltin("printf", printf)	
+	vm.RegisterBuiltin("storel", storel)
+	vm.RegisterBuiltin("storem", storem)
 	vm.RegisterBuiltin("trace", trace)
 	vm.RegisterBuiltin("to", to)
 	vm.RegisterBuiltin("types", types)
@@ -379,8 +444,26 @@ func (vm *VM) RegisterBuiltins() {
 	vm.RegisterBuiltin("help", help)
 	vm.RegisterBuiltin("explain", explain)
 	vm.RegisterBuiltin("exit", exit)
-	vm.SetHelp("mul", "	 Num: Multiplies two numbers. Cover for muli and mulf.") 
 	
+	vm.AddOverloads("mul", 
+			Over("mulf", FloatTypeValue, FloatTypeValue),
+			Over("muli", IntTypeValue, IntTypeValue),
+			Over("mulf", FloatTypeValue, IntTypeValue),
+			Over("mulf", FloatTypeValue, IntTypeValue))
+			
+	vm.SetHelp("mul", "	 Num: Multiplies two numbers. Cover for muli and mulf.")	
+	vm.AddOverloads("fetch", 
+			Over("fetchl", ListTypeValue, IntTypeValue),
+			Over("fetchm", MapTypeValue, AnyTypeValue),
+		)			
+	vm.SetHelp("fetch", " storage, index. Fetch value in storage at given index.")
+	/*
+	vm.AddOverloads("store", 
+			Over("storel", ListTypeValue, IntTypeValue, AnyTypeValue),
+			Over("storem", MapTypeValue, AnyTypeValue, AnyTypeValue),
+		)
+	vm.SetHelp("store", " storage, index, value. Store value in storage at given index.")
+	*/
 }
 
 

+ 34 - 10
lexer.go

@@ -18,6 +18,16 @@ import (
 	// _ "gitlab.com/beoran/woe/monolog"
 )
 
+
+/* Muesli has no key words by default, but they can be defined if desired
+ * for ease of use. A key word is replaced by a token during lexing. */
+type Keyword struct {
+	Name string
+	TokenKind
+	Value 
+} 
+  
+
 /* A Lexer splits scanned input into tokens.
  */
 type Lexer struct {
@@ -27,6 +37,7 @@ type Lexer struct {
 	io.RuneScanner
 	buffer  []rune
 	Current rune
+	Keywords map[string]*Keyword
 	LoggerWrapper
 }
 
@@ -50,6 +61,12 @@ func (lexer *Lexer) MakeIntegerToken() Token {
 	}
 }
 
+func (lexer *Lexer) MakeTokenFromKeyword(kw * Keyword) Token {
+	lexer.ClearBuffer()
+	return NewToken(kw.TokenKind, kw.Value, lexer.Position)
+}
+
+
 func (lexer *Lexer) MakeFloatToken() Token {
 	var sbuffer = string(lexer.buffer)
 	f, err := strconv.ParseFloat(sbuffer, 64)
@@ -529,17 +546,11 @@ func (lexer *Lexer) LexWordOrType(kind TokenKind) Token {
 
 	sbuffer := string(lexer.buffer)
 
-	// handle key words
-	switch sbuffer {
-	case "true":
-		return lexer.MakeBooleanToken(true)
-	case "false":
-		return lexer.MakeBooleanToken(false)
-    case "nil":
-        return lexer.MakeNilToken()
-	default:
+	// handle keywords
+	if kw, ok := lexer.Keywords[sbuffer] ; ok { 
+		return lexer.MakeTokenFromKeyword(kw)
 	}
-
+	
 	return lexer.MakeToken(kind)
 }
 
@@ -730,6 +741,7 @@ func NewLexer(scanner io.RuneScanner, filename string) *Lexer {
 	lexer.Position.Column = 1
 	lexer.Position.Line = 1
 	lexer.LoggerWrapper = LoggerWrapper{nil}
+	lexer.Keywords = make(map[string]*Keyword)
 	return lexer
 }
 
@@ -744,6 +756,18 @@ func (lexer * Lexer) Report() {
     }
 }
 
+func (lexer *Lexer) AddKeyword(kw * Keyword) *Keyword {
+	if kw != nil { 
+		lexer.Keywords[kw.Name] = kw
+	}
+	return kw
+}
+
+func (lexer *Lexer) NewKeyword(name string, kind TokenKind, value Value) *Keyword {
+	kw := &Keyword{Name: name, TokenKind: kind, Value: value}
+	return lexer.AddKeyword(kw)
+}
+
 func NewLexerFromString(input string) *Lexer {
 	reader := strings.NewReader(input)
 	return NewLexer(reader, "<input>")

+ 37 - 0
parser.go

@@ -550,6 +550,7 @@ func (parser *Parser) Parse() (ast *Ast) {
 
 func NewParser(lexer *Lexer) *Parser {
 	parser := &Parser{Lexer: lexer, current: NoToken(), LoggerWrapper: LoggerWrapper{nil}}
+	parser.AddDefaultKeywords()
 	return parser
 }
 
@@ -565,3 +566,39 @@ func NewParserFromFilename(filename string) (*Parser, error) {
 	}
 	return NewParser(lexer), nil
 }
+
+func (parser * Parser) NewKeyword(name string, tk TokenKind, val Value) *Keyword {
+	return parser.Lexer.NewKeyword(name, tk, val)
+}
+
+func (parser * Parser) AddKeyword(kw * Keyword) *Keyword {
+	return parser.Lexer.AddKeyword(kw)
+}
+
+func (parser * Parser) AddKeywords(keywords []*Keyword) {
+	for _, kw := range keywords {
+		parser.AddKeyword(kw)
+	}	
+}
+
+var DefaultKeywords []*Keyword = []*Keyword{
+	&Keyword { "true", TokenKindBoolean, TrueValue },
+	&Keyword { "false", TokenKindBoolean, FalseValue },
+	&Keyword { "nil", TokenKindNil, NilValue },
+	&Keyword { "do", TokenKindOpenBlock, StringValue("{") },
+	&Keyword { "end", TokenKindCloseBlock, StringValue("}") },
+	&Keyword { "as", TokenKindOpenParen, StringValue("(") },
+	&Keyword { "so", TokenKindCloseParen, StringValue(")") },
+	&Keyword { "list", TokenKindOpenList, StringValue("[") },
+	&Keyword { "done", TokenKindCloseList, StringValue("]") },
+}
+
+
+func (parser * Parser) AddDefaultKeywords() {
+	parser.AddKeywords(DefaultKeywords)
+}
+
+
+
+
+

+ 1 - 1
token.go

@@ -65,7 +65,7 @@ var TokenKindNames map[TokenKind]string = map[TokenKind]string{
 	TokenKindEOF:        "EOF",
 }
 
-/* Transforms a token kid to a String */
+/* Transforms a token kind to a String */
 func (kind TokenKind) String() string {
 	name, ok := TokenKindNames[kind]
 	if !ok {

+ 83 - 8
value.go

@@ -30,6 +30,10 @@ type ListValue struct {
 	List []Value
 }
 
+type MapValue struct { 
+	Map map[Value]Value
+}
+
 // Values is simply a shorthand alias for []Value
 type Values = []Value
 
@@ -45,6 +49,7 @@ const (
 	TypeTypeValue   = TypeValue("Type")
 	EmptyTypeValue  = TypeValue("Empty")
 	ListTypeValue   = TypeValue("List")
+	MapTypeValue    = TypeValue("Map")
 	AnyTypeValue    = TypeValue("Any")
 	ZeroTypeValue   = TypeValue("")
 )
@@ -98,6 +103,18 @@ func (val ListValue) String() string {
 	return res
 }
 
+func (val MapValue) String() string {
+	res := "{"
+	sep := ""
+	for k, v := range val.Map {
+		res = res + sep + k.String() + "=>" + v.String()
+		sep = ", "
+	}
+	res += "}"
+	return res
+}
+
+
 func (v IntValue) Type() TypeValue    { return IntTypeValue }
 func (v FloatValue) Type() TypeValue  { return FloatTypeValue }
 func (v StringValue) Type() TypeValue { return StringTypeValue }
@@ -107,14 +124,15 @@ func (v TypeValue) Type() TypeValue   { return TypeTypeValue }
 func (v ErrorValue) Type() TypeValue  { return ErrorTypeValue }
 func (v EmptyValue) Type() TypeValue  { return EmptyTypeValue }
 func (v ListValue) Type() TypeValue   { return ListTypeValue }
+func (v MapValue) Type() TypeValue    { return MapTypeValue }
 
 func NewErrorValuef(format string, args ...interface{}) ErrorValue {
 	err := fmt.Errorf(format, args...)
 	return ErrorValue{err}
 }
 
-func NewListValue(elements ...Value) ListValue {
-	return ListValue{elements}
+func NewListValue(elements ...Value) * ListValue {
+	return &ListValue{elements}
 }
 
 func (list *ListValue) Append(elements ...Value) {
@@ -129,20 +147,27 @@ func (list ListValue) Length() int {
 	return len(list.List)
 }
 
-func (list *ListValue) Index(i int) Value {
+func (list *ListValue) Fetch(i int) Value {
 	if i >= len(list.List) {
 		return NilValue
 	}
 	return list.List[i]
 }
 
+func (list *ListValue) Place(i int, v Value) Value {
+	if i >= len(list.List) {
+		return NilValue
+	}
+	list.List[i] = v
+	return list.List[i]
+}
 
 func (list *ListValue) First() Value {
-	return list.Index(0)
+	return list.Fetch(0)
 }
 
 func (list *ListValue) Last() Value {
-	return list.Index(list.Length()-1)
+	return list.Fetch(list.Length()-1)
 }
 
 
@@ -158,6 +183,24 @@ func NewValueArray(elements ...Value) []Value {
 	return elements
 }
 
+func NewMapValue(elements map[Value]Value) * MapValue {
+	return &MapValue{elements}
+}
+
+func (m *MapValue) Fetch(key Value) Value {
+	var res Value
+	var ok bool
+	if res, ok = m.Map[key] ; !ok {
+		return NilValue
+	}
+	return res
+}
+
+func (m *MapValue) Place(key Value, value Value) Value {
+	m.Map[key] = value
+	return m.Map[key]
+}
+
 
 func (from IntValue) Convert(to interface{}) error {
 	switch toPtr := to.(type) {
@@ -181,6 +224,8 @@ func (from IntValue) Convert(to interface{}) error {
 			(*toPtr) = float64(from)
 		case *IntValue:
 			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from			
 		default:
 			return NewErrorValuef("Cannot convert IntValue value %v to %v", from, to)
 	}
@@ -209,6 +254,8 @@ func (from FloatValue) Convert(to interface{}) error {
 			(*toPtr) = float64(from)
 		case *FloatValue:
 			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from
 		default:
 			return NewErrorValuef("Cannot convert FloatValue value %v to %v", from, to)
 	}
@@ -221,6 +268,8 @@ func (from StringValue) Convert(to interface{}) error {
 			(*toPtr) = from.String()
 		case *StringValue:
 			(*toPtr) = from	
+		case *Value:
+			(*toPtr) = from	
 		default:
 			return NewErrorValuef("Cannot convert StringValue %v to %v", from, to)
 	}
@@ -233,6 +282,8 @@ func (from WordValue) Convert(to interface{}) error {
 			(*toPtr) = from.String()
 		case *WordValue:
 			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from			
 		default:
 			return NewErrorValuef("Cannot convert WordValue %v to %v", from, to)
 	}
@@ -245,7 +296,9 @@ func (from TypeValue) Convert(to interface{}) error {
 		case *string:
 			(*toPtr) = from.String()
 		case *TypeValue:
-			(*toPtr) = from			
+			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from
 		default:
 			return NewErrorValuef("Cannot convert value %v to %v", from, to)
 	}
@@ -258,7 +311,9 @@ func (from BoolValue) Convert(to interface{}) error {
 		case *bool:			 
 			(*toPtr) = bool(from) 		
 		case *BoolValue:
-			(*toPtr) = from		
+			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from												
 		default:
 			return NewErrorValuef("Cannot convert value %v to %v", from, to)
 	}
@@ -273,6 +328,8 @@ func (from ErrorValue) Convert(to interface{}) error {
 			(*toPtr) = from.error
 		case *ErrorValue:
 			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from			
 		default:
 			return NewErrorValuef("Cannot convert value %v to %v", from, to)
 	}
@@ -283,10 +340,28 @@ func (from EmptyValue) Convert(to interface{}) error {
 	return NewErrorValuef("Cannot convert the empty value %v to %v", from, to)
 }
 
-func (from ListValue) Convert(to interface{}) error {
+func (from * ListValue) Convert(to interface{}) error {
 	switch toPtr := to.(type) {
 		case *[]Value:
 			(*toPtr) = from.List
+		case **ListValue:
+			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from
+		default:
+			return NewErrorValuef("Cannot convert value %v to %v", from, to)
+	}
+	return nil
+}
+
+func (from * MapValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *map[Value]Value:
+			(*toPtr) = from.Map
+		case **MapValue:
+			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from			
 		default:
 			return NewErrorValuef("Cannot convert value %v to %v", from, to)
 	}

+ 47 - 16
vm.go

@@ -172,15 +172,28 @@ func (defined *DefinedValue) Help() string {
 
 /*
 	Amount of types that will be considered inside a signature.
-	Limited mosty to allow hashability.
+	Limited mosty to allow hashability, that is, Signature is a map key.
 */
-const TypesInSignature = 8
+const TypesInSignature = 32
 
 /* A signature describes the desired types of an overloaded function call. */
 type Signature struct {
 	Types [TypesInSignature]TypeValue
 }
 
+func (s Signature) String() string {
+	res := "["
+	sep := ""
+	for _, typ := range s.Types {
+		if typ != ZeroTypeValue { 
+			res = res + sep + typ.String()
+			sep = " "
+		}
+	}
+	res = res + "]"
+	return res
+}
+
 func CalculateSignature(arguments ...Value) Signature {
 	signature := Signature{}
 	for i := 0; i < len(signature.Types); i++ {
@@ -216,6 +229,7 @@ func (signature Signature) IsMatch(other Signature) bool {
 
 /* An overload is an overloaded value that can be called. */
 type Overload struct {
+	Name string
 	Caller
 }
 
@@ -231,7 +245,7 @@ type CoverValue struct {
 func (cv CoverValue) String() string {
 	res := fmt.Sprintf("cover %s [ ", cv.Name)
 	for k, v := range cv.Overloads {
-		res = fmt.Sprintf("%s [%v] %v", res, k, v.Caller)
+		res = fmt.Sprintf("%s [%v] %s", res, k, v.Name)
 	}
 	res = fmt.Sprintf("%s].", res)
 	return res;
@@ -247,11 +261,12 @@ func NewCoverValue(name string) *CoverValue {
 
 func (cover *CoverValue) Help() string {
 	help := cover.CallableValue.Help()
-	extra := ""
-	for signature, _ := range cover.Overloads {
-		extra = fmt.Sprintf("%s overloads: %v\n", extra, signature)
+	extra := "\n"
+	for signature, overload := range cover.Overloads {
+		// fmt.Printf("overload: %v", signature)
+		extra = extra + fmt.Sprintf("* %v -> %s\n", signature.String(), overload.Name)
 	}
-	return extra + help
+	return help + extra
 }
 
 
@@ -304,7 +319,7 @@ func (from BlockValue) Convert(to interface{}) error {
 }
 
 
-func (cv * CoverValue) AddOverload(callable Caller, tv ... TypeValue) error {
+func (cv * CoverValue) AddOverload(name string, callable Caller, tv ... TypeValue) error {
 	// fmt.Printf("AddOverload: %v\n", tv)
 	
 	signature := Signature{}
@@ -317,7 +332,7 @@ func (cv * CoverValue) AddOverload(callable Caller, tv ... TypeValue) error {
 		signature.Types[i] = tv[i]
 	}
 		
-	cv.Overloads[signature] = Overload { callable } 
+	cv.Overloads[signature] = Overload { Name: name, Caller: callable } 
 	
 	// fmt.Printf("Overloads: %v\n", cv.Overloads)
 	
@@ -346,12 +361,31 @@ func (vm * VM) AddOverload(from, target string, tv... TypeValue) error {
 	if callable, ok = lookup.(Caller) ; !ok {
 		return fmt.Errorf("%s is not a callable value", target)
 	}
-	res := cover.AddOverload(callable, tv...)
+	res := cover.AddOverload(target, callable, tv...)
 	
 	// fmt.Printf("AddOverload: %v %v\n", lookup, cover)
 	
 	return res
-} 
+}
+
+type OverloadDescription struct {
+	Target string
+	Types []TypeValue
+}
+
+func (vm * VM) AddOverloads(from string, descriptions ... OverloadDescription) error {
+	for _, od := range descriptions {
+		err := vm.AddOverload(from, od.Target, od.Types...)
+		if err != nil {
+			panic(fmt.Errorf("internal error: could not register overloads: %s", err))
+		}
+	}
+	return nil
+}
+
+func Over(target string, types ... TypeValue) OverloadDescription {
+	return OverloadDescription { Target: target, Types: types}
+}
 
 func (vm * VM) SetHelp(target, help string) error {
 	var helper Helper
@@ -448,10 +482,7 @@ func (scope* Scope) DefinedHelpers() []Helper {
 	scope.ForEachDefined(func (k string, v Value) (bool, error) {
 		helper, hok := v.(Helper)
 		if hok {
-			fmt.Printf("Helper: %s\n", helper.HelperName())
 			res = append(res, helper)
-		} else {
-			fmt.Printf("NOT Helper: %s\n", v.String())
 		}
 		return true, nil
 	})
@@ -522,8 +553,8 @@ func (vm *VM) PopScope() *Scope {
 	return nil
 }
 
-func (vm *VM) CallDefined(ast *Ast, arguments ...Value) []Value {
-	arr := ast.Run(vm, NewListValue(arguments...))
+func (vm *VM) CallDefined(ast *Ast, arguments ...Value) []Value {	
+	arr := vm.RunChildren(*ast, arguments...)
 	return arr
 }