Documentation
¶
Index ¶
Constants ¶
const ( RE_IGNORECASE = 2 // re.I or re.IGNORECASE RE_MULTILINE = 8 // re.M or re.MULTILINE RE_DOTALL = 16 // re.S or re.DOTALL )
Flag constants matching Python's re module
const ( JSONLibraryName = "json" ReLibraryName = "re" TimeLibraryName = "time" DatetimeLibraryName = "datetime" MathLibraryName = "math" Base64LibraryName = "base64" HashlibLibraryName = "hashlib" RandomLibraryName = "random" URLLibLibraryName = "urllib" URLParseLibraryName = "urllib.parse" StringLibraryName = "string" UUIDLibraryName = "uuid" HTMLLibraryName = "html" StatisticsLibraryName = "statistics" FunctoolsLibraryName = "functools" TextwrapLibraryName = "textwrap" PlatformLibraryName = "platform" ItertoolsLibraryName = "itertools" CollectionsLibraryName = "collections" )
Library names as constants for easy reference
Variables ¶
Boolean constants for datetime comparisons
var ( DatetimeClass *object.Class DateClass *object.Class )
Forward declarations for classes (set in init)
var Base64Library = object.NewLibrary(map[string]*object.Builtin{ "b64encode": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } str, err := args[0].AsString() if err != nil { return err } encoded := base64.StdEncoding.EncodeToString([]byte(str)) return &object.String{Value: encoded} }, HelpText: `b64encode(s) - Encode bytes-like object to Base64 Returns a Base64-encoded version of the input string.`, }, "b64decode": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } str, err := args[0].AsString() if err != nil { return err } decoded, decodeErr := base64.StdEncoding.DecodeString(str) if decodeErr != nil { return errors.NewError("base64 decode error: %s", decodeErr.Error()) } return &object.String{Value: string(decoded)} }, HelpText: `b64decode(s) - Decode a Base64 encoded string Returns the decoded string from a Base64-encoded input.`, }, }, nil, "Base64 encoding and decoding library")
var CollectionsLibrary = object.NewLibrary(map[string]*object.Builtin{ "Counter": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { counter := createCounterInstance() if len(args) == 0 { return counter } if err := errors.MaxArgs(args, 1); err != nil { return err } switch arg := args[0].(type) { case *object.List: for _, elem := range arg.Elements { key := elem.Inspect() if countObj, exists := counter.Fields[key]; exists { if count, ok := countObj.(*object.Integer); ok { counter.Fields[key] = object.NewInteger(count.Value + 1) } } else { counter.Fields[key] = object.NewInteger(1) } } case *object.Tuple: for _, elem := range arg.Elements { key := elem.Inspect() if countObj, exists := counter.Fields[key]; exists { if count, ok := countObj.(*object.Integer); ok { counter.Fields[key] = object.NewInteger(count.Value + 1) } } else { counter.Fields[key] = object.NewInteger(1) } } case *object.String: for _, ch := range arg.Value { key := string(ch) if countObj, exists := counter.Fields[key]; exists { if count, ok := countObj.(*object.Integer); ok { counter.Fields[key] = object.NewInteger(count.Value + 1) } } else { counter.Fields[key] = object.NewInteger(1) } } case *object.Dict: for k, v := range arg.Pairs { if count, ok := v.Value.(*object.Integer); ok { counter.Fields[k] = count } } default: return errors.NewTypeError("iterable or dict", args[0].Type().String()) } return counter }, HelpText: `Counter([iterable]) - Count elements Creates a Counter object that counts occurrences of elements. Example: c = collections.Counter([1, 1, 2, 3, 3, 3]) c[1] -> 2 # Count of element 1 c[4] -> 0 # Missing elements return 0 c.most_common() -> [(3, 3), (1, 2), (2, 1)] c.elements() -> [1, 1, 2, 3, 3, 3]`, }, "most_common": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.RangeArgs(args, 1, 2); err != nil { return err } counter, ok := args[0].(*object.Instance) if !ok || counter.Class != CounterClass { return errors.NewTypeError("Counter", args[0].Type().String()) } n := len(counter.Fields) if len(args) == 2 { if nArg, ok := args[1].(*object.Integer); ok { n = int(nArg.Value) } else { return errors.NewTypeError("INTEGER", args[1].Type().String()) } } // Convert to sortable slice type pair struct { key string count int64 } pairs := make([]pair, 0, len(counter.Fields)) for key, countObj := range counter.Fields { if count, ok := countObj.(*object.Integer); ok { pairs = append(pairs, pair{key: key, count: count.Value}) } } sort.Slice(pairs, func(i, j int) bool { return pairs[i].count > pairs[j].count }) if n > len(pairs) { n = len(pairs) } result := make([]object.Object, n) for i := 0; i < n; i++ { key := pairs[i].key if intVal, err := strconv.ParseInt(key, 10, 64); err == nil { result[i] = &object.Tuple{Elements: []object.Object{ object.NewInteger(intVal), object.NewInteger(pairs[i].count), }} } else { result[i] = &object.Tuple{Elements: []object.Object{ &object.String{Value: key}, object.NewInteger(pairs[i].count), }} } } return &object.List{Elements: result} }, HelpText: `most_common(counter[, n]) - Return n most common elements Returns a list of (element, count) tuples sorted by count. Example: c = collections.Counter([1, 1, 2, 3, 3, 3]) collections.most_common(c, 2) -> [(3, 3), (1, 2)]`, }, "OrderedDict": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { od := &object.Dict{Pairs: make(map[string]object.DictPair)} if len(args) == 0 { return od } if err := errors.MaxArgs(args, 1); err != nil { return err } switch arg := args[0].(type) { case *object.List: for _, elem := range arg.Elements { tuple, ok := elem.(*object.Tuple) if !ok || len(tuple.Elements) != 2 { return errors.NewError("OrderedDict() items must be (key, value) tuples") } key := tuple.Elements[0].Inspect() od.Pairs[key] = object.DictPair{ Key: tuple.Elements[0], Value: tuple.Elements[1], } } case *object.Dict: for k, v := range arg.Pairs { od.Pairs[k] = v } default: return errors.NewTypeError("list of tuples or dict", args[0].Type().String()) } return od }, HelpText: `OrderedDict([items]) - Dict that remembers insertion order Creates a dict that maintains insertion order. Note: Scriptling dicts already maintain order, so this is equivalent to dict(). Example: od = collections.OrderedDict([("a", 1), ("b", 2)])`, }, "deque": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { elements := []object.Object{} if len(args) >= 1 { switch arg := args[0].(type) { case *object.List: elements = make([]object.Object, len(arg.Elements)) copy(elements, arg.Elements) case *object.Tuple: elements = make([]object.Object, len(arg.Elements)) copy(elements, arg.Elements) case *object.String: for _, ch := range arg.Value { elements = append(elements, &object.String{Value: string(ch)}) } default: return errors.NewTypeError("iterable", args[0].Type().String()) } } maxlen := int64(-1) if len(args) >= 2 { if ml, ok := args[1].(*object.Integer); ok { maxlen = ml.Value if maxlen >= 0 && int64(len(elements)) > maxlen { elements = elements[len(elements)-int(maxlen):] } } else if args[1].Type() != object.NULL_OBJ { return errors.NewTypeError("INTEGER or None", args[1].Type().String()) } } dequeList := &object.List{Elements: elements} return dequeList }, HelpText: `deque([iterable[, maxlen]]) - Double-ended queue Creates a double-ended queue (deque) from an iterable. Use collections.deque_* functions for deque-specific operations. Example: d = collections.deque([1, 2, 3]) collections.deque_appendleft(d, 0) # [0, 1, 2, 3]`, }, "deque_appendleft": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } deque, ok := args[0].(*object.List) if !ok { return errors.NewTypeError("LIST (deque)", args[0].Type().String()) } newElements := make([]object.Object, len(deque.Elements)+1) newElements[0] = args[1] copy(newElements[1:], deque.Elements) deque.Elements = newElements return &object.Null{} }, HelpText: `deque_appendleft(deque, elem) - Add element to left side Adds an element to the left side of the deque. Example: d = collections.deque([1, 2, 3]) collections.deque_appendleft(d, 0) # d is now [0, 1, 2, 3]`, }, "deque_popleft": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } deque, ok := args[0].(*object.List) if !ok { return errors.NewTypeError("LIST (deque)", args[0].Type().String()) } if len(deque.Elements) == 0 { return errors.NewError("popleft from empty deque") } elem := deque.Elements[0] deque.Elements = deque.Elements[1:] return elem }, HelpText: `deque_popleft(deque) - Remove and return element from left Removes and returns the leftmost element. Example: d = collections.deque([1, 2, 3]) x = collections.deque_popleft(d) # x=1, d=[2, 3]`, }, "deque_extendleft": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } deque, ok := args[0].(*object.List) if !ok { return errors.NewTypeError("LIST (deque)", args[0].Type().String()) } var elements []object.Object switch arg := args[1].(type) { case *object.List: elements = arg.Elements case *object.Tuple: elements = arg.Elements default: return errors.NewTypeError("iterable", args[1].Type().String()) } newElements := make([]object.Object, len(elements)+len(deque.Elements)) for i, elem := range elements { newElements[len(elements)-1-i] = elem } copy(newElements[len(elements):], deque.Elements) deque.Elements = newElements return &object.Null{} }, HelpText: `deque_extendleft(deque, iterable) - Extend left with iterable Extends the left side with elements from iterable (in reverse order). Example: d = collections.deque([1, 2, 3]) collections.deque_extendleft(d, [4, 5]) # d is now [5, 4, 1, 2, 3]`, }, "deque_rotate": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } deque, ok := args[0].(*object.List) if !ok { return errors.NewTypeError("LIST (deque)", args[0].Type().String()) } n, ok := args[1].(*object.Integer) if !ok { return errors.NewTypeError("INTEGER", args[1].Type().String()) } if len(deque.Elements) == 0 { return &object.Null{} } steps := int(n.Value) % len(deque.Elements) if steps < 0 { steps += len(deque.Elements) } if steps == 0 { return &object.Null{} } newElements := make([]object.Object, len(deque.Elements)) splitPoint := len(deque.Elements) - steps copy(newElements, deque.Elements[splitPoint:]) copy(newElements[steps:], deque.Elements[:splitPoint]) deque.Elements = newElements return &object.Null{} }, HelpText: `deque_rotate(deque, n) - Rotate deque n steps Rotates the deque n steps to the right. If n is negative, rotates left. Example: d = collections.deque([1, 2, 3, 4]) collections.deque_rotate(d, 1) # d is now [4, 1, 2, 3] collections.deque_rotate(d, -1) # d is now [1, 2, 3, 4]`, }, "namedtuple": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } typename, ok := args[0].(*object.String) if !ok { return errors.NewTypeError("STRING", args[0].Type().String()) } var fieldNames []string switch fn := args[1].(type) { case *object.List: for _, elem := range fn.Elements { if s, ok := elem.(*object.String); ok { fieldNames = append(fieldNames, s.Value) } else { return errors.NewError("field names must be strings") } } case *object.Tuple: for _, elem := range fn.Elements { if s, ok := elem.(*object.String); ok { fieldNames = append(fieldNames, s.Value) } else { return errors.NewError("field names must be strings") } } case *object.String: fields := strings.FieldsFunc(fn.Value, func(r rune) bool { return r == ' ' || r == ',' }) for _, f := range fields { f = strings.TrimSpace(f) if f != "" { fieldNames = append(fieldNames, f) } } default: return errors.NewTypeError("list, tuple, or string", args[1].Type().String()) } methods := make(map[string]object.Object) methods["__init__"] = &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) != len(fieldNames)+1 { return errors.NewArgumentError(len(args), len(fieldNames)+1) } nt := args[0].(*object.Instance) for i, name := range fieldNames { nt.Fields[name] = args[i+1] } nt.Fields["__typename__"] = typename fieldNameObjs := make([]object.Object, len(fieldNames)) for i, name := range fieldNames { fieldNameObjs[i] = &object.String{Value: name} } nt.Fields["__fields__"] = &object.Tuple{Elements: fieldNameObjs} return &object.Null{} }, } methods["__getitem__"] = &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } nt := args[0].(*object.Instance) key := args[1].Inspect() if key == "__typename__" || key == "__fields__" { return &object.Null{} } if value, exists := nt.Fields[key]; exists { return value } return &object.Null{} }, HelpText: `__getitem__(key) - Get field value (supports nt[key] syntax)`, } ntClass := &object.Class{ Name: typename.Value, Methods: methods, } return ntClass }, HelpText: `namedtuple(typename, field_names) - Create a named tuple class Creates a class for creating named tuple instances with direct attribute access. Example: Point = collections.namedtuple("Point", ["x", "y"]) p = Point(1, 2) p.x # 1 (direct attribute access) p["y"] # 2 (dict-style access) p.x() # Also works for backward compatibility`, }, "ChainMap": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { chainMap := &object.Dict{Pairs: make(map[string]object.DictPair)} maps := make([]object.Object, len(args)) for i, arg := range args { if _, ok := arg.(*object.Dict); !ok { return errors.NewTypeError("DICT", arg.Type().String()) } maps[i] = arg } for i := len(args) - 1; i >= 0; i-- { d := args[i].(*object.Dict) for k, v := range d.Pairs { chainMap.Pairs[k] = v } } return chainMap }, HelpText: `ChainMap(*maps) - Group multiple dicts for single lookup Creates a single dict view over multiple dicts. First dict has priority. Example: d1 = {"a": 1} d2 = {"b": 2, "a": 10} cm = collections.ChainMap(d1, d2) cm["a"] # 1 (from d1) cm["b"] # 2 (from d2)`, }, }, map[string]object.Object{ "Counter": CounterClass, "DefaultDict": DefaultDictClass, "defaultdict": DefaultDictClass, }, "Python-compatible collections library for specialized container datatypes")
CollectionsLibrary provides Python-like collections functions
var CounterClass = &object.Class{ Name: "Counter", Methods: map[string]object.Object{ "__init__": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) == 0 { return &object.Null{} } counter := args[0].(*object.Instance) if len(args) == 1 { return &object.Null{} } if err := errors.MaxArgs(args, 2); err != nil { return err } countKey := func(key string) { if countObj, exists := counter.Fields[key]; exists { if count, ok := countObj.(*object.Integer); ok { counter.Fields[key] = object.NewInteger(count.Value + 1) } } else { counter.Fields[key] = object.NewInteger(1) } } switch arg := args[1].(type) { case *object.List: for _, elem := range arg.Elements { countKey(elem.Inspect()) } case *object.Tuple: for _, elem := range arg.Elements { countKey(elem.Inspect()) } case *object.String: for _, ch := range arg.Value { countKey(string(ch)) } case *object.Dict: for k, v := range arg.Pairs { if count, ok := v.Value.(*object.Integer); ok { counter.Fields[k] = count } } default: return errors.NewTypeError("iterable or dict", args[1].Type().String()) } return &object.Null{} }, }, "__getitem__": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } counter := args[0].(*object.Instance) key := args[1].Inspect() if count, ok := counter.Fields[key]; ok { return count } return &object.Integer{Value: 0} }, HelpText: `__getitem__(key) - Get count for key (supports c[key] syntax)`, }, "most_common": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { counter := args[0].(*object.Instance) n := len(counter.Fields) if len(args) == 2 { if nArg, ok := args[1].(*object.Integer); ok { n = int(nArg.Value) } else { return errors.NewTypeError("INTEGER", args[1].Type().String()) } } // Convert to sortable slice type pair struct { key string count int64 } pairs := make([]pair, 0, len(counter.Fields)) for key, countObj := range counter.Fields { if count, ok := countObj.(*object.Integer); ok { pairs = append(pairs, pair{key: key, count: count.Value}) } } sort.Slice(pairs, func(i, j int) bool { return pairs[i].count > pairs[j].count }) if n > len(pairs) { n = len(pairs) } result := make([]object.Object, n) for i := 0; i < n; i++ { key := pairs[i].key if intVal, err := strconv.ParseInt(key, 10, 64); err == nil { result[i] = &object.Tuple{Elements: []object.Object{ object.NewInteger(intVal), object.NewInteger(pairs[i].count), }} } else { result[i] = &object.Tuple{Elements: []object.Object{ &object.String{Value: key}, object.NewInteger(pairs[i].count), }} } } return &object.List{Elements: result} }, HelpText: `most_common([n]) - Return n most common elements Returns a list of (element, count) tuples sorted by count descending. If n is omitted, returns all elements.`, }, "elements": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.NoArgs(args); err != nil { return err } counter := args[0].(*object.Instance) var result []object.Object for key, countObj := range counter.Fields { if count, ok := countObj.(*object.Integer); ok { for i := int64(0); i < count.Value; i++ { result = append(result, &object.String{Value: key}) } } } return &object.List{Elements: result} }, HelpText: `elements() - Return iterator over elements Returns an iterator over elements, repeating each element by its count.`, }, }, }
Counter class for counting elements
var DatetimeLibrary = object.NewLibrary( map[string]*object.Builtin{ "timedelta": timedeltaBuiltinNew, "datetime": datetimeConstructorBuiltin, "date": dateConstructorBuiltin, }, nil, "Date and time manipulation library.", )
DatetimeLibrary is the main datetime module
var DefaultDictClass = &object.Class{ Name: "DefaultDict", Methods: map[string]object.Object{ "__init__": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } dd := args[0].(*object.Instance) factory := args[1] dd.Fields["__default_factory__"] = factory return &object.Null{} }, }, "__getitem__": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } dd := args[0].(*object.Instance) key := args[1].Inspect() if value, exists := dd.Fields[key]; exists { return value } factory, hasFactory := dd.Fields["__default_factory__"] if !hasFactory { return &object.Null{} } // Create default value based on factory var defaultValue object.Object switch f := factory.(type) { case *object.Builtin: defaultValue = f.Fn(ctx, object.NewKwargs(nil)) if object.IsError(defaultValue) { defaultValue = f.Fn(ctx, object.NewKwargs(nil), object.NewInteger(0)) if object.IsError(defaultValue) { return defaultValue } } case *object.String: switch f.Value { case "int": defaultValue = object.NewInteger(0) case "float": defaultValue = &object.Float{Value: 0} case "str": defaultValue = &object.String{Value: ""} case "list": defaultValue = &object.List{Elements: []object.Object{}} case "dict": defaultValue = &object.Dict{Pairs: make(map[string]object.DictPair)} default: return errors.NewError("unknown default factory type: %s", f.Value) } default: return errors.NewError("default_factory must be a builtin function or type name") } dd.Fields[key] = defaultValue return defaultValue }, HelpText: `__getitem__(key) - Get value with default creation (supports d[key] syntax)`, }, "__setitem__": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 3); err != nil { return err } dd := args[0].(*object.Instance) key := args[1].Inspect() value := args[2] dd.Fields[key] = value return &object.Null{} }, HelpText: `__setitem__(key, value) - Set value (supports d[key] = value syntax)`, }, }, }
DefaultDict class for dicts with default factory behavior
var FunctoolsLibrary = object.NewLibrary(map[string]*object.Builtin{ "reduce": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) < 2 || len(args) > 3 { return errors.NewError("reduce() requires 2 or 3 arguments") } fn, ok := args[0].(*object.Function) if !ok { if builtin, ok := args[0].(*object.Builtin); ok { return reduceWithBuiltin(ctx, builtin, args[1:]) } return errors.NewTypeError("FUNCTION", args[0].Type().String()) } list, ok := args[1].(*object.List) if !ok { return errors.NewTypeError("LIST", args[1].Type().String()) } if len(list.Elements) == 0 { if len(args) == 3 { return args[2] } return errors.NewError("reduce() of empty sequence with no initial value") } // Get initial accumulator var accumulator object.Object startIdx := 0 if len(args) == 3 { accumulator = args[2] } else { accumulator = list.Elements[0] startIdx = 1 } for i := startIdx; i < len(list.Elements); i++ { fnEnv := object.NewEnclosedEnvironment(fn.Env) if len(fn.Parameters) != 2 { return errors.NewError("reduce function must take exactly 2 arguments") } fnEnv.Set(fn.Parameters[0].Value, accumulator) fnEnv.Set(fn.Parameters[1].Value, list.Elements[i]) result := callFunction(ctx, fn, []object.Object{accumulator, list.Elements[i]}, nil) if result == nil { return errors.NewError("reduce function returned nil") } if object.IsError(result) { return result } accumulator = result } return accumulator }, HelpText: `reduce(function, iterable[, initializer]) - Apply function cumulatively to items Parameters: function - Function taking 2 arguments (accumulator, item) iterable - List of items to reduce initializer - Optional starting value Returns: Reduced value Example: import functools def add(x, y): return x + y functools.reduce(add, [1, 2, 3, 4]) # 10 functools.reduce(add, [1, 2, 3], 10) # 16`, }, "partial": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) < 1 { return errors.NewError("partial() requires at least 1 argument") } // First arg must be a function or builtin var fn *object.Function var builtin *object.Builtin if f, ok := args[0].(*object.Function); ok { fn = f } else if b, ok := args[0].(*object.Builtin); ok { builtin = b } else { return errors.NewTypeError("FUNCTION", args[0].Type().String()) } partialArgs := args[1:] partialKwargs := make(map[string]object.Object) for k, v := range kwargs.Kwargs { partialKwargs[k] = v } return &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { allArgs := append(partialArgs, args...) allKwargs := make(map[string]object.Object) for k, v := range partialKwargs { allKwargs[k] = v } for k, v := range kwargs.Kwargs { allKwargs[k] = v } if fn != nil { return callFunction(ctx, fn, allArgs, allKwargs) } else { return builtin.Fn(ctx, object.NewKwargs(allKwargs), allArgs...) } }, HelpText: "Partial function application", } }, HelpText: `partial(func, *args, **kwargs) - Create a partial function application Parameters: func - Function to partially apply *args - Arguments to pre-fill **kwargs - Keyword arguments to pre-fill Returns: New function with pre-filled arguments Example: import functools def add(x, y): return x + y add_five = functools.partial(add, 5) add_five(3) # 8`, }, }, nil, "Higher-order functions and operations on callable objects")
var HTMLLibrary = object.NewLibrary(map[string]*object.Builtin{ "escape": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } str, ok := args[0].(*object.String) if !ok { return errors.NewTypeError("STRING", args[0].Type().String()) } return &object.String{Value: html.EscapeString(str.Value)} }, HelpText: `escape(s) - Escape HTML special characters Converts &, <, >, ", and ' to HTML-safe sequences. Parameters: s - String to escape Returns: Escaped string Example: import html safe = html.escape("<script>alert('xss')</script>") print(safe) # "<script>alert('xss')</script>"`, }, "unescape": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } str, ok := args[0].(*object.String) if !ok { return errors.NewTypeError("STRING", args[0].Type().String()) } result := html.UnescapeString(str.Value) result = unescapeNumericEntities(result) return &object.String{Value: result} }, HelpText: `unescape(s) - Unescape HTML entities Converts HTML entities back to their corresponding characters. Handles named entities (<, >, &, ", ') and numeric entities (<, <). Parameters: s - String with HTML entities to unescape Returns: Unescaped string Example: import html text = html.unescape("<script>") print(text) # "<script>"`, }, }, nil, "HTML escaping and unescaping library")
var HashlibLibrary = object.NewLibrary(map[string]*object.Builtin{ "sha256": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } str, err := args[0].AsString() if err != nil { return err } hash := sha256.Sum256([]byte(str)) return &object.String{Value: hex.EncodeToString(hash[:])} }, HelpText: `sha256(string) - Compute SHA-256 hash Returns the SHA-256 hash of the input string as a hexadecimal string.`, }, "sha1": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } str, err := args[0].AsString() if err != nil { return err } hash := sha1.Sum([]byte(str)) return &object.String{Value: hex.EncodeToString(hash[:])} }, HelpText: `sha1(string) - Compute SHA-1 hash Returns the SHA-1 hash of the input string as a hexadecimal string.`, }, "md5": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } str, err := args[0].AsString() if err != nil { return err } hash := md5.Sum([]byte(str)) return &object.String{Value: hex.EncodeToString(hash[:])} }, HelpText: `md5(string) - Compute MD5 hash Returns a hexadecimal string.`, }, }, nil, "Cryptographic hash functions library")
var ItertoolsLibrary = object.NewLibrary(map[string]*object.Builtin{ "chain": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { result := []object.Object{} for _, arg := range args { switch a := arg.(type) { case *object.List: result = append(result, a.Elements...) case *object.Tuple: result = append(result, a.Elements...) case *object.String: for _, ch := range a.Value { result = append(result, &object.String{Value: string(ch)}) } default: return errors.NewTypeError("iterable", arg.Type().String()) } } return &object.List{Elements: result} }, HelpText: `chain(*iterables) - Chain multiple iterables together Returns a list with elements from all iterables concatenated. Example: itertools.chain([1, 2], [3, 4]) -> [1, 2, 3, 4] itertools.chain("ab", "cd") -> ["a", "b", "c", "d"]`, }, "repeat": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.RangeArgs(args, 1, 2); err != nil { return err } elem := args[0] times := int64(1) if len(args) == 2 { if n, ok := args[1].(*object.Integer); ok { times = n.Value } else { return errors.NewTypeError("INTEGER", args[1].Type().String()) } } if times < 0 { times = 0 } result := make([]object.Object, times) for i := int64(0); i < times; i++ { result[i] = elem } return &object.List{Elements: result} }, HelpText: `repeat(elem, n) - Repeat element n times Returns a list with the element repeated n times. Example: itertools.repeat("x", 3) -> ["x", "x", "x"] itertools.repeat(0, 5) -> [0, 0, 0, 0, 0]`, }, "cycle": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } var elements []object.Object switch a := args[0].(type) { case *object.List: elements = a.Elements case *object.Tuple: elements = a.Elements case *object.String: for _, ch := range a.Value { elements = append(elements, &object.String{Value: string(ch)}) } default: return errors.NewTypeError("iterable", args[0].Type().String()) } n, ok := args[1].(*object.Integer) if !ok { return errors.NewTypeError("INTEGER", args[1].Type().String()) } if len(elements) == 0 || n.Value <= 0 { return &object.List{Elements: []object.Object{}} } result := make([]object.Object, 0, len(elements)*int(n.Value)) for i := int64(0); i < n.Value; i++ { result = append(result, elements...) } return &object.List{Elements: result} }, HelpText: `cycle(iterable, n) - Cycle through iterable n times Returns a list with elements of iterable repeated n times. Note: Unlike Python's infinite cycle, this requires specifying the count. Example: itertools.cycle([1, 2, 3], 2) -> [1, 2, 3, 1, 2, 3]`, }, "count": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.RangeArgs(args, 2, 3); err != nil { return err } start, ok := args[0].(*object.Integer) if !ok { return errors.NewTypeError("INTEGER", args[0].Type().String()) } stop, ok := args[1].(*object.Integer) if !ok { return errors.NewTypeError("INTEGER", args[1].Type().String()) } step := int64(1) if len(args) == 3 { if s, ok := args[2].(*object.Integer); ok { step = s.Value } else { return errors.NewTypeError("INTEGER", args[2].Type().String()) } } if step == 0 { return errors.NewError("step cannot be zero") } result := []object.Object{} if step > 0 { for i := start.Value; i < stop.Value; i += step { result = append(result, object.NewInteger(i)) } } else { for i := start.Value; i > stop.Value; i += step { result = append(result, object.NewInteger(i)) } } return &object.List{Elements: result} }, HelpText: `count(start, stop[, step]) - Generate a sequence of numbers Returns a list of numbers from start to stop (exclusive) with optional step. Similar to range() but as an itertools function. Example: itertools.count(0, 5) -> [0, 1, 2, 3, 4] itertools.count(0, 10, 2) -> [0, 2, 4, 6, 8]`, }, "islice": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.RangeArgs(args, 2, 4); err != nil { return err } var elements []object.Object switch a := args[0].(type) { case *object.List: elements = a.Elements case *object.Tuple: elements = a.Elements case *object.String: for _, ch := range a.Value { elements = append(elements, &object.String{Value: string(ch)}) } default: return errors.NewTypeError("iterable", args[0].Type().String()) } var start, stop, step int64 = 0, 0, 1 if len(args) == 2 { if s, ok := args[1].(*object.Integer); ok { stop = s.Value } else { return errors.NewTypeError("INTEGER", args[1].Type().String()) } } else { if s, ok := args[1].(*object.Integer); ok { start = s.Value } else { return errors.NewTypeError("INTEGER", args[1].Type().String()) } if s, ok := args[2].(*object.Integer); ok { stop = s.Value } else { return errors.NewTypeError("INTEGER", args[2].Type().String()) } if len(args) == 4 { if s, ok := args[3].(*object.Integer); ok { step = s.Value } else { return errors.NewTypeError("INTEGER", args[3].Type().String()) } } } if step <= 0 { return errors.NewError("step must be positive") } if start < 0 { start = 0 } if stop > int64(len(elements)) { stop = int64(len(elements)) } result := []object.Object{} for i := start; i < stop; i += step { result = append(result, elements[i]) } return &object.List{Elements: result} }, HelpText: `islice(iterable, stop) or islice(iterable, start, stop[, step]) - Slice an iterable Returns a list with elements from the iterable sliced by indices. Example: itertools.islice([0, 1, 2, 3, 4], 3) -> [0, 1, 2] itertools.islice([0, 1, 2, 3, 4], 1, 4) -> [1, 2, 3] itertools.islice([0, 1, 2, 3, 4], 0, 5, 2) -> [0, 2, 4]`, }, "takewhile": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } pred, ok := args[0].(*object.Builtin) if !ok { return errors.NewError("takewhile() predicate must be a builtin function") } var elements []object.Object switch a := args[1].(type) { case *object.List: elements = a.Elements case *object.Tuple: elements = a.Elements default: return errors.NewTypeError("iterable", args[1].Type().String()) } result := []object.Object{} for _, elem := range elements { res := pred.Fn(ctx, object.NewKwargs(nil), elem) if object.IsError(res) { return res } if !isTruthy(res) { break } result = append(result, elem) } return &object.List{Elements: result} }, HelpText: `takewhile(predicate, iterable) - Take elements while predicate is true Returns a list with elements from the start of iterable as long as predicate is true. Example: itertools.takewhile(lambda x: x < 5, [1, 3, 5, 2, 4]) -> [1, 3]`, }, "dropwhile": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } pred, ok := args[0].(*object.Builtin) if !ok { return errors.NewError("dropwhile() predicate must be a builtin function") } var elements []object.Object switch a := args[1].(type) { case *object.List: elements = a.Elements case *object.Tuple: elements = a.Elements default: return errors.NewTypeError("iterable", args[1].Type().String()) } result := []object.Object{} dropping := true for _, elem := range elements { if dropping { res := pred.Fn(ctx, object.NewKwargs(nil), elem) if object.IsError(res) { return res } if isTruthy(res) { continue } dropping = false } result = append(result, elem) } return &object.List{Elements: result} }, HelpText: `dropwhile(predicate, iterable) - Drop elements while predicate is true Returns a list with elements after the predicate becomes false. Example: itertools.dropwhile(lambda x: x < 5, [1, 3, 5, 2, 4]) -> [5, 2, 4]`, }, "zip_longest": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) < 1 { return &object.List{Elements: []object.Object{}} } fillvalue := object.Object(&object.Null{}) if kwargs.Len() > 0 { if kwargs.Has("fillvalue") { fillvalue = kwargs.Get("fillvalue") } } iterables := make([][]object.Object, len(args)) maxLen := 0 for i, arg := range args { switch a := arg.(type) { case *object.List: iterables[i] = a.Elements case *object.Tuple: iterables[i] = a.Elements case *object.String: chars := []object.Object{} for _, ch := range a.Value { chars = append(chars, &object.String{Value: string(ch)}) } iterables[i] = chars default: return errors.NewTypeError("iterable", arg.Type().String()) } if len(iterables[i]) > maxLen { maxLen = len(iterables[i]) } } result := []object.Object{} for j := 0; j < maxLen; j++ { tuple := make([]object.Object, len(iterables)) for i, iter := range iterables { if j < len(iter) { tuple[i] = iter[j] } else { tuple[i] = fillvalue } } result = append(result, &object.Tuple{Elements: tuple}) } return &object.List{Elements: result} }, HelpText: `zip_longest(*iterables, fillvalue=None) - Zip iterables, filling shorter ones Zips iterables together, using fillvalue for missing values in shorter iterables. Example: itertools.zip_longest([1, 2, 3], ["a", "b"]) -> [(1, "a"), (2, "b"), (3, None)] itertools.zip_longest([1, 2], ["a"], fillvalue="-") -> [(1, "a"), (2, "-")]`, }, "product": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) < 1 { return &object.List{Elements: []object.Object{&object.Tuple{Elements: []object.Object{}}}} } iterables := make([][]object.Object, len(args)) for i, arg := range args { switch a := arg.(type) { case *object.List: iterables[i] = a.Elements case *object.Tuple: iterables[i] = a.Elements case *object.String: chars := []object.Object{} for _, ch := range a.Value { chars = append(chars, &object.String{Value: string(ch)}) } iterables[i] = chars default: return errors.NewTypeError("iterable", arg.Type().String()) } } for _, iter := range iterables { if len(iter) == 0 { return &object.List{Elements: []object.Object{}} } } result := []object.Object{} indices := make([]int, len(iterables)) for { tuple := make([]object.Object, len(iterables)) for i, idx := range indices { tuple[i] = iterables[i][idx] } result = append(result, &object.Tuple{Elements: tuple}) carry := true for i := len(indices) - 1; i >= 0 && carry; i-- { indices[i]++ if indices[i] >= len(iterables[i]) { indices[i] = 0 } else { carry = false } } if carry { break } } return &object.List{Elements: result} }, HelpText: `product(*iterables) - Cartesian product of iterables Returns all possible combinations (tuples) of elements from input iterables. Example: itertools.product([1, 2], ["a", "b"]) -> [(1, "a"), (1, "b"), (2, "a"), (2, "b")] itertools.product([1, 2], [3, 4]) -> [(1, 3), (1, 4), (2, 3), (2, 4)]`, }, "permutations": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.RangeArgs(args, 1, 2); err != nil { return err } var elements []object.Object switch a := args[0].(type) { case *object.List: elements = a.Elements case *object.Tuple: elements = a.Elements case *object.String: for _, ch := range a.Value { elements = append(elements, &object.String{Value: string(ch)}) } default: return errors.NewTypeError("iterable", args[0].Type().String()) } r := len(elements) if len(args) == 2 { if rArg, ok := args[1].(*object.Integer); ok { r = int(rArg.Value) } else { return errors.NewTypeError("INTEGER", args[1].Type().String()) } } if r < 0 || r > len(elements) { return &object.List{Elements: []object.Object{}} } result := []object.Object{} generatePermutations(elements, r, []object.Object{}, make([]bool, len(elements)), &result) return &object.List{Elements: result} }, HelpText: `permutations(iterable[, r]) - Generate permutations Returns all r-length permutations of elements from iterable. If r is not specified, defaults to length of iterable (full permutations). Example: itertools.permutations([1, 2, 3], 2) -> [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)] itertools.permutations("ab") -> [("a", "b"), ("b", "a")]`, }, "combinations": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } var elements []object.Object switch a := args[0].(type) { case *object.List: elements = a.Elements case *object.Tuple: elements = a.Elements case *object.String: for _, ch := range a.Value { elements = append(elements, &object.String{Value: string(ch)}) } default: return errors.NewTypeError("iterable", args[0].Type().String()) } rArg, ok := args[1].(*object.Integer) if !ok { return errors.NewTypeError("INTEGER", args[1].Type().String()) } r := int(rArg.Value) if r < 0 || r > len(elements) { return &object.List{Elements: []object.Object{}} } result := []object.Object{} generateCombinations(elements, r, 0, []object.Object{}, &result) return &object.List{Elements: result} }, HelpText: `combinations(iterable, r) - Generate combinations Returns all r-length combinations of elements from iterable (without repetition). Example: itertools.combinations([1, 2, 3], 2) -> [(1, 2), (1, 3), (2, 3)] itertools.combinations("abc", 2) -> [("a", "b"), ("a", "c"), ("b", "c")]`, }, "combinations_with_replacement": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } var elements []object.Object switch a := args[0].(type) { case *object.List: elements = a.Elements case *object.Tuple: elements = a.Elements case *object.String: for _, ch := range a.Value { elements = append(elements, &object.String{Value: string(ch)}) } default: return errors.NewTypeError("iterable", args[0].Type().String()) } rArg, ok := args[1].(*object.Integer) if !ok { return errors.NewTypeError("INTEGER", args[1].Type().String()) } r := int(rArg.Value) if r < 0 { return &object.List{Elements: []object.Object{}} } if len(elements) == 0 && r > 0 { return &object.List{Elements: []object.Object{}} } result := []object.Object{} generateCombinationsWithReplacement(elements, r, 0, []object.Object{}, &result) return &object.List{Elements: result} }, HelpText: `combinations_with_replacement(iterable, r) - Generate combinations with replacement Returns all r-length combinations of elements from iterable (with repetition allowed). Example: itertools.combinations_with_replacement([1, 2], 2) -> [(1, 1), (1, 2), (2, 2)] itertools.combinations_with_replacement("ab", 2) -> [("a", "a"), ("a", "b"), ("b", "b")]`, }, "groupby": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.RangeArgs(args, 1, 2); err != nil { return err } var elements []object.Object switch a := args[0].(type) { case *object.List: elements = a.Elements case *object.Tuple: elements = a.Elements default: return errors.NewTypeError("iterable", args[0].Type().String()) } var keyFunc *object.Builtin if len(args) == 2 { var ok bool keyFunc, ok = args[1].(*object.Builtin) if !ok { return errors.NewError("groupby() key must be a builtin function") } } if len(elements) == 0 { return &object.List{Elements: []object.Object{}} } result := []object.Object{} var currentKey object.Object var currentGroup []object.Object for i, elem := range elements { var key object.Object if keyFunc != nil { key = keyFunc.Fn(ctx, object.NewKwargs(nil), elem) if object.IsError(key) { return key } } else { key = elem } if i == 0 { currentKey = key currentGroup = []object.Object{elem} } else if objectsEqual(key, currentKey) { currentGroup = append(currentGroup, elem) } else { result = append(result, &object.Tuple{Elements: []object.Object{ currentKey, &object.List{Elements: currentGroup}, }}) currentKey = key currentGroup = []object.Object{elem} } } if len(currentGroup) > 0 { result = append(result, &object.Tuple{Elements: []object.Object{ currentKey, &object.List{Elements: currentGroup}, }}) } return &object.List{Elements: result} }, HelpText: `groupby(iterable[, key]) - Group consecutive elements Groups consecutive elements that have the same key value. Returns list of (key, group) tuples where group is a list. Example: itertools.groupby([1, 1, 2, 2, 3]) -> [(1, [1, 1]), (2, [2, 2]), (3, [3])] itertools.groupby(["aa", "ab", "ba"], lambda x: x[0]) -> [("a", ["aa", "ab"]), ("b", ["ba"])]`, }, "accumulate": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.RangeArgs(args, 1, 2); err != nil { return err } var elements []object.Object switch a := args[0].(type) { case *object.List: elements = a.Elements case *object.Tuple: elements = a.Elements default: return errors.NewTypeError("iterable", args[0].Type().String()) } if len(elements) == 0 { return &object.List{Elements: []object.Object{}} } var accumFunc *object.Builtin if len(args) == 2 { var ok bool accumFunc, ok = args[1].(*object.Builtin) if !ok { return errors.NewError("accumulate() func must be a builtin function") } } result := []object.Object{elements[0]} accumulator := elements[0] for i := 1; i < len(elements); i++ { if accumFunc != nil { accumulator = accumFunc.Fn(ctx, object.NewKwargs(nil), accumulator, elements[i]) if object.IsError(accumulator) { return accumulator } } else { accumulator = addObjects(accumulator, elements[i]) if object.IsError(accumulator) { return accumulator } } result = append(result, accumulator) } return &object.List{Elements: result} }, HelpText: `accumulate(iterable[, func]) - Running totals/accumulation Returns list of accumulated values. Default is sum, but can provide custom function. Example: itertools.accumulate([1, 2, 3, 4]) -> [1, 3, 6, 10] itertools.accumulate([1, 2, 3], operator.mul) -> [1, 2, 6]`, }, "filterfalse": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } pred, ok := args[0].(*object.Builtin) if !ok { return errors.NewError("filterfalse() predicate must be a builtin function") } var elements []object.Object switch a := args[1].(type) { case *object.List: elements = a.Elements case *object.Tuple: elements = a.Elements default: return errors.NewTypeError("iterable", args[1].Type().String()) } result := []object.Object{} for _, elem := range elements { res := pred.Fn(ctx, object.NewKwargs(nil), elem) if object.IsError(res) { return res } if !isTruthy(res) { result = append(result, elem) } } return &object.List{Elements: result} }, HelpText: `filterfalse(predicate, iterable) - Filter elements where predicate is false Returns elements for which the predicate returns false. Example: itertools.filterfalse(lambda x: x % 2, [1, 2, 3, 4]) -> [2, 4]`, }, "starmap": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } fn, ok := args[0].(*object.Builtin) if !ok { return errors.NewError("starmap() func must be a builtin function") } var elements []object.Object switch a := args[1].(type) { case *object.List: elements = a.Elements case *object.Tuple: elements = a.Elements default: return errors.NewTypeError("iterable", args[1].Type().String()) } result := []object.Object{} for _, elem := range elements { var fnArgs []object.Object switch e := elem.(type) { case *object.List: fnArgs = e.Elements case *object.Tuple: fnArgs = e.Elements default: return errors.NewError("starmap() iterable must contain sequences") } res := fn.Fn(ctx, object.NewKwargs(nil), fnArgs...) if object.IsError(res) { return res } result = append(result, res) } return &object.List{Elements: result} }, HelpText: `starmap(func, iterable) - Apply function to argument tuples Applies function using elements of each tuple as arguments. Example: itertools.starmap(pow, [(2, 3), (3, 2)]) -> [8, 9]`, }, "compress": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } var data []object.Object switch a := args[0].(type) { case *object.List: data = a.Elements case *object.Tuple: data = a.Elements default: return errors.NewTypeError("iterable", args[0].Type().String()) } var selectors []object.Object switch a := args[1].(type) { case *object.List: selectors = a.Elements case *object.Tuple: selectors = a.Elements default: return errors.NewTypeError("iterable", args[1].Type().String()) } result := []object.Object{} minLen := len(data) if len(selectors) < minLen { minLen = len(selectors) } for i := 0; i < minLen; i++ { if isTruthy(selectors[i]) { result = append(result, data[i]) } } return &object.List{Elements: result} }, HelpText: `compress(data, selectors) - Filter data based on selectors Returns elements from data where corresponding selector is truthy. Example: itertools.compress([1, 2, 3, 4], [True, False, True, False]) -> [1, 3] itertools.compress("abcd", [1, 0, 1, 0]) -> ["a", "c"]`, }, "pairwise": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } var elements []object.Object switch a := args[0].(type) { case *object.List: elements = a.Elements case *object.Tuple: elements = a.Elements case *object.String: for _, ch := range a.Value { elements = append(elements, &object.String{Value: string(ch)}) } default: return errors.NewTypeError("iterable", args[0].Type().String()) } if len(elements) < 2 { return &object.List{Elements: []object.Object{}} } result := make([]object.Object, len(elements)-1) for i := 0; i < len(elements)-1; i++ { result[i] = &object.Tuple{Elements: []object.Object{elements[i], elements[i+1]}} } return &object.List{Elements: result} }, HelpText: `pairwise(iterable) - Return successive overlapping pairs Returns consecutive pairs from the iterable. Example: itertools.pairwise([1, 2, 3, 4]) -> [(1, 2), (2, 3), (3, 4)] itertools.pairwise("abc") -> [("a", "b"), ("b", "c")]`, }, "batched": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } var elements []object.Object switch a := args[0].(type) { case *object.List: elements = a.Elements case *object.Tuple: elements = a.Elements case *object.String: for _, ch := range a.Value { elements = append(elements, &object.String{Value: string(ch)}) } default: return errors.NewTypeError("iterable", args[0].Type().String()) } n, ok := args[1].(*object.Integer) if !ok { return errors.NewTypeError("INTEGER", args[1].Type().String()) } if n.Value <= 0 { return errors.NewError("n must be positive") } batchSize := int(n.Value) result := []object.Object{} for i := 0; i < len(elements); i += batchSize { end := i + batchSize if end > len(elements) { end = len(elements) } batch := make([]object.Object, end-i) copy(batch, elements[i:end]) result = append(result, &object.Tuple{Elements: batch}) } return &object.List{Elements: result} }, HelpText: `batched(iterable, n) - Batch elements into tuples of size n Groups elements into batches of n elements each. Example: itertools.batched([1, 2, 3, 4, 5], 2) -> [(1, 2), (3, 4), (5,)] itertools.batched("abcdef", 3) -> [("a", "b", "c"), ("d", "e", "f")]`, }, }, nil, "Python-compatible itertools library for iteration utilities")
ItertoolsLibrary provides Python-like itertools functions
var JSONLibrary = object.NewLibrary(map[string]*object.Builtin{ "loads": { Fn: jsonLoads, HelpText: `loads(json_string) - Parse JSON string Parses a JSON string and returns the corresponding Scriptling object.`, }, "dumps": { Fn: jsonDumps, HelpText: `dumps(obj, indent="") - Serialize object to JSON string Converts a Scriptling object to its JSON string representation. Optional indent parameter for pretty-printing.`, }, "parse": { Fn: jsonLoads, HelpText: `parse(json_string) - Parse JSON string (alias for loads) Parses a JSON string and returns the corresponding Scriptling object.`, }, "stringify": { Fn: jsonDumps, HelpText: `stringify(obj, indent="") - Serialize object to JSON string (alias for dumps) Converts a Scriptling object to its JSON string representation. Optional indent parameter for pretty-printing.`, }, }, nil, "JSON encoding and decoding library")
var MatchClass = &object.Class{ Name: "Match", Methods: map[string]object.Object{ "group": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) > 2 { return errors.NewError("group() takes at most 1 argument (%d given)", len(args)) } match := args[0].(*object.Instance) groups := match.Fields["groups"].(*object.List).Elements groupNum := 0 if len(args) == 2 { if args[1].Type() != object.INTEGER_OBJ { return errors.NewTypeError("INTEGER", args[1].Type().String()) } val, _ := args[1].AsInt() groupNum = int(val) } if groupNum < 0 || groupNum >= len(groups) { return errors.NewError("no such group: %d", groupNum) } return groups[groupNum] }, HelpText: `group(n=0) - Return the nth matched group (0 = full match)`, }, "groups": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } match := args[0].(*object.Instance) groups := match.Fields["groups"].(*object.List).Elements if len(groups) <= 1 { return &object.Tuple{Elements: []object.Object{}} } elements := make([]object.Object, len(groups)-1) for i := 1; i < len(groups); i++ { elements[i-1] = groups[i] } return &object.Tuple{Elements: elements} }, HelpText: `groups() - Return tuple of all matched groups (excluding group 0)`, }, "start": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) > 2 { return errors.NewError("start() takes at most 1 argument (%d given)", len(args)) } match := args[0].(*object.Instance) groupNum := 0 if len(args) == 2 { if args[1].Type() != object.INTEGER_OBJ { return errors.NewTypeError("INTEGER", args[1].Type().String()) } val, _ := args[1].AsInt() groupNum = int(val) } if groupNum != 0 { return errors.NewError("start() only supports group 0") } return match.Fields["start"] }, HelpText: `start(n=0) - Return start position of nth group`, }, "end": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) > 2 { return errors.NewError("end() takes at most 1 argument (%d given)", len(args)) } match := args[0].(*object.Instance) groupNum := 0 if len(args) == 2 { if args[1].Type() != object.INTEGER_OBJ { return errors.NewTypeError("INTEGER", args[1].Type().String()) } val, _ := args[1].AsInt() groupNum = int(val) } if groupNum != 0 { return errors.NewError("end() only supports group 0") } return match.Fields["end"] }, HelpText: `end(n=0) - Return end position of nth group`, }, "span": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) > 2 { return errors.NewError("span() takes at most 1 argument (%d given)", len(args)) } match := args[0].(*object.Instance) groupNum := 0 if len(args) == 2 { if args[1].Type() != object.INTEGER_OBJ { return errors.NewTypeError("INTEGER", args[1].Type().String()) } val, _ := args[1].AsInt() groupNum = int(val) } if groupNum != 0 { return errors.NewError("span() only supports group 0") } return &object.Tuple{Elements: []object.Object{ match.Fields["start"], match.Fields["end"], }} }, HelpText: `span(n=0) - Return (start, end) tuple for nth group`, }, }, }
Match class definition
var MathLibrary = object.NewLibrary(map[string]*object.Builtin{ "sqrt": { Fn: oneFloatFunc(math.Sqrt), HelpText: `sqrt(x) - Return the square root of x x must be a non-negative number (integer or float). Returns a float.`, }, "pow": { Fn: twoFloatFunc(math.Pow), HelpText: `pow(base, exp) - Return base raised to the power exp base and exp can be integers or floats. Returns a float.`, }, "fabs": { Fn: oneFloatFunc(math.Abs), HelpText: `fabs(x) - Return the absolute value of x as a float x can be an integer or float. Always returns a float.`, }, "floor": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } switch arg := args[0].(type) { case *object.Integer: return arg case *object.Float: return &object.Integer{Value: int64(math.Floor(arg.Value))} default: return errors.NewTypeError("INTEGER or FLOAT", arg.Type().String()) } }, HelpText: `floor(x) - Return the floor of x x can be an integer or float. Returns the largest integer less than or equal to x.`, }, "ceil": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } switch arg := args[0].(type) { case *object.Integer: return arg case *object.Float: return &object.Integer{Value: int64(math.Ceil(arg.Value))} default: return errors.NewTypeError("INTEGER or FLOAT", arg.Type().String()) } }, HelpText: `ceil(x) - Return the ceiling of x x can be an integer or float. Returns the smallest integer greater than or equal to x.`, }, "sin": { Fn: oneFloatFunc(math.Sin), HelpText: `sin(x) - Return the sine of x (radians) x can be an integer or float in radians. Returns a float.`, }, "cos": { Fn: oneFloatFunc(math.Cos), HelpText: `cos(x) - Return the cosine of x (radians) x can be an integer or float in radians. Returns a float.`, }, "tan": { Fn: oneFloatFunc(math.Tan), HelpText: `tan(x) - Return the tangent of x (radians) x can be an integer or float in radians. Returns a float.`, }, "log": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } x, err := args[0].AsFloat() if err != nil { return errors.NewTypeError("INTEGER or FLOAT", args[0].Type().String()) } if x <= 0 { return errors.NewError("log: domain error") } return &object.Float{Value: math.Log(x)} }, HelpText: `log(x) - Return the natural logarithm of x x must be positive (integer or float). Returns a float.`, }, "exp": { Fn: oneFloatFunc(math.Exp), HelpText: `exp(x) - Return e raised to the power x x can be an integer or float. Returns a float.`, }, "degrees": { Fn: oneFloatFunc(func(x float64) float64 { return x * 180.0 / math.Pi }), HelpText: `degrees(x) - Convert radians to degrees x can be an integer or float in radians. Returns a float in degrees.`, }, "radians": { Fn: oneFloatFunc(func(x float64) float64 { return x * math.Pi / 180.0 }), HelpText: `radians(x) - Convert degrees to radians x can be an integer or float in degrees. Returns a float in radians.`, }, "fmod": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } x, err := args[0].AsFloat() if err != nil { return errors.NewTypeError("INTEGER or FLOAT", args[0].Type().String()) } y, err := args[1].AsFloat() if err != nil { return errors.NewTypeError("INTEGER or FLOAT", args[1].Type().String()) } if y == 0 { return errors.NewError("fmod: division by zero") } return &object.Float{Value: math.Mod(x, y)} }, HelpText: `fmod(x, y) - Return the floating-point remainder of x/y x and y can be integers or floats. y must not be zero. Returns a float.`, }, "gcd": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } a, err := args[0].AsInt() if err != nil { return errors.NewTypeError("INTEGER", args[0].Type().String()) } b, err := args[1].AsInt() if err != nil { return errors.NewTypeError("INTEGER", args[1].Type().String()) } return &object.Integer{Value: gcd(a, b)} }, HelpText: `gcd(a, b) - Return the greatest common divisor of a and b a and b must be integers. Returns an integer.`, }, "factorial": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } n, err := args[0].AsInt() if err != nil { return errors.NewTypeError("INTEGER", args[0].Type().String()) } if n < 0 { return errors.NewError("factorial: negative number") } if n > 20 { return errors.NewError("factorial: result too large") } result := int64(1) for i := int64(2); i <= n; i++ { result *= i } return &object.Integer{Value: result} }, HelpText: `factorial(n) - Return n! n must be a non-negative integer <= 20. Returns an integer.`, }, "isnan": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } switch arg := args[0].(type) { case *object.Integer: return &object.Boolean{Value: false} case *object.Float: return &object.Boolean{Value: math.IsNaN(arg.Value)} default: return errors.NewTypeError("INTEGER or FLOAT", arg.Type().String()) } }, HelpText: `isnan(x) - Check if x is NaN (Not a Number) Returns True if x is NaN, False otherwise.`, }, "isinf": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } switch arg := args[0].(type) { case *object.Integer: return &object.Boolean{Value: false} case *object.Float: return &object.Boolean{Value: math.IsInf(arg.Value, 0)} default: return errors.NewTypeError("INTEGER or FLOAT", arg.Type().String()) } }, HelpText: `isinf(x) - Check if x is infinite Returns True if x is positive or negative infinity.`, }, "isfinite": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } switch arg := args[0].(type) { case *object.Integer: return &object.Boolean{Value: true} case *object.Float: return &object.Boolean{Value: !math.IsNaN(arg.Value) && !math.IsInf(arg.Value, 0)} default: return errors.NewTypeError("INTEGER or FLOAT", arg.Type().String()) } }, HelpText: `isfinite(x) - Check if x is finite Returns True if x is neither NaN nor infinite.`, }, "copysign": { Fn: twoFloatFunc(math.Copysign), HelpText: `copysign(x, y) - Return x with the sign of y Returns a float with magnitude of x and sign of y.`, }, "trunc": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } switch arg := args[0].(type) { case *object.Integer: return arg case *object.Float: return &object.Integer{Value: int64(math.Trunc(arg.Value))} default: return errors.NewTypeError("INTEGER or FLOAT", arg.Type().String()) } }, HelpText: `trunc(x) - Truncate x to the nearest integer toward zero Returns an integer.`, }, "log10": { Fn: oneFloatFunc(math.Log10), HelpText: `log10(x) - Return the base-10 logarithm of x x must be positive. Returns a float.`, }, "log2": { Fn: oneFloatFunc(math.Log2), HelpText: `log2(x) - Return the base-2 logarithm of x x must be positive. Returns a float.`, }, "hypot": { Fn: twoFloatFunc(math.Hypot), HelpText: `hypot(x, y) - Return the Euclidean distance sqrt(x*x + y*y) Returns a float.`, }, "asin": { Fn: oneFloatFunc(math.Asin), HelpText: `asin(x) - Return the arc sine of x in radians x must be in the range [-1, 1]. Returns a float.`, }, "acos": { Fn: oneFloatFunc(math.Acos), HelpText: `acos(x) - Return the arc cosine of x in radians x must be in the range [-1, 1]. Returns a float.`, }, "atan": { Fn: oneFloatFunc(math.Atan), HelpText: `atan(x) - Return the arc tangent of x in radians Returns a float in the range [-pi/2, pi/2].`, }, "atan2": { Fn: twoFloatFunc(math.Atan2), HelpText: `atan2(y, x) - Return the arc tangent of y/x in radians Correctly handles the quadrant of the result. Returns a float in the range [-pi, pi].`, }, }, map[string]object.Object{ "pi": &object.Float{Value: math.Pi}, "e": &object.Float{Value: math.E}, "inf": &object.Float{Value: math.Inf(1)}, "nan": &object.Float{Value: math.NaN()}, }, "Mathematical functions library")
var ParseResultClass = &object.Class{ Name: "ParseResult", Methods: map[string]object.Object{ "geturl": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } result := args[0].(*object.Instance) scheme, _ := result.Fields["scheme"].(*object.String) netloc, _ := result.Fields["netloc"].(*object.String) path, _ := result.Fields["path"].(*object.String) query, _ := result.Fields["query"].(*object.String) fragment, _ := result.Fields["fragment"].(*object.String) url := scheme.Value + "://" if netloc.Value != "" { url += netloc.Value } url += path.Value if query.Value != "" { url += "?" + query.Value } if fragment.Value != "" { url += "#" + fragment.Value } return &object.String{Value: url} }, HelpText: `geturl() - Reconstruct URL from parsed components`, }, }, }
ParseResult class for URL parsing results
var PlatformLibrary = object.NewLibrary(map[string]*object.Builtin{ "python_version": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } return &object.String{Value: build.Version} }, HelpText: `python_version() - Returns the Python version Returns the Python version (Scriptling version for compatibility).`, }, "system": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } switch runtime.GOOS { case "darwin": return &object.String{Value: "Darwin"} case "linux": return &object.String{Value: "Linux"} case "windows": return &object.String{Value: "Windows"} case "freebsd": return &object.String{Value: "FreeBSD"} default: return &object.String{Value: runtime.GOOS} } }, HelpText: `system() - Returns the system/OS name Returns 'Darwin', 'Linux', 'Windows', etc.`, }, "architecture": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } arch := "64bit" if runtime.GOARCH == "386" || runtime.GOARCH == "arm" { arch = "32bit" } return &object.List{Elements: []object.Object{&object.String{Value: arch}, &object.String{Value: ""}}} }, HelpText: `architecture() - Returns the architecture Returns a list like ['64bit', ''] indicating bits and linkage.`, }, "machine": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } return &object.String{Value: runtime.GOARCH} }, HelpText: `machine() - Returns the machine type (architecture) Returns 'amd64', 'arm64', 'arm', etc.`, }, "platform": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } return &object.String{Value: runtime.GOOS + "-" + runtime.GOARCH} }, HelpText: `platform() - Returns a string identifying the platform Returns a string like 'darwin-amd64', 'linux-amd64', etc.`, }, "scriptling_version": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } return &object.String{Value: build.Version} }, HelpText: `scriptling_version() - Returns Scriptling version string Returns the current version of Scriptling.`, }, "processor": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } return &object.String{Value: runtime.GOARCH} }, HelpText: `processor() - Returns the processor name Returns the processor name, often same as machine.`, }, "node": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } if hostname, err := os.Hostname(); err == nil { return &object.String{Value: hostname} } return &object.String{Value: ""} }, HelpText: `node() - Returns the network name (hostname) Returns the computer's network name.`, }, "release": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } return &object.String{Value: build.Version} }, HelpText: `release() - Returns the system release Returns the system release (Scriptling version for compatibility).`, }, "version": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } return &object.String{Value: build.Version} }, HelpText: `version() - Returns the system version Returns the system version (Scriptling version for compatibility).`, }, "uname": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } pairs := make(map[string]object.DictPair) // Get system name (capitalized, matching system() function) var systemName string switch runtime.GOOS { case "darwin": systemName = "Darwin" case "linux": systemName = "Linux" case "windows": systemName = "Windows" case "freebsd": systemName = "FreeBSD" default: systemName = runtime.GOOS } pairs["system"] = object.DictPair{Key: &object.String{Value: "system"}, Value: &object.String{Value: systemName}} pairs["machine"] = object.DictPair{Key: &object.String{Value: "machine"}, Value: &object.String{Value: runtime.GOARCH}} pairs["processor"] = object.DictPair{Key: &object.String{Value: "processor"}, Value: &object.String{Value: runtime.GOARCH}} node := "" if hostname, err := os.Hostname(); err == nil { node = hostname } pairs["node"] = object.DictPair{Key: &object.String{Value: "node"}, Value: &object.String{Value: node}} pairs["release"] = object.DictPair{Key: &object.String{Value: "release"}, Value: &object.String{Value: build.Version}} pairs["version"] = object.DictPair{Key: &object.String{Value: "version"}, Value: &object.String{Value: build.Version}} return &object.Dict{Pairs: pairs} }, HelpText: `uname() - Returns system information Returns a dict with keys: system, node, release, version, machine, processor`, }, }, nil, "Access to underlying platform's identifying data")
PlatformLibrary provides system/platform information (Python's platform module)
var RandomLibrary = object.NewLibrary(map[string]*object.Builtin{ "seed": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.MaxArgs(args, 1); err != nil { return err } var seedVal int64 if len(args) == 0 { seedVal = time.Now().UnixNano() } else { switch arg := args[0].(type) { case *object.Integer: seedVal = arg.Value case *object.Float: seedVal = int64(arg.Value) default: return errors.NewTypeError("INTEGER or FLOAT", args[0].Type().String()) } } rng = rand.New(rand.NewSource(seedVal)) return &object.Null{} }, HelpText: `seed([a]) - Initialize the random number generator If a is omitted, current time is used. Otherwise, a is used as the seed.`, }, "randint": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } var min, max int64 switch arg := args[0].(type) { case *object.Integer: min = arg.Value default: return errors.NewTypeError("INTEGER", args[0].Type().String()) } switch arg := args[1].(type) { case *object.Integer: max = arg.Value default: return errors.NewTypeError("INTEGER", args[1].Type().String()) } if min > max { return errors.NewError("randint() min must be <= max") } val := min + rng.Int63n(max-min+1) return &object.Integer{Value: val} }, HelpText: `randint(min, max) - Return random integer Returns a random integer N such that min <= N <= max.`, }, "random": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } return &object.Float{Value: rng.Float64()} }, HelpText: `random() - Return random float Returns a random float in the range [0.0, 1.0).`, }, "choice": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } if str, ok := args[0].(*object.String); ok { if len(str.Value) == 0 { return errors.NewError("choice() string cannot be empty") } idx := rng.Intn(len(str.Value)) return &object.String{Value: string(str.Value[idx])} } if list, ok := args[0].(*object.List); ok { if len(list.Elements) == 0 { return errors.NewError("choice() list cannot be empty") } idx := rng.Intn(len(list.Elements)) return list.Elements[idx] } return errors.NewTypeError("LIST or STRING", args[0].Type().String()) }, HelpText: `choice(seq) - Return random element from sequence Returns a randomly selected element from the given list or string.`, }, "shuffle": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } if list, ok := args[0].(*object.List); ok { n := len(list.Elements) for i := n - 1; i > 0; i-- { j := rng.Intn(i + 1) list.Elements[i], list.Elements[j] = list.Elements[j], list.Elements[i] } return &object.Null{} } return errors.NewTypeError("LIST", args[0].Type().String()) }, HelpText: `shuffle(list) - Shuffle list in place Randomly shuffles the elements of the list in place using the Fisher-Yates algorithm. Returns None.`, }, "uniform": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } var a, b float64 switch arg := args[0].(type) { case *object.Integer: a = float64(arg.Value) case *object.Float: a = arg.Value default: return errors.NewTypeError("INTEGER or FLOAT", args[0].Type().String()) } switch arg := args[1].(type) { case *object.Integer: b = float64(arg.Value) case *object.Float: b = arg.Value default: return errors.NewTypeError("INTEGER or FLOAT", args[1].Type().String()) } val := a + rng.Float64()*(b-a) return &object.Float{Value: val} }, HelpText: `uniform(a, b) - Return random float N such that a <= N <= b Returns a random floating-point number N such that a <= N <= b.`, }, "sample": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } list, err := args[0].AsList() if err != nil { return err } k, ok := args[1].(*object.Integer) if !ok { return errors.NewTypeError("INTEGER", args[1].Type().String()) } n := len(list) if k.Value < 0 || k.Value > int64(n) { return errors.NewError("sample larger than population or is negative") } indices := make([]int, n) for i := range indices { indices[i] = i } for i := 0; i < int(k.Value); i++ { j := i + rng.Intn(n-i) indices[i], indices[j] = indices[j], indices[i] } result := make([]object.Object, k.Value) for i := 0; i < int(k.Value); i++ { result[i] = list[indices[i]] } return &object.List{Elements: result} }, HelpText: `sample(population, k) - Return k unique random elements from population Returns a k length list of unique elements chosen from the population sequence. Used for random sampling without replacement.`, }, "randrange": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) < 1 || len(args) > 3 { return errors.NewError("randrange() takes 1 to 3 arguments (%d given)", len(args)) } var start, stop, step int64 step = 1 switch len(args) { case 1: start = 0 if i, ok := args[0].(*object.Integer); ok { stop = i.Value } else { return errors.NewTypeError("INTEGER", args[0].Type().String()) } case 2: if i, ok := args[0].(*object.Integer); ok { start = i.Value } else { return errors.NewTypeError("INTEGER", args[0].Type().String()) } if i, ok := args[1].(*object.Integer); ok { stop = i.Value } else { return errors.NewTypeError("INTEGER", args[1].Type().String()) } case 3: if i, ok := args[0].(*object.Integer); ok { start = i.Value } else { return errors.NewTypeError("INTEGER", args[0].Type().String()) } if i, ok := args[1].(*object.Integer); ok { stop = i.Value } else { return errors.NewTypeError("INTEGER", args[1].Type().String()) } if i, ok := args[2].(*object.Integer); ok { step = i.Value } else { return errors.NewTypeError("INTEGER", args[2].Type().String()) } } if step == 0 { return errors.NewError("randrange() step argument must not be zero") } var n int64 if step > 0 { n = (stop - start + step - 1) / step } else { n = (start - stop - step - 1) / (-step) } if n <= 0 { return errors.NewError("randrange() empty range") } return &object.Integer{Value: start + step*rng.Int63n(n)} }, HelpText: `randrange(stop) or randrange(start, stop[, step]) - Return random integer from range Returns a randomly selected element from range(start, stop, step). Like randint, but doesn't include the endpoint.`, }, "gauss": { Fn: gaussianRandom, HelpText: `gauss(mu, sigma) - Return random number from Gaussian distribution mu is the mean, sigma is the standard deviation.`, }, "normalvariate": { Fn: gaussianRandom, HelpText: `normalvariate(mu, sigma) - Return random number from normal distribution mu is the mean, sigma is the standard deviation. Same as gauss() but provided for compatibility.`, }, "expovariate": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } var lambd float64 switch arg := args[0].(type) { case *object.Integer: lambd = float64(arg.Value) case *object.Float: lambd = arg.Value default: return errors.NewTypeError("INTEGER or FLOAT", args[0].Type().String()) } if lambd == 0 { return errors.NewError("expovariate() lambda must not be zero") } val := -math.Log(1.0-rng.Float64()) / lambd return &object.Float{Value: val} }, HelpText: `expovariate(lambd) - Return random number from exponential distribution lambd is 1.0 divided by the desired mean.`, }, }, nil, "Random number generation library")
var ReLibrary = object.NewLibrary(map[string]*object.Builtin{ "match": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) < 2 || len(args) > 3 { return errors.NewError("match() takes 2 or 3 arguments (%d given)", len(args)) } if args[0].Type() != object.STRING_OBJ || args[1].Type() != object.STRING_OBJ { return errors.NewTypeError("STRING", "mixed types") } pattern, _ := args[0].AsString() text, _ := args[1].AsString() flags, err := getFlags(args, 2) if err != nil { return errors.NewError("%s", err.Error()) } pattern = applyFlags(pattern, flags) re, err := GetCompiledRegex(pattern) if err != nil { return errors.NewError("regex compile error: %s", err.Error()) } match := re.FindStringSubmatchIndex(text) if match == nil || match[0] != 0 { return &object.Null{} } groups := make([]string, 0) for i := 0; i < len(match); i += 2 { if match[i] >= 0 && match[i+1] >= 0 { groups = append(groups, text[match[i]:match[i+1]]) } else { groups = append(groups, "") } } return createMatchInstance(groups, match[0], match[1]) }, HelpText: `match(pattern, string, flags=0) - Match pattern at start of string Returns a Match object if the pattern matches at the beginning, or None if no match. Use match.group(0) for the full match, match.group(1) for the first group, etc. Methods on Match object: group(n=0) - Return the nth matched group (0 = full match) groups() - Return tuple of all matched groups (excluding group 0) start(n=0) - Return start position of nth group end(n=0) - Return end position of nth group span(n=0) - Return (start, end) tuple for nth group Flags: re.IGNORECASE or re.I - Case-insensitive matching re.MULTILINE or re.M - ^ and $ match at line boundaries re.DOTALL or re.S - . matches newlines`, }, "search": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) < 2 || len(args) > 3 { return errors.NewError("search() takes 2 or 3 arguments (%d given)", len(args)) } if args[0].Type() != object.STRING_OBJ || args[1].Type() != object.STRING_OBJ { return errors.NewTypeError("STRING", "mixed types") } pattern, _ := args[0].AsString() text, _ := args[1].AsString() flags, err := getFlags(args, 2) if err != nil { return errors.NewError("%s", err.Error()) } pattern = applyFlags(pattern, flags) re, err := GetCompiledRegex(pattern) if err != nil { return errors.NewError("regex compile error: %s", err.Error()) } match := re.FindStringSubmatchIndex(text) if match == nil { return &object.Null{} } groups := make([]string, 0) for i := 0; i < len(match); i += 2 { if match[i] >= 0 && match[i+1] >= 0 { groups = append(groups, text[match[i]:match[i+1]]) } else { groups = append(groups, "") } } return createMatchInstance(groups, match[0], match[1]) }, HelpText: `search(pattern, string, flags=0) - Search for pattern anywhere in string Returns a Match object for the first match, or None if no match found. Use match.group(0) for the full match, match.group(1) for the first group, etc. Methods on Match object: group(n=0) - Return the nth matched group (0 = full match) groups() - Return tuple of all matched groups (excluding group 0) start(n=0) - Return start position of nth group end(n=0) - Return end position of nth group span(n=0) - Return (start, end) tuple for nth group Flags: re.IGNORECASE or re.I - Case-insensitive matching re.MULTILINE or re.M - ^ and $ match at line boundaries re.DOTALL or re.S - . matches newlines`, }, "findall": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) < 2 || len(args) > 3 { return errors.NewError("findall() takes 2 or 3 arguments (%d given)", len(args)) } if args[0].Type() != object.STRING_OBJ || args[1].Type() != object.STRING_OBJ { return errors.NewTypeError("STRING", "mixed types") } pattern, _ := args[0].AsString() text, _ := args[1].AsString() flags, err := getFlags(args, 2) if err != nil { return errors.NewError("%s", err.Error()) } pattern = applyFlags(pattern, flags) re, err := GetCompiledRegex(pattern) if err != nil { return errors.NewError("regex compile error: %s", err.Error()) } matches := re.FindAllStringSubmatch(text, -1) elements := make([]object.Object, len(matches)) numGroups := re.NumSubexp() for i, match := range matches { if numGroups == 0 { elements[i] = &object.String{Value: match[0]} } else if numGroups == 1 { elements[i] = &object.String{Value: match[1]} } else { groupElements := make([]object.Object, numGroups) for j := 1; j <= numGroups; j++ { groupElements[j-1] = &object.String{Value: match[j]} } elements[i] = &object.Tuple{Elements: groupElements} } } return &object.List{Elements: elements} }, HelpText: `findall(pattern, string, flags=0) - Find all matches Returns a list of all substrings that match the regex pattern. If the pattern contains capturing groups, returns a list of tuples containing the groups. If there is one capturing group, returns a list of strings for that group. If there are no capturing groups, returns a list of strings for the full matches. Flags: re.IGNORECASE or re.I - Case-insensitive matching re.MULTILINE or re.M - ^ and $ match at line boundaries re.DOTALL or re.S - . matches newlines`, }, "finditer": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) < 2 || len(args) > 3 { return errors.NewError("finditer() takes 2 or 3 arguments (%d given)", len(args)) } if args[0].Type() != object.STRING_OBJ || args[1].Type() != object.STRING_OBJ { return errors.NewTypeError("STRING", "mixed types") } pattern, _ := args[0].AsString() text, _ := args[1].AsString() flags, err := getFlags(args, 2) if err != nil { return errors.NewError("%s", err.Error()) } pattern = applyFlags(pattern, flags) re, err := GetCompiledRegex(pattern) if err != nil { return errors.NewError("regex compile error: %s", err.Error()) } allMatches := re.FindAllStringSubmatchIndex(text, -1) elements := make([]object.Object, len(allMatches)) for i, match := range allMatches { groups := make([]string, 0) for j := 0; j < len(match); j += 2 { if match[j] >= 0 && match[j+1] >= 0 { groups = append(groups, text[match[j]:match[j+1]]) } else { groups = append(groups, "") } } elements[i] = createMatchInstance(groups, match[0], match[1]) } return &object.List{Elements: elements} }, HelpText: `finditer(pattern, string, flags=0) - Find all matches as Match objects Returns a list of Match objects for all matches of the regex pattern in the string. Flags: re.IGNORECASE or re.I - Case-insensitive matching re.MULTILINE or re.M - ^ and $ match at line boundaries re.DOTALL or re.S - . matches newlines`, }, "sub": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) < 3 || len(args) > 5 { return errors.NewError("sub() takes 3 to 5 arguments (%d given)", len(args)) } if args[0].Type() != object.STRING_OBJ || args[1].Type() != object.STRING_OBJ || args[2].Type() != object.STRING_OBJ { return errors.NewTypeError("STRING", "mixed types") } pattern, _ := args[0].AsString() replacement, _ := args[1].AsString() text, _ := args[2].AsString() count := -1 if len(args) > 3 { if args[3].Type() != object.INTEGER_OBJ { return errors.NewError("count must be an integer") } val, _ := args[3].AsInt() count = int(val) } flags, err := getFlags(args, 4) if err != nil { return errors.NewError("%s", err.Error()) } pattern = applyFlags(pattern, flags) re, err := GetCompiledRegex(pattern) if err != nil { return errors.NewError("regex compile error: %s", err.Error()) } var result string if count == 0 { result = text } else if count < 0 { result = re.ReplaceAllString(text, replacement) } else { replaced := 0 result = re.ReplaceAllStringFunc(text, func(match string) string { if replaced < count { replaced++ return re.ReplaceAllString(match, replacement) } return match }) } return &object.String{Value: result} }, HelpText: `sub(pattern, repl, string, count=0, flags=0) - Replace matches Replaces occurrences of the regex pattern in the string with the replacement. If count is 0 (default), all occurrences are replaced. If count > 0, only the first count occurrences are replaced. Flags: re.IGNORECASE or re.I - Case-insensitive matching re.MULTILINE or re.M - ^ and $ match at line boundaries re.DOTALL or re.S - . matches newlines`, }, "split": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) < 2 || len(args) > 4 { return errors.NewError("split() takes 2 to 4 arguments (%d given)", len(args)) } if args[0].Type() != object.STRING_OBJ || args[1].Type() != object.STRING_OBJ { return errors.NewTypeError("STRING", "mixed types") } pattern, _ := args[0].AsString() text, _ := args[1].AsString() maxsplit := -1 if len(args) > 2 { if args[2].Type() != object.INTEGER_OBJ { return errors.NewError("maxsplit must be an integer") } val, _ := args[2].AsInt() maxsplit = int(val) if maxsplit == 0 { maxsplit = -1 } } flags, err := getFlags(args, 3) if err != nil { return errors.NewError("%s", err.Error()) } pattern = applyFlags(pattern, flags) re, err := GetCompiledRegex(pattern) if err != nil { return errors.NewError("regex compile error: %s", err.Error()) } parts := re.Split(text, maxsplit) elements := make([]object.Object, len(parts)) for i, part := range parts { elements[i] = &object.String{Value: part} } return &object.List{Elements: elements} }, HelpText: `split(pattern, string, maxsplit=0, flags=0) - Split string by pattern Splits the string by occurrences of the regex pattern and returns a list of substrings. If maxsplit is 0 (default), all occurrences are split. If maxsplit > 0, at most maxsplit splits are done. Flags: re.IGNORECASE or re.I - Case-insensitive matching re.MULTILINE or re.M - ^ and $ match at line boundaries re.DOTALL or re.S - . matches newlines`, }, "compile": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) < 1 || len(args) > 2 { return errors.NewError("compile() takes 1 or 2 arguments (%d given)", len(args)) } if args[0].Type() != object.STRING_OBJ { return errors.NewTypeError("STRING", args[0].Type().String()) } pattern, _ := args[0].AsString() flags, err := getFlags(args, 1) if err != nil { return errors.NewError("%s", err.Error()) } pattern = applyFlags(pattern, flags) _, err = GetCompiledRegex(pattern) if err != nil { return errors.NewError("regex compile error: %s", err.Error()) } return createRegexInstance(pattern, flags) }, HelpText: `compile(pattern, flags=0) - Compile regex pattern Validates and caches a regex pattern for later use. Returns the pattern if valid. Flags: re.IGNORECASE or re.I - Case-insensitive matching re.MULTILINE or re.M - ^ and $ match at line boundaries re.DOTALL or re.S - . matches newlines`, }, "escape": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } if args[0].Type() != object.STRING_OBJ { return errors.NewTypeError("STRING", args[0].Type().String()) } text, _ := args[0].AsString() escaped := regexp.QuoteMeta(text) return &object.String{Value: escaped} }, HelpText: `escape(pattern) - Escape special regex characters Returns a string with all special regex characters escaped.`, }, "fullmatch": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) < 2 || len(args) > 3 { return errors.NewError("fullmatch() takes 2 or 3 arguments (%d given)", len(args)) } if args[0].Type() != object.STRING_OBJ || args[1].Type() != object.STRING_OBJ { return errors.NewTypeError("STRING", "mixed types") } pattern, _ := args[0].AsString() text, _ := args[1].AsString() flags, err := getFlags(args, 2) if err != nil { return errors.NewError("%s", err.Error()) } pattern = applyFlags(pattern, flags) re, err := GetCompiledRegex(pattern) if err != nil { return errors.NewError("regex compile error: %s", err.Error()) } match := re.FindStringSubmatchIndex(text) if match == nil || match[0] != 0 || match[1] != len(text) { return &object.Null{} } groups := make([]string, 0) for i := 0; i < len(match); i += 2 { if match[i] >= 0 && match[i+1] >= 0 { groups = append(groups, text[match[i]:match[i+1]]) } else { groups = append(groups, "") } } return createMatchInstance(groups, match[0], match[1]) }, HelpText: `fullmatch(pattern, string, flags=0) - Match entire string Returns a Match object if the regex pattern matches the entire string, or None if no match. Flags: re.IGNORECASE or re.I - Case-insensitive matching re.MULTILINE or re.M - ^ and $ match at line boundaries re.DOTALL or re.S - . matches newlines`, }, }, map[string]object.Object{ "IGNORECASE": &object.Integer{Value: RE_IGNORECASE}, "I": &object.Integer{Value: RE_IGNORECASE}, "MULTILINE": &object.Integer{Value: RE_MULTILINE}, "M": &object.Integer{Value: RE_MULTILINE}, "DOTALL": &object.Integer{Value: RE_DOTALL}, "S": &object.Integer{Value: RE_DOTALL}, }, "Regular expression library")
var RegexClass = &object.Class{ Name: "Regex", Methods: map[string]object.Object{ "match": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } if args[1].Type() != object.STRING_OBJ { return errors.NewTypeError("STRING", args[1].Type().String()) } regex := args[0].(*object.Instance) pattern := regex.Fields["pattern"].(*object.String).Value text, _ := args[1].AsString() re, err := GetCompiledRegex(pattern) if err != nil { return errors.NewError("regex compile error: %s", err.Error()) } match := re.FindStringSubmatchIndex(text) if match == nil || match[0] != 0 { return &object.Null{} } groups := make([]string, 0) for i := 0; i < len(match); i += 2 { if match[i] >= 0 && match[i+1] >= 0 { groups = append(groups, text[match[i]:match[i+1]]) } else { groups = append(groups, "") } } return createMatchInstance(groups, match[0], match[1]) }, HelpText: `match(string) - Match pattern at start of string Returns a Match object if the pattern matches at the beginning, or None if no match.`, }, "search": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } if args[1].Type() != object.STRING_OBJ { return errors.NewTypeError("STRING", args[1].Type().String()) } regex := args[0].(*object.Instance) pattern := regex.Fields["pattern"].(*object.String).Value text, _ := args[1].AsString() re, err := GetCompiledRegex(pattern) if err != nil { return errors.NewError("regex compile error: %s", err.Error()) } match := re.FindStringSubmatchIndex(text) if match == nil { return &object.Null{} } groups := make([]string, 0) for i := 0; i < len(match); i += 2 { if match[i] >= 0 && match[i+1] >= 0 { groups = append(groups, text[match[i]:match[i+1]]) } else { groups = append(groups, "") } } return createMatchInstance(groups, match[0], match[1]) }, HelpText: `search(string) - Search for pattern anywhere in string Returns a Match object for the first match, or None if no match found.`, }, "findall": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } if args[1].Type() != object.STRING_OBJ { return errors.NewTypeError("STRING", args[1].Type().String()) } regex := args[0].(*object.Instance) pattern := regex.Fields["pattern"].(*object.String).Value text, _ := args[1].AsString() re, err := GetCompiledRegex(pattern) if err != nil { return errors.NewError("regex compile error: %s", err.Error()) } matches := re.FindAllStringSubmatch(text, -1) elements := make([]object.Object, len(matches)) numGroups := re.NumSubexp() for i, match := range matches { if numGroups == 0 { elements[i] = &object.String{Value: match[0]} } else if numGroups == 1 { elements[i] = &object.String{Value: match[1]} } else { groupElements := make([]object.Object, numGroups) for j := 1; j <= numGroups; j++ { groupElements[j-1] = &object.String{Value: match[j]} } elements[i] = &object.Tuple{Elements: groupElements} } } return &object.List{Elements: elements} }, HelpText: `findall(string) - Find all matches Returns a list of all substrings that match the regex pattern. If the pattern contains capturing groups, returns a list of tuples containing the groups. If there is one capturing group, returns a list of strings for that group. If there are no capturing groups, returns a list of strings for the full matches.`, }, "finditer": &object.Builtin{ Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } if args[1].Type() != object.STRING_OBJ { return errors.NewTypeError("STRING", args[1].Type().String()) } regex := args[0].(*object.Instance) pattern := regex.Fields["pattern"].(*object.String).Value text, _ := args[1].AsString() re, err := GetCompiledRegex(pattern) if err != nil { return errors.NewError("regex compile error: %s", err.Error()) } allMatches := re.FindAllStringSubmatchIndex(text, -1) elements := make([]object.Object, len(allMatches)) for i, match := range allMatches { groups := make([]string, 0) for j := 0; j < len(match); j += 2 { if match[j] >= 0 && match[j+1] >= 0 { groups = append(groups, text[match[j]:match[j+1]]) } else { groups = append(groups, "") } } elements[i] = createMatchInstance(groups, match[0], match[1]) } return &object.List{Elements: elements} }, HelpText: `finditer(string) - Find all matches as Match objects Returns a list of Match objects for all matches of the regex pattern in the string.`, }, }, }
Regex class definition
var StatisticsLibrary = object.NewLibrary(map[string]*object.Builtin{ "mean": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } values, err := extractNumbers(args[0]) if err != nil { return err } if len(values) == 0 { return errors.NewError("mean requires at least one data point") } sum := 0.0 for _, v := range values { sum += v } return &object.Float{Value: sum / float64(len(values))} }, HelpText: `mean(data) - Return the arithmetic mean of data Parameters: data - List of numbers Returns: Float Example: import statistics statistics.mean([1, 2, 3, 4, 5]) # 3.0`, }, "fmean": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } values, err := extractNumbers(args[0]) if err != nil { return err } if len(values) == 0 { return errors.NewError("fmean requires at least one data point") } sum := 0.0 for _, v := range values { sum += v } return &object.Float{Value: sum / float64(len(values))} }, HelpText: `fmean(data) - Return the arithmetic mean of data (faster float version) Parameters: data - List of numbers Returns: Float Example: import statistics statistics.fmean([1.0, 2.0, 3.0]) # 2.0`, }, "geometric_mean": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } values, err := extractNumbers(args[0]) if err != nil { return err } if len(values) == 0 { return errors.NewError("geometric_mean requires at least one data point") } logSum := 0.0 for _, v := range values { if v <= 0 { return errors.NewError("geometric_mean requires positive numbers") } logSum += math.Log(v) } return &object.Float{Value: math.Exp(logSum / float64(len(values)))} }, HelpText: `geometric_mean(data) - Return the geometric mean of data Parameters: data - List of positive numbers Returns: Float Example: import statistics statistics.geometric_mean([1, 2, 4]) # 2.0`, }, "harmonic_mean": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } values, err := extractNumbers(args[0]) if err != nil { return err } if len(values) == 0 { return errors.NewError("harmonic_mean requires at least one data point") } reciprocalSum := 0.0 for _, v := range values { if v <= 0 { return errors.NewError("harmonic_mean requires positive numbers") } reciprocalSum += 1.0 / v } return &object.Float{Value: float64(len(values)) / reciprocalSum} }, HelpText: `harmonic_mean(data) - Return the harmonic mean of data Parameters: data - List of positive numbers Returns: Float Example: import statistics statistics.harmonic_mean([1, 2, 4]) # ~1.714`, }, "median": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } values, err := extractNumbers(args[0]) if err != nil { return err } if len(values) == 0 { return errors.NewError("median requires at least one data point") } sorted := make([]float64, len(values)) copy(sorted, values) sort.Float64s(sorted) n := len(sorted) if n%2 == 0 { return &object.Float{Value: (sorted[n/2-1] + sorted[n/2]) / 2} } return &object.Float{Value: sorted[n/2]} }, HelpText: `median(data) - Return the median (middle value) of data Parameters: data - List of numbers Returns: Float Example: import statistics statistics.median([1, 3, 5]) # 3.0 statistics.median([1, 3, 5, 7]) # 4.0`, }, "mode": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } list, ok := args[0].(*object.List) if !ok { return errors.NewTypeError("LIST", args[0].Type().String()) } if len(list.Elements) == 0 { return errors.NewError("mode requires at least one data point") } counts := make(map[string]int) elements := make(map[string]object.Object) for _, elem := range list.Elements { key := elem.Inspect() counts[key]++ elements[key] = elem } maxCount := 0 var modeKey string for key, count := range counts { if count > maxCount { maxCount = count modeKey = key } } return elements[modeKey] }, HelpText: `mode(data) - Return the most common value in data Parameters: data - List of values Returns: Most frequent value (same type as input elements) Example: import statistics statistics.mode([1, 1, 2, 3]) # 1 statistics.mode(["a", "b", "a"]) # "a"`, }, "stdev": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } values, err := extractNumbers(args[0]) if err != nil { return err } if len(values) < 2 { return errors.NewError("stdev requires at least two data points") } variance := sampleVariance(values) return &object.Float{Value: math.Sqrt(variance)} }, HelpText: `stdev(data) - Return the sample standard deviation of data Parameters: data - List of numbers (at least 2) Returns: Float Example: import statistics statistics.stdev([1, 2, 3, 4, 5]) # ~1.58`, }, "pstdev": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } values, err := extractNumbers(args[0]) if err != nil { return err } if len(values) < 1 { return errors.NewError("pstdev requires at least one data point") } variance := populationVariance(values) return &object.Float{Value: math.Sqrt(variance)} }, HelpText: `pstdev(data) - Return the population standard deviation of data Parameters: data - List of numbers Returns: Float Example: import statistics statistics.pstdev([1, 2, 3, 4, 5]) # ~1.41`, }, "variance": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } values, err := extractNumbers(args[0]) if err != nil { return err } if len(values) < 2 { return errors.NewError("variance requires at least two data points") } return &object.Float{Value: sampleVariance(values)} }, HelpText: `variance(data) - Return the sample variance of data Parameters: data - List of numbers (at least 2) Returns: Float Example: import statistics statistics.variance([1, 2, 3, 4, 5]) # 2.5`, }, "pvariance": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } values, err := extractNumbers(args[0]) if err != nil { return err } if len(values) < 1 { return errors.NewError("pvariance requires at least one data point") } return &object.Float{Value: populationVariance(values)} }, HelpText: `pvariance(data) - Return the population variance of data Parameters: data - List of numbers Returns: Float Example: import statistics statistics.pvariance([1, 2, 3, 4, 5]) # 2.0`, }, }, nil, "Statistical functions library")
var StringLibrary = object.NewLibrary( nil, map[string]object.Object{ "ascii_letters": &object.String{Value: asciiLetters}, "ascii_lowercase": &object.String{Value: asciiLowercase}, "ascii_uppercase": &object.String{Value: asciiUppercase}, "digits": &object.String{Value: digits}, "hexdigits": &object.String{Value: hexdigits}, "octdigits": &object.String{Value: octdigits}, "punctuation": &object.String{Value: punctuation}, "whitespace": &object.String{Value: whitespace}, "printable": &object.String{Value: printable}, }, "String constants for character classification", )
var TextwrapLibrary = object.NewLibrary(map[string]*object.Builtin{ "wrap": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { width, _ := kwargs.GetInt("width", 70) widthInt := int(width) if len(args) < 1 { return errors.NewError("wrap() requires at least 1 argument") } text, ok := args[0].(*object.String) if !ok { return errors.NewTypeError("STRING", args[0].Type().String()) } if len(args) >= 2 { if intVal, ok := args[1].(*object.Integer); ok { widthInt = int(intVal.Value) } } lines := wrapText(text.Value, widthInt) elements := make([]object.Object, len(lines)) for i, line := range lines { elements[i] = &object.String{Value: line} } return &object.List{Elements: elements} }, HelpText: `wrap(text, width=70) - Wrap a single paragraph of text Parameters: text - Text to wrap width - Maximum line width (default 70) Returns: List of lines Example: import textwrap lines = textwrap.wrap("Hello world, this is a long line", 10)`, }, "fill": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { width, _ := kwargs.GetInt("width", 70) widthInt := int(width) if len(args) < 1 { return errors.NewError("fill() requires at least 1 argument") } text, ok := args[0].(*object.String) if !ok { return errors.NewTypeError("STRING", args[0].Type().String()) } if len(args) >= 2 { if intVal, ok := args[1].(*object.Integer); ok { widthInt = int(intVal.Value) } } lines := wrapText(text.Value, widthInt) return &object.String{Value: strings.Join(lines, "\n")} }, HelpText: `fill(text, width=70) - Wrap text and return a single string Parameters: text - Text to wrap width - Maximum line width (default 70) Returns: Wrapped text as single string with newlines Example: import textwrap result = textwrap.fill("Hello world, this is a long line", 10)`, }, "dedent": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) != 1 { return errors.NewError("dedent() requires exactly 1 argument") } text, ok := args[0].(*object.String) if !ok { return errors.NewTypeError("STRING", args[0].Type().String()) } return &object.String{Value: dedentText(text.Value)} }, HelpText: `dedent(text) - Remove common leading whitespace from all lines Parameters: text - Text to dedent Returns: Dedented text Example: import textwrap text = """ Hello World """ result = textwrap.dedent(text) # Lines start at column 0`, }, "indent": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if len(args) < 2 { return errors.NewError("indent() requires at least 2 arguments") } text, ok := args[0].(*object.String) if !ok { return errors.NewTypeError("STRING", args[0].Type().String()) } prefix, ok := args[1].(*object.String) if !ok { return errors.NewTypeError("STRING", args[1].Type().String()) } lines := strings.Split(text.Value, "\n") result := make([]string, len(lines)) for i, line := range lines { if len(strings.TrimSpace(line)) > 0 { result[i] = prefix.Value + line } else { result[i] = line } } return &object.String{Value: strings.Join(result, "\n")} }, HelpText: `indent(text, prefix) - Add prefix to non-empty lines Parameters: text - Text to indent prefix - String to add to beginning of each line Returns: Indented text Example: import textwrap result = textwrap.indent("Hello\nWorld", " ") # " Hello\n World"`, }, "shorten": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { placeholder, _ := kwargs.GetString("placeholder", "[...]") if len(args) < 2 { return errors.NewError("shorten() requires at least 2 arguments") } text, ok := args[0].(*object.String) if !ok { return errors.NewTypeError("STRING", args[0].Type().String()) } widthObj, ok := args[1].(*object.Integer) if !ok { return errors.NewTypeError("INTEGER", args[1].Type().String()) } width := int(widthObj.Value) collapsed := collapseWhitespace(text.Value) if len(collapsed) <= width { return &object.String{Value: collapsed} } if width <= len(placeholder) { return &object.String{Value: placeholder[:width]} } maxLen := width - len(placeholder) truncated := collapsed[:maxLen] lastSpace := strings.LastIndex(truncated, " ") if lastSpace > 0 { truncated = truncated[:lastSpace] } return &object.String{Value: strings.TrimSpace(truncated) + placeholder} }, HelpText: `shorten(text, width, placeholder="[...]") - Truncate text to fit width Parameters: text - Text to shorten width - Maximum width including placeholder placeholder - String to indicate truncation (default "[...]") Returns: Shortened text Example: import textwrap result = textwrap.shorten("Hello World!", 10) # "Hello[...]"`, }, }, nil, "Text wrapping and filling utilities")
var TimeLibrary = object.NewLibrary(map[string]*object.Builtin{ "time": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { return &object.Float{Value: float64(time.Now().UnixNano()) / 1e9} }, HelpText: `time() - Return current time in seconds Returns the current time as a floating point number of seconds since the Unix epoch.`, }, "perf_counter": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { return &object.Float{Value: time.Since(startTime).Seconds()} }, HelpText: `perf_counter() - Return performance counter Returns the value of a performance counter in fractional seconds.`, }, "sleep": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } seconds, err := args[0].AsFloat() if err != nil { return errors.ParameterError("seconds", err) } timer := time.NewTimer(time.Duration(seconds * float64(time.Second))) defer timer.Stop() select { case <-ctx.Done(): if ctx.Err() == context.DeadlineExceeded { return errors.NewTimeoutError() } return errors.NewCancelledError() case <-timer.C: return &object.Null{} } }, HelpText: `sleep(seconds) - Sleep for specified seconds Suspends execution for the given number of seconds.`, }, "localtime": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { var t time.Time if len(args) == 0 { t = time.Now() } else if len(args) == 1 { if ts, err := args[0].AsFloat(); err == nil { t = time.Unix(int64(ts), 0) } else if instance, ok := args[0].(*object.Instance); ok { if dt, err := GetTimeFromObject(instance); err == nil { t = dt } else { return errors.NewTypeError("INTEGER, FLOAT, or datetime instance", args[0].Type().String()) } } else { return errors.NewTypeError("INTEGER, FLOAT, or datetime instance", args[0].Type().String()) } } else { if err := errors.MaxArgs(args, 1); err != nil { return err } } return timeToTuple(t, false) }, HelpText: `localtime([timestamp_or_datetime]) - Convert to local time tuple Returns a time tuple in local time. If timestamp/datetime is omitted, uses current time.`, }, "gmtime": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { var t time.Time if len(args) == 0 { t = time.Now() } else if len(args) == 1 { if ts, err := args[0].AsFloat(); err == nil { t = time.Unix(int64(ts), 0) } else if instance, ok := args[0].(*object.Instance); ok { if dt, err := GetTimeFromObject(instance); err == nil { t = dt } else { return errors.NewTypeError("INTEGER, FLOAT, or datetime instance", args[0].Type().String()) } } else { return errors.NewTypeError("INTEGER, FLOAT, or datetime instance", args[0].Type().String()) } } else { if err := errors.MaxArgs(args, 1); err != nil { return err } } return timeToTuple(t, true) }, HelpText: `gmtime([timestamp_or_datetime]) - Convert to UTC time tuple Returns a time tuple in UTC. If timestamp/datetime is omitted, uses current time.`, }, "mktime": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } tuple, err := args[0].AsList() if err != nil { return err } if len(tuple) != 9 { return errors.NewError("time tuple must have exactly 9 elements") } year, _ := tuple[0].AsInt() month, _ := tuple[1].AsInt() day, _ := tuple[2].AsInt() hour, _ := tuple[3].AsInt() minute, _ := tuple[4].AsInt() second, _ := tuple[5].AsInt() t := time.Date(int(year), time.Month(month), int(day), int(hour), int(minute), int(second), 0, time.Local) return &object.Float{Value: float64(t.Unix())} }, HelpText: `mktime(tuple) - Convert time tuple to timestamp Converts a time tuple (9 elements) to a Unix timestamp.`, }, "strftime": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.RangeArgs(args, 1, 2); err != nil { return err } format, err := args[0].AsString() if err != nil { return err } var t time.Time if len(args) == 1 { t = time.Now() } else { tuple, err := args[1].AsList() if err != nil { return err } if len(tuple) != 9 { return errors.NewError("time tuple must have exactly 9 elements") } year, _ := tuple[0].AsInt() month, _ := tuple[1].AsInt() day, _ := tuple[2].AsInt() hour, _ := tuple[3].AsInt() minute, _ := tuple[4].AsInt() second, _ := tuple[5].AsInt() t = time.Date(int(year), time.Month(month), int(day), int(hour), int(minute), int(second), 0, time.Local) } return &object.String{Value: t.Format(pythonToGoFormat(format))} }, HelpText: `strftime(format[, tuple]) - Format time as string Formats a time according to the given format string. If tuple is omitted, uses current time.`, }, "strptime": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } str, err := args[0].AsString() if err != nil { return err } format, err := args[1].AsString() if err != nil { return err } t, parseErr := time.Parse(pythonToGoFormat(format), str) if parseErr != nil { return errors.NewError("strptime() parse error: %s", parseErr.Error()) } return timeToTuple(t, false) }, HelpText: `strptime(string, format) - Parse time from string Parses a time string according to the given format and returns a time tuple.`, }, "asctime": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { var t time.Time if len(args) == 0 { t = time.Now() } else if len(args) == 1 { tuple, err := args[0].AsList() if err != nil { return err } if len(tuple) != 9 { return errors.NewError("time tuple must have exactly 9 elements") } year, _ := tuple[0].AsInt() month, _ := tuple[1].AsInt() day, _ := tuple[2].AsInt() hour, _ := tuple[3].AsInt() minute, _ := tuple[4].AsInt() second, _ := tuple[5].AsInt() t = time.Date(int(year), time.Month(month), int(day), int(hour), int(minute), int(second), 0, time.Local) } else { if err := errors.MaxArgs(args, 1); err != nil { return err } } return &object.String{Value: t.Format("Mon Jan 2 15:04:05 2006")} }, HelpText: `asctime([tuple]) - Convert time tuple to string Converts a time tuple to a string in the format 'Mon Jan 2 15:04:05 2006'. If tuple is omitted, uses current time.`, }, "ctime": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { var t time.Time if len(args) == 0 { t = time.Now() } else if len(args) == 1 { timestamp, err := args[0].AsFloat() if err != nil { return errors.ParameterError("timestamp", err) } t = time.Unix(int64(timestamp), 0) } else { if err := errors.MaxArgs(args, 1); err != nil { return err } } return &object.String{Value: t.Format("Mon Jan 2 15:04:05 2006")} }, HelpText: `ctime([timestamp]) - Convert timestamp to string Converts a Unix timestamp to a string in the format 'Mon Jan 2 15:04:05 2006'. If timestamp is omitted, uses current time.`, }, }, nil, "Time-related functions library")
var URLLibLibrary = object.NewLibraryWithSubs( nil, nil, map[string]*object.Library{ "parse": URLParseLibrary, }, "URL handling modules", )
URLLibrary is the parent urllib module with parse as a sub-library
var URLParseLibrary = object.NewLibrary(map[string]*object.Builtin{ "quote": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.RangeArgs(args, 1, 2); err != nil { return err } str, err := args[0].AsString() if err != nil { return err } safe := "" if len(args) == 2 { safe, err = args[1].AsString() if err != nil { return err } } encoded := urlQuote(str, safe) return &object.String{Value: encoded} }, HelpText: `quote(string, safe='') - URL encode string Returns a URL-encoded version of the string. Characters in 'safe' are not encoded.`, }, "quote_plus": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.RangeArgs(args, 1, 2); err != nil { return err } str, err := args[0].AsString() if err != nil { return err } safe := "" if len(args) == 2 { safe, err = args[1].AsString() if err != nil { return err } } encoded := urlQuote(str, safe) encoded = strings.ReplaceAll(encoded, "%20", "+") return &object.String{Value: encoded} }, HelpText: `quote_plus(string, safe='') - URL encode string with + for spaces Like quote(), but also replaces spaces with plus signs.`, }, "unquote": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } str, err := args[0].AsString() if err != nil { return err } decoded, urlErr := url.PathUnescape(str) if urlErr != nil { return errors.NewError("unquote() invalid URL encoding") } return &object.String{Value: decoded} }, HelpText: `unquote(string) - URL decode string Returns a URL-decoded version of the string.`, }, "unquote_plus": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } str, err := args[0].AsString() if err != nil { return err } str = strings.ReplaceAll(str, "+", " ") decoded, urlErr := url.PathUnescape(str) if urlErr != nil { return errors.NewError("unquote_plus() invalid URL encoding") } return &object.String{Value: decoded} }, HelpText: `unquote_plus(string) - URL decode string with + as spaces Like unquote(), but also replaces plus signs with spaces.`, }, "urlparse": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } str, err := args[0].AsString() if err != nil { return err } u, urlErr := url.Parse(str) if urlErr != nil { return errors.NewError("urlparse() invalid URL") } netloc := u.Host if u.User != nil { if pwd, hasPwd := u.User.Password(); hasPwd { netloc = u.User.Username() + ":" + pwd + "@" + u.Host } else { netloc = u.User.Username() + "@" + u.Host } } return createParseResultInstance(u.Scheme, netloc, u.Path, "", u.RawQuery, u.Fragment) }, HelpText: `urlparse(urlstring) - Parse URL into components Returns a ParseResult object with URL components: scheme, netloc, path, params, query, fragment. Access components as attributes: result.scheme, result.netloc, etc. Use result.geturl() to reconstruct URL.`, }, "urlunparse": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } switch arg := args[0].(type) { case *object.Instance: if arg.Class == ParseResultClass { u := &url.URL{} if value, ok := arg.Fields["scheme"]; ok { if str, err := value.AsString(); err == nil { u.Scheme = str } } if value, ok := arg.Fields["netloc"]; ok { if str, err := value.AsString(); err == nil { u.Host = str } } if value, ok := arg.Fields["path"]; ok { if str, err := value.AsString(); err == nil { u.Path = str } } if value, ok := arg.Fields["query"]; ok { if str, err := value.AsString(); err == nil { u.RawQuery = str } } if value, ok := arg.Fields["fragment"]; ok { if str, err := value.AsString(); err == nil { u.Fragment = str } } return &object.String{Value: u.String()} } return errors.NewTypeError("DICT, LIST, TUPLE, or ParseResult", args[0].Type().String()) case *object.Dict: u := &url.URL{} if value, ok := arg.Pairs["scheme"]; ok { if str, err := value.Value.AsString(); err == nil { u.Scheme = str } } if value, ok := arg.Pairs["netloc"]; ok { if str, err := value.Value.AsString(); err == nil { u.Host = str } } if value, ok := arg.Pairs["path"]; ok { if str, err := value.Value.AsString(); err == nil { u.Path = str } } if value, ok := arg.Pairs["query"]; ok { if str, err := value.Value.AsString(); err == nil { u.RawQuery = str } } if value, ok := arg.Pairs["fragment"]; ok { if str, err := value.Value.AsString(); err == nil { u.Fragment = str } } return &object.String{Value: u.String()} case *object.List: if len(arg.Elements) != 6 { return errors.NewError("urlunparse() requires exactly 6 elements") } components := make([]string, 6) for i, elem := range arg.Elements { str, err := elem.AsString() if err != nil { return err } components[i] = str } u := &url.URL{ Scheme: components[0], Host: components[1], Path: components[2], RawQuery: components[4], Fragment: components[5], } return &object.String{Value: u.String()} case *object.Tuple: if len(arg.Elements) != 6 { return errors.NewError("urlunparse() requires exactly 6 elements") } components := make([]string, 6) for i, elem := range arg.Elements { str, err := elem.AsString() if err != nil { return err } components[i] = str } u := &url.URL{ Scheme: components[0], Host: components[1], Path: components[2], RawQuery: components[4], Fragment: components[5], } return &object.String{Value: u.String()} default: return errors.NewTypeError("DICT, LIST, TUPLE, or ParseResult", args[0].Type().String()) } }, HelpText: `urlunparse(components) - Construct URL from components Constructs a URL string from a 6-tuple or dict of URL components.`, }, "urljoin": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 2); err != nil { return err } base, err := args[0].AsString() if err != nil { return err } ref, err := args[1].AsString() if err != nil { return err } baseURL, urlErr := url.Parse(base) if urlErr != nil { return errors.NewError("urljoin() invalid base URL") } refURL, urlErr := url.Parse(ref) if urlErr != nil { return errors.NewError("urljoin() invalid reference URL") } joined := baseURL.ResolveReference(refURL) return &object.String{Value: joined.String()} }, HelpText: `urljoin(base, url) - Join base URL with reference Joins a base URL with a reference URL, resolving relative references.`, }, "urlsplit": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } str, err := args[0].AsString() if err != nil { return err } u, urlErr := url.Parse(str) if urlErr != nil { return errors.NewError("urlsplit() invalid URL") } netloc := u.Host if u.User != nil { if pwd, hasPwd := u.User.Password(); hasPwd { netloc = u.User.Username() + ":" + pwd + "@" + u.Host } else { netloc = u.User.Username() + "@" + u.Host } } elements := []object.Object{ &object.String{Value: u.Scheme}, &object.String{Value: netloc}, &object.String{Value: u.Path}, &object.String{Value: u.RawQuery}, &object.String{Value: u.Fragment}, } return &object.List{Elements: elements} }, HelpText: `urlsplit(urlstring) - Split URL into components Returns a 5-tuple: (scheme, netloc, path, query, fragment).`, }, "urlunsplit": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 1); err != nil { return err } elements, err := args[0].AsList() if err != nil { return errors.ParameterError("elements", err) } if len(elements) != 5 { return errors.NewError("urlunsplit() requires exactly 5 elements") } components := make([]string, 5) for i, elem := range elements { str, err := elem.AsString() if err != nil { return err } components[i] = str } u := &url.URL{ Scheme: components[0], Host: components[1], Path: components[2], RawQuery: components[3], Fragment: components[4], } return &object.String{Value: u.String()} }, HelpText: `urlunsplit(components) - Construct URL from component tuple Constructs a URL string from a 5-tuple of URL components.`, }, "parse_qs": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.RangeArgs(args, 1, 2); err != nil { return err } str, err := args[0].AsString() if err != nil { return err } values, urlErr := url.ParseQuery(str) if urlErr != nil { return errors.NewError("parse_qs() invalid query string") } pairs := make(map[string]object.DictPair) for key, vals := range values { elements := make([]object.Object, len(vals)) for i, val := range vals { elements[i] = &object.String{Value: val} } pairs[key] = object.DictPair{ Key: &object.String{Value: key}, Value: &object.List{Elements: elements}, } } return &object.Dict{Pairs: pairs} }, HelpText: `parse_qs(qs, keep_blank_values=False) - Parse query string Parses a URL query string and returns a dictionary where values are lists.`, }, "parse_qsl": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.RangeArgs(args, 1, 2); err != nil { return err } str, err := args[0].AsString() if err != nil { return err } values, urlErr := url.ParseQuery(str) if urlErr != nil { return errors.NewError("parse_qsl() invalid query string") } // Convert to list of (key, value) tuples var result []object.Object for key, vals := range values { for _, val := range vals { tuple := &object.Tuple{ Elements: []object.Object{ &object.String{Value: key}, &object.String{Value: val}, }, } result = append(result, tuple) } } return &object.List{Elements: result} }, HelpText: `parse_qsl(qs, keep_blank_values=False) - Parse query string as list Parses a URL query string and returns a list of (key, value) tuples.`, }, "urlencode": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.RangeArgs(args, 1, 2); err != nil { return err } values := make(url.Values) switch arg := args[0].(type) { case *object.Dict: for key, pair := range arg.Pairs { switch val := pair.Value.(type) { case *object.String: values[key] = []string{val.Value} case *object.List: strVals := make([]string, len(val.Elements)) for i, elem := range val.Elements { if str, err := elem.AsString(); err == nil { strVals[i] = str } } values[key] = strVals } } case *object.List: for _, elem := range arg.Elements { if tuple, ok := elem.(*object.Tuple); ok && len(tuple.Elements) == 2 { if key, err := tuple.Elements[0].AsString(); err == nil { if val, err := tuple.Elements[1].AsString(); err == nil { values.Add(key, val) } } } } default: return errors.NewTypeError("DICT or LIST", args[0].Type().String()) } return &object.String{Value: values.Encode()} }, HelpText: `urlencode(query, doseq=False) - Encode dictionary as query string Encodes a dictionary or list of tuples into a URL query string.`, }, }, nil, "URL parsing and manipulation (urllib.parse compatible)")
URLParseLibrary implements Python's urllib.parse module
var UUIDLibrary = object.NewLibrary(map[string]*object.Builtin{ "uuid1": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } id, err := uuid.NewUUID() if err != nil { return errors.NewError("failed to generate UUID v1: %s", err.Error()) } return &object.String{Value: id.String()} }, HelpText: `uuid1() - Generate a UUID version 1 (time-based) Returns a UUID based on current time and MAC address. Format: xxxxxxxx-xxxx-1xxx-yxxx-xxxxxxxxxxxx Example: import uuid id = uuid.uuid1() print(id) # e.g., "f47ac10b-58cc-1e4c-a26f-e3fc32165abc"`, }, "uuid4": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } return &object.String{Value: uuid.New().String()} }, HelpText: `uuid4() - Generate a UUID version 4 (random) Returns a randomly generated UUID. Format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx Example: import uuid id = uuid.uuid4() print(id) # e.g., "550e8400-e29b-41d4-a716-446655440000"`, }, "uuid7": { Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object { if err := errors.ExactArgs(args, 0); err != nil { return err } id, err := uuid.NewV7() if err != nil { return errors.NewError("failed to generate UUID v7: %s", err.Error()) } return &object.String{Value: id.String()} }, HelpText: `uuid7() - Generate a UUID version 7 (Unix timestamp-based, sortable) Returns a UUID based on Unix timestamp in milliseconds. UUIDs generated in sequence will sort in chronological order. Format: xxxxxxxx-xxxx-7xxx-yxxx-xxxxxxxxxxxx Example: import uuid id = uuid.uuid7() print(id) # e.g., "018f6b1c-4e5d-7abc-8def-0123456789ab"`, }, }, nil, "UUID generation library")
Functions ¶
func GetCompiledRegex ¶
GetCompiledRegex retrieves a compiled regex from cache or compiles and caches it
func GetTimeFromObject ¶
GetTimeFromObject extracts time.Time from a datetime/date instance
func PythonToGoDateFormat ¶
PythonToGoDateFormat converts Python datetime format codes to Go format
func RegisterAll ¶
RegisterAll registers all standard libraries
Types ¶
This section is empty.