git.delta.rocks / jrsonnet / refs/heads / master

difftreelog

source

crates/jrsonnet-evaluator/src/obj/static_shape.rs4.2 KiBsourcehistory
1use std::{fmt, ops::ControlFlow, rc::Rc};23use jrsonnet_gcmodule::{Acyclic, Trace, TraceBox};4use jrsonnet_interner::IStr;5use jrsonnet_ir::Span;67use super::{8	CcObjectAssertion, EnumFields, EnumFieldsHandler, FieldVisibility, GetFor,9	HasFieldIncludeHidden, ObjFieldFlags, ObjectCore, SupThis, Visibility,10	ordering::{FieldIndex, SuperDepth},11};12use crate::{MaybeUnbound, Result};1314#[derive(Acyclic, Debug)]15pub struct ShapeField {16	pub name: IStr,17	pub flags: ObjFieldFlags,18	pub location: Option<Span>,19	pub index: FieldIndex,20}2122#[derive(Acyclic, Debug)]23pub struct ObjShape {24	fields: Vec<ShapeField>,25}2627impl ObjShape {28	#[must_use]29	pub fn new(fields: Vec<ShapeField>) -> Self {30		Self { fields }31	}3233	#[inline]34	pub fn fields(&self) -> &[ShapeField] {35		&self.fields36	}3738	#[inline]39	#[must_use]40	pub fn len(&self) -> usize {41		self.fields.len()42	}4344	#[inline]45	#[must_use]46	pub fn is_empty(&self) -> bool {47		self.fields.is_empty()48	}4950	#[inline]51	pub fn find_index(&self, name: &IStr) -> Option<usize> {52		self.fields.iter().position(|f| &f.name == name)53	}54}5556#[derive(Trace)]57pub struct StaticShapeOopObject {58	shape: Rc<ObjShape>,59	bindings: TraceBox<[MaybeUnbound]>,60	assertion: Option<CcObjectAssertion>,61}6263impl fmt::Debug for StaticShapeOopObject {64	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {65		f.debug_struct("StaticShapeOopObject")66			.field("shape", &self.shape)67			.field("has_assertion", &self.assertion.is_some())68			.finish_non_exhaustive()69	}70}7172impl StaticShapeOopObject {73	pub fn new(74		shape: Rc<ObjShape>,75		bindings: Vec<MaybeUnbound>,76		assertion: Option<CcObjectAssertion>,77	) -> Self {78		debug_assert_eq!(79			shape.fields.len(),80			bindings.len(),81			"shape arity must match bindings"82		);83		Self {84			shape,85			bindings: TraceBox(bindings.into_boxed_slice()),86			assertion,87		}88	}8990	#[inline]91	#[must_use]92	pub const fn shape(&self) -> &Rc<ObjShape> {93		&self.shape94	}95}9697impl ObjectCore for StaticShapeOopObject {98	fn enum_fields_core(99		&self,100		super_depth: &mut SuperDepth,101		handler: &mut EnumFieldsHandler<'_>,102	) -> bool {103		for field in &self.shape.fields {104			if matches!(105				handler(106					*super_depth,107					field.index,108					field.name.clone(),109					EnumFields::Normal(field.flags.visibility()),110				),111				ControlFlow::Break(())112			) {113				return false;114			}115		}116		true117	}118119	fn has_field_include_hidden_core(&self, name: IStr) -> HasFieldIncludeHidden {120		if self.shape.find_index(&name).is_some() {121			HasFieldIncludeHidden::Exists122		} else {123			HasFieldIncludeHidden::NotFound124		}125	}126127	fn get_for_core(&self, key: IStr, sup_this: SupThis, omit_only: bool) -> Result<GetFor> {128		if omit_only {129			return Ok(GetFor::NotFound);130		}131		let Some(i) = self.shape.find_index(&key) else {132			return Ok(GetFor::NotFound);133		};134		let field = &self.shape.fields[i];135		let v = self.bindings[i].evaluate(sup_this)?;136		Ok(if field.flags.add() {137			GetFor::SuperPlus(v)138		} else {139			GetFor::Final(v)140		})141	}142143	fn field_visibility_core(&self, field: IStr) -> FieldVisibility {144		self.shape145			.find_index(&field)146			.map_or(FieldVisibility::NotFound, |i| {147				FieldVisibility::Found(self.shape.fields[i].flags.visibility())148			})149	}150151	fn run_assertions_core(&self, sup_this: SupThis) -> Result<()> {152		if let Some(assertion) = &self.assertion {153			assertion.0.run(sup_this)?;154		}155		Ok(())156	}157158	fn has_assertion(&self) -> bool {159		self.assertion.is_some()160	}161}162163pub struct ObjShapeBuilder {164	fields: Vec<ShapeField>,165	next_index: FieldIndex,166}167168impl ObjShapeBuilder {169	#[must_use]170	pub fn new() -> Self {171		Self {172			fields: Vec::new(),173			next_index: FieldIndex::default(),174		}175	}176177	#[must_use]178	pub fn with_capacity(cap: usize) -> Self {179		Self {180			fields: Vec::with_capacity(cap),181			next_index: FieldIndex::default(),182		}183	}184185	pub fn field(186		&mut self,187		name: impl Into<IStr>,188		visibility: Visibility,189		add: bool,190		location: Option<Span>,191	) -> &mut Self {192		let index = self.next_index;193		self.next_index = self.next_index.next();194		self.fields.push(ShapeField {195			name: name.into(),196			flags: ObjFieldFlags::new(add, visibility),197			location,198			index,199		});200		self201	}202203	#[must_use]204	pub fn build(self) -> ObjShape {205		ObjShape::new(self.fields)206	}207}208209impl Default for ObjShapeBuilder {210	fn default() -> Self {211		Self::new()212	}213}