math.ts 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. export const mathConstants = new Set(["PI", "E", "LN2", "LN10", "LOG2E", "LOG10E", "SQRT2", "SQRT1_2"])
  2. export const mathMethods = new Set([
  3. "max",
  4. "min",
  5. "abs",
  6. "floor",
  7. "ceil",
  8. "round",
  9. "trunc",
  10. "sign",
  11. "sqrt",
  12. "cbrt",
  13. "pow",
  14. "hypot",
  15. "log",
  16. "log2",
  17. "log10",
  18. "exp",
  19. ])
  20. export const invokeMathMethod = (name: string, args: Array<unknown>, node: AstNode): number => {
  21. if (!mathMethods.has(name)) throw new InterpreterRuntimeError(`Math.${name} is not available in CodeMode.`, node)
  22. const nums = args.map((arg) => {
  23. if (typeof arg !== "number") throw new InterpreterRuntimeError(`Math.${name} expects number arguments.`, node)
  24. return arg
  25. })
  26. const [a = Number.NaN, b = Number.NaN] = nums
  27. switch (name) {
  28. case "max":
  29. return Math.max(...nums)
  30. case "min":
  31. return Math.min(...nums)
  32. case "abs":
  33. return Math.abs(a)
  34. case "floor":
  35. return Math.floor(a)
  36. case "ceil":
  37. return Math.ceil(a)
  38. case "round":
  39. return Math.round(a)
  40. case "trunc":
  41. return Math.trunc(a)
  42. case "sign":
  43. return Math.sign(a)
  44. case "sqrt":
  45. return Math.sqrt(a)
  46. case "cbrt":
  47. return Math.cbrt(a)
  48. case "pow":
  49. return Math.pow(a, b)
  50. case "hypot":
  51. return Math.hypot(...nums)
  52. case "log":
  53. return Math.log(a)
  54. case "log2":
  55. return Math.log2(a)
  56. case "log10":
  57. return Math.log10(a)
  58. case "exp":
  59. return Math.exp(a)
  60. }
  61. throw new InterpreterRuntimeError(`Math.${name} is not available in CodeMode.`, node)
  62. }
  63. import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js"