number.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. package checker
  2. import (
  3. "kumachan/transformer/node"
  4. "math"
  5. "math/big"
  6. "strconv"
  7. )
  8. func (impl UntypedInteger) SemiExprVal() {}
  9. type UntypedInteger struct {
  10. Value *big.Int
  11. }
  12. func (impl IntLiteral) ExprVal() {}
  13. type IntLiteral struct {
  14. Value *big.Int
  15. }
  16. func (impl SmallIntLiteral) ExprVal() {}
  17. type SmallIntLiteral struct {
  18. Kind string
  19. Value interface {}
  20. }
  21. func (impl FloatLiteral) ExprVal() {}
  22. type FloatLiteral struct {
  23. Value float64
  24. }
  25. func CheckInteger(i node.IntegerLiteral, ctx ExprContext) (SemiExpr, *ExprError) {
  26. var info = ctx.GetExprInfo(i.Node)
  27. var chars = i.Value
  28. var abs_chars []rune
  29. if chars[0] == '-' {
  30. abs_chars = chars[1:]
  31. } else {
  32. abs_chars = chars
  33. }
  34. var has_base_prefix = false
  35. if len(abs_chars) >= 2 {
  36. var c1 = abs_chars[0]
  37. var c2 = abs_chars[1]
  38. if c1 == '0' && (c2 == 'x' || c2 == 'o' || c2 == 'b' || c2 == 'X' || c2 == 'O' || c2 == 'B') {
  39. has_base_prefix = true
  40. }
  41. }
  42. var str = string(chars)
  43. var value *big.Int
  44. var ok bool
  45. if has_base_prefix {
  46. value, ok = big.NewInt(0).SetString(str, 0)
  47. } else {
  48. // avoid "0" prefix to be recognized as octal with base 0
  49. value, ok = big.NewInt(0).SetString(str, 10)
  50. }
  51. if ok {
  52. return SemiExpr {
  53. Value: UntypedInteger { value },
  54. Info: info,
  55. }, nil
  56. } else {
  57. return SemiExpr{}, &ExprError {
  58. Point: info.ErrorPoint,
  59. Concrete: E_InvalidInteger { str },
  60. }
  61. }
  62. }
  63. func CheckFloat(f node.FloatLiteral, ctx ExprContext) (SemiExpr, *ExprError) {
  64. var info = ctx.GetExprInfo(f.Node)
  65. var value, err = strconv.ParseFloat(string(f.Value), 64)
  66. if err != nil { panic("invalid float literal got from parser") }
  67. return LiftTyped(Expr {
  68. Type: NamedType {
  69. Name: __Float,
  70. Args: make([]Type, 0),
  71. },
  72. Value: FloatLiteral { value },
  73. Info: info,
  74. }), nil
  75. }
  76. func AssignIntegerTo(expected Type, integer UntypedInteger, info ExprInfo, ctx ExprContext) (Expr, *ExprError) {
  77. var err = RequireExplicitType(expected, info)
  78. if err != nil { return Expr{}, err }
  79. switch E := expected.(type) {
  80. case NamedType:
  81. var sym = E.Name
  82. var kind, exists = __IntegerTypeMap[sym]
  83. if exists {
  84. if len(E.Args) > 0 { panic("something went wrong") }
  85. var val, ok = AdaptInteger(kind, integer.Value)
  86. if ok {
  87. return Expr {
  88. Type: expected,
  89. Info: info,
  90. Value: val,
  91. }, nil
  92. } else {
  93. return Expr{}, &ExprError {
  94. Point: info.ErrorPoint,
  95. Concrete: E_IntegerOverflow { kind },
  96. }
  97. }
  98. }
  99. }
  100. return Expr{}, &ExprError {
  101. Point: info.ErrorPoint,
  102. Concrete: E_IntegerAssignedToNonIntegerType {},
  103. }
  104. }
  105. func AdaptInteger(expected_kind string, value *big.Int) (ExprVal, bool) {
  106. switch expected_kind {
  107. case "Integer",
  108. "Natural":
  109. return IntLiteral { value }, true
  110. case "Int64":
  111. if value.IsInt64() {
  112. return SmallIntLiteral {
  113. Kind: "Int64",
  114. Value: int64(value.Int64()),
  115. }, true
  116. } else {
  117. return nil, false
  118. }
  119. case "Uint64", "Qword":
  120. if value.IsUint64() {
  121. return SmallIntLiteral {
  122. Kind: "Uint64",
  123. Value: uint64(value.Uint64()),
  124. }, true
  125. } else {
  126. return nil, false
  127. }
  128. case "Int32":
  129. if value.IsInt64() {
  130. var x = value.Int64()
  131. if math.MinInt32 <= x && x <= math.MaxInt32 {
  132. return SmallIntLiteral {
  133. Kind: "Int32",
  134. Value: int32(x),
  135. }, true
  136. } else {
  137. return nil, false
  138. }
  139. } else {
  140. return nil, false
  141. }
  142. case "Uint32", "Dword", "Char":
  143. if value.IsUint64() {
  144. var x = value.Uint64()
  145. if x <= math.MaxUint32 {
  146. return SmallIntLiteral {
  147. Kind: "Uint32",
  148. Value: uint32(x),
  149. }, true
  150. } else {
  151. return nil, false
  152. }
  153. } else {
  154. return nil, false
  155. }
  156. case "Int16":
  157. if value.IsInt64() {
  158. var x = value.Int64()
  159. if math.MinInt16 <= x && x <= math.MaxInt16 {
  160. return SmallIntLiteral {
  161. Kind: "Int16",
  162. Value: int16(x),
  163. }, true
  164. } else {
  165. return nil, false
  166. }
  167. } else {
  168. return nil, false
  169. }
  170. case "Uint16", "Word":
  171. if value.IsUint64() {
  172. var x = value.Uint64()
  173. if x <= math.MaxUint16 {
  174. return SmallIntLiteral {
  175. Kind: "Uint16",
  176. Value: uint16(x),
  177. }, true
  178. } else {
  179. return nil, false
  180. }
  181. } else {
  182. return nil, false
  183. }
  184. case "Int8":
  185. if value.IsInt64() {
  186. var x = value.Int64()
  187. if math.MinInt8 <= x && x <= math.MaxInt8 {
  188. return SmallIntLiteral {
  189. Kind: "Int8",
  190. Value: int8(x),
  191. }, true
  192. } else {
  193. return nil, false
  194. }
  195. } else {
  196. return nil, false
  197. }
  198. case "Uint8", "Byte":
  199. if value.IsUint64() {
  200. var x = value.Uint64()
  201. if x <= math.MaxUint8 {
  202. return SmallIntLiteral {
  203. Kind: "Uint8",
  204. Value: uint8(x),
  205. }, true
  206. } else {
  207. return nil, false
  208. }
  209. } else {
  210. return nil, false
  211. }
  212. case "Bit":
  213. if value.IsUint64() {
  214. var x = value.Uint64()
  215. if x == 0 || x == 1 {
  216. return SmallIntLiteral {
  217. Kind: "Bit",
  218. Value: (x == 1),
  219. }, true
  220. } else {
  221. return nil, false
  222. }
  223. } else {
  224. return nil, false
  225. }
  226. default:
  227. panic("impossible branch")
  228. }
  229. }