errorhandling.nim 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2021 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## This module contains support code for new-styled error
  10. ## handling via an `nkError` node kind.
  11. import ast, renderer, options, types
  12. import std/strutils
  13. when defined(nimPreviewSlimSystem):
  14. import std/assertions
  15. type
  16. ErrorKind* = enum ## expand as you need.
  17. RawTypeMismatchError
  18. ExpressionCannotBeCalled
  19. CustomError
  20. WrongNumberOfArguments
  21. AmbiguousCall
  22. proc errorSubNode*(n: PNode): PNode =
  23. case n.kind
  24. of nkEmpty..nkNilLit:
  25. result = nil
  26. of nkError:
  27. result = n
  28. else:
  29. result = nil
  30. for i in 0..<n.len:
  31. result = errorSubNode(n[i])
  32. if result != nil: break
  33. proc newError*(wrongNode: PNode; k: ErrorKind; args: varargs[PNode]): PNode =
  34. assert wrongNode.kind != nkError
  35. let innerError = errorSubNode(wrongNode)
  36. if innerError != nil:
  37. return innerError
  38. var idgen = idGeneratorForPackage(-1'i32)
  39. result = newNodeIT(nkError, wrongNode.info, newType(tyError, idgen, nil))
  40. result.add wrongNode
  41. result.add newIntNode(nkIntLit, ord(k))
  42. for a in args: result.add a
  43. proc newError*(wrongNode: PNode; msg: string): PNode =
  44. assert wrongNode.kind != nkError
  45. let innerError = errorSubNode(wrongNode)
  46. if innerError != nil:
  47. return innerError
  48. var idgen = idGeneratorForPackage(-1'i32)
  49. result = newNodeIT(nkError, wrongNode.info, newType(tyError, idgen, nil))
  50. result.add wrongNode
  51. result.add newIntNode(nkIntLit, ord(CustomError))
  52. result.add newStrNode(msg, wrongNode.info)
  53. proc errorToString*(config: ConfigRef; n: PNode): string =
  54. assert n.kind == nkError
  55. assert n.len > 1
  56. let wrongNode = n[0]
  57. case ErrorKind(n[1].intVal)
  58. of RawTypeMismatchError:
  59. result = "type mismatch"
  60. of ExpressionCannotBeCalled:
  61. result = "expression '$1' cannot be called" % wrongNode[0].renderTree
  62. of CustomError:
  63. result = n[2].strVal
  64. of WrongNumberOfArguments:
  65. result = "wrong number of arguments"
  66. of AmbiguousCall:
  67. let a = n[2].sym
  68. let b = n[3].sym
  69. var args = "("
  70. for i in 1..<wrongNode.len:
  71. if i > 1: args.add(", ")
  72. args.add(typeToString(wrongNode[i].typ))
  73. args.add(")")
  74. result = "ambiguous call; both $1 and $2 match for: $3" % [
  75. getProcHeader(config, a),
  76. getProcHeader(config, b),
  77. args]