add bytearray type for faster access to bytes (API identical to array type)
This commit is contained in:
parent
4749c142fa
commit
456d39399e
8 changed files with 262 additions and 75 deletions
|
@ -42,19 +42,19 @@ construct net:http:server:Request {
|
||||||
construct { this | with server stream this ;
|
construct { this | with server stream this ;
|
||||||
server this:=server
|
server this:=server
|
||||||
stream this:=stream
|
stream this:=stream
|
||||||
0 anew this:=head
|
0 banew this:=head
|
||||||
0 anew this:=body
|
0 banew this:=body
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
read-head { this | with this ;
|
read-head { this | with this ;
|
||||||
def read
|
def read
|
||||||
def buf 1024 anew =buf
|
def buf 1024 banew =buf
|
||||||
def found
|
def found
|
||||||
while {
|
while {
|
||||||
buf this:stream:read pop dup =read
|
buf this:stream:read pop dup =read
|
||||||
"\r\n\r\n" :to-bytes buf:find dup =found null eq and
|
"\r\n\r\n" :to-bytes buf:find dup =found null eq and
|
||||||
} {
|
} {
|
||||||
this:head buf:sub<0 read>:replace<"\r" :to-bytes 0 anew> aadd this:=head
|
this:head buf:sub<0 read>:replace<"\r" :to-bytes 0 banew> aadd this:=head
|
||||||
"\n\n" :to-bytes this:head:find dup null eq not if {
|
"\n\n" :to-bytes this:head:find dup null eq not if {
|
||||||
=found
|
=found
|
||||||
this:head:sub<0 found>:to-str this:=head
|
this:head:sub<0 found>:to-str this:=head
|
||||||
|
@ -108,7 +108,7 @@ construct net:http:server:Request {
|
||||||
read-body { this | with this ;
|
read-body { this | with this ;
|
||||||
this:headers:get<"content-length"> dup if { _mega with content-length ;
|
this:headers:get<"content-length"> dup if { _mega with content-length ;
|
||||||
def read
|
def read
|
||||||
def buf 1024 anew =buf
|
def buf 1024 banew =buf
|
||||||
while {
|
while {
|
||||||
this:body:len content-length lt read and
|
this:body:len content-length lt read and
|
||||||
} {
|
} {
|
||||||
|
@ -154,7 +154,7 @@ construct net:http:server:Request {
|
||||||
}
|
}
|
||||||
finish { | with this ;
|
finish { | with this ;
|
||||||
this:wrote-body not if {
|
this:wrote-body not if {
|
||||||
0 anew this:write-body;
|
0 banew this:write-body;
|
||||||
}
|
}
|
||||||
this:stream:close;
|
this:stream:close;
|
||||||
}
|
}
|
||||||
|
|
30
spl/std.spl
30
spl/std.spl
|
@ -47,6 +47,9 @@ construct _str_ext {
|
||||||
starts-with { bool | with beginning this ;
|
starts-with { bool | with beginning this ;
|
||||||
beginning:to-bytes this:to-bytes:starts-with
|
beginning:to-bytes this:to-bytes:starts-with
|
||||||
}
|
}
|
||||||
|
ends-with { bool | with ending this ;
|
||||||
|
ending:to-bytes this:to-bytes:ends-with
|
||||||
|
}
|
||||||
_char { int | with this ;
|
_char { int | with this ;
|
||||||
0 (this _array):get
|
0 (this _array):get
|
||||||
}
|
}
|
||||||
|
@ -98,6 +101,15 @@ construct _mega-ext {
|
||||||
|
|
||||||
construct _array-ext {
|
construct _array-ext {
|
||||||
;
|
;
|
||||||
|
another { array | with this ;
|
||||||
|
this gettype =this
|
||||||
|
this "array" eq if {
|
||||||
|
anew
|
||||||
|
}
|
||||||
|
this "bytearray" eq if {
|
||||||
|
banew
|
||||||
|
}
|
||||||
|
}
|
||||||
get { any | array-get }
|
get { any | array-get }
|
||||||
sget { any|null | with idx this ;
|
sget { any|null | with idx this ;
|
||||||
idx this:len lt idx -1 gt and dup if {
|
idx this:len lt idx -1 gt and dup if {
|
||||||
|
@ -135,7 +147,7 @@ construct _array-ext {
|
||||||
}
|
}
|
||||||
to-str { str | bytes-to-str }
|
to-str { str | bytes-to-str }
|
||||||
sub { [any] | with begin end this ;
|
sub { [any] | with begin end this ;
|
||||||
this (end begin - anew) begin 0 (end begin -) acopy
|
this (end begin - this:another) begin 0 (end begin -) acopy
|
||||||
}
|
}
|
||||||
split { arr | with splitter this ;
|
split { arr | with splitter this ;
|
||||||
def i 0 =i
|
def i 0 =i
|
||||||
|
@ -204,6 +216,13 @@ construct _array-ext {
|
||||||
}
|
}
|
||||||
0 beginning:len this:sub beginning eq
|
0 beginning:len this:sub beginning eq
|
||||||
}
|
}
|
||||||
|
ends-with { bool | with ending this ;
|
||||||
|
this:len ending:len lt if {
|
||||||
|
0
|
||||||
|
2 stop
|
||||||
|
}
|
||||||
|
this:len ending:len - this:len this:sub ending eq
|
||||||
|
}
|
||||||
last { | with this ;
|
last { | with this ;
|
||||||
this:len -- this:get
|
this:len -- this:get
|
||||||
}
|
}
|
||||||
|
@ -240,7 +259,9 @@ construct _array-ext {
|
||||||
=4 { | with this ;
|
=4 { | with this ;
|
||||||
4 this:set;
|
4 this:set;
|
||||||
}
|
}
|
||||||
} include _array-ext in array
|
}
|
||||||
|
include _array-ext in array
|
||||||
|
include _array-ext in bytearray
|
||||||
|
|
||||||
construct _func-ext {
|
construct _func-ext {
|
||||||
args
|
args
|
||||||
|
@ -345,7 +366,7 @@ construct ArrayIter {
|
||||||
construct _IterableArray {
|
construct _IterableArray {
|
||||||
;
|
;
|
||||||
iter { ArrayIter | with this ;
|
iter { ArrayIter | with this ;
|
||||||
this gettype "array" eq dup if {
|
this gettype:ends-with<"array"> dup if {
|
||||||
pop
|
pop
|
||||||
this ArrayIter:new
|
this ArrayIter:new
|
||||||
2 stop
|
2 stop
|
||||||
|
@ -357,6 +378,7 @@ construct _IterableArray {
|
||||||
include _Iter in ArrayIter
|
include _Iter in ArrayIter
|
||||||
include _IterableArray in List
|
include _IterableArray in List
|
||||||
include _IterableArray in array
|
include _IterableArray in array
|
||||||
|
include _IterableArray in bytearray
|
||||||
|
|
||||||
construct MicroMap {
|
construct MicroMap {
|
||||||
pairs
|
pairs
|
||||||
|
@ -459,7 +481,7 @@ construct shadow { }
|
||||||
|
|
||||||
func aadd { array | with arr1 arr2 ;
|
func aadd { array | with arr1 arr2 ;
|
||||||
|
|
||||||
def newarr arr1:len arr2:len + anew =newarr
|
def newarr arr1:len arr2:len + arr1:another =newarr
|
||||||
|
|
||||||
arr1 newarr 0 0 arr1:len acopy;
|
arr1 newarr 0 0 arr1:len acopy;
|
||||||
arr2 newarr 0 arr1:len arr2:len acopy;
|
arr2 newarr 0 arr1:len arr2:len acopy;
|
||||||
|
|
|
@ -15,23 +15,23 @@ construct Stream {
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
read-one { mega | with this ;
|
read-one { mega | with this ;
|
||||||
def buf 1 anew =buf
|
def buf 1 banew =buf
|
||||||
while { buf this:id read-stream pop not } { }
|
while { buf this:id read-stream pop not } { }
|
||||||
0 buf:get _mega
|
0 buf:get _mega
|
||||||
}
|
}
|
||||||
"the buffer is written to in-place.";
|
"the buffer is written to in-place.";
|
||||||
read { mega [int] | with buf this ;
|
read { mega [int] | with buf this ;
|
||||||
buf gettype "mega" eq if { buf anew =buf }
|
buf gettype "mega" eq if { buf banew =buf }
|
||||||
buf this:id read-stream
|
buf this:id read-stream
|
||||||
}
|
}
|
||||||
"the buffer is written to in-place.";
|
"the buffer is written to in-place.";
|
||||||
read-exact { [int] | with buf this ;
|
read-exact { [int] | with buf this ;
|
||||||
buf gettype "mega" eq if { buf anew =buf }
|
buf gettype "mega" eq if { buf banew =buf }
|
||||||
buf this:id read-all-stream buf
|
buf this:id read-all-stream buf
|
||||||
}
|
}
|
||||||
read-to-end { [int] | with buf this ;
|
read-to-end { [int] | with buf this ;
|
||||||
def full 0 anew =full
|
def full 0 banew =full
|
||||||
buf gettype "mega" eq if { buf anew =buf }
|
buf gettype "mega" eq if { buf banew =buf }
|
||||||
def read
|
def read
|
||||||
while { buf this:id read-stream pop _mega dup =read } {
|
while { buf this:id read-stream pop _mega dup =read } {
|
||||||
full (0 read buf:sub) aadd =full
|
full (0 read buf:sub) aadd =full
|
||||||
|
|
43
src/lib.rs
43
src/lib.rs
|
@ -101,6 +101,24 @@ nofmt! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! require_mut_on_stack {
|
||||||
|
($name:tt, $type:tt, $stack:expr, $fn:literal) => {
|
||||||
|
let binding = $stack.pop();
|
||||||
|
let Value::$type(ref mut $name) = binding.lock().native else {
|
||||||
|
return $stack.err(ErrorKind::InvalidCall($fn.to_owned()))
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! require_mut {
|
||||||
|
($name:tt, $type:tt, $binding:expr, $stack:expr, $fn:literal) => {
|
||||||
|
let Value::$type(ref mut $name) = $binding.lock().native else {
|
||||||
|
return $stack.err(ErrorKind::InvalidCall($fn.to_owned()))
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! require_int_on_stack {
|
macro_rules! require_int_on_stack {
|
||||||
($name:tt, $stack:expr, $fn:literal) => {
|
($name:tt, $stack:expr, $fn:literal) => {
|
||||||
|
@ -133,6 +151,31 @@ nofmt! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
macro_rules! require_byte_array_on_stack {
|
||||||
|
($name:tt, $stack:expr, $fn:literal) => {
|
||||||
|
let binding = $stack.pop();
|
||||||
|
let $name = match binding.lock_ro().native {
|
||||||
|
Value::Array(ref x) => x
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(|x| {
|
||||||
|
Ok(match &x.lock_ro().native {
|
||||||
|
Value::Int(x) => *x as u8,
|
||||||
|
Value::Long(x) => *x as u8,
|
||||||
|
Value::Mega(x) => *x as u8,
|
||||||
|
_ => $stack.err(ErrorKind::InvalidType(
|
||||||
|
x.lock_ro().kind.lock_ro().get_name(),
|
||||||
|
"byte".to_owned(),
|
||||||
|
))?,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
|
Value::ByteArray(ref x) => x.clone(),
|
||||||
|
_ => return $stack.err(ErrorKind::InvalidCall($fn.to_owned())),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#[macro_export]
|
||||||
macro_rules! require_mut_array_on_stack {
|
macro_rules! require_mut_array_on_stack {
|
||||||
($name:tt, $stack:expr, $fn:literal) => {
|
($name:tt, $stack:expr, $fn:literal) => {
|
||||||
let binding = $stack.pop();
|
let binding = $stack.pop();
|
||||||
|
|
|
@ -115,6 +115,7 @@ impl Runtime {
|
||||||
let _ = rt.make_type("func".to_owned(), Ok); // infallible
|
let _ = rt.make_type("func".to_owned(), Ok); // infallible
|
||||||
let _ = rt.make_type("array".to_owned(), Ok); // infallible
|
let _ = rt.make_type("array".to_owned(), Ok); // infallible
|
||||||
let _ = rt.make_type("str".to_owned(), Ok); // infallible
|
let _ = rt.make_type("str".to_owned(), Ok); // infallible
|
||||||
|
let _ = rt.make_type("bytearray".to_owned(), Ok); // infallible
|
||||||
stdlib::register(&mut rt);
|
stdlib::register(&mut rt);
|
||||||
rt
|
rt
|
||||||
}
|
}
|
||||||
|
@ -771,6 +772,7 @@ pub enum Value {
|
||||||
Double(f64),
|
Double(f64),
|
||||||
Func(AFunc),
|
Func(AFunc),
|
||||||
Array(Vec<AMObject>),
|
Array(Vec<AMObject>),
|
||||||
|
ByteArray(Vec<u8>),
|
||||||
Str(String),
|
Str(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1066,6 +1068,7 @@ impl Object {
|
||||||
Value::Func(_) => true,
|
Value::Func(_) => true,
|
||||||
Value::Array(_) => true,
|
Value::Array(_) => true,
|
||||||
Value::Str(x) => !x.is_empty(),
|
Value::Str(x) => !x.is_empty(),
|
||||||
|
Value::ByteArray(_) => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1125,6 +1128,7 @@ impl From<Value> for Object {
|
||||||
Value::Func(_) => x.get_type_by_id(6),
|
Value::Func(_) => x.get_type_by_id(6),
|
||||||
Value::Array(_) => x.get_type_by_id(7),
|
Value::Array(_) => x.get_type_by_id(7),
|
||||||
Value::Str(_) => x.get_type_by_id(8),
|
Value::Str(_) => x.get_type_by_id(8),
|
||||||
|
Value::ByteArray(_) => x.get_type_by_id(9),
|
||||||
}
|
}
|
||||||
.expect("runtime uninitialized: default types not set.")
|
.expect("runtime uninitialized: default types not set.")
|
||||||
}),
|
}),
|
||||||
|
|
38
src/sasm.rs
38
src/sasm.rs
|
@ -175,6 +175,25 @@ fn sasm_parse<'a>(line: &str, words: &mut Vec<Word>, lines: &mut impl Iterator<I
|
||||||
})))),
|
})))),
|
||||||
"null" => words.push(Word::Const(Value::Null)),
|
"null" => words.push(Word::Const(Value::Null)),
|
||||||
"array" => panic!("invalid sasm const: array - not all Values can be consts!"),
|
"array" => panic!("invalid sasm const: array - not all Values can be consts!"),
|
||||||
|
"bytearray" => {
|
||||||
|
let mut array = Vec::new();
|
||||||
|
let inp = line[2].chars().collect::<Vec<_>>();
|
||||||
|
fn v(c: char) -> u8 {
|
||||||
|
if c > '0' && c <= '9' {
|
||||||
|
c as u8 - '0' as u8
|
||||||
|
} else if c > 'a' && c <= 'f' {
|
||||||
|
c as u8 - 'a' as u8
|
||||||
|
} else {
|
||||||
|
panic!("invalid sasm const: const bytearray [nonbytearray]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i in (0..inp.len() / 2).map(|x| x * 2) {
|
||||||
|
let a = inp[i];
|
||||||
|
let b = inp[i + 1];
|
||||||
|
array.push(v(a) * 0x10 + v(b));
|
||||||
|
}
|
||||||
|
words.push(Word::Const(Value::ByteArray(array)));
|
||||||
|
}
|
||||||
_ => panic!("invalid sasm const: {}", line[1]),
|
_ => panic!("invalid sasm const: {}", line[1]),
|
||||||
},
|
},
|
||||||
"call" => {
|
"call" => {
|
||||||
|
@ -356,6 +375,25 @@ fn sasm_write_func(words: Words) -> String {
|
||||||
text.replace("\0", "\0\x01").replace("\n", "\0\0")
|
text.replace("\0", "\0\x01").replace("\n", "\0\0")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Value::ByteArray(b) => {
|
||||||
|
fn c(v: u8) -> char {
|
||||||
|
if v > 16 {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
(if v < 10 {
|
||||||
|
'0' as u8 + v
|
||||||
|
} else {
|
||||||
|
'a' as u8 + v - 10
|
||||||
|
}) as char
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut out = String::with_capacity(b.len() * 2);
|
||||||
|
for b in b {
|
||||||
|
out.push(c(b / 0x10));
|
||||||
|
out.push(c(b % 0x10));
|
||||||
|
}
|
||||||
|
output += &format!("const bytearray {out}\n");
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Word::Call(name, rem, ra) => {
|
Word::Call(name, rem, ra) => {
|
||||||
output += "call ";
|
output += "call ";
|
||||||
|
|
136
src/std_fns.rs
136
src/std_fns.rs
|
@ -110,6 +110,17 @@ pub fn gettype(stack: &mut Stack) -> OError {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn barray_new(stack: &mut Stack) -> OError {
|
||||||
|
let Value::Mega(i) = stack.pop().lock_ro().native.clone() else {
|
||||||
|
return stack.err(ErrorKind::InvalidCall("banew".to_owned()));
|
||||||
|
};
|
||||||
|
if i < 0 {
|
||||||
|
return stack.err(ErrorKind::InvalidCall("banew".to_owned()));
|
||||||
|
}
|
||||||
|
stack.push(Value::ByteArray(vec![0u8; i as usize]).spl());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn array_new(stack: &mut Stack) -> OError {
|
pub fn array_new(stack: &mut Stack) -> OError {
|
||||||
let Value::Mega(i) = stack.pop().lock_ro().native.clone() else {
|
let Value::Mega(i) = stack.pop().lock_ro().native.clone() else {
|
||||||
return stack.err(ErrorKind::InvalidCall("anew".to_owned()));
|
return stack.err(ErrorKind::InvalidCall("anew".to_owned()));
|
||||||
|
@ -123,36 +134,47 @@ pub fn array_new(stack: &mut Stack) -> OError {
|
||||||
|
|
||||||
pub fn array_len(stack: &mut Stack) -> OError {
|
pub fn array_len(stack: &mut Stack) -> OError {
|
||||||
let binding = stack.pop();
|
let binding = stack.pop();
|
||||||
let Value::Array(ref a) = binding.lock_ro().native else {
|
let len = match binding.lock_ro().native {
|
||||||
return stack.err(ErrorKind::InvalidCall("array-len".to_owned()));
|
Value::Array(ref a) => a.len(),
|
||||||
|
Value::ByteArray(ref a) => a.len(),
|
||||||
|
_ => return stack.err(ErrorKind::InvalidCall("array-len".to_owned())),
|
||||||
};
|
};
|
||||||
stack.push(Value::Mega(a.len() as i128).spl());
|
stack.push(Value::Mega(len as i128).spl());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_get(stack: &mut Stack) -> OError {
|
pub fn array_get(stack: &mut Stack) -> OError {
|
||||||
let binding = stack.pop();
|
let binding = stack.pop();
|
||||||
let Value::Array(ref a) = binding.lock_ro().native else {
|
|
||||||
return stack.err(ErrorKind::InvalidCall("array-get".to_owned()));
|
|
||||||
};
|
|
||||||
let Value::Mega(i) = stack.pop().lock_ro().native.clone() else {
|
let Value::Mega(i) = stack.pop().lock_ro().native.clone() else {
|
||||||
return stack.err(ErrorKind::InvalidCall("array-get".to_owned()));
|
return stack.err(ErrorKind::InvalidCall("array-get".to_owned()));
|
||||||
};
|
};
|
||||||
stack.push(a.get(i as usize).ok_or_else(array!(stack, i))?.clone());
|
let o = match binding.lock_ro().native {
|
||||||
|
Value::Array(ref a) => a.get(i as usize).cloned(),
|
||||||
|
Value::ByteArray(ref a) => a.get(i as usize).map(|x| Value::Int(*x as i32).spl()),
|
||||||
|
_ => return stack.err(ErrorKind::InvalidCall("array-get".to_owned())),
|
||||||
|
};
|
||||||
|
stack.push(o.ok_or_else(array!(stack, i))?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_set(stack: &mut Stack) -> OError {
|
pub fn array_set(stack: &mut Stack) -> OError {
|
||||||
let binding = stack.pop();
|
let binding = stack.pop();
|
||||||
let Value::Array(ref mut a) = binding.lock().native else {
|
|
||||||
return stack.err(ErrorKind::InvalidCall("array-set".to_owned()));
|
|
||||||
};
|
|
||||||
let Value::Mega(i) = stack.pop().lock_ro().native.clone() else {
|
let Value::Mega(i) = stack.pop().lock_ro().native.clone() else {
|
||||||
return stack.err(ErrorKind::InvalidCall("array-set".to_owned()));
|
return stack.err(ErrorKind::InvalidCall("array-set".to_owned()));
|
||||||
};
|
};
|
||||||
let o = stack.pop();
|
let o = stack.pop();
|
||||||
stack.push(a.get(i as usize).ok_or_else(array!(stack, i))?.clone());
|
if let Value::Array(ref mut a) = binding.lock().native {
|
||||||
*a.get_mut(i as usize).ok_or_else(array!(stack, i))? = o;
|
stack.push(a.get(i as usize).ok_or_else(array!(stack, i))?.clone());
|
||||||
|
*a.get_mut(i as usize).ok_or_else(array!(stack, i))? = o;
|
||||||
|
} else if let Value::ByteArray(ref mut a) = binding.lock().native {
|
||||||
|
let Value::Int(o) = o.lock_ro().native else {
|
||||||
|
return stack.err(ErrorKind::InvalidCall("array-set".to_owned()));
|
||||||
|
};
|
||||||
|
stack.push(Value::Int(*a.get(i as usize).ok_or_else(array!(stack, i))? as i32).spl());
|
||||||
|
*a.get_mut(i as usize).ok_or_else(array!(stack, i))? = o as u8;
|
||||||
|
} else {
|
||||||
|
return stack.err(ErrorKind::InvalidCall("array-set".to_owned()));
|
||||||
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,6 +342,7 @@ pub fn to_int(stack: &mut Stack) -> OError {
|
||||||
Value::Str(x) => x
|
Value::Str(x) => x
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|_| stack.error(ErrorKind::Parse(x, "int".to_owned())))?,
|
.map_err(|_| stack.error(ErrorKind::Parse(x, "int".to_owned())))?,
|
||||||
|
Value::ByteArray(x) => x.len() as i32,
|
||||||
})
|
})
|
||||||
.spl(),
|
.spl(),
|
||||||
);
|
);
|
||||||
|
@ -341,6 +364,7 @@ pub fn to_long(stack: &mut Stack) -> OError {
|
||||||
Value::Str(x) => x
|
Value::Str(x) => x
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|_| stack.error(ErrorKind::Parse(x, "long".to_owned())))?,
|
.map_err(|_| stack.error(ErrorKind::Parse(x, "long".to_owned())))?,
|
||||||
|
Value::ByteArray(x) => x.len() as i64,
|
||||||
})
|
})
|
||||||
.spl(),
|
.spl(),
|
||||||
);
|
);
|
||||||
|
@ -362,6 +386,7 @@ pub fn to_mega(stack: &mut Stack) -> OError {
|
||||||
Value::Str(x) => x
|
Value::Str(x) => x
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|_| stack.error(ErrorKind::Parse(x, "mega".to_owned())))?,
|
.map_err(|_| stack.error(ErrorKind::Parse(x, "mega".to_owned())))?,
|
||||||
|
Value::ByteArray(x) => x.len() as i128,
|
||||||
})
|
})
|
||||||
.spl(),
|
.spl(),
|
||||||
);
|
);
|
||||||
|
@ -383,6 +408,7 @@ pub fn to_float(stack: &mut Stack) -> OError {
|
||||||
Value::Str(x) => x
|
Value::Str(x) => x
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|_| stack.error(ErrorKind::Parse(x, "float".to_owned())))?,
|
.map_err(|_| stack.error(ErrorKind::Parse(x, "float".to_owned())))?,
|
||||||
|
Value::ByteArray(_) => type_err!(stack, "bytearray", "float"),
|
||||||
})
|
})
|
||||||
.spl(),
|
.spl(),
|
||||||
);
|
);
|
||||||
|
@ -404,6 +430,7 @@ pub fn to_double(stack: &mut Stack) -> OError {
|
||||||
Value::Str(x) => x
|
Value::Str(x) => x
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|_| stack.error(ErrorKind::Parse(x, "double".to_owned())))?,
|
.map_err(|_| stack.error(ErrorKind::Parse(x, "double".to_owned())))?,
|
||||||
|
Value::ByteArray(_) => type_err!(stack, "bytearray", "double"),
|
||||||
})
|
})
|
||||||
.spl(),
|
.spl(),
|
||||||
);
|
);
|
||||||
|
@ -426,6 +453,11 @@ pub fn to_array(stack: &mut Stack) -> OError {
|
||||||
.chars()
|
.chars()
|
||||||
.map(|x| Value::Int(x as u32 as i32).spl())
|
.map(|x| Value::Int(x as u32 as i32).spl())
|
||||||
.collect(),
|
.collect(),
|
||||||
|
Value::ByteArray(x) => x
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(|x| Value::Int(x as i32).spl())
|
||||||
|
.collect(),
|
||||||
})
|
})
|
||||||
.spl(),
|
.spl(),
|
||||||
);
|
);
|
||||||
|
@ -466,6 +498,46 @@ pub fn to_str(stack: &mut Stack) -> OError {
|
||||||
fixed
|
fixed
|
||||||
}
|
}
|
||||||
Value::Str(x) => x,
|
Value::Str(x) => x,
|
||||||
|
Value::ByteArray(x) => String::from_utf8(x).map_err(|_| {
|
||||||
|
stack.error(ErrorKind::InvalidType(
|
||||||
|
"!utf8".to_owned(),
|
||||||
|
"utf8".to_owned(),
|
||||||
|
))
|
||||||
|
})?,
|
||||||
|
})
|
||||||
|
.spl(),
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_bytearray(stack: &mut Stack) -> OError {
|
||||||
|
let o = stack.pop().lock_ro().native.clone();
|
||||||
|
stack.push(
|
||||||
|
Value::ByteArray(match o {
|
||||||
|
Value::Null => type_err!(stack, "null", "array"),
|
||||||
|
Value::Int(_) => type_err!(stack, "int", "array"),
|
||||||
|
Value::Long(_) => type_err!(stack, "long", "array"),
|
||||||
|
Value::Mega(_) => type_err!(stack, "mega", "array"),
|
||||||
|
Value::Float(_) => type_err!(stack, "float", "array"),
|
||||||
|
Value::Double(_) => type_err!(stack, "double", "array"),
|
||||||
|
Value::Func(_) => type_err!(stack, "func", "array"),
|
||||||
|
Value::Array(x) => x
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(|x| {
|
||||||
|
Ok(match &x.lock_ro().native {
|
||||||
|
Value::Int(x) => *x as u8,
|
||||||
|
Value::Long(x) => *x as u8,
|
||||||
|
Value::Mega(x) => *x as u8,
|
||||||
|
_ => stack.err(ErrorKind::InvalidType(
|
||||||
|
x.lock_ro().kind.lock_ro().get_name(),
|
||||||
|
"byte".to_owned(),
|
||||||
|
))?,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
|
Value::Str(x) => x.into_bytes(),
|
||||||
|
Value::ByteArray(x) => x,
|
||||||
})
|
})
|
||||||
.spl(),
|
.spl(),
|
||||||
);
|
);
|
||||||
|
@ -759,29 +831,18 @@ pub fn command_wait(stack: &mut Stack) -> OError {
|
||||||
|
|
||||||
pub fn str_to_bytes(stack: &mut Stack) -> OError {
|
pub fn str_to_bytes(stack: &mut Stack) -> OError {
|
||||||
require_on_stack!(s, Str, stack, "str-to-bytes");
|
require_on_stack!(s, Str, stack, "str-to-bytes");
|
||||||
stack.push(
|
stack.push(Value::ByteArray(s.bytes().collect()).spl());
|
||||||
Value::Array(
|
|
||||||
s.bytes()
|
|
||||||
.into_iter()
|
|
||||||
.map(|x| Value::Int(x as i32).spl())
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
.spl(),
|
|
||||||
);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bytes_to_str(stack: &mut Stack) -> OError {
|
pub fn bytes_to_str(stack: &mut Stack) -> OError {
|
||||||
require_array_on_stack!(a, stack, "str-to-bytes");
|
if stack.peek().lock_ro().kind.lock_ro().get_name() == "bytearray" {
|
||||||
let mut chars = Vec::new();
|
require_on_stack!(a, ByteArray, stack, "bytes-to-str");
|
||||||
for item in a.iter() {
|
stack.push(Value::Str(String::from_utf8_lossy(&a[..]).into_owned()).spl());
|
||||||
if let Value::Int(x) = item.lock_ro().native.clone().try_mega_to_int() {
|
return Ok(());
|
||||||
chars.push(x as u8);
|
|
||||||
} else {
|
|
||||||
return stack.err(ErrorKind::InvalidCall("command".to_owned()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
stack.push(Value::Str(String::from_utf8_lossy(&chars[..]).into_owned()).spl());
|
require_byte_array_on_stack!(a, stack, "bytes-to-str");
|
||||||
|
stack.push(Value::Str(String::from_utf8_lossy(&a).into_owned()).spl());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -790,7 +851,8 @@ pub fn acopy(stack: &mut Stack) -> OError {
|
||||||
require_on_stack!(idx_dest, Mega, stack, "acopy");
|
require_on_stack!(idx_dest, Mega, stack, "acopy");
|
||||||
require_on_stack!(idx_src, Mega, stack, "acopy");
|
require_on_stack!(idx_src, Mega, stack, "acopy");
|
||||||
let dest_array = stack.pop();
|
let dest_array = stack.pop();
|
||||||
{
|
let kind = dest_array.lock_ro().kind.lock_ro().get_name();
|
||||||
|
if kind == "array" {
|
||||||
require_mut_array!(dest, dest_array, stack, "acopy");
|
require_mut_array!(dest, dest_array, stack, "acopy");
|
||||||
require_array_on_stack!(src, stack, "acopy");
|
require_array_on_stack!(src, stack, "acopy");
|
||||||
let offset = idx_dest - idx_src;
|
let offset = idx_dest - idx_src;
|
||||||
|
@ -805,6 +867,14 @@ pub fn acopy(stack: &mut Stack) -> OError {
|
||||||
*dest.get_mut((i + offset) as usize).unwrap() = src.get(i as usize).unwrap().clone();
|
*dest.get_mut((i + offset) as usize).unwrap() = src.get(i as usize).unwrap().clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if kind == "bytearray" {
|
||||||
|
require_mut!(dest, ByteArray, dest_array, stack, "acopy");
|
||||||
|
require_byte_array_on_stack!(src, stack, "acopy");
|
||||||
|
let len = len as usize;
|
||||||
|
let idx_src = idx_src as usize;
|
||||||
|
let idx_dest = idx_dest as usize;
|
||||||
|
(&mut dest[idx_dest..idx_dest + len]).clone_from_slice(&src[idx_src..idx_src + len]);
|
||||||
|
}
|
||||||
stack.push(dest_array);
|
stack.push(dest_array);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -997,7 +1067,7 @@ pub fn from_properties(stack: &mut Stack) -> OError {
|
||||||
|
|
||||||
pub fn register(r: &mut Stack, o: Arc<Frame>) {
|
pub fn register(r: &mut Stack, o: Arc<Frame>) {
|
||||||
type Fn = fn(&mut Stack) -> OError;
|
type Fn = fn(&mut Stack) -> OError;
|
||||||
let fns: [(&str, Fn, u32); 61] = [
|
let fns: [(&str, Fn, u32); 63] = [
|
||||||
("pop", pop, 0),
|
("pop", pop, 0),
|
||||||
("dup", dup, 2),
|
("dup", dup, 2),
|
||||||
("dup2", dup2, 3),
|
("dup2", dup2, 3),
|
||||||
|
@ -1007,6 +1077,7 @@ pub fn register(r: &mut Stack, o: Arc<Frame>) {
|
||||||
("print", print, 0),
|
("print", print, 0),
|
||||||
("gettype", gettype, 1),
|
("gettype", gettype, 1),
|
||||||
("settype", settype, 1),
|
("settype", settype, 1),
|
||||||
|
("banew", barray_new, 1),
|
||||||
("anew", array_new, 1),
|
("anew", array_new, 1),
|
||||||
("array-len", array_len, 1),
|
("array-len", array_len, 1),
|
||||||
("array-get", array_get, 1),
|
("array-get", array_get, 1),
|
||||||
|
@ -1029,6 +1100,7 @@ pub fn register(r: &mut Stack, o: Arc<Frame>) {
|
||||||
("_double", to_double, 1),
|
("_double", to_double, 1),
|
||||||
("_array", to_array, 1),
|
("_array", to_array, 1),
|
||||||
("_str", to_str, 1),
|
("_str", to_str, 1),
|
||||||
|
("_barray", to_bytearray, 1),
|
||||||
("call", call, 0),
|
("call", call, 0),
|
||||||
("callp", callp, 0),
|
("callp", callp, 0),
|
||||||
("trace", trace, 1),
|
("trace", trace, 1),
|
||||||
|
|
|
@ -155,23 +155,16 @@ pub fn new_stream(stack: &mut Stack) -> OError {
|
||||||
|
|
||||||
pub fn write_stream(stack: &mut Stack) -> OError {
|
pub fn write_stream(stack: &mut Stack) -> OError {
|
||||||
require_on_stack!(id, Mega, stack, "write-stream");
|
require_on_stack!(id, Mega, stack, "write-stream");
|
||||||
require_array_on_stack!(a, stack, "write-stream");
|
require_byte_array_on_stack!(a, stack, "write-stream");
|
||||||
let stream = runtime(|rt| {
|
let stream = runtime(|rt| {
|
||||||
rt.get_stream(id as u128)
|
rt.get_stream(id as u128)
|
||||||
.ok_or_else(|| stack.error(ErrorKind::VariableNotFound(format!("__stream-{id}"))))
|
.ok_or_else(|| stack.error(ErrorKind::VariableNotFound(format!("__stream-{id}"))))
|
||||||
})?;
|
})?;
|
||||||
let mut fixed = Vec::with_capacity(a.len());
|
|
||||||
for item in a.iter() {
|
|
||||||
match item.lock_ro().native {
|
|
||||||
Value::Int(x) => fixed.push(x as u8),
|
|
||||||
_ => type_err!(stack, "!int", "int"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stack.push(
|
stack.push(
|
||||||
Value::Mega(
|
Value::Mega(
|
||||||
stream
|
stream
|
||||||
.lock()
|
.lock()
|
||||||
.write(&fixed[..])
|
.write(&a)
|
||||||
.map_err(|x| stack.error(ErrorKind::IO(format!("{x:?}"))))? as i128,
|
.map_err(|x| stack.error(ErrorKind::IO(format!("{x:?}"))))? as i128,
|
||||||
)
|
)
|
||||||
.spl(),
|
.spl(),
|
||||||
|
@ -182,21 +175,14 @@ pub fn write_stream(stack: &mut Stack) -> OError {
|
||||||
|
|
||||||
pub fn write_all_stream(stack: &mut Stack) -> OError {
|
pub fn write_all_stream(stack: &mut Stack) -> OError {
|
||||||
require_on_stack!(id, Mega, stack, "write-all-stream");
|
require_on_stack!(id, Mega, stack, "write-all-stream");
|
||||||
require_array_on_stack!(a, stack, "write-all-stream");
|
require_byte_array_on_stack!(a, stack, "write-all-stream");
|
||||||
let stream = runtime(|rt| {
|
let stream = runtime(|rt| {
|
||||||
rt.get_stream(id as u128)
|
rt.get_stream(id as u128)
|
||||||
.ok_or_else(|| stack.error(ErrorKind::VariableNotFound(format!("__stream-{id}"))))
|
.ok_or_else(|| stack.error(ErrorKind::VariableNotFound(format!("__stream-{id}"))))
|
||||||
})?;
|
})?;
|
||||||
let mut fixed = Vec::with_capacity(a.len());
|
|
||||||
for item in a.iter() {
|
|
||||||
match item.lock_ro().native {
|
|
||||||
Value::Int(x) => fixed.push(x as u8),
|
|
||||||
_ => type_err!(stack, "!int", "int"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stream
|
stream
|
||||||
.lock()
|
.lock()
|
||||||
.write_all(&fixed[..])
|
.write_all(&a)
|
||||||
.map_err(|x| stack.error(ErrorKind::IO(format!("{x:?}"))))?;
|
.map_err(|x| stack.error(ErrorKind::IO(format!("{x:?}"))))?;
|
||||||
black_box(&stream.lock_ro()._writer_storage);
|
black_box(&stream.lock_ro()._writer_storage);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -219,12 +205,13 @@ pub fn flush_stream(stack: &mut Stack) -> OError {
|
||||||
pub fn read_stream(stack: &mut Stack) -> OError {
|
pub fn read_stream(stack: &mut Stack) -> OError {
|
||||||
require_on_stack!(id, Mega, stack, "read-stream");
|
require_on_stack!(id, Mega, stack, "read-stream");
|
||||||
let array = stack.pop();
|
let array = stack.pop();
|
||||||
{
|
let kind = array.lock_ro().kind.lock_ro().get_name();
|
||||||
|
let stream = runtime(|rt| {
|
||||||
|
rt.get_stream(id as u128)
|
||||||
|
.ok_or_else(|| stack.error(ErrorKind::VariableNotFound(format!("__stream-{id}"))))
|
||||||
|
})?;
|
||||||
|
if kind == "array" {
|
||||||
require_mut_array!(a, array, stack, "read-stream");
|
require_mut_array!(a, array, stack, "read-stream");
|
||||||
let stream = runtime(|rt| {
|
|
||||||
rt.get_stream(id as u128)
|
|
||||||
.ok_or_else(|| stack.error(ErrorKind::VariableNotFound(format!("__stream-{id}"))))
|
|
||||||
})?;
|
|
||||||
let mut vec = vec![0; a.len()];
|
let mut vec = vec![0; a.len()];
|
||||||
stack.push(
|
stack.push(
|
||||||
Value::Mega(
|
Value::Mega(
|
||||||
|
@ -242,6 +229,19 @@ pub fn read_stream(stack: &mut Stack) -> OError {
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if kind == "bytearray" {
|
||||||
|
require_mut!(a, ByteArray, array, stack, "read-stream");
|
||||||
|
stack.push(
|
||||||
|
Value::Mega(
|
||||||
|
stream
|
||||||
|
.lock()
|
||||||
|
.read(a)
|
||||||
|
.map_err(|x| stack.error(ErrorKind::IO(format!("{x:?}"))))?
|
||||||
|
as i128,
|
||||||
|
)
|
||||||
|
.spl(),
|
||||||
|
);
|
||||||
|
}
|
||||||
stack.push(array);
|
stack.push(array);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -249,12 +249,13 @@ pub fn read_stream(stack: &mut Stack) -> OError {
|
||||||
pub fn read_all_stream(stack: &mut Stack) -> OError {
|
pub fn read_all_stream(stack: &mut Stack) -> OError {
|
||||||
require_on_stack!(id, Mega, stack, "read-all-stream");
|
require_on_stack!(id, Mega, stack, "read-all-stream");
|
||||||
let array = stack.pop();
|
let array = stack.pop();
|
||||||
{
|
let kind = array.lock_ro().kind.lock_ro().get_name();
|
||||||
|
let stream = runtime(|rt| {
|
||||||
|
rt.get_stream(id as u128)
|
||||||
|
.ok_or_else(|| stack.error(ErrorKind::VariableNotFound(format!("__stream-{id}"))))
|
||||||
|
})?;
|
||||||
|
if kind == "array" {
|
||||||
require_mut_array!(a, array, stack, "read-all-stream");
|
require_mut_array!(a, array, stack, "read-all-stream");
|
||||||
let stream = runtime(|rt| {
|
|
||||||
rt.get_stream(id as u128)
|
|
||||||
.ok_or_else(|| stack.error(ErrorKind::VariableNotFound(format!("__stream-{id}"))))
|
|
||||||
})?;
|
|
||||||
let mut vec = vec![0; a.len()];
|
let mut vec = vec![0; a.len()];
|
||||||
stream
|
stream
|
||||||
.lock()
|
.lock()
|
||||||
|
@ -266,6 +267,13 @@ pub fn read_all_stream(stack: &mut Stack) -> OError {
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if kind == "bytearray" {
|
||||||
|
require_mut!(a, ByteArray, array, stack, "read-stream");
|
||||||
|
stream
|
||||||
|
.lock()
|
||||||
|
.read_exact(a)
|
||||||
|
.map_err(|x| stack.error(ErrorKind::IO(format!("{x:?}"))))?;
|
||||||
|
}
|
||||||
stack.push(array);
|
stack.push(array);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue