github.com/goplus/igop@v0.25.0/cmd/internal/repl/repl.go (about) 1 /* 2 * Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package repl 18 19 import ( 20 "fmt" 21 "io" 22 "os" 23 "runtime" 24 "strings" 25 26 "github.com/goplus/igop" 27 "github.com/goplus/igop/cmd/internal/base" 28 _ "github.com/goplus/igop/pkg" 29 "github.com/goplus/igop/repl" 30 "github.com/peterh/liner" 31 ) 32 33 // Cmd - igop test 34 var Cmd = &base.Command{ 35 UsageLine: "igop repl", 36 Short: "igop repl mode", 37 } 38 39 var ( 40 flag = &Cmd.Flag 41 flagGoPlus bool 42 flagGoOnly bool 43 flagDumpInstr bool 44 flagTrace bool 45 ) 46 47 func init() { 48 Cmd.Run = runCmd 49 flag.BoolVar(&flagGoPlus, "gop", true, "support Go+ mode") 50 flag.BoolVar(&flagGoOnly, "go", false, "use Go mode only") 51 flag.BoolVar(&flagDumpInstr, "dump", false, "dump SSA instruction code") 52 flag.BoolVar(&flagTrace, "trace", false, "trace interpreter code") 53 } 54 55 // LinerUI implements repl.UI interface. 56 type LinerUI struct { 57 state *liner.State 58 prompt string 59 } 60 61 // SetPrompt is required by repl.UI interface. 62 func (u *LinerUI) SetPrompt(prompt string) { 63 u.prompt = prompt 64 } 65 66 // Printf is required by repl.UI interface. 67 func (u *LinerUI) Printf(format string, a ...interface{}) { 68 fmt.Printf(format, a...) 69 } 70 71 var ( 72 welcomeGo string = fmt.Sprintf("iGo+ v0.9.9 (build %v %v/%v)", runtime.Version(), runtime.GOOS, runtime.GOARCH) 73 ) 74 75 var helpGo string = `Use ?expr to dump expr information 76 Use ?pkg.symbol to dump pkg symbol information 77 Use help() to show help information 78 Use exit() or Ctrl-D to exit` 79 80 var helpGop string = `Use ?expr to dump expr information 81 Use ?pkg.symbol to dump pkg symbol information 82 Use help to show help information 83 Use exit or Ctrl-D to exit` 84 85 var ( 86 gopVersion string 87 supportGoplus bool 88 ) 89 90 func runCmd(cmd *base.Command, args []string) { 91 err := flag.Parse(args) 92 if err != nil { 93 os.Exit(2) 94 } 95 if flagGoOnly { 96 flagGoPlus = false 97 } 98 var help string 99 var welcome string 100 if supportGoplus && flagGoPlus { 101 welcome = welcomeGo + " (Go+ version " + gopVersion + ")" 102 help = helpGop 103 } else { 104 welcome = welcomeGo 105 help = helpGo 106 } 107 fmt.Println(welcome) 108 fmt.Println(help) 109 110 state := liner.NewLiner() 111 defer state.Close() 112 113 // state.SetCtrlCAborts(true) 114 state.SetMultiLineMode(true) 115 state.SetCompleter(func(line string) []string { 116 if strings.TrimSpace(line) == "" { 117 return []string{line + " "} 118 } 119 return nil 120 }) 121 ui := &LinerUI{state: state} 122 var mode igop.Mode 123 if flagDumpInstr { 124 mode |= igop.EnableDumpInstr 125 } 126 if flagTrace { 127 mode |= igop.EnableTracing 128 } 129 var r *repl.REPL 130 igop.RegisterCustomBuiltin("exit", func() { 131 r.Interp().Exit(0) 132 }) 133 igop.RegisterCustomBuiltin("help", func() { 134 fmt.Println(help) 135 }) 136 r = repl.NewREPL(mode) 137 r.SetUI(ui) 138 if supportGoplus && flagGoPlus { 139 r.SetFileName("main.gop") 140 } 141 for { 142 line, err := ui.state.Prompt(ui.prompt) 143 if err != nil { 144 if err == liner.ErrPromptAborted || err == io.EOF { 145 fmt.Printf("exit\n") 146 break 147 } 148 fmt.Printf("Problem reading line: %v\n", err) 149 continue 150 } 151 if strings.TrimSpace(line) == "?" { 152 fmt.Println(help) 153 continue 154 } 155 if line != "" { 156 state.AppendHistory(line) 157 } 158 err = r.Run(line) 159 switch e := err.(type) { 160 case nil: 161 // 162 case igop.ExitError: 163 fmt.Printf("exit %v\n", int(e)) 164 return 165 default: 166 fmt.Printf("error: %v\n", err) 167 } 168 } 169 }