Skip to content

Commit

Permalink
multiple: Implement fmt.Stringer for a Bunch of Types (#117)
Browse files Browse the repository at this point in the history
* wdte: Implement `fmt.Stringer` for `GoFunc`, `Scope`, and `ScopedFunc`.

Also, switch to `strings.Builder`. Go 1.11 is out now, so I don't think
I have to worry too much about compatability problems. Hopefully.

* wdte: Implement `fmt.Stringer` for `Array` and tweak `Scope.String()`.

* std/io: Implement `fmt.Stringer` for `Reader` and `Writer`.

Also, clarify the documentation for those types a bit.

* std/io: Implement special `fmt.Stringer` handling for std{in,out,err}.

* std/io: Actually use stdout for stdout.

Holy crud. How long has that bug been there?

* std/io: Defer the `fmt.Stringer` implementation upwards for std{in,out,err}.

This removes the specialness of the handling.

* std/io: Fix a typo.

* std/io/file: Implement `fmt.Stringer` for `File`.

* std/stream: Implement a very basic `fmt.Stringer` for every type.

* std/arrays: Implement `fmt.Stringer` for the `Stream` implementation.
  • Loading branch information
DeedleFake authored Sep 14, 2018
1 parent b6892aa commit d7d6392
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 21 deletions.
4 changes: 4 additions & 0 deletions std/arrays/arrays.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ func (a *streamer) Next(frame wdte.Frame) (wdte.Func, bool) { // nolint
return r, true
}

func (a *streamer) String() string { // nolint
return "<stream>"
}

// Scope is a scope containing the functions in this package.
var Scope = wdte.S().Map(map[wdte.ID]wdte.Func{
"append": wdte.GoFunc(Append),
Expand Down
5 changes: 5 additions & 0 deletions std/io/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package file

import (
"fmt"
"os"

"github.com/DeedleFake/wdte"
Expand All @@ -17,6 +18,10 @@ func (f File) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func { // nolint
return f
}

func (f File) String() string { // nolint
return fmt.Sprintf("<file %q>", f.Name())
}

// Open is a WDTE function with the following signature:
//
// open path
Expand Down
74 changes: 64 additions & 10 deletions std/io/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,53 @@ import (

// These variables are what are returned by the corresponding
// functions in this package. If a client wants to globally redirect
// input or output, them may simply change these variables.
// input or output, they may simply change these variables.
var (
Stdin io.Reader = os.Stdin
Stdout io.Writer = os.Stdout
Stderr io.Writer = os.Stderr
)

func stdin(frame wdte.Frame, args ...wdte.Func) wdte.Func {
return Reader{Stdin}
type stdin struct{}

func (r stdin) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func {
return r
}

func (stdin) Read(buf []byte) (int, error) {
return Stdin.Read(buf)
}

func (stdin) String() string {
return "<reader(stdin)>"
}

type stdout struct{}

func (w stdout) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func {
return w
}

func (stdout) Write(data []byte) (int, error) {
return Stdout.Write(data)
}

func (stdout) String() string {
return "<writer(stdout)>"
}

func stdout(frame wdte.Frame, args ...wdte.Func) wdte.Func {
return Writer{Stderr}
type stderr struct{}

func (w stderr) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func {
return w
}

func (stderr) Write(data []byte) (int, error) {
return Stderr.Write(data)
}

func stderr(frame wdte.Frame, args ...wdte.Func) wdte.Func {
return Writer{Stderr}
func (stderr) String() string {
return "<writer(stderr)>"
}

type reader interface {
Expand All @@ -42,6 +72,10 @@ type reader interface {

// Reader wraps an io.Reader, allowing it to be used as a WDTE
// function.
//
// Note that using this specific type is not necessary. Any wdte.Func
// that implements io.Reader is also accepted by the functions in this
// module.
type Reader struct {
io.Reader
}
Expand All @@ -50,13 +84,25 @@ func (r Reader) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func { // nolint
return r
}

func (r Reader) String() string { // nolint
if inner, ok := r.Reader.(fmt.Stringer); ok {
return inner.String()
}

return "<reader>"
}

type writer interface {
wdte.Func
io.Writer
}

// Writer wraps an io.Writer, allowing it to be used as a WDTE
// function.
//
// Note that using this specific type is not necessary. Any wdte.Func
// that implements io.Writer is also accepted by the functions in this
// module.
type Writer struct {
io.Writer
}
Expand All @@ -65,6 +111,14 @@ func (w Writer) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func { // nolint
return w
}

func (w Writer) String() string { // nolint
if inner, ok := w.Writer.(fmt.Stringer); ok {
return inner.String()
}

return "<writer>"
}

// Seek is a WDTE function with the following signatures:
//
// seek s n w
Expand Down Expand Up @@ -514,9 +568,9 @@ func Writeln(frame wdte.Frame, args ...wdte.Func) wdte.Func {

// Scope is a scope containing the functions in this package.
var Scope = wdte.S().Map(map[wdte.ID]wdte.Func{
"stdin": wdte.GoFunc(stdin),
"stdout": wdte.GoFunc(stdout),
"stderr": wdte.GoFunc(stderr),
"stdin": stdin{},
"stdout": stdout{},
"stderr": stderr{},

"seek": wdte.GoFunc(Seek),
"close": wdte.GoFunc(Close),
Expand Down
12 changes: 12 additions & 0 deletions std/stream/middle.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ func (m *mapper) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func { // nolint
return m
}

func (m *mapper) String() string { // nolint
return "<stream>"
}

type filter struct {
f wdte.Func
}
Expand Down Expand Up @@ -85,6 +89,10 @@ func (f filter) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func { // nolint
return f
}

func (f filter) String() string { // nolint
return "<stream>"
}

type flatMapper struct {
m wdte.Func
}
Expand Down Expand Up @@ -149,6 +157,10 @@ func (m *flatMapper) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func { // no
return m
}

func (m *flatMapper) String() string { // nolint
return "<stream>"
}

// Enumerate is a WDTE function with the following signature:
//
// enumerate s
Expand Down
8 changes: 8 additions & 0 deletions std/stream/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ func (a *array) Next(frame wdte.Frame) (wdte.Func, bool) { // nolint
return r, true
}

func (a *array) String() string { // nolint
return "<stream>"
}

// An rng (range) is a stream that yields successive numbers.
type rng struct {
// i is the next number to return.
Expand Down Expand Up @@ -128,6 +132,10 @@ func (r *rng) Next(frame wdte.Frame) (wdte.Func, bool) { // nolint
return n, true
}

func (r *rng) String() string { // nolint
return "<stream>"
}

// Concat is a WDTE function with the following signatures:
//
// concat s ...
Expand Down
4 changes: 4 additions & 0 deletions std/stream/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ func (n NextFunc) Next(frame wdte.Frame) (wdte.Func, bool) { // nolint
return n(frame)
}

func (NextFunc) String() string { // nolint
return "<stream>"
}

// Scope is a scope containing the functions in this package.
var Scope = wdte.S().Map(map[wdte.ID]wdte.Func{
"new": wdte.GoFunc(New),
Expand Down
16 changes: 16 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package wdte
import (
"bytes"
"fmt"
"strings"
)

// A Comparer is a Func that is able to be compared to other
Expand Down Expand Up @@ -120,6 +121,21 @@ func (a Array) At(i Func) (Func, bool) { // nolint
return nil, false
}

func (a Array) String() string { // nolint
var buf strings.Builder

buf.WriteByte('[')
var pre string
for _, f := range a {
buf.WriteString(pre)
fmt.Fprint(&buf, f)
pre = "; "
}
buf.WriteByte(']')

return buf.String()
}

//func (a Array)Compare(other Func) (int, bool) {
// TODO: Implement this. I'm not sure if it should support ordering
// or not. I'm also not sure if it should call its elements in order
Expand Down
44 changes: 33 additions & 11 deletions wdte.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package wdte

import (
"bytes"
"context"
"fmt"
"io"
"sort"
"unsafe"
"strings"

"github.com/DeedleFake/wdte/ast"
)
Expand Down Expand Up @@ -349,15 +348,29 @@ func (s *Scope) Call(frame Frame, args ...Func) Func { // nolint
return s
}

func (s *Scope) String() string { // nolint
return fmt.Sprint(s.Known())
}

func (s *Scope) At(i Func) (Func, bool) { // nolint
v := s.Get(ID(i.(String)))
return v, v != nil
}

func (s *Scope) String() string { // nolint
var buf strings.Builder

buf.WriteByte('[')
var pre string
for _, id := range s.Known() {
buf.WriteString(pre)
buf.WriteString(string(id))
buf.WriteString(": ")
fmt.Fprint(&buf, s.Get(id))

pre = "; "
}
buf.WriteByte(']')

return buf.String()
}

// A GoFunc is an implementation of Func that calls a Go function.
// This is the easiest way to implement lower-level systems for WDTE
// scripts to make use of.
Expand Down Expand Up @@ -404,6 +417,10 @@ func (f GoFunc) Call(frame Frame, args ...Func) (r Func) { // nolint
return f(frame, args...)
}

func (f GoFunc) String() string { // nolint
return "<go func>"
}

// A FuncCall is an unevaluated function call. This is usually the
// right-hand side of a function declaration, but could also be any of
// various pieces of switches, compounds, or arrays.
Expand Down Expand Up @@ -580,6 +597,14 @@ func (f ScopedFunc) Call(frame Frame, args ...Func) Func { // nolint
return f.Func.Call(frame.WithScope(f.Scope), args...)
}

func (f ScopedFunc) String() string {
if inner, ok := f.Func.(fmt.Stringer); ok {
return inner.String()
}

return fmt.Sprint(f.Func)
}

// A Memo wraps another function, caching the results of calls with
// the same arguments.
type Memo struct {
Expand Down Expand Up @@ -707,9 +732,7 @@ func (lambda *Lambda) Call(frame Frame, args ...Func) Func { // nolint
}

func (lambda *Lambda) String() string { // nolint
// Could use strings.Builder, but then it'll only work on Go 10+...

var buf bytes.Buffer
var buf strings.Builder

fmt.Fprintf(&buf, "(@ %v", lambda.ID)
for _, arg := range lambda.Args {
Expand All @@ -718,8 +741,7 @@ func (lambda *Lambda) String() string { // nolint
}
buf.WriteString(" => ...)")

raw := buf.Bytes()
return *(*string)(unsafe.Pointer(&raw))
return buf.String()
}

// A Let is an expression that maps an expression to an ID. It's used
Expand Down

0 comments on commit d7d6392

Please sign in to comment.