holy crap, I had it so wrong before

good god, the original implementation was just... wrong.  Soooo, so
fucking wrong I can't even fathom it.
master
Jordan Orelli 12 years ago
parent cf73b5fec0
commit 4e12cefbba

@ -7,7 +7,6 @@ import (
"github.com/jordanorelli/skeam/cm" "github.com/jordanorelli/skeam/cm"
"io" "io"
"net" "net"
"strings"
) )
const MAX_SEXP_LINES = 40 const MAX_SEXP_LINES = 40
@ -15,127 +14,70 @@ const MAX_SEXP_LINES = 40
var manager = cm.New() var manager = cm.New()
var errSexpTooLong = errors.New("error: sexp is too long") var errSexpTooLong = errors.New("error: sexp is too long")
func depth(s string) int { type tcpInterpreter struct {
n := 0 fout io.Writer // buffered file-like output stream
for _, r := range s { ferr io.Writer // buffered file-like error stream
switch r { tokens chan token // tokens returns from the lexer
case '(': values chan interface{} // values returned from the interpreter
n += 1 errors chan error // errors returned from the interpreter
case ')':
n -= 1
case ';':
return n
}
}
return n
} }
func tcpInterpreter(conn net.Conn, userinput chan string, out chan interface{}, errors chan error) { func runTCPServer() {
lines := make([]string, 0, MAX_SEXP_LINES) addr, err := net.ResolveTCPAddr("tcp", *tcpAddr)
currentDepth := 0 if err != nil {
addLine := func(line string) error { die(err.Error())
if len(lines) >= MAX_SEXP_LINES {
return errSexpTooLong
}
lines = append(lines, line+"\n")
return nil
}
errorMode := false
skipLine := func(line string) {
currentDepth += depth(line)
if currentDepth == 0 {
errorMode = false
}
}
s := make(chan string)
go func() {
for program := range s {
tokens := make(chan token, 32)
go lexs(program, tokens)
evalall(tokens, out, errors, universe)
} }
}() ln, err := net.ListenTCP("tcp", addr)
go func() { if err != nil {
for v := range out { die(err.Error())
fmt.Fprintln(conn, v)
} }
}()
for { for {
select { conn, err := ln.AcceptTCP()
case err := <-errors: if err != nil {
fmt.Fprintf(conn, "error: %v\n", err) printErrorMsg(err.Error())
case line := <-userinput: continue
if errorMode {
skipLine(line)
break
} }
lineDepth := depth(line) go startConnection(conn, manager)
currentDepth += lineDepth
if currentDepth < 0 {
lines = lines[:0]
currentDepth = 0
break
} }
}
if len(lines) == 0 && lineDepth == 0 { func newTcpInterpreter() *tcpInterpreter {
s <- line + "\n" return &tcpInterpreter{
break tokens: make(chan token),
values: make(chan interface{}),
errors: make(chan error),
} }
}
if err := addLine(line); err != nil { func (t *tcpInterpreter) send() {
errorMode = true for {
lines = lines[:0] select {
currentDepth = 0 case v := <-t.values:
break if _, err := fmt.Fprintln(t.fout, v); err != nil {
fmt.Println("can't write out to client: ", err)
} }
case e := <-t.errors:
if currentDepth == 0 { if _, err := fmt.Fprintln(t.ferr, e); err != nil {
program := strings.Join(append(lines, "\n"), " ") fmt.Println("can't write error to client: ", err)
lines = lines[:0]
s <- program
} }
} }
} }
} }
func runTCPServer() { func (t *tcpInterpreter) Run(in io.Reader, out, errors io.Writer) {
ln, err := net.Listen("tcp", *tcpAddr) go lex(bufio.NewReader(in), t.tokens)
if err != nil {
die(err.Error()) t.fout = out
} t.ferr = errors
for { go t.send()
conn, err := ln.Accept()
if err != nil { evalall(t.tokens, t.values, t.errors, universe)
printErrorMsg(err.Error())
continue
}
go startConnection(conn, manager)
}
} }
func startConnection(conn net.Conn, m *cm.Manager) { func startConnection(conn net.Conn, m *cm.Manager) {
m.Add(conn) m.Add(conn)
defer m.Remove(conn) defer m.Remove(conn)
out, errors := make(chan interface{}), make(chan error) i := newTcpInterpreter()
userinput := make(chan string) i.Run(conn, conn, conn)
go tcpInterpreter(conn, userinput, out, errors)
r := bufio.NewReader(conn)
for {
line, _, err := r.ReadLine()
switch err {
case nil:
break
case io.EOF:
io.WriteString(conn, "<eof>")
return
default:
printErrorMsg(err.Error())
return
}
userinput <- string(line)
}
} }

Loading…
Cancel
Save