error.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*
  2. * ECAL
  3. *
  4. * Copyright 2020 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the MIT
  7. * License, If a copy of the MIT License was not distributed with this
  8. * file, You can obtain one at https://opensource.org/licenses/MIT.
  9. */
  10. /*
  11. Package util contains utility definitions and functions for the event condition language ECAL.
  12. */
  13. package util
  14. import (
  15. "errors"
  16. "fmt"
  17. "devt.de/krotik/ecal/parser"
  18. )
  19. /*
  20. TraceableRuntimeError can record and show a stack trace.
  21. */
  22. type TraceableRuntimeError interface {
  23. error
  24. /*
  25. AddTrace adds a trace step.
  26. */
  27. AddTrace(*parser.ASTNode)
  28. /*
  29. GetTrace returns the current stacktrace.
  30. */
  31. GetTrace() []*parser.ASTNode
  32. /*
  33. GetTrace returns the current stacktrace as a string.
  34. */
  35. GetTraceString() []string
  36. }
  37. /*
  38. RuntimeError is a runtime related error.
  39. */
  40. type RuntimeError struct {
  41. Source string // Name of the source which was given to the parser
  42. Type error // Error type (to be used for equal checks)
  43. Detail string // Details of this error
  44. Node *parser.ASTNode // AST Node where the error occurred
  45. Line int // Line of the error
  46. Pos int // Position of the error
  47. Trace []*parser.ASTNode // Stacktrace
  48. }
  49. /*
  50. Runtime related error types.
  51. */
  52. var (
  53. ErrRuntimeError = errors.New("Runtime error")
  54. ErrUnknownConstruct = errors.New("Unknown construct")
  55. ErrInvalidConstruct = errors.New("Invalid construct")
  56. ErrInvalidState = errors.New("Invalid state")
  57. ErrVarAccess = errors.New("Cannot access variable")
  58. ErrNotANumber = errors.New("Operand is not a number")
  59. ErrNotABoolean = errors.New("Operand is not a boolean")
  60. ErrNotAList = errors.New("Operand is not a list")
  61. ErrNotAMap = errors.New("Operand is not a map")
  62. ErrNotAListOrMap = errors.New("Operand is not a list nor a map")
  63. ErrSink = errors.New("Error in sink")
  64. // ErrReturn is not an error. It is used to return when executing a function
  65. ErrReturn = errors.New("*** return ***")
  66. // Error codes for loop operations
  67. ErrIsIterator = errors.New("Function is an iterator")
  68. ErrEndOfIteration = errors.New("End of iteration was reached")
  69. ErrContinueIteration = errors.New("End of iteration step - Continue iteration")
  70. )
  71. /*
  72. NewRuntimeError creates a new RuntimeError object.
  73. */
  74. func NewRuntimeError(source string, t error, d string, node *parser.ASTNode) error {
  75. if node.Token != nil {
  76. return &RuntimeError{source, t, d, node, node.Token.Lline, node.Token.Lpos, nil}
  77. }
  78. return &RuntimeError{source, t, d, node, 0, 0, nil}
  79. }
  80. /*
  81. Error returns a human-readable string representation of this error.
  82. */
  83. func (re *RuntimeError) Error() string {
  84. ret := fmt.Sprintf("ECAL error in %s: %v (%v)", re.Source, re.Type, re.Detail)
  85. if re.Line != 0 {
  86. // Add line if available
  87. ret = fmt.Sprintf("%s (Line:%d Pos:%d)", ret, re.Line, re.Pos)
  88. }
  89. return ret
  90. }
  91. /*
  92. AddTrace adds a trace step.
  93. */
  94. func (re *RuntimeError) AddTrace(n *parser.ASTNode) {
  95. re.Trace = append(re.Trace, n)
  96. }
  97. /*
  98. GetTrace returns the current stacktrace.
  99. */
  100. func (re *RuntimeError) GetTrace() []*parser.ASTNode {
  101. return re.Trace
  102. }
  103. /*
  104. GetTrace returns the current stacktrace as a string.
  105. */
  106. func (re *RuntimeError) GetTraceString() []string {
  107. res := []string{}
  108. for _, t := range re.GetTrace() {
  109. pp, _ := parser.PrettyPrint(t)
  110. res = append(res, fmt.Sprintf("%v (%v:%v)", pp, t.Token.Lsource, t.Token.Lline))
  111. }
  112. return res
  113. }
  114. /*
  115. RuntimeErrorWithDetail is a runtime error with additional environment information.
  116. */
  117. type RuntimeErrorWithDetail struct {
  118. *RuntimeError
  119. Environment parser.Scope
  120. Data interface{}
  121. }