math.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package main
  2. import (
  3. "fmt"
  4. "math"
  5. "math/rand"
  6. )
  7. func opAdd(val1, val2 value) value {
  8. return value{tp: typeNumber, num: toNumber(val1) + toNumber(val2)}
  9. }
  10. func opSub(val1, val2 value) value {
  11. return value{tp: typeNumber, num: toNumber(val1) - toNumber(val2)}
  12. }
  13. func opMul(val1, val2 value) value {
  14. return value{tp: typeNumber, num: toNumber(val1) * toNumber(val2)}
  15. }
  16. func opDiv(val1, val2 value) value {
  17. num1, num2 := toNumber(val1), toNumber(val2)
  18. if num2 == 0 {
  19. panic(fmt.Errorf("div: %s (%f / %f)", errDivisionByZero, num1, num2))
  20. }
  21. return value{tp: typeNumber, num: num1 / num2}
  22. }
  23. func opMod(val1, val2 value) value {
  24. num1, num2 := toNumber(val1), toNumber(val2)
  25. if num2 == 0 {
  26. panic(fmt.Errorf("mod: %s (%f %% %f)", errDivisionByZero, num1, num2))
  27. }
  28. return value{tp: typeNumber, num: math.Mod(num1, num2)}
  29. }
  30. func opEq(val1, val2 value) value {
  31. if isNumber(val1) && isNumber(val2) {
  32. return value{tp: typeBool, b: toNumber(val1) == toNumber(val2)}
  33. }
  34. if isBool(val1) && isBool(val2) {
  35. return value{tp: typeBool, b: toBool(val1) == toBool(val2)}
  36. }
  37. if isWord(val1) && isWord(val2) {
  38. return value{tp: typeBool, b: escapeWord(val1.word) == escapeWord(val2.word)}
  39. }
  40. panic(fmt.Errorf("eq: %s (%s == %s)", errIllegalOperandType, toString(val1), toString(val2)))
  41. }
  42. func opGt(val1, val2 value) value {
  43. if isNumber(val1) && isNumber(val2) {
  44. return value{tp: typeBool, b: toNumber(val1) > toNumber(val2)}
  45. }
  46. if isBool(val1) && isBool(val2) {
  47. return value{tp: typeBool, b: toBool(val1) || !toBool(val2)}
  48. }
  49. if isWord(val1) && isWord(val2) {
  50. return value{tp: typeBool, b: escapeWord(val1.word) > escapeWord(val2.word)}
  51. }
  52. panic(fmt.Errorf("gt: %s (%s > %s)", errIllegalOperandType, toString(val1), toString(val2)))
  53. }
  54. func opLt(val1, val2 value) value {
  55. if isNumber(val1) && isNumber(val2) {
  56. return value{tp: typeBool, b: toNumber(val1) < toNumber(val2)}
  57. }
  58. if isBool(val1) && isBool(val2) {
  59. return value{tp: typeBool, b: !toBool(val1) || toBool(val2)}
  60. }
  61. if isWord(val1) && isWord(val2) {
  62. return value{tp: typeBool, b: escapeWord(val1.word) < escapeWord(val2.word)}
  63. }
  64. panic(fmt.Errorf("lt: %s (%s < %s)", errIllegalOperandType, toString(val1), toString(val2)))
  65. }
  66. func opAnd(val1, val2 value) value {
  67. return value{tp: typeBool, b: toBool(val1) && toBool(val2)}
  68. }
  69. func opOr(val1, val2 value) value {
  70. return value{tp: typeBool, b: toBool(val1) || toBool(val2)}
  71. }
  72. func opNot(val1 value) value {
  73. return value{tp: typeBool, b: !toBool(val1)}
  74. }
  75. func opRandom(val1 value) value {
  76. return value{tp: typeNumber, num: toNumber(val1) * rand.Float64()}
  77. }
  78. func opInt(val1 value) value {
  79. return value{tp: typeNumber, num: math.Floor(toNumber(val1))}
  80. }
  81. func opSqrt(val1 value) value {
  82. num1 := toNumber(val1)
  83. if num1 < 0 {
  84. panic(fmt.Errorf("sqrt: %s (%f)", errNegativeSquareRoot, num1))
  85. }
  86. return value{tp: typeNumber, num: math.Sqrt(num1)}
  87. }