numerictower.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package glisp
  2. import (
  3. "errors"
  4. )
  5. type IntegerOp int
  6. const (
  7. ShiftLeft IntegerOp = iota
  8. ShiftRightArith
  9. ShiftRightLog
  10. Modulo
  11. BitAnd
  12. BitOr
  13. BitXor
  14. )
  15. var WrongType error = errors.New("operands have invalid type")
  16. func IntegerDo(op IntegerOp, a, b Sexp) (Sexp, error) {
  17. var ia SexpInt
  18. var ib SexpInt
  19. switch i := a.(type) {
  20. case SexpInt:
  21. ia = i
  22. case SexpChar:
  23. ia = SexpInt(i)
  24. default:
  25. return SexpNull, WrongType
  26. }
  27. switch i := b.(type) {
  28. case SexpInt:
  29. ib = i
  30. case SexpChar:
  31. ib = SexpInt(i)
  32. default:
  33. return SexpNull, WrongType
  34. }
  35. switch op {
  36. case ShiftLeft:
  37. return ia << uint(ib), nil
  38. case ShiftRightArith:
  39. return ia >> uint(ib), nil
  40. case ShiftRightLog:
  41. return SexpInt(uint(ia) >> uint(ib)), nil
  42. case Modulo:
  43. return ia % ib, nil
  44. case BitAnd:
  45. return ia & ib, nil
  46. case BitOr:
  47. return ia | ib, nil
  48. case BitXor:
  49. return ia ^ ib, nil
  50. }
  51. return SexpNull, errors.New("unrecognized shift operation")
  52. }
  53. type NumericOp int
  54. const (
  55. Add NumericOp = iota
  56. Sub
  57. Mult
  58. Div
  59. )
  60. func NumericFloatDo(op NumericOp, a, b SexpFloat) Sexp {
  61. switch op {
  62. case Add:
  63. return a + b
  64. case Sub:
  65. return a - b
  66. case Mult:
  67. return a * b
  68. case Div:
  69. return a / b
  70. }
  71. return SexpNull
  72. }
  73. func NumericIntDo(op NumericOp, a, b SexpInt) Sexp {
  74. switch op {
  75. case Add:
  76. return a + b
  77. case Sub:
  78. return a - b
  79. case Mult:
  80. return a * b
  81. case Div:
  82. if a%b == 0 {
  83. return a / b
  84. } else {
  85. return SexpFloat(a) / SexpFloat(b)
  86. }
  87. }
  88. return SexpNull
  89. }
  90. func NumericMatchFloat(op NumericOp, a SexpFloat, b Sexp) (Sexp, error) {
  91. var fb SexpFloat
  92. switch tb := b.(type) {
  93. case SexpFloat:
  94. fb = tb
  95. case SexpInt:
  96. fb = SexpFloat(tb)
  97. case SexpChar:
  98. fb = SexpFloat(tb)
  99. default:
  100. return SexpNull, WrongType
  101. }
  102. return NumericFloatDo(op, a, fb), nil
  103. }
  104. func NumericMatchInt(op NumericOp, a SexpInt, b Sexp) (Sexp, error) {
  105. switch tb := b.(type) {
  106. case SexpFloat:
  107. return NumericFloatDo(op, SexpFloat(a), tb), nil
  108. case SexpInt:
  109. return NumericIntDo(op, a, tb), nil
  110. case SexpChar:
  111. return NumericIntDo(op, a, SexpInt(tb)), nil
  112. }
  113. return SexpNull, WrongType
  114. }
  115. func NumericMatchChar(op NumericOp, a SexpChar, b Sexp) (Sexp, error) {
  116. var res Sexp
  117. switch tb := b.(type) {
  118. case SexpFloat:
  119. res = NumericFloatDo(op, SexpFloat(a), tb)
  120. case SexpInt:
  121. res = NumericIntDo(op, SexpInt(a), tb)
  122. case SexpChar:
  123. res = NumericIntDo(op, SexpInt(a), SexpInt(tb))
  124. default:
  125. return SexpNull, WrongType
  126. }
  127. switch tres := res.(type) {
  128. case SexpFloat:
  129. return tres, nil
  130. case SexpInt:
  131. return SexpChar(tres), nil
  132. }
  133. return SexpNull, errors.New("unexpected result")
  134. }
  135. func NumericDo(op NumericOp, a, b Sexp) (Sexp, error) {
  136. switch ta := a.(type) {
  137. case SexpFloat:
  138. return NumericMatchFloat(op, ta, b)
  139. case SexpInt:
  140. return NumericMatchInt(op, ta, b)
  141. case SexpChar:
  142. return NumericMatchChar(op, ta, b)
  143. }
  144. return SexpNull, WrongType
  145. }