Skip to content
This repository was archived by the owner on Mar 23, 2023. It is now read-only.

Implementation of raw_input() #233

Merged
merged 15 commits into from
Feb 18, 2017
38 changes: 38 additions & 0 deletions runtime/builtin_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package grumpy

import (
"bufio"
"fmt"
"math/big"
"os"
Expand Down Expand Up @@ -559,6 +560,42 @@ func builtinRange(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException)
return ListType.Call(f, []*Object{r}, nil)
}

func builtinRawInput(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
if len(args) > 1 {
msg := fmt.Sprintf("[raw_]input expcted at most 1 arguments, got %d", len(args))
return nil, f.RaiseType(TypeErrorType, msg)
}

fin := os.Stdin
fout := os.Stdout
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than writing to Stdout directly, you could use the Print() function: Print(f, args, false)

if fin == nil {
msg := fmt.Sprintf("[raw_]input: lost sys.stdin")
return nil, f.RaiseType(RuntimeErrorType, msg)
}

if fout == nil {
msg := fmt.Sprintf("[raw_]input: lost sys.stdout")
return nil, f.RaiseType(RuntimeErrorType, msg)
}

in := bufio.NewReader(fin)
if len(args) == 1 {
prompt, _ := ToStr(f, args[0])
fmt.Fprint(fout, prompt.Value())
}
s, _, _ := in.ReadLine()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReadLine() isn't ideal here because it can return with less than a full line. I think the right thing to do is probably use the grumpy.File object representing sys.stdin and call readLine() on it. But there's no clear way to get the sys module from here.

One possible solution that would be to create Stdin, Stdout and Stderr variables in the grumpy package that wrap os.Stdin/out/err with a grumpy.File object, and then have the sys module expose those instead of creating new files. The grumpy.Print() function could then use the new Stdout object. This isn't perfect but I think it is an improvement over what we have today.


// Todo: Should implement more cases of error.
pySsizeTmax := ((^uint(0)) - 1) >> 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that if len(s) were ever > than this value that Go would panic so don't bother checking this.

size := len(s)
if uint(size) > pySsizeTmax {
msg := fmt.Sprintf("[raw_]input: input too long")
return nil, f.RaiseType(OverflowErrorType, msg)
}

return NewStr(string(s[0:size])).ToObject(), nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this different than NewStr(s)?

}

func builtinRepr(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
if raised := checkFunctionArgs(f, "repr", args, ObjectType); raised != nil {
return nil, raised
Expand Down Expand Up @@ -666,6 +703,7 @@ func init() {
"ord": newBuiltinFunction("ord", builtinOrd).ToObject(),
"print": newBuiltinFunction("print", builtinPrint).ToObject(),
"range": newBuiltinFunction("range", builtinRange).ToObject(),
"raw_input": newBuiltinFunction("raw_input", builtinRawInput).ToObject(),
"repr": newBuiltinFunction("repr", builtinRepr).ToObject(),
"setattr": newBuiltinFunction("setattr", builtinSetAttr).ToObject(),
"sorted": newBuiltinFunction("sorted", builtinSorted).ToObject(),
Expand Down