From 098b1c10c56fadb5982ae279454e079bd6543c0c Mon Sep 17 00:00:00 2001 From: visualfc Date: Thu, 7 Jul 2022 16:33:54 +0800 Subject: [PATCH] repl: eval const --- constant/constant.go | 13 ++++--- repl.go | 85 +++++++++++++++++++++++++------------------- 2 files changed, 55 insertions(+), 43 deletions(-) diff --git a/constant/constant.go b/constant/constant.go index ffa03ac8..ee56bea4 100644 --- a/constant/constant.go +++ b/constant/constant.go @@ -58,10 +58,8 @@ func ExactConstantEx(c constant.Value, toFloat bool) (s string, exact bool) { if !ok { panic(fmt.Errorf("parser rat %q error", s)) } - if v, ok := r.Float64(); ok { - return fmt.Sprintf("%v", v), false - } - return r.FloatString(10), false + v, _ := r.Float64() + return fmt.Sprintf("%v", v), false } return s, true } @@ -76,9 +74,10 @@ func ExactConstantEx(c constant.Value, toFloat bool) (s string, exact bool) { } return s, true case constant.Complex: - re, e1 := ExactConstantEx(constant.Real(c), toFloat) - im, e2 := ExactConstantEx(constant.Imag(c), toFloat) - return fmt.Sprintf("%v+%vi", re, im), e1 && e2 + return c.ExactString(), true + // re, e1 := ExactConstantEx(constant.Real(c), toFloat) + // im, e2 := ExactConstantEx(constant.Imag(c), toFloat) + // return fmt.Sprintf("%v+%vi", re, im), e1 && e2 default: panic("unreachable") } diff --git a/repl.go b/repl.go index 9f680150..cf9ca9e8 100644 --- a/repl.go +++ b/repl.go @@ -3,12 +3,13 @@ package igop import ( "fmt" "go/ast" + "go/constant" "go/scanner" "go/token" "go/types" - "strconv" "strings" + xconst "github.com/goplus/igop/constant" "golang.org/x/tools/go/ssa" ) @@ -128,6 +129,7 @@ func main() { func (r *Repl) eval(tok token.Token, expr string) (err error) { var src string var inMain bool + var evalConst bool switch tok { case token.PACKAGE: // skip package @@ -192,11 +194,15 @@ func (r *Repl) eval(tok token.Token, expr string) (err error) { fixed = append(fixed, "__igop_repl_used__(&"+v+")") // fixed = append(fixed, "__igop_repl_dump__("+v+")") } else if strings.HasSuffix(e.Msg, errIsNotUsed) { - if c, ok := extractConstant([]byte(e.Msg[:len(e.Msg)-len(errIsNotUsed)])); ok { - r.lastDump = []string{c.Lit} - return nil + if _, ok := extractConstant([]byte(e.Msg[:len(e.Msg)-len(errIsNotUsed)])); ok { + // r.lastDump = []string{c.Lit} + // return nil + expr = "const __igop_repl_const__ = " + expr + tok = token.CONST + evalConst = true + } else { + expr = "__igop_repl_dump__(" + expr + ")" } - expr = "__igop_repl_dump__(" + expr + ")" } else { return e } @@ -210,16 +216,44 @@ func (r *Repl) eval(tok token.Token, expr string) (err error) { if err != nil { return err } - err = r.run() + i, err := newInterp(r.ctx, r.pkg, r.globalMap) + if err != nil { + return err + } + rinit, err := r.runFunc(i, "init", r.fsInit) if err == nil { - if inMain { - r.infuncs = append(r.infuncs, expr) + rinit.pc-- + } + rmain, err := r.runFunc(i, "main", r.fsMain) + if err != nil { + return err + } + if evalConst { + m, _ := i.mainpkg.Members["__igop_repl_const__"] + c, _ := m.(*ssa.NamedConst) + s, _ := xconst.ExactConstantEx(c.Value.Value, true) + kind := c.Value.Value.Kind() + if kind == constant.Float { + es := c.Value.Value.ExactString() + r.lastDump = []string{fmt.Sprintf("%v %v\n(%v)", s, c.Type(), es)} } else { - r.globals = append(r.globals, expr) + r.lastDump = []string{fmt.Sprintf("%v %v", s, c.Type())} } - r.source = src + return nil + } + r.interp = i + r.fsInit = rinit + r.fsMain = rmain + for k, v := range i.globals { + r.globalMap[k.String()] = v } - return err + if inMain { + r.infuncs = append(r.infuncs, expr) + } else { + r.globals = append(r.globals, expr) + } + r.source = src + return nil } const ( @@ -261,28 +295,6 @@ func (r *Repl) firstToken(src string) token.Token { return tok } -func (repl *Repl) run() error { - i, err := newInterp(repl.ctx, repl.pkg, repl.globalMap) - if err != nil { - return err - } - rinit, err := repl.runFunc(i, "init", repl.fsInit) - if err == nil { - repl.fsInit = rinit - repl.fsInit.pc-- - } - rmain, err := repl.runFunc(i, "main", repl.fsMain) - if err != nil { - return err - } - repl.fsMain = rmain - repl.interp = i - for k, v := range i.globals { - repl.globalMap[k.String()] = v - } - return nil -} - type fnState struct { fr *frame pc int @@ -375,10 +387,11 @@ func extractConstant(src []byte) (constant *tokenLit, ok bool) { case token.INT: return nodes[0], true case token.FLOAT: + return nodes[0], true // extract if not parse float64 - if _, err := strconv.ParseFloat(nodes[0].Lit, 128); err != nil { - return nodes[0], true - } + // if _, err := strconv.ParseFloat(nodes[0].Lit, 128); err != nil { + // return nodes[0], true + // } } default: last := nodes[len(nodes)-1]