chcks.nim 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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. proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} =
  12. when hostOS == "standalone":
  13. sysFatal(RangeDefect, "value out of range")
  14. else:
  15. sysFatal(RangeDefect, "value out of range: ", $val)
  16. proc raiseIndexError3(i, a, b: int) {.compilerproc, noinline.} =
  17. sysFatal(IndexDefect, formatErrorIndexBound(i, a, b))
  18. proc raiseIndexError2(i, n: int) {.compilerproc, noinline.} =
  19. sysFatal(IndexDefect, formatErrorIndexBound(i, n))
  20. proc raiseIndexError() {.compilerproc, noinline.} =
  21. sysFatal(IndexDefect, "index out of bounds")
  22. proc raiseFieldError(f: string) {.compilerproc, noinline.} =
  23. sysFatal(FieldDefect, f)
  24. proc raiseRangeErrorI(i, a, b: BiggestInt) {.compilerproc, noinline.} =
  25. when defined(standalone):
  26. sysFatal(RangeDefect, "value out of range")
  27. else:
  28. sysFatal(RangeDefect, "value out of range: " & $i & " notin " & $a & " .. " & $b)
  29. proc raiseRangeErrorF(i, a, b: float) {.compilerproc, noinline.} =
  30. when defined(standalone):
  31. sysFatal(RangeDefect, "value out of range")
  32. else:
  33. sysFatal(RangeDefect, "value out of range: " & $i & " notin " & $a & " .. " & $b)
  34. proc raiseRangeErrorU(i, a, b: uint64) {.compilerproc, noinline.} =
  35. # todo: better error reporting
  36. sysFatal(RangeDefect, "value out of range")
  37. proc raiseRangeErrorNoArgs() {.compilerproc, noinline.} =
  38. sysFatal(RangeDefect, "value out of range")
  39. proc raiseObjectConversionError() {.compilerproc, noinline.} =
  40. sysFatal(ObjectConversionDefect, "invalid object conversion")
  41. proc chckIndx(i, a, b: int): int =
  42. if i >= a and i <= b:
  43. return i
  44. else:
  45. raiseIndexError3(i, a, b)
  46. proc chckRange(i, a, b: int): int =
  47. if i >= a and i <= b:
  48. return i
  49. else:
  50. raiseRangeError(i)
  51. proc chckRange64(i, a, b: int64): int64 {.compilerproc.} =
  52. if i >= a and i <= b:
  53. return i
  54. else:
  55. raiseRangeError(i)
  56. proc chckRangeU(i, a, b: uint64): uint64 {.compilerproc.} =
  57. if i >= a and i <= b:
  58. return i
  59. else:
  60. sysFatal(RangeDefect, "value out of range")
  61. proc chckRangeF(x, a, b: float): float =
  62. if x >= a and x <= b:
  63. return x
  64. else:
  65. when hostOS == "standalone":
  66. sysFatal(RangeDefect, "value out of range")
  67. else:
  68. sysFatal(RangeDefect, "value out of range: ", $x)
  69. proc chckNil(p: pointer) =
  70. if p == nil:
  71. sysFatal(NilAccessDefect, "attempt to write to a nil address")
  72. proc chckNilDisp(p: pointer) {.compilerproc.} =
  73. if p == nil:
  74. sysFatal(NilAccessDefect, "cannot dispatch; dispatcher is nil")
  75. when not defined(nimV2):
  76. proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
  77. # checks if obj is of type subclass:
  78. var x = obj
  79. if x == subclass: return # optimized fast path
  80. while x != subclass:
  81. if x == nil:
  82. sysFatal(ObjectConversionDefect, "invalid object conversion")
  83. x = x.base
  84. proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} =
  85. if a != b:
  86. sysFatal(ObjectAssignmentDefect, "invalid object assignment")
  87. type ObjCheckCache = array[0..1, PNimType]
  88. proc isObjSlowPath(obj, subclass: PNimType;
  89. cache: var ObjCheckCache): bool {.noinline.} =
  90. # checks if obj is of type subclass:
  91. var x = obj.base
  92. while x != subclass:
  93. if x == nil:
  94. cache[0] = obj
  95. return false
  96. x = x.base
  97. cache[1] = obj
  98. return true
  99. proc isObjWithCache(obj, subclass: PNimType;
  100. cache: var ObjCheckCache): bool {.compilerproc, inline.} =
  101. if obj == subclass: return true
  102. if obj.base == subclass: return true
  103. if cache[0] == obj: return false
  104. if cache[1] == obj: return true
  105. return isObjSlowPath(obj, subclass, cache)
  106. proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
  107. # checks if obj is of type subclass:
  108. var x = obj
  109. if x == subclass: return true # optimized fast path
  110. while x != subclass:
  111. if x == nil: return false
  112. x = x.base
  113. return true
  114. when defined(nimV2):
  115. proc raiseObjectCaseTransition() {.compilerproc.} =
  116. sysFatal(FieldDefect, "assignment to discriminant changes object branch")