1package tengo 2 3var builtinFuncs = []*BuiltinFunction{ 4 { 5 Name: "len", 6 Value: builtinLen, 7 }, 8 { 9 Name: "copy", 10 Value: builtinCopy, 11 }, 12 { 13 Name: "append", 14 Value: builtinAppend, 15 }, 16 { 17 Name: "delete", 18 Value: builtinDelete, 19 }, 20 { 21 Name: "splice", 22 Value: builtinSplice, 23 }, 24 { 25 Name: "string", 26 Value: builtinString, 27 }, 28 { 29 Name: "int", 30 Value: builtinInt, 31 }, 32 { 33 Name: "bool", 34 Value: builtinBool, 35 }, 36 { 37 Name: "float", 38 Value: builtinFloat, 39 }, 40 { 41 Name: "char", 42 Value: builtinChar, 43 }, 44 { 45 Name: "bytes", 46 Value: builtinBytes, 47 }, 48 { 49 Name: "time", 50 Value: builtinTime, 51 }, 52 { 53 Name: "is_int", 54 Value: builtinIsInt, 55 }, 56 { 57 Name: "is_float", 58 Value: builtinIsFloat, 59 }, 60 { 61 Name: "is_string", 62 Value: builtinIsString, 63 }, 64 { 65 Name: "is_bool", 66 Value: builtinIsBool, 67 }, 68 { 69 Name: "is_char", 70 Value: builtinIsChar, 71 }, 72 { 73 Name: "is_bytes", 74 Value: builtinIsBytes, 75 }, 76 { 77 Name: "is_array", 78 Value: builtinIsArray, 79 }, 80 { 81 Name: "is_immutable_array", 82 Value: builtinIsImmutableArray, 83 }, 84 { 85 Name: "is_map", 86 Value: builtinIsMap, 87 }, 88 { 89 Name: "is_immutable_map", 90 Value: builtinIsImmutableMap, 91 }, 92 { 93 Name: "is_iterable", 94 Value: builtinIsIterable, 95 }, 96 { 97 Name: "is_time", 98 Value: builtinIsTime, 99 }, 100 { 101 Name: "is_error", 102 Value: builtinIsError, 103 }, 104 { 105 Name: "is_undefined", 106 Value: builtinIsUndefined, 107 }, 108 { 109 Name: "is_function", 110 Value: builtinIsFunction, 111 }, 112 { 113 Name: "is_callable", 114 Value: builtinIsCallable, 115 }, 116 { 117 Name: "type_name", 118 Value: builtinTypeName, 119 }, 120 { 121 Name: "format", 122 Value: builtinFormat, 123 }, 124 { 125 Name: "range", 126 Value: builtinRange, 127 }, 128} 129 130// GetAllBuiltinFunctions returns all builtin function objects. 131func GetAllBuiltinFunctions() []*BuiltinFunction { 132 return append([]*BuiltinFunction{}, builtinFuncs...) 133} 134 135func builtinTypeName(args ...Object) (Object, error) { 136 if len(args) != 1 { 137 return nil, ErrWrongNumArguments 138 } 139 return &String{Value: args[0].TypeName()}, nil 140} 141 142func builtinIsString(args ...Object) (Object, error) { 143 if len(args) != 1 { 144 return nil, ErrWrongNumArguments 145 } 146 if _, ok := args[0].(*String); ok { 147 return TrueValue, nil 148 } 149 return FalseValue, nil 150} 151 152func builtinIsInt(args ...Object) (Object, error) { 153 if len(args) != 1 { 154 return nil, ErrWrongNumArguments 155 } 156 if _, ok := args[0].(*Int); ok { 157 return TrueValue, nil 158 } 159 return FalseValue, nil 160} 161 162func builtinIsFloat(args ...Object) (Object, error) { 163 if len(args) != 1 { 164 return nil, ErrWrongNumArguments 165 } 166 if _, ok := args[0].(*Float); ok { 167 return TrueValue, nil 168 } 169 return FalseValue, nil 170} 171 172func builtinIsBool(args ...Object) (Object, error) { 173 if len(args) != 1 { 174 return nil, ErrWrongNumArguments 175 } 176 if _, ok := args[0].(*Bool); ok { 177 return TrueValue, nil 178 } 179 return FalseValue, nil 180} 181 182func builtinIsChar(args ...Object) (Object, error) { 183 if len(args) != 1 { 184 return nil, ErrWrongNumArguments 185 } 186 if _, ok := args[0].(*Char); ok { 187 return TrueValue, nil 188 } 189 return FalseValue, nil 190} 191 192func builtinIsBytes(args ...Object) (Object, error) { 193 if len(args) != 1 { 194 return nil, ErrWrongNumArguments 195 } 196 if _, ok := args[0].(*Bytes); ok { 197 return TrueValue, nil 198 } 199 return FalseValue, nil 200} 201 202func builtinIsArray(args ...Object) (Object, error) { 203 if len(args) != 1 { 204 return nil, ErrWrongNumArguments 205 } 206 if _, ok := args[0].(*Array); ok { 207 return TrueValue, nil 208 } 209 return FalseValue, nil 210} 211 212func builtinIsImmutableArray(args ...Object) (Object, error) { 213 if len(args) != 1 { 214 return nil, ErrWrongNumArguments 215 } 216 if _, ok := args[0].(*ImmutableArray); ok { 217 return TrueValue, nil 218 } 219 return FalseValue, nil 220} 221 222func builtinIsMap(args ...Object) (Object, error) { 223 if len(args) != 1 { 224 return nil, ErrWrongNumArguments 225 } 226 if _, ok := args[0].(*Map); ok { 227 return TrueValue, nil 228 } 229 return FalseValue, nil 230} 231 232func builtinIsImmutableMap(args ...Object) (Object, error) { 233 if len(args) != 1 { 234 return nil, ErrWrongNumArguments 235 } 236 if _, ok := args[0].(*ImmutableMap); ok { 237 return TrueValue, nil 238 } 239 return FalseValue, nil 240} 241 242func builtinIsTime(args ...Object) (Object, error) { 243 if len(args) != 1 { 244 return nil, ErrWrongNumArguments 245 } 246 if _, ok := args[0].(*Time); ok { 247 return TrueValue, nil 248 } 249 return FalseValue, nil 250} 251 252func builtinIsError(args ...Object) (Object, error) { 253 if len(args) != 1 { 254 return nil, ErrWrongNumArguments 255 } 256 if _, ok := args[0].(*Error); ok { 257 return TrueValue, nil 258 } 259 return FalseValue, nil 260} 261 262func builtinIsUndefined(args ...Object) (Object, error) { 263 if len(args) != 1 { 264 return nil, ErrWrongNumArguments 265 } 266 if args[0] == UndefinedValue { 267 return TrueValue, nil 268 } 269 return FalseValue, nil 270} 271 272func builtinIsFunction(args ...Object) (Object, error) { 273 if len(args) != 1 { 274 return nil, ErrWrongNumArguments 275 } 276 switch args[0].(type) { 277 case *CompiledFunction: 278 return TrueValue, nil 279 } 280 return FalseValue, nil 281} 282 283func builtinIsCallable(args ...Object) (Object, error) { 284 if len(args) != 1 { 285 return nil, ErrWrongNumArguments 286 } 287 if args[0].CanCall() { 288 return TrueValue, nil 289 } 290 return FalseValue, nil 291} 292 293func builtinIsIterable(args ...Object) (Object, error) { 294 if len(args) != 1 { 295 return nil, ErrWrongNumArguments 296 } 297 if args[0].CanIterate() { 298 return TrueValue, nil 299 } 300 return FalseValue, nil 301} 302 303// len(obj object) => int 304func builtinLen(args ...Object) (Object, error) { 305 if len(args) != 1 { 306 return nil, ErrWrongNumArguments 307 } 308 switch arg := args[0].(type) { 309 case *Array: 310 return &Int{Value: int64(len(arg.Value))}, nil 311 case *ImmutableArray: 312 return &Int{Value: int64(len(arg.Value))}, nil 313 case *String: 314 return &Int{Value: int64(len(arg.Value))}, nil 315 case *Bytes: 316 return &Int{Value: int64(len(arg.Value))}, nil 317 case *Map: 318 return &Int{Value: int64(len(arg.Value))}, nil 319 case *ImmutableMap: 320 return &Int{Value: int64(len(arg.Value))}, nil 321 default: 322 return nil, ErrInvalidArgumentType{ 323 Name: "first", 324 Expected: "array/string/bytes/map", 325 Found: arg.TypeName(), 326 } 327 } 328} 329 330//range(start, stop[, step]) 331func builtinRange(args ...Object) (Object, error) { 332 numArgs := len(args) 333 if numArgs < 2 || numArgs > 3 { 334 return nil, ErrWrongNumArguments 335 } 336 var start, stop, step *Int 337 338 for i, arg := range args { 339 v, ok := args[i].(*Int) 340 if !ok { 341 var name string 342 switch i { 343 case 0: 344 name = "start" 345 case 1: 346 name = "stop" 347 case 2: 348 name = "step" 349 } 350 351 return nil, ErrInvalidArgumentType{ 352 Name: name, 353 Expected: "int", 354 Found: arg.TypeName(), 355 } 356 } 357 if i == 2 && v.Value <= 0 { 358 return nil, ErrInvalidRangeStep 359 } 360 switch i { 361 case 0: 362 start = v 363 case 1: 364 stop = v 365 case 2: 366 step = v 367 } 368 } 369 370 if step == nil { 371 step = &Int{Value: int64(1)} 372 } 373 374 return buildRange(start.Value, stop.Value, step.Value), nil 375} 376 377func buildRange(start, stop, step int64) *Array { 378 array := &Array{} 379 if start <= stop { 380 for i := start; i < stop; i += step { 381 array.Value = append(array.Value, &Int{ 382 Value: i, 383 }) 384 } 385 } else { 386 for i := start; i > stop; i -= step { 387 array.Value = append(array.Value, &Int{ 388 Value: i, 389 }) 390 } 391 } 392 return array 393} 394 395func builtinFormat(args ...Object) (Object, error) { 396 numArgs := len(args) 397 if numArgs == 0 { 398 return nil, ErrWrongNumArguments 399 } 400 format, ok := args[0].(*String) 401 if !ok { 402 return nil, ErrInvalidArgumentType{ 403 Name: "format", 404 Expected: "string", 405 Found: args[0].TypeName(), 406 } 407 } 408 if numArgs == 1 { 409 // okay to return 'format' directly as String is immutable 410 return format, nil 411 } 412 s, err := Format(format.Value, args[1:]...) 413 if err != nil { 414 return nil, err 415 } 416 return &String{Value: s}, nil 417} 418 419func builtinCopy(args ...Object) (Object, error) { 420 if len(args) != 1 { 421 return nil, ErrWrongNumArguments 422 } 423 return args[0].Copy(), nil 424} 425 426func builtinString(args ...Object) (Object, error) { 427 argsLen := len(args) 428 if !(argsLen == 1 || argsLen == 2) { 429 return nil, ErrWrongNumArguments 430 } 431 if _, ok := args[0].(*String); ok { 432 return args[0], nil 433 } 434 v, ok := ToString(args[0]) 435 if ok { 436 if len(v) > MaxStringLen { 437 return nil, ErrStringLimit 438 } 439 return &String{Value: v}, nil 440 } 441 if argsLen == 2 { 442 return args[1], nil 443 } 444 return UndefinedValue, nil 445} 446 447func builtinInt(args ...Object) (Object, error) { 448 argsLen := len(args) 449 if !(argsLen == 1 || argsLen == 2) { 450 return nil, ErrWrongNumArguments 451 } 452 if _, ok := args[0].(*Int); ok { 453 return args[0], nil 454 } 455 v, ok := ToInt64(args[0]) 456 if ok { 457 return &Int{Value: v}, nil 458 } 459 if argsLen == 2 { 460 return args[1], nil 461 } 462 return UndefinedValue, nil 463} 464 465func builtinFloat(args ...Object) (Object, error) { 466 argsLen := len(args) 467 if !(argsLen == 1 || argsLen == 2) { 468 return nil, ErrWrongNumArguments 469 } 470 if _, ok := args[0].(*Float); ok { 471 return args[0], nil 472 } 473 v, ok := ToFloat64(args[0]) 474 if ok { 475 return &Float{Value: v}, nil 476 } 477 if argsLen == 2 { 478 return args[1], nil 479 } 480 return UndefinedValue, nil 481} 482 483func builtinBool(args ...Object) (Object, error) { 484 if len(args) != 1 { 485 return nil, ErrWrongNumArguments 486 } 487 if _, ok := args[0].(*Bool); ok { 488 return args[0], nil 489 } 490 v, ok := ToBool(args[0]) 491 if ok { 492 if v { 493 return TrueValue, nil 494 } 495 return FalseValue, nil 496 } 497 return UndefinedValue, nil 498} 499 500func builtinChar(args ...Object) (Object, error) { 501 argsLen := len(args) 502 if !(argsLen == 1 || argsLen == 2) { 503 return nil, ErrWrongNumArguments 504 } 505 if _, ok := args[0].(*Char); ok { 506 return args[0], nil 507 } 508 v, ok := ToRune(args[0]) 509 if ok { 510 return &Char{Value: v}, nil 511 } 512 if argsLen == 2 { 513 return args[1], nil 514 } 515 return UndefinedValue, nil 516} 517 518func builtinBytes(args ...Object) (Object, error) { 519 argsLen := len(args) 520 if !(argsLen == 1 || argsLen == 2) { 521 return nil, ErrWrongNumArguments 522 } 523 524 // bytes(N) => create a new bytes with given size N 525 if n, ok := args[0].(*Int); ok { 526 if n.Value > int64(MaxBytesLen) { 527 return nil, ErrBytesLimit 528 } 529 return &Bytes{Value: make([]byte, int(n.Value))}, nil 530 } 531 v, ok := ToByteSlice(args[0]) 532 if ok { 533 if len(v) > MaxBytesLen { 534 return nil, ErrBytesLimit 535 } 536 return &Bytes{Value: v}, nil 537 } 538 if argsLen == 2 { 539 return args[1], nil 540 } 541 return UndefinedValue, nil 542} 543 544func builtinTime(args ...Object) (Object, error) { 545 argsLen := len(args) 546 if !(argsLen == 1 || argsLen == 2) { 547 return nil, ErrWrongNumArguments 548 } 549 if _, ok := args[0].(*Time); ok { 550 return args[0], nil 551 } 552 v, ok := ToTime(args[0]) 553 if ok { 554 return &Time{Value: v}, nil 555 } 556 if argsLen == 2 { 557 return args[1], nil 558 } 559 return UndefinedValue, nil 560} 561 562// append(arr, items...) 563func builtinAppend(args ...Object) (Object, error) { 564 if len(args) < 2 { 565 return nil, ErrWrongNumArguments 566 } 567 switch arg := args[0].(type) { 568 case *Array: 569 return &Array{Value: append(arg.Value, args[1:]...)}, nil 570 case *ImmutableArray: 571 return &Array{Value: append(arg.Value, args[1:]...)}, nil 572 default: 573 return nil, ErrInvalidArgumentType{ 574 Name: "first", 575 Expected: "array", 576 Found: arg.TypeName(), 577 } 578 } 579} 580 581// builtinDelete deletes Map keys 582// usage: delete(map, "key") 583// key must be a string 584func builtinDelete(args ...Object) (Object, error) { 585 argsLen := len(args) 586 if argsLen != 2 { 587 return nil, ErrWrongNumArguments 588 } 589 switch arg := args[0].(type) { 590 case *Map: 591 if key, ok := args[1].(*String); ok { 592 delete(arg.Value, key.Value) 593 return UndefinedValue, nil 594 } 595 return nil, ErrInvalidArgumentType{ 596 Name: "second", 597 Expected: "string", 598 Found: args[1].TypeName(), 599 } 600 default: 601 return nil, ErrInvalidArgumentType{ 602 Name: "first", 603 Expected: "map", 604 Found: arg.TypeName(), 605 } 606 } 607} 608 609// builtinSplice deletes and changes given Array, returns deleted items. 610// usage: 611// deleted_items := splice(array[,start[,delete_count[,item1[,item2[,...]]]]) 612func builtinSplice(args ...Object) (Object, error) { 613 argsLen := len(args) 614 if argsLen == 0 { 615 return nil, ErrWrongNumArguments 616 } 617 618 array, ok := args[0].(*Array) 619 if !ok { 620 return nil, ErrInvalidArgumentType{ 621 Name: "first", 622 Expected: "array", 623 Found: args[0].TypeName(), 624 } 625 } 626 arrayLen := len(array.Value) 627 628 var startIdx int 629 if argsLen > 1 { 630 arg1, ok := args[1].(*Int) 631 if !ok { 632 return nil, ErrInvalidArgumentType{ 633 Name: "second", 634 Expected: "int", 635 Found: args[1].TypeName(), 636 } 637 } 638 startIdx = int(arg1.Value) 639 if startIdx < 0 || startIdx > arrayLen { 640 return nil, ErrIndexOutOfBounds 641 } 642 } 643 644 delCount := len(array.Value) 645 if argsLen > 2 { 646 arg2, ok := args[2].(*Int) 647 if !ok { 648 return nil, ErrInvalidArgumentType{ 649 Name: "third", 650 Expected: "int", 651 Found: args[2].TypeName(), 652 } 653 } 654 delCount = int(arg2.Value) 655 if delCount < 0 { 656 return nil, ErrIndexOutOfBounds 657 } 658 } 659 // if count of to be deleted items is bigger than expected, truncate it 660 if startIdx+delCount > arrayLen { 661 delCount = arrayLen - startIdx 662 } 663 // delete items 664 endIdx := startIdx + delCount 665 deleted := append([]Object{}, array.Value[startIdx:endIdx]...) 666 667 head := array.Value[:startIdx] 668 var items []Object 669 if argsLen > 3 { 670 items = make([]Object, 0, argsLen-3) 671 for i := 3; i < argsLen; i++ { 672 items = append(items, args[i]) 673 } 674 } 675 items = append(items, array.Value[endIdx:]...) 676 array.Value = append(head, items...) 677 678 // return deleted items 679 return &Array{Value: deleted}, nil 680} 681