Jelajahi Sumber

Improve help a bit.

Beoran 5 tahun lalu
induk
melakukan
d1fb86969c
2 mengubah file dengan 101 tambahan dan 1 penghapusan
  1. 13 1
      builtin.go
  2. 88 0
      vm.go

+ 13 - 1
builtin.go

@@ -3,6 +3,8 @@ package muesli
 import "fmt"
 import "log"
 import "runtime"
+import "strings"
+import "sort"
 
 type LogTracer struct {
 }
@@ -284,7 +286,15 @@ func get(vm *VM, val ...Value) []Value {
 
 func help(vm *VM, val ...Value) [] Value {
 	if len(val) < 1 {
-		fmt.Printf("help <callable> will display help on the callable\n")
+		fmt.Printf("help <callable> will display help on the callable\n\nThe following commands are available:\n")
+		helpers := vm.DefinedHelpers()
+		sort.SliceStable(helpers, func(i, j int) bool {
+			return helpers[i].HelperName() < helpers[j].HelperName()
+		})
+		for _, helper := range helpers {
+			fl := strings.SplitN(helper.Help(),"\n", 2)
+			fmt.Printf("%s %s: \n", helper.HelperName(), fl[0])
+		}
 		return Ok()
 	}
 	targetName := val[0].String() 	
@@ -369,6 +379,8 @@ 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.") 
+	
 }
 
 

+ 88 - 0
vm.go

@@ -18,6 +18,7 @@ type Caller interface {
 // A helper Value has a help text available.
 // This help text can be set as well.
 type Helper interface {
+	HelperName() string
 	Help() string
 	SetHelp(string) string
 }
@@ -42,6 +43,11 @@ func (val * CallableValue) SetHelp(help string) string {
 	return val.HelpText
 }
 
+// Implement Helper interface
+func (val CallableValue) HelperName() string {
+	return val.Name
+}
+
 // AppendHelp appends help to an existing helper. 
 func AppendHelp(helper Helper, extra string) string {
 	return helper.SetHelp( helper.Help() + extra)
@@ -153,6 +159,17 @@ func (defined *DefinedValue) Call(vm *VM, arguments ...Value) []Value {
 
 }
 
+func (defined *DefinedValue) Help() string {
+	help := defined.CallableValue.Help()
+	extra := "["
+	for _, parameter := range defined.Parameters {
+		extra = fmt.Sprintf("%s %s %s", extra, parameter.Name, parameter.Type)
+	}
+	extra = extra + "]:"
+	return extra + help
+}
+
+
 /*
 	Amount of types that will be considered inside a signature.
 	Limited mosty to allow hashability.
@@ -227,6 +244,18 @@ func NewCoverValue(name string) *CoverValue {
 	return result
 }
 
+
+func (cover *CoverValue) Help() string {
+	help := cover.CallableValue.Help()
+	extra := ""
+	for signature, _ := range cover.Overloads {
+		extra = fmt.Sprintf("%s overloads: %v\n", extra, signature)
+	}
+	return extra + help
+}
+
+
+
 func (cover *CoverValue) Call(vm *VM, arguments ...Value) []Value {
 	signature := CalculateSignature(arguments...)
 	if overload, ok := cover.Overloads[signature]; ok {
@@ -377,6 +406,59 @@ func (scope *Scope) Register(name string, value Value) Value {
 	return value
 }
 
+func (scope * Scope) Known(filter func(string, Value) bool) map[string]Value {
+	res := make(map[string]Value)
+	if scope.parent != nil {
+		res = scope.parent.Known(filter)
+	}
+	for k, v := range scope.symbols {
+		if (filter == nil) || filter(k, v) {
+			res[k] = v
+		}
+	}
+	return res
+}
+
+func (scope * Scope) ForEachDefined(do func(string, Value) (bool, error)) (bool, error)  {
+	var res bool = true
+	var err error
+	
+	if (do == nil) {
+		return false, fmt.Errorf("do may not be nil")
+	}
+			
+	if scope.parent != nil {
+		res, err = scope.parent.ForEachDefined(do)
+	}
+	if res == false || err != nil {
+		return res, err
+	}
+	for k, v := range scope.symbols {
+		res, err = do(k, v)
+		if res == false || err != nil {
+			return res, err
+		}		
+	}
+	return res, err
+}
+
+
+func (scope* Scope) DefinedHelpers() []Helper {
+	res := []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
+	})
+	return res
+}
+
+
 // Frame of execution of a function
 type Frame struct {
 	parent    *Frame
@@ -601,6 +683,12 @@ func (vm *VM) RunAst(ast Ast, args ...Value) []Value {
 }
 
 
+func (vm *VM) DefinedHelpers() []Helper {
+	return vm.Scope.DefinedHelpers()
+}
+
+
+
 /*
 
 func (vm *VM) RunProgram(ast *BasicAst) ListValue {