diff options
author | Ting-Wei Lan <tingwei.lan@cobinhood.com> | 2019-02-23 17:47:20 +0800 |
---|---|---|
committer | Jhih-Ming Huang <jm.huang@cobinhood.com> | 2019-05-06 10:44:04 +0800 |
commit | 3274f055838e0bbc499a24ac58e06a4604d0a322 (patch) | |
tree | 410dd752e6eeb8597e59c72a03285bf3ea19f786 | |
parent | 7628271e5d363a9a7283efb6f7d8b1b52e392e45 (diff) | |
download | dexon-3274f055838e0bbc499a24ac58e06a4604d0a322.tar.gz dexon-3274f055838e0bbc499a24ac58e06a4604d0a322.tar.zst dexon-3274f055838e0bbc499a24ac58e06a4604d0a322.zip |
core: vm: sqlvm: ast: handle error in AST printer
Catch the error reported by fmt.Fprintf and report it to the caller.
-rw-r--r-- | core/vm/sqlvm/ast/printer.go | 80 | ||||
-rw-r--r-- | core/vm/sqlvm/cmd/ast-printer/main.go | 16 |
2 files changed, 63 insertions, 33 deletions
diff --git a/core/vm/sqlvm/ast/printer.go b/core/vm/sqlvm/ast/printer.go index 4800fc86b..ac4c43fe0 100644 --- a/core/vm/sqlvm/ast/printer.go +++ b/core/vm/sqlvm/ast/printer.go @@ -36,21 +36,19 @@ func formatString(s string) string { } func printAST(w io.Writer, n interface{}, s []byte, prefix string, - detail bool, depth int) { + detail bool, depth int) (int, error) { indent := strings.Repeat(prefix, depth) indentLong := strings.Repeat(prefix, depth+1) if n == nil { - fmt.Fprintf(w, "%snil\n", indent) - return + return fmt.Fprintf(w, "%snil\n", indent) } typeOf := reflect.TypeOf(n) valueOf := reflect.ValueOf(n) kind := typeOf.Kind() if kind == reflect.Ptr { if valueOf.IsNil() { - fmt.Fprintf(w, "%snil\n", indent) - return + return fmt.Fprintf(w, "%snil\n", indent) } valueOf = valueOf.Elem() typeOf = typeOf.Elem() @@ -60,30 +58,37 @@ func printAST(w io.Writer, n interface{}, s []byte, prefix string, if stringer, ok := n.(fmt.Stringer); ok { s := stringer.String() - fmt.Fprintf(w, "%s%s\n", indent, formatString(s)) - return + return fmt.Fprintf(w, "%s%s\n", indent, formatString(s)) } if s, ok := n.(string); ok { - fmt.Fprintf(w, "%s%s\n", indent, formatString(s)) - return + return fmt.Fprintf(w, "%s%s\n", indent, formatString(s)) } if bs, ok := n.([]byte); ok { - fmt.Fprintf(w, "%s%s\n", indent, formatBytes(bs)) - return + return fmt.Fprintf(w, "%s%s\n", indent, formatBytes(bs)) } if kind == reflect.Slice { l := valueOf.Len() if l == 0 { - fmt.Fprintf(w, "%s[]\n", indent) - return + return fmt.Fprintf(w, "%s[]\n", indent) + } + + var bytesWritten int + b, err := fmt.Fprintf(w, "%s[\n", indent) + bytesWritten += b + if err != nil { + return bytesWritten, err } - fmt.Fprintf(w, "%s[\n", indent) for i := 0; i < l; i++ { v := valueOf.Index(i) - printAST(w, v.Interface(), s, prefix, detail, depth+1) + b, err = printAST(w, v.Interface(), s, prefix, detail, depth+1) + bytesWritten += b + if err != nil { + return bytesWritten, err + } } - fmt.Fprintf(w, "%s]\n", indent) - return + b, err = fmt.Fprintf(w, "%s]\n", indent) + bytesWritten += b + return bytesWritten, err } if kind == reflect.Struct { type field struct { @@ -127,25 +132,44 @@ func printAST(w io.Writer, n interface{}, s []byte, prefix string, } } - fmt.Fprintf(w, "%s%s", indent, name) + var bytesWritten int + b, err := fmt.Fprintf(w, "%s%s", indent, name) + bytesWritten += b + if err != nil { + return bytesWritten, err + } if len(fields) == 0 { - fmt.Fprintf(w, " {} // %s\n", position) - return + b, err = fmt.Fprintf(w, " {} // %s\n", position) + bytesWritten += b + return bytesWritten, err + } + b, err = fmt.Fprintf(w, " { // %s\n", position) + bytesWritten += b + if err != nil { + return bytesWritten, err } - fmt.Fprintf(w, " { // %s\n", position) for i := 0; i < len(fields); i++ { - fmt.Fprintf(w, "%s%s:\n", indentLong, fields[i].name) - printAST(w, fields[i].value, s, prefix, detail, depth+2) + b, err = fmt.Fprintf(w, "%s%s:\n", indentLong, fields[i].name) + bytesWritten += b + if err != nil { + return bytesWritten, err + } + b, err = printAST(w, fields[i].value, s, prefix, detail, depth+2) + bytesWritten += b + if err != nil { + return bytesWritten, err + } } - fmt.Fprintf(w, "%s}\n", indent) - return + b, err = fmt.Fprintf(w, "%s}\n", indent) + bytesWritten += b + return bytesWritten, err } - fmt.Fprintf(w, "%s%+v\n", indent, valueOf.Interface()) + return fmt.Fprintf(w, "%s%+v\n", indent, valueOf.Interface()) } // PrintAST prints AST for debugging. func PrintAST(output io.Writer, node interface{}, source []byte, - indent string, detail bool) { + indent string, detail bool) (int, error) { - printAST(output, node, source, indent, detail, 0) + return printAST(output, node, source, indent, detail, 0) } diff --git a/core/vm/sqlvm/cmd/ast-printer/main.go b/core/vm/sqlvm/cmd/ast-printer/main.go index 33710f2b0..d62cb4fc8 100644 --- a/core/vm/sqlvm/cmd/ast-printer/main.go +++ b/core/vm/sqlvm/cmd/ast-printer/main.go @@ -15,12 +15,18 @@ func main() { flag.Parse() + fmt.Fprintf(os.Stderr, "detail: %t\n", detail) s := []byte(flag.Arg(0)) - n, err := parser.Parse(s) - fmt.Printf("detail: %t\n", detail) - if err != nil { - fmt.Fprintf(os.Stderr, "err:\n%+v\n", err) + n, parseErr := parser.Parse(s) + b, printErr := ast.PrintAST(os.Stdout, n, s, " ", detail) + if parseErr != nil { + fmt.Fprintf(os.Stderr, "Parse error:\n%+v\n", parseErr) + } + if printErr != nil { + fmt.Fprintf(os.Stderr, "Print error:\n%+v\n", printErr) + } + fmt.Fprintf(os.Stderr, "Output size: %d bytes\n", b) + if parseErr != nil || printErr != nil { os.Exit(1) } - ast.PrintAST(os.Stdout, n, s, " ", detail) } |