Skip to content

Commit f261296

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 01b7ac4 + 50cd487 commit f261296

File tree

19 files changed

+1148
-141
lines changed

19 files changed

+1148
-141
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ It includes:
1414
* lexer
1515
* parser
1616
* compiler
17-
* interactive mode (REPL)
17+
* interactive mode (REPL) ([try online!](https://gpython.org))
1818

1919
It does not include very many python modules as many of the core
2020
modules are written in C not python. The converted modules are:

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
module github.com/go-python/gpython
22

3-
require github.com/peterh/liner v1.1.0
3+
require (
4+
github.com/gopherjs/gopherwasm v1.0.0 // indirect
5+
github.com/peterh/liner v1.1.0
6+
)

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c h1:16eHWuMGvCjSfgRJKqIzapE78onvvTbdi1rMkU00lZw=
2+
github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
3+
github.com/gopherjs/gopherwasm v1.0.0 h1:32nge/RlujS1Im4HNCJPp0NbBOAeBXFuT1KonUuLl+Y=
4+
github.com/gopherjs/gopherwasm v1.0.0/go.mod h1:SkZ8z7CWBz5VXbhJel8TxCmAcsQqzgWGR/8nMhyhZSI=
15
github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
26
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
37
github.com/peterh/liner v1.1.0 h1:f+aAedNJA6uk7+6rXsYBnhdo4Xux7ESLe+kcuVUF5os=

main.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import (
1212
"runtime/pprof"
1313

1414
_ "github.com/go-python/gpython/builtin"
15-
"github.com/go-python/gpython/repl"
15+
"github.com/go-python/gpython/repl/cli"
16+
1617
//_ "github.com/go-python/gpython/importlib"
1718
"io/ioutil"
1819
"log"
@@ -62,7 +63,7 @@ func main() {
6263
args := flag.Args()
6364
py.MustGetModule("sys").Globals["argv"] = pysys.MakeArgv(args)
6465
if len(args) == 0 {
65-
repl.Run()
66+
cli.RunREPL()
6667
return
6768
}
6869
prog := args[0]

py/complex.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package py
88

99
import (
10+
"fmt"
1011
"math"
1112
"math/cmplx"
1213
)
@@ -60,6 +61,14 @@ func convertToComplex(other Object) (Complex, bool) {
6061
return 0, false
6162
}
6263

64+
func (a Complex) M__str__() (Object, error) {
65+
return String(fmt.Sprintf("(%g%+gj)", real(complex128(a)), imag(complex128(a)))), nil
66+
}
67+
68+
func (a Complex) M__repr__() (Object, error) {
69+
return a.M__str__()
70+
}
71+
6372
func (a Complex) M__neg__() (Object, error) {
6473
return -a, nil
6574
}
@@ -286,6 +295,24 @@ func (a Complex) M__ge__(other Object) (Object, error) {
286295
return a.M__lt__(other)
287296
}
288297

298+
// Properties
299+
func init() {
300+
ComplexType.Dict["real"] = &Property{
301+
Fget: func(self Object) (Object, error) {
302+
return Float(real(self.(Complex))), nil
303+
},
304+
}
305+
ComplexType.Dict["imag"] = &Property{
306+
Fget: func(self Object) (Object, error) {
307+
return Float(imag(self.(Complex))), nil
308+
},
309+
}
310+
ComplexType.Dict["conjugate"] = MustNewMethod("conjugate", func(self Object) (Object, error) {
311+
cnj := cmplx.Conj(complex128(self.(Complex)))
312+
return Complex(cnj), nil
313+
}, 0, "conjugate() -> Returns the complex conjugate.")
314+
}
315+
289316
// Check interface is satisfied
290317
var _ floatArithmetic = Complex(complex(0, 0))
291318
var _ richComparison = Complex(0)

py/tests/complex.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Copyright 2018 The go-python Authors. All rights reserved.
2+
# Use of this source code is governed by a BSD-style
3+
# license that can be found in the LICENSE file.
4+
5+
from libtest import assertRaises
6+
7+
doc="str"
8+
assert str(3+4j) == "(3+4j)"
9+
10+
doc="repr"
11+
assert repr(3+4j) == "(3+4j)"
12+
13+
doc="real"
14+
assert (3+4j).real == 3.0
15+
16+
doc="imag"
17+
assert (3+4j).imag == 4.0
18+
19+
doc="conjugate"
20+
assert (3+4j).conjugate() == 3-4j
21+
22+
doc="add"
23+
assert (3+4j) + 2 == 5+4j
24+
assert (3+4j) + 2j == 3+6j
25+
26+
doc="sub"
27+
assert (3+4j) - 1 == 2+4j
28+
assert (3+4j) - 1j == 3+3j
29+
30+
doc="mul"
31+
assert (3+4j) * 2 == 6+8j
32+
assert (3+4j) * 2j == -8+6j
33+
34+
doc="finished"

repl/cli/cli.go

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// Copyright 2018 The go-python Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Read Eval Print Loop for CLI
6+
package cli
7+
8+
import (
9+
"fmt"
10+
"io"
11+
"os"
12+
"os/user"
13+
"path/filepath"
14+
15+
"github.com/go-python/gpython/py"
16+
"github.com/go-python/gpython/repl"
17+
"github.com/peterh/liner"
18+
)
19+
20+
const HistoryFileName = ".gpyhistory"
21+
22+
// homeDirectory finds the home directory or returns ""
23+
func homeDirectory() string {
24+
usr, err := user.Current()
25+
if err == nil {
26+
return usr.HomeDir
27+
}
28+
// Fall back to reading $HOME - work around user.Current() not
29+
// working for cross compiled binaries on OSX.
30+
// https://github.com/golang/go/issues/6376
31+
return os.Getenv("HOME")
32+
}
33+
34+
// Holds state for readline services
35+
type readline struct {
36+
*liner.State
37+
repl *repl.REPL
38+
historyFile string
39+
module *py.Module
40+
prompt string
41+
}
42+
43+
// newReadline creates a new instance of readline
44+
func newReadline(repl *repl.REPL) *readline {
45+
rl := &readline{
46+
State: liner.NewLiner(),
47+
repl: repl,
48+
}
49+
home := homeDirectory()
50+
if home != "" {
51+
rl.historyFile = filepath.Join(home, HistoryFileName)
52+
}
53+
rl.SetTabCompletionStyle(liner.TabPrints)
54+
rl.SetWordCompleter(rl.Completer)
55+
return rl
56+
}
57+
58+
// readHistory reads the history into the term
59+
func (rl *readline) ReadHistory() error {
60+
f, err := os.Open(rl.historyFile)
61+
if err != nil {
62+
return err
63+
}
64+
defer f.Close()
65+
_, err = rl.State.ReadHistory(f)
66+
if err != nil {
67+
return err
68+
}
69+
return nil
70+
}
71+
72+
// writeHistory writes the history from the term
73+
func (rl *readline) WriteHistory() error {
74+
f, err := os.OpenFile(rl.historyFile, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
75+
if err != nil {
76+
return err
77+
}
78+
defer f.Close()
79+
_, err = rl.State.WriteHistory(f)
80+
if err != nil {
81+
return err
82+
}
83+
return nil
84+
}
85+
86+
// Close the readline and write history
87+
func (rl *readline) Close() error {
88+
err := rl.State.Close()
89+
if err != nil {
90+
return err
91+
}
92+
if rl.historyFile != "" {
93+
err := rl.WriteHistory()
94+
if err != nil {
95+
return err
96+
}
97+
}
98+
return nil
99+
}
100+
101+
// Completer takes the currently edited line with the cursor
102+
// position and returns the completion candidates for the partial word
103+
// to be completed. If the line is "Hello, wo!!!" and the cursor is
104+
// before the first '!', ("Hello, wo!!!", 9) is passed to the
105+
// completer which may returns ("Hello, ", {"world", "Word"}, "!!!")
106+
// to have "Hello, world!!!".
107+
func (rl *readline) Completer(line string, pos int) (head string, completions []string, tail string) {
108+
return rl.repl.Completer(line, pos)
109+
}
110+
111+
// SetPrompt sets the current terminal prompt
112+
func (rl *readline) SetPrompt(prompt string) {
113+
rl.prompt = prompt
114+
}
115+
116+
// Print prints the output
117+
func (rl *readline) Print(out string) {
118+
_, _ = os.Stdout.WriteString(out + "\n")
119+
}
120+
121+
// RunREPL starts the REPL loop
122+
func RunREPL() {
123+
repl := repl.New()
124+
rl := newReadline(repl)
125+
repl.SetUI(rl)
126+
defer rl.Close()
127+
err := rl.ReadHistory()
128+
if err != nil {
129+
fmt.Printf("Failed to open history: %v\n", err)
130+
}
131+
132+
fmt.Printf("Gpython 3.4.0\n")
133+
134+
for {
135+
line, err := rl.Prompt(rl.prompt)
136+
if err != nil {
137+
if err == io.EOF {
138+
fmt.Printf("\n")
139+
break
140+
}
141+
fmt.Printf("Problem reading line: %v\n", err)
142+
continue
143+
}
144+
if line != "" {
145+
rl.AppendHistory(line)
146+
}
147+
rl.repl.Run(line)
148+
}
149+
}

0 commit comments

Comments
 (0)