difftreelog
style fix clippy warnings
in: master
2 files changed
crates/jrsonnet-evaluator/src/evaluate/destructure.rsdiffbeforeafterboth1use jrsonnet_gcmodule::Trace;2use jrsonnet_interner::IStr;3use jrsonnet_parser::{BindSpec, Destruct, LocExpr, ParamsDesc};45use crate::{6 error::{ErrorKind::*, Result},7 evaluate, evaluate_method, evaluate_named,8 gc::GcHashMap,9 tb, throw,10 val::ThunkValue,11 Context, Pending, Thunk, Val,12};1314#[allow(clippy::too_many_lines)]15#[allow(unused_variables)]16pub fn destruct(17 d: &Destruct,18 parent: Thunk<Val>,19 fctx: Pending<Context>,20 new_bindings: &mut GcHashMap<IStr, Thunk<Val>>,21) -> Result<()> {22 match d {23 Destruct::Full(v) => {24 let old = new_bindings.insert(v.clone(), parent);25 if old.is_some() {26 throw!(DuplicateLocalVar(v.clone()))27 }28 }29 #[cfg(feature = "exp-destruct")]30 Destruct::Skip => {}31 #[cfg(feature = "exp-destruct")]32 Destruct::Array { start, rest, end } => {33 use jrsonnet_parser::DestructRest;3435 use crate::arr::ArrValue;3637 #[derive(Trace)]38 struct DataThunk {39 parent: Thunk<Val>,40 min_len: usize,41 has_rest: bool,42 }43 impl ThunkValue for DataThunk {44 type Output = ArrValue;4546 fn get(self: Box<Self>) -> Result<Self::Output> {47 let v = self.parent.evaluate()?;48 let Val::Arr(arr) = v else {49 throw!("expected array");50 };51 if !self.has_rest {52 if arr.len() != self.min_len {53 throw!("expected {} elements, got {}", self.min_len, arr.len())54 }55 } else if arr.len() < self.min_len {56 throw!(57 "expected at least {} elements, but array was only {}",58 self.min_len,59 arr.len()60 )61 }62 Ok(arr)63 }64 }6566 let full = Thunk::new(tb!(DataThunk {67 min_len: start.len() + end.len(),68 has_rest: rest.is_some(),69 parent,70 }));7172 {73 #[derive(Trace)]74 struct BaseThunk {75 full: Thunk<ArrValue>,76 index: usize,77 }78 impl ThunkValue for BaseThunk {79 type Output = Val;8081 fn get(self: Box<Self>) -> Result<Self::Output> {82 let full = self.full.evaluate()?;83 Ok(full.get(self.index)?.expect("length is checked"))84 }85 }86 for (i, d) in start.iter().enumerate() {87 destruct(88 d,89 Thunk::new(tb!(BaseThunk {90 full: full.clone(),91 index: i,92 })),93 fctx.clone(),94 new_bindings,95 )?;96 }97 }9899 match rest {100 Some(DestructRest::Keep(v)) => {101 #[derive(Trace)]102 struct RestThunk {103 full: Thunk<ArrValue>,104 start: usize,105 end: usize,106 }107 impl ThunkValue for RestThunk {108 type Output = Val;109110 fn get(self: Box<Self>) -> Result<Self::Output> {111 let full = self.full.evaluate()?;112 let to = full.len() - self.end;113 Ok(Val::Arr(114 full.slice(Some(self.start), Some(to), None)115 .expect("arguments checked"),116 ))117 }118 }119120 destruct(121 &Destruct::Full(v.clone()),122 Thunk::new(tb!(RestThunk {123 full: full.clone(),124 start: start.len(),125 end: end.len(),126 })),127 fctx.clone(),128 new_bindings,129 )?;130 }131 Some(DestructRest::Drop) => {}132 None => {}133 }134135 {136 #[derive(Trace)]137 struct EndThunk {138 full: Thunk<ArrValue>,139 index: usize,140 end: usize,141 }142 impl ThunkValue for EndThunk {143 type Output = Val;144145 fn get(self: Box<Self>) -> Result<Self::Output> {146 let full = self.full.evaluate()?;147 Ok(full148 .get(full.len() - self.end + self.index)?149 .expect("length is checked"))150 }151 }152 for (i, d) in end.iter().enumerate() {153 destruct(154 d,155 Thunk::new(tb!(EndThunk {156 full: full.clone(),157 index: i,158 end: end.len(),159 })),160 fctx.clone(),161 new_bindings,162 )?;163 }164 }165 }166 #[cfg(feature = "exp-destruct")]167 Destruct::Object { fields, rest } => {168 use crate::obj::ObjValue;169170 #[derive(Trace)]171 struct DataThunk {172 parent: Thunk<Val>,173 field_names: Vec<IStr>,174 has_rest: bool,175 }176 impl ThunkValue for DataThunk {177 type Output = ObjValue;178179 fn get(self: Box<Self>) -> Result<Self::Output> {180 let v = self.parent.evaluate()?;181 let Val::Obj(obj) = v else {182 throw!("expected object");183 };184 for field in &self.field_names {185 if !obj.has_field_ex(field.clone(), true) {186 throw!("missing field: {}", field);187 }188 }189 if !self.has_rest {190 let len = obj.len();191 if len != self.field_names.len() {192 throw!("too many fields, and rest not found");193 }194 }195 Ok(obj)196 }197 }198 let field_names: Vec<_> = fields199 .iter()200 .filter(|f| f.2.is_none())201 .map(|f| f.0.clone())202 .collect();203 let full = Thunk::new(tb!(DataThunk {204 parent,205 field_names: field_names.clone(),206 has_rest: rest.is_some()207 }));208209 for (field, d, default) in fields {210 #[derive(Trace)]211 struct FieldThunk {212 full: Thunk<ObjValue>,213 field: IStr,214 default: Option<(Pending<Context>, LocExpr)>,215 }216 impl ThunkValue for FieldThunk {217 type Output = Val;218219 fn get(self: Box<Self>) -> Result<Self::Output> {220 let full = self.full.evaluate()?;221 if let Some(field) = full.get(self.field)? {222 Ok(field)223 } else {224 let (fctx, expr) = self.default.as_ref().expect("shape is checked");225 Ok(evaluate(fctx.clone().unwrap(), &expr)?)226 }227 }228 }229 let value = Thunk::new(tb!(FieldThunk {230 full: full.clone(),231 field: field.clone(),232 default: default.clone().map(|e| (fctx.clone(), e)),233 }));234 if let Some(d) = d {235 destruct(d, value, fctx.clone(), new_bindings)?;236 } else {237 destruct(238 &Destruct::Full(field.clone()),239 value,240 fctx.clone(),241 new_bindings,242 )?;243 }244 }245 }246 }247 Ok(())248}249250pub fn evaluate_dest(251 d: &BindSpec,252 fctx: Pending<Context>,253 new_bindings: &mut GcHashMap<IStr, Thunk<Val>>,254) -> Result<()> {255 match d {256 BindSpec::Field { into, value } => {257 #[derive(Trace)]258 struct EvaluateThunkValue {259 name: Option<IStr>,260 fctx: Pending<Context>,261 expr: LocExpr,262 }263 impl ThunkValue for EvaluateThunkValue {264 type Output = Val;265 fn get(self: Box<Self>) -> Result<Self::Output> {266 self.name.map_or_else(267 || evaluate(self.fctx.unwrap(), &self.expr),268 |name| evaluate_named(self.fctx.unwrap(), &self.expr, name),269 )270 }271 }272 let data = Thunk::new(tb!(EvaluateThunkValue {273 name: into.name(),274 fctx: fctx.clone(),275 expr: value.clone(),276 }));277 destruct(into, data, fctx, new_bindings)?;278 }279 BindSpec::Function {280 name,281 params,282 value,283 } => {284 #[derive(Trace)]285 struct MethodThunk {286 fctx: Pending<Context>,287 name: IStr,288 params: ParamsDesc,289 value: LocExpr,290 }291 impl ThunkValue for MethodThunk {292 type Output = Val;293294 fn get(self: Box<Self>) -> Result<Self::Output> {295 Ok(evaluate_method(296 self.fctx.unwrap(),297 self.name,298 self.params,299 self.value,300 ))301 }302 }303304 let old = new_bindings.insert(305 name.clone(),306 Thunk::new(tb!(MethodThunk {307 fctx,308 name: name.clone(),309 params: params.clone(),310 value: value.clone()311 })),312 );313 if old.is_some() {314 throw!(DuplicateLocalVar(name.clone()))315 }316 }317 }318 Ok(())319}1use jrsonnet_gcmodule::Trace;2use jrsonnet_interner::IStr;3use jrsonnet_parser::{BindSpec, Destruct, LocExpr, ParamsDesc};45use crate::{6 error::{ErrorKind::*, Result},7 evaluate, evaluate_method, evaluate_named,8 gc::GcHashMap,9 tb, throw,10 val::ThunkValue,11 Context, Pending, Thunk, Val,12};1314#[allow(clippy::too_many_lines)]15#[allow(unused_variables)]16pub fn destruct(17 d: &Destruct,18 parent: Thunk<Val>,19 fctx: Pending<Context>,20 new_bindings: &mut GcHashMap<IStr, Thunk<Val>>,21) -> Result<()> {22 match d {23 Destruct::Full(v) => {24 let old = new_bindings.insert(v.clone(), parent);25 if old.is_some() {26 throw!(DuplicateLocalVar(v.clone()))27 }28 }29 #[cfg(feature = "exp-destruct")]30 Destruct::Skip => {}31 #[cfg(feature = "exp-destruct")]32 Destruct::Array { start, rest, end } => {33 use jrsonnet_parser::DestructRest;3435 use crate::arr::ArrValue;3637 #[derive(Trace)]38 struct DataThunk {39 parent: Thunk<Val>,40 min_len: usize,41 has_rest: bool,42 }43 impl ThunkValue for DataThunk {44 type Output = ArrValue;4546 fn get(self: Box<Self>) -> Result<Self::Output> {47 let v = self.parent.evaluate()?;48 let Val::Arr(arr) = v else {49 throw!("expected array");50 };51 if !self.has_rest {52 if arr.len() != self.min_len {53 throw!("expected {} elements, got {}", self.min_len, arr.len())54 }55 } else if arr.len() < self.min_len {56 throw!(57 "expected at least {} elements, but array was only {}",58 self.min_len,59 arr.len()60 )61 }62 Ok(arr)63 }64 }6566 let full = Thunk::new(tb!(DataThunk {67 min_len: start.len() + end.len(),68 has_rest: rest.is_some(),69 parent,70 }));7172 {73 #[derive(Trace)]74 struct BaseThunk {75 full: Thunk<ArrValue>,76 index: usize,77 }78 impl ThunkValue for BaseThunk {79 type Output = Val;8081 fn get(self: Box<Self>) -> Result<Self::Output> {82 let full = self.full.evaluate()?;83 Ok(full.get(self.index)?.expect("length is checked"))84 }85 }86 for (i, d) in start.iter().enumerate() {87 destruct(88 d,89 Thunk::new(tb!(BaseThunk {90 full: full.clone(),91 index: i,92 })),93 fctx.clone(),94 new_bindings,95 )?;96 }97 }9899 match rest {100 Some(DestructRest::Keep(v)) => {101 #[derive(Trace)]102 struct RestThunk {103 full: Thunk<ArrValue>,104 start: usize,105 end: usize,106 }107 impl ThunkValue for RestThunk {108 type Output = Val;109110 fn get(self: Box<Self>) -> Result<Self::Output> {111 let full = self.full.evaluate()?;112 let to = full.len() - self.end;113 Ok(Val::Arr(114 full.slice(Some(self.start), Some(to), None)115 .expect("arguments checked"),116 ))117 }118 }119120 destruct(121 &Destruct::Full(v.clone()),122 Thunk::new(tb!(RestThunk {123 full: full.clone(),124 start: start.len(),125 end: end.len(),126 })),127 fctx.clone(),128 new_bindings,129 )?;130 }131 Some(DestructRest::Drop) | None => {}132 }133134 {135 #[derive(Trace)]136 struct EndThunk {137 full: Thunk<ArrValue>,138 index: usize,139 end: usize,140 }141 impl ThunkValue for EndThunk {142 type Output = Val;143144 fn get(self: Box<Self>) -> Result<Self::Output> {145 let full = self.full.evaluate()?;146 Ok(full147 .get(full.len() - self.end + self.index)?148 .expect("length is checked"))149 }150 }151 for (i, d) in end.iter().enumerate() {152 destruct(153 d,154 Thunk::new(tb!(EndThunk {155 full: full.clone(),156 index: i,157 end: end.len(),158 })),159 fctx.clone(),160 new_bindings,161 )?;162 }163 }164 }165 #[cfg(feature = "exp-destruct")]166 Destruct::Object { fields, rest } => {167 use crate::obj::ObjValue;168169 #[derive(Trace)]170 struct DataThunk {171 parent: Thunk<Val>,172 field_names: Vec<IStr>,173 has_rest: bool,174 }175 impl ThunkValue for DataThunk {176 type Output = ObjValue;177178 fn get(self: Box<Self>) -> Result<Self::Output> {179 let v = self.parent.evaluate()?;180 let Val::Obj(obj) = v else {181 throw!("expected object");182 };183 for field in &self.field_names {184 if !obj.has_field_ex(field.clone(), true) {185 throw!("missing field: {}", field);186 }187 }188 if !self.has_rest {189 let len = obj.len();190 if len != self.field_names.len() {191 throw!("too many fields, and rest not found");192 }193 }194 Ok(obj)195 }196 }197 let field_names: Vec<_> = fields198 .iter()199 .filter(|f| f.2.is_none())200 .map(|f| f.0.clone())201 .collect();202 let full = Thunk::new(tb!(DataThunk {203 parent,204 field_names,205 has_rest: rest.is_some()206 }));207208 for (field, d, default) in fields {209 #[derive(Trace)]210 struct FieldThunk {211 full: Thunk<ObjValue>,212 field: IStr,213 default: Option<(Pending<Context>, LocExpr)>,214 }215 impl ThunkValue for FieldThunk {216 type Output = Val;217218 fn get(self: Box<Self>) -> Result<Self::Output> {219 let full = self.full.evaluate()?;220 if let Some(field) = full.get(self.field)? {221 Ok(field)222 } else {223 let (fctx, expr) = self.default.as_ref().expect("shape is checked");224 Ok(evaluate(fctx.clone().unwrap(), expr)?)225 }226 }227 }228 let value = Thunk::new(tb!(FieldThunk {229 full: full.clone(),230 field: field.clone(),231 default: default.clone().map(|e| (fctx.clone(), e)),232 }));233 if let Some(d) = d {234 destruct(d, value, fctx.clone(), new_bindings)?;235 } else {236 destruct(237 &Destruct::Full(field.clone()),238 value,239 fctx.clone(),240 new_bindings,241 )?;242 }243 }244 }245 }246 Ok(())247}248249pub fn evaluate_dest(250 d: &BindSpec,251 fctx: Pending<Context>,252 new_bindings: &mut GcHashMap<IStr, Thunk<Val>>,253) -> Result<()> {254 match d {255 BindSpec::Field { into, value } => {256 #[derive(Trace)]257 struct EvaluateThunkValue {258 name: Option<IStr>,259 fctx: Pending<Context>,260 expr: LocExpr,261 }262 impl ThunkValue for EvaluateThunkValue {263 type Output = Val;264 fn get(self: Box<Self>) -> Result<Self::Output> {265 self.name.map_or_else(266 || evaluate(self.fctx.unwrap(), &self.expr),267 |name| evaluate_named(self.fctx.unwrap(), &self.expr, name),268 )269 }270 }271 let data = Thunk::new(tb!(EvaluateThunkValue {272 name: into.name(),273 fctx: fctx.clone(),274 expr: value.clone(),275 }));276 destruct(into, data, fctx, new_bindings)?;277 }278 BindSpec::Function {279 name,280 params,281 value,282 } => {283 #[derive(Trace)]284 struct MethodThunk {285 fctx: Pending<Context>,286 name: IStr,287 params: ParamsDesc,288 value: LocExpr,289 }290 impl ThunkValue for MethodThunk {291 type Output = Val;292293 fn get(self: Box<Self>) -> Result<Self::Output> {294 Ok(evaluate_method(295 self.fctx.unwrap(),296 self.name,297 self.params,298 self.value,299 ))300 }301 }302303 let old = new_bindings.insert(304 name.clone(),305 Thunk::new(tb!(MethodThunk {306 fctx,307 name: name.clone(),308 params: params.clone(),309 value: value.clone()310 })),311 );312 if old.is_some() {313 throw!(DuplicateLocalVar(name.clone()))314 }315 }316 }317 Ok(())318}crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/lib.rs
+++ b/crates/jrsonnet-evaluator/src/lib.rs
@@ -44,6 +44,8 @@
extern crate self as jrsonnet_evaluator;
mod arr;
+#[cfg(feature = "async-import")]
+pub mod async_import;
mod ctx;
mod dynamic;
pub mod error;
@@ -188,6 +190,18 @@
evaluating: false,
}
}
+ pub(crate) fn get_string(&mut self) -> Option<IStr> {
+ if self.string.is_none() {
+ self.string = Some(
+ self.bytes
+ .as_ref()
+ .expect("either string or bytes should be set")
+ .clone()
+ .cast_str()?,
+ );
+ }
+ Some(self.string.clone().expect("just set"))
+ }
}
#[derive(Default, Trace)]
@@ -223,20 +237,9 @@
.1
}
};
- if let Some(str) = &file.string {
- return Ok(str.clone());
- }
- if file.string.is_none() {
- file.string = Some(
- file.bytes
- .as_ref()
- .expect("either string or bytes should be set")
- .clone()
- .cast_str()
- .ok_or_else(|| ImportBadFileUtf8(path.clone()))?,
- );
- }
- Ok(file.string.as_ref().expect("just set").clone())
+ Ok(file
+ .get_string()
+ .ok_or_else(|| ImportBadFileUtf8(path.clone()))?)
}
/// Should only be called with path retrieved from [`resolve_path`], may panic otherwise
pub fn import_resolved_bin(&self, path: SourcePath) -> Result<IBytes> {
@@ -288,23 +291,14 @@
if let Some(val) = &file.evaluated {
return Ok(val.clone());
}
- if file.string.is_none() {
- file.string = Some(
- std::str::from_utf8(
- file.bytes
- .as_ref()
- .expect("either string or bytes should be set"),
- )
- .map_err(|_| ImportBadFileUtf8(path.clone()))?
- .into(),
- );
- }
- let code = file.string.as_ref().expect("just set");
+ let code = file
+ .get_string()
+ .ok_or_else(|| ImportBadFileUtf8(path.clone()))?;
let file_name = Source::new(path.clone(), code.clone());
if file.parsed.is_none() {
file.parsed = Some(
jrsonnet_parser::parse(
- code,
+ &code,
&ParserSettings {
source: file_name.clone(),
},