add client, seek, and size

This commit is contained in:
2023-06-25 00:52:52 +01:00
parent 4ca158cc96
commit 6ff2d7c69f
8 changed files with 244 additions and 7 deletions

2
go.mod
View File

@@ -8,7 +8,7 @@ require (
)
require (
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gabriel-vasile/mimetype v1.4.2
golang.org/x/net v0.8.0 // indirect
)

View File

@@ -9,9 +9,13 @@ func makeGlobal() ArObject {
var vars = anymap{}
vars["global"] = vars
vars["term"] = ArTerm
vars["ArgonVersion"] = ArString(VERSION)
vars["number"] = builtinFunc{"number", ArgonNumber}
vars["string"] = builtinFunc{"string", ArgonString}
vars["socket"] = builtinFunc{"boolean", ArSocket}
vars["socket"] = Map(anymap{
"server": builtinFunc{"server", ArSocketServer},
"client": builtinFunc{"client", ArSocketClient},
})
vars["infinity"] = infinity
vars["map"] = builtinFunc{"map", func(a ...any) (any, ArErr) {
if len(a) == 0 {
@@ -277,5 +281,59 @@ func makeGlobal() ArObject {
}
return nil, ArErr{TYPE: "TypeError", message: "Cannot convert '" + typeof(a[0]) + "' to string", EXISTS: true}
}}
vars["max"] = builtinFunc{"max", func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{TYPE: "runtime Error", message: "max takes 1 argument, got " + fmt.Sprint(len(a)), EXISTS: true}
}
a[0] = ArValidToAny(a[0])
switch x := a[0].(type) {
case []any:
if len(x) == 0 {
return nil, ArErr{TYPE: "runtime Error", message: "max takes a non-empty array", EXISTS: true}
}
var max number
for i, v := range x {
switch m := v.(type) {
case number:
if i == 0 {
max = m
} else {
if m.Cmp(max) == 1 {
max = m
}
}
}
}
return max, ArErr{}
}
return nil, ArErr{TYPE: "TypeError", message: "Cannot get max of type '" + typeof(a[0]) + "'", EXISTS: true}
}}
vars["min"] = builtinFunc{"min", func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{TYPE: "runtime Error", message: "max takes 1 argument, got " + fmt.Sprint(len(a)), EXISTS: true}
}
a[0] = ArValidToAny(a[0])
switch x := a[0].(type) {
case []any:
if len(x) == 0 {
return nil, ArErr{TYPE: "runtime Error", message: "max takes a non-empty array", EXISTS: true}
}
var max number
for i, v := range x {
switch m := v.(type) {
case number:
if i == 0 {
max = m
} else {
if m.Cmp(max) == -1 {
max = m
}
}
}
}
return max, ArErr{}
}
return nil, ArErr{TYPE: "TypeError", message: "Cannot get max of type '" + typeof(a[0]) + "'", EXISTS: true}
}}
return Map(vars)
}

View File

@@ -92,6 +92,30 @@ func ArRead(args ...any) (any, ArErr) {
}
return ArBuffer(bytes), ArErr{}
}},
"seek": builtinFunc{"seek", func(args ...any) (any, ArErr) {
if len(args) != 1 {
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "seek takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
}
if typeof(args[0]) != "number" {
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "seek takes a number not type '" + typeof(args[0]) + "'", EXISTS: true}
}
offset := args[0].(number)
if offset.Denom().Int64() != 1 {
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "seek takes an integer not type '" + typeof(args[0]) + "'", EXISTS: true}
}
_, err := file.Seek(offset.Num().Int64(), io.SeekStart)
if err != nil {
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
}
return nil, ArErr{}
}},
"size": builtinFunc{"size", func(...any) (any, ArErr) {
info, err := file.Stat()
if err != nil {
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
}
return newNumber().SetInt64(info.Size()), ArErr{}
}},
}), ArErr{}
}

View File

@@ -10,6 +10,8 @@ var Args = os.Args[1:]
type stack = []ArObject
const VERSION = "3.0.0"
func newscope() ArObject {
return Map(anymap{})
}

View File

