Fixes comment lexing, adds tls to net-conn, adds timeout to net-conn, adds read-all-lines

This commit is contained in:
sloum 2021-07-27 22:45:52 -07:00
parent cb561e0b8d
commit 940624fa6a
6 changed files with 172 additions and 31 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
slope
*.slo

View File

@ -111,11 +111,6 @@ Implemented:
`net-conn`
Not implemented, but on my radar:
`net-conn-tls`
\*the general write, read, and close operations in the IO section apply to net objects as well as files and string buffers

View File

@ -1,6 +1,7 @@
package main
import (
"fmt"
"strings"
"unicode"
)
@ -148,8 +149,14 @@ func Tokenize(s string) []string {
case '"':
currentString = eatString(reader)
tokens = append(tokens, currentString)
case '#':
case ';':
eatSingleLineComment(reader)
case '#':
c, _, err := reader.ReadRune()
if err != nil {
break TokenizationLoop
}
tokens = append(tokens, fmt.Sprintf("#%c", c))
default:
reader.UnreadRune()
currentString = eatSymbol(reader)

182
lib.go
View File

@ -2,6 +2,7 @@ package main
import (
"bufio"
"crypto/tls"
"fmt"
"io"
"io/ioutil"
@ -11,6 +12,7 @@ import (
"reflect"
"strconv"
"strings"
"time"
)
var stdLibrary = vars{
@ -513,6 +515,9 @@ var stdLibrary = vars{
case *net.Conn:
(*ft).Write([]byte(stringOut))
return a[1].(*IOHandle)
case *tls.Conn:
ft.Write([]byte(stringOut))
return a[1].(*IOHandle)
default:
return false
}
@ -536,6 +541,9 @@ var stdLibrary = vars{
case *net.Conn:
(*ft).Write([]byte(String(a[0])))
return a[1].(*IOHandle)
case *tls.Conn:
ft.Write([]byte([]byte(String(a[0]))))
return a[1].(*IOHandle)
default:
return false
}
@ -571,8 +579,54 @@ var stdLibrary = vars{
return false
}
return string(b)
case *tls.Conn:
b, err := ioutil.ReadAll(f)
if err != nil {
return false
}
return string(b)
default:
panic("'read-line' has not been implemented for this object type")
panic("'read-all' has not been implemented for this object type")
}
}
},
"read-all-lines": func(a ...expression) expression {
if len(a) == 0 {
reader := bufio.NewReader(os.Stdin)
text, err := reader.ReadString('\n')
if err != nil {
return false
}
return strings.SplitN(text[:len(text)-1], "\n", -1)
} else {
obj, ok := a[0].(*IOHandle)
if !ok {
panic("'read-all-lines' expected an IO handle as its argument, but was not given an IO handle")
}
if !obj.Open {
panic("'read-all-lines' was given an IO handle that is already closed")
}
switch f := obj.Obj.(type) {
case *os.File:
b, err := ioutil.ReadAll(f)
if err != nil {
return false
}
return strings.SplitN(string(b), "\n", -1)
case *net.Conn:
b, err := ioutil.ReadAll(*f)
if err != nil {
return false
}
return strings.SplitN(string(b), "\n", -1)
case *tls.Conn:
b, err := ioutil.ReadAll(f)
if err != nil {
return false
}
return strings.SplitN(string(b), "\n", -1)
default:
panic("'read-all' has not been implemented for this object type")
}
}
},
@ -633,6 +687,26 @@ var stdLibrary = vars{
}
}
return o.String()
case *tls.Conn:
var o strings.Builder
for {
b := make([]byte, 1)
n, err := (*f).Read(b)
if n > 0 {
if b[0] == '\n' {
break
}
o.Write(b)
}
if err != nil && err != io.EOF && o.Len() == 0 {
return false
} else if err != nil && err == io.EOF {
return symbol("EOF")
} else if err != nil {
break
}
}
return o.String()
default:
panic("'read-line' has not been implemented for this object type")
}
@ -814,6 +888,8 @@ var stdLibrary = vars{
o.Close()
case *net.Conn:
(*o).Close()
case *tls.Conn:
o.Close()
default:
panic("'close' encountered an unsupported IO handle type")
}
@ -851,15 +927,77 @@ var stdLibrary = vars{
if !ok {
panic("'net-conn' expects a host as a string, a non-string value was given")
}
port, ok := a[1].(string)
if !ok {
var port string
switch p := a[1].(type) {
case string:
port = p
case number:
port = strconv.Itoa(int(p))
default:
panic("'net-conn' expects a port as a string, a non-string value was given")
}
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%s", host, port))
if err != nil {
return false
usetls := false
if len(a) >= 3 {
t, ok := a[2].(bool)
if !ok {
panic("'net-conn' expects a boolean value as the third argument (use-tls), a non-bool value was given")
}
usetls = t
}
timeout := -1
if len(a) >= 4 {
switch to := a[3].(type) {
case number:
timeout = int(to)
case string:
t, err := strconv.Atoi(to)
if err != nil {
panic("'net-conn' was given a timeout string that does not cast to an integer")
}
timeout = t
default:
panic("'net-conn' expects a string or number value representing a timeout, in seconds; a non-string non-number value was given ")
}
}
var conn net.Conn
var tlsconn *tls.Conn
var err error
addr := fmt.Sprintf("%s:%s", host, port)
if usetls {
conf := &tls.Config{InsecureSkipVerify: true}
if timeout > 0 {
tlsconn, err = tls.DialWithDialer(&net.Dialer{Timeout: time.Duration(timeout)*time.Second}, "tcp", addr, conf)
if err != nil {
return false
}
} else {
tlsconn, err = tls.Dial("tcp", addr, conf)
if err != nil {
return false
}
}
} else {
if timeout > 0 {
conn, err = net.DialTimeout("tcp", addr, time.Duration(timeout) * time.Second)
if err != nil {
return false
}
} else {
conn, err = net.Dial("tcp", addr)
if err != nil {
return false
}
}
}
// based on the tls value use tls or not, same with the timeout value for adding a timeout
var handle *IOHandle
if usetls {
handle = &IOHandle{tlsconn, true}
} else {
handle = &IOHandle{&conn, true}
}
handle := &IOHandle{&conn, true}
openFiles = append(openFiles, handle)
return handle
},
@ -944,9 +1082,9 @@ IO Based:
[x] write (should do stdout by default, or accept a file, buf, or conn)
[x] write-raw (same as write, but does not unescape strings)
[x] read-line (defaults to stdin, or takes a file or conn)
[ ] read-all (takes a file or conn as argument)
[x] read-all (takes a file or conn as argument)
[ ] read-bytes (takes a file or conn)
[ ] read-all-lines (takes a file or conn)
[x] read-all-lines (takes a file or conn)
[x] file-create (overwrites existing, returns *File || bool)
[x] file-open-read (returns *file || bool, file is set to read only)
[x] file-open-write (returns *file || bool, file is set to read only)
@ -956,23 +1094,21 @@ IO Based:
Net Based:
[x] net-conn
- url-host
- url-port
- url-scheme
- url-path
- url-query
- url-set-host
- url-set-port
- url-set-query
- url-set-path
[ ] http-get
[ ] http-post
[ ] url-host
[ ] url-port
[ ] url-scheme
[ ] url-path
[ ] url-query
[ ] url-set-host
[ ] url-set-port
[ ] url-set-query
[ ] url-set-path
System Based:
[x] exit
[ ] env-get
[ ] env-set
[ ] env-chdir
[ ] environ (can be used to list, get, or set)
[ ] subprocess (may require multiple funcs)
[ ] load (loads a scheme file)
[x] equal? (compares any two things)

View File

@ -2,6 +2,7 @@ package main
import (
"bufio"
"crypto/tls"
"flag"
"fmt"
"io/ioutil"
@ -26,6 +27,9 @@ func SafeExit(code int) {
case *net.Conn:
(*o).Close()
openFiles[i].Open = false
case *tls.Conn:
o.Close()
openFiles[i].Open = false
}
}
os.Exit(code)

View File

@ -1,2 +0,0 @@
I am some text
I am more text