errorhandling.nim 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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, strutils, types
  12. when defined(nimPreviewSlimSystem):
  13. import std/assertions
  14. type
  15. ErrorKind* = enum ## expand as you need.
  16. RawTypeMismatchError
  17. ExpressionCannotBeCalled
  18. CustomError
  19. WrongNumberOfArguments
  20. AmbiguousCall
  21. proc errorSubNode*(n: PNode): PNode =
  22. case n.kind
  23. of nkEmpty..nkNilLit:
  24. result = nil
  25. of nkError:
  26. result = n
  27. else:
  28. result = nil
  29. for i in 0..<n.len:
  30. result = errorSubNode(n[i])
  31. if result != nil: break
  32. proc newError*(wrongNode: PNode; k: ErrorKind; args: varargs[PNode]): PNode =
  33. assert wrongNode.kind != nkError
  34. let innerError = errorSubNode(wrongNode)
  35. if innerError != nil:
  36. return innerError
  37. result = newNodeIT(nkError, wrongNode.info, newType(tyError, ItemId(module: -1, item: -1), nil))
  38. result.add wrongNode
  39. result.add newIntNode(nkIntLit, ord(k))
  40. for a in args: result.add a
  41. proc newError*(wrongNode: PNode; msg: string): PNode =
  42. assert wrongNode.kind != nkError
  43. let innerError = errorSubNode(wrongNode)
  44. if innerError != nil:
  45. return innerError
  46. result = newNodeIT(nkError, wrongNode.info, newType(tyError, ItemId(module: -1, item: -1), nil))
  47. result.add wrongNode
  48. result.add newIntNode(nkIntLit, ord(CustomError))
  49. result.add newStrNode(msg, wrongNode.info)
  50. proc errorToString*(config: ConfigRef; n: PNode): string =
  51. assert n.kind == nkError
  52. assert n.len > 1
  53. let wrongNode = n[0]
  54. case ErrorKind(n[1].intVal)
  55. of RawTypeMismatchError:
  56. result = "type mismatch"
  57. of ExpressionCannotBeCalled:
  58. result = "expression '$1' cannot be called" % wrongNode[0].renderTree
  59. of CustomError:
  60. result = n[2].strVal
  61. of WrongNumberOfArguments:
  62. result = "wrong number of arguments"
  63. of AmbiguousCall:
  64. let a = n[2].sym
  65. let b = n[3].sym
  66. var args = "("
  67. for i in 1..<wrongNode.len:
  68. if i > 1: args.add(", ")
  69. args.add(typeToString(wrongNode[i].typ))
  70. args.add(")")
  71. result = "ambiguous call; both $1 and $2 match for: $3" % [
  72. getProcHeader(config, a),
  73. getProcHeader(config, b),
  74. args]