Compare commits
	
		
			15 Commits
		
	
	
		
			a02f998fc6
			...
			234759158c
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 234759158c | |||
| 00fda29606 | |||
| 2a2840bdf2 | |||
| 06373f5126 | |||
| e69dad5fb5 | |||
| 7459057df9 | |||
| 176969c956 | |||
| cde2efacf1 | |||
| d7a7b3218c | |||
| be3bb12f28 | |||
| 032916d4fa | |||
| f3cc0cc7ad | |||
| 905337f963 | |||
| 9a95a837f6 | |||
| 8547248ea2 | 
							
								
								
									
										4
									
								
								ast.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								ast.go
									
									
									
									
									
								
							| @ -19,6 +19,10 @@ func NewAst() *ast { | |||||||
| 	return &ast{} | 	return &ast{} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (expr *ast) TypeName() string { | ||||||
|  | 	return "Expression" | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (expr *ast) ToForest() { | func (expr *ast) ToForest() { | ||||||
| 	if expr.root != nil { | 	if expr.root != nil { | ||||||
| 		if expr.forest == nil { | 		if expr.forest == nil { | ||||||
|  | |||||||
| @ -29,6 +29,10 @@ func newExprFunctor(e Expr, params []ExprFuncParam, ctx ExprContext) *exprFuncto | |||||||
| 	return &exprFunctor{expr: e, params: params, defCtx: defCtx} | 	return &exprFunctor{expr: e, params: params, defCtx: defCtx} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (functor *exprFunctor) TypeName() string { | ||||||
|  | 	return "ExprFunctor" | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (functor *exprFunctor) GetDefinitionContext() ExprContext { | func (functor *exprFunctor) GetDefinitionContext() ExprContext { | ||||||
| 	return functor.defCtx | 	return functor.defCtx | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,6 +14,10 @@ func NewGolangFunctor(f FuncTemplate) *golangFunctor { | |||||||
| 	return &golangFunctor{f: f} | 	return &golangFunctor{f: f} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (functor *golangFunctor) TypeName() string { | ||||||
|  | 	return "GoFunctor" | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (functor *golangFunctor) Invoke(ctx ExprContext, name string, args []any) (result any, err error) { | func (functor *golangFunctor) Invoke(ctx ExprContext, name string, args []any) (result any, err error) { | ||||||
| 	return functor.f(ctx, name, args) | 	return functor.f(ctx, name, args) | ||||||
| } | } | ||||||
|  | |||||||
| @ -133,54 +133,79 @@ func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (dc *dataCursor) _Next() (item any, err error) { // must return io.EOF after the last item
 | // func (dc *dataCursor) _Next() (item any, err error) { // must return io.EOF after the last item
 | ||||||
| 	if dc.resource != nil { | // 	if dc.resource != nil {
 | ||||||
| 		ctx := cloneContext(dc.ctx) | // 		ctx := cloneContext(dc.ctx)
 | ||||||
| 		// fmt.Printf("Entering Inner-Ctx [%p]: %s\n", ctx, CtxToString(ctx, 0))
 | // 		// fmt.Printf("Entering Inner-Ctx [%p]: %s\n", ctx, CtxToString(ctx, 0))
 | ||||||
| 		if item, err = dc.nextFunc.Invoke(ctx, nextName, []any{dc.resource}); err == nil { | // 		if item, err = dc.nextFunc.Invoke(ctx, nextName, []any{dc.resource}); err == nil {
 | ||||||
| 			if item == nil { | // 			if item == nil {
 | ||||||
| 				err = io.EOF | // 				err = io.EOF
 | ||||||
| 			} else { | // 			} else {
 | ||||||
| 				dc.index++ | // 				dc.index++
 | ||||||
| 			} | // 			}
 | ||||||
| 		} | // 		}
 | ||||||
| 		// fmt.Printf("Exiting Inner-Ctx [%p]: %s\n", ctx, CtxToString(ctx, 0))
 | // 		// fmt.Printf("Exiting Inner-Ctx [%p]: %s\n", ctx, CtxToString(ctx, 0))
 | ||||||
| 		exportObjects(dc.ctx, ctx) | // 		exportObjects(dc.ctx, ctx)
 | ||||||
| 		// fmt.Printf("Outer-Ctx [%p]: %s\n", dc.ctx, CtxToString(dc.ctx, 0))
 | // 		// fmt.Printf("Outer-Ctx [%p]: %s\n", dc.ctx, CtxToString(dc.ctx, 0))
 | ||||||
| 	} else { | // 	} else {
 | ||||||
| 		err = errInvalidDataSource() | // 		err = errInvalidDataSource()
 | ||||||
|  | // 	}
 | ||||||
|  | // 	return
 | ||||||
|  | // }
 | ||||||
|  | 
 | ||||||
|  | // func (dc *dataCursor) _filter(item any) (filterdItem any, err error) {
 | ||||||
|  | // 	if filter, ok := dc.ds[filterName]; ok {
 | ||||||
|  | // 		ctx := cloneContext(dc.ctx)
 | ||||||
|  | // 		filterdItem, err = filter.Invoke(ctx, filterName, []any{item, dc.index})
 | ||||||
|  | // 	} else {
 | ||||||
|  | // 		filterdItem = item
 | ||||||
|  | // 	}
 | ||||||
|  | // 	return
 | ||||||
|  | // }
 | ||||||
|  | 
 | ||||||
|  | func (dc *dataCursor) checkFilter(filter Functor, item any) (accepted bool, err error) { | ||||||
|  | 	var v any | ||||||
|  | 	var ok bool | ||||||
|  | 	ctx := cloneContext(dc.ctx) | ||||||
|  | 	if v, err = filter.Invoke(ctx, filterName, []any{item, dc.index}); err == nil && v != nil { | ||||||
|  | 		if accepted, ok = v.(bool); !ok { | ||||||
|  | 			accepted = true  // NOTE: A non-boolean value that is not nil means the item has been accepted
 | ||||||
|  | 		}  | ||||||
| 	} | 	} | ||||||
|  | 	 | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | func (dc *dataCursor) mapItem(mapper Functor, item any) (mappedItem any, err error) { | ||||||
| const filterName = "filter" | 	ctx := cloneContext(dc.ctx) | ||||||
| func (dc *dataCursor) filter(item any) (filterdItem any, err error) { | 	mappedItem, err = mapper.Invoke(ctx, mapName, []any{item, dc.index}); | ||||||
| 	if filter, ok := dc.ds[filterName]; ok { |  | ||||||
| 		ctx := cloneContext(dc.ctx) |  | ||||||
| 		filterdItem, err = filter.Invoke(ctx, filterName, []any{item, dc.index}); |  | ||||||
| 	} else { |  | ||||||
| 		filterdItem = item |  | ||||||
| 	} |  | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (dc *dataCursor) Next() (item any, err error) { // must return io.EOF after the last item
 | func (dc *dataCursor) Next() (item any, err error) { // must return io.EOF after the last item
 | ||||||
|  | 	var accepted bool | ||||||
| 	if dc.resource != nil { | 	if dc.resource != nil { | ||||||
| 		ctx := cloneContext(dc.ctx) | 		filter := dc.ds[filterName] | ||||||
| 		// fmt.Printf("Entering Inner-Ctx [%p]: %s\n", ctx, CtxToString(ctx, 0))
 | 		mapper := dc.ds[mapName] | ||||||
|  | 
 | ||||||
| 		for item == nil && err == nil { | 		for item == nil && err == nil { | ||||||
|  | 			ctx := cloneContext(dc.ctx) | ||||||
| 			if item, err = dc.nextFunc.Invoke(ctx, nextName, []any{dc.resource}); err == nil { | 			if item, err = dc.nextFunc.Invoke(ctx, nextName, []any{dc.resource}); err == nil { | ||||||
| 				if item == nil { | 				if item == nil { | ||||||
| 					err = io.EOF | 					err = io.EOF | ||||||
| 				} else { | 				} else { | ||||||
| 					dc.index++ | 					dc.index++ | ||||||
| 					item, err = dc.filter(item) | 					if filter != nil { | ||||||
|  | 						if accepted, err = dc.checkFilter(filter, item); err != nil || !accepted { | ||||||
|  | 							item = nil | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					if item != nil && mapper != nil { | ||||||
|  | 						item, err = dc.mapItem(mapper, item) | ||||||
|  | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | 			exportObjects(dc.ctx, ctx) | ||||||
| 		} | 		} | ||||||
| 		// fmt.Printf("Exiting Inner-Ctx [%p]: %s\n", ctx, CtxToString(ctx, 0))
 |  | ||||||
| 		exportObjects(dc.ctx, ctx) |  | ||||||
| 		// fmt.Printf("Outer-Ctx [%p]: %s\n", dc.ctx, CtxToString(dc.ctx, 0))
 |  | ||||||
| 	} else { | 	} else { | ||||||
| 		err = errInvalidDataSource() | 		err = errInvalidDataSource() | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -14,8 +14,15 @@ type ExprContext interface { | |||||||
| 	GetLast() any | 	GetLast() any | ||||||
| 	SetVar(varName string, value any) | 	SetVar(varName string, value any) | ||||||
| 	UnsafeSetVar(varName string, value any) | 	UnsafeSetVar(varName string, value any) | ||||||
|  | 
 | ||||||
| 	EnumVars(func(name string) (accept bool)) (varNames []string) | 	EnumVars(func(name string) (accept bool)) (varNames []string) | ||||||
|  | 	VarCount() int | ||||||
|  | 	DeleteVar(varName string) | ||||||
|  | 
 | ||||||
| 	EnumFuncs(func(name string) (accept bool)) (funcNames []string) | 	EnumFuncs(func(name string) (accept bool)) (funcNames []string) | ||||||
|  | 	FuncCount() int | ||||||
|  | 	DeleteFunc(funcName string) | ||||||
|  | 
 | ||||||
| 	GetFuncInfo(name string) (item ExprFunc, exists bool) | 	GetFuncInfo(name string) (item ExprFunc, exists bool) | ||||||
| 	Call(name string, args []any) (result any, err error) | 	Call(name string, args []any) (result any, err error) | ||||||
| 	RegisterFuncInfo(info ExprFunc) | 	RegisterFuncInfo(info ExprFunc) | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ package expr | |||||||
| 
 | 
 | ||||||
| // ---- Functor interface
 | // ---- Functor interface
 | ||||||
| type Functor interface { | type Functor interface { | ||||||
|  | 	Typer | ||||||
| 	Invoke(ctx ExprContext, name string, args []any) (result any, err error) | 	Invoke(ctx ExprContext, name string, args []any) (result any, err error) | ||||||
| 	SetFunc(info ExprFunc) | 	SetFunc(info ExprFunc) | ||||||
| 	GetFunc() ExprFunc | 	GetFunc() ExprFunc | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								expr.go
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								expr.go
									
									
									
									
									
								
							| @ -6,6 +6,7 @@ package expr | |||||||
| 
 | 
 | ||||||
| // ----Expression interface
 | // ----Expression interface
 | ||||||
| type Expr interface { | type Expr interface { | ||||||
|  | 	Typer | ||||||
| 	Eval(ctx ExprContext) (result any, err error) | 	Eval(ctx ExprContext) (result any, err error) | ||||||
| 	String() string | 	String() string | ||||||
| } | } | ||||||
|  | |||||||
| @ -19,6 +19,8 @@ const ( | |||||||
| 	currentName = "current" | 	currentName = "current" | ||||||
| 	indexName   = "index" | 	indexName   = "index" | ||||||
| 	countName   = "count" | 	countName   = "count" | ||||||
|  | 	filterName  = "filter" | ||||||
|  | 	mapName     = "map" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type Iterator interface { | type Iterator interface { | ||||||
|  | |||||||
| @ -90,16 +90,20 @@ func (it *ListIterator) TypeName() string { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (it *ListIterator) HasOperation(name string) bool { | func (it *ListIterator) HasOperation(name string) bool { | ||||||
| 	yes := name == resetName || name == indexName || name == countName | 	yes := name == nextName || name == resetName || name == indexName || name == countName || name == currentName | ||||||
| 	return yes | 	return yes | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (it *ListIterator) CallOperation(name string, args []any) (v any, err error) { | func (it *ListIterator) CallOperation(name string, args []any) (v any, err error) { | ||||||
| 	switch name { | 	switch name { | ||||||
|  | 	case nextName: | ||||||
|  | 		v, err = it.Next() | ||||||
| 	case resetName: | 	case resetName: | ||||||
| 		v, err = it.Reset() | 		v, err = it.Reset() | ||||||
| 	case indexName: | 	case indexName: | ||||||
| 		v = int64(it.Index()) | 		v = int64(it.Index()) | ||||||
|  | 	case currentName: | ||||||
|  | 		v, err = it.Current() | ||||||
| 	case countName: | 	case countName: | ||||||
| 		v = it.count | 		v = it.count | ||||||
| 	default: | 	default: | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ func newDefaultTerm(tk *Token) (inst *term) { | |||||||
| 		tk:       *tk, | 		tk:       *tk, | ||||||
| 		children: make([]*term, 0, 2), | 		children: make([]*term, 0, 2), | ||||||
| 		position: posInfix, | 		position: posInfix, | ||||||
| 		priority: priCoalesce, | 		priority: priDefault, | ||||||
| 		evalFunc: evalDefault, | 		evalFunc: evalDefault, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @ -45,7 +45,7 @@ func newAlternateTerm(tk *Token) (inst *term) { | |||||||
| 		tk:       *tk, | 		tk:       *tk, | ||||||
| 		children: make([]*term, 0, 2), | 		children: make([]*term, 0, 2), | ||||||
| 		position: posInfix, | 		position: posInfix, | ||||||
| 		priority: priCoalesce, | 		priority: priDefault, | ||||||
| 		evalFunc: evalAlternate, | 		evalFunc: evalAlternate, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @ -81,7 +81,7 @@ func newDefaultAssignTerm(tk *Token) (inst *term) { | |||||||
| 		tk:       *tk, | 		tk:       *tk, | ||||||
| 		children: make([]*term, 0, 2), | 		children: make([]*term, 0, 2), | ||||||
| 		position: posInfix, | 		position: posInfix, | ||||||
| 		priority: priCoalesce, | 		priority: priDefault, | ||||||
| 		evalFunc: evalAssignDefault, | 		evalFunc: evalAssignDefault, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -25,8 +25,8 @@ func evalInclude(ctx ExprContext, opTerm *term) (v any, err error) { | |||||||
| 
 | 
 | ||||||
| 	count := 0 | 	count := 0 | ||||||
| 	if IsList(childValue) { | 	if IsList(childValue) { | ||||||
| 		list, _ := childValue.([]any) | 		list, _ := childValue.(*ListType) | ||||||
| 		for i, filePathSpec := range list { | 		for i, filePathSpec := range *list { | ||||||
| 			if filePath, ok := filePathSpec.(string); ok { | 			if filePath, ok := filePathSpec.(string); ok { | ||||||
| 				if v, err = EvalFile(ctx, filePath); err == nil { | 				if v, err = EvalFile(ctx, filePath); err == nil { | ||||||
| 					count++ | 					count++ | ||||||
| @ -47,8 +47,9 @@ func evalInclude(ctx ExprContext, opTerm *term) (v any, err error) { | |||||||
| 	} else { | 	} else { | ||||||
| 		err = opTerm.errIncompatibleType(childValue) | 		err = opTerm.errIncompatibleType(childValue) | ||||||
| 	} | 	} | ||||||
| 	if err == nil { | 	if err != nil { | ||||||
| 		v = count | 		//v = count
 | ||||||
|  | 		v = nil | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | |||||||
| @ -33,5 +33,6 @@ func evalIterValue(ctx ExprContext, opTerm *term) (v any, err error) { | |||||||
| 
 | 
 | ||||||
| // init
 | // init
 | ||||||
| func init() { | func init() { | ||||||
| 	registerTermConstructor(SymOpenClosedRound, newIterValueTerm) | //	registerTermConstructor(SymOpenClosedRound, newIterValueTerm)
 | ||||||
|  | 	registerTermConstructor(SymCaret, newIterValueTerm) | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										69
									
								
								operator-unset.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								operator-unset.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,69 @@ | |||||||
|  | // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | ||||||
|  | // All rights reserved.
 | ||||||
|  | 
 | ||||||
|  | // operator-unset.go
 | ||||||
|  | package expr | ||||||
|  | 
 | ||||||
|  | import "strings" | ||||||
|  | 
 | ||||||
|  | //-------- unset term
 | ||||||
|  | 
 | ||||||
|  | func newUnsetTerm(tk *Token) (inst *term) { | ||||||
|  | 	return &term{ | ||||||
|  | 		tk:       *tk, | ||||||
|  | 		children: make([]*term, 0, 1), | ||||||
|  | 		position: posPrefix, | ||||||
|  | 		priority: priSign, | ||||||
|  | 		evalFunc: evalUnset, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func deleteContextItem(ctx ExprContext, opTerm *term, item any) (deleted bool, err error) { | ||||||
|  | 	if name, ok := item.(string); ok { | ||||||
|  | 		var size int | ||||||
|  | 		if strings.HasSuffix(name, "()") { | ||||||
|  | 			size = ctx.FuncCount() | ||||||
|  | 			ctx.DeleteFunc(strings.TrimRight(name, "()")) | ||||||
|  | 			deleted = ctx.FuncCount() < size | ||||||
|  | 		} else { | ||||||
|  | 			size = ctx.VarCount() | ||||||
|  | 			ctx.DeleteVar(name) | ||||||
|  | 			deleted = ctx.VarCount() < size | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		err = opTerm.errIncompatibleType(item) | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func evalUnset(ctx ExprContext, opTerm *term) (v any, err error) { | ||||||
|  | 	var childValue any | ||||||
|  | 	var deleted bool | ||||||
|  | 
 | ||||||
|  | 	if childValue, err = opTerm.evalPrefix(ctx); err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	count := 0 | ||||||
|  | 	if IsList(childValue) { | ||||||
|  | 		list, _ := childValue.(*ListType) | ||||||
|  | 		for _, item := range *list { | ||||||
|  | 			if deleted, err = deleteContextItem(ctx, opTerm, item); err != nil { | ||||||
|  | 				break | ||||||
|  | 			} else if deleted { | ||||||
|  | 				count++ | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} else if deleted, err = deleteContextItem(ctx, opTerm, childValue); err == nil && deleted { | ||||||
|  | 		count++ | ||||||
|  | 	} | ||||||
|  | 	if err == nil { | ||||||
|  | 		v = int64(count) | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // init
 | ||||||
|  | func init() { | ||||||
|  | 	registerTermConstructor(SymKwUnset, newUnsetTerm) | ||||||
|  | } | ||||||
| @ -269,11 +269,11 @@ func (scanner *scanner) fetchNextToken() (tk *Token) { | |||||||
| 				tk = scanner.makeToken(SymDollar, ch) | 				tk = scanner.makeToken(SymDollar, ch) | ||||||
| 			} | 			} | ||||||
| 		case '(': | 		case '(': | ||||||
| 			if next, _ := scanner.peek(); next == ')' { | //			if next, _ := scanner.peek(); next == ')' {
 | ||||||
| 				tk = scanner.moveOn(SymOpenClosedRound, ch, next) | //				tk = scanner.moveOn(SymOpenClosedRound, ch, next)
 | ||||||
| 			} else { | //			} else {
 | ||||||
| 				tk = scanner.makeToken(SymOpenRound, ch) | 				tk = scanner.makeToken(SymOpenRound, ch) | ||||||
| 			} | //			}
 | ||||||
| 		case ')': | 		case ')': | ||||||
| 			tk = scanner.makeToken(SymClosedRound, ch) | 			tk = scanner.makeToken(SymClosedRound, ch) | ||||||
| 		case '[': | 		case '[': | ||||||
|  | |||||||
| @ -132,6 +132,14 @@ func (ctx *SimpleStore) EnumVars(acceptor func(name string) (accept bool)) (varN | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (ctx *SimpleStore) VarCount() int { | ||||||
|  | 	return len(ctx.varStore) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (ctx *SimpleStore) DeleteVar(varName string) { | ||||||
|  | 	delete(ctx.varStore, varName) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (ctx *SimpleStore) GetFuncInfo(name string) (info ExprFunc, exists bool) { | func (ctx *SimpleStore) GetFuncInfo(name string) (info ExprFunc, exists bool) { | ||||||
| 	info, exists = ctx.funcStore[name] | 	info, exists = ctx.funcStore[name] | ||||||
| 	return | 	return | ||||||
| @ -163,6 +171,14 @@ func (ctx *SimpleStore) EnumFuncs(acceptor func(name string) (accept bool)) (fun | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (ctx *SimpleStore) FuncCount() int { | ||||||
|  | 	return len(ctx.funcStore) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (ctx *SimpleStore) DeleteFunc(funcName string) { | ||||||
|  | 	delete(ctx.funcStore, funcName) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (ctx *SimpleStore) Call(name string, args []any) (result any, err error) { | func (ctx *SimpleStore) Call(name string, args []any) (result any, err error) { | ||||||
| 	if info, exists := GetLocalFuncInfo(ctx, name); exists { | 	if info, exists := GetLocalFuncInfo(ctx, name); exists { | ||||||
| 		functor := info.Functor() | 		functor := info.Functor() | ||||||
|  | |||||||
| @ -106,6 +106,7 @@ const ( | |||||||
| 	SymKwIn | 	SymKwIn | ||||||
| 	SymKwInclude | 	SymKwInclude | ||||||
| 	SymKwNil | 	SymKwNil | ||||||
|  | 	SymKwUnset | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var keywords map[string]Symbol | var keywords map[string]Symbol | ||||||
| @ -123,5 +124,6 @@ func init() { | |||||||
| 		"NOT":     SymKwNot, | 		"NOT":     SymKwNot, | ||||||
| 		"OR":      SymKwOr, | 		"OR":      SymKwOr, | ||||||
| 		"NIL":     SymKwNil, | 		"NIL":     SymKwNil, | ||||||
|  | 		"UNSET":   SymKwUnset, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -30,13 +30,14 @@ func TestFuncs(t *testing.T) { | |||||||
| 		/*  17 */ {`f=func(x,n){1}; f(3,4,)`, nil, `[1:24] expected "function-param-value", got ")"`}, | 		/*  17 */ {`f=func(x,n){1}; f(3,4,)`, nil, `[1:24] expected "function-param-value", got ")"`}, | ||||||
| 		/*  18 */ {`factory=func(base){func(){@base=base+1}}; inc10=factory(10); inc5=factory(5); inc10(); inc5(); inc10()`, int64(12), nil}, | 		/*  18 */ {`factory=func(base){func(){@base=base+1}}; inc10=factory(10); inc5=factory(5); inc10(); inc5(); inc10()`, int64(12), nil}, | ||||||
| 		/*  19 */ {`f=func(a,y=1,z="sos"){}; string(f)`, `f(a, y=1, z="sos"):any{}`, nil}, | 		/*  19 */ {`f=func(a,y=1,z="sos"){}; string(f)`, `f(a, y=1, z="sos"):any{}`, nil}, | ||||||
|  | //		/*  20 */ {`a=[func(){3}]; a[0]()`, int64(3), nil},
 | ||||||
| //		/*  20 */ {`m={}; m["f"]=func(){3}; m["f"]()`, int64(3), nil},
 | //		/*  20 */ {`m={}; m["f"]=func(){3}; m["f"]()`, int64(3), nil},
 | ||||||
| 		// /*  18 */ {`f=func(a){a*2}`, nil, errors.New(`[1:24] expected "function-param-value", got ")"`)},
 | 		// /*  18 */ {`f=func(a){a*2}`, nil, errors.New(`[1:24] expected "function-param-value", got ")"`)},
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// t.Setenv("EXPR_PATH", ".")
 | 	// t.Setenv("EXPR_PATH", ".")
 | ||||||
| 
 | 
 | ||||||
| 	// runTestSuiteSpec(t, section, inputs, 20)
 | 	//runTestSuiteSpec(t, section, inputs, 20)
 | ||||||
| 	runTestSuite(t, section, inputs) | 	runTestSuite(t, section, inputs) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -20,7 +20,11 @@ func TestIteratorParser(t *testing.T) { | |||||||
| 		/*   9 */ {`include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); it.clean`, true, nil}, | 		/*   9 */ {`include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); it.clean`, true, nil}, | ||||||
| 		/*  10 */ {`it=$(1,2,3); it++`, int64(1), nil}, | 		/*  10 */ {`it=$(1,2,3); it++`, int64(1), nil}, | ||||||
| 		/*  11 */ {`it=$(1,2,3); it++; it.reset; it++`, int64(1), nil}, | 		/*  11 */ {`it=$(1,2,3); it++; it.reset; it++`, int64(1), nil}, | ||||||
| //		/*  12 */ {`include "test-resources/filter.expr"; it=$(ds,10); it++`, int64(1), nil},
 | 		/*  12 */ {`it=$([1,2,3,4],1); it++`, int64(2), nil}, | ||||||
|  | 		/*  13 */ {`it=$([1,2,3,4],1,3); it++; it++;`, int64(3), nil}, | ||||||
|  | 		/*  14 */ {`it=$([1,2,3,4],1,3,2); it++; it++;`, int64(4), nil}, | ||||||
|  | 		/*  15 */ {`it=$([1,2,3,4],1,2,2); it++; it++;`, nil, `EOF`}, | ||||||
|  | 		/*  16 */ {`include "test-resources/filter.expr"; it=$(ds,10); it++`, int64(2), nil}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	//runTestSuiteSpec(t, section, inputs, 12)
 | 	//runTestSuiteSpec(t, section, inputs, 12)
 | ||||||
|  | |||||||
							
								
								
									
										23
									
								
								t_operator_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								t_operator_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | ||||||
|  | // All rights reserved.
 | ||||||
|  | 
 | ||||||
|  | // t_operator_test.go
 | ||||||
|  | package expr | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestOperator(t *testing.T) { | ||||||
|  | 	section := "Operator" | ||||||
|  | 	inputs := []inputType{ | ||||||
|  | 		/*   1 */ {`a=1; unset "a"; a`, nil, `undefined variable or function "a"`}, | ||||||
|  | 		/*   2 */ {`a=1; unset ["a", "b"]`, int64(1), nil}, | ||||||
|  | 		/*   3 */ {`f=func(){3}; unset "f()"`, int64(1), nil}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// t.Setenv("EXPR_PATH", ".")
 | ||||||
|  | 
 | ||||||
|  | 	//runTestSuiteSpec(t, section, inputs, 3)
 | ||||||
|  | 	runTestSuite(t, section, inputs) | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								term.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								term.go
									
									
									
									
									
								
							| @ -26,7 +26,7 @@ const ( | |||||||
| 	priSign | 	priSign | ||||||
| 	priFact | 	priFact | ||||||
| 	priIterValue | 	priIterValue | ||||||
| 	priCoalesce | 	priDefault | ||||||
| 	priIncDec | 	priIncDec | ||||||
| 	priDot | 	priDot | ||||||
| 	priValue | 	priValue | ||||||
|  | |||||||
							
								
								
									
										15
									
								
								test-resources/filter.expr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test-resources/filter.expr
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | ds={ | ||||||
|  | 		"init":func(end){@end=end; @current=0 but true}, | ||||||
|  | 		"current":func(){current}, | ||||||
|  | 		"next":func(){ | ||||||
|  | 			((next=current+1) <= end) ? [true] {@current=next but current} :: {nil} | ||||||
|  | 		} | ||||||
|  | 		,		"filter":func(item,index) { item > 0 } | ||||||
|  | 		,		"map":   func(item,index) { item * 2 } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Example | ||||||
|  | ; | ||||||
|  | it=$(ds,3); | ||||||
|  | add(it) | ||||||
|  | */ | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user