aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm/sqlvm/errors/errors.go
blob: 922158fe96bcf25088c1895df761583ef624513c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package errors

import (
    "fmt"
    "strconv"
    "strings"
)

// Error collects error information which should be reported to users.
type Error struct {
    // These keys are parts of SQL VM ABI. Database contract callers can
    // obtain values stored in these fields from function return values.
    Position uint32 // Position is the offset in bytes to the error location.
    Category ErrorCategory
    Code     ErrorCode

    // These keys are only used for debugging purposes and not included in ABI.
    // Values stored in these fields are not guaranteed to be stable, so they
    // MUST NOT be returned to the contract caller.
    Token   string // Token is the source code token where the error occurred.
    Prefix  string // Prefix identified the cause of the error.
    Message string // Message provides detailed the error message.
}

func (e Error) Error() string {
    b := strings.Builder{}
    b.WriteString(fmt.Sprintf("offset %d, category %d (%s), code %d (%s)",
        e.Position, e.Category, e.Category, e.Code, e.Code))
    if e.Token != "" {
        b.WriteString(", token ")
        b.WriteString(strconv.Quote(e.Token))
    }
    if e.Prefix != "" {
        b.WriteString(", hint ")
        b.WriteString(strconv.Quote(e.Prefix))
    }
    if e.Message != "" {
        b.WriteString(", message: ")
        b.WriteString(e.Message)
    }
    return b.String()
}

// ErrorList is a list of Error.
type ErrorList []Error

func (e ErrorList) Error() string {
    b := strings.Builder{}
    for i := range e {
        if i > 0 {
            b.WriteByte('\n')
        }
        b.WriteString(e[i].Error())
    }
    return b.String()
}

// ErrorCategory is used to distinguish errors come from different phases.
type ErrorCategory uint16

// Error category starts from 1. Zero value is invalid.
const (
    ErrorCategorNil ErrorCategory = iota
    ErrorCategoryGrammar
    ErrorCategorySemantic
)

var errorCategoryMap = [...]string{
    ErrorCategoryGrammar:  "grammar",
    ErrorCategorySemantic: "semantic",
}

func (c ErrorCategory) Error() string {
    return errorCategoryMap[c]
}

// ErrorCode describes the reason of the error.
type ErrorCode uint16

// Error code starts from 1. Zero value is invalid.
const (
    ErrorCodeNil ErrorCode = iota
    ErrorCodeParser
    ErrorCodeSyntax
    ErrorCodeIntegerRange
    ErrorCodeFractionalPartTooLong
)

var errorCodeMap = [...]string{
    ErrorCodeParser:                "parser error",
    ErrorCodeSyntax:                "syntax error",
    ErrorCodeIntegerRange:          "integer out of range",
    ErrorCodeFractionalPartTooLong: "fractional part too long",
}

func (c ErrorCode) Error() string {
    return errorCodeMap[c]
}