mirror of
https://github.com/Open-Argon/argon-v3.git
synced 2025-12-06 08:56:07 +00:00
add buffer and byte objects, making socket read and write faster
This commit is contained in:
@@ -8,6 +8,10 @@ func AnyToArValid(arr any) any {
|
||||
return ArString(arr)
|
||||
case anymap:
|
||||
return Map(arr)
|
||||
case []byte:
|
||||
return ArBuffer(arr)
|
||||
case byte:
|
||||
return ArByte(arr)
|
||||
default:
|
||||
return arr
|
||||
}
|
||||
|
||||
194
src/buffer.go
Normal file
194
src/buffer.go
Normal file
@@ -0,0 +1,194 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func ArByte(Byte byte) ArObject {
|
||||
obj := ArObject{
|
||||
obj: anymap{
|
||||
"__name__": "byte",
|
||||
"__value__": Byte,
|
||||
},
|
||||
}
|
||||
obj.obj["__string__"] = builtinFunc{
|
||||
"__string__",
|
||||
func(a ...any) (any, ArErr) {
|
||||
return "<byte>", ArErr{}
|
||||
},
|
||||
}
|
||||
obj.obj["__repr__"] = builtinFunc{
|
||||
"__repr__",
|
||||
func(a ...any) (any, ArErr) {
|
||||
return "<byte>", ArErr{}
|
||||
},
|
||||
}
|
||||
obj.obj["number"] = builtinFunc{
|
||||
"number",
|
||||
func(a ...any) (any, ArErr) {
|
||||
return newNumber().SetInt64(int64(Byte)), ArErr{}
|
||||
},
|
||||
}
|
||||
obj.obj["from"] = builtinFunc{
|
||||
"from",
|
||||
func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "expected at least 1 argument, got 0",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
a[0] = ArValidToAny(a[0])
|
||||
switch x := a[0].(type) {
|
||||
case number:
|
||||
if x.Denom().Cmp(one.Denom()) != 0 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "expected integer, got " + fmt.Sprint(x),
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
n := x.Num().Int64()
|
||||
if n > 255 || n < 0 {
|
||||
return nil, ArErr{
|
||||
TYPE: "ValueError",
|
||||
message: "expected number between 0 and 255, got " + fmt.Sprint(floor(x).Num().Int64()),
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
Byte = byte(n)
|
||||
case string:
|
||||
if len(x) != 1 {
|
||||
return nil, ArErr{
|
||||
TYPE: "ValueError",
|
||||
message: "expected string of length 1, got " + fmt.Sprint(len(x)),
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
Byte = byte(x[0])
|
||||
default:
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "expected number or string, got " + typeof(x),
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
return obj, ArErr{}
|
||||
},
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
func ArBuffer(buf []byte) ArObject {
|
||||
obj := ArObject{
|
||||
obj: anymap{
|
||||
"__name__": "buffer",
|
||||
"__value__": buf,
|
||||
"length": newNumber().SetInt64(int64(len(buf))),
|
||||
},
|
||||
}
|
||||
obj.obj["__string__"] = builtinFunc{
|
||||
"__string__",
|
||||
func(a ...any) (any, ArErr) {
|
||||
return "<buffer>", ArErr{}
|
||||
},
|
||||
}
|
||||
obj.obj["__repr__"] = builtinFunc{
|
||||
"__repr__",
|
||||
func(a ...any) (any, ArErr) {
|
||||
return "<buffer>", ArErr{}
|
||||
},
|
||||
}
|
||||
obj.obj["from"] = builtinFunc{
|
||||
"from",
|
||||
func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "expected at least 1 argument, got 0",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
a[0] = ArValidToAny(a[0])
|
||||
switch x := a[0].(type) {
|
||||
case string:
|
||||
buf = []byte(x)
|
||||
case []byte:
|
||||
buf = x
|
||||
case []any:
|
||||
outputbuf := []byte{}
|
||||
for _, v := range x {
|
||||
switch y := v.(type) {
|
||||
case number:
|
||||
if y.Denom().Cmp(one.Denom()) != 0 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "Cannot convert non-integer to byte",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
outputbuf = append(outputbuf, byte(y.Num().Int64()))
|
||||
default:
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "Cannot convert " + typeof(v) + " to byte",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
buf = outputbuf
|
||||
default:
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "expected string or []byte, got " + typeof(x),
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
obj.obj["__value__"] = buf
|
||||
obj.obj["length"] = newNumber().SetInt64(int64(len(buf)))
|
||||
return obj, ArErr{}
|
||||
},
|
||||
}
|
||||
obj.obj["to"] = builtinFunc{
|
||||
"to",
|
||||
func(a ...any) (any, ArErr) {
|
||||
if len(a) != 1 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "expected 1 argument, got " + fmt.Sprint(len(a)),
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if typeof(a[0]) != "string" {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "expected string, got " + typeof(a[0]),
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
Type := ArValidToAny(a[0]).(string)
|
||||
switch Type {
|
||||
case "string":
|
||||
return ArString(string(buf)), ArErr{}
|
||||
case "bytes":
|
||||
output := []any{}
|
||||
for _, v := range buf {
|
||||
output = append(output, ArByte(v))
|
||||
}
|
||||
return ArArray(output), ArErr{}
|
||||
case "array":
|
||||
output := []any{}
|
||||
for _, v := range buf {
|
||||
output = append(output, newNumber().SetInt64(int64(v)))
|
||||
}
|
||||
return ArArray(output), ArErr{}
|
||||
default:
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "expected string, bytes or array, got '" + Type + "'",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
return obj
|
||||
}
|
||||
@@ -63,6 +63,12 @@ func makeGlobal() ArObject {
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot convert '" + typeof(a[0]) + "' to hex", EXISTS: true}
|
||||
}}
|
||||
vars["buffer"] = builtinFunc{"buffer", func(a ...any) (any, ArErr) {
|
||||
if len(a) != 0 {
|
||||
return nil, ArErr{TYPE: "TypeError", message: "expected 0 arguments, got " + fmt.Sprint(len(a)), EXISTS: true}
|
||||
}
|
||||
return ArBuffer([]byte{}), ArErr{}
|
||||
}}
|
||||
vars["throwError"] = builtinFunc{"throwError", ArThrowError}
|
||||
vars["array"] = builtinFunc{"array", func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
|
||||
37
src/file.go
37
src/file.go
@@ -67,16 +67,30 @@ func ArRead(args ...any) (any, ArErr) {
|
||||
}
|
||||
return mimetype.String(), ArErr{}
|
||||
}},
|
||||
"bytes": builtinFunc{"bytes", func(...any) (any, ArErr) {
|
||||
"buffer": builtinFunc{"buffer", func(args ...any) (any, ArErr) {
|
||||
if len(args) > 1 {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "buffer takes 0 or 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
}
|
||||
if len(args) == 1 {
|
||||
if typeof(args[0]) != "number" {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "buffer takes a number not type '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
}
|
||||
size := args[0].(number)
|
||||
if size.Denom().Int64() != 1 {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "buffer takes an integer not type '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
}
|
||||
buf := make([]byte, size.Num().Int64())
|
||||
n, err := file.Read(buf)
|
||||
if err != nil {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
return ArBuffer(buf[:n]), ArErr{}
|
||||
}
|
||||
bytes, err := readbinary(file)
|
||||
if err != nil {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
ArBinary := []any{}
|
||||
for _, b := range bytes {
|
||||
ArBinary = append(ArBinary, newNumber().SetInt64(int64(b)))
|
||||
}
|
||||
return ArBinary, ArErr{}
|
||||
return ArBuffer(bytes), ArErr{}
|
||||
}},
|
||||
}), ArErr{}
|
||||
}
|
||||
@@ -105,6 +119,17 @@ func ArWrite(args ...any) (any, ArErr) {
|
||||
file.Write([]byte(args[0].(string)))
|
||||
return nil, ArErr{}
|
||||
}},
|
||||
"buffer": builtinFunc{"buffer", func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "buffer takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
}
|
||||
if typeof(args[0]) != "buffer" {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "buffer takes a buffer not type '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
}
|
||||
args[0] = ArValidToAny(args[0])
|
||||
file.Write(args[0].([]byte))
|
||||
return nil, ArErr{}
|
||||
}},
|
||||
"json": builtinFunc{"json", func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "json takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
|
||||
@@ -216,7 +216,7 @@ func runVal(line any, stack stack, stacklevel int) (any, ArErr) {
|
||||
break
|
||||
}
|
||||
return runTryCatch(x, stack, stacklevel+1)
|
||||
case bool, ArObject, number, nil, Callable:
|
||||
case bool, ArObject, number, nil, Callable, builtinFunc, anymap:
|
||||
return x, ArErr{}
|
||||
}
|
||||
if stackoverflow {
|
||||
|
||||
120
src/socket.go
120
src/socket.go
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ArSocket(args ...any) (any, ArErr) {
|
||||
@@ -46,6 +47,13 @@ func ArSocket(args ...any) (any, ArErr) {
|
||||
"accept": builtinFunc{
|
||||
"accept",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if ln == nil {
|
||||
return ArObject{}, ArErr{
|
||||
TYPE: "SocketError",
|
||||
message: "Socket is closed",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
conn, err := ln.Accept()
|
||||
if err != nil {
|
||||
return ArObject{}, ArErr{
|
||||
@@ -61,13 +69,14 @@ func ArSocket(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArObject{}, ArErr{
|
||||
TYPE: "SocketError",
|
||||
message: "Socket.read() takes exactly 1 argument",
|
||||
message: "Socket.readData() takes exactly 1 argument",
|
||||
EXISTS: true,
|
||||
}
|
||||
} else if typeof(args[0]) != "number" {
|
||||
}
|
||||
if conn == nil {
|
||||
return ArObject{}, ArErr{
|
||||
TYPE: "SocketError",
|
||||
message: "Socket.read() argument must be a number",
|
||||
message: "Connection is closed",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
@@ -80,33 +89,7 @@ func ArSocket(args ...any) (any, ArErr) {
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
return ArString(string(buf[:n])), ArErr{}
|
||||
},
|
||||
},
|
||||
"writeData": builtinFunc{
|
||||
"writeData",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArObject{}, ArErr{
|
||||
TYPE: "SocketError",
|
||||
message: "Socket.writeData() takes exactly 1 argument",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
data := ArValidToAny(args[0])
|
||||
switch x := data.(type) {
|
||||
case []any:
|
||||
bytes := []byte{}
|
||||
for _, v := range x {
|
||||
bytes = append(bytes, byte(v.(number).Num().Int64()))
|
||||
}
|
||||
conn.Write(bytes)
|
||||
return nil, ArErr{}
|
||||
}
|
||||
return nil, ArErr{
|
||||
TYPE: "SocketError",
|
||||
message: "Socket.writeData() argument must be a array of numbers",
|
||||
}
|
||||
return ArBuffer(buf[:n]), ArErr{}
|
||||
},
|
||||
},
|
||||
"write": builtinFunc{
|
||||
@@ -115,24 +98,53 @@ func ArSocket(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArObject{}, ArErr{
|
||||
TYPE: "SocketError",
|
||||
message: "Socket.write() takes exactly 1 argument",
|
||||
EXISTS: true,
|
||||
}
|
||||
} else if typeof(args[0]) != "string" {
|
||||
return ArObject{}, ArErr{
|
||||
TYPE: "SocketError",
|
||||
message: "Socket.write() argument must be a string",
|
||||
message: "Socket.writeData() takes exactly 1 argument",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
data := ArValidToAny(args[0]).(string)
|
||||
conn.Write([]byte(data))
|
||||
return nil, ArErr{}
|
||||
if conn == nil {
|
||||
return ArObject{}, ArErr{
|
||||
TYPE: "SocketError",
|
||||
message: "Connection is closed",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
data := ArValidToAny(args[0])
|
||||
switch x := data.(type) {
|
||||
case []any:
|
||||
bytes := []byte{}
|
||||
for _, v := range x {
|
||||
if typeof(v) != "number" && v.(number).Denom().Int64() != 1 {
|
||||
return ArObject{}, ArErr{
|
||||
TYPE: "SocketError",
|
||||
message: "Socket.writeData() argument must be a array of integers",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
bytes = append(bytes, byte(v.(number).Num().Int64()))
|
||||
}
|
||||
conn.Write(bytes)
|
||||
return nil, ArErr{}
|
||||
case []byte:
|
||||
conn.Write(x)
|
||||
return nil, ArErr{}
|
||||
}
|
||||
return nil, ArErr{
|
||||
TYPE: "SocketError",
|
||||
message: "Socket.writeData() argument must be a array of numbers",
|
||||
}
|
||||
},
|
||||
},
|
||||
"close": builtinFunc{
|
||||
"close",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if conn == nil {
|
||||
return ArObject{}, ArErr{
|
||||
TYPE: "SocketError",
|
||||
message: "Connection is already closed",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
conn.Close()
|
||||
conn = nil
|
||||
return nil, ArErr{}
|
||||
@@ -141,12 +153,31 @@ func ArSocket(args ...any) (any, ArErr) {
|
||||
"isClosed": builtinFunc{
|
||||
"isClosed",
|
||||
func(args ...any) (any, ArErr) {
|
||||
return conn == nil, 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{}
|
||||
|
||||
},
|
||||
},
|
||||
"RemoteAddr": builtinFunc{
|
||||
"RemoteAddr",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if conn == nil {
|
||||
return ArObject{}, ArErr{
|
||||
TYPE: "SocketError",
|
||||
message: "Connection is closed",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
return ArString(conn.RemoteAddr().String()), ArErr{}
|
||||
},
|
||||
},
|
||||
@@ -162,6 +193,13 @@ func ArSocket(args ...any) (any, ArErr) {
|
||||
"close": builtinFunc{
|
||||
"close",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if ln == nil {
|
||||
return ArObject{}, ArErr{
|
||||
TYPE: "SocketError",
|
||||
message: "Socket is already closed",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
ln.Close()
|
||||
ln = nil
|
||||
return nil, ArErr{}
|
||||
|
||||
@@ -2,10 +2,12 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var timing = anymap{}
|
||||
var timingSync = sync.RWMutex{}
|
||||
|
||||
var ArTerm = Map(anymap{
|
||||
"log": builtinFunc{"log", func(args ...any) (any, ArErr) {
|
||||
@@ -100,7 +102,9 @@ var ArTerm = Map(anymap{
|
||||
if len(args) > 0 {
|
||||
id = ArValidToAny(args[0])
|
||||
}
|
||||
timingSync.Lock()
|
||||
timing[id] = time.Now()
|
||||
timingSync.Unlock()
|
||||
return nil, ArErr{}
|
||||
},
|
||||
},
|
||||
@@ -109,11 +113,15 @@ var ArTerm = Map(anymap{
|
||||
if len(args) > 0 {
|
||||
id = ArValidToAny(args[0])
|
||||
}
|
||||
timingSync.RLock()
|
||||
if _, ok := timing[id]; !ok {
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot find timer with id '" + fmt.Sprint(id) + "'", EXISTS: true}
|
||||
}
|
||||
timesince := time.Since(timing[id].(time.Time))
|
||||
timingSync.RUnlock()
|
||||
timingSync.Lock()
|
||||
delete(timing, id)
|
||||
timingSync.Unlock()
|
||||
if id == nil {
|
||||
id = "Timer"
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
)
|
||||
|
||||
func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored bool, plain int) string {
|
||||
x = ArValidToAny(x)
|
||||
output := []string{}
|
||||
maybenewline := ""
|
||||
if plain == 1 {
|
||||
@@ -75,7 +74,37 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored
|
||||
output = append(output, "\x1b[0m")
|
||||
}
|
||||
case ArObject:
|
||||
|
||||
if callable, ok := x.obj["__string__"]; ok && !quote {
|
||||
val, err := runCall(
|
||||
call{
|
||||
callable: callable,
|
||||
args: []any{},
|
||||
},
|
||||
stack{},
|
||||
0,
|
||||
)
|
||||
if !err.EXISTS {
|
||||
output = append(output, anyToArgon(val, false, simplify, depth, indent, colored, plain))
|
||||
break
|
||||
}
|
||||
} else if callable, ok := x.obj["__repr__"]; ok {
|
||||
val, err := runCall(
|
||||
call{
|
||||
callable: callable,
|
||||
args: []any{},
|
||||
},
|
||||
stack{},
|
||||
0,
|
||||
)
|
||||
if !err.EXISTS {
|
||||
output = append(output, anyToArgon(val, false, simplify, depth, indent, colored, plain))
|
||||
break
|
||||
}
|
||||
} else if val, ok := x.obj["__value__"]; ok {
|
||||
output = append(output, anyToArgon(val, quote, simplify, depth, indent, colored, plain))
|
||||
break
|
||||
}
|
||||
output = append(output, "<object>")
|
||||
case anymap:
|
||||
if len(x) == 0 {
|
||||
return "{}"
|
||||
|
||||
Reference in New Issue
Block a user