github.com/unidoc/unidoc@v2.2.0+incompatible/pdf/ps/object.go (about) 1 /* 2 * This file is subject to the terms and conditions defined in 3 * file 'LICENSE.md', which is part of this source code package. 4 */ 5 6 // Package ps implements a small subset of the postscript language used in PDF for type 4 functions. 7 // Only objects are integers, real numbers, and boolean values only. 8 // 9 package ps 10 11 import ( 12 "errors" 13 "fmt" 14 "math" 15 ) 16 17 type PSObject interface { 18 Duplicate() PSObject 19 DebugString() string // Only for debugging. 20 String() string 21 } 22 23 // Integer. 24 type PSInteger struct { 25 Val int 26 } 27 28 func (this *PSInteger) Duplicate() PSObject { 29 obj := PSInteger{} 30 obj.Val = this.Val 31 return &obj 32 } 33 34 func (this *PSInteger) DebugString() string { 35 return fmt.Sprintf("int:%d", this.Val) 36 } 37 38 func (this *PSInteger) String() string { 39 return fmt.Sprintf("%d", this.Val) 40 } 41 42 // Real number. 43 type PSReal struct { 44 Val float64 45 } 46 47 func (this *PSReal) DebugString() string { 48 return fmt.Sprintf("real:%.5f", this.Val) 49 } 50 51 func (this *PSReal) String() string { 52 return fmt.Sprintf("%.5f", this.Val) 53 } 54 55 func (this *PSReal) Duplicate() PSObject { 56 obj := PSReal{} 57 obj.Val = this.Val 58 return &obj 59 } 60 61 // Bool. 62 type PSBoolean struct { 63 Val bool 64 } 65 66 func (this *PSBoolean) DebugString() string { 67 return fmt.Sprintf("bool:%v", this.Val) 68 } 69 70 func (this *PSBoolean) String() string { 71 return fmt.Sprintf("%v", this.Val) 72 } 73 74 func (this *PSBoolean) Duplicate() PSObject { 75 obj := PSBoolean{} 76 obj.Val = this.Val 77 return &obj 78 } 79 80 // A Postscript program is a series of PS objects (arguments, commands, programs etc). 81 type PSProgram []PSObject 82 83 func NewPSProgram() *PSProgram { 84 return &PSProgram{} 85 } 86 87 func (this *PSProgram) Append(obj PSObject) { 88 *this = append(*this, obj) 89 } 90 91 func (this *PSProgram) DebugString() string { 92 s := "{ " 93 for _, obj := range *this { 94 s += obj.DebugString() 95 s += " " 96 } 97 s += "}" 98 99 return s 100 } 101 102 func (this *PSProgram) String() string { 103 s := "{ " 104 for _, obj := range *this { 105 s += obj.String() 106 s += " " 107 } 108 s += "}" 109 110 return s 111 } 112 113 func (this *PSProgram) Duplicate() PSObject { 114 prog := &PSProgram{} 115 for _, obj := range *this { 116 prog.Append(obj.Duplicate()) 117 } 118 return prog 119 } 120 121 func (this *PSProgram) Exec(stack *PSStack) error { 122 for _, obj := range *this { 123 var err error 124 if number, isInt := obj.(*PSInteger); isInt { 125 err = stack.Push(number) 126 } else if number, isReal := obj.(*PSReal); isReal { 127 err = stack.Push(number) 128 } else if val, isBool := obj.(*PSBoolean); isBool { 129 err = stack.Push(val) 130 } else if function, isFunc := obj.(*PSProgram); isFunc { 131 err = stack.Push(function) 132 } else if op, isOp := obj.(*PSOperand); isOp { 133 err = op.Exec(stack) 134 } else { 135 return ErrTypeCheck 136 } 137 if err != nil { 138 return err 139 } 140 } 141 return nil 142 } 143 144 // Operand. 145 type PSOperand string 146 147 func (this *PSOperand) DebugString() string { 148 return fmt.Sprintf("op:'%s'", *this) 149 } 150 151 func (this *PSOperand) String() string { 152 return fmt.Sprintf("%s", *this) 153 } 154 155 func (this *PSOperand) Duplicate() PSObject { 156 s := *this 157 return &s 158 } 159 160 func (this *PSOperand) Exec(stack *PSStack) error { 161 err := errors.New("Unsupported operand") 162 switch *this { 163 case "abs": 164 err = this.Abs(stack) 165 case "add": 166 err = this.Add(stack) 167 case "and": 168 err = this.And(stack) 169 case "atan": 170 err = this.Atan(stack) 171 172 case "bitshift": 173 err = this.Bitshift(stack) 174 175 case "ceiling": 176 err = this.Ceiling(stack) 177 case "copy": 178 err = this.Copy(stack) 179 case "cos": 180 err = this.Cos(stack) 181 case "cvi": 182 err = this.Cvi(stack) 183 case "cvr": 184 err = this.Cvr(stack) 185 186 case "div": 187 err = this.Div(stack) 188 case "dup": 189 err = this.Dup(stack) 190 191 case "eq": 192 err = this.Eq(stack) 193 case "exch": 194 err = this.Exch(stack) 195 case "exp": 196 err = this.Exp(stack) 197 198 case "floor": 199 err = this.Floor(stack) 200 201 case "ge": 202 err = this.Ge(stack) 203 case "gt": 204 err = this.Gt(stack) 205 206 case "idiv": 207 err = this.IDiv(stack) 208 case "if": 209 err = this.If(stack) 210 case "ifelse": 211 err = this.IfElse(stack) 212 case "index": 213 err = this.Index(stack) 214 215 case "le": 216 err = this.Le(stack) 217 case "log": 218 err = this.Log(stack) 219 case "ln": 220 err = this.Ln(stack) 221 case "lt": 222 err = this.Lt(stack) 223 224 case "mod": 225 err = this.Mod(stack) 226 case "mul": 227 err = this.Mul(stack) 228 229 case "ne": 230 err = this.Ne(stack) 231 case "neg": 232 err = this.Neg(stack) 233 case "not": 234 err = this.Not(stack) 235 236 case "or": 237 err = this.Or(stack) 238 239 case "pop": 240 err = this.Pop(stack) 241 242 case "round": 243 err = this.Round(stack) 244 case "roll": 245 err = this.Roll(stack) 246 247 case "sin": 248 err = this.Sin(stack) 249 case "sqrt": 250 err = this.Sqrt(stack) 251 case "sub": 252 err = this.Sub(stack) 253 254 case "truncate": 255 err = this.Truncate(stack) 256 257 case "xor": 258 err = this.Xor(stack) 259 } 260 261 return err 262 } 263 264 ////// 265 // Operation implementations 266 267 // Absolute value. 268 func (this *PSOperand) Abs(stack *PSStack) error { 269 obj, err := stack.Pop() 270 if err != nil { 271 return err 272 } 273 274 if num, is := obj.(*PSReal); is { 275 val := num.Val 276 if val < 0 { 277 err = stack.Push(MakeReal(-val)) 278 } else { 279 err = stack.Push(MakeReal(val)) 280 } 281 } else if num, is := obj.(*PSInteger); is { 282 val := num.Val 283 if val < 0 { 284 err = stack.Push(MakeInteger(-val)) 285 } else { 286 err = stack.Push(MakeInteger(val)) 287 } 288 } else { 289 return ErrTypeCheck 290 } 291 292 return err 293 } 294 295 // 5 27 add -> 32 296 func (this *PSOperand) Add(stack *PSStack) error { 297 obj1, err := stack.Pop() 298 if err != nil { 299 return err 300 } 301 302 obj2, err := stack.Pop() 303 if err != nil { 304 return err 305 } 306 307 real1, isReal1 := obj1.(*PSReal) 308 int1, isInt1 := obj1.(*PSInteger) 309 if !isReal1 && !isInt1 { 310 return ErrTypeCheck 311 } 312 313 real2, isReal2 := obj2.(*PSReal) 314 int2, isInt2 := obj2.(*PSInteger) 315 if !isReal2 && !isInt2 { 316 return ErrTypeCheck 317 } 318 319 // If both numbers integers -> integer output. 320 if isInt1 && isInt2 { 321 result := int1.Val + int2.Val 322 err := stack.Push(MakeInteger(result)) 323 return err 324 } 325 326 // Otherwise -> real output. 327 var result float64 = 0 328 if isReal1 { 329 result = real1.Val 330 } else { 331 result = float64(int1.Val) 332 } 333 334 if isReal2 { 335 result += real2.Val 336 } else { 337 result += float64(int2.Val) 338 } 339 340 err = stack.Push(MakeReal(result)) 341 return err 342 } 343 344 // And operation. 345 // if bool: returns the logical "and" of the inputs 346 // bool1 bool2 and -> bool3 347 // if int: returns the bitwise "and" of the inputs 348 // int1 int2 and -> int3 349 func (this *PSOperand) And(stack *PSStack) error { 350 obj1, err := stack.Pop() 351 if err != nil { 352 return err 353 } 354 355 obj2, err := stack.Pop() 356 if err != nil { 357 return err 358 } 359 360 // Boolean inputs. 361 if bool1, is := obj1.(*PSBoolean); is { 362 bool2, ok := obj2.(*PSBoolean) 363 if !ok { 364 return ErrTypeCheck 365 } 366 err = stack.Push(MakeBool(bool1.Val && bool2.Val)) // logical and 367 return err 368 } 369 370 // Integer inputs 371 if int1, is := obj1.(*PSInteger); is { 372 int2, ok := obj2.(*PSInteger) 373 if !ok { 374 return ErrTypeCheck 375 } 376 err = stack.Push(MakeInteger(int1.Val & int2.Val)) // bitwise and 377 return err 378 } 379 380 return ErrTypeCheck 381 } 382 383 // den num atan -> atan(num/den) in degrees. 384 // result is a real value. 385 func (this *PSOperand) Atan(stack *PSStack) error { 386 // Denominator 387 den, err := stack.PopNumberAsFloat64() 388 if err != nil { 389 return err 390 } 391 392 // Numerator 393 num, err := stack.PopNumberAsFloat64() 394 if err != nil { 395 return err 396 } 397 398 // special cases. 399 // atan(inf) -> 90 400 // atan(-inf) -> 270 401 if den == 0 { 402 var err error 403 if num < 0 { 404 err = stack.Push(MakeReal(270)) 405 } else { 406 err = stack.Push(MakeReal(90)) 407 } 408 return err 409 } 410 411 ratio := num / den 412 angleDeg := math.Atan(ratio) * 180 / math.Pi 413 414 err = stack.Push(MakeReal(angleDeg)) 415 return err 416 } 417 418 // bitshift 419 // int1 shift bitshift -> int2 420 func (this *PSOperand) Bitshift(stack *PSStack) error { 421 shift, err := stack.PopInteger() 422 if err != nil { 423 return err 424 } 425 426 int1, err := stack.PopInteger() 427 if err != nil { 428 return err 429 } 430 431 var result int 432 433 if shift >= 0 { 434 result = int1 << uint(shift) 435 } else { 436 result = int1 >> uint(-shift) 437 } 438 439 err = stack.Push(MakeInteger(result)) 440 return err 441 } 442 443 // Ceiling of number. 444 // num1 ceiling -> num2 445 // The type of the result is the same as of the operand. 446 func (this *PSOperand) Ceiling(stack *PSStack) error { 447 obj, err := stack.Pop() 448 if err != nil { 449 return err 450 } 451 452 if num, is := obj.(*PSReal); is { 453 err = stack.Push(MakeReal(math.Ceil(num.Val))) 454 } else if num, is := obj.(*PSInteger); is { 455 err = stack.Push(MakeInteger(num.Val)) 456 } else { 457 err = ErrTypeCheck 458 } 459 460 return err 461 } 462 463 // Copy 464 // any1 ... anyn n copy -> any1 ... anyn any1 ... anyn 465 func (this *PSOperand) Copy(stack *PSStack) error { 466 n, err := stack.PopInteger() 467 if err != nil { 468 return err 469 } 470 471 if n < 0 { 472 return ErrRangeCheck 473 } 474 475 if n > len(*stack) { 476 return ErrRangeCheck 477 } 478 479 *stack = append(*stack, (*stack)[len(*stack)-n:]...) 480 return nil 481 } 482 483 // Cosine 484 // angle cos -> real 485 // Angle is in degrees 486 func (this *PSOperand) Cos(stack *PSStack) error { 487 angle, err := stack.PopNumberAsFloat64() 488 if err != nil { 489 return err 490 } 491 492 result := math.Cos(angle * math.Pi / 180.0) 493 err = stack.Push(MakeReal(result)) 494 return err 495 } 496 497 // Convert to integer 498 func (this *PSOperand) Cvi(stack *PSStack) error { 499 obj, err := stack.Pop() 500 if err != nil { 501 return err 502 } 503 504 if num, is := obj.(*PSReal); is { 505 val := int(num.Val) 506 err = stack.Push(MakeInteger(val)) 507 } else if num, is := obj.(*PSInteger); is { 508 val := num.Val 509 err = stack.Push(MakeInteger(val)) 510 } else { 511 return ErrTypeCheck 512 } 513 514 return err 515 } 516 517 // Convert number tor real 518 func (this *PSOperand) Cvr(stack *PSStack) error { 519 obj, err := stack.Pop() 520 if err != nil { 521 return err 522 } 523 524 if num, is := obj.(*PSReal); is { 525 err = stack.Push(MakeReal(num.Val)) 526 } else if num, is := obj.(*PSInteger); is { 527 err = stack.Push(MakeReal(float64(num.Val))) 528 } else { 529 return ErrTypeCheck 530 } 531 532 return err 533 } 534 535 func (this *PSOperand) Div(stack *PSStack) error { 536 obj1, err := stack.Pop() 537 if err != nil { 538 return err 539 } 540 541 obj2, err := stack.Pop() 542 if err != nil { 543 return err 544 } 545 546 real1, isReal1 := obj1.(*PSReal) 547 int1, isInt1 := obj1.(*PSInteger) 548 if !isReal1 && !isInt1 { 549 return ErrTypeCheck 550 } 551 // Cannot be 0. 552 if isReal1 && real1.Val == 0 { 553 return ErrUndefinedResult 554 } 555 if isInt1 && int1.Val == 0 { 556 return ErrUndefinedResult 557 } 558 559 real2, isReal2 := obj2.(*PSReal) 560 int2, isInt2 := obj2.(*PSInteger) 561 if !isReal2 && !isInt2 { 562 return ErrTypeCheck 563 } 564 565 // Float output. 566 var result float64 = 0 567 if isReal2 { 568 result = real2.Val 569 } else { 570 result = float64(int2.Val) 571 } 572 573 if isReal1 { 574 result /= real1.Val 575 } else { 576 result /= float64(int1.Val) 577 } 578 579 err = stack.Push(MakeReal(result)) 580 return err 581 } 582 583 // Duplicates the top object on the stack (dup) 584 func (this *PSOperand) Dup(stack *PSStack) error { 585 obj, err := stack.Pop() 586 if err != nil { 587 return err 588 } 589 590 // Push it back. 591 err = stack.Push(obj) 592 if err != nil { 593 return err 594 } 595 // Push the duplicate. 596 err = stack.Push(obj.Duplicate()) 597 return err 598 } 599 600 // Check for equality. 601 // any1 any2 eq bool 602 func (this *PSOperand) Eq(stack *PSStack) error { 603 obj1, err := stack.Pop() 604 if err != nil { 605 return err 606 } 607 608 obj2, err := stack.Pop() 609 if err != nil { 610 return err 611 } 612 613 // bool, real, int 614 // if bool, both must be bool 615 bool1, isBool1 := obj1.(*PSBoolean) 616 bool2, isBool2 := obj2.(*PSBoolean) 617 if isBool1 || isBool2 { 618 var err error 619 if isBool1 && isBool2 { 620 err = stack.Push(MakeBool(bool1.Val == bool2.Val)) 621 } else { 622 // Type mismatch -> false 623 err = stack.Push(MakeBool(false)) 624 } 625 return err 626 } 627 628 var val1 float64 629 var val2 float64 630 631 if number, is := obj1.(*PSInteger); is { 632 val1 = float64(number.Val) 633 } else if number, is := obj1.(*PSReal); is { 634 val1 = number.Val 635 } else { 636 return ErrTypeCheck 637 } 638 639 if number, is := obj2.(*PSInteger); is { 640 val2 = float64(number.Val) 641 } else if number, is := obj2.(*PSReal); is { 642 val2 = number.Val 643 } else { 644 return ErrTypeCheck 645 } 646 647 if math.Abs(val2-val1) < TOLERANCE { 648 err = stack.Push(MakeBool(true)) 649 } else { 650 err = stack.Push(MakeBool(false)) 651 } 652 653 return err 654 } 655 656 // Exchange the top two elements of the stack (exch) 657 func (this *PSOperand) Exch(stack *PSStack) error { 658 top, err := stack.Pop() 659 if err != nil { 660 return err 661 } 662 663 next, err := stack.Pop() 664 if err != nil { 665 return err 666 } 667 668 err = stack.Push(top) 669 if err != nil { 670 return err 671 } 672 err = stack.Push(next) 673 674 return err 675 } 676 677 // base exponent exp -> base^exp 678 // Raises base to exponent power. 679 // The result is a real number. 680 func (this *PSOperand) Exp(stack *PSStack) error { 681 exponent, err := stack.PopNumberAsFloat64() 682 if err != nil { 683 return err 684 } 685 686 base, err := stack.PopNumberAsFloat64() 687 if err != nil { 688 return err 689 } 690 691 if math.Abs(exponent) < 1 && base < 0 { 692 return ErrUndefinedResult 693 } 694 695 result := math.Pow(base, exponent) 696 err = stack.Push(MakeReal(result)) 697 698 return err 699 } 700 701 // Floor of number. 702 func (this *PSOperand) Floor(stack *PSStack) error { 703 obj, err := stack.Pop() 704 if err != nil { 705 return err 706 } 707 708 if num, is := obj.(*PSReal); is { 709 err = stack.Push(MakeReal(math.Floor(num.Val))) 710 } else if num, is := obj.(*PSInteger); is { 711 err = stack.Push(MakeInteger(num.Val)) 712 } else { 713 return ErrTypeCheck 714 } 715 716 return err 717 } 718 719 // Greater than or equal 720 // num1 num2 ge -> bool; num1 >= num2 721 func (this *PSOperand) Ge(stack *PSStack) error { 722 num2, err := stack.PopNumberAsFloat64() 723 if err != nil { 724 return err 725 } 726 727 num1, err := stack.PopNumberAsFloat64() 728 if err != nil { 729 return err 730 } 731 732 // Check equlity. 733 if math.Abs(num1-num2) < TOLERANCE { 734 err := stack.Push(MakeBool(true)) 735 return err 736 } else if num1 > num2 { 737 err := stack.Push(MakeBool(true)) 738 return err 739 } else { 740 err := stack.Push(MakeBool(false)) 741 return err 742 } 743 } 744 745 // Greater than 746 // num1 num2 gt -> bool; num1 > num2 747 func (this *PSOperand) Gt(stack *PSStack) error { 748 num2, err := stack.PopNumberAsFloat64() 749 if err != nil { 750 return err 751 } 752 753 num1, err := stack.PopNumberAsFloat64() 754 if err != nil { 755 return err 756 } 757 758 // Check equlity. 759 if math.Abs(num1-num2) < TOLERANCE { 760 err := stack.Push(MakeBool(false)) 761 return err 762 } else if num1 > num2 { 763 err := stack.Push(MakeBool(true)) 764 return err 765 } else { 766 err := stack.Push(MakeBool(false)) 767 return err 768 } 769 } 770 771 // Integral division 772 // 25 3 div -> 8 773 func (this *PSOperand) IDiv(stack *PSStack) error { 774 obj1, err := stack.Pop() 775 if err != nil { 776 return err 777 } 778 779 obj2, err := stack.Pop() 780 if err != nil { 781 return err 782 } 783 784 int1, ok := obj1.(*PSInteger) 785 if !ok { 786 return ErrTypeCheck 787 } 788 if int1.Val == 0 { 789 return ErrUndefinedResult 790 } 791 792 int2, ok := obj2.(*PSInteger) 793 if !ok { 794 return ErrTypeCheck 795 } 796 797 result := int2.Val / int1.Val 798 err = stack.Push(MakeInteger(result)) 799 800 return err 801 } 802 803 // If conditional 804 // bool proc if -> run proc() if bool is true 805 func (this *PSOperand) If(stack *PSStack) error { 806 obj1, err := stack.Pop() 807 if err != nil { 808 return err 809 } 810 obj2, err := stack.Pop() 811 if err != nil { 812 return err 813 } 814 815 // Type checks. 816 proc, ok := obj1.(*PSProgram) 817 if !ok { 818 return ErrTypeCheck 819 } 820 condition, ok := obj2.(*PSBoolean) 821 if !ok { 822 return ErrTypeCheck 823 } 824 825 // Run proc if condition is true. 826 if condition.Val { 827 err := proc.Exec(stack) 828 return err 829 } 830 831 return nil 832 } 833 834 // If else conditional 835 // bool proc1 proc2 ifelse -> execute proc1() if bool is true, otherwise proc2() 836 func (this *PSOperand) IfElse(stack *PSStack) error { 837 obj1, err := stack.Pop() 838 if err != nil { 839 return err 840 } 841 obj2, err := stack.Pop() 842 if err != nil { 843 return err 844 } 845 obj3, err := stack.Pop() 846 if err != nil { 847 return err 848 } 849 850 // Type checks. 851 proc2, ok := obj1.(*PSProgram) 852 if !ok { 853 return ErrTypeCheck 854 } 855 proc1, ok := obj2.(*PSProgram) 856 if !ok { 857 return ErrTypeCheck 858 } 859 condition, ok := obj3.(*PSBoolean) 860 if !ok { 861 return ErrTypeCheck 862 } 863 864 // Run proc if condition is true. 865 if condition.Val { 866 err := proc1.Exec(stack) 867 return err 868 } else { 869 err := proc2.Exec(stack) 870 return err 871 } 872 } 873 874 // Add a copy of the nth object in the stack to the top. 875 // any_n ... any_0 n index -> any_n ... any_0 any_n 876 // index from 0 877 func (this *PSOperand) Index(stack *PSStack) error { 878 obj, err := stack.Pop() 879 if err != nil { 880 return err 881 } 882 883 n, ok := obj.(*PSInteger) 884 if !ok { 885 return ErrTypeCheck 886 } 887 888 if n.Val < 0 { 889 return ErrRangeCheck 890 } 891 892 if n.Val > len(*stack)-1 { 893 return ErrStackUnderflow 894 } 895 896 objN := (*stack)[len(*stack)-1-n.Val] 897 898 err = stack.Push(objN.Duplicate()) 899 return err 900 } 901 902 // Less or equal 903 // num1 num2 le -> bool; num1 <= num2 904 func (this *PSOperand) Le(stack *PSStack) error { 905 num2, err := stack.PopNumberAsFloat64() 906 if err != nil { 907 return err 908 } 909 910 num1, err := stack.PopNumberAsFloat64() 911 if err != nil { 912 return err 913 } 914 915 // Check equlity. 916 if math.Abs(num1-num2) < TOLERANCE { 917 err := stack.Push(MakeBool(true)) 918 return err 919 } else if num1 < num2 { 920 err := stack.Push(MakeBool(true)) 921 return err 922 } else { 923 err := stack.Push(MakeBool(false)) 924 return err 925 } 926 } 927 928 // num log -> real 929 func (this *PSOperand) Log(stack *PSStack) error { 930 // Value 931 val, err := stack.PopNumberAsFloat64() 932 if err != nil { 933 return err 934 } 935 936 result := math.Log10(val) 937 err = stack.Push(MakeReal(result)) 938 return err 939 } 940 941 // num ln -> ln(num) 942 // The result is a real number. 943 func (this *PSOperand) Ln(stack *PSStack) error { 944 // Value 945 val, err := stack.PopNumberAsFloat64() 946 if err != nil { 947 return err 948 } 949 950 result := math.Log(val) 951 err = stack.Push(MakeReal(result)) 952 return err 953 } 954 955 // Less than 956 // num1 num2 lt -> bool; num1 < num2 957 func (this *PSOperand) Lt(stack *PSStack) error { 958 num2, err := stack.PopNumberAsFloat64() 959 if err != nil { 960 return err 961 } 962 963 num1, err := stack.PopNumberAsFloat64() 964 if err != nil { 965 return err 966 } 967 968 // Check equlity. 969 if math.Abs(num1-num2) < TOLERANCE { 970 err := stack.Push(MakeBool(false)) 971 return err 972 } else if num1 < num2 { 973 err := stack.Push(MakeBool(true)) 974 return err 975 } else { 976 err := stack.Push(MakeBool(false)) 977 return err 978 } 979 } 980 981 // 12 10 mod -> 2 982 func (this *PSOperand) Mod(stack *PSStack) error { 983 obj1, err := stack.Pop() 984 if err != nil { 985 return err 986 } 987 988 obj2, err := stack.Pop() 989 if err != nil { 990 return err 991 } 992 993 int1, ok := obj1.(*PSInteger) 994 if !ok { 995 return ErrTypeCheck 996 } 997 if int1.Val == 0 { 998 return ErrUndefinedResult 999 } 1000 1001 int2, ok := obj2.(*PSInteger) 1002 if !ok { 1003 return ErrTypeCheck 1004 } 1005 1006 result := int2.Val % int1.Val 1007 err = stack.Push(MakeInteger(result)) 1008 return err 1009 } 1010 1011 // 6 8 mul -> 48 1012 func (this *PSOperand) Mul(stack *PSStack) error { 1013 obj1, err := stack.Pop() 1014 if err != nil { 1015 return err 1016 } 1017 1018 obj2, err := stack.Pop() 1019 if err != nil { 1020 return err 1021 } 1022 1023 real1, isReal1 := obj1.(*PSReal) 1024 int1, isInt1 := obj1.(*PSInteger) 1025 if !isReal1 && !isInt1 { 1026 return ErrTypeCheck 1027 } 1028 1029 real2, isReal2 := obj2.(*PSReal) 1030 int2, isInt2 := obj2.(*PSInteger) 1031 if !isReal2 && !isInt2 { 1032 return ErrTypeCheck 1033 } 1034 1035 // If both numbers integers -> integer output. 1036 if isInt1 && isInt2 { 1037 result := int1.Val * int2.Val 1038 err := stack.Push(MakeInteger(result)) 1039 return err 1040 } 1041 1042 // Otherwise -> real output. 1043 var result float64 = 0 1044 if isReal1 { 1045 result = real1.Val 1046 } else { 1047 result = float64(int1.Val) 1048 } 1049 1050 if isReal2 { 1051 result *= real2.Val 1052 } else { 1053 result *= float64(int2.Val) 1054 } 1055 1056 err = stack.Push(MakeReal(result)) 1057 return err 1058 } 1059 1060 // Not equal (inverse of eq) 1061 // any1 any2 ne -> bool 1062 func (this *PSOperand) Ne(stack *PSStack) error { 1063 // Simply call equate and then negate the result. 1064 // Implementing directly could be more efficient, but probably not a big deal in most cases. 1065 err := this.Eq(stack) 1066 if err != nil { 1067 return err 1068 } 1069 1070 err = this.Not(stack) 1071 return err 1072 } 1073 1074 // Negate 1075 // 6 neg -> -6 1076 func (this *PSOperand) Neg(stack *PSStack) error { 1077 obj, err := stack.Pop() 1078 if err != nil { 1079 return err 1080 } 1081 1082 if real, isReal := obj.(*PSReal); isReal { 1083 err = stack.Push(MakeReal(-real.Val)) 1084 return err 1085 } else if inum, isInt := obj.(*PSInteger); isInt { 1086 err = stack.Push(MakeInteger(-inum.Val)) 1087 return err 1088 1089 } else { 1090 return ErrTypeCheck 1091 } 1092 } 1093 1094 // Logical/bitwise negation 1095 // bool1 not -> bool2 (logical) 1096 // int1 not -> int2 (bitwise) 1097 func (this *PSOperand) Not(stack *PSStack) error { 1098 obj, err := stack.Pop() 1099 if err != nil { 1100 return err 1101 } 1102 1103 if bool1, is := obj.(*PSBoolean); is { 1104 err = stack.Push(MakeBool(!bool1.Val)) 1105 return err 1106 } else if int1, isInt := obj.(*PSInteger); isInt { 1107 err = stack.Push(MakeInteger(^int1.Val)) 1108 return err 1109 } else { 1110 return ErrTypeCheck 1111 } 1112 } 1113 1114 // OR logical/bitwise operation. 1115 // bool1 bool2 or -> bool3 (logical or) 1116 // int1 int2 or -> int3 (bitwise or) 1117 func (this *PSOperand) Or(stack *PSStack) error { 1118 obj1, err := stack.Pop() 1119 if err != nil { 1120 return err 1121 } 1122 1123 obj2, err := stack.Pop() 1124 if err != nil { 1125 return err 1126 } 1127 1128 // Boolean inputs (logical). 1129 if bool1, is := obj1.(*PSBoolean); is { 1130 bool2, ok := obj2.(*PSBoolean) 1131 if !ok { 1132 return ErrTypeCheck 1133 } 1134 err = stack.Push(MakeBool(bool1.Val || bool2.Val)) 1135 return err 1136 } 1137 1138 // Integer inputs (bitwise). 1139 if int1, is := obj1.(*PSInteger); is { 1140 int2, ok := obj2.(*PSInteger) 1141 if !ok { 1142 return ErrTypeCheck 1143 } 1144 err = stack.Push(MakeInteger(int1.Val | int2.Val)) 1145 return err 1146 } 1147 1148 return ErrTypeCheck 1149 } 1150 1151 // Remove the top element on the stack (pop) 1152 func (this *PSOperand) Pop(stack *PSStack) error { 1153 _, err := stack.Pop() 1154 if err != nil { 1155 return err 1156 } 1157 return nil 1158 } 1159 1160 // Round number off. 1161 // num1 round -> num2 1162 func (this *PSOperand) Round(stack *PSStack) error { 1163 obj, err := stack.Pop() 1164 if err != nil { 1165 return err 1166 } 1167 1168 if num, is := obj.(*PSReal); is { 1169 err = stack.Push(MakeReal(math.Floor(num.Val + 0.5))) 1170 } else if num, is := obj.(*PSInteger); is { 1171 err = stack.Push(MakeInteger(num.Val)) 1172 } else { 1173 return ErrTypeCheck 1174 } 1175 1176 return err 1177 } 1178 1179 // Roll stack contents (num dir roll) 1180 // num: number of elements, dir: direction 1181 // 7 8 9 3 1 roll -> 9 7 8 1182 // 7 8 9 3 -1 roll -> 8 9 7 1183 // n j roll 1184 func (this *PSOperand) Roll(stack *PSStack) error { 1185 obj1, err := stack.Pop() 1186 if err != nil { 1187 return err 1188 } 1189 1190 obj2, err := stack.Pop() 1191 if err != nil { 1192 return err 1193 } 1194 1195 j, ok := obj1.(*PSInteger) 1196 if !ok { 1197 return ErrTypeCheck 1198 } 1199 1200 n, ok := obj2.(*PSInteger) 1201 if !ok { 1202 return ErrTypeCheck 1203 } 1204 if n.Val < 0 { 1205 return ErrRangeCheck 1206 } 1207 if n.Val == 0 || n.Val == 1 { 1208 // Do nothing.. 1209 return nil 1210 } 1211 if n.Val > len(*stack) { 1212 return ErrStackUnderflow 1213 } 1214 1215 for i := 0; i < abs(j.Val); i++ { 1216 var substack []PSObject 1217 1218 substack = (*stack)[len(*stack)-(n.Val) : len(*stack)] 1219 if j.Val > 0 { 1220 // if j > 0; put the top element on bottom of the substack 1221 top := substack[len(substack)-1] 1222 substack = append([]PSObject{top}, substack[0:len(substack)-1]...) 1223 } else { 1224 // if j < 0: put the bottom element on top 1225 bottom := substack[len(substack)-n.Val] 1226 substack = append(substack[1:], bottom) 1227 } 1228 1229 s := append((*stack)[0:len(*stack)-n.Val], substack...) 1230 stack = &s 1231 } 1232 1233 return nil 1234 } 1235 1236 // Sine. 1237 // angle sin -> real 1238 // Angle is in degrees 1239 func (this *PSOperand) Sin(stack *PSStack) error { 1240 angle, err := stack.PopNumberAsFloat64() 1241 if err != nil { 1242 return err 1243 } 1244 1245 result := math.Sin(angle * math.Pi / 180.0) 1246 err = stack.Push(MakeReal(result)) 1247 return err 1248 } 1249 1250 // Square root. 1251 // num sqrt -> real; real=sqrt(num) 1252 // The result is a real number. 1253 func (this *PSOperand) Sqrt(stack *PSStack) error { 1254 val, err := stack.PopNumberAsFloat64() 1255 if err != nil { 1256 return err 1257 } 1258 1259 if val < 0 { 1260 return ErrRangeCheck 1261 } 1262 1263 result := math.Sqrt(val) 1264 err = stack.Push(MakeReal(result)) 1265 return err 1266 } 1267 1268 // 8.3 6.6 sub -> 1.7 (real) 1269 // 8 6.3 sub -> 1.7 (real) 1270 // 8 6 sub -> 2 (int) 1271 func (this *PSOperand) Sub(stack *PSStack) error { 1272 obj1, err := stack.Pop() 1273 if err != nil { 1274 return err 1275 } 1276 1277 obj2, err := stack.Pop() 1278 if err != nil { 1279 return err 1280 } 1281 1282 real1, isReal1 := obj1.(*PSReal) 1283 int1, isInt1 := obj1.(*PSInteger) 1284 if !isReal1 && !isInt1 { 1285 return ErrTypeCheck 1286 } 1287 1288 real2, isReal2 := obj2.(*PSReal) 1289 int2, isInt2 := obj2.(*PSInteger) 1290 if !isReal2 && !isInt2 { 1291 return ErrTypeCheck 1292 } 1293 1294 // If both numbers integers -> integer output. 1295 if isInt1 && isInt2 { 1296 result := int2.Val - int1.Val 1297 err := stack.Push(MakeInteger(result)) 1298 return err 1299 } 1300 1301 // Otherwise -> real output. 1302 var result float64 = 0 1303 if isReal2 { 1304 result = real2.Val 1305 } else { 1306 result = float64(int2.Val) 1307 } 1308 1309 if isReal1 { 1310 result -= real1.Val 1311 } else { 1312 result -= float64(int1.Val) 1313 } 1314 1315 err = stack.Push(MakeReal(result)) 1316 return err 1317 } 1318 1319 // Truncate number. 1320 // num1 truncate -> num2 1321 // The resulting number is the same type as the input. 1322 func (this *PSOperand) Truncate(stack *PSStack) error { 1323 obj, err := stack.Pop() 1324 if err != nil { 1325 return err 1326 } 1327 1328 if num, is := obj.(*PSReal); is { 1329 truncated := int(num.Val) 1330 err = stack.Push(MakeReal(float64(truncated))) 1331 } else if num, is := obj.(*PSInteger); is { 1332 err = stack.Push(MakeInteger(num.Val)) 1333 } else { 1334 return ErrTypeCheck 1335 } 1336 1337 return err 1338 } 1339 1340 // XOR logical/bitwise operation. 1341 // bool1 bool2 xor -> bool3 (logical xor) 1342 // int1 int2 xor -> int3 (bitwise xor) 1343 func (this *PSOperand) Xor(stack *PSStack) error { 1344 obj1, err := stack.Pop() 1345 if err != nil { 1346 return err 1347 } 1348 1349 obj2, err := stack.Pop() 1350 if err != nil { 1351 return err 1352 } 1353 1354 // Boolean inputs (logical). 1355 if bool1, is := obj1.(*PSBoolean); is { 1356 bool2, ok := obj2.(*PSBoolean) 1357 if !ok { 1358 return ErrTypeCheck 1359 } 1360 err = stack.Push(MakeBool(bool1.Val != bool2.Val)) 1361 return err 1362 } 1363 1364 // Integer inputs (bitwise). 1365 if int1, is := obj1.(*PSInteger); is { 1366 int2, ok := obj2.(*PSInteger) 1367 if !ok { 1368 return ErrTypeCheck 1369 } 1370 err = stack.Push(MakeInteger(int1.Val ^ int2.Val)) 1371 return err 1372 } 1373 1374 return ErrTypeCheck 1375 }