You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
2.4 KiB
Go

package main
import (
"bufio"
"flag"
"fmt"
"io"
"net"
"os"
)
var tcpAddr = flag.String("tcp", "", "foo")
func args() {
flag.Parse()
if *tcpAddr != "" {
runTCPServer()
return
}
filename := flag.Args()[1]
f, err := os.Open(filename)
if err != nil {
fmt.Fprintln(os.Stderr, "unable to read file ", filename)
os.Exit(1)
}
defer f.Close()
out, errors := make(chan interface{}), make(chan error)
go defaultInterpreter(out, errors)
c := make(chan token, 32)
go lex(bufio.NewReader(f), c)
evalall(c, out, errors, universe)
}
func printErrorMsg(message string) {
io.WriteString(os.Stderr, message)
}
func die(message string) {
printErrorMsg(message)
os.Exit(2)
}
func tcpInterpreter(conn net.Conn, out chan interface{}, errors chan error) {
for {
select {
case v := <-out:
fmt.Fprintln(conn, v)
case err := <-errors:
fmt.Fprintf(conn, "error: %v", err)
}
}
}
func startConnection(conn net.Conn, c, d chan net.Conn) {
c <- conn
defer func() { d <- conn }()
disconnect := func() {
fmt.Println("disconnected")
}
out, errors := make(chan interface{}), make(chan error)
go tcpInterpreter(conn, out, errors)
r := bufio.NewReader(conn)
for {
if _, err := io.WriteString(conn, "> "); err != nil {
disconnect()
return
}
line, prefix, err := r.ReadLine()
if prefix {
fmt.Println("(prefix)")
}
switch err {
case nil:
break
case io.EOF:
disconnect()
return
default:
printErrorMsg(err.Error())
disconnect()
return
}
tokens := make(chan token, 32)
go lexs(string(line)+"\n", tokens)
evalall(tokens, out, errors, universe)
}
}
var activeConnections = make([]net.Conn, 0, 10)
func removeConnection(conn net.Conn) {
for i, other := range activeConnections {
if conn.RemoteAddr() == other.RemoteAddr() {
activeConnections = append(activeConnections[:i], activeConnections[i+1:]...)
return
}
}
}
func manageConnections(connect, disconnect chan net.Conn) {
for {
select {
case conn := <-connect:
activeConnections = append(activeConnections, conn)
case conn := <-disconnect:
removeConnection(conn)
}
}
}
func runTCPServer() {
connect, disconnect := make(chan net.Conn), make(chan net.Conn)
go manageConnections(connect, disconnect)
ln, err := net.Listen("tcp", *tcpAddr)
if err != nil {
die(err.Error())
}
for {
conn, err := ln.Accept()
if err != nil {
printErrorMsg(err.Error())
continue
}
go startConnection(conn, connect, disconnect)
}
}