@@ -114,8 +114,9 @@ func parseMap(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool,
}, true, ArErr{}, countIndex
}
var mutex = sync.RWMutex{}
func Map(m anymap) ArObject {
var mutex = sync.RWMutex{}
obj := ArObject{
obj: anymap{
"__value__": m,

View File

@@ -6,7 +6,152 @@ import (
"time"
)
func ArSocket(args ...any) (any, ArErr) {
func ArSocketClient(args ...any) (any, ArErr) {
if len(args) != 2 {
return ArObject{}, ArErr{
TYPE: "SocketError",
message: "Socket takes exactly 2 arguments",
EXISTS: true,
}
} else if typeof(args[0]) != "string" {
return ArObject{}, ArErr{
TYPE: "SocketError",
message: "Socket type must be a string",
EXISTS: true,
}
} else if typeof(args[1]) != "string" {
return ArObject{}, ArErr{
TYPE: "SocketError",
message: "Socket address must be a string",
EXISTS: true,
}
}
networktype := ArValidToAny(args[0]).(string)
address := ArValidToAny(args[1]).(string)
conn, err := net.Dial(networktype, address)
if err != nil {
return ArObject{}, ArErr{
TYPE: "SocketError",
message: fmt.Sprintf("Socket connection failed: %s", err.Error()),
EXISTS: true,
}
}
return ArObject{
obj: anymap{
"read": builtinFunc{
"read",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return ArObject{}, ArErr{
TYPE: "SocketError",
message: "Socket.readData() takes exactly 1 argument",
EXISTS: true,
}
}
if conn == nil {
return ArObject{}, ArErr{
TYPE: "SocketError",
message: "Connection is closed",
EXISTS: true,
}
}
buf := make([]byte, args[0].(number).Num().Int64())
n, err := conn.Read(buf)
if err != nil {
return ArObject{}, ArErr{
TYPE: "SocketError",
message: fmt.Sprintf("Socket read failed: %s", err.Error()),
EXISTS: true,
}
}
return ArBuffer(buf[:n]), ArErr{}
}},
"write": builtinFunc{
"write",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "TypeError",
message: fmt.Sprintf("write() takes exactly 1 argument (%d given)", len(args)),
EXISTS: true,
}
}
if typeof(args[0]) != "buffer" {
return ArObject{}, ArErr{
TYPE: "TypeError",
message: fmt.Sprintf("write() argument must be a buffer, not %s", typeof(args[0])),
EXISTS: true,
}
}
if conn == nil {
return ArObject{}, ArErr{
TYPE: "SocketError",
message: "Connection is closed",
EXISTS: true,
}
}
args[0] = ArValidToAny(args[0])
if typeof(args[0]) != "buffer" {
return ArObject{}, ArErr{
TYPE: "TypeError",
message: fmt.Sprintf("write() argument must be a buffer, not %s", typeof(args[0])),
EXISTS: true,
}
}
_, err := conn.Write(args[0].([]byte))
if err != nil {
return ArObject{}, ArErr{
TYPE: "SocketError",
message: err.Error(),
EXISTS: true,
}
}
return nil, ArErr{}
}},
"close": builtinFunc{
"close",
func(args ...any) (any, ArErr) {
if conn == nil {
return ArObject{}, ArErr{
TYPE: "SocketError",
message: "Connection is already closed",
EXISTS: true,
}
}
err := conn.Close()
if err != nil {
return ArObject{}, ArErr{
TYPE: "SocketError",
message: err.Error(),
EXISTS: true,
}
}
conn = nil
return nil, ArErr{}
},
},
"isClosed": builtinFunc{
"isClosed",
func(args ...any) (any, ArErr) {
if conn == nil {
return true, ArErr{}
}
conn.SetWriteDeadline(time.Now().Add(1 * time.Millisecond))
_, err := conn.Write([]byte{})
conn.SetWriteDeadline(time.Time{})
if err != nil {
conn.Close()
conn = nil
return true, ArErr{}
}
return false, ArErr{}
},
},
}}, ArErr{}
}
func ArSocketServer(args ...any) (any, ArErr) {
if len(args) != 2 {
return ArObject{}, ArErr{
TYPE: "SocketError",

View File

@@ -71,9 +71,6 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i
return resp, worked, err, i
}
}
if isnot(code) {
return parseNot(code, index, codelines, isLine)
}
if isSetVariable(code) {
resp, worked, err, i = parseSetVariable(code, index, codelines, isLine)
if worked {
@@ -121,6 +118,12 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i
return nil, worked, err, step
}
}
if isnot(code) {
resp, worked, err, i = parseNot(code, index, codelines, isLine)
if worked {
return resp, worked, err, i
}
}
if isCall(code) {
resp, worked, err, i = parseCall(code, index, codelines)
if worked {

View File

@@ -18,6 +18,10 @@ func typeof(val any) string {
return "function"
case builtinFunc:
return "function"
case byte:
return "byte"
case []byte:
return "buffer"
case ArObject:
if val, ok := x.obj["__name__"]; ok {
val := ArValidToAny(val)