func list(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "list", parser.VALUE_FUNCTION) if err != nil { return err } if values[0].F.Type != parser.FUNCTION_LAMBDA { return util.NewInvalidArgumentError("list", "expected a lambda", context.Token.Line, context.Token.Column, context.Token.File) } err = values[0].F.L.Exec() if err != nil { return err } var data []*parser.Value list := parser.NewListValue() for values[0].F.L.Stack.Len() > 0 { data = append(data, values[0].F.L.Stack.Pop().(*parser.Value)) } for i := len(data) - 1; i >= 0; i-- { list.L = append(list.L, data[i]) } context.Block.Stack.Push(list) return nil }
func listFilter(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "list-filter", parser.VALUE_FUNCTION, parser.VALUE_LIST) if err != nil { return err } list := parser.NewListValue() for _, item := range values[1].L { block, err := execFunctionWithArguments(context, values[0].F, "list-filter", false, item) if err != nil { return err } if block.Stack.Len() == 1 { b := block.Stack.Pop().(*parser.Value) if b.Type != parser.VALUE_BOOL { return util.NewInvalidArgumentError("list-filter", "callback function should have a boolean value on the stack, found "+b.Type.String(), context.Token.Line, context.Token.Column, context.Token.File) } if b.B { list.L = append(list.L, item) } } else { return util.NewInvalidArgumentError("list-filter", fmt.Sprintf("callback function needs to exactly have 1 boolean value on top of the stack, found %d", block.Stack.Len()), context.Token.Line, context.Token.Column, context.Token.File) } } context.Block.Stack.Push(list) return nil }
func listSeq(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "list-seq", parser.VALUE_NUMBER, parser.VALUE_NUMBER) if err != nil { return err } newList := parser.NewListValue() min, _ := values[1].N.Float64() max, _ := values[0].N.Float64() if int(min) > int(max) { for i := int(min); i >= int(max); i-- { newList.L = append(newList.L, parser.NewValueFromInt64(int64(i))) } } else { for i := int(min); i <= int(max); i++ { newList.L = append(newList.L, parser.NewValueFromInt64(int64(i))) } } context.Block.Stack.Push(newList) return nil }
func listMap(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "list-map", parser.VALUE_FUNCTION, parser.VALUE_LIST) if err != nil { return err } list := parser.NewListValue() for _, item := range values[1].L { block, err := execFunctionWithArguments(context, values[0].F, "list-map", false, item) if err != nil { return err } for block.Stack.Len() > 0 { list.L = append(list.L, block.Stack.Pop().(*parser.Value)) } } context.Block.Stack.Push(list) return nil }
func keep(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "keep", parser.VALUE_NUMBER) if err != nil { return err } n, _ := values[0].N.Float64() if int(n) < 0 || int(n) > context.Block.Stack.Len() { return util.NewInvalidArgumentError("keep", fmt.Sprintf("cannot keep %d values while stack height is %d", int(n), context.Block.Stack.Len()), context.Token.Line, context.Token.Column, context.Token.File) } var kept []*parser.Value for i := 0; i < int(n); i++ { kept = append(kept, context.Block.Stack.Pop().(*parser.Value)) } for context.Block.Stack.Len() > 0 { context.Block.Stack.Pop() } for i := len(kept) - 1; i >= 0; i-- { context.Block.Stack.Push(kept[i]) } return nil }
func stringFormat(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "string-format", parser.VALUE_STRING) if err != nil { return err } format := values[0].S count := strings.Count(format, "{}") if count > context.Block.Stack.Len() { return util.NewArgumentCountError("string-format", count, context.Block.Stack.Len(), context.Token.Line, context.Token.Column, context.Token.File) } var items []*parser.Value for i := 0; i < count; i++ { items = append(items, context.Block.Stack.Pop().(*parser.Value)) } for i := count - 1; i >= 0; i-- { format = strings.Replace(format, "{}", items[i].String(), 1) } context.Block.Stack.Push(parser.NewValueFromString(format)) return nil }
func stringRange(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "string-range", parser.VALUE_NUMBER, parser.VALUE_NUMBER, parser.VALUE_STRING) if err != nil { return err } beginf, _ := values[1].N.Float64() endf, _ := values[0].N.Float64() begin := int(beginf) end := int(endf) s := values[2].S if begin < 0 || begin > len(s)-1 { return util.NewInvalidArgumentError("string-range", fmt.Sprintf("%d out of range (string length is: %d)", begin, len(s)), context.Token.Line, context.Token.Column, context.Token.File) } if end < begin { return util.NewInvalidArgumentError("string-range", fmt.Sprintf("%d must be bigger then %d", end, begin), context.Token.Line, context.Token.Column, context.Token.File) } if end < 0 || end > len(s)-1 { return util.NewInvalidArgumentError("string-range", fmt.Sprintf("%d out of range (string length is: %d)", end, len(s)), context.Token.Line, context.Token.Column, context.Token.File) } context.Block.Stack.Push(parser.NewValueFromString(s[begin : end+1])) return nil }
func while_(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "while", parser.VALUE_FUNCTION, parser.VALUE_FUNCTION) if err != nil { return err } check := values[0].F recheck: fakeBlock := parser.NewBlock(nil, nil, nil) checkErr := check.Exec(fakeBlock, context.Token) if checkErr != nil { return checkErr } if fakeBlock.Stack.Len() != 1 || fakeBlock.Stack.Peek(0).(*parser.Value).Type != parser.VALUE_BOOL { return util.NewInvalidArgumentError("while", "the callback function provided to while must return 1 boolean value", context.Token.Line, context.Token.Column, context.Token.File) } if fakeBlock.Stack.Peek(0).(*parser.Value).B { runErr := values[1].F.Exec(context.Block, context.Token) if runErr != nil { return runErr } goto recheck } return nil }
func orN(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "or-n", parser.VALUE_FUNCTION) if err != nil { return err } fakeBlock := parser.NewBlock(nil, nil, nil) runErr := values[0].F.Exec(fakeBlock, context.Token) if runErr != nil { return runErr } result := false if fakeBlock.Stack.Len() >= 1 { for fakeBlock.Stack.Len() > 0 { value := fakeBlock.Stack.Pop().(*parser.Value) if value.Type != parser.VALUE_BOOL { return util.NewInvalidArgumentError("or-n", "expected a boolean in the function stack", context.Token.Line, context.Token.Column, context.Token.File) } result = result || value.B } } else { return util.NewInvalidArgumentError("or-n", "expected at least 2 values to compare in function stack", context.Token.Line, context.Token.Column, context.Token.File) } context.Block.Stack.Push(parser.NewValueFromBool(result)) return nil }
func listRange(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "list-range", parser.VALUE_NUMBER, parser.VALUE_NUMBER, parser.VALUE_LIST) if err != nil { return err } newList := parser.NewListValue() list := values[2].L start, _ := values[1].N.Float64() end, _ := values[0].N.Float64() if int(start) > int(end) || int(end) >= len(list) || int(start) < 0 || int(end) < 0 { return util.NewInvalidArgumentError("list-range", "invalid bounds", context.Token.Line, context.Token.Column, context.Token.File) } for i := int(start); i <= int(end); i++ { newList.L = append(newList.L, list[i]) } context.Block.Stack.Push(newList) return nil }
func fileRemove(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "file-remove", parser.VALUE_STRING) if err != nil { return err } return os.Remove(values[0].S) }
func call(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "call", parser.VALUE_FUNCTION) if err != nil { return err } return values[0].F.Exec(context.Block, context.Token) }
func drop(context *parser.FunctionCallContext) error { _, err := parser.ValidateArguments(context, "drop", parser.VALUE_ANY) if err != nil { return err } return nil }
func print_(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "print", parser.VALUE_ANY) if err != nil { return err } fmt.Print(values[0]) return nil }
func stringAt(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "string-at", parser.VALUE_STRING, parser.VALUE_STRING) if err != nil { return err } context.Block.Stack.Push(parser.NewValueFromInt64(int64(strings.Index(values[1].S, values[0].S)))) return nil }
func clone(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "clone", parser.VALUE_ANY) if err != nil { return err } context.Block.Stack.Push(values[0].Copy()) return nil }
func stringLength(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "string-length", parser.VALUE_STRING) if err != nil { return err } context.Block.Stack.Push(parser.NewValueFromInt64(int64(len(values[0].S)))) return nil }
func fileCreate(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "file-create", parser.VALUE_STRING) if err != nil { return err } _, err = os.Create(values[0].S) return err }
func stringUpper(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "string-upper", parser.VALUE_STRING) if err != nil { return err } context.Block.Stack.Push(parser.NewValueFromString(strings.ToUpper(values[0].S))) return nil }
func abs(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "abs", parser.VALUE_NUMBER) if err != nil { return err } context.Block.Stack.Push(parser.NewValueFromRat(big.NewRat(0, 1).Abs(values[0].N))) return nil }
func xor(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "xor", parser.VALUE_BOOL, parser.VALUE_BOOL) if err != nil { return err } context.Block.Stack.Push(parser.NewValueFromBool(values[0].B || values[1].B && !(values[0].B && values[1].B))) return nil }
func stringCat(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "string-cat", parser.VALUE_ANY, parser.VALUE_ANY) if err != nil { return err } context.Block.Stack.Push(parser.NewValueFromString(values[1].String() + values[0].String())) return nil }
func err(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "err", parser.VALUE_ANY) if err != nil { return err } context.Block.Stack.Push(parser.NewErrorValue(values[0])) return nil }
func stringContains(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "string-contains?", parser.VALUE_STRING, parser.VALUE_STRING) if err != nil { return err } context.Block.Stack.Push(parser.NewValueFromBool(strings.Contains(values[1].S, values[0].S))) return nil }
func not(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "not", parser.VALUE_BOOL) if err != nil { return err } context.Block.Stack.Push(parser.NewValueFromBool(!values[0].B)) return nil }
func fileMkdir(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "file-mkdir", parser.VALUE_STRING, parser.VALUE_NUMBER) if err != nil { return err } perms, _ := values[1].N.Float64() return os.Mkdir(values[0].String(), os.FileMode(perms)) }
func ne(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "ne?", parser.VALUE_ANY, parser.VALUE_ANY) if err != nil { return err } context.Block.Stack.Push(parser.NewValueFromBool(!values[0].Equals(values[1]))) return nil }
func le(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "le?", parser.VALUE_NUMBER, parser.VALUE_NUMBER) if err != nil { return err } context.Block.Stack.Push(parser.NewValueFromBool(values[1].N.Cmp(values[0].N) <= 0)) return nil }
func listSize(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "list-size", parser.VALUE_LIST) if err != nil { return err } context.Block.Stack.Push(parser.NewValueFromInt64(int64(len(values[0].L)))) return nil }
func fileBase(context *parser.FunctionCallContext) error { values, err := parser.ValidateArguments(context, "file-base", parser.VALUE_STRING) if err != nil { return err } context.Block.Stack.Push(parser.NewValueFromString(filepath.Base(values[0].S))) return nil }