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.

92 lines
1.8 KiB
Go

package main
import (
"bufio"
"fmt"
"io"
)
func eval(v interface{}, env *environment) (interface{}, error) {
if v == nil {
return &sexp{}, nil
}
switch t := v.(type) {
case symbol:
return t.eval(env)
case *sexp:
return t.eval(env)
default:
debugPrint("default eval")
return v, nil
}
panic("not reached")
}
type interpreter struct {
in io.Reader // reader of input source code
out1 io.Writer // writer of evaluated values
out2 io.Writer // writer of error info
tokens chan token // tokens returns from the lexer (internal only)
values chan interface{} // values returned from the interpreter (internal only)
errors chan error // errors returned from the interpreter (internal only)
}
func newInterpreter(in io.Reader, out1, out2 io.Writer) *interpreter {
return &interpreter{
in: in,
out1: out1,
out2: out2,
tokens: make(chan token),
values: make(chan interface{}),
errors: make(chan error),
}
}
func (i interpreter) run(env *environment) {
go lex(bufio.NewReader(i.in), i.tokens)
go i.send()
for {
v, err := parse(i.tokens)
switch err {
case io.EOF:
return
case nil:
i.eval(v, env)
default:
i.errors <- err
}
}
}
func (i interpreter) eval(v interface{}, env *environment) {
val, err := eval(v, env)
if err != nil {
i.errors <- err
return
}
i.values <- val
}
func (i interpreter) send() {
for {
select {
case v := <-i.values:
if i.out1 == nil {
return
}
if _, err := fmt.Fprintln(i.out1, v); err != nil {
fmt.Println("can't write out to client: ", err)
}
case e := <-i.errors:
if i.out2 == nil {
return
}
if _, err := fmt.Fprintln(i.out2, e); err != nil {
fmt.Println("can't write error to client: ", err)
}
}
}
}