Fix circle (#1715)

* start of circle

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixews

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix all samples

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* docs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* bump version;

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
Jess Frazelle
2024-03-13 17:16:57 -07:00
committed by GitHub
parent d3d2612a3b
commit c571b15318
9 changed files with 1519 additions and 344 deletions

View File

@ -1,22 +1,43 @@
--- ---
title: "circle" title: "circle"
excerpt: "Sketch a circle on the given plane" excerpt: "Sketch a circle."
layout: manual layout: manual
--- ---
Sketch a circle on the given plane Sketch a circle.
```js ```js
circle(center: [number, number], radius: number, surface: SketchSurface, tag?: String) -> SketchGroup circle(center: [number], radius: number, tag?: String, sketch_surface_or_group: SketchSurfaceOrGroup) -> SketchGroup
```
### Examples
```js
const circles = startSketchOn('XY')
|> circle([5, 5], 1, %)
|> patternLinear2d({
axis: [1, 1],
repetitions: 12,
distance: 3
}, %)
const rectangle = startSketchOn('XY')
|> startProfileAt([0, 0], %)
|> line([0, 50], %)
|> line([50, 0], %)
|> line([0, -50], %)
|> close(%)
|> hole(circles, %)
``` ```
### Arguments ### Arguments
* `center`: `[number, number]` (REQUIRED) * `center`: `[number]` (REQUIRED)
* `radius`: `number` (REQUIRED) * `radius`: `number` (REQUIRED)
* `surface`: `SketchSurface` - A sketch group type. (REQUIRED) * `tag`: `String` (OPTIONAL)
* `sketch_surface_or_group`: `SketchSurfaceOrGroup` - A sketch surface or a sketch group. (REQUIRED)
```js ```js
{ {
// The id of the plane. // The id of the plane.
@ -75,9 +96,169 @@ circle(center: [number, number], radius: number, surface: SketchSurface, tag?: S
y: number, y: number,
z: number, z: number,
}, },
} |
{
// The plane id or face id of the sketch group.
entityId: uuid,
// The id of the sketch group.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
// The id of the plane.
id: uuid,
// Origin of the plane.
origin: {
x: number,
y: number,
z: number,
},
type: "plane",
// Type for a plane.
value: "XY" | "XZ" | "YZ" | "Custom",
// What should the planes X axis be?
xAxis: {
x: number,
y: number,
z: number,
},
// What should the planes Y axis be?
yAxis: {
x: number,
y: number,
z: number,
},
// The z-axis (normal).
zAxis: {
x: number,
y: number,
z: number,
},
} |
{
// The id of the face.
id: uuid,
// The original sketch group id of the object we are sketching on.
sketchGroupId: uuid,
type: "face",
// The tag of the face.
value: string,
// What should the faces X axis be?
xAxis: {
x: number,
y: number,
z: number,
},
// What should the faces Y axis be?
yAxis: {
x: number,
y: number,
z: number,
},
// The z-axis (normal).
zAxis: {
x: number,
y: number,
z: number,
},
},
// The position of the sketch group.
position: [number, number, number],
// The rotation of the sketch group base plane.
rotation: [number, number, number, number],
// The starting path.
start: {
// The from point.
from: [number, number],
// The name of the path.
name: string,
// The to point.
to: [number, number],
},
// The paths in the sketch group.
value: [{
// The from point.
from: [number, number],
// The name of the path.
name: string,
// The to point.
to: [number, number],
type: "ToPoint",
} |
{
// arc's direction
ccw: string,
// the arc's center
center: [number, number],
// The from point.
from: [number, number],
// The name of the path.
name: string,
// The to point.
to: [number, number],
type: "TangentialArcTo",
} |
{
// The from point.
from: [number, number],
// The name of the path.
name: string,
// The to point.
to: [number, number],
type: "TangentialArc",
} |
{
// The from point.
from: [number, number],
// The name of the path.
name: string,
// The to point.
to: [number, number],
type: "Horizontal",
// The x coordinate.
x: number,
} |
{
// The from point.
from: [number, number],
// The name of the path.
name: string,
// The to point.
to: [number, number],
type: "AngledLineTo",
// The x coordinate.
x: number,
// The y coordinate.
y: number,
} |
{
// The from point.
from: [number, number],
// The name of the path.
name: string,
// The to point.
to: [number, number],
type: "Base",
}],
// The x-axis of the sketch group base plane in the 3D space
xAxis: {
x: number,
y: number,
z: number,
},
// The y-axis of the sketch group base plane in the 3D space
yAxis: {
x: number,
y: number,
z: number,
},
// The z-axis of the sketch group base plane in the 3D space
zAxis: {
x: number,
y: number,
z: number,
},
} }
``` ```
* `tag`: `String` (OPTIONAL)
### Returns ### Returns

View File

@ -21,8 +21,8 @@ const square = startSketchOn('XY')
|> line([10, 0], %) |> line([10, 0], %)
|> line([0, -10], %) |> line([0, -10], %)
|> close(%) |> close(%)
|> hole(circle([2, 2], .5, startSketchOn('XY')), %) |> hole(circle([2, 2], .5, %), %)
|> hole(circle([2, 8], .5, startSketchOn('XY')), %) |> hole(circle([2, 8], .5, %), %)
|> extrude(2, %) |> extrude(2, %)
``` ```

File diff suppressed because it is too large Load Diff

View File

@ -1909,7 +1909,7 @@ dependencies = [
[[package]] [[package]]
name = "kcl-lib" name = "kcl-lib"
version = "0.1.45" version = "0.1.46"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"approx 0.5.1", "approx 0.5.1",

View File

@ -1,7 +1,7 @@
[package] [package]
name = "kcl-lib" name = "kcl-lib"
description = "KittyCAD Language implementation and tools" description = "KittyCAD Language implementation and tools"
version = "0.1.45" version = "0.1.46"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app" repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -49,6 +49,7 @@ lazy_static! {
Box::new(crate::std::segment::SegAng), Box::new(crate::std::segment::SegAng),
Box::new(crate::std::segment::AngleToMatchLengthX), Box::new(crate::std::segment::AngleToMatchLengthX),
Box::new(crate::std::segment::AngleToMatchLengthY), Box::new(crate::std::segment::AngleToMatchLengthY),
Box::new(crate::std::shapes::Circle),
Box::new(crate::std::sketch::LineTo), Box::new(crate::std::sketch::LineTo),
Box::new(crate::std::sketch::Line), Box::new(crate::std::sketch::Line),
Box::new(crate::std::sketch::XLineTo), Box::new(crate::std::sketch::XLineTo),
@ -130,7 +131,7 @@ impl StdLib {
.map(|internal_fn| (internal_fn.name(), internal_fn)) .map(|internal_fn| (internal_fn.name(), internal_fn))
.collect(); .collect();
let kcl_internal_fns: [Box<dyn KclStdLibFn>; 1] = [Box::<shapes::Circle>::default()]; let kcl_internal_fns: [Box<dyn KclStdLibFn>; 0] = [];
let kcl_fns = kcl_internal_fns let kcl_fns = kcl_internal_fns
.into_iter() .into_iter()
.map(|internal_fn| (internal_fn.name(), internal_fn)) .map(|internal_fn| (internal_fn.name(), internal_fn))
@ -265,6 +266,103 @@ impl Args {
Ok((numbers[0], numbers[1])) Ok((numbers[0], numbers[1]))
} }
fn get_circle_args(
&self,
) -> Result<([f64; 2], f64, crate::std::shapes::SketchSurfaceOrGroup, Option<String>), KclError> {
let first_value = self
.args
.first()
.ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!(
"Expected a [number, number] as the first argument, found `{:?}`",
self.args
),
source_ranges: vec![self.source_range],
})
})?
.get_json_value()?;
let center: [f64; 2] = if let serde_json::Value::Array(arr) = first_value {
if arr.len() != 2 {
return Err(KclError::Type(KclErrorDetails {
message: format!(
"Expected a [number, number] as the first argument, found `{:?}`",
self.args
),
source_ranges: vec![self.source_range],
}));
}
let x = parse_json_number_as_f64(&arr[0], self.source_range)?;
let y = parse_json_number_as_f64(&arr[1], self.source_range)?;
[x, y]
} else {
return Err(KclError::Type(KclErrorDetails {
message: format!(
"Expected a [number, number] as the first argument, found `{:?}`",
self.args
),
source_ranges: vec![self.source_range],
}));
};
let second_value = self
.args
.get(1)
.ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected a number as the second argument, found `{:?}`", self.args),
source_ranges: vec![self.source_range],
})
})?
.get_json_value()?;
let radius: f64 = serde_json::from_value(second_value).map_err(|e| {
KclError::Type(KclErrorDetails {
message: format!("Failed to deserialize number from JSON: {}", e),
source_ranges: vec![self.source_range],
})
})?;
let third_value = self.args.get(2).ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!(
"Expected a SketchGroup or SketchSurface as the third argument, found `{:?}`",
self.args
),
source_ranges: vec![self.source_range],
})
})?;
let sketch_group_or_surface = if let MemoryItem::SketchGroup(sg) = third_value {
crate::std::shapes::SketchSurfaceOrGroup::SketchGroup(sg.clone())
} else if let MemoryItem::Plane(sg) = third_value {
crate::std::shapes::SketchSurfaceOrGroup::SketchSurface(SketchSurface::Plane(sg.clone()))
} else if let MemoryItem::Face(sg) = third_value {
crate::std::shapes::SketchSurfaceOrGroup::SketchSurface(SketchSurface::Face(sg.clone()))
} else {
return Err(KclError::Type(KclErrorDetails {
message: format!(
"Expected a SketchGroup or SketchSurface as the third argument, found `{:?}`",
self.args
),
source_ranges: vec![self.source_range],
}));
};
if let Some(fourth_value) = self.args.get(3) {
let tag: String = serde_json::from_value(fourth_value.get_json_value()?).map_err(|e| {
KclError::Type(KclErrorDetails {
message: format!("Failed to deserialize String from JSON: {}", e),
source_ranges: vec![self.source_range],
})
})?;
Ok((center, radius, sketch_group_or_surface, Some(tag)))
} else {
Ok((center, radius, sketch_group_or_surface, None))
}
}
fn get_segment_name_sketch_group(&self) -> Result<(String, Box<SketchGroup>), KclError> { fn get_segment_name_sketch_group(&self) -> Result<(String, Box<SketchGroup>), KclError> {
// Iterate over our args, the first argument should be a UserVal with a string value. // Iterate over our args, the first argument should be a UserVal with a string value.
// The second argument should be a SketchGroup. // The second argument should be a SketchGroup.

View File

@ -1,155 +1,83 @@
//! Standard library shapes.
use anyhow::Result;
use derive_docs::stdlib;
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::kcl_stdlib::KclStdLibFn;
use crate::{ use crate::{
ast::types::{FunctionExpression, Program}, errors::KclError,
docs::StdLibFn, executor::MemoryItem,
std::{Args, SketchGroup, SketchSurface},
}; };
pub const CIRCLE_FN: &str = r#" /// A sketch surface or a sketch group.
(center, radius, surface, tag?) => { #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
const sg = startProfileAt([center[0] + radius, center[1]], surface) #[ts(export)]
|> arc({ #[serde(untagged)]
angle_end: 360, pub enum SketchSurfaceOrGroup {
angle_start: 0, SketchSurface(SketchSurface),
radius: radius, SketchGroup(Box<SketchGroup>),
tag: tag
}, %)
|> close(%)
return sg
}
"#;
#[derive(Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
pub struct Circle {
function: FunctionExpression,
program: Program,
} }
impl Default for Circle { /// Sketch a circle.
fn default() -> Self { pub async fn circle(args: Args) -> Result<MemoryItem, KclError> {
// TODO in https://github.com/KittyCAD/modeling-app/issues/1018 let (center, radius, sketch_surface_or_group, tag): ([f64; 2], f64, SketchSurfaceOrGroup, Option<String>) =
// Don't unwrap here, parse it at compile-time. args.get_circle_args()?;
let (src, function) = super::kcl_stdlib::extract_function(CIRCLE_FN).unwrap();
Self { let sketch_group = inner_circle(center, radius, tag, sketch_surface_or_group, args).await?;
function: *function, Ok(MemoryItem::SketchGroup(sketch_group))
program: src,
}
}
} }
impl std::fmt::Debug for Circle { /// Sketch a circle.
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { ///
"circle".fmt(f) /// ```no_run
} /// const circles = startSketchOn('XY')
} /// |> circle([5, 5], 1, %)
/// |> patternLinear2d({axis: [1,1], repetitions: 12, distance: 3}, %)
///
/// const rectangle = startSketchOn('XY')
/// |> startProfileAt([0, 0], %)
/// |> line([0, 50], %)
/// |> line([50, 0], %)
/// |> line([0, -50], %)
/// |> close(%)
/// |> hole(circles, %)
/// ```
#[stdlib {
name = "circle",
}]
async fn inner_circle(
center: [f64; 2],
radius: f64,
tag: Option<String>,
sketch_surface_or_group: SketchSurfaceOrGroup,
args: Args,
) -> Result<Box<SketchGroup>, KclError> {
let sketch_surface = match sketch_surface_or_group {
SketchSurfaceOrGroup::SketchSurface(surface) => surface,
SketchSurfaceOrGroup::SketchGroup(group) => group.on,
};
let mut sketch_group = crate::std::sketch::inner_start_profile_at(
crate::std::sketch::LineData::Point([center[0] + radius, center[1]]),
sketch_surface,
args.clone(),
)
.await?;
/// TODO: Parse the KCL in a macro and generate these // Call arc.
impl StdLibFn for Circle { sketch_group = crate::std::sketch::inner_arc(
fn name(&self) -> String { crate::std::sketch::ArcData::AnglesAndRadius {
"circle".to_owned() angle_start: 0.0,
} angle_end: 360.0,
radius,
tag,
},
sketch_group,
args.clone(),
)
.await?;
fn summary(&self) -> String { // Call close.
"Sketch a circle on the given plane".to_owned() crate::std::sketch::inner_close(sketch_group, None, args).await
}
fn description(&self) -> String {
String::new()
}
fn tags(&self) -> Vec<String> {
Vec::new()
}
fn args(&self) -> Vec<crate::docs::StdLibFnArg> {
let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = true;
let mut generator = schemars::gen::SchemaGenerator::new(settings);
let mut args = Vec::new();
for parameter in &self.function.params {
match parameter.identifier.name.as_str() {
"center" => {
args.push(crate::docs::StdLibFnArg {
name: parameter.identifier.name.to_owned(),
type_: "[number, number]".to_string(),
schema: <[f64; 2]>::json_schema(&mut generator),
required: true,
});
}
"radius" => {
args.push(crate::docs::StdLibFnArg {
name: parameter.identifier.name.to_owned(),
type_: "number".to_string(),
schema: <f64>::json_schema(&mut generator),
required: true,
});
}
"surface" => {
args.push(crate::docs::StdLibFnArg {
name: parameter.identifier.name.to_owned(),
type_: "SketchSurface".to_string(),
schema: <crate::executor::SketchSurface>::json_schema(&mut generator),
required: true,
});
}
"tag" => {
args.push(crate::docs::StdLibFnArg {
name: parameter.identifier.name.to_owned(),
type_: "String".to_string(),
schema: <String>::json_schema(&mut generator),
required: false,
});
}
_ => panic!("Unknown parameter: {:?}", parameter.identifier.name),
}
}
args
}
fn return_value(&self) -> Option<crate::docs::StdLibFnArg> {
let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = true;
let mut generator = schemars::gen::SchemaGenerator::new(settings);
Some(crate::docs::StdLibFnArg {
name: "SketchGroup".to_owned(),
type_: "SketchGroup".to_string(),
schema: <crate::executor::SketchGroup>::json_schema(&mut generator),
required: true,
})
}
fn unpublished(&self) -> bool {
false
}
fn deprecated(&self) -> bool {
false
}
fn examples(&self) -> Vec<String> {
vec![]
}
fn std_lib_fn(&self) -> crate::std::StdFn {
todo!()
}
fn clone_box(&self) -> Box<dyn StdLibFn> {
Box::new(self.to_owned())
}
}
impl KclStdLibFn for Circle {
fn function(&self) -> &FunctionExpression {
&self.function
}
fn program(&self) -> &Program {
&self.program
}
fn kcl_clone_box(&self) -> Box<dyn KclStdLibFn> {
Box::new(self.clone())
}
} }

View File

@ -1220,7 +1220,7 @@ pub async fn start_profile_at(args: Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "startProfileAt", name = "startProfileAt",
}] }]
async fn inner_start_profile_at( pub(crate) async fn inner_start_profile_at(
data: LineData, data: LineData,
sketch_surface: SketchSurface, sketch_surface: SketchSurface,
args: Args, args: Args,
@ -1306,7 +1306,7 @@ pub async fn close(args: Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "close", name = "close",
}] }]
async fn inner_close( pub(crate) async fn inner_close(
sketch_group: Box<SketchGroup>, sketch_group: Box<SketchGroup>,
tag: Option<String>, tag: Option<String>,
args: Args, args: Args,
@ -1402,7 +1402,11 @@ pub async fn arc(args: Args) -> Result<MemoryItem, KclError> {
#[stdlib { #[stdlib {
name = "arc", name = "arc",
}] }]
async fn inner_arc(data: ArcData, sketch_group: Box<SketchGroup>, args: Args) -> Result<Box<SketchGroup>, KclError> { pub(crate) async fn inner_arc(
data: ArcData,
sketch_group: Box<SketchGroup>,
args: Args,
) -> Result<Box<SketchGroup>, KclError> {
let from: Point2d = sketch_group.get_coords_from_paths()?; let from: Point2d = sketch_group.get_coords_from_paths()?;
let (center, angle_start, angle_end, radius, end) = match &data { let (center, angle_start, angle_end, radius, end) = match &data {
@ -1790,8 +1794,8 @@ pub async fn hole(args: Args) -> Result<MemoryItem, KclError> {
/// |> line([10, 0], %) /// |> line([10, 0], %)
/// |> line([0, -10], %) /// |> line([0, -10], %)
/// |> close(%) /// |> close(%)
/// |> hole(circle([2, 2], .5, startSketchOn('XY')), %) /// |> hole(circle([2, 2], .5, %), %)
/// |> hole(circle([2, 8], .5, startSketchOn('XY')), %) /// |> hole(circle([2, 8], .5, %), %)
/// |> extrude(2, %) /// |> extrude(2, %)
/// ``` /// ```
#[stdlib { #[stdlib {

View File

@ -731,8 +731,8 @@ async fn serial_test_holes() {
|> line([10, 0], %) |> line([10, 0], %)
|> line([0, -10], %) |> line([0, -10], %)
|> close(%) |> close(%)
|> hole(circle([2, 2], .5, startSketchOn('XY')), %) |> hole(circle([2, 2], .5, %), %)
|> hole(circle([2, 8], .5, startSketchOn('XY')), %) |> hole(circle([2, 8], .5, %), %)
|> extrude(2, %) |> extrude(2, %)
"#; "#;
@ -787,10 +787,10 @@ const holeRadius = 1
const holeIndex = 6 const holeIndex = 6
const part = roundedRectangle([0, 0], 20, 20, 4) const part = roundedRectangle([0, 0], 20, 20, 4)
|> hole(circle([-holeIndex, holeIndex], holeRadius, startSketchOn('XY')), %) |> hole(circle([-holeIndex, holeIndex], holeRadius, %), %)
|> hole(circle([holeIndex, holeIndex], holeRadius, startSketchOn('XY')), %) |> hole(circle([holeIndex, holeIndex], holeRadius, %), %)
|> hole(circle([-holeIndex, -holeIndex], holeRadius, startSketchOn('XY')), %) |> hole(circle([-holeIndex, -holeIndex], holeRadius, %), %)
|> hole(circle([holeIndex, -holeIndex], holeRadius, startSketchOn('XY')), %) |> hole(circle([holeIndex, -holeIndex], holeRadius, %), %)
|> extrude(2, %) |> extrude(2, %)
"#; "#;
@ -802,7 +802,7 @@ const part = roundedRectangle([0, 0], 20, 20, 4)
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn serial_test_top_level_expression() { async fn serial_test_top_level_expression() {
let code = r#"circle([0,0], 22, startSketchOn('XY')) |> extrude(14, %)"#; let code = r#"startSketchOn('XY') |> circle([0,0], 22, %) |> extrude(14, %)"#;
let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm)
.await .await
@ -1252,7 +1252,7 @@ async fn serial_test_stdlib_kcl_error_right_code_path() {
|> line([0, -10], %) |> line([0, -10], %)
|> close(%) |> close(%)
|> hole(circle([2, 2], .5), %) |> hole(circle([2, 2], .5), %)
|> hole(circle([2, 8], .5, startSketchOn('XY')), %) |> hole(circle([2, 8], .5, %), %)
|> extrude(2, %) |> extrude(2, %)
"#; "#;
@ -1260,7 +1260,7 @@ async fn serial_test_stdlib_kcl_error_right_code_path() {
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([157, 175])], message: "this function expected 3 arguments, got 2" }"# r#"type: KclErrorDetails { source_ranges: [SourceRange([157, 175])], message: "Expected a SketchGroup or SketchSurface as the third argument, found `[UserVal(UserVal { value: Array [Number(2), Number(2)], meta: [Metadata { source_range: SourceRange([164, 170]) }] }), UserVal(UserVal { value: Number(0.5), meta: [Metadata { source_range: SourceRange([172, 174]) }] })]`" }"#
); );
} }
@ -1367,6 +1367,6 @@ const part = rectShape([0, 0], 20, 20)
assert!(result.is_err()); assert!(result.is_err());
assert_eq!( assert_eq!(
result.err().unwrap().to_string(), result.err().unwrap().to_string(),
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([987, 1036])], message: "MemberExpression array is not an array: UserVal(UserVal { value: String(\"XY\"), meta: [Metadata { source_range: SourceRange([994, 998]) }] })" }"# r#"type: KclErrorDetails { source_ranges: [SourceRange([987, 1036])], message: "Expected a [number, number] as the first argument, found `[UserVal(UserVal { value: String(\"XY\"), meta: [Metadata { source_range: SourceRange([994, 998]) }] }), UserVal(UserVal { value: Array [Number(-6.0), Number(6)], meta: [Metadata { source_range: SourceRange([1000, 1023]) }] }), UserVal(UserVal { value: Number(1), meta: [Metadata { source_range: SourceRange([856, 857]) }] })]`" }"#
); );
} }