diff --git a/source/err/errorfile.go b/source/err/errorfile.go index a8ac2d7a..0f6006b3 100644 --- a/source/err/errorfile.go +++ b/source/err/errorfile.go @@ -2585,6 +2585,26 @@ var ErrorCreatorMap = map[string]ErrorCreator{ }, }, + "vm/cast/a": { + Message: func(tok *token.Token, args ...any) string { + return "unable to perform cast" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "Types can only be cast between clones of the same parent, or the " + + "parent itself." + }, + }, + + "vm/cast/b": { + Message: func(tok *token.Token, args ...any) string { + return "unable to perform cast" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "Types can only be cast between clones of the same parent, or the " + + "parent itself." + }, + }, + "vm/div/float": { Message: func(tok *token.Token, args ...any) string { return "division by zero" @@ -2603,6 +2623,71 @@ var ErrorCreatorMap = map[string]ErrorCreator{ }, }, + "vm/for/type/a": { + Message: func(tok *token.Token, args ...any) string { + return "can't range over given type" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "You can range over lists, strings, maps, sets, and enums." + }, + }, + + "vm/for/type/b": { + Message: func(tok *token.Token, args ...any) string { + return "can't range over given type" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "You can range over lists, strings, maps, sets, and enums." + }, + }, + + "vm/for/type/c": { + Message: func(tok *token.Token, args ...any) string { + return "can't range over given type" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "You can range over lists, strings, maps, sets, and enums." + }, + }, + + "vm/for/pair": { + Message: func(tok *token.Token, args ...any) string { + return "range should be pair of integers" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "If you're going to give the range of a list using `::`, the elements of the pair should both be integers." + }, + }, + + "vm/func/args": { + Message: func(tok *token.Token, args ...any) string { + return "lambda function has the wrong number of arguments" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "The arguments passed are different in number from the parameters of the function." + }, + }, + + "vm/func/go": { + Message: func(tok *token.Token, args ...any) string { + return "failed to convert Pipefish value" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "You're trying to apply a Go lambda function (wrapped in a Pipefish " + + "lambda function), to something that Pipefish doesn't know how to convert " + + "into Go." + }, + }, + + "vm/func/types": { + Message: func(tok *token.Token, args ...any) string { + return "function has the wrong types" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "The arguments passed are different in type from the parameters of the function." + }, + }, + "vm/go/type": { Message: func(tok *token.Token, args ...any) string { return "can't convert Go value of type " + emph(args[0]) + " to Pipefish" @@ -2819,6 +2904,15 @@ var ErrorCreatorMap = map[string]ErrorCreator{ }, }, + "vm/index/q": { + Message: func(tok *token.Token, args ...any) string { + return fmt.Sprintf("out of range: can't index value of type %v by %v", emph(args[0]), emph(args[1])) + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return fmt.Sprintf("Pipefish just can't make sense of that at all.") + }, + }, + "vm/label/exist": { Message: func(tok *token.Token, args ...any) string { return fmt.Sprintf("can't convert string %v to a label", emphStr(args[0])) @@ -2846,6 +2940,16 @@ var ErrorCreatorMap = map[string]ErrorCreator{ }, }, + "vm/mf/lhs": { + Message: func(tok *token.Token, args ...any) string { + return "expected value of type 'list'" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "The value on the left-hand side of the operators '?>' and '>>' " + + "should always be of type 'list'." + }, + }, + "vm/mod/int": { Message: func(tok *token.Token, args ...any) string { return "taking the modulus of a number by zero" @@ -2855,6 +2959,15 @@ var ErrorCreatorMap = map[string]ErrorCreator{ }, }, + "vm/oopsie": { + Message: func(tok *token.Token, args ...any) string { + return "something unexpected has gone wrong" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "Please tell the author of Pipefish that he messed up. Thank you." + }, + }, + "vm/pipe/filter/bool": { Message: func(tok *token.Token, args ...any) string { return "right-hand side of filter expression cannot return boolean" @@ -3017,6 +3130,43 @@ var ErrorCreatorMap = map[string]ErrorCreator{ }, }, + "vm/splat/type": { + Message: func(tok *token.Token, args ...any) string { + return "expected value of type 'list'" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "The value on the left-hand side of the splat operator '...' " + + "should always be of type 'list'." + }, + }, + + "vm/tup/first": { + Message: func(tok *token.Token, args ...any) string { + return "trying to take the first element of an empty tuple" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "The empty tuple '()' has no first element." + }, + }, + + "vm/tup/last": { + Message: func(tok *token.Token, args ...any) string { + return "trying to take the last element of an empty tuple" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "The empty tuple '()' has no last element." + }, + }, + + "vm/typecheck": { + Message: func(tok *token.Token, args ...any) string { + return "failed typecheck" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "You placed constraints on the types of this expression which you then violated." + }, + }, + "vm/types/a": { Message: func(tok *token.Token, args ...any) string { return "No implementation of function " + emph(tok.Literal) + " exists for the given types" @@ -3053,6 +3203,16 @@ var ErrorCreatorMap = map[string]ErrorCreator{ }, }, + "vm/unwrap": { + Message: func(tok *token.Token, args ...any) string { + return "trying to unwrap something that isn't an 'error'" + }, + Explanation: func(errors Errors, pos int, tok *token.Token, args ...any) string { + return "The 'unwrap' function converts things of type 'error' into type 'Error': " + + "it doesn't work on anything else." + }, + }, + "vm/with/a": { Message: func(tok *token.Token, args ...any) string { return fmt.Sprintf("type %v found indexing list in %v expression where %v was expected", emph(args[0]), emph("with"), emph("int")) diff --git a/source/vm/vm.go b/source/vm/vm.go index 53415425..d5db3dfa 100644 --- a/source/vm/vm.go +++ b/source/vm/vm.go @@ -377,7 +377,7 @@ loop: pfArg := vm.Mem[pfMemLoc] goArg, ok := vm.pipefishToGo(pfArg) if !ok { - vm.Mem[args[0]] = values.Value{values.ERROR, err.CreateErr("vm/func/go", lambda.Tok, goArg)} // If the conversion failed, the goArg will be the Pipefish value it couldn't convert. + vm.Mem[args[0]] = values.Value{values.ERROR, err.CreateErr("vm/func/go", lambda.Tok, goArg)} // If the conversion failed, the goArg will be the value it couldn't convert. break Switch } goArgs = append(goArgs, reflect.ValueOf(goArg)) @@ -2043,7 +2043,7 @@ func (vm *Vm) NewIterator(container values.Value, keysOnly bool, tokLoc uint32) case values.TYPE: abTyp := container.V.(values.AbstractType) if len(abTyp.Types) != 1 { - return values.Value{values.ERROR, vm.makeError("vm/for/type/a", tokLoc)} + return values.Value{values.ERROR, vm.makeError("vm/for/type/a", tokLoc, )} } typ := abTyp.Types[0] if !vm.ConcreteTypeInfo[typ].IsEnum() { @@ -2055,7 +2055,7 @@ func (vm *Vm) NewIterator(container values.Value, keysOnly bool, tokLoc uint32) return values.Value{values.ITERATOR, &values.EnumIterator{Type: typ, Max: len(vm.ConcreteTypeInfo[typ].(EnumType).ElementNames)}} } default: - return values.Value{values.ERROR, vm.makeError("vm/for/type", tokLoc)} + return values.Value{values.ERROR, vm.makeError("vm/for/type/c", tokLoc)} } }