added very sloppy tcp functionality

can now send multi-line sexps over TCP.  Max line limit is 40 lines in a
single sexp.  A max needed to be selected to prevent clients from
filling up enormous buffers.
master
Jordan Orelli 11 years ago
parent d672d51f7d
commit e11bcf3d91

@ -137,27 +137,27 @@ func (s *sexp) readIn(c chan token) error {
s.append(v) s.append(v)
} }
} }
fmt.Println("sexp.readIn hit weird EOF")
return errors.New("unexpected EOF in sexp.readIn") return errors.New("unexpected EOF in sexp.readIn")
} }
// parses one value that can be evaled from the channel // parses one value that can be evaled from the channel
func parse(c chan token) (interface{}, bool, error) { func parse(c chan token) (interface{}, error) {
for t := range c { for t := range c {
switch t.t { switch t.t {
case closeParenToken: case closeParenToken:
return nil, false, errors.New("unexpected EOF in read") return nil, errors.New("unexpected close paren in read")
case openParenToken: case openParenToken:
s := newSexp() s := newSexp()
if err := s.readIn(c); err != nil { if err := s.readIn(c); err != nil {
return nil, true, err return nil, err
} }
return s, false, nil return s, nil
default: default:
v, err := atom(t) return atom(t)
return v, false, err
} }
} }
return nil, false, io.EOF return nil, io.EOF
} }
func eval(v interface{}, env *environment) (interface{}, error) { func eval(v interface{}, env *environment) (interface{}, error) {
@ -210,7 +210,7 @@ func eval(v interface{}, env *environment) (interface{}, error) {
func evalall(c chan token, out chan interface{}, e chan error, env *environment) { func evalall(c chan token, out chan interface{}, e chan error, env *environment) {
for { for {
v, _, err := parse(c) v, err := parse(c)
switch err { switch err {
case io.EOF: case io.EOF:
return return

@ -3,14 +3,48 @@ package main
import ( import (
"./cm" "./cm"
"bufio" "bufio"
"errors"
"fmt" "fmt"
"io" "io"
"net" "net"
"strings"
) )
const MAX_SEXP_LINES = 40
var manager = cm.New() var manager = cm.New()
var errSexpTooLong = errors.New("error: sexp is too long")
func depth(s string) int {
n := 0
for _, r := range s {
switch r {
case '(':
n += 1
case ')':
n -= 1
}
}
return n
}
func tcpInterpreter(conn net.Conn, userinput chan string, out chan interface{}, errors chan error) { func tcpInterpreter(conn net.Conn, userinput chan string, out chan interface{}, errors chan error) {
lines := make([]string, 0, MAX_SEXP_LINES)
currentDepth := 0
addLine := func(line string) error {
if len(lines) >= MAX_SEXP_LINES {
return errSexpTooLong
}
lines = append(lines, line)
return nil
}
errorMode := false
skipLine := func(line string) {
currentDepth += depth(line)
if currentDepth == 0 {
errorMode = false
}
}
for { for {
select { select {
case v := <-out: case v := <-out:
@ -18,10 +52,35 @@ func tcpInterpreter(conn net.Conn, userinput chan string, out chan interface{},
case err := <-errors: case err := <-errors:
fmt.Fprintf(conn, "error: %v", err) fmt.Fprintf(conn, "error: %v", err)
case line := <-userinput: case line := <-userinput:
if errorMode {
skipLine(line)
break
}
lineDepth := depth(line)
currentDepth += lineDepth
if len(lines) == 0 && lineDepth == 0 {
tokens := make(chan token, 32) tokens := make(chan token, 32)
// this is probably dumb
go lexs(line+"\n", tokens) go lexs(line+"\n", tokens)
go evalall(tokens, out, errors, universe) go evalall(tokens, out, errors, universe)
break
}
if err := addLine(line); err != nil {
fmt.Fprintf(conn, "error in addLine: %v", err)
errorMode = true
lines = lines[:0]
currentDepth = 0
break
}
if currentDepth == 0 {
runnable := strings.Join(lines, " ")
lines = lines[:0]
tokens := make(chan token, 32)
go lexs(runnable+"\n", tokens)
go evalall(tokens, out, errors, universe)
}
} }
} }
} }

Loading…
Cancel
Save