gitea源码

eval.go 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. // Copyright 2023 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package eval
  4. import (
  5. "fmt"
  6. "strconv"
  7. "strings"
  8. "code.gitea.io/gitea/modules/util"
  9. )
  10. type Num struct {
  11. Value any // int64 or float64, nil on error
  12. }
  13. var opPrecedence = map[string]int{
  14. // "(": 1, this is for low precedence like function calls, they are handled separately
  15. "or": 2,
  16. "and": 3,
  17. "not": 4,
  18. "==": 5, "!=": 5, "<": 5, "<=": 5, ">": 5, ">=": 5,
  19. "+": 6, "-": 6,
  20. "*": 7, "/": 7,
  21. }
  22. type stack[T any] struct {
  23. name string
  24. elems []T
  25. }
  26. func (s *stack[T]) push(t T) {
  27. s.elems = append(s.elems, t)
  28. }
  29. func (s *stack[T]) pop() T {
  30. if len(s.elems) == 0 {
  31. panic(s.name + " stack is empty")
  32. }
  33. t := s.elems[len(s.elems)-1]
  34. s.elems = s.elems[:len(s.elems)-1]
  35. return t
  36. }
  37. func (s *stack[T]) peek() T {
  38. if len(s.elems) == 0 {
  39. panic(s.name + " stack is empty")
  40. }
  41. return s.elems[len(s.elems)-1]
  42. }
  43. type operator string
  44. type eval struct {
  45. stackNum stack[Num]
  46. stackOp stack[operator]
  47. funcMap map[string]func([]Num) Num
  48. }
  49. func newEval() *eval {
  50. e := &eval{}
  51. e.stackNum.name = "num"
  52. e.stackOp.name = "op"
  53. return e
  54. }
  55. func toNum(v any) (Num, error) {
  56. switch v := v.(type) {
  57. case string:
  58. if strings.Contains(v, ".") {
  59. n, err := strconv.ParseFloat(v, 64)
  60. if err != nil {
  61. return Num{n}, err
  62. }
  63. return Num{n}, nil
  64. }
  65. n, err := strconv.ParseInt(v, 10, 64)
  66. if err != nil {
  67. return Num{n}, err
  68. }
  69. return Num{n}, nil
  70. case float32, float64:
  71. n, _ := util.ToFloat64(v)
  72. return Num{n}, nil
  73. default:
  74. n, err := util.ToInt64(v)
  75. if err != nil {
  76. return Num{n}, err
  77. }
  78. return Num{n}, nil
  79. }
  80. }
  81. func truth(b bool) int64 {
  82. if b {
  83. return int64(1)
  84. }
  85. return int64(0)
  86. }
  87. func applyOp2Generic[T int64 | float64](op operator, n1, n2 T) Num {
  88. switch op {
  89. case "+":
  90. return Num{n1 + n2}
  91. case "-":
  92. return Num{n1 - n2}
  93. case "*":
  94. return Num{n1 * n2}
  95. case "/":
  96. return Num{n1 / n2}
  97. case "==":
  98. return Num{truth(n1 == n2)}
  99. case "!=":
  100. return Num{truth(n1 != n2)}
  101. case "<":
  102. return Num{truth(n1 < n2)}
  103. case "<=":
  104. return Num{truth(n1 <= n2)}
  105. case ">":
  106. return Num{truth(n1 > n2)}
  107. case ">=":
  108. return Num{truth(n1 >= n2)}
  109. case "and":
  110. t1, _ := util.ToFloat64(n1)
  111. t2, _ := util.ToFloat64(n2)
  112. return Num{truth(t1 != 0 && t2 != 0)}
  113. case "or":
  114. t1, _ := util.ToFloat64(n1)
  115. t2, _ := util.ToFloat64(n2)
  116. return Num{truth(t1 != 0 || t2 != 0)}
  117. }
  118. panic("unknown operator: " + string(op))
  119. }
  120. func applyOp2(op operator, n1, n2 Num) Num {
  121. float := false
  122. if _, ok := n1.Value.(float64); ok {
  123. float = true
  124. } else if _, ok = n2.Value.(float64); ok {
  125. float = true
  126. }
  127. if float {
  128. f1, _ := util.ToFloat64(n1.Value)
  129. f2, _ := util.ToFloat64(n2.Value)
  130. return applyOp2Generic(op, f1, f2)
  131. }
  132. return applyOp2Generic(op, n1.Value.(int64), n2.Value.(int64))
  133. }
  134. func toOp(v any) (operator, error) {
  135. if v, ok := v.(string); ok {
  136. return operator(v), nil
  137. }
  138. return "", fmt.Errorf(`unsupported token type "%T"`, v)
  139. }
  140. func (op operator) hasOpenBracket() bool {
  141. return strings.HasSuffix(string(op), "(") // it's used to support functions like "sum("
  142. }
  143. func (op operator) isComma() bool {
  144. return op == ","
  145. }
  146. func (op operator) isCloseBracket() bool {
  147. return op == ")"
  148. }
  149. type ExprError struct {
  150. msg string
  151. tokens []any
  152. err error
  153. }
  154. func (err ExprError) Error() string {
  155. sb := strings.Builder{}
  156. sb.WriteString(err.msg)
  157. sb.WriteString(" [ ")
  158. for _, token := range err.tokens {
  159. _, _ = fmt.Fprintf(&sb, `"%v" `, token)
  160. }
  161. sb.WriteString("]")
  162. if err.err != nil {
  163. sb.WriteString(": ")
  164. sb.WriteString(err.err.Error())
  165. }
  166. return sb.String()
  167. }
  168. func (err ExprError) Unwrap() error {
  169. return err.err
  170. }
  171. func (e *eval) applyOp() {
  172. op := e.stackOp.pop()
  173. if op == "not" {
  174. num := e.stackNum.pop()
  175. i, _ := util.ToInt64(num.Value)
  176. e.stackNum.push(Num{truth(i == 0)})
  177. } else if op.hasOpenBracket() || op.isCloseBracket() || op.isComma() {
  178. panic(fmt.Sprintf("incomplete sub-expression with operator %q", op))
  179. } else {
  180. num2 := e.stackNum.pop()
  181. num1 := e.stackNum.pop()
  182. e.stackNum.push(applyOp2(op, num1, num2))
  183. }
  184. }
  185. func (e *eval) exec(tokens ...any) (ret Num, err error) {
  186. defer func() {
  187. if r := recover(); r != nil {
  188. rErr, ok := r.(error)
  189. if !ok {
  190. rErr = fmt.Errorf("%v", r)
  191. }
  192. err = ExprError{"invalid expression", tokens, rErr}
  193. }
  194. }()
  195. for _, token := range tokens {
  196. n, err := toNum(token)
  197. if err == nil {
  198. e.stackNum.push(n)
  199. continue
  200. }
  201. op, err := toOp(token)
  202. if err != nil {
  203. return Num{}, ExprError{"invalid expression", tokens, err}
  204. }
  205. switch {
  206. case op.hasOpenBracket():
  207. e.stackOp.push(op)
  208. case op.isCloseBracket(), op.isComma():
  209. var stackTopOp operator
  210. for len(e.stackOp.elems) > 0 {
  211. stackTopOp = e.stackOp.peek()
  212. if stackTopOp.hasOpenBracket() || stackTopOp.isComma() {
  213. break
  214. }
  215. e.applyOp()
  216. }
  217. if op.isCloseBracket() {
  218. nums := []Num{e.stackNum.pop()}
  219. for !e.stackOp.peek().hasOpenBracket() {
  220. stackTopOp = e.stackOp.pop()
  221. if !stackTopOp.isComma() {
  222. return Num{}, ExprError{"bracket doesn't match", tokens, nil}
  223. }
  224. nums = append(nums, e.stackNum.pop())
  225. }
  226. for i, j := 0, len(nums)-1; i < j; i, j = i+1, j-1 {
  227. nums[i], nums[j] = nums[j], nums[i] // reverse nums slice, to get the right order for arguments
  228. }
  229. stackTopOp = e.stackOp.pop()
  230. fn := string(stackTopOp[:len(stackTopOp)-1])
  231. if fn == "" {
  232. if len(nums) != 1 {
  233. return Num{}, ExprError{"too many values in one bracket", tokens, nil}
  234. }
  235. e.stackNum.push(nums[0])
  236. } else if f, ok := e.funcMap[fn]; ok {
  237. e.stackNum.push(f(nums))
  238. } else {
  239. return Num{}, ExprError{"unknown function: " + fn, tokens, nil}
  240. }
  241. } else {
  242. e.stackOp.push(op)
  243. }
  244. default:
  245. for len(e.stackOp.elems) > 0 && len(e.stackNum.elems) > 0 {
  246. stackTopOp := e.stackOp.peek()
  247. if stackTopOp.hasOpenBracket() || stackTopOp.isComma() || precedence(stackTopOp, op) < 0 {
  248. break
  249. }
  250. e.applyOp()
  251. }
  252. e.stackOp.push(op)
  253. }
  254. }
  255. for len(e.stackOp.elems) > 0 && !e.stackOp.peek().isComma() {
  256. e.applyOp()
  257. }
  258. if len(e.stackNum.elems) != 1 {
  259. return Num{}, ExprError{fmt.Sprintf("expect 1 value as final result, but there are %d", len(e.stackNum.elems)), tokens, nil}
  260. }
  261. return e.stackNum.pop(), nil
  262. }
  263. func precedence(op1, op2 operator) int {
  264. p1 := opPrecedence[string(op1)]
  265. p2 := opPrecedence[string(op2)]
  266. if p1 == 0 {
  267. panic("unknown operator precedence: " + string(op1))
  268. } else if p2 == 0 {
  269. panic("unknown operator precedence: " + string(op2))
  270. }
  271. return p1 - p2
  272. }
  273. func castFloat64(nums []Num) bool {
  274. hasFloat := false
  275. for _, num := range nums {
  276. if _, hasFloat = num.Value.(float64); hasFloat {
  277. break
  278. }
  279. }
  280. if hasFloat {
  281. for i, num := range nums {
  282. if _, ok := num.Value.(float64); !ok {
  283. f, _ := util.ToFloat64(num.Value)
  284. nums[i] = Num{f}
  285. }
  286. }
  287. }
  288. return hasFloat
  289. }
  290. func fnSum(nums []Num) Num {
  291. if castFloat64(nums) {
  292. var sum float64
  293. for _, num := range nums {
  294. sum += num.Value.(float64)
  295. }
  296. return Num{sum}
  297. }
  298. var sum int64
  299. for _, num := range nums {
  300. sum += num.Value.(int64)
  301. }
  302. return Num{sum}
  303. }
  304. // Expr evaluates the given expression tokens and returns the result.
  305. // It supports the following operators: +, -, *, /, and, or, not, ==, !=, >, >=, <, <=.
  306. // Non-zero values are treated as true, zero values are treated as false.
  307. // If no error occurs, the result is either an int64 or a float64.
  308. // If all numbers are integer, the result is an int64, otherwise if there is any float number, the result is a float64.
  309. func Expr(tokens ...any) (Num, error) {
  310. e := newEval()
  311. e.funcMap = map[string]func([]Num) Num{"sum": fnSum}
  312. return e.exec(tokens...)
  313. }