From 552b6c19e66051196d93b0d86b46aecf6e6a2561 Mon Sep 17 00:00:00 2001 From: linux_china Date: Fri, 26 Apr 2024 17:13:17 +0800 Subject: [PATCH] feat: add parse() and rparse() functions --- src/builtins.rs | 19 +++++++++++++++++++ src/bytecode.rs | 12 ++++++++++++ src/codegen/intrinsics.rs | 16 ++++++++++++++++ src/codegen/mod.rs | 12 ++++++++++++ src/compile.rs | 18 ++++++++++++++++++ src/dataflow.rs | 8 ++++++++ src/display.rs | 2 ++ src/interp.rs | 14 ++++++++++++++ 8 files changed, 101 insertions(+) diff --git a/src/builtins.rs b/src/builtins.rs index 0008323..422bc79 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -51,6 +51,8 @@ pub enum Function { Fend, Trim, Truncate, + Parse, + RegexParse, Strtonum, FormatBytes, ToBytes, @@ -404,6 +406,8 @@ static_map!( ["bf_contains", Function::BloomFilterContains], ["local_ip", Function::LocalIp], ["truncate", Function::Truncate], + ["parse", Function::Parse], + ["rparse", Function::RegexParse], ["strtonum", Function::Strtonum], ["format_bytes", Function::FormatBytes], ["to_bytes", Function::ToBytes], @@ -690,6 +694,8 @@ impl Function { Fend => (smallvec![Str], Str), Url | Path | SemVer => (smallvec![Str], MapStrStr), Pairs => (smallvec![Str,Str,Str], MapStrStr), + Parse => (smallvec![Str, Str], MapStrStr), + RegexParse => (smallvec![Str, Str], MapIntStr), Record => (smallvec![Str], MapStrStr), Message => (smallvec![Str], MapStrStr), DataUrl => (smallvec![Str], MapStrStr), @@ -797,6 +803,7 @@ impl Function { AppendIfMissing | PrependIfMissing | RemoveIfEnd | RemoveIfBegin => 2, Pairs => 3, LastPart => 2, + Parse | RegexParse => 2, Record | Message => 1, Quote | DoubleQuote => 1, VarDump => 1, @@ -923,6 +930,18 @@ impl Function { val: BaseTy::Int, }.abs()) } + RegexParse => { + Ok(Map { + key: BaseTy::Int, + val: BaseTy::Str, + }.abs()) + } + Parse => { + Ok(Map { + key: BaseTy::Str, + val: BaseTy::Str, + }.abs()) + } Shlex | Func | Tuple | ParseArray => { Ok(Map { key: BaseTy::Int, diff --git a/src/bytecode.rs b/src/bytecode.rs index 5f0133c..52c47c8 100644 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -312,6 +312,8 @@ pub(crate) enum Instr<'a> { Trim(Reg>, Reg>, Reg>), Escape(Reg>, Reg>, Reg>), Truncate(Reg>, Reg>, Reg, Reg>), + Parse(Reg>>, Reg>, Reg>), + RegexParse(Reg>>, Reg>, Reg>), Strtonum(Reg, Reg>), FormatBytes(Reg>, Reg), ToBytes(Reg, Reg>), @@ -999,6 +1001,16 @@ impl<'a> Instr<'a> { len.accum(&mut f); place_holder.accum(&mut f); } + Parse(dst, text, template ) => { + dst.accum(&mut f); + text.accum(&mut f); + template.accum(&mut f); + } + RegexParse(dst, text, template ) => { + dst.accum(&mut f); + text.accum(&mut f); + template.accum(&mut f); + } Strtonum(dst, text ) => { dst.accum(&mut f); text.accum(&mut f); diff --git a/src/codegen/intrinsics.rs b/src/codegen/intrinsics.rs index 404a755..caa1788 100644 --- a/src/codegen/intrinsics.rs +++ b/src/codegen/intrinsics.rs @@ -198,6 +198,8 @@ pub(crate) fn register_all(cg: &mut impl Backend) -> Result<()> { [ReadOnly] encrypt(str_ref_ty, str_ref_ty, str_ref_ty, str_ref_ty) -> str_ty; [ReadOnly] decrypt(str_ref_ty, str_ref_ty, str_ref_ty, str_ref_ty) -> str_ty; [ReadOnly] url(str_ref_ty) -> map_ty; + [ReadOnly] parse(str_ref_ty,str_ref_ty) -> map_ty; + [ReadOnly] rparse(str_ref_ty,str_ref_ty) -> map_ty; [ReadOnly] record(str_ref_ty) -> map_ty; [ReadOnly] message(str_ref_ty) -> map_ty; [ReadOnly] pairs(str_ref_ty, str_ref_ty, str_ref_ty) -> map_ty; @@ -1139,6 +1141,20 @@ pub(crate) unsafe extern "C" fn truncate(src: *mut U128, len: Int, place_holder: mem::transmute::(res) } +pub(crate) unsafe extern "C" fn parse(text: *mut U128, template: *mut U128) -> *mut c_void { + let text = &*(text as *mut Str); + let template = &*(template as *mut Str); + let res = string_util::parse(text.as_str(), template.as_str()); + mem::transmute::, *mut c_void>(res) +} + +pub(crate) unsafe extern "C" fn rparse(text: *mut U128, template: *mut U128) -> *mut c_void { + let text = &*(text as *mut Str); + let template = &*(template as *mut Str); + let res = string_util::rparse(text.as_str(), template.as_str()); + mem::transmute::, *mut c_void>(res) +} + pub(crate) unsafe extern "C" fn kv_get(namespace: *mut U128, key: *mut U128) -> U128 { let namespace = &*(namespace as *mut Str); let key = &*(key as *mut Str); diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 3acc06d..745cb1f 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1286,6 +1286,18 @@ pub(crate) trait CodeGenerator: Backend { let resv = self.call_intrinsic(intrinsic!(truncate), &mut [src, len, place_holder])?; self.bind_val(dst.reflect(),resv) } + Parse(dst,text, template) => { + let text = self.get_val(text.reflect())?; + let template = self.get_val(template.reflect())?; + let resv = self.call_intrinsic(intrinsic!(parse), &mut [text, template])?; + self.bind_val(dst.reflect(),resv) + } + RegexParse(dst,text, template) => { + let text = self.get_val(text.reflect())?; + let template = self.get_val(template.reflect())?; + let resv = self.call_intrinsic(intrinsic!(rparse), &mut [text, template])?; + self.bind_val(dst.reflect(),resv) + } KvGet(dst,namespace, key) => { let namespace = self.get_val(namespace.reflect())?; let key = self.get_val(key.reflect())?; diff --git a/src/compile.rs b/src/compile.rs index bb9e4d8..828409c 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -1890,6 +1890,24 @@ impl<'a, 'b> View<'a, 'b> { )) } } + Parse => { + if res_reg != UNUSED { + self.pushl(LL::Parse( + res_reg.into(), + conv_regs[0].into(), + conv_regs[1].into(), + )) + } + } + RegexParse => { + if res_reg != UNUSED { + self.pushl(LL::RegexParse( + res_reg.into(), + conv_regs[0].into(), + conv_regs[1].into(), + )) + } + } Strtonum => { if res_reg != UNUSED { self.pushl(LL::Strtonum( diff --git a/src/dataflow.rs b/src/dataflow.rs index a1d79c0..b56f177 100644 --- a/src/dataflow.rs +++ b/src/dataflow.rs @@ -361,6 +361,14 @@ pub(crate) mod boilerplate { f(dst.into(), Some(len.into())); f(dst.into(), Some(place_holder.into())); } + Parse(dst, text, template) => { + f(dst.into(), Some(text.into())); + f(dst.into(), Some(template.into())); + } + RegexParse(dst, text, template) => { + f(dst.into(), Some(text.into())); + f(dst.into(), Some(template.into())); + } Strtonum(dst, text) => { f(dst.into(), Some(text.into())); } diff --git a/src/display.rs b/src/display.rs index bc2077d..3a40ae4 100644 --- a/src/display.rs +++ b/src/display.rs @@ -181,6 +181,8 @@ impl Display for Function { Fend => write!(f, "fend"), Trim => write!(f, "trim"), Truncate => write!(f, "truncate"), + Parse => write!(f, "parse"), + RegexParse => write!(f, "rparse"), Strtonum => write!(f, "strtonum"), FormatBytes => write!(f, "format_bytes"), ToBytes => write!(f, "to_bytes"), diff --git a/src/interp.rs b/src/interp.rs index e95a898..14dd0c8 100644 --- a/src/interp.rs +++ b/src/interp.rs @@ -835,6 +835,20 @@ impl<'a, LR: LineReader> Interp<'a, LR> { let dst = *dst; *self.get_mut(dst) = res; } + Parse(dst, text, template) => { + let text = index(&self.strs, text); + let template = index(&self.strs, template); + let res = runtime::string_util::parse(text.as_str(), template.as_str()); + let dst = *dst; + *self.get_mut(dst) = res; + } + RegexParse(dst, text, template) => { + let text = index(&self.strs, text); + let template = index(&self.strs, template); + let res = runtime::string_util::rparse(text.as_str(), template.as_str()); + let dst = *dst; + *self.get_mut(dst) = res; + } Record(dst, src) => { let src = index(&self.strs, src); let res = runtime::string_util::record(src.as_str());