more http progress
This commit is contained in:
parent
75a54d3dfd
commit
954f817437
10 changed files with 287 additions and 84 deletions
53
http.spl
53
http.spl
|
@ -6,6 +6,7 @@
|
|||
construct net:http namespace {
|
||||
Request
|
||||
Response
|
||||
help
|
||||
}
|
||||
|
||||
construct net:http:Request {
|
||||
|
@ -58,22 +59,68 @@ construct net:http:Request {
|
|||
body stream:write-exact;
|
||||
stream:flush;
|
||||
|
||||
1024 stream:read-to-end:to-str println
|
||||
def response 1024 stream:read-to-end =response
|
||||
|
||||
response net:http:Response:new:read-from-bytes
|
||||
|
||||
stream:close;
|
||||
}
|
||||
}
|
||||
|
||||
"todo" panic
|
||||
construct net:http:help namespace {
|
||||
;
|
||||
assert-str { | with expected iter _ ;
|
||||
[ { | pop iter:next } (expected _array):len:foreach ] _str
|
||||
expected _str
|
||||
eq not if {
|
||||
"Expected " expected concat throw
|
||||
}
|
||||
}
|
||||
until-str { str | with expected iter _ ;
|
||||
def match 0 =match
|
||||
def bytes expected:to-bytes =bytes
|
||||
[
|
||||
while { match bytes:len eq not } {
|
||||
iter:next dup (match bytes:get) eq dup if {
|
||||
match ++ =match
|
||||
} not if {
|
||||
0 =match
|
||||
}
|
||||
}
|
||||
{ | pop pop } match:foreach
|
||||
] _str
|
||||
}
|
||||
}
|
||||
|
||||
construct net:http:Response {
|
||||
version
|
||||
state-num state-msg
|
||||
headers
|
||||
body
|
||||
;
|
||||
construct { this | with this ;
|
||||
List:new this:=headers
|
||||
MicroMap:new this:=headers
|
||||
"" this:=body
|
||||
this
|
||||
}
|
||||
read-from-bytes { this | with bytes this ;
|
||||
use net:http:help
|
||||
bytes:iter =bytes
|
||||
"HTTP/" bytes help:assert-str
|
||||
" " bytes help:until-str this:=version
|
||||
" " bytes help:until-str _mega this:=state-num
|
||||
"\r\n" bytes help:until-str this:=state-msg
|
||||
while { "\r\n" bytes help:until-str dup "" eq not } {
|
||||
def iter ": " swap:split:iter =iter
|
||||
(
|
||||
iter:next ": "
|
||||
iter:join
|
||||
) this:headers:set;
|
||||
} pop
|
||||
0 ("Content-Length" this:headers:get _mega) bytes:collect:sub this:=body
|
||||
this
|
||||
}
|
||||
content-type { str | with this ;
|
||||
"Content-Type" this:headers:get
|
||||
}
|
||||
}
|
||||
|
|
2
iter.spl
2
iter.spl
|
@ -31,7 +31,7 @@ construct _Iter {
|
|||
}
|
||||
join { str | with separator this ;
|
||||
{ str | with accum item ;
|
||||
accum _str separator item _str strconcat strconcat
|
||||
accum _str separator item _str concat concat
|
||||
} this:reduce:calculate
|
||||
}
|
||||
filter { FilterIter | with filter this ;
|
||||
|
|
2
spl.vim
2
spl.vim
|
@ -6,7 +6,7 @@ endif
|
|||
syn match Comment /".*?";/
|
||||
syn match Number /\<[0-9._]*\>/
|
||||
syn match Function /\<func[ \n]\+[^ ]\+[ \n]\+{ .*[ ]*|\|{ .*[ ]*|\|{\|}/
|
||||
syn keyword Keyword while if exit eq lt gt neg or and not + - * ++ -- % / with namespace
|
||||
syn keyword Keyword while if exit eq lt gt neg or and not + - * ++ -- % / with namespace catch use
|
||||
syn match Keyword /;/
|
||||
syn keyword Type pop dup swap
|
||||
syn match Type /=[a-zA-Z0-9_\-]\+\|\<_[a-zA-Z0-9_\-]\+\>/
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use crate::{lexer, runtime::*};
|
||||
use crate::*;
|
||||
|
||||
pub fn dyn_dump(stack: &mut Stack) -> OError {
|
||||
Words {
|
||||
|
@ -76,11 +77,8 @@ pub fn dyn_def_field(stack: &mut Stack) -> OError {
|
|||
) else {
|
||||
return stack.err(ErrorKind::InvalidCall("dyn-def-field".to_owned()))
|
||||
};
|
||||
runtime(|rt| rt.get_type_by_name(s.to_owned()))
|
||||
.ok_or_else(|| Error {
|
||||
kind: ErrorKind::TypeNotFound(s),
|
||||
stack: stack.trace(),
|
||||
})?
|
||||
runtime(|rt| rt.get_type_by_name(&s))
|
||||
.ok_or_else(|| stack.error(ErrorKind::TypeNotFound(s)))?
|
||||
.lock()
|
||||
.add_property(name, stack.get_frame())?;
|
||||
Ok(())
|
||||
|
@ -98,11 +96,8 @@ pub fn dyn_def_method(stack: &mut Stack) -> OError {
|
|||
) else {
|
||||
return stack.err(ErrorKind::InvalidCall("dyn-def-method".to_owned()))
|
||||
};
|
||||
runtime(|rt| rt.get_type_by_name(s.to_owned()))
|
||||
.ok_or_else(|| Error {
|
||||
kind: ErrorKind::TypeNotFound(s),
|
||||
stack: stack.trace(),
|
||||
})?
|
||||
runtime(|rt| rt.get_type_by_name(&s))
|
||||
.ok_or_else(|| stack.error(ErrorKind::TypeNotFound(s)))?
|
||||
.lock()
|
||||
.functions
|
||||
.insert(name, f);
|
||||
|
@ -214,10 +209,9 @@ pub fn dyn_read(stack: &mut Stack) -> OError {
|
|||
stack.push(
|
||||
Value::Func(AFunc::new(Func {
|
||||
ret_count: 0,
|
||||
to_call: FuncImpl::SPL(lexer::lex(s).map_err(|x| Error {
|
||||
kind: ErrorKind::LexError(format!("{x:?}")),
|
||||
stack: stack.trace(),
|
||||
})?),
|
||||
to_call: FuncImpl::SPL(
|
||||
lexer::lex(s).map_err(|x| stack.error(ErrorKind::LexError(format!("{x:?}"))))?,
|
||||
),
|
||||
run_as_base: false,
|
||||
origin: stack.get_frame(),
|
||||
fname: None,
|
||||
|
@ -241,10 +235,9 @@ pub fn dyn_readf(stack: &mut Stack) -> OError {
|
|||
stack.push(
|
||||
Value::Func(AFunc::new(Func {
|
||||
ret_count: 0,
|
||||
to_call: FuncImpl::SPL(lexer::lex(s).map_err(|x| Error {
|
||||
kind: ErrorKind::LexError(format!("{x:?}")),
|
||||
stack: stack.trace(),
|
||||
})?),
|
||||
to_call: FuncImpl::SPL(
|
||||
lexer::lex(s).map_err(|x| stack.error(ErrorKind::LexError(format!("{x:?}"))))?,
|
||||
),
|
||||
run_as_base: true,
|
||||
origin: stack.get_frame(),
|
||||
fname: Some(n),
|
||||
|
@ -255,6 +248,27 @@ pub fn dyn_readf(stack: &mut Stack) -> OError {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn dyn_catch(stack: &mut Stack) -> OError {
|
||||
require_on_stack!(ctch, Func, stack, "dyn-catch");
|
||||
require_on_stack!(blk, Func, stack, "dyn-catch");
|
||||
require_on_stack!(types, Array, stack, "dyn-catch");
|
||||
if let Err(e) = blk.to_call.call(stack) {
|
||||
if types.is_empty() || types.contains(&e.kind.to_string().spl()) {
|
||||
stack.push(e.spl());
|
||||
ctch.to_call.call(stack)
|
||||
} else {
|
||||
Err(e)
|
||||
}
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dyn_use(stack: &mut Stack) -> OError {
|
||||
require_on_stack!(item, Str, stack, "dyn-use");
|
||||
Words::new(vec![Word::Key(Keyword::Use(item))]).exec(stack)
|
||||
}
|
||||
|
||||
pub(crate) fn wrap(f: fn(&mut Stack) -> OError) -> impl Fn(&mut Stack) -> OError {
|
||||
move |stack| unsafe {
|
||||
let frame = stack.pop_frame(0);
|
||||
|
@ -266,7 +280,7 @@ pub(crate) fn wrap(f: fn(&mut Stack) -> OError) -> impl Fn(&mut Stack) -> OError
|
|||
|
||||
pub fn register(r: &mut Stack, o: Arc<Frame>) {
|
||||
type Fn = fn(&mut Stack) -> OError;
|
||||
let fns: [(&str, Fn, u32); 15] = [
|
||||
let fns: [(&str, Fn, u32); 17] = [
|
||||
("dyn-__dump", dyn_dump, 0),
|
||||
("dyn-def", dyn_def, 0),
|
||||
("dyn-func", dyn_func, 0),
|
||||
|
@ -282,6 +296,8 @@ pub fn register(r: &mut Stack, o: Arc<Frame>) {
|
|||
("dyn-all-types", dyn_all_types, 1),
|
||||
("dyn-read", dyn_read, 1),
|
||||
("dyn-readf", dyn_readf, 1),
|
||||
("dyn-catch", dyn_catch, 0),
|
||||
("dyn-use", dyn_use, 0),
|
||||
];
|
||||
for f in fns {
|
||||
r.define_func(
|
||||
|
|
17
src/lexer.rs
17
src/lexer.rs
|
@ -121,6 +121,11 @@ fn read_block(str_words: &[String], isfn: bool) -> Result<(Option<u32>, Words, u
|
|||
}
|
||||
i += 3;
|
||||
}
|
||||
"use" => {
|
||||
let item = str_words[i + 1].to_owned();
|
||||
i += 1;
|
||||
words.push(Word::Key(Keyword::Use(item)));
|
||||
}
|
||||
"while" => {
|
||||
let cond = read_block(&str_words[i + 2..], false)?;
|
||||
i += 2 + cond.2;
|
||||
|
@ -133,6 +138,18 @@ fn read_block(str_words: &[String], isfn: bool) -> Result<(Option<u32>, Words, u
|
|||
i += 2 + blk.2;
|
||||
words.push(Word::Key(Keyword::If(blk.1)));
|
||||
}
|
||||
"catch" => {
|
||||
let mut types = Vec::new();
|
||||
i += 1;
|
||||
while &str_words[i] != "{" {
|
||||
types.push(str_words[i].to_owned());
|
||||
i += 1;
|
||||
}
|
||||
let blk = read_block(&str_words[i..], false)?;
|
||||
i += 2 + blk.2;
|
||||
let ctch = read_block(&str_words[i..], false)?;
|
||||
words.push(Word::Key(Keyword::Catch(types, blk.1, ctch.1)))
|
||||
}
|
||||
"with" => {
|
||||
let mut vars = Vec::new();
|
||||
i += 1;
|
||||
|
|
|
@ -63,7 +63,7 @@ pub fn start_file_in_runtime(path: &str) -> Result<Stack, Error> {
|
|||
Ok(stack)
|
||||
}
|
||||
|
||||
/// Inćlude the standard library in a runtime-stack-pair, where the runtime has been .set().
|
||||
/// Include the standard library in a runtime-stack-pair, where the runtime has been .set().
|
||||
pub fn add_std(stack: &mut Stack) -> OError {
|
||||
let f = find_in_splpath("std.spl");
|
||||
let words = lex(if let Ok(f) = f {
|
||||
|
@ -71,10 +71,7 @@ pub fn add_std(stack: &mut Stack) -> OError {
|
|||
} else {
|
||||
f.unwrap_err()
|
||||
})
|
||||
.map_err(|x| Error {
|
||||
kind: ErrorKind::LexError(format!("{x:?}")),
|
||||
stack: Vec::new(),
|
||||
})?;
|
||||
.map_err(|x| stack.error(ErrorKind::LexError(format!("{x:?}"))))?;
|
||||
words.exec(stack)
|
||||
}
|
||||
|
||||
|
@ -94,6 +91,7 @@ nofmt! {
|
|||
};
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! require_int_on_stack {
|
||||
($name:tt, $stack:expr, $fn:literal) => {
|
||||
|
|
147
src/runtime.rs
147
src/runtime.rs
|
@ -46,6 +46,10 @@ pub fn runtime_mut<T>(f: impl FnOnce(RwLockWriteGuard<Runtime>) -> T) -> T {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn get_type(name: &str) -> Option<AMType> {
|
||||
runtime(|rt| rt.get_type_by_name(name))
|
||||
}
|
||||
|
||||
/// An SPL runtime.
|
||||
///
|
||||
/// This holds:
|
||||
|
@ -99,8 +103,8 @@ impl Runtime {
|
|||
rt
|
||||
}
|
||||
|
||||
pub fn get_type_by_name(&self, name: String) -> Option<AMType> {
|
||||
self.types_by_name.get(&name).cloned()
|
||||
pub fn get_type_by_name(&self, name: &str) -> Option<AMType> {
|
||||
self.types_by_name.get(name).cloned()
|
||||
}
|
||||
|
||||
pub fn get_type_by_id(&self, id: u32) -> Option<AMType> {
|
||||
|
@ -166,7 +170,7 @@ impl SetRuntime for Arc<Mut<Runtime>> {
|
|||
}
|
||||
|
||||
/// A frame's location in SPL code.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct FrameInfo {
|
||||
pub file: String,
|
||||
pub function: String,
|
||||
|
@ -288,10 +292,7 @@ impl Frame {
|
|||
if let Some(ref x) = frame.parent {
|
||||
frame = x;
|
||||
} else {
|
||||
return Err(Error {
|
||||
kind: ErrorKind::VariableNotFound(name),
|
||||
stack: stack.trace(),
|
||||
});
|
||||
return Err(stack.error(ErrorKind::VariableNotFound(name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -305,10 +306,7 @@ impl Frame {
|
|||
if let Some(ref x) = frame.parent {
|
||||
frame = x;
|
||||
} else {
|
||||
return Err(Error {
|
||||
kind: ErrorKind::VariableNotFound(name),
|
||||
stack: stack.trace(),
|
||||
});
|
||||
return Err(stack.error(ErrorKind::VariableNotFound(name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -457,10 +455,7 @@ impl Stack {
|
|||
if let Some(ref x) = frame.parent {
|
||||
frame = x;
|
||||
} else {
|
||||
return Err(Error {
|
||||
kind: ErrorKind::FuncNotFound(name),
|
||||
stack: self.trace(),
|
||||
});
|
||||
return Err(self.error(ErrorKind::FuncNotFound(name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -553,6 +548,7 @@ impl Stack {
|
|||
Err(Error {
|
||||
kind,
|
||||
stack: self.trace(),
|
||||
mr_stack: self.mr_trace(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -560,6 +556,7 @@ impl Stack {
|
|||
Error {
|
||||
kind,
|
||||
stack: self.trace(),
|
||||
mr_stack: self.mr_trace(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,7 +617,7 @@ pub enum Keyword {
|
|||
/// def <name>
|
||||
///
|
||||
/// Defines a variable.
|
||||
/// equivalent to <name> dyn-def
|
||||
/// equivalent to "<name>" dyn-def
|
||||
Def(String),
|
||||
/// func <name> { <rem> | <words> }
|
||||
///
|
||||
|
@ -639,6 +636,10 @@ pub enum Keyword {
|
|||
/// Adds <typeA> as a parent type of <typeB>.
|
||||
/// equivalent to "<typeA>" "<typeB>" dyn-include
|
||||
Include(String, String),
|
||||
/// use <path>:<item>
|
||||
///
|
||||
/// equivalent to "<path>:<item>" dyn-use
|
||||
Use(String),
|
||||
/// while { <wordsA> } { <wordsB> }
|
||||
///
|
||||
/// If wordsA result in a truthy value being on the top of the stack, execute wordsB, and
|
||||
|
@ -656,6 +657,12 @@ pub enum Keyword {
|
|||
/// equivalent to def <...> =<...> def <item> =<item>
|
||||
/// or "<...>" dyn-def "=<...>" dyn-call "<item>" dyn-def "=<item>" dyn-call
|
||||
With(Vec<String>),
|
||||
/// catch [<type> <...>] { <code> } with { <wordsOnCatch> }
|
||||
///
|
||||
/// Catches errors that happen within <code>, running <wordsOnCatch> when an error is
|
||||
/// encountered and the error is of <type> (or, if no type is specified, any error).
|
||||
/// equivalent to \[ ["<type>" <...>] \] { | <code> } { | <wordsOnCatch> } dyn-catch
|
||||
Catch(Vec<String>, Words, Words),
|
||||
}
|
||||
|
||||
/// Any SPL value that is not a construct.
|
||||
|
@ -978,6 +985,34 @@ impl Object {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<String> for Object {
|
||||
fn from(value: String) -> Self {
|
||||
Value::Str(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FrameInfo> for Object {
|
||||
fn from(value: FrameInfo) -> Self {
|
||||
let mut obj = Object::new(
|
||||
get_type("FrameInfo").expect("FrameInfo type must exist"),
|
||||
Value::Null,
|
||||
);
|
||||
obj.property_map.insert("file".to_owned(), value.file.spl());
|
||||
obj.property_map
|
||||
.insert("function".to_owned(), value.function.spl());
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Vec<T>> for Object
|
||||
where
|
||||
T: Into<Object>,
|
||||
{
|
||||
fn from(value: Vec<T>) -> Self {
|
||||
Value::Array(value.into_iter().map(|x| x.spl()).collect()).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Value> for Object {
|
||||
fn from(value: Value) -> Self {
|
||||
Object::new(
|
||||
|
@ -1105,17 +1140,32 @@ impl Words {
|
|||
Keyword::Include(ta, tb) => {
|
||||
let rstack = &stack;
|
||||
runtime(move |rt| {
|
||||
rt.get_type_by_name(tb.clone())
|
||||
rt.get_type_by_name(&tb)
|
||||
.ok_or_else(|| rstack.error(ErrorKind::TypeNotFound(tb)))?
|
||||
.lock()
|
||||
.parents
|
||||
.push(
|
||||
rt.get_type_by_name(ta.clone())
|
||||
rt.get_type_by_name(&ta)
|
||||
.ok_or_else(|| rstack.error(ErrorKind::TypeNotFound(ta)))?,
|
||||
);
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
Keyword::Use(item) => {
|
||||
if let Some((a, mut name)) = item.split_once(':') {
|
||||
let mut f = stack.get_var(a.to_owned())?;
|
||||
while let Some((a, b)) = name.split_once(':') {
|
||||
name = b;
|
||||
let o = f.lock_ro();
|
||||
let nf = o.field(a, stack)?;
|
||||
mem::drop(o);
|
||||
f = nf;
|
||||
}
|
||||
stack.define_var(name.to_owned());
|
||||
let o = f.lock_ro().field(name, stack)?.clone();
|
||||
stack.set_var(name.to_owned(), o)?;
|
||||
}
|
||||
}
|
||||
Keyword::While(cond, blk) => loop {
|
||||
cond.exec(stack)?;
|
||||
if !stack.pop().lock_ro().is_truthy() {
|
||||
|
@ -1123,6 +1173,7 @@ impl Words {
|
|||
}
|
||||
blk.exec(stack)?;
|
||||
if stack.return_accumultor > 0 {
|
||||
stack.return_accumultor -= 1;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
@ -1131,6 +1182,16 @@ impl Words {
|
|||
blk.exec(stack)?;
|
||||
}
|
||||
}
|
||||
Keyword::Catch(types, blk, ctch) => {
|
||||
if let Err(e) = blk.exec(stack) {
|
||||
if types.is_empty() || types.contains(&e.kind.to_string()) {
|
||||
stack.push(e.spl());
|
||||
ctch.exec(stack)?;
|
||||
} else {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Keyword::With(vars) => {
|
||||
for var in vars.into_iter().rev() {
|
||||
stack.define_var(var.clone());
|
||||
|
@ -1186,9 +1247,8 @@ impl Words {
|
|||
let f0 = o.kind.lock_ro();
|
||||
let f = f0
|
||||
.get_fn(x.clone())
|
||||
.ok_or_else(|| Error {
|
||||
kind: ErrorKind::MethodNotFound(f0.name.clone(), x.clone()),
|
||||
stack: stack.trace(),
|
||||
.ok_or_else(|| {
|
||||
stack.error(ErrorKind::MethodNotFound(f0.name.clone(), x.clone()))
|
||||
})?
|
||||
.clone();
|
||||
if option_env!("SPLDEBUG").is_some() {
|
||||
|
@ -1254,11 +1314,31 @@ pub enum ErrorKind {
|
|||
CustomObject(AMObject),
|
||||
}
|
||||
|
||||
impl Display for ErrorKind {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
ErrorKind::Parse(_, _) => f.write_str("Parse"),
|
||||
ErrorKind::InvalidCall(_) => f.write_str("InvalidCall"),
|
||||
ErrorKind::InvalidType(_, _) => f.write_str("InvalidType"),
|
||||
ErrorKind::VariableNotFound(_) => f.write_str("VariableNotFound"),
|
||||
ErrorKind::FuncNotFound(_) => f.write_str("FuncNotFound"),
|
||||
ErrorKind::MethodNotFound(_, _) => f.write_str("MethodNotFound"),
|
||||
ErrorKind::PropertyNotFound(_, _) => f.write_str("PropertyNotFound"),
|
||||
ErrorKind::TypeNotFound(_) => f.write_str("TypeNotFound"),
|
||||
ErrorKind::LexError(_) => f.write_str("LexError"),
|
||||
ErrorKind::IO(_) => f.write_str("IO"),
|
||||
ErrorKind::Custom(_) => f.write_str("Custom"),
|
||||
ErrorKind::CustomObject(_) => f.write_str("CustomObject"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper for ErrorKind with the stack trace.
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct Error {
|
||||
pub kind: ErrorKind,
|
||||
pub stack: Vec<String>,
|
||||
pub mr_stack: Vec<Vec<FrameInfo>>,
|
||||
}
|
||||
|
||||
impl Debug for Error {
|
||||
|
@ -1271,3 +1351,28 @@ impl Debug for Error {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for Object {
|
||||
fn from(value: Error) -> Self {
|
||||
let mut obj = Object::new(
|
||||
get_type("error").expect("error type must exist"),
|
||||
Value::Null,
|
||||
);
|
||||
obj.property_map
|
||||
.insert("kind".to_owned(), value.kind.to_string().spl());
|
||||
obj.property_map
|
||||
.insert("message".to_owned(), format!("{:?}", value.kind).spl());
|
||||
if let ErrorKind::CustomObject(ref o) = value.kind {
|
||||
obj.property_map.insert("object".to_owned(), o.clone());
|
||||
}
|
||||
if let ErrorKind::Custom(ref s) = value.kind {
|
||||
obj.property_map
|
||||
.insert("message".to_owned(), s.clone().spl());
|
||||
}
|
||||
obj.property_map
|
||||
.insert("trace".to_owned(), value.stack.spl());
|
||||
obj.property_map
|
||||
.insert("mr-trace".to_owned(), value.mr_stack.spl());
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,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 {
|
||||
|
@ -77,7 +72,7 @@ pub fn settype(stack: &mut Stack) -> OError {
|
|||
return stack.err(ErrorKind::InvalidCall("settype".to_owned()))
|
||||
};
|
||||
let o = stack.pop();
|
||||
let kind = runtime(|rt| rt.get_type_by_name(s.clone()))
|
||||
let kind = runtime(|rt| rt.get_type_by_name(&s))
|
||||
.ok_or_else(|| stack.error(ErrorKind::TypeNotFound(s)))?;
|
||||
let mut obj = o.lock();
|
||||
kind.lock_ro().write_into(&mut obj);
|
||||
|
@ -485,31 +480,11 @@ pub fn trace(stack: &mut Stack) -> OError {
|
|||
|
||||
pub fn mr_trace(stack: &mut Stack) -> OError {
|
||||
let trace = stack.mr_trace();
|
||||
let kind = runtime(|rt| rt.get_type_by_name("TraceElement".to_owned()))
|
||||
.ok_or_else(|| stack.error(ErrorKind::TypeNotFound("TraceElement".to_owned())))?;
|
||||
stack.push(
|
||||
Value::Array(
|
||||
trace
|
||||
.into_iter()
|
||||
.map(|x| {
|
||||
Value::Array(
|
||||
x.into_iter()
|
||||
.map(|x| {
|
||||
let item = Value::Null.spl();
|
||||
let mut obj = item.lock();
|
||||
kind.lock_ro().write_into(&mut obj);
|
||||
obj.kind = kind.clone();
|
||||
obj.property_map
|
||||
.insert("file".to_owned(), Value::Str(x.file).spl());
|
||||
obj.property_map
|
||||
.insert("function".to_owned(), Value::Str(x.function).spl());
|
||||
mem::drop(obj);
|
||||
item
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
.spl()
|
||||
})
|
||||
.map(|x| Value::Array(x.into_iter().map(|x| x.spl()).collect()).spl())
|
||||
.collect(),
|
||||
)
|
||||
.spl(),
|
||||
|
@ -784,9 +759,14 @@ pub fn acopy(stack: &mut Stack) -> OError {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn throw(stack: &mut Stack) -> OError {
|
||||
let kind = ErrorKind::CustomObject(stack.pop());
|
||||
stack.err(kind)
|
||||
}
|
||||
|
||||
pub fn register(r: &mut Stack, o: Arc<Frame>) {
|
||||
type Fn = fn(&mut Stack) -> OError;
|
||||
let fns: [(&str, Fn, u32); 49] = [
|
||||
let fns: [(&str, Fn, u32); 50] = [
|
||||
("pop", pop, 0),
|
||||
("dup", dup, 2),
|
||||
("clone", clone, 1),
|
||||
|
@ -836,6 +816,7 @@ pub fn register(r: &mut Stack, o: Arc<Frame>) {
|
|||
("str-to-bytes", str_to_bytes, 1),
|
||||
("bytes-to-str", bytes_to_str, 1),
|
||||
("acopy", acopy, 1),
|
||||
("throw", throw, 0),
|
||||
];
|
||||
for f in fns {
|
||||
r.define_func(
|
||||
|
|
41
std.spl
41
std.spl
|
@ -8,22 +8,57 @@ func println { |
|
|||
print "\n" print
|
||||
}
|
||||
|
||||
construct error {
|
||||
kind
|
||||
message
|
||||
object
|
||||
trace
|
||||
mr-trace
|
||||
}
|
||||
|
||||
construct FrameInfo {
|
||||
file
|
||||
function
|
||||
}
|
||||
|
||||
construct _str_ext {
|
||||
;
|
||||
new { any | with this ;
|
||||
null clone this settype:construct
|
||||
}
|
||||
to-bytes { [int] | str-to-bytes }
|
||||
split { str | with splitter this ;
|
||||
def bytes splitter:to-bytes =bytes
|
||||
def iter this:to-bytes:iter =iter
|
||||
def item 0 =item
|
||||
[ while { item null eq not } {
|
||||
def match 0 =match
|
||||
[
|
||||
while { match bytes:len eq not } {
|
||||
iter:next =item
|
||||
item null eq if {
|
||||
3 stop
|
||||
}
|
||||
item dup (match bytes:get) eq dup if {
|
||||
match ++ =match
|
||||
} not if {
|
||||
0 =match
|
||||
}
|
||||
}
|
||||
{ | pop pop } match:foreach
|
||||
] _str
|
||||
} ]
|
||||
}
|
||||
} include _str_ext in str
|
||||
|
||||
construct _mega-ext {
|
||||
;
|
||||
swap { .. | with this ;
|
||||
i mswap
|
||||
i -- mswap
|
||||
this mswap
|
||||
this -- mswap
|
||||
}
|
||||
mswap { .. | mswap }
|
||||
foreach { | with this ;
|
||||
foreach { | with callable this ;
|
||||
def i 0 =i
|
||||
while { i this lt } { i callable call i ++ =i }
|
||||
}
|
||||
|
|
8
test.spl
8
test.spl
|
@ -107,11 +107,15 @@ func main { int | with args ;
|
|||
"hi\n" _:to-bytes file:write-exact;
|
||||
file:close null =file
|
||||
|
||||
"" println
|
||||
"testing split" println
|
||||
{ | println } (" " "hello how are you" _:split):foreach
|
||||
"" println
|
||||
|
||||
use net:http:Request
|
||||
"testing http" println
|
||||
def req "tudbut.de" 80 "GET" "/" net:http:Request:new =req
|
||||
req:send
|
||||
def req "tudbut.de" 81 "GET" "/" Request:new =req
|
||||
req:send:body _str println
|
||||
"" println
|
||||
|
||||
100
|
||||
|
|
Loading…
Add table
Reference in a new issue