chcks.nim 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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(RangeError, "value out of range")
  14. else:
  15. sysFatal(RangeError, "value out of range: ", $val)
  16. proc raiseIndexError3(i, a, b: int) {.compilerproc, noinline.} =
  17. sysFatal(IndexError, formatErrorIndexBound(i, a, b))
  18. proc raiseIndexError2(i, n: int) {.compilerproc, noinline.} =
  19. sysFatal(IndexError, formatErrorIndexBound(i, n))
  20. proc raiseIndexError() {.compilerproc, noinline.} =
  21. sysFatal(IndexError, "index out of bounds")
  22. proc raiseFieldError(f: string) {.compilerproc, noinline.} =
  23. sysFatal(FieldError, f, " is not accessible")
  24. proc chckIndx(i, a, b: int): int =
  25. if i >= a and i <= b:
  26. return i
  27. else:
  28. raiseIndexError3(i, a, b)
  29. proc chckRange(i, a, b: int): int =
  30. if i >= a and i <= b:
  31. return i
  32. else:
  33. raiseRangeError(i)
  34. proc chckRange64(i, a, b: int64): int64 {.compilerproc.} =
  35. if i >= a and i <= b:
  36. return i
  37. else:
  38. raiseRangeError(i)
  39. proc chckRangeU(i, a, b: uint64): uint64 {.compilerproc.} =
  40. if i >= a and i <= b:
  41. return i
  42. else:
  43. sysFatal(RangeError, "value out of range")
  44. proc chckRangeF(x, a, b: float): float =
  45. if x >= a and x <= b:
  46. return x
  47. else:
  48. when hostOS == "standalone":
  49. sysFatal(RangeError, "value out of range")
  50. else:
  51. sysFatal(RangeError, "value out of range: ", $x)
  52. proc chckNil(p: pointer) =
  53. if p == nil:
  54. sysFatal(NilAccessError, "attempt to write to a nil address")
  55. proc chckNilDisp(p: pointer) {.compilerproc.} =
  56. if p == nil:
  57. sysFatal(NilAccessError, "cannot dispatch; dispatcher is nil")
  58. when not defined(nimV2):
  59. proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
  60. # checks if obj is of type subclass:
  61. var x = obj
  62. if x == subclass: return # optimized fast path
  63. while x != subclass:
  64. if x == nil:
  65. sysFatal(ObjectConversionError, "invalid object conversion")
  66. x = x.base
  67. proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} =
  68. if a != b:
  69. sysFatal(ObjectAssignmentError, "invalid object assignment")
  70. type ObjCheckCache = array[0..1, PNimType]
  71. proc isObjSlowPath(obj, subclass: PNimType;
  72. cache: var ObjCheckCache): bool {.noinline.} =
  73. # checks if obj is of type subclass:
  74. var x = obj.base
  75. while x != subclass:
  76. if x == nil:
  77. cache[0] = obj
  78. return false
  79. x = x.base
  80. cache[1] = obj
  81. return true
  82. proc isObjWithCache(obj, subclass: PNimType;
  83. cache: var ObjCheckCache): bool {.compilerProc, inline.} =
  84. if obj == subclass: return true
  85. if obj.base == subclass: return true
  86. if cache[0] == obj: return false
  87. if cache[1] == obj: return true
  88. return isObjSlowPath(obj, subclass, cache)
  89. proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
  90. # checks if obj is of type subclass:
  91. var x = obj
  92. if x == subclass: return true # optimized fast path
  93. while x != subclass:
  94. if x == nil: return false
  95. x = x.base
  96. return true
  97. when defined(nimV2):
  98. proc nimFieldDiscriminantCheckV2(oldDiscVal, newDiscVal: uint8) {.compilerProc.} =
  99. if oldDiscVal != newDiscVal:
  100. sysFatal(FieldError, "assignment to discriminant changes object branch")