chcks.nim 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2013 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # Implementation of some runtime checks.
  10. include system/indexerrors
  11. when defined(nimPreviewSlimSystem):
  12. import std/formatfloat
  13. proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} =
  14. when hostOS == "standalone":
  15. sysFatal(RangeDefect, "value out of range")
  16. else:
  17. sysFatal(RangeDefect, "value out of range: ", $val)
  18. proc raiseIndexError4(l1, h1, h2: int) {.compilerproc, noinline.} =
  19. sysFatal(IndexDefect, "index out of bounds: " & $l1 & ".." & $h1 & " notin 0.." & $(h2 - 1))
  20. proc raiseIndexError3(i, a, b: int) {.compilerproc, noinline.} =
  21. sysFatal(IndexDefect, formatErrorIndexBound(i, a, b))
  22. proc raiseIndexError2(i, n: int) {.compilerproc, noinline.} =
  23. sysFatal(IndexDefect, formatErrorIndexBound(i, n))
  24. proc raiseIndexError() {.compilerproc, noinline.} =
  25. sysFatal(IndexDefect, "index out of bounds")
  26. proc raiseFieldError(f: string) {.compilerproc, noinline.} =
  27. ## remove after bootstrap > 1.5.1
  28. sysFatal(FieldDefect, f)
  29. when defined(nimV2):
  30. proc raiseFieldError2(f: string, discVal: int) {.compilerproc, noinline.} =
  31. ## raised when field is inaccessible given runtime value of discriminant
  32. sysFatal(FieldDefect, f & $discVal & "'")
  33. proc raiseFieldErrorStr(f: string, discVal: string) {.compilerproc, noinline.} =
  34. ## raised when field is inaccessible given runtime value of discriminant
  35. sysFatal(FieldDefect, formatFieldDefect(f, discVal))
  36. else:
  37. proc raiseFieldError2(f: string, discVal: string) {.compilerproc, noinline.} =
  38. ## raised when field is inaccessible given runtime value of discriminant
  39. sysFatal(FieldDefect, formatFieldDefect(f, discVal))
  40. proc raiseRangeErrorI(i, a, b: BiggestInt) {.compilerproc, noinline.} =
  41. when defined(standalone):
  42. sysFatal(RangeDefect, "value out of range")
  43. else:
  44. sysFatal(RangeDefect, "value out of range: " & $i & " notin " & $a & " .. " & $b)
  45. proc raiseRangeErrorF(i, a, b: float) {.compilerproc, noinline.} =
  46. when defined(standalone):
  47. sysFatal(RangeDefect, "value out of range")
  48. else:
  49. sysFatal(RangeDefect, "value out of range: " & $i & " notin " & $a & " .. " & $b)
  50. proc raiseRangeErrorU(i, a, b: uint64) {.compilerproc, noinline.} =
  51. # todo: better error reporting
  52. sysFatal(RangeDefect, "value out of range")
  53. proc raiseRangeErrorNoArgs() {.compilerproc, noinline.} =
  54. sysFatal(RangeDefect, "value out of range")
  55. proc raiseObjectConversionError() {.compilerproc, noinline.} =
  56. sysFatal(ObjectConversionDefect, "invalid object conversion")
  57. proc chckIndx(i, a, b: int): int =
  58. if i >= a and i <= b:
  59. return i
  60. else:
  61. result = 0
  62. raiseIndexError3(i, a, b)
  63. proc chckRange(i, a, b: int): int =
  64. if i >= a and i <= b:
  65. return i
  66. else:
  67. result = 0
  68. raiseRangeError(i)
  69. proc chckRange64(i, a, b: int64): int64 {.compilerproc.} =
  70. if i >= a and i <= b:
  71. return i
  72. else:
  73. result = 0
  74. raiseRangeError(i)
  75. proc chckRangeU(i, a, b: uint64): uint64 {.compilerproc.} =
  76. if i >= a and i <= b:
  77. return i
  78. else:
  79. result = 0
  80. sysFatal(RangeDefect, "value out of range")
  81. proc chckRangeF(x, a, b: float): float =
  82. if x >= a and x <= b:
  83. return x
  84. else:
  85. result = 0.0
  86. when hostOS == "standalone":
  87. sysFatal(RangeDefect, "value out of range")
  88. else:
  89. sysFatal(RangeDefect, "value out of range: ", $x)
  90. proc chckNil(p: pointer) =
  91. if p == nil:
  92. sysFatal(NilAccessDefect, "attempt to write to a nil address")
  93. proc chckNilDisp(p: pointer) {.compilerproc.} =
  94. if p == nil:
  95. sysFatal(NilAccessDefect, "cannot dispatch; dispatcher is nil")
  96. when not defined(nimV2):
  97. proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
  98. # checks if obj is of type subclass:
  99. var x = obj
  100. if x == subclass: return # optimized fast path
  101. while x != subclass:
  102. if x == nil:
  103. sysFatal(ObjectConversionDefect, "invalid object conversion")
  104. x = x.base
  105. proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} =
  106. if a != b:
  107. sysFatal(ObjectAssignmentDefect, "invalid object assignment")
  108. type ObjCheckCache = array[0..1, PNimType]
  109. proc isObjSlowPath(obj, subclass: PNimType;
  110. cache: var ObjCheckCache): bool {.noinline.} =
  111. # checks if obj is of type subclass:
  112. var x = obj.base
  113. while x != subclass:
  114. if x == nil:
  115. cache[0] = obj
  116. return false
  117. x = x.base
  118. cache[1] = obj
  119. return true
  120. proc isObjWithCache(obj, subclass: PNimType;
  121. cache: var ObjCheckCache): bool {.compilerproc, inline.} =
  122. if obj == subclass: return true
  123. if obj.base == subclass: return true
  124. if cache[0] == obj: return false
  125. if cache[1] == obj: return true
  126. return isObjSlowPath(obj, subclass, cache)
  127. proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
  128. # checks if obj is of type subclass:
  129. var x = obj
  130. if x == subclass: return true # optimized fast path
  131. while x != subclass:
  132. if x == nil: return false
  133. x = x.base
  134. return true
  135. when defined(nimV2):
  136. proc raiseObjectCaseTransition() {.compilerproc.} =
  137. sysFatal(FieldDefect, "assignment to discriminant changes object branch")