Compare commits
	
		
			7 Commits
		
	
	
		
			1757298eb4
			...
			9fb611aa20
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9fb611aa20 | |||
| 56d6d06d15 | |||
| d9f7e5b1ad | |||
| 0f54e01ef3 | |||
| 63f5db00b3 | |||
| 9745a5d909 | |||
| 0bb4c96481 | 
| @ -67,7 +67,7 @@ func boolFunc(ctx ExprContext, name string, args []any) (result any, err error) | |||||||
| 	case string: | 	case string: | ||||||
| 		result = len(v) > 0 | 		result = len(v) > 0 | ||||||
| 	default: | 	default: | ||||||
| 		err = errCantConvert(name, v, "bool") | 		err = ErrCantConvert(name, v, "bool") | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| @ -90,7 +90,7 @@ func intFunc(ctx ExprContext, name string, args []any) (result any, err error) { | |||||||
| 			result = int64(i) | 			result = int64(i) | ||||||
| 		} | 		} | ||||||
| 	default: | 	default: | ||||||
| 		err = errCantConvert(name, v, "int") | 		err = ErrCantConvert(name, v, "int") | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| @ -115,7 +115,7 @@ func decFunc(ctx ExprContext, name string, args []any) (result any, err error) { | |||||||
| 	case *FractionType: | 	case *FractionType: | ||||||
| 		result = v.toFloat() | 		result = v.toFloat() | ||||||
| 	default: | 	default: | ||||||
| 		err = errCantConvert(name, v, "float") | 		err = ErrCantConvert(name, v, "float") | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| @ -127,9 +127,9 @@ func fractFunc(ctx ExprContext, name string, args []any) (result any, err error) | |||||||
| 		if len(args) > 1 { | 		if len(args) > 1 { | ||||||
| 			var ok bool | 			var ok bool | ||||||
| 			if den, ok = args[1].(int64); !ok { | 			if den, ok = args[1].(int64); !ok { | ||||||
| 				err = errExpectedGot(name, "integer", args[1]) | 				err = ErrExpectedGot(name, "integer", args[1]) | ||||||
| 			} else if den == 0 { | 			} else if den == 0 { | ||||||
| 				err = errFuncDivisionByZero(name) | 				err = ErrFuncDivisionByZero(name) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if err == nil { | 		if err == nil { | ||||||
| @ -148,7 +148,7 @@ func fractFunc(ctx ExprContext, name string, args []any) (result any, err error) | |||||||
| 	case *FractionType: | 	case *FractionType: | ||||||
| 		result = v | 		result = v | ||||||
| 	default: | 	default: | ||||||
| 		err = errCantConvert(name, v, "float") | 		err = ErrCantConvert(name, v, "float") | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ func doJoinStr(funcName string, sep string, it Iterator) (result any, err error) | |||||||
| 		if s, ok := v.(string); ok { | 		if s, ok := v.(string); ok { | ||||||
| 			sb.WriteString(s) | 			sb.WriteString(s) | ||||||
| 		} else { | 		} else { | ||||||
| 			err = errExpectedGot(funcName, TypeString, v) | 			err = ErrExpectedGot(funcName, TypeString, v) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @ -45,13 +45,13 @@ func joinStrFunc(ctx ExprContext, name string, args []any) (result any, err erro | |||||||
| 			} else if it, ok := args[1].(Iterator); ok { | 			} else if it, ok := args[1].(Iterator); ok { | ||||||
| 				result, err = doJoinStr(name, sep, it) | 				result, err = doJoinStr(name, sep, it) | ||||||
| 			} else { | 			} else { | ||||||
| 				err = errInvalidParameterValue(name, ParamParts, args[1]) | 				err = ErrInvalidParameterValue(name, ParamParts, args[1]) | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			result, err = doJoinStr(name, sep, NewArrayIterator(args[1:])) | 			result, err = doJoinStr(name, sep, NewArrayIterator(args[1:])) | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		err = errWrongParamType(name, ParamSeparator, TypeString, args[0]) | 		err = ErrWrongParamType(name, ParamSeparator, TypeString, args[0]) | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| @ -63,14 +63,14 @@ func subStrFunc(ctx ExprContext, name string, args []any) (result any, err error | |||||||
| 	var ok bool | 	var ok bool | ||||||
| 
 | 
 | ||||||
| 	if source, ok = args[0].(string); !ok { | 	if source, ok = args[0].(string); !ok { | ||||||
| 		return nil, errWrongParamType(name, ParamSource, TypeString, args[0]) | 		return nil, ErrWrongParamType(name, ParamSource, TypeString, args[0]) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if start, err = toInt(args[1], name+"()"); err != nil { | 	if start, err = ToInt(args[1], name+"()"); err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if count, err = toInt(args[2], name+"()"); err != nil { | 	if count, err = ToInt(args[2], name+"()"); err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -91,7 +91,7 @@ func trimStrFunc(ctx ExprContext, name string, args []any) (result any, err erro | |||||||
| 	var ok bool | 	var ok bool | ||||||
| 
 | 
 | ||||||
| 	if source, ok = args[0].(string); !ok { | 	if source, ok = args[0].(string); !ok { | ||||||
| 		return nil, errWrongParamType(name, ParamSource, TypeString, args[0]) | 		return nil, ErrWrongParamType(name, ParamSource, TypeString, args[0]) | ||||||
| 	} | 	} | ||||||
| 	result = strings.TrimSpace(source) | 	result = strings.TrimSpace(source) | ||||||
| 	return | 	return | ||||||
| @ -104,7 +104,7 @@ func startsWithStrFunc(ctx ExprContext, name string, args []any) (result any, er | |||||||
| 	result = false | 	result = false | ||||||
| 
 | 
 | ||||||
| 	if source, ok = args[0].(string); !ok { | 	if source, ok = args[0].(string); !ok { | ||||||
| 		return result, errWrongParamType(name, ParamSource, TypeString, args[0]) | 		return result, ErrWrongParamType(name, ParamSource, TypeString, args[0]) | ||||||
| 	} | 	} | ||||||
| 	for i, targetSpec := range args[1:] { | 	for i, targetSpec := range args[1:] { | ||||||
| 		if target, ok := targetSpec.(string); ok { | 		if target, ok := targetSpec.(string); ok { | ||||||
| @ -127,7 +127,7 @@ func endsWithStrFunc(ctx ExprContext, name string, args []any) (result any, err | |||||||
| 	result = false | 	result = false | ||||||
| 
 | 
 | ||||||
| 	if source, ok = args[0].(string); !ok { | 	if source, ok = args[0].(string); !ok { | ||||||
| 		return result, errWrongParamType(name, ParamSource, TypeString, args[0]) | 		return result, ErrWrongParamType(name, ParamSource, TypeString, args[0]) | ||||||
| 	} | 	} | ||||||
| 	for i, targetSpec := range args[1:] { | 	for i, targetSpec := range args[1:] { | ||||||
| 		if target, ok := targetSpec.(string); ok { | 		if target, ok := targetSpec.(string); ok { | ||||||
| @ -150,7 +150,7 @@ func splitStrFunc(ctx ExprContext, name string, args []any) (result any, err err | |||||||
| 	var ok bool | 	var ok bool | ||||||
| 
 | 
 | ||||||
| 	if source, ok = args[0].(string); !ok { | 	if source, ok = args[0].(string); !ok { | ||||||
| 		return result, errWrongParamType(name, ParamSource, TypeString, args[0]) | 		return result, ErrWrongParamType(name, ParamSource, TypeString, args[0]) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if sep, ok = args[1].(string); !ok { | 	if sep, ok = args[1].(string); !ok { | ||||||
| @ -182,34 +182,34 @@ func splitStrFunc(ctx ExprContext, name string, args []any) (result any, err err | |||||||
| 
 | 
 | ||||||
| // Import above functions in the context
 | // Import above functions in the context
 | ||||||
| func ImportStringFuncs(ctx ExprContext) { | func ImportStringFuncs(ctx ExprContext) { | ||||||
| 	ctx.RegisterFunc("joinStr", NewGolangFunctor(joinStrFunc), TypeString, []ExprFuncParam{ | 	ctx.RegisterFunc("strJoin", NewGolangFunctor(joinStrFunc), TypeString, []ExprFuncParam{ | ||||||
| 		NewFuncParam(ParamSeparator), | 		NewFuncParam(ParamSeparator), | ||||||
| 		NewFuncParamFlag(ParamItem, PfRepeat), | 		NewFuncParamFlag(ParamItem, PfRepeat), | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	ctx.RegisterFunc("subStr", NewGolangFunctor(subStrFunc), TypeString, []ExprFuncParam{ | 	ctx.RegisterFunc("strSub", NewGolangFunctor(subStrFunc), TypeString, []ExprFuncParam{ | ||||||
| 		NewFuncParam(ParamSource), | 		NewFuncParam(ParamSource), | ||||||
| 		NewFuncParamFlagDef(ParamStart, PfDefault, int64(0)), | 		NewFuncParamFlagDef(ParamStart, PfDefault, int64(0)), | ||||||
| 		NewFuncParamFlagDef(ParamCount, PfDefault, int64(-1)), | 		NewFuncParamFlagDef(ParamCount, PfDefault, int64(-1)), | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	ctx.RegisterFunc("splitStr", NewGolangFunctor(splitStrFunc), "list of "+TypeString, []ExprFuncParam{ | 	ctx.RegisterFunc("strSplit", NewGolangFunctor(splitStrFunc), "list of "+TypeString, []ExprFuncParam{ | ||||||
| 		NewFuncParam(ParamSource), | 		NewFuncParam(ParamSource), | ||||||
| 		NewFuncParamFlagDef(ParamSeparator, PfDefault, ""), | 		NewFuncParamFlagDef(ParamSeparator, PfDefault, ""), | ||||||
| 		NewFuncParamFlagDef(ParamCount, PfDefault, int64(-1)), | 		NewFuncParamFlagDef(ParamCount, PfDefault, int64(-1)), | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	ctx.RegisterFunc("trimStr", NewGolangFunctor(trimStrFunc), TypeString, []ExprFuncParam{ | 	ctx.RegisterFunc("strTrim", NewGolangFunctor(trimStrFunc), TypeString, []ExprFuncParam{ | ||||||
| 		NewFuncParam(ParamSource), | 		NewFuncParam(ParamSource), | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	ctx.RegisterFunc("startsWithStr", NewGolangFunctor(startsWithStrFunc), TypeBoolean, []ExprFuncParam{ | 	ctx.RegisterFunc("strStartsWith", NewGolangFunctor(startsWithStrFunc), TypeBoolean, []ExprFuncParam{ | ||||||
| 		NewFuncParam(ParamSource), | 		NewFuncParam(ParamSource), | ||||||
| 		NewFuncParam(ParamPrefix), | 		NewFuncParam(ParamPrefix), | ||||||
| 		NewFuncParamFlag("other "+ParamPrefix, PfRepeat), | 		NewFuncParamFlag("other "+ParamPrefix, PfRepeat), | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	ctx.RegisterFunc("endsWithStr", NewGolangFunctor(endsWithStrFunc), TypeBoolean, []ExprFuncParam{ | 	ctx.RegisterFunc("strEndsWith", NewGolangFunctor(endsWithStrFunc), TypeBoolean, []ExprFuncParam{ | ||||||
| 		NewFuncParam(ParamSource), | 		NewFuncParam(ParamSource), | ||||||
| 		NewFuncParam(ParamSuffix), | 		NewFuncParam(ParamSuffix), | ||||||
| 		NewFuncParamFlag("other "+ParamSuffix, PfRepeat), | 		NewFuncParamFlag("other "+ParamSuffix, PfRepeat), | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func errTooFewParams(funcName string, minArgs, maxArgs, argCount int) (err error) { | func ErrTooFewParams(funcName string, minArgs, maxArgs, argCount int) (err error) { | ||||||
| 	if maxArgs < 0 { | 	if maxArgs < 0 { | ||||||
| 		err = fmt.Errorf("%s(): too few params -- expected %d or more, got %d", funcName, minArgs, argCount) | 		err = fmt.Errorf("%s(): too few params -- expected %d or more, got %d", funcName, minArgs, argCount) | ||||||
| 	} else { | 	} else { | ||||||
| @ -17,39 +17,39 @@ func errTooFewParams(funcName string, minArgs, maxArgs, argCount int) (err error | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func errTooMuchParams(funcName string, maxArgs, argCount int) (err error) { | func ErrTooMuchParams(funcName string, maxArgs, argCount int) (err error) { | ||||||
| 	err = fmt.Errorf("%s(): too much params -- expected %d, got %d", funcName, maxArgs, argCount) | 	err = fmt.Errorf("%s(): too much params -- expected %d, got %d", funcName, maxArgs, argCount) | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // --- General errors
 | // --- General errors
 | ||||||
| 
 | 
 | ||||||
| func errCantConvert(funcName string, value any, kind string) error { | func ErrCantConvert(funcName string, value any, kind string) error { | ||||||
| 	return fmt.Errorf("%s(): can't convert %s to %s", funcName, TypeName(value), kind) | 	return fmt.Errorf("%s(): can't convert %s to %s", funcName, TypeName(value), kind) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func errExpectedGot(funcName string, kind string, value any) error { | func ErrExpectedGot(funcName string, kind string, value any) error { | ||||||
| 	return fmt.Errorf("%s() expected %s, got %s (%v)", funcName, kind, TypeName(value), value) | 	return fmt.Errorf("%s(): expected %s, got %s (%v)", funcName, kind, TypeName(value), value) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func errFuncDivisionByZero(funcName string) error { | func ErrFuncDivisionByZero(funcName string) error { | ||||||
| 	return fmt.Errorf("%s(): division by zero", funcName) | 	return fmt.Errorf("%s(): division by zero", funcName) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func errDivisionByZero() error { | func ErrDivisionByZero() error { | ||||||
| 	return fmt.Errorf("division by zero") | 	return fmt.Errorf("division by zero") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // --- Parameter errors
 | // --- Parameter errors
 | ||||||
| 
 | 
 | ||||||
| func errMissingRequiredParameter(funcName, paramName string) error { | func ErrMissingRequiredParameter(funcName, paramName string) error { | ||||||
| 	return fmt.Errorf("%s() missing required parameter %q", funcName, paramName) | 	return fmt.Errorf("%s(): missing required parameter %q", funcName, paramName) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func errInvalidParameterValue(funcName, paramName string, paramValue any) error { | func ErrInvalidParameterValue(funcName, paramName string, paramValue any) error { | ||||||
| 	return fmt.Errorf("%s() invalid value %s (%v) for parameter %q", funcName, TypeName(paramValue), paramValue, paramName) | 	return fmt.Errorf("%s(): invalid value %s (%v) for parameter %q", funcName, TypeName(paramValue), paramValue, paramName) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func errWrongParamType(funcName, paramName, paramType string, paramValue any) error { | func ErrWrongParamType(funcName, paramName, paramType string, paramValue any) error { | ||||||
| 	return fmt.Errorf("%s() the %q parameter must be a %s, got a %s (%v)", funcName, paramName, paramType, TypeName(paramValue), paramValue) | 	return fmt.Errorf("%s(): the %q parameter must be a %s, got a %s (%v)", funcName, paramName, paramType, TypeName(paramValue), paramValue) | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										34
									
								
								dict-type.go
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								dict-type.go
									
									
									
									
									
								
							| @ -32,9 +32,16 @@ func newDict(dictAny map[any]*term) (dict *DictType) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (dict *DictType) toMultiLine(sb *strings.Builder, indent int) { | func (dict *DictType) toMultiLine(sb *strings.Builder, opt FmtOpt) { | ||||||
| 	sb.WriteString(strings.Repeat("\t", indent)) | 	indent := GetFormatIndent(opt) | ||||||
| 	sb.WriteString("{\n") | 	flags := GetFormatFlags(opt) | ||||||
|  | 	//sb.WriteString(strings.Repeat("  ", indent))
 | ||||||
|  | 	sb.WriteByte('{') | ||||||
|  | 
 | ||||||
|  | 	if len(*dict) > 0 { | ||||||
|  | 		innerOpt := MakeFormatOptions(flags, indent+1) | ||||||
|  | 		nest := strings.Repeat("  ", indent+1) | ||||||
|  | 		sb.WriteByte('\n') | ||||||
| 
 | 
 | ||||||
| 		first := true | 		first := true | ||||||
| 		for name, value := range *dict { | 		for name, value := range *dict { | ||||||
| @ -45,7 +52,7 @@ func (dict *DictType) toMultiLine(sb *strings.Builder, indent int) { | |||||||
| 				sb.WriteByte('\n') | 				sb.WriteByte('\n') | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 		sb.WriteString(strings.Repeat("\t", indent+1)) | 			sb.WriteString(nest) | ||||||
| 			if key, ok := name.(string); ok { | 			if key, ok := name.(string); ok { | ||||||
| 				sb.WriteString(string('"') + key + string('"')) | 				sb.WriteString(string('"') + key + string('"')) | ||||||
| 			} else { | 			} else { | ||||||
| @ -53,21 +60,24 @@ func (dict *DictType) toMultiLine(sb *strings.Builder, indent int) { | |||||||
| 			} | 			} | ||||||
| 			sb.WriteString(": ") | 			sb.WriteString(": ") | ||||||
| 			if f, ok := value.(Formatter); ok { | 			if f, ok := value.(Formatter); ok { | ||||||
| 			sb.WriteString(f.ToString(MultiLine)) | 				sb.WriteString(f.ToString(innerOpt)) | ||||||
| 			} else if _, ok = value.(Functor); ok { | 			} else if _, ok = value.(Functor); ok { | ||||||
| 				sb.WriteString("func(){}") | 				sb.WriteString("func(){}") | ||||||
| 			} else { | 			} else { | ||||||
| 				sb.WriteString(fmt.Sprintf("%v", value)) | 				sb.WriteString(fmt.Sprintf("%v", value)) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	sb.WriteString(strings.Repeat("\t", indent)) | 		sb.WriteByte('\n') | ||||||
| 	sb.WriteString("\n}") | 		sb.WriteString(strings.Repeat("  ", indent)) | ||||||
|  | 	} | ||||||
|  | 	sb.WriteString("}") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (dict *DictType) ToString(opt FmtOpt) string { | func (dict *DictType) ToString(opt FmtOpt) string { | ||||||
| 	var sb strings.Builder | 	var sb strings.Builder | ||||||
| 	if opt&MultiLine != 0 { | 	flags := GetFormatFlags(opt) | ||||||
| 		dict.toMultiLine(&sb, 0) | 	if flags&MultiLine != 0 { | ||||||
|  | 		dict.toMultiLine(&sb, opt) | ||||||
| 	} else { | 	} else { | ||||||
| 		sb.WriteByte('{') | 		sb.WriteByte('{') | ||||||
| 		first := true | 		first := true | ||||||
| @ -133,3 +143,9 @@ func (dict *DictType) setItem(key any, value any) (err error) { | |||||||
| 	(*dict)[key] = value | 	(*dict)[key] = value | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | ////////////////
 | ||||||
|  | 
 | ||||||
|  | type DictFormat interface { | ||||||
|  | 	ToDict() *DictType | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								formatter.go
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								formatter.go
									
									
									
									
									
								
							| @ -6,7 +6,7 @@ package expr | |||||||
| 
 | 
 | ||||||
| import "fmt" | import "fmt" | ||||||
| 
 | 
 | ||||||
| type FmtOpt uint16 | type FmtOpt uint32 // lower 16 bits hold a bit-mask, higher 16 bits hold an indentation number
 | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	TTY FmtOpt = 1 << iota | 	TTY FmtOpt = 1 << iota | ||||||
| @ -30,6 +30,18 @@ func TruncateString(s string) (trunc string) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func MakeFormatOptions(flags FmtOpt, indent int) FmtOpt { | ||||||
|  | 	return FmtOpt(indent<<16) | flags | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func GetFormatFlags(opt FmtOpt) FmtOpt { | ||||||
|  | 	return opt & 0xFFFF | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func GetFormatIndent(opt FmtOpt) int { | ||||||
|  | 	return int(opt >> 16) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| type Formatter interface { | type Formatter interface { | ||||||
| 	ToString(options FmtOpt) string | 	ToString(options FmtOpt) string | ||||||
| } | } | ||||||
|  | |||||||
| @ -70,7 +70,7 @@ func makeGeneratingFraction(s string) (f *FractionType, err error) { | |||||||
| 			} | 			} | ||||||
| 			for _, c := range dec[0:lsd] { | 			for _, c := range dec[0:lsd] { | ||||||
| 				if c < '0' || c > '9' { | 				if c < '0' || c > '9' { | ||||||
| 					return nil, errExpectedGot("fract", "digit", c) | 					return nil, ErrExpectedGot("fract", "digit", c) | ||||||
| 				} | 				} | ||||||
| 				num = num*10 + int64(c-'0') | 				num = num*10 + int64(c-'0') | ||||||
| 				den = den * 10 | 				den = den * 10 | ||||||
| @ -81,7 +81,7 @@ func makeGeneratingFraction(s string) (f *FractionType, err error) { | |||||||
| 			mul := int64(1) | 			mul := int64(1) | ||||||
| 			for _, c := range subParts[0] { | 			for _, c := range subParts[0] { | ||||||
| 				if c < '0' || c > '9' { | 				if c < '0' || c > '9' { | ||||||
| 					return nil, errExpectedGot("fract", "digit", c) | 					return nil, ErrExpectedGot("fract", "digit", c) | ||||||
| 				} | 				} | ||||||
| 				num = num*10 + int64(c-'0') | 				num = num*10 + int64(c-'0') | ||||||
| 				sub = sub*10 + int64(c-'0') | 				sub = sub*10 + int64(c-'0') | ||||||
| @ -94,7 +94,7 @@ func makeGeneratingFraction(s string) (f *FractionType, err error) { | |||||||
| 				p := subParts[1][0 : len(subParts[1])-1] | 				p := subParts[1][0 : len(subParts[1])-1] | ||||||
| 				for _, c := range p { | 				for _, c := range p { | ||||||
| 					if c < '0' || c > '9' { | 					if c < '0' || c > '9' { | ||||||
| 						return nil, errExpectedGot("fract", "digit", c) | 						return nil, ErrExpectedGot("fract", "digit", c) | ||||||
| 					} | 					} | ||||||
| 					num = num*10 + int64(c-'0') | 					num = num*10 + int64(c-'0') | ||||||
| 					den = den*10 + 9 | 					den = den*10 + 9 | ||||||
| @ -212,7 +212,7 @@ func anyToFract(v any) (f *FractionType, err error) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if f == nil { | 	if f == nil { | ||||||
| 		err = errExpectedGot("fract", TypeFraction, v) | 		err = ErrExpectedGot("fract", TypeFraction, v) | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ func (functor *baseFunctor) ToString(opt FmtOpt) (s string) { | |||||||
| 	if functor.info != nil { | 	if functor.info != nil { | ||||||
| 		s = functor.info.ToString(opt) | 		s = functor.info.ToString(opt) | ||||||
| 	} else { | 	} else { | ||||||
| 		s = "func() {<body>}" | 		s = "func() {}" | ||||||
| 	} | 	} | ||||||
| 	return s | 	return s | ||||||
| } | } | ||||||
| @ -180,7 +180,7 @@ func (info *funcInfo) ToString(opt FmtOpt) string { | |||||||
| 	} else { | 	} else { | ||||||
| 		sb.WriteString(TypeAny) | 		sb.WriteString(TypeAny) | ||||||
| 	} | 	} | ||||||
| 	sb.WriteString(" {<body>}") | 	sb.WriteString(" {}") | ||||||
| 	return sb.String() | 	return sb.String() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -26,21 +26,21 @@ func NewListIterator(list *ListType, args []any) (it *ListIterator) { | |||||||
| 	} | 	} | ||||||
| 	it = &ListIterator{a: list, count: 0, index: -1, start: 0, stop: listLen - 1, step: 1} | 	it = &ListIterator{a: list, count: 0, index: -1, start: 0, stop: listLen - 1, step: 1} | ||||||
| 	if argc >= 1 { | 	if argc >= 1 { | ||||||
| 		if i, err := toInt(args[0], "start index"); err == nil { | 		if i, err := ToInt(args[0], "start index"); err == nil { | ||||||
| 			if i < 0 { | 			if i < 0 { | ||||||
| 				i = listLen + i | 				i = listLen + i | ||||||
| 			} | 			} | ||||||
| 			it.start = i | 			it.start = i | ||||||
| 		} | 		} | ||||||
| 		if argc >= 2 { | 		if argc >= 2 { | ||||||
| 			if i, err := toInt(args[1], "stop index"); err == nil { | 			if i, err := ToInt(args[1], "stop index"); err == nil { | ||||||
| 				if i < 0 { | 				if i < 0 { | ||||||
| 					i = listLen + i | 					i = listLen + i | ||||||
| 				} | 				} | ||||||
| 				it.stop = i | 				it.stop = i | ||||||
| 			} | 			} | ||||||
| 			if argc >= 3 { | 			if argc >= 3 { | ||||||
| 				if i, err := toInt(args[2], "step"); err == nil { | 				if i, err := ToInt(args[2], "step"); err == nil { | ||||||
| 					if i < 0 { | 					if i < 0 { | ||||||
| 						i = -i | 						i = -i | ||||||
| 					} | 					} | ||||||
|  | |||||||
							
								
								
									
										23
									
								
								list-type.go
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								list-type.go
									
									
									
									
									
								
							| @ -52,16 +52,24 @@ func ListFromStrings(stringList []string) (list *ListType) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (ls *ListType) ToString(opt FmtOpt) (s string) { | func (ls *ListType) ToString(opt FmtOpt) (s string) { | ||||||
|  |         indent := GetFormatIndent(opt) | ||||||
|  |         flags := GetFormatFlags(opt) | ||||||
|  | 
 | ||||||
| 	var sb strings.Builder | 	var sb strings.Builder | ||||||
| 	sb.WriteByte('[') | 	sb.WriteByte('[') | ||||||
| 	if len(*ls) > 0 { | 	if len(*ls) > 0 { | ||||||
| 		if opt&MultiLine != 0 { |                 innerOpt := MakeFormatOptions(flags, indent+1) | ||||||
| 			sb.WriteString("\n  ") |                 nest := strings.Repeat("  ", indent+1) | ||||||
|  | 
 | ||||||
|  | 		if flags&MultiLine != 0 { | ||||||
|  | 			sb.WriteByte('\n') | ||||||
|  | 			sb.WriteString(nest) | ||||||
| 		} | 		} | ||||||
| 		for i, item := range []any(*ls) { | 		for i, item := range []any(*ls) { | ||||||
| 			if i > 0 { | 			if i > 0 { | ||||||
| 				if opt&MultiLine != 0 { | 				if flags&MultiLine != 0 { | ||||||
| 					sb.WriteString(",\n  ") | 					sb.WriteString(",\n") | ||||||
|  | 					sb.WriteString(nest) | ||||||
| 				} else { | 				} else { | ||||||
| 					sb.WriteString(", ") | 					sb.WriteString(", ") | ||||||
| 				} | 				} | ||||||
| @ -70,17 +78,20 @@ func (ls *ListType) ToString(opt FmtOpt) (s string) { | |||||||
| 				sb.WriteByte('"') | 				sb.WriteByte('"') | ||||||
| 				sb.WriteString(s) | 				sb.WriteString(s) | ||||||
| 				sb.WriteByte('"') | 				sb.WriteByte('"') | ||||||
|  | 			} else if formatter, ok := item.(Formatter); ok { | ||||||
|  | 				sb.WriteString(formatter.ToString(innerOpt)) | ||||||
| 			} else { | 			} else { | ||||||
| 				sb.WriteString(fmt.Sprintf("%v", item)) | 				sb.WriteString(fmt.Sprintf("%v", item)) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if opt&MultiLine != 0 { | 		if flags&MultiLine != 0 { | ||||||
| 			sb.WriteByte('\n') | 			sb.WriteByte('\n') | ||||||
|  | 			sb.WriteString(strings.Repeat("  ", indent)) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	sb.WriteByte(']') | 	sb.WriteByte(']') | ||||||
| 	s = sb.String() | 	s = sb.String() | ||||||
| 	if opt&Truncate != 0 && len(s) > TruncateSize { | 	if flags&Truncate != 0 && len(s) > TruncateSize { | ||||||
| 		s = TruncateString(s) | 		s = TruncateString(s) | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
|  | |||||||
| @ -26,7 +26,7 @@ func checkFunctionCall(ctx ExprContext, name string, varParams *[]any) (err erro | |||||||
| 	if info, exists, owner := GetFuncInfo(ctx, name); exists { | 	if info, exists, owner := GetFuncInfo(ctx, name); exists { | ||||||
| 		passedCount := len(*varParams) | 		passedCount := len(*varParams) | ||||||
| 		if info.MinArgs() > passedCount { | 		if info.MinArgs() > passedCount { | ||||||
| 			err = errTooFewParams(name, info.MinArgs(), info.MaxArgs(), passedCount) | 			err = ErrTooFewParams(name, info.MinArgs(), info.MaxArgs(), passedCount) | ||||||
| 		} | 		} | ||||||
| 		for i, p := range info.Params() { | 		for i, p := range info.Params() { | ||||||
| 			if i >= passedCount { | 			if i >= passedCount { | ||||||
| @ -37,7 +37,7 @@ func checkFunctionCall(ctx ExprContext, name string, varParams *[]any) (err erro | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if err == nil && info.MaxArgs() >= 0 && info.MaxArgs() < len(*varParams) { | 		if err == nil && info.MaxArgs() >= 0 && info.MaxArgs() < len(*varParams) { | ||||||
| 			err = errTooMuchParams(name, info.MaxArgs(), len(*varParams)) | 			err = ErrTooMuchParams(name, info.MaxArgs(), len(*varParams)) | ||||||
| 		} | 		} | ||||||
| 		if err == nil && owner != ctx { | 		if err == nil && owner != ctx { | ||||||
| 			ctx.RegisterFuncInfo(info) | 			ctx.RegisterFuncInfo(info) | ||||||
|  | |||||||
| @ -25,7 +25,7 @@ func evalNot(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if b, ok := toBool(rightValue); ok { | 	if b, ok := ToBool(rightValue); ok { | ||||||
| 		v = !b | 		v = !b | ||||||
| 	} else { | 	} else { | ||||||
| 		err = self.errIncompatibleType(rightValue) | 		err = self.errIncompatibleType(rightValue) | ||||||
| @ -65,8 +65,8 @@ func evalAndWithoutShortcut(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	leftBool, lok = toBool(leftValue) | 	leftBool, lok = ToBool(leftValue) | ||||||
| 	rightBool, rok = toBool(rightValue) | 	rightBool, rok = ToBool(rightValue) | ||||||
| 
 | 
 | ||||||
| 	if lok && rok { | 	if lok && rok { | ||||||
| 		v = leftBool && rightBool | 		v = leftBool && rightBool | ||||||
| @ -87,13 +87,13 @@ func evalAndWithShortcut(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if leftBool, lok := toBool(leftValue); !lok { | 	if leftBool, lok := ToBool(leftValue); !lok { | ||||||
| 		err = fmt.Errorf("got %T as left operand type of 'and' operator, it must be bool", leftBool) | 		err = fmt.Errorf("got %T as left operand type of 'and' operator, it must be bool", leftBool) | ||||||
| 		return | 		return | ||||||
| 	} else if !leftBool { | 	} else if !leftBool { | ||||||
| 		v = false | 		v = false | ||||||
| 	} else if rightValue, err = self.children[1].compute(ctx); err == nil { | 	} else if rightValue, err = self.children[1].compute(ctx); err == nil { | ||||||
| 		if rightBool, rok := toBool(rightValue); rok { | 		if rightBool, rok := ToBool(rightValue); rok { | ||||||
| 			v = rightBool | 			v = rightBool | ||||||
| 		} else { | 		} else { | ||||||
| 			err = self.errIncompatibleTypes(leftValue, rightValue) | 			err = self.errIncompatibleTypes(leftValue, rightValue) | ||||||
| @ -134,8 +134,8 @@ func evalOrWithoutShortcut(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	leftBool, lok = toBool(leftValue) | 	leftBool, lok = ToBool(leftValue) | ||||||
| 	rightBool, rok = toBool(rightValue) | 	rightBool, rok = ToBool(rightValue) | ||||||
| 
 | 
 | ||||||
| 	if lok && rok { | 	if lok && rok { | ||||||
| 		v = leftBool || rightBool | 		v = leftBool || rightBool | ||||||
| @ -156,13 +156,13 @@ func evalOrWithShortcut(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if leftBool, lok := toBool(leftValue); !lok { | 	if leftBool, lok := ToBool(leftValue); !lok { | ||||||
| 		err = fmt.Errorf("got %T as left operand type of 'or' operator, it must be bool", leftBool) | 		err = fmt.Errorf("got %T as left operand type of 'or' operator, it must be bool", leftBool) | ||||||
| 		return | 		return | ||||||
| 	} else if leftBool { | 	} else if leftBool { | ||||||
| 		v = true | 		v = true | ||||||
| 	} else if rightValue, err = self.children[1].compute(ctx); err == nil { | 	} else if rightValue, err = self.children[1].compute(ctx); err == nil { | ||||||
| 		if rightBool, rok := toBool(rightValue); rok { | 		if rightBool, rok := ToBool(rightValue); rok { | ||||||
| 			v = rightBool | 			v = rightBool | ||||||
| 		} else { | 		} else { | ||||||
| 			err = self.errIncompatibleTypes(leftValue, rightValue) | 			err = self.errIncompatibleTypes(leftValue, rightValue) | ||||||
|  | |||||||
| @ -31,7 +31,9 @@ func evalContextValue(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if sourceCtx != nil { | 	if sourceCtx != nil { | ||||||
| 		if formatter, ok := sourceCtx.(Formatter); ok { | 		if formatter, ok := sourceCtx.(DictFormat); ok { | ||||||
|  | 			v = formatter.ToDict() | ||||||
|  | 		} else if formatter, ok := sourceCtx.(Formatter); ok { | ||||||
| 			v = formatter.ToString(0) | 			v = formatter.ToString(0) | ||||||
| 		} else { | 		} else { | ||||||
| 			// keys := sourceCtx.EnumVars(func(name string) bool { return name[0] != '_' })
 | 			// keys := sourceCtx.EnumVars(func(name string) bool { return name[0] != '_' })
 | ||||||
|  | |||||||
| @ -23,7 +23,7 @@ func verifyKey(indexTerm *term, indexList *ListType) (index any, err error) { | |||||||
| func verifyIndex(indexTerm *term, indexList *ListType, maxValue int) (index int, err error) { | func verifyIndex(indexTerm *term, indexList *ListType, maxValue int) (index int, err error) { | ||||||
| 	var v int | 	var v int | ||||||
| 
 | 
 | ||||||
| 	if v, err = toInt((*indexList)[0], "index expression"); err == nil { | 	if v, err = ToInt((*indexList)[0], "index expression"); err == nil { | ||||||
| 		if v < 0 && v >= -maxValue { | 		if v < 0 && v >= -maxValue { | ||||||
| 			v = maxValue + v | 			v = maxValue + v | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -36,7 +36,7 @@ func evalLength(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 	} else if it, ok := childValue.(Iterator); ok { | 	} else if it, ok := childValue.(Iterator); ok { | ||||||
| 		if extIt, ok := childValue.(ExtIterator); ok && extIt.HasOperation(countName) { | 		if extIt, ok := childValue.(ExtIterator); ok && extIt.HasOperation(countName) { | ||||||
| 			count, _ := extIt.CallOperation(countName, nil) | 			count, _ := extIt.CallOperation(countName, nil) | ||||||
| 			v, _ = toInt(count, "") | 			v, _ = ToInt(count, "") | ||||||
| 		} else { | 		} else { | ||||||
| 			v = int64(it.Index() + 1) | 			v = int64(it.Index() + 1) | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -70,7 +70,7 @@ func newNotEqualTerm(tk *Token) (inst *term) { | |||||||
| 
 | 
 | ||||||
| func evalNotEqual(ctx ExprContext, self *term) (v any, err error) { | func evalNotEqual(ctx ExprContext, self *term) (v any, err error) { | ||||||
| 	if v, err = evalEqual(ctx, self); err == nil { | 	if v, err = evalEqual(ctx, self); err == nil { | ||||||
| 		b, _ := toBool(v) | 		b, _ := ToBool(v) | ||||||
| 		v = !b | 		v = !b | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								scanner.go
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								scanner.go
									
									
									
									
									
								
							| @ -178,13 +178,18 @@ func (self *scanner) fetchNextToken() (tk *Token) { | |||||||
| 				tk = self.makeToken(SymDot, ch) | 				tk = self.makeToken(SymDot, ch) | ||||||
| 			} | 			} | ||||||
| 		case '\'': | 		case '\'': | ||||||
|  | 			if escape { | ||||||
| 				tk = self.makeToken(SymQuote, ch) | 				tk = self.makeToken(SymQuote, ch) | ||||||
|  | 				escape = false | ||||||
|  | 			} else { | ||||||
|  | 				tk = self.fetchString(ch) | ||||||
|  | 			} | ||||||
| 		case '"': | 		case '"': | ||||||
| 			if escape { | 			if escape { | ||||||
| 				tk = self.makeToken(SymDoubleQuote, ch) | 				tk = self.makeToken(SymDoubleQuote, ch) | ||||||
| 				escape = false | 				escape = false | ||||||
| 			} else { | 			} else { | ||||||
| 				tk = self.fetchString() | 				tk = self.fetchString(ch) | ||||||
| 			} | 			} | ||||||
| 		case '`': | 		case '`': | ||||||
| 			tk = self.makeToken(SymBackTick, ch) | 			tk = self.makeToken(SymBackTick, ch) | ||||||
| @ -533,7 +538,7 @@ func (self *scanner) fetchUntil(sym Symbol, allowEos bool, endings ...byte) (tk | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (self *scanner) fetchString() (tk *Token) { | func (self *scanner) fetchString(termCh byte) (tk *Token) { | ||||||
| 	var err error | 	var err error | ||||||
| 	var ch, prev byte | 	var ch, prev byte | ||||||
| 	var sb strings.Builder | 	var sb strings.Builder | ||||||
| @ -554,7 +559,7 @@ func (self *scanner) fetchString() (tk *Token) { | |||||||
| 				sb.WriteByte(ch) | 				sb.WriteByte(ch) | ||||||
| 			} | 			} | ||||||
| 			prev = 0 | 			prev = 0 | ||||||
| 		} else if ch == '"' { | 		} else if ch == termCh { | ||||||
| 			break | 			break | ||||||
| 		} else { | 		} else { | ||||||
| 			prev = ch | 			prev = ch | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ package expr | |||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"slices" | 	"slices" | ||||||
| 	"strings" | //	"strings"
 | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type SimpleStore struct { | type SimpleStore struct { | ||||||
| @ -50,7 +50,7 @@ func (ctx *SimpleStore) Merge(src ExprContext) { | |||||||
| 		ctx.funcStore[name], _ = src.GetFuncInfo(name) | 		ctx.funcStore[name], _ = src.GetFuncInfo(name) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | /* | ||||||
| func varsCtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) { | func varsCtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) { | ||||||
| 	sb.WriteString("vars: {\n") | 	sb.WriteString("vars: {\n") | ||||||
| 	first := true | 	first := true | ||||||
| @ -77,7 +77,7 @@ func varsCtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	sb.WriteString(strings.Repeat("\t", indent)) | 	sb.WriteString(strings.Repeat("\t", indent)) | ||||||
| 	sb.WriteString("\n}\n") | 	sb.WriteString("\n}") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func varsCtxToString(ctx ExprContext, indent int) string { | func varsCtxToString(ctx ExprContext, indent int) string { | ||||||
| @ -106,15 +106,59 @@ func funcsCtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) { | |||||||
| 			sb.WriteString(fmt.Sprintf("%v", value)) | 			sb.WriteString(fmt.Sprintf("%v", value)) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	sb.WriteString("\n}\n") | 	sb.WriteString("\n}") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (ctx *SimpleStore) ToString(opt FmtOpt) string { | func (ctx *SimpleStore) ToString(opt FmtOpt) string { | ||||||
| 	var sb strings.Builder | 	var sb strings.Builder | ||||||
| 	varsCtxToBuilder(&sb, ctx, 0) | 	varsCtxToBuilder(&sb, ctx, 0) | ||||||
|  | 	sb.WriteByte('\n') | ||||||
| 	funcsCtxToBuilder(&sb, ctx, 0) | 	funcsCtxToBuilder(&sb, ctx, 0) | ||||||
| 	return sb.String() | 	return sb.String() | ||||||
| } | } | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | func (ctx *SimpleStore) ToString(opt FmtOpt) string { | ||||||
|  | 	dict := ctx.ToDict() | ||||||
|  | 	return dict.ToString(opt) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (ctx *SimpleStore) varsToDict(dict *DictType) *DictType { | ||||||
|  | 	names := ctx.EnumVars(nil) | ||||||
|  | 	slices.Sort(names) | ||||||
|  | 	for _, name := range ctx.EnumVars(nil) { | ||||||
|  | 		value, _ := ctx.GetVar(name) | ||||||
|  | 		if f, ok := value.(Formatter); ok { | ||||||
|  | 			(*dict)[name] = f.ToString(0) | ||||||
|  | 		} else if _, ok = value.(Functor); ok { | ||||||
|  | 			(*dict)[name] = "func(){}" | ||||||
|  | 		} else { | ||||||
|  | 			(*dict)[name] = fmt.Sprintf("%v", value) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return dict | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (ctx *SimpleStore) funcsToDict(dict *DictType) *DictType { | ||||||
|  | 	names := ctx.EnumFuncs(func(name string) bool { return true }) | ||||||
|  | 	slices.Sort(names) | ||||||
|  | 	for _, name := range names { | ||||||
|  | 		value, _ := ctx.GetFuncInfo(name) | ||||||
|  | 		if formatter, ok := value.(Formatter); ok { | ||||||
|  | 			(*dict)[name] = formatter.ToString(0) | ||||||
|  | 		} else { | ||||||
|  | 			(*dict)[name] = fmt.Sprintf("%v", value) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return dict | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (ctx *SimpleStore) ToDict() (dict *DictType) { | ||||||
|  | 	dict = MakeDict() | ||||||
|  | 	(*dict)["variables"] = ctx.varsToDict(MakeDict()) | ||||||
|  | 	(*dict)["functions"] = ctx.funcsToDict(MakeDict()) | ||||||
|  | 	return | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| func (ctx *SimpleStore) GetVar(varName string) (v any, exists bool) { | func (ctx *SimpleStore) GetVar(varName string) (v any, exists bool) { | ||||||
| 	v, exists = ctx.varStore[varName] | 	v, exists = ctx.varStore[varName] | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | ||||||
| // All rights reserved.
 | // All rights reserved.
 | ||||||
| 
 | 
 | ||||||
| // t_func-base_test.go
 | // t_builtin-base_test.go
 | ||||||
| package expr | package expr | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| @ -10,7 +10,7 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func TestFuncBase(t *testing.T) { | func TestFuncBase(t *testing.T) { | ||||||
| 	section := "Func-Base" | 	section := "Builtin-Base" | ||||||
| 
 | 
 | ||||||
| 	inputs := []inputType{ | 	inputs := []inputType{ | ||||||
| 		/*   1 */ {`isNil(nil)`, true, nil}, | 		/*   1 */ {`isNil(nil)`, true, nil}, | ||||||
							
								
								
									
										24
									
								
								t_builtin-import_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								t_builtin-import_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | ||||||
|  | // All rights reserved.
 | ||||||
|  | 
 | ||||||
|  | // t_builtin-import_test.go
 | ||||||
|  | package expr | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestFuncImport(t *testing.T) { | ||||||
|  | 	section := "Builtin-Import" | ||||||
|  | 	inputs := []inputType{ | ||||||
|  | 		/*   1 */ {`builtin "import"; import("./test-resources/test-funcs.expr"); (double(3+a) + 1) * two()`, int64(34), nil}, | ||||||
|  | 		/*   2 */ {`builtin "import"; import("test-funcs.expr"); (double(3+a) + 1) * two()`, int64(34), nil}, | ||||||
|  | 		/*   3 */ {`builtin "import"; importAll("./test-resources/test-funcs.expr"); six()`, int64(6), nil}, | ||||||
|  | 		/*   4 */ {`builtin "import"; import("./test-resources/sample-export-all.expr"); six()`, int64(6), nil}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	t.Setenv("EXPR_PATH", "test-resources") | ||||||
|  | 
 | ||||||
|  | 	// parserTestSpec(t, section, inputs, 69)
 | ||||||
|  | 	parserTest(t, section, inputs) | ||||||
|  | } | ||||||
| @ -1,7 +1,7 @@ | |||||||
| // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | ||||||
| // All rights reserved.
 | // All rights reserved.
 | ||||||
| 
 | 
 | ||||||
| // t_func-math-arith_test.go
 | // t_builtin-math-arith_test.go
 | ||||||
| package expr | package expr | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| @ -10,7 +10,7 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func TestFuncMathArith(t *testing.T) { | func TestFuncMathArith(t *testing.T) { | ||||||
| 	section := "Func-Math-Arith" | 	section := "Builtin-Math-Arith" | ||||||
| 	inputs := []inputType{ | 	inputs := []inputType{ | ||||||
| 		/*   1 */ {`builtin "math.arith"; add(1,2)`, int64(3), nil}, | 		/*   1 */ {`builtin "math.arith"; add(1,2)`, int64(3), nil}, | ||||||
| 		/*   2 */ {`builtin "math.arith"; add(1,2,3)`, int64(6), nil}, | 		/*   2 */ {`builtin "math.arith"; add(1,2,3)`, int64(6), nil}, | ||||||
| @ -1,7 +1,7 @@ | |||||||
| // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | ||||||
| // All rights reserved.
 | // All rights reserved.
 | ||||||
| 
 | 
 | ||||||
| // t_func-os_test.go
 | // t_builtin-os-file_test.go
 | ||||||
| package expr | package expr | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| @ -10,7 +10,7 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func TestFuncOs(t *testing.T) { | func TestFuncOs(t *testing.T) { | ||||||
| 	section := "Func-OS" | 	section := "Builtin-OS-File" | ||||||
| 	inputs := []inputType{ | 	inputs := []inputType{ | ||||||
| 		/*   1 */ {`builtin "os.file"`, int64(1), nil}, | 		/*   1 */ {`builtin "os.file"`, int64(1), nil}, | ||||||
| 		/*   2 */ {`builtin "os.file"; handle=fileOpen("/etc/hosts"); fileClose(handle)`, true, nil}, | 		/*   2 */ {`builtin "os.file"; handle=fileOpen("/etc/hosts"); fileClose(handle)`, true, nil}, | ||||||
							
								
								
									
										69
									
								
								t_builtin-string_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								t_builtin-string_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,69 @@ | |||||||
|  | // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | ||||||
|  | // All rights reserved.
 | ||||||
|  | 
 | ||||||
|  | // t_builtin-string_test.go
 | ||||||
|  | package expr | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestFuncString(t *testing.T) { | ||||||
|  | 	section := "Builtin-String" | ||||||
|  | 
 | ||||||
|  | 	inputs := []inputType{ | ||||||
|  | 		/*   1 */ {`builtin "string"; strJoin("-", "one", "two", "three")`, "one-two-three", nil}, | ||||||
|  | 		/*   2 */ {`builtin "string"; strJoin("-", ["one", "two", "three"])`, "one-two-three", nil}, | ||||||
|  | 		/*   3 */ {`builtin "string"; ls= ["one", "two", "three"]; strJoin("-", ls)`, "one-two-three", nil}, | ||||||
|  | 		/*   4 */ {`builtin "string"; ls= ["one", "two", "three"]; strJoin(1, ls)`, nil, errors.New(`strJoin(): the "separator" parameter must be a string, got a integer (1)`)}, | ||||||
|  | 		/*   5 */ {`builtin "string"; ls= ["one", 2, "three"]; strJoin("-", ls)`, nil, errors.New(`strJoin(): expected string, got integer (2)`)}, | ||||||
|  | 		/*   6 */ {`builtin "string"; "<"+strTrim("  bye bye  ")+">"`, "<bye bye>", nil}, | ||||||
|  | 		/*   7 */ {`builtin "string"; strSub("0123456789", 1,2)`, "12", nil}, | ||||||
|  | 		/*   8 */ {`builtin "string"; strSub("0123456789", -3,2)`, "78", nil}, | ||||||
|  | 		/*   9 */ {`builtin "string"; strSub("0123456789", -3)`, "789", nil}, | ||||||
|  | 		/*  10 */ {`builtin "string"; strSub("0123456789")`, "0123456789", nil}, | ||||||
|  | 		/*  11 */ {`builtin "string"; strStartsWith("0123456789", "xyz", "012")`, true, nil}, | ||||||
|  | 		/*  12 */ {`builtin "string"; strStartsWith("0123456789", "xyz", "0125")`, false, nil}, | ||||||
|  | 		/*  13 */ {`builtin "string"; strStartsWith("0123456789")`, nil, errors.New(`strStartsWith(): too few params -- expected 2 or more, got 1`)}, | ||||||
|  | 		/*  14 */ {`builtin "string"; strEndsWith("0123456789", "xyz", "789")`, true, nil}, | ||||||
|  | 		/*  15 */ {`builtin "string"; strEndsWith("0123456789", "xyz", "0125")`, false, nil}, | ||||||
|  | 		/*  16 */ {`builtin "string"; strEndsWith("0123456789")`, nil, errors.New(`strEndsWith(): too few params -- expected 2 or more, got 1`)}, | ||||||
|  | 		/*  17 */ {`builtin "string"; strSplit("one-two-three", "-")`, newListA("one", "two", "three"), nil}, | ||||||
|  | 		/*  18 */ {`builtin "string"; strJoin("-", [1, "two", "three"])`, nil, errors.New(`strJoin(): expected string, got integer (1)`)}, | ||||||
|  | 		/*  19 */ {`builtin "string"; strJoin()`, nil, errors.New(`strJoin(): too few params -- expected 1 or more, got 0`)}, | ||||||
|  | 
 | ||||||
|  | 		/*  69 */ /*{`builtin "string"; $$global`, `vars: { | ||||||
|  | 		} | ||||||
|  | 		funcs: { | ||||||
|  | 		    	add(any=0 ...) -> number, | ||||||
|  | 		    	dec(any) -> decimal, | ||||||
|  | 		    	endsWithStr(source, suffix) -> boolean, | ||||||
|  | 		    	fract(any, denominator=1) -> fraction, | ||||||
|  | 		    	import( ...) -> any, | ||||||
|  | 		    	importAll( ...) -> any, | ||||||
|  | 		    	int(any) -> integer, | ||||||
|  | 		    	isBool(any) -> boolean, | ||||||
|  | 		    	isDec(any) -> boolean, | ||||||
|  | 		    	isDict(any) -> boolean, | ||||||
|  | 		    	isFloat(any) -> boolean, | ||||||
|  | 		    	isFract(any) -> boolean, | ||||||
|  | 		    	isInt(any) -> boolean, | ||||||
|  | 		    	isList(any) -> boolean, | ||||||
|  | 		    	isNil(any) -> boolean, | ||||||
|  | 		    	isString(any) -> boolean, | ||||||
|  | 		    	joinStr(separator, item="" ...) -> string, | ||||||
|  | 		    	mul(any=1 ...) -> number, | ||||||
|  | 		    	splitStr(source, separator="", count=-1) -> list of string, | ||||||
|  | 		    	startsWithStr(source, prefix) -> boolean, | ||||||
|  | 		    	subStr(source, start=0, count=-1) -> string, | ||||||
|  | 		    	trimStr(source) -> string | ||||||
|  | 		} | ||||||
|  | 		`, nil},*/ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	//t.Setenv("EXPR_PATH", ".")
 | ||||||
|  | 
 | ||||||
|  | 	// parserTestSpec(t, section, inputs, 19)
 | ||||||
|  | 	parserTest(t, section, inputs) | ||||||
|  | } | ||||||
| @ -1,24 +0,0 @@ | |||||||
| // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 |  | ||||||
| // All rights reserved.
 |  | ||||||
| 
 |  | ||||||
| // t_func-import_test.go
 |  | ||||||
| package expr |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"testing" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| func TestFuncImport(t *testing.T) { |  | ||||||
| 	section := "Func-Import" |  | ||||||
| 	inputs := []inputType{ |  | ||||||
| 		/*   1 */ {`builtin "import"; import("./test-funcs.expr"); (double(3+a) + 1) * two()`, int64(34), nil}, |  | ||||||
| 		/*   2 */ {`builtin "import"; import("test-funcs.expr"); (double(3+a) + 1) * two()`, int64(34), nil}, |  | ||||||
| 		/*   3 */ {`builtin "import"; importAll("./test-funcs.expr"); six()`, int64(6), nil}, |  | ||||||
| 		/*   4 */ {`builtin "import"; import("./sample-export-all.expr"); six()`, int64(6), nil}, |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	t.Setenv("EXPR_PATH", ".") |  | ||||||
| 
 |  | ||||||
| 	// parserTestSpec(t, section, inputs, 69)
 |  | ||||||
| 	parserTest(t, section, inputs) |  | ||||||
| } |  | ||||||
| @ -1,69 +0,0 @@ | |||||||
| // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 |  | ||||||
| // All rights reserved.
 |  | ||||||
| 
 |  | ||||||
| // t_func-string_test.go
 |  | ||||||
| package expr |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| 	"testing" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| func TestFuncString(t *testing.T) { |  | ||||||
| 	section := "Func-String" |  | ||||||
| 
 |  | ||||||
| 	inputs := []inputType{ |  | ||||||
| 		/*   1 */ {`builtin "string"; joinStr("-", "one", "two", "three")`, "one-two-three", nil}, |  | ||||||
| 		/*   2 */ {`builtin "string"; joinStr("-", ["one", "two", "three"])`, "one-two-three", nil}, |  | ||||||
| 		/*   3 */ {`builtin "string"; ls= ["one", "two", "three"]; joinStr("-", ls)`, "one-two-three", nil}, |  | ||||||
| 		/*   4 */ {`builtin "string"; ls= ["one", "two", "three"]; joinStr(1, ls)`, nil, errors.New(`joinStr() the "separator" parameter must be a string, got a integer (1)`)}, |  | ||||||
| 		/*   5 */ {`builtin "string"; ls= ["one", 2, "three"]; joinStr("-", ls)`, nil, errors.New(`joinStr() expected string, got integer (2)`)}, |  | ||||||
| 		/*   6 */ {`builtin "string"; "<"+trimStr("  bye bye  ")+">"`, "<bye bye>", nil}, |  | ||||||
| 		/*   7 */ {`builtin "string"; subStr("0123456789", 1,2)`, "12", nil}, |  | ||||||
| 		/*   8 */ {`builtin "string"; subStr("0123456789", -3,2)`, "78", nil}, |  | ||||||
| 		/*   9 */ {`builtin "string"; subStr("0123456789", -3)`, "789", nil}, |  | ||||||
| 		/*  10 */ {`builtin "string"; subStr("0123456789")`, "0123456789", nil}, |  | ||||||
| 		/*  11 */ {`builtin "string"; startsWithStr("0123456789", "xyz", "012")`, true, nil}, |  | ||||||
| 		/*  12 */ {`builtin "string"; startsWithStr("0123456789", "xyz", "0125")`, false, nil}, |  | ||||||
| 		/*  13 */ {`builtin "string"; startsWithStr("0123456789")`, nil, errors.New(`startsWithStr(): too few params -- expected 2 or more, got 1`)}, |  | ||||||
| 		/*  14 */ {`builtin "string"; endsWithStr("0123456789", "xyz", "789")`, true, nil}, |  | ||||||
| 		/*  15 */ {`builtin "string"; endsWithStr("0123456789", "xyz", "0125")`, false, nil}, |  | ||||||
| 		/*  16 */ {`builtin "string"; endsWithStr("0123456789")`, nil, errors.New(`endsWithStr(): too few params -- expected 2 or more, got 1`)}, |  | ||||||
| 		/*  17 */ {`builtin "string"; splitStr("one-two-three", "-")`, newListA("one", "two", "three"), nil}, |  | ||||||
| 		/*  18 */ {`builtin "string"; joinStr("-", [1, "two", "three"])`, nil, errors.New(`joinStr() expected string, got integer (1)`)}, |  | ||||||
| 		/*  19 */ {`builtin "string"; joinStr()`, nil, errors.New(`joinStr(): too few params -- expected 1 or more, got 0`)}, |  | ||||||
| 
 |  | ||||||
| 		/*  69 */ /*{`builtin "string"; $$global`, `vars: { |  | ||||||
| 		} |  | ||||||
| 		funcs: { |  | ||||||
| 		    	add(any=0 ...) -> number, |  | ||||||
| 		    	dec(any) -> decimal, |  | ||||||
| 		    	endsWithStr(source, suffix) -> boolean, |  | ||||||
| 		    	fract(any, denominator=1) -> fraction, |  | ||||||
| 		    	import( ...) -> any, |  | ||||||
| 		    	importAll( ...) -> any, |  | ||||||
| 		    	int(any) -> integer, |  | ||||||
| 		    	isBool(any) -> boolean, |  | ||||||
| 		    	isDec(any) -> boolean, |  | ||||||
| 		    	isDict(any) -> boolean, |  | ||||||
| 		    	isFloat(any) -> boolean, |  | ||||||
| 		    	isFract(any) -> boolean, |  | ||||||
| 		    	isInt(any) -> boolean, |  | ||||||
| 		    	isList(any) -> boolean, |  | ||||||
| 		    	isNil(any) -> boolean, |  | ||||||
| 		    	isString(any) -> boolean, |  | ||||||
| 		    	joinStr(separator, item="" ...) -> string, |  | ||||||
| 		    	mul(any=1 ...) -> number, |  | ||||||
| 		    	splitStr(source, separator="", count=-1) -> list of string, |  | ||||||
| 		    	startsWithStr(source, prefix) -> boolean, |  | ||||||
| 		    	subStr(source, start=0, count=-1) -> string, |  | ||||||
| 		    	trimStr(source) -> string |  | ||||||
| 		} |  | ||||||
| 		`, nil},*/ |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	//t.Setenv("EXPR_PATH", ".")
 |  | ||||||
| 
 |  | ||||||
| 	// parserTestSpec(t, section, inputs, 19)
 |  | ||||||
| 	parserTest(t, section, inputs) |  | ||||||
| } |  | ||||||
| @ -44,7 +44,7 @@ func dummy(ctx ExprContext, name string, args []any) (result any, err error) { | |||||||
| 
 | 
 | ||||||
| func TestFunctionToStringSimple(t *testing.T) { | func TestFunctionToStringSimple(t *testing.T) { | ||||||
| 	source := NewGolangFunctor(dummy) | 	source := NewGolangFunctor(dummy) | ||||||
| 	want := "func() {<body>}" | 	want := "func() {}" | ||||||
| 	got := source.ToString(0) | 	got := source.ToString(0) | ||||||
| 	if got != want { | 	if got != want { | ||||||
| 		t.Errorf(`(func() -> result = %v [%T], want = %v [%T]`, got, got, want, want) | 		t.Errorf(`(func() -> result = %v [%T], want = %v [%T]`, got, got, want, want) | ||||||
|  | |||||||
| @ -45,7 +45,7 @@ func TestScanner(t *testing.T) { | |||||||
| 		/* 22 */ {"@", SymAt, nil, nil}, | 		/* 22 */ {"@", SymAt, nil, nil}, | ||||||
| 		/* 23 */ {`#`, SymHash, nil, nil}, | 		/* 23 */ {`#`, SymHash, nil, nil}, | ||||||
| 		/* 24 */ {`%`, SymPercent, nil, nil}, | 		/* 24 */ {`%`, SymPercent, nil, nil}, | ||||||
| 		/* 25 */ {`'`, SymQuote, nil, nil}, | 		/* 25 */ {`\'`, SymQuote, nil, nil}, | ||||||
| 		/* 26 */ {`\"`, SymDoubleQuote, nil, nil}, | 		/* 26 */ {`\"`, SymDoubleQuote, nil, nil}, | ||||||
| 		/* 27 */ {`_`, SymUndescore, nil, nil}, | 		/* 27 */ {`_`, SymUndescore, nil, nil}, | ||||||
| 		/* 28 */ {`<>`, SymLessGreater, nil, nil}, | 		/* 28 */ {`<>`, SymLessGreater, nil, nil}, | ||||||
|  | |||||||
| @ -63,7 +63,7 @@ func TestIsString(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	count++ | 	count++ | ||||||
| 	b, ok := toBool(true) | 	b, ok := ToBool(true) | ||||||
| 	if !(ok && b) { | 	if !(ok && b) { | ||||||
| 		t.Errorf("%d: toBool(true) b=%v, ok=%v -> result = false, want true", count, b, ok) | 		t.Errorf("%d: toBool(true) b=%v, ok=%v -> result = false, want true", count, b, ok) | ||||||
| 		failed++ | 		failed++ | ||||||
| @ -72,7 +72,7 @@ func TestIsString(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	count++ | 	count++ | ||||||
| 	b, ok = toBool("abc") | 	b, ok = ToBool("abc") | ||||||
| 	if !(ok && b) { | 	if !(ok && b) { | ||||||
| 		t.Errorf("%d: toBool(\"abc\") b=%v, ok=%v -> result = false, want true", count, b, ok) | 		t.Errorf("%d: toBool(\"abc\") b=%v, ok=%v -> result = false, want true", count, b, ok) | ||||||
| 		failed++ | 		failed++ | ||||||
| @ -81,7 +81,7 @@ func TestIsString(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	count++ | 	count++ | ||||||
| 	b, ok = toBool([]int{}) | 	b, ok = ToBool([]int{}) | ||||||
| 	if ok { | 	if ok { | ||||||
| 		t.Errorf("%d: toBool([]) b=%v, ok=%v -> result = true, want false", count, b, ok) | 		t.Errorf("%d: toBool([]) b=%v, ok=%v -> result = true, want false", count, b, ok) | ||||||
| 		failed++ | 		failed++ | ||||||
| @ -97,7 +97,7 @@ func TestToIntOk(t *testing.T) { | |||||||
| 	wantValue := int(64) | 	wantValue := int(64) | ||||||
| 	wantErr := error(nil) | 	wantErr := error(nil) | ||||||
| 
 | 
 | ||||||
| 	gotValue, gotErr := toInt(source, "test") | 	gotValue, gotErr := ToInt(source, "test") | ||||||
| 
 | 
 | ||||||
| 	if gotErr != nil || gotValue != wantValue { | 	if gotErr != nil || gotValue != wantValue { | ||||||
| 		t.Errorf("toInt(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v", | 		t.Errorf("toInt(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v", | ||||||
| @ -110,7 +110,7 @@ func TestToIntErr(t *testing.T) { | |||||||
| 	wantValue := 0 | 	wantValue := 0 | ||||||
| 	wantErr := errors.New(`test expected integer, got uint64 (64)`) | 	wantErr := errors.New(`test expected integer, got uint64 (64)`) | ||||||
| 
 | 
 | ||||||
| 	gotValue, gotErr := toInt(source, "test") | 	gotValue, gotErr := ToInt(source, "test") | ||||||
| 
 | 
 | ||||||
| 	if gotErr.Error() != wantErr.Error() || gotValue != wantValue { | 	if gotErr.Error() != wantErr.Error() || gotValue != wantValue { | ||||||
| 		t.Errorf("toInt(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v", | 		t.Errorf("toInt(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v", | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								utils.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								utils.go
									
									
									
									
									
								
							| @ -86,7 +86,7 @@ func numAsFloat(v any) (f float64) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func toBool(v any) (b bool, ok bool) { | func ToBool(v any) (b bool, ok bool) { | ||||||
| 	ok = true | 	ok = true | ||||||
| 	switch x := v.(type) { | 	switch x := v.(type) { | ||||||
| 	case string: | 	case string: | ||||||
| @ -201,7 +201,7 @@ func CloneFilteredMap[K comparable, V any](source map[K]V, filter func(key K) (a | |||||||
| 	return CopyFilteredMap(dest, source, filter) | 	return CopyFilteredMap(dest, source, filter) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func toInt(value any, description string) (i int, err error) { | func ToInt(value any, description string) (i int, err error) { | ||||||
| 	if valueInt64, ok := value.(int64); ok { | 	if valueInt64, ok := value.(int64); ok { | ||||||
| 		i = int(valueInt64) | 		i = int(valueInt64) | ||||||
| 	} else if valueInt, ok := value.(int); ok { | 	} else if valueInt, ok := value.(int); ok { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user