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: | ||||
| 		result = len(v) > 0 | ||||
| 	default: | ||||
| 		err = errCantConvert(name, v, "bool") | ||||
| 		err = ErrCantConvert(name, v, "bool") | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| @ -90,7 +90,7 @@ func intFunc(ctx ExprContext, name string, args []any) (result any, err error) { | ||||
| 			result = int64(i) | ||||
| 		} | ||||
| 	default: | ||||
| 		err = errCantConvert(name, v, "int") | ||||
| 		err = ErrCantConvert(name, v, "int") | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| @ -115,7 +115,7 @@ func decFunc(ctx ExprContext, name string, args []any) (result any, err error) { | ||||
| 	case *FractionType: | ||||
| 		result = v.toFloat() | ||||
| 	default: | ||||
| 		err = errCantConvert(name, v, "float") | ||||
| 		err = ErrCantConvert(name, v, "float") | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| @ -127,9 +127,9 @@ func fractFunc(ctx ExprContext, name string, args []any) (result any, err error) | ||||
| 		if len(args) > 1 { | ||||
| 			var ok bool | ||||
| 			if den, ok = args[1].(int64); !ok { | ||||
| 				err = errExpectedGot(name, "integer", args[1]) | ||||
| 				err = ErrExpectedGot(name, "integer", args[1]) | ||||
| 			} else if den == 0 { | ||||
| 				err = errFuncDivisionByZero(name) | ||||
| 				err = ErrFuncDivisionByZero(name) | ||||
| 			} | ||||
| 		} | ||||
| 		if err == nil { | ||||
| @ -148,7 +148,7 @@ func fractFunc(ctx ExprContext, name string, args []any) (result any, err error) | ||||
| 	case *FractionType: | ||||
| 		result = v | ||||
| 	default: | ||||
| 		err = errCantConvert(name, v, "float") | ||||
| 		err = ErrCantConvert(name, v, "float") | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| @ -21,7 +21,7 @@ func doJoinStr(funcName string, sep string, it Iterator) (result any, err error) | ||||
| 		if s, ok := v.(string); ok { | ||||
| 			sb.WriteString(s) | ||||
| 		} else { | ||||
| 			err = errExpectedGot(funcName, TypeString, v) | ||||
| 			err = ErrExpectedGot(funcName, TypeString, v) | ||||
| 			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 { | ||||
| 				result, err = doJoinStr(name, sep, it) | ||||
| 			} else { | ||||
| 				err = errInvalidParameterValue(name, ParamParts, args[1]) | ||||
| 				err = ErrInvalidParameterValue(name, ParamParts, args[1]) | ||||
| 			} | ||||
| 		} else { | ||||
| 			result, err = doJoinStr(name, sep, NewArrayIterator(args[1:])) | ||||
| 		} | ||||
| 	} else { | ||||
| 		err = errWrongParamType(name, ParamSeparator, TypeString, args[0]) | ||||
| 		err = ErrWrongParamType(name, ParamSeparator, TypeString, args[0]) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| @ -63,14 +63,14 @@ func subStrFunc(ctx ExprContext, name string, args []any) (result any, err error | ||||
| 	var ok bool | ||||
| 
 | ||||
| 	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 | ||||
| 	} | ||||
| 
 | ||||
| 	if count, err = toInt(args[2], name+"()"); err != nil { | ||||
| 	if count, err = ToInt(args[2], name+"()"); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| @ -91,7 +91,7 @@ func trimStrFunc(ctx ExprContext, name string, args []any) (result any, err erro | ||||
| 	var ok bool | ||||
| 
 | ||||
| 	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) | ||||
| 	return | ||||
| @ -104,7 +104,7 @@ func startsWithStrFunc(ctx ExprContext, name string, args []any) (result any, er | ||||
| 	result = false | ||||
| 
 | ||||
| 	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:] { | ||||
| 		if target, ok := targetSpec.(string); ok { | ||||
| @ -127,7 +127,7 @@ func endsWithStrFunc(ctx ExprContext, name string, args []any) (result any, err | ||||
| 	result = false | ||||
| 
 | ||||
| 	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:] { | ||||
| 		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 | ||||
| 
 | ||||
| 	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 { | ||||
| @ -182,34 +182,34 @@ func splitStrFunc(ctx ExprContext, name string, args []any) (result any, err err | ||||
| 
 | ||||
| // Import above functions in the context
 | ||||
| func ImportStringFuncs(ctx ExprContext) { | ||||
| 	ctx.RegisterFunc("joinStr", NewGolangFunctor(joinStrFunc), TypeString, []ExprFuncParam{ | ||||
| 	ctx.RegisterFunc("strJoin", NewGolangFunctor(joinStrFunc), TypeString, []ExprFuncParam{ | ||||
| 		NewFuncParam(ParamSeparator), | ||||
| 		NewFuncParamFlag(ParamItem, PfRepeat), | ||||
| 	}) | ||||
| 
 | ||||
| 	ctx.RegisterFunc("subStr", NewGolangFunctor(subStrFunc), TypeString, []ExprFuncParam{ | ||||
| 	ctx.RegisterFunc("strSub", NewGolangFunctor(subStrFunc), TypeString, []ExprFuncParam{ | ||||
| 		NewFuncParam(ParamSource), | ||||
| 		NewFuncParamFlagDef(ParamStart, PfDefault, int64(0)), | ||||
| 		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), | ||||
| 		NewFuncParamFlagDef(ParamSeparator, PfDefault, ""), | ||||
| 		NewFuncParamFlagDef(ParamCount, PfDefault, int64(-1)), | ||||
| 	}) | ||||
| 
 | ||||
| 	ctx.RegisterFunc("trimStr", NewGolangFunctor(trimStrFunc), TypeString, []ExprFuncParam{ | ||||
| 	ctx.RegisterFunc("strTrim", NewGolangFunctor(trimStrFunc), TypeString, []ExprFuncParam{ | ||||
| 		NewFuncParam(ParamSource), | ||||
| 	}) | ||||
| 
 | ||||
| 	ctx.RegisterFunc("startsWithStr", NewGolangFunctor(startsWithStrFunc), TypeBoolean, []ExprFuncParam{ | ||||
| 	ctx.RegisterFunc("strStartsWith", NewGolangFunctor(startsWithStrFunc), TypeBoolean, []ExprFuncParam{ | ||||
| 		NewFuncParam(ParamSource), | ||||
| 		NewFuncParam(ParamPrefix), | ||||
| 		NewFuncParamFlag("other "+ParamPrefix, PfRepeat), | ||||
| 	}) | ||||
| 
 | ||||
| 	ctx.RegisterFunc("endsWithStr", NewGolangFunctor(endsWithStrFunc), TypeBoolean, []ExprFuncParam{ | ||||
| 	ctx.RegisterFunc("strEndsWith", NewGolangFunctor(endsWithStrFunc), TypeBoolean, []ExprFuncParam{ | ||||
| 		NewFuncParam(ParamSource), | ||||
| 		NewFuncParam(ParamSuffix), | ||||
| 		NewFuncParamFlag("other "+ParamSuffix, PfRepeat), | ||||
|  | ||||
| @ -8,7 +8,7 @@ import ( | ||||
| 	"fmt" | ||||
| ) | ||||
| 
 | ||||
| func errTooFewParams(funcName string, minArgs, maxArgs, argCount int) (err error) { | ||||
| func ErrTooFewParams(funcName string, minArgs, maxArgs, argCount int) (err error) { | ||||
| 	if maxArgs < 0 { | ||||
| 		err = fmt.Errorf("%s(): too few params -- expected %d or more, got %d", funcName, minArgs, argCount) | ||||
| 	} else { | ||||
| @ -17,39 +17,39 @@ func errTooFewParams(funcName string, minArgs, maxArgs, argCount int) (err error | ||||
| 	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) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // --- 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) | ||||
| } | ||||
| 
 | ||||
| func errExpectedGot(funcName string, kind string, value any) error { | ||||
| 	return fmt.Errorf("%s() expected %s, got %s (%v)", funcName, kind, TypeName(value), value) | ||||
| func ErrExpectedGot(funcName string, kind string, value any) error { | ||||
| 	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) | ||||
| } | ||||
| 
 | ||||
| func errDivisionByZero() error { | ||||
| func ErrDivisionByZero() error { | ||||
| 	return fmt.Errorf("division by zero") | ||||
| } | ||||
| 
 | ||||
| // --- Parameter errors
 | ||||
| 
 | ||||
| func errMissingRequiredParameter(funcName, paramName string) error { | ||||
| 	return fmt.Errorf("%s() missing required parameter %q", funcName, paramName) | ||||
| func ErrMissingRequiredParameter(funcName, paramName string) error { | ||||
| 	return fmt.Errorf("%s(): missing required parameter %q", funcName, paramName) | ||||
| } | ||||
| 
 | ||||
| func errInvalidParameterValue(funcName, paramName string, paramValue any) error { | ||||
| 	return fmt.Errorf("%s() invalid value %s (%v) for parameter %q", funcName, TypeName(paramValue), paramValue, paramName) | ||||
| func ErrInvalidParameterValue(funcName, paramName string, paramValue any) error { | ||||
| 	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 { | ||||
| 	return fmt.Errorf("%s() the %q parameter must be a %s, got a %s (%v)", funcName, paramName, paramType, TypeName(paramValue), paramValue) | ||||
| 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) | ||||
| } | ||||
|  | ||||
							
								
								
									
										72
									
								
								dict-type.go
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								dict-type.go
									
									
									
									
									
								
							| @ -32,42 +32,52 @@ func newDict(dictAny map[any]*term) (dict *DictType) { | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (dict *DictType) toMultiLine(sb *strings.Builder, indent int) { | ||||
| 	sb.WriteString(strings.Repeat("\t", indent)) | ||||
| 	sb.WriteString("{\n") | ||||
| func (dict *DictType) toMultiLine(sb *strings.Builder, opt FmtOpt) { | ||||
| 	indent := GetFormatIndent(opt) | ||||
| 	flags := GetFormatFlags(opt) | ||||
| 	//sb.WriteString(strings.Repeat("  ", indent))
 | ||||
| 	sb.WriteByte('{') | ||||
| 
 | ||||
| 	first := true | ||||
| 	for name, value := range *dict { | ||||
| 		if first { | ||||
| 			first = false | ||||
| 		} else { | ||||
| 			sb.WriteByte(',') | ||||
| 			sb.WriteByte('\n') | ||||
| 		} | ||||
| 	if len(*dict) > 0 { | ||||
| 		innerOpt := MakeFormatOptions(flags, indent+1) | ||||
| 		nest := strings.Repeat("  ", indent+1) | ||||
| 		sb.WriteByte('\n') | ||||
| 
 | ||||
| 		sb.WriteString(strings.Repeat("\t", indent+1)) | ||||
| 		if key, ok := name.(string); ok { | ||||
| 			sb.WriteString(string('"') + key + string('"')) | ||||
| 		} else { | ||||
| 			sb.WriteString(fmt.Sprintf("%v", name)) | ||||
| 		} | ||||
| 		sb.WriteString(": ") | ||||
| 		if f, ok := value.(Formatter); ok { | ||||
| 			sb.WriteString(f.ToString(MultiLine)) | ||||
| 		} else if _, ok = value.(Functor); ok { | ||||
| 			sb.WriteString("func(){}") | ||||
| 		} else { | ||||
| 			sb.WriteString(fmt.Sprintf("%v", value)) | ||||
| 		first := true | ||||
| 		for name, value := range *dict { | ||||
| 			if first { | ||||
| 				first = false | ||||
| 			} else { | ||||
| 				sb.WriteByte(',') | ||||
| 				sb.WriteByte('\n') | ||||
| 			} | ||||
| 
 | ||||
| 			sb.WriteString(nest) | ||||
| 			if key, ok := name.(string); ok { | ||||
| 				sb.WriteString(string('"') + key + string('"')) | ||||
| 			} else { | ||||
| 				sb.WriteString(fmt.Sprintf("%v", name)) | ||||
| 			} | ||||
| 			sb.WriteString(": ") | ||||
| 			if f, ok := value.(Formatter); ok { | ||||
| 				sb.WriteString(f.ToString(innerOpt)) | ||||
| 			} else if _, ok = value.(Functor); ok { | ||||
| 				sb.WriteString("func(){}") | ||||
| 			} else { | ||||
| 				sb.WriteString(fmt.Sprintf("%v", value)) | ||||
| 			} | ||||
| 		} | ||||
| 		sb.WriteByte('\n') | ||||
| 		sb.WriteString(strings.Repeat("  ", indent)) | ||||
| 	} | ||||
| 	sb.WriteString(strings.Repeat("\t", indent)) | ||||
| 	sb.WriteString("\n}") | ||||
| 	sb.WriteString("}") | ||||
| } | ||||
| 
 | ||||
| func (dict *DictType) ToString(opt FmtOpt) string { | ||||
| 	var sb strings.Builder | ||||
| 	if opt&MultiLine != 0 { | ||||
| 		dict.toMultiLine(&sb, 0) | ||||
| 	flags := GetFormatFlags(opt) | ||||
| 	if flags&MultiLine != 0 { | ||||
| 		dict.toMultiLine(&sb, opt) | ||||
| 	} else { | ||||
| 		sb.WriteByte('{') | ||||
| 		first := true | ||||
| @ -133,3 +143,9 @@ func (dict *DictType) setItem(key any, value any) (err error) { | ||||
| 	(*dict)[key] = value | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| ////////////////
 | ||||
| 
 | ||||
| type DictFormat interface { | ||||
| 	ToDict() *DictType | ||||
| } | ||||
|  | ||||
							
								
								
									
										14
									
								
								formatter.go
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								formatter.go
									
									
									
									
									
								
							| @ -6,7 +6,7 @@ package expr | ||||
| 
 | ||||
| import "fmt" | ||||
| 
 | ||||
| type FmtOpt uint16 | ||||
| type FmtOpt uint32 // lower 16 bits hold a bit-mask, higher 16 bits hold an indentation number
 | ||||
| 
 | ||||
| const ( | ||||
| 	TTY FmtOpt = 1 << iota | ||||
| @ -30,6 +30,18 @@ func TruncateString(s string) (trunc string) { | ||||
| 	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 { | ||||
| 	ToString(options FmtOpt) string | ||||
| } | ||||
|  | ||||
| @ -70,7 +70,7 @@ func makeGeneratingFraction(s string) (f *FractionType, err error) { | ||||
| 			} | ||||
| 			for _, c := range dec[0:lsd] { | ||||
| 				if c < '0' || c > '9' { | ||||
| 					return nil, errExpectedGot("fract", "digit", c) | ||||
| 					return nil, ErrExpectedGot("fract", "digit", c) | ||||
| 				} | ||||
| 				num = num*10 + int64(c-'0') | ||||
| 				den = den * 10 | ||||
| @ -81,7 +81,7 @@ func makeGeneratingFraction(s string) (f *FractionType, err error) { | ||||
| 			mul := int64(1) | ||||
| 			for _, c := range subParts[0] { | ||||
| 				if c < '0' || c > '9' { | ||||
| 					return nil, errExpectedGot("fract", "digit", c) | ||||
| 					return nil, ErrExpectedGot("fract", "digit", c) | ||||
| 				} | ||||
| 				num = num*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] | ||||
| 				for _, c := range p { | ||||
| 					if c < '0' || c > '9' { | ||||
| 						return nil, errExpectedGot("fract", "digit", c) | ||||
| 						return nil, ErrExpectedGot("fract", "digit", c) | ||||
| 					} | ||||
| 					num = num*10 + int64(c-'0') | ||||
| 					den = den*10 + 9 | ||||
| @ -212,7 +212,7 @@ func anyToFract(v any) (f *FractionType, err error) { | ||||
| 		} | ||||
| 	} | ||||
| 	if f == nil { | ||||
| 		err = errExpectedGot("fract", TypeFraction, v) | ||||
| 		err = ErrExpectedGot("fract", TypeFraction, v) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| @ -21,7 +21,7 @@ func (functor *baseFunctor) ToString(opt FmtOpt) (s string) { | ||||
| 	if functor.info != nil { | ||||
| 		s = functor.info.ToString(opt) | ||||
| 	} else { | ||||
| 		s = "func() {<body>}" | ||||
| 		s = "func() {}" | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
| @ -180,7 +180,7 @@ func (info *funcInfo) ToString(opt FmtOpt) string { | ||||
| 	} else { | ||||
| 		sb.WriteString(TypeAny) | ||||
| 	} | ||||
| 	sb.WriteString(" {<body>}") | ||||
| 	sb.WriteString(" {}") | ||||
| 	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} | ||||
| 	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 { | ||||
| 				i = listLen + i | ||||
| 			} | ||||
| 			it.start = i | ||||
| 		} | ||||
| 		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 { | ||||
| 					i = listLen + i | ||||
| 				} | ||||
| 				it.stop = i | ||||
| 			} | ||||
| 			if argc >= 3 { | ||||
| 				if i, err := toInt(args[2], "step"); err == nil { | ||||
| 				if i, err := ToInt(args[2], "step"); err == nil { | ||||
| 					if i < 0 { | ||||
| 						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) { | ||||
|         indent := GetFormatIndent(opt) | ||||
|         flags := GetFormatFlags(opt) | ||||
| 
 | ||||
| 	var sb strings.Builder | ||||
| 	sb.WriteByte('[') | ||||
| 	if len(*ls) > 0 { | ||||
| 		if opt&MultiLine != 0 { | ||||
| 			sb.WriteString("\n  ") | ||||
|                 innerOpt := MakeFormatOptions(flags, indent+1) | ||||
|                 nest := strings.Repeat("  ", indent+1) | ||||
| 
 | ||||
| 		if flags&MultiLine != 0 { | ||||
| 			sb.WriteByte('\n') | ||||
| 			sb.WriteString(nest) | ||||
| 		} | ||||
| 		for i, item := range []any(*ls) { | ||||
| 			if i > 0 { | ||||
| 				if opt&MultiLine != 0 { | ||||
| 					sb.WriteString(",\n  ") | ||||
| 				if flags&MultiLine != 0 { | ||||
| 					sb.WriteString(",\n") | ||||
| 					sb.WriteString(nest) | ||||
| 				} else { | ||||
| 					sb.WriteString(", ") | ||||
| 				} | ||||
| @ -70,17 +78,20 @@ func (ls *ListType) ToString(opt FmtOpt) (s string) { | ||||
| 				sb.WriteByte('"') | ||||
| 				sb.WriteString(s) | ||||
| 				sb.WriteByte('"') | ||||
| 			} else if formatter, ok := item.(Formatter); ok { | ||||
| 				sb.WriteString(formatter.ToString(innerOpt)) | ||||
| 			} else { | ||||
| 				sb.WriteString(fmt.Sprintf("%v", item)) | ||||
| 			} | ||||
| 		} | ||||
| 		if opt&MultiLine != 0 { | ||||
| 		if flags&MultiLine != 0 { | ||||
| 			sb.WriteByte('\n') | ||||
| 			sb.WriteString(strings.Repeat("  ", indent)) | ||||
| 		} | ||||
| 	} | ||||
| 	sb.WriteByte(']') | ||||
| 	s = sb.String() | ||||
| 	if opt&Truncate != 0 && len(s) > TruncateSize { | ||||
| 	if flags&Truncate != 0 && len(s) > TruncateSize { | ||||
| 		s = TruncateString(s) | ||||
| 	} | ||||
| 	return | ||||
|  | ||||
| @ -26,7 +26,7 @@ func checkFunctionCall(ctx ExprContext, name string, varParams *[]any) (err erro | ||||
| 	if info, exists, owner := GetFuncInfo(ctx, name); exists { | ||||
| 		passedCount := len(*varParams) | ||||
| 		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() { | ||||
| 			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) { | ||||
| 			err = errTooMuchParams(name, info.MaxArgs(), len(*varParams)) | ||||
| 			err = ErrTooMuchParams(name, info.MaxArgs(), len(*varParams)) | ||||
| 		} | ||||
| 		if err == nil && owner != ctx { | ||||
| 			ctx.RegisterFuncInfo(info) | ||||
|  | ||||
| @ -25,7 +25,7 @@ func evalNot(ctx ExprContext, self *term) (v any, err error) { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if b, ok := toBool(rightValue); ok { | ||||
| 	if b, ok := ToBool(rightValue); ok { | ||||
| 		v = !b | ||||
| 	} else { | ||||
| 		err = self.errIncompatibleType(rightValue) | ||||
| @ -65,8 +65,8 @@ func evalAndWithoutShortcut(ctx ExprContext, self *term) (v any, err error) { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	leftBool, lok = toBool(leftValue) | ||||
| 	rightBool, rok = toBool(rightValue) | ||||
| 	leftBool, lok = ToBool(leftValue) | ||||
| 	rightBool, rok = ToBool(rightValue) | ||||
| 
 | ||||
| 	if lok && rok { | ||||
| 		v = leftBool && rightBool | ||||
| @ -87,13 +87,13 @@ func evalAndWithShortcut(ctx ExprContext, self *term) (v any, err error) { | ||||
| 		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) | ||||
| 		return | ||||
| 	} else if !leftBool { | ||||
| 		v = false | ||||
| 	} 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 | ||||
| 		} else { | ||||
| 			err = self.errIncompatibleTypes(leftValue, rightValue) | ||||
| @ -134,8 +134,8 @@ func evalOrWithoutShortcut(ctx ExprContext, self *term) (v any, err error) { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	leftBool, lok = toBool(leftValue) | ||||
| 	rightBool, rok = toBool(rightValue) | ||||
| 	leftBool, lok = ToBool(leftValue) | ||||
| 	rightBool, rok = ToBool(rightValue) | ||||
| 
 | ||||
| 	if lok && rok { | ||||
| 		v = leftBool || rightBool | ||||
| @ -156,13 +156,13 @@ func evalOrWithShortcut(ctx ExprContext, self *term) (v any, err error) { | ||||
| 		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) | ||||
| 		return | ||||
| 	} else if leftBool { | ||||
| 		v = true | ||||
| 	} 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 | ||||
| 		} else { | ||||
| 			err = self.errIncompatibleTypes(leftValue, rightValue) | ||||
|  | ||||
| @ -31,7 +31,9 @@ func evalContextValue(ctx ExprContext, self *term) (v any, err error) { | ||||
| 	} | ||||
| 
 | ||||
| 	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) | ||||
| 		} else { | ||||
| 			// 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) { | ||||
| 	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 { | ||||
| 			v = maxValue + v | ||||
| 		} | ||||
|  | ||||
| @ -36,7 +36,7 @@ func evalLength(ctx ExprContext, self *term) (v any, err error) { | ||||
| 	} else if it, ok := childValue.(Iterator); ok { | ||||
| 		if extIt, ok := childValue.(ExtIterator); ok && extIt.HasOperation(countName) { | ||||
| 			count, _ := extIt.CallOperation(countName, nil) | ||||
| 			v, _ = toInt(count, "") | ||||
| 			v, _ = ToInt(count, "") | ||||
| 		} else { | ||||
| 			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) { | ||||
| 	if v, err = evalEqual(ctx, self); err == nil { | ||||
| 		b, _ := toBool(v) | ||||
| 		b, _ := ToBool(v) | ||||
| 		v = !b | ||||
| 	} | ||||
| 	return | ||||
|  | ||||
							
								
								
									
										13
									
								
								scanner.go
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								scanner.go
									
									
									
									
									
								
							| @ -178,13 +178,18 @@ func (self *scanner) fetchNextToken() (tk *Token) { | ||||
| 				tk = self.makeToken(SymDot, ch) | ||||
| 			} | ||||
| 		case '\'': | ||||
| 			tk = self.makeToken(SymQuote, ch) | ||||
| 			if escape { | ||||
| 				tk = self.makeToken(SymQuote, ch) | ||||
| 				escape = false | ||||
| 			} else { | ||||
| 				tk = self.fetchString(ch) | ||||
| 			} | ||||
| 		case '"': | ||||
| 			if escape { | ||||
| 				tk = self.makeToken(SymDoubleQuote, ch) | ||||
| 				escape = false | ||||
| 			} else { | ||||
| 				tk = self.fetchString() | ||||
| 				tk = self.fetchString(ch) | ||||
| 			} | ||||
| 		case '`': | ||||
| 			tk = self.makeToken(SymBackTick, ch) | ||||
| @ -533,7 +538,7 @@ func (self *scanner) fetchUntil(sym Symbol, allowEos bool, endings ...byte) (tk | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (self *scanner) fetchString() (tk *Token) { | ||||
| func (self *scanner) fetchString(termCh byte) (tk *Token) { | ||||
| 	var err error | ||||
| 	var ch, prev byte | ||||
| 	var sb strings.Builder | ||||
| @ -554,7 +559,7 @@ func (self *scanner) fetchString() (tk *Token) { | ||||
| 				sb.WriteByte(ch) | ||||
| 			} | ||||
| 			prev = 0 | ||||
| 		} else if ch == '"' { | ||||
| 		} else if ch == termCh { | ||||
| 			break | ||||
| 		} else { | ||||
| 			prev = ch | ||||
|  | ||||
| @ -7,7 +7,7 @@ package expr | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"slices" | ||||
| 	"strings" | ||||
| //	"strings"
 | ||||
| ) | ||||
| 
 | ||||
| type SimpleStore struct { | ||||
| @ -50,7 +50,7 @@ func (ctx *SimpleStore) Merge(src ExprContext) { | ||||
| 		ctx.funcStore[name], _ = src.GetFuncInfo(name) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| func varsCtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) { | ||||
| 	sb.WriteString("vars: {\n") | ||||
| 	first := true | ||||
| @ -77,7 +77,7 @@ func varsCtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) { | ||||
| 		} | ||||
| 	} | ||||
| 	sb.WriteString(strings.Repeat("\t", indent)) | ||||
| 	sb.WriteString("\n}\n") | ||||
| 	sb.WriteString("\n}") | ||||
| } | ||||
| 
 | ||||
| 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("\n}\n") | ||||
| 	sb.WriteString("\n}") | ||||
| } | ||||
| 
 | ||||
| func (ctx *SimpleStore) ToString(opt FmtOpt) string { | ||||
| 	var sb strings.Builder | ||||
| 	varsCtxToBuilder(&sb, ctx, 0) | ||||
| 	sb.WriteByte('\n') | ||||
| 	funcsCtxToBuilder(&sb, ctx, 0) | ||||
| 	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) { | ||||
| 	v, exists = ctx.varStore[varName] | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | ||||
| // All rights reserved.
 | ||||
| 
 | ||||
| // t_func-base_test.go
 | ||||
| // t_builtin-base_test.go
 | ||||
| package expr | ||||
| 
 | ||||
| import ( | ||||
| @ -10,7 +10,7 @@ import ( | ||||
| ) | ||||
| 
 | ||||
| func TestFuncBase(t *testing.T) { | ||||
| 	section := "Func-Base" | ||||
| 	section := "Builtin-Base" | ||||
| 
 | ||||
| 	inputs := []inputType{ | ||||
| 		/*   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).
 | ||||
| // All rights reserved.
 | ||||
| 
 | ||||
| // t_func-math-arith_test.go
 | ||||
| // t_builtin-math-arith_test.go
 | ||||
| package expr | ||||
| 
 | ||||
| import ( | ||||
| @ -10,7 +10,7 @@ import ( | ||||
| ) | ||||
| 
 | ||||
| func TestFuncMathArith(t *testing.T) { | ||||
| 	section := "Func-Math-Arith" | ||||
| 	section := "Builtin-Math-Arith" | ||||
| 	inputs := []inputType{ | ||||
| 		/*   1 */ {`builtin "math.arith"; add(1,2)`, int64(3), 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).
 | ||||
| // All rights reserved.
 | ||||
| 
 | ||||
| // t_func-os_test.go
 | ||||
| // t_builtin-os-file_test.go
 | ||||
| package expr | ||||
| 
 | ||||
| import ( | ||||
| @ -10,7 +10,7 @@ import ( | ||||
| ) | ||||
| 
 | ||||
| func TestFuncOs(t *testing.T) { | ||||
| 	section := "Func-OS" | ||||
| 	section := "Builtin-OS-File" | ||||
| 	inputs := []inputType{ | ||||
| 		/*   1 */ {`builtin "os.file"`, int64(1), 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) | ||||
| } | ||||
| @ -110,7 +110,7 @@ func TestDictToStringMultiLine(t *testing.T) { | ||||
| 	var good bool | ||||
| 	section := "dict-ToString-ML" | ||||
| 	want := `{ | ||||
| 	"first": 1 | ||||
|   "first": 1 | ||||
| }` | ||||
| 	args := map[any]*term{ | ||||
| 		"first": newLiteralTerm(NewValueToken(0, 0, SymInteger, "1", 1)), | ||||
|  | ||||
| @ -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) { | ||||
| 	source := NewGolangFunctor(dummy) | ||||
| 	want := "func() {<body>}" | ||||
| 	want := "func() {}" | ||||
| 	got := source.ToString(0) | ||||
| 	if got != 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}, | ||||
| 		/* 23 */ {`#`, SymHash, nil, nil}, | ||||
| 		/* 24 */ {`%`, SymPercent, nil, nil}, | ||||
| 		/* 25 */ {`'`, SymQuote, nil, nil}, | ||||
| 		/* 25 */ {`\'`, SymQuote, nil, nil}, | ||||
| 		/* 26 */ {`\"`, SymDoubleQuote, nil, nil}, | ||||
| 		/* 27 */ {`_`, SymUndescore, nil, nil}, | ||||
| 		/* 28 */ {`<>`, SymLessGreater, nil, nil}, | ||||
|  | ||||
| @ -63,7 +63,7 @@ func TestIsString(t *testing.T) { | ||||
| 	} | ||||
| 
 | ||||
| 	count++ | ||||
| 	b, ok := toBool(true) | ||||
| 	b, ok := ToBool(true) | ||||
| 	if !(ok && b) { | ||||
| 		t.Errorf("%d: toBool(true) b=%v, ok=%v -> result = false, want true", count, b, ok) | ||||
| 		failed++ | ||||
| @ -72,7 +72,7 @@ func TestIsString(t *testing.T) { | ||||
| 	} | ||||
| 
 | ||||
| 	count++ | ||||
| 	b, ok = toBool("abc") | ||||
| 	b, ok = ToBool("abc") | ||||
| 	if !(ok && b) { | ||||
| 		t.Errorf("%d: toBool(\"abc\") b=%v, ok=%v -> result = false, want true", count, b, ok) | ||||
| 		failed++ | ||||
| @ -81,7 +81,7 @@ func TestIsString(t *testing.T) { | ||||
| 	} | ||||
| 
 | ||||
| 	count++ | ||||
| 	b, ok = toBool([]int{}) | ||||
| 	b, ok = ToBool([]int{}) | ||||
| 	if ok { | ||||
| 		t.Errorf("%d: toBool([]) b=%v, ok=%v -> result = true, want false", count, b, ok) | ||||
| 		failed++ | ||||
| @ -97,7 +97,7 @@ func TestToIntOk(t *testing.T) { | ||||
| 	wantValue := int(64) | ||||
| 	wantErr := error(nil) | ||||
| 
 | ||||
| 	gotValue, gotErr := toInt(source, "test") | ||||
| 	gotValue, gotErr := ToInt(source, "test") | ||||
| 
 | ||||
| 	if gotErr != nil || gotValue != wantValue { | ||||
| 		t.Errorf("toInt(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v", | ||||
| @ -110,7 +110,7 @@ func TestToIntErr(t *testing.T) { | ||||
| 	wantValue := 0 | ||||
| 	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 { | ||||
| 		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 | ||||
| } | ||||
| 
 | ||||
| func toBool(v any) (b bool, ok bool) { | ||||
| func ToBool(v any) (b bool, ok bool) { | ||||
| 	ok = true | ||||
| 	switch x := v.(type) { | ||||
| 	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) | ||||
| } | ||||
| 
 | ||||
| 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 { | ||||
| 		i = int(valueInt64) | ||||
| 	} else if valueInt, ok := value.(int); ok { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user