From e037dbabe98dbdb3f2c1c7fe82ccb4868f180c5a Mon Sep 17 00:00:00 2001 From: TudbuT Date: Sat, 25 Feb 2023 12:41:02 +0100 Subject: [PATCH] stream api fixes, str-to-bytes, bytes-to-str --- src/dyn_fns.rs | 12 +++++------- src/lib.rs | 12 ++++++++---- src/runtime.rs | 4 ++-- src/std_fns.rs | 36 ++++++++++++++++++++++++++++++++++-- src/stream.rs | 37 ++++++++++++++++++------------------- std.spl | 11 ++++++++--- test.spl | 2 +- test.txt | 2 +- 8 files changed, 77 insertions(+), 39 deletions(-) diff --git a/src/dyn_fns.rs b/src/dyn_fns.rs index 089472f..ec23a8e 100644 --- a/src/dyn_fns.rs +++ b/src/dyn_fns.rs @@ -235,13 +235,11 @@ pub fn dyn_readf(stack: &mut Stack) -> OError { } fn wrap(f: fn(&mut Stack) -> OError) -> impl Fn(&mut Stack) -> OError { - move |stack| { - unsafe { - let frame = stack.pop_frame(0); - let r = f(stack); - stack.push_frame(frame); - r - } + move |stack| unsafe { + let frame = stack.pop_frame(0); + let r = f(stack); + stack.push_frame(frame); + r } } diff --git a/src/lib.rs b/src/lib.rs index c59acf3..60a60b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,7 +46,8 @@ pub fn start_file_in_runtime(path: &str) -> Result { #[macro_export] macro_rules! require_on_stack { ($name:tt, $type:tt, $stack:expr, $fn:literal) => { - let Value::$type($name) = $stack.pop().lock_ro().native.clone() else { + let Value::$type($name) + = $stack.pop().lock_ro().native.clone() else { return $stack.err(ErrorKind::InvalidCall($fn.to_owned())) }; }; @@ -54,7 +55,8 @@ macro_rules! require_on_stack { #[macro_export] macro_rules! require_int_on_stack { ($name:tt, $stack:expr, $fn:literal) => { - let Value::Int($name) = $stack.pop().lock_ro().native.clone().try_mega_to_int() else { + let Value::Int($name) + = $stack.pop().lock_ro().native.clone().try_mega_to_int() else { return $stack.err(ErrorKind::InvalidCall($fn.to_owned())) }; }; @@ -62,7 +64,8 @@ macro_rules! require_int_on_stack { #[macro_export] macro_rules! require_array { ($name:tt, $array:expr, $stack:expr, $fn:literal) => { - let Value::Array(ref $name) = $array.lock_ro().native else { + let Value::Array(ref $name) + = $array.lock_ro().native else { return $stack.err(ErrorKind::InvalidCall($fn.to_owned())) }; }; @@ -70,7 +73,8 @@ macro_rules! require_array { #[macro_export] macro_rules! require_mut_array { ($name:tt, $array:expr, $stack:expr, $fn:literal) => { - let Value::Array(ref mut $name) = $array.lock().native else { + let Value::Array(ref mut $name) + = $array.lock().native else { return $stack.err(ErrorKind::InvalidCall($fn.to_owned())) }; }; diff --git a/src/runtime.rs b/src/runtime.rs index 2958920..66d7bad 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -6,7 +6,8 @@ use crate::{ }; use core::panic; -use std::sync::{RwLockWriteGuard, RwLockReadGuard}; +use std::collections::VecDeque; +use std::sync::{RwLockReadGuard, RwLockWriteGuard}; use std::{ cell::RefCell, collections::HashMap, @@ -14,7 +15,6 @@ use std::{ sync::Arc, vec, }; -use std::collections::VecDeque; use std::{env::var, mem, path::Path}; pub type AMObject = Arc>; diff --git a/src/std_fns.rs b/src/std_fns.rs index c74f683..61c4aa5 100644 --- a/src/std_fns.rs +++ b/src/std_fns.rs @@ -8,7 +8,7 @@ use std::{ sync::Arc, }; -use crate::{dyn_fns, mutex::Mut, runtime::*}; +use crate::{dyn_fns, mutex::Mut, runtime::*, *}; #[macro_export] macro_rules! type_err { @@ -638,6 +638,8 @@ pub fn command_wait(stack: &mut Stack) -> OError { for item in a.into_iter() { if let Value::Str(ref s) = item.lock_ro().native { args.push(s.to_owned()); + } else { + return stack.err(ErrorKind::InvalidCall("command".to_owned())); } } if args.len() < 1 { @@ -662,9 +664,37 @@ pub fn command_wait(stack: &mut Stack) -> OError { Ok(()) } +pub fn str_to_bytes(stack: &mut Stack) -> OError { + require_on_stack!(s, Str, stack, "str-to-bytes"); + stack.push( + Value::Array( + s.bytes() + .into_iter() + .map(|x| Value::Int(x as i32).spl()) + .collect(), + ) + .spl(), + ); + Ok(()) +} + +pub fn bytes_to_str(stack: &mut Stack) -> OError { + require_array_on_stack!(a, stack, "str-to-bytes"); + let mut chars = Vec::new(); + for item in a.into_iter() { + if let Value::Int(x) = item.lock_ro().native.clone().try_mega_to_int() { + 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()); + Ok(()) +} + pub fn register(r: &mut Stack, o: Arc) { type Fn = fn(&mut Stack) -> OError; - let fns: [(&str, Fn, u32); 46] = [ + let fns: [(&str, Fn, u32); 48] = [ ("pop", pop, 0), ("dup", dup, 2), ("clone", clone, 1), @@ -711,6 +741,8 @@ pub fn register(r: &mut Stack, o: Arc) { ("readln", readln, 1), ("command", command, 0), ("command-wait", command_wait, 1), + ("str-to-bytes", str_to_bytes, 1), + ("bytes-to-str", bytes_to_str, 1), ]; for f in fns { r.define_func( diff --git a/src/stream.rs b/src/stream.rs index 46c1188..f6017da 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -1,10 +1,10 @@ use std::{ collections::HashMap, - fs::{OpenOptions}, + fs::OpenOptions, io::Read, io::Write, mem, - net::{TcpStream, Shutdown}, + net::{Shutdown, TcpStream}, sync::Arc, }; @@ -58,7 +58,11 @@ impl Stream { close, } } - pub fn new_split(reader: impl Read + 'static, writer: impl Write + 'static, close: fn(&mut Self)) -> Self { + pub fn new_split( + reader: impl Read + 'static, + writer: impl Write + 'static, + close: fn(&mut Self), + ) -> Self { Self { reader: Box::new(reader), writer: Box::new(writer), @@ -125,15 +129,9 @@ where pub fn new_stream(stack: &mut Stack) -> OError { require_on_stack!(s, Str, stack, "write-stream"); let stream = get_stream_type(s.clone()) - .ok_or_else(|| { - stack.error(ErrorKind::VariableNotFound(format!("__stream-type-{s}"))) - })? + .ok_or_else(|| stack.error(ErrorKind::VariableNotFound(format!("__stream-type-{s}"))))? .make_stream(stack)?; - let stream = runtime_mut(move |mut rt| { - Ok(rt.register_stream( - stream - )) - })?; + let stream = runtime_mut(move |mut rt| Ok(rt.register_stream(stream)))?; stack.push(Value::Mega(stream.0 as i128).spl()); Ok(()) } @@ -200,7 +198,8 @@ pub fn read_stream(stack: &mut Stack) -> OError { stream .lock() .read(&mut vec[..]) - .map_err(|x| stack.error(ErrorKind::IO(format!("{x:?}"))))? as i128, + .map_err(|x| stack.error(ErrorKind::IO(format!("{x:?}"))))? + as i128, ) .spl(), ); @@ -240,16 +239,14 @@ pub fn read_all_stream(stack: &mut Stack) -> OError { pub fn close_stream(stack: &mut Stack) -> OError { require_on_stack!(id, Mega, stack, "close-stream"); - if let Some(stream) = runtime(|rt| { - rt.get_stream(id as u128) - }) { + if let Some(stream) = runtime(|rt| rt.get_stream(id as u128)) { let mut stream = stream.lock(); (stream.close)(&mut stream); } Ok(()) } -fn nop(_stream: &mut Stream) {} +fn nop(_stream: &mut Stream) {} fn stream_file(stack: &mut Stack) -> Result { let truncate = stack.pop().lock_ro().is_truthy(); @@ -262,7 +259,7 @@ fn stream_file(stack: &mut Stack) -> Result { .truncate(truncate) .open(path) .map_err(|x| stack.error(ErrorKind::IO(x.to_string())))?, - nop + nop, )) } @@ -271,14 +268,16 @@ fn stream_tcp(stack: &mut Stack) -> Result { require_on_stack!(ip, Str, stack, "TCP new-stream"); fn close_tcp(stream: &mut Stream) { unsafe { - let f = ((stream.reader.as_mut() as *mut dyn Read).cast() as *mut TcpStream).as_mut().unwrap(); + let f = ((stream.reader.as_mut() as *mut dyn Read).cast() as *mut TcpStream) + .as_mut() + .unwrap(); let _ = f.shutdown(Shutdown::Both); } } Ok(Stream::new( TcpStream::connect((ip, port as u16)) .map_err(|x| stack.error(ErrorKind::IO(x.to_string())))?, - close_tcp + close_tcp, )) } diff --git a/std.spl b/std.spl index 9291742..b75dd12 100644 --- a/std.spl +++ b/std.spl @@ -8,9 +8,13 @@ func println { | print "\n" print } -{ any | with type ; - null clone type settype "construct" dyn-objcall -} "new" "str" dyn-def-method +construct _str_ext { + ; + new { any | with this ; + null clone this settype "construct" dyn-objcall + } + to-bytes { [int] | str-to-bytes } +} include _str_ext in str construct _mega-ext { ; @@ -51,6 +55,7 @@ construct _array-ext { def i 0 =i while { i this:len lt } { i this:get callable call i ++ =i } } + to-str { str | bytes-to-str } 0 { any | with this ; 0 this:get } diff --git a/test.spl b/test.spl index fbd4ba4..aa77d5a 100644 --- a/test.spl +++ b/test.spl @@ -104,7 +104,7 @@ func main { int | with args ; "testing stream" println def file "test.txt" 1 StreamTypes:file:create =file - "hi" _array file:write-exact; + "hi\n" _:to-bytes file:write-exact; file:close null =file "" println diff --git a/test.txt b/test.txt index 32f95c0..45b983b 100644 --- a/test.txt +++ b/test.txt @@ -1 +1 @@ -hi \ No newline at end of file +hi