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)
}
}
fmt.Println("sexp.readIn hit weird EOF")
return errors.New("unexpected EOF in sexp.readIn")
}
// 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 {
switch t.t {
case closeParenToken:
return nil, false, errors.New("unexpected EOF in read")
return nil, errors.New("unexpected close paren in read")
case openParenToken:
s := newSexp()
if err := s.readIn(c); err != nil {
return nil, true, err
return nil, err
}
return s, false, nil
return s, nil
default:
v, err := atom(t)
return v, false, err
return atom(t)
}
}
return nil, false, io.EOF
return nil, io.EOF
}
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) {
for {
v, _, err := parse(c)
v, err := parse(c)
switch err {
case io.EOF:
return

@ -3,14 +3,48 @@ package main
import (
"./cm"
"bufio"
"errors"
"fmt"
"io"
"net"
"strings"
)
const MAX_SEXP_LINES = 40
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) {
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 {
select {
case v := <-out:
@ -18,10 +52,35 @@ func tcpInterpreter(conn net.Conn, userinput chan string, out chan interface{},
case err := <-errors:
fmt.Fprintf(conn, "error: %v", err)
case line := <-userinput:
tokens := make(chan token, 32)
// this is probably dumb
go lexs(line+"\n", tokens)
go evalall(tokens, out, errors, universe)
if errorMode {
skipLine(line)
break
}
lineDepth := depth(line)
currentDepth += lineDepth
if len(lines) == 0 && lineDepth == 0 {
tokens := make(chan token, 32)
go lexs(line+"\n", tokens)
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