aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTing-Wei Lan <tingwei.lan@cobinhood.com>2019-02-23 17:47:20 +0800
committerJhih-Ming Huang <jm.huang@cobinhood.com>2019-04-11 10:39:58 +0800
commitebe075ef5928fc5e4d50aafd34f07a70bd02b469 (patch)
treee33c7accf6802da69fe79420a91bc253be135b3c
parent5245db1f425ffb50f1a3a5b6381559fb693ae39a (diff)
downloaddexon-ebe075ef5928fc5e4d50aafd34f07a70bd02b469.tar.gz
dexon-ebe075ef5928fc5e4d50aafd34f07a70bd02b469.tar.zst
dexon-ebe075ef5928fc5e4d50aafd34f07a70bd02b469.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.go80
-rw-r--r--core/vm/sqlvm/cmd/ast-printer/main.go16
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)
}