Merge branch 'main' into paultag/import

This commit is contained in:
Paul Tagliamonte
2025-03-28 14:40:34 -04:00
1429 changed files with 428359 additions and 793058 deletions

View File

@ -23,7 +23,9 @@ use crate::{
const TYPES_DIR: &str = "../../docs/kcl/types";
const LANG_TOPICS: [&str; 5] = ["Types", "Modules", "Settings", "Known Issues", "Constants"];
// These types are declared in std.
const DECLARED_TYPES: [&str; 7] = ["number", "string", "tag", "bool", "Sketch", "Solid", "Plane"];
const DECLARED_TYPES: [&str; 11] = [
"number", "string", "tag", "bool", "Sketch", "Solid", "Plane", "Helix", "Face", "Point2d", "Point3d",
];
fn init_handlebars() -> Result<handlebars::Handlebars<'static>> {
let mut hbs = handlebars::Handlebars::new();
@ -457,6 +459,7 @@ fn generate_type_from_kcl(ty: &TyData, file_name: String, example_name: String)
let data = json!({
"name": ty.qual_name(),
"definition": ty.alias.as_ref().map(|t| format!("type {} = {t}", ty.name)),
"summary": ty.summary,
"description": ty.description,
"deprecated": ty.properties.deprecated,
@ -464,6 +467,10 @@ fn generate_type_from_kcl(ty: &TyData, file_name: String, example_name: String)
});
let output = hbs.render("kclType", &data)?;
let output = cleanup_type_links(
&output,
ty.referenced_types.iter().filter(|t| !DECLARED_TYPES.contains(&&***t)),
);
expectorate::assert_contents(format!("../../docs/kcl/{}.md", file_name), &output);
Ok(())
@ -511,6 +518,13 @@ fn generate_function_from_kcl(function: &FnData, file_name: String) -> Result<()
});
let output = hbs.render("function", &data)?;
let output = cleanup_type_links(
&output,
function
.referenced_types
.iter()
.filter(|t| !DECLARED_TYPES.contains(&&***t)),
);
expectorate::assert_contents(format!("../../docs/kcl/{}.md", file_name), &output);
Ok(())
@ -674,6 +688,12 @@ fn cleanup_type_links<'a>(output: &str, types: impl Iterator<Item = &'a String>)
}
}
// TODO handle union types generically rather than special casing them.
cleaned_output = cleaned_output.replace(
"`Sketch | Plane | Face`",
"[`Sketch`](/docs/kcl/types/Sketch) `|` [`Plane`](/docs/kcl/types/Face) `|` [`Plane`](/docs/kcl/types/Face)",
);
cleanup_static_links(&cleaned_output)
}

View File

@ -1,5 +1,6 @@
use std::str::FromStr;
use std::{collections::HashSet, str::FromStr};
use regex::Regex;
use tower_lsp::lsp_types::{
CompletionItem, CompletionItemKind, CompletionItemLabelDetails, Documentation, InsertTextFormat, MarkupContent,
MarkupKind, ParameterInformation, ParameterLabel, SignatureHelp, SignatureInformation,
@ -8,7 +9,7 @@ use tower_lsp::lsp_types::{
use crate::{
execution::annotations,
parsing::{
ast::types::{Annotation, Node, NonCodeNode, NonCodeValue, VariableKind},
ast::types::{Annotation, Node, PrimitiveType, Type, VariableKind},
token::NumericSuffix,
},
ModuleId,
@ -36,7 +37,7 @@ impl CollectionVisitor {
.unwrap();
self.id += 1;
for (i, n) in parsed.body.iter().enumerate() {
for n in &parsed.body {
match n {
crate::parsing::ast::types::BodyItem::ImportStatement(import) if !import.visibility.is_default() => {
// Only supports glob imports for now.
@ -58,17 +59,15 @@ impl CollectionVisitor {
format!("std::{}::", self.name)
};
let mut dd = match var.kind {
// TODO metadata for args
VariableKind::Fn => DocData::Fn(FnData::from_ast(var, qual_name)),
VariableKind::Const => DocData::Const(ConstData::from_ast(var, qual_name)),
};
// FIXME this association of metadata with items is pretty flaky.
if i == 0 {
dd.with_meta(&parsed.non_code_meta.start_nodes, &var.outer_attrs);
} else if let Some(meta) = parsed.non_code_meta.non_code_nodes.get(&(i - 1)) {
dd.with_meta(meta, &var.outer_attrs);
dd.with_meta(&var.outer_attrs);
for a in &var.outer_attrs {
dd.with_comments(&a.pre_comments);
}
dd.with_comments(n.get_comments());
self.result.push(dd);
}
@ -80,12 +79,11 @@ impl CollectionVisitor {
};
let mut dd = DocData::Ty(TyData::from_ast(ty, qual_name));
// FIXME this association of metadata with items is pretty flaky.
if i == 0 {
dd.with_meta(&parsed.non_code_meta.start_nodes, &ty.outer_attrs);
} else if let Some(meta) = parsed.non_code_meta.non_code_nodes.get(&(i - 1)) {
dd.with_meta(meta, &ty.outer_attrs);
dd.with_meta(&ty.outer_attrs);
for a in &ty.outer_attrs {
dd.with_comments(&a.pre_comments);
}
dd.with_comments(n.get_comments());
self.result.push(dd);
}
@ -172,11 +170,19 @@ impl DocData {
}
}
fn with_meta(&mut self, meta: &[Node<NonCodeNode>], attrs: &[Node<Annotation>]) {
fn with_meta(&mut self, attrs: &[Node<Annotation>]) {
match self {
DocData::Fn(f) => f.with_meta(meta, attrs),
DocData::Const(c) => c.with_meta(meta, attrs),
DocData::Ty(t) => t.with_meta(meta, attrs),
DocData::Fn(f) => f.with_meta(attrs),
DocData::Const(c) => c.with_meta(attrs),
DocData::Ty(t) => t.with_meta(attrs),
}
}
fn with_comments(&mut self, comments: &[String]) {
match self {
DocData::Fn(f) => f.with_comments(comments),
DocData::Const(c) => c.with_comments(comments),
DocData::Ty(t) => t.with_comments(comments),
}
}
@ -276,7 +282,7 @@ impl ConstData {
documentation: self.short_docs().map(|s| {
Documentation::MarkupContent(MarkupContent {
kind: MarkupKind::Markdown,
value: s,
value: remove_md_links(&s),
})
}),
deprecated: Some(self.properties.deprecated),
@ -315,6 +321,8 @@ pub struct FnData {
/// Code examples.
/// These are tested and we know they compile and execute.
pub examples: Vec<(String, ExampleProperties)>,
#[allow(dead_code)]
pub referenced_types: Vec<String>,
}
impl FnData {
@ -325,11 +333,22 @@ impl FnData {
};
let name = var.declaration.id.name.clone();
qual_name.push_str(&name);
let mut referenced_types = HashSet::new();
if let Some(t) = &expr.return_type {
collect_type_names(&mut referenced_types, t);
}
for p in &expr.params {
if let Some(t) = &p.type_ {
collect_type_names(&mut referenced_types, t);
}
}
FnData {
name,
qual_name,
args: expr.params.iter().map(ArgData::from_ast).collect(),
return_type: expr.return_type.as_ref().map(|t| t.recast(&Default::default(), 0)),
return_type: expr.return_type.as_ref().map(|t| t.to_string()),
properties: Properties {
exported: !var.visibility.is_default(),
deprecated: false,
@ -339,6 +358,7 @@ impl FnData {
summary: None,
description: None,
examples: Vec::new(),
referenced_types: referenced_types.into_iter().collect(),
}
}
@ -387,7 +407,7 @@ impl FnData {
documentation: self.short_docs().map(|s| {
Documentation::MarkupContent(MarkupContent {
kind: MarkupKind::Markdown,
value: s,
value: remove_md_links(&s),
})
}),
deprecated: Some(self.properties.deprecated),
@ -407,7 +427,7 @@ impl FnData {
}
#[allow(clippy::literal_string_with_formatting_args)]
fn to_autocomplete_snippet(&self) -> String {
pub(super) fn to_autocomplete_snippet(&self) -> String {
if self.name == "loft" {
return "loft([${0:sketch000}, ${1:sketch001}])${}".to_owned();
} else if self.name == "hole" {
@ -473,12 +493,12 @@ pub struct ArgData {
/// If the argument is required.
pub kind: ArgKind,
/// Additional information that could be used instead of the type's description.
/// This is helpful if the type is really basic, like "u32" -- that won't tell the user much about
/// This is helpful if the type is really basic, like "number" -- that won't tell the user much about
/// how this argument is meant to be used.
pub docs: Option<String>,
}
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ArgKind {
Special,
// Parameter is whether the arg is optional.
@ -488,38 +508,47 @@ pub enum ArgKind {
impl ArgData {
fn from_ast(arg: &crate::parsing::ast::types::Parameter) -> Self {
ArgData {
let mut result = ArgData {
name: arg.identifier.name.clone(),
ty: arg.type_.as_ref().map(|t| t.recast(&Default::default(), 0)),
// Doc comments are not yet supported on parameters.
ty: arg.type_.as_ref().map(|t| t.to_string()),
docs: None,
kind: if arg.labeled {
ArgKind::Labelled(arg.optional())
} else {
ArgKind::Special
},
}
}
};
fn _with_meta(&mut self, _meta: &[Node<NonCodeNode>]) {
// TODO use comments for docs (we can't currently get the comments for an argument)
result.with_comments(&arg.identifier.pre_comments);
result
}
pub fn get_autocomplete_snippet(&self, index: usize) -> Option<(usize, String)> {
match &self.ty {
Some(s)
if [
"Sketch",
"SketchSet",
"Solid",
"SolidSet",
"SketchSurface",
"SketchOrSurface",
]
.contains(&&**s) =>
{
Some((index, format!("${{{}:{}}}", index, "%")))
let label = if self.kind == ArgKind::Special {
String::new()
} else {
format!("{} = ", self.name)
};
match self.ty.as_deref() {
Some(s) if ["Sketch", "Solid", "Plane | Face", "Sketch | Plane | Face"].contains(&s) => {
Some((index, format!("{label}${{{}:{}}}", index, "%")))
}
Some("number") if self.kind.required() => Some((index, format!(r#"{label}${{{}:3.14}}"#, index))),
Some("Point2d") if self.kind.required() => Some((
index + 1,
format!(r#"{label}[${{{}:3.14}}, ${{{}:3.14}}]"#, index, index + 1),
)),
Some("Point3d") if self.kind.required() => Some((
index + 2,
format!(
r#"{label}[${{{}:3.14}}, ${{{}:3.14}}, ${{{}:3.14}}]"#,
index,
index + 1,
index + 2
),
)),
Some("string") if self.kind.required() => Some((index, format!(r#"{label}${{{}:"string"}}"#, index))),
Some("bool") if self.kind.required() => Some((index, format!(r#"{label}${{{}:false}}"#, index))),
_ => None,
}
}
@ -554,6 +583,7 @@ pub struct TyData {
/// The fully qualified name.
pub qual_name: String,
pub properties: Properties,
pub alias: Option<String>,
/// The summary of the function.
pub summary: Option<String>,
@ -562,12 +592,19 @@ pub struct TyData {
/// Code examples.
/// These are tested and we know they compile and execute.
pub examples: Vec<(String, ExampleProperties)>,
#[allow(dead_code)]
pub referenced_types: Vec<String>,
}
impl TyData {
fn from_ast(ty: &crate::parsing::ast::types::TypeDeclaration, mut qual_name: String) -> Self {
let name = ty.name.name.clone();
qual_name.push_str(&name);
let mut referenced_types = HashSet::new();
if let Some(t) = &ty.alias {
collect_type_names(&mut referenced_types, t);
}
TyData {
name,
qual_name,
@ -577,9 +614,11 @@ impl TyData {
doc_hidden: false,
impl_kind: annotations::Impl::Kcl,
},
alias: ty.alias.as_ref().map(|t| t.to_string()),
summary: None,
description: None,
examples: Vec::new(),
referenced_types: referenced_types.into_iter().collect(),
}
}
@ -603,13 +642,16 @@ impl TyData {
fn to_completion_item(&self) -> CompletionItem {
CompletionItem {
label: self.name.clone(),
label_details: None,
label_details: self.alias.as_ref().map(|t| CompletionItemLabelDetails {
detail: Some(format!("type {} = {t}", self.name)),
description: None,
}),
kind: Some(CompletionItemKind::FUNCTION),
detail: Some(self.qual_name().to_owned()),
documentation: self.short_docs().map(|s| {
Documentation::MarkupContent(MarkupContent {
kind: MarkupKind::Markdown,
value: s,
value: remove_md_links(&s),
})
}),
deprecated: Some(self.properties.deprecated),
@ -629,6 +671,11 @@ impl TyData {
}
}
fn remove_md_links(s: &str) -> String {
let re = Regex::new(r"\[([^\]]*)\]\([^\)]*\)").unwrap();
re.replace_all(s, "$1").to_string()
}
trait ApplyMeta {
fn apply_docs(
&mut self,
@ -640,55 +687,20 @@ trait ApplyMeta {
fn doc_hidden(&mut self, doc_hidden: bool);
fn impl_kind(&mut self, impl_kind: annotations::Impl);
fn with_meta(&mut self, meta: &[Node<NonCodeNode>], attrs: &[Node<Annotation>]) {
for attr in attrs {
if let Annotation {
name: None,
properties: Some(props),
..
} = &attr.inner
{
for p in props {
match &*p.key.name {
annotations::IMPL => {
if let Some(s) = p.value.ident_name() {
self.impl_kind(annotations::Impl::from_str(s).unwrap());
}
}
"deprecated" => {
if let Some(b) = p.value.literal_bool() {
self.deprecated(b);
}
}
"doc_hidden" => {
if let Some(b) = p.value.literal_bool() {
self.doc_hidden(b);
}
}
_ => {}
}
}
}
}
let mut comments = Vec::new();
for m in meta {
match &m.value {
NonCodeValue::BlockComment { value, .. } | NonCodeValue::NewLineBlockComment { value, .. } => {
comments.push(value)
}
_ => {}
}
fn with_comments(&mut self, comments: &[String]) {
if comments.iter().all(|s| s.is_empty()) {
return;
}
let mut summary = None;
let mut description = None;
let mut example: Option<(String, ExampleProperties)> = None;
let mut examples = Vec::new();
for l in comments.into_iter().filter(|l| l.starts_with('/')).map(|l| {
if let Some(ll) = l.strip_prefix("/ ") {
for l in comments.iter().filter(|l| l.starts_with("///")).map(|l| {
if let Some(ll) = l.strip_prefix("/// ") {
ll
} else {
&l[1..]
&l[3..]
}
}) {
if description.is_none() && summary.is_none() {
@ -763,6 +775,38 @@ trait ApplyMeta {
examples,
);
}
fn with_meta(&mut self, attrs: &[Node<Annotation>]) {
for attr in attrs {
if let Annotation {
name: None,
properties: Some(props),
..
} = &attr.inner
{
for p in props {
match &*p.key.name {
annotations::IMPL => {
if let Some(s) = p.value.ident_name() {
self.impl_kind(annotations::Impl::from_str(s).unwrap());
}
}
"deprecated" => {
if let Some(b) = p.value.literal_bool() {
self.deprecated(b);
}
}
"doc_hidden" => {
if let Some(b) = p.value.literal_bool() {
self.doc_hidden(b);
}
}
_ => {}
}
}
}
}
}
}
impl ApplyMeta for ConstData {
@ -838,6 +882,66 @@ impl ApplyMeta for TyData {
}
}
impl ApplyMeta for ArgData {
fn apply_docs(
&mut self,
summary: Option<String>,
description: Option<String>,
_examples: Vec<(String, ExampleProperties)>,
) {
let Some(mut docs) = summary else {
return;
};
if let Some(desc) = description {
docs.push_str("\n\n");
docs.push_str(&desc);
}
self.docs = Some(docs);
}
fn deprecated(&mut self, _deprecated: bool) {
unreachable!();
}
fn doc_hidden(&mut self, _doc_hidden: bool) {
unreachable!();
}
fn impl_kind(&mut self, _impl_kind: annotations::Impl) {
unreachable!();
}
}
fn collect_type_names(acc: &mut HashSet<String>, ty: &Type) {
match ty {
Type::Primitive(primitive_type) => {
acc.insert(collect_type_names_from_primitive(primitive_type));
}
Type::Array { ty, .. } => {
acc.insert(collect_type_names_from_primitive(ty));
}
Type::Union { tys } => tys.iter().for_each(|t| {
acc.insert(collect_type_names_from_primitive(t));
}),
Type::Object { properties } => properties.iter().for_each(|p| {
if let Some(t) = &p.type_ {
collect_type_names(acc, t)
}
}),
}
}
fn collect_type_names_from_primitive(ty: &PrimitiveType) -> String {
match ty {
PrimitiveType::String => "string".to_owned(),
PrimitiveType::Number(_) => "number".to_owned(),
PrimitiveType::Boolean => "bool".to_owned(),
PrimitiveType::Tag => "tag".to_owned(),
PrimitiveType::Named(id) => id.name.clone(),
}
}
#[cfg(test)]
mod test {
use super::*;
@ -860,6 +964,24 @@ mod test {
panic!("didn't find PI");
}
#[test]
fn test_remove_md_links() {
assert_eq!(
remove_md_links("sdf dsf sd fj sdk fasdfs. asad[sdfs] dfsdf(dsfs, dsf)"),
"sdf dsf sd fj sdk fasdfs. asad[sdfs] dfsdf(dsfs, dsf)".to_owned()
);
assert_eq!(remove_md_links("[]()"), "".to_owned());
assert_eq!(remove_md_links("[foo](bar)"), "foo".to_owned());
assert_eq!(
remove_md_links("asdasda dsa[foo](http://www.bar/baz/qux.md). asdasdasdas asdas"),
"asdasda dsafoo. asdasdasdas asdas".to_owned()
);
assert_eq!(
remove_md_links("a [foo](bar) b [2](bar) c [_](bar)"),
"a foo b 2 c _".to_owned()
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn test_examples() -> miette::Result<()> {
let std = walk_prelude();

View File

@ -18,7 +18,7 @@ use tower_lsp::lsp_types::{
};
use crate::{
execution::{kcl_value::NumericType, Sketch},
execution::{types::NumericType, Sketch},
std::Primitive,
};
@ -127,13 +127,14 @@ impl StdLibFnArg {
} else {
""
};
if self.type_ == "Sketch"
if (self.type_ == "Sketch"
|| self.type_ == "[Sketch]"
|| self.type_ == "Solid"
|| self.type_ == "[Solid]"
|| self.type_ == "SketchSurface"
|| self.type_ == "SketchOrSurface"
|| self.type_ == "SolidOrImportedGeometry"
|| self.type_ == "SolidOrSketchOrImportedGeometry")
&& (self.required || self.include_in_snippet)
{
return Ok(Some((index, format!("{label}${{{}:{}}}", index, "%"))));
} else if (self.type_ == "TagDeclarator" || self.type_ == "TagNode") && self.required {
@ -927,6 +928,7 @@ mod tests {
use pretty_assertions::assert_eq;
use super::StdLibFn;
use crate::docs::kcl_doc::{self, DocData};
#[test]
fn test_serialize_function() {
@ -1000,19 +1002,17 @@ mod tests {
fn get_autocomplete_snippet_revolve() {
let revolve_fn: Box<dyn StdLibFn> = Box::new(crate::std::revolve::Revolve);
let snippet = revolve_fn.to_autocomplete_snippet().unwrap();
assert_eq!(
snippet,
r#"revolve({
axis = ${0:"X"},
}, ${1:%})${}"#
);
assert_eq!(snippet, r#"revolve(${0:%}, axis = ${1:"X"})${}"#);
}
#[test]
#[allow(clippy::literal_string_with_formatting_args)]
fn get_autocomplete_snippet_circle() {
let circle_fn: Box<dyn StdLibFn> = Box::new(crate::std::shapes::Circle);
let snippet = circle_fn.to_autocomplete_snippet().unwrap();
let data = kcl_doc::walk_prelude();
let DocData::Fn(circle_fn) = data.into_iter().find(|d| d.name() == "circle").unwrap() else {
panic!();
};
let snippet = circle_fn.to_autocomplete_snippet();
assert_eq!(
snippet,
r#"circle(${0:%}, center = [${1:3.14}, ${2:3.14}], radius = ${3:3.14})${}"#
@ -1099,16 +1099,38 @@ mod tests {
#[test]
#[allow(clippy::literal_string_with_formatting_args)]
fn get_autocomplete_snippet_helix_revolutions() {
let helix_fn: Box<dyn StdLibFn> = Box::new(crate::std::helix::HelixRevolutions);
let snippet = helix_fn.to_autocomplete_snippet().unwrap();
fn get_autocomplete_snippet_union() {
let union_fn: Box<dyn StdLibFn> = Box::new(crate::std::csg::Union);
let snippet = union_fn.to_autocomplete_snippet().unwrap();
assert_eq!(snippet, r#"union(${0:%})${}"#);
}
#[test]
#[allow(clippy::literal_string_with_formatting_args)]
fn get_autocomplete_snippet_subtract() {
let subtract_fn: Box<dyn StdLibFn> = Box::new(crate::std::csg::Subtract);
let snippet = subtract_fn.to_autocomplete_snippet().unwrap();
assert_eq!(snippet, r#"subtract(${0:%}, tools = ${1:%})${}"#);
}
#[test]
#[allow(clippy::literal_string_with_formatting_args)]
fn get_autocomplete_snippet_intersect() {
let intersect_fn: Box<dyn StdLibFn> = Box::new(crate::std::csg::Intersect);
let snippet = intersect_fn.to_autocomplete_snippet().unwrap();
assert_eq!(snippet, r#"intersect(${0:%})${}"#);
}
#[test]
#[allow(clippy::literal_string_with_formatting_args)]
fn get_autocomplete_snippet_get_common_edge() {
let get_common_edge_fn: Box<dyn StdLibFn> = Box::new(crate::std::edge::GetCommonEdge);
let snippet = get_common_edge_fn.to_autocomplete_snippet().unwrap();
assert_eq!(
snippet,
r#"helixRevolutions({
revolutions = ${0:3.14},
angleStart = ${1:3.14},
ccw = ${2:false},
}, ${3:%})${}"#
r#"getCommonEdge(faces = [{
value = ${0:"string"},
}])${}"#
);
}

View File

@ -10,6 +10,12 @@ layout: manual
{{/if}}
{{{summary}}}
{{#if definition}}
```kcl
{{{definition}}}
```
{{/if}}
{{{description}}}

View File

@ -104,23 +104,29 @@ impl EngineConnection {
})?;
let value = crate::wasm::JsFuture::from(promise).await.map_err(|e| {
KclError::Engine(KclErrorDetails {
message: format!("Failed to wait for promise from engine: {:?}", e),
source_ranges: vec![source_range],
})
// Try to parse the error as an engine error.
let err_str = e.as_string().unwrap_or_default();
if let Ok(kittycad_modeling_cmds::websocket::FailureWebSocketResponse { errors, .. }) =
serde_json::from_str(&err_str)
{
KclError::Engine(KclErrorDetails {
message: errors.iter().map(|e| e.message.clone()).collect::<Vec<_>>().join("\n"),
source_ranges: vec![source_range],
})
} else {
KclError::Engine(KclErrorDetails {
message: format!("Failed to wait for promise from send modeling command: {:?}", e),
source_ranges: vec![source_range],
})
}
})?;
// Parse the value as a string.
let s = value.as_string().ok_or_else(|| {
KclError::Engine(KclErrorDetails {
message: format!("Failed to get string from response from engine: `{:?}`", value),
source_ranges: vec![source_range],
})
})?;
// Convert JsValue to a Uint8Array
let data = js_sys::Uint8Array::from(value);
let ws_result: WebSocketResponse = serde_json::from_str(&s).map_err(|e| {
let ws_result: WebSocketResponse = bson::from_slice(&data.to_vec()).map_err(|e| {
KclError::Engine(KclErrorDetails {
message: format!("Failed to deserialize response from engine: {:?}", e),
message: format!("Failed to deserialize bson response from engine: {:?}", e),
source_ranges: vec![source_range],
})
})?;

View File

@ -147,6 +147,11 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
source_range: SourceRange,
) -> Result<(), crate::errors::KclError>;
async fn clear_queues(&self) {
self.batch().write().await.clear();
self.batch_end().write().await.clear();
}
/// Send a modeling command and wait for the response message.
async fn inner_send_modeling_cmd(
&self,
@ -161,6 +166,9 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
id_generator: &mut IdGenerator,
source_range: SourceRange,
) -> Result<(), crate::errors::KclError> {
// Clear any batched commands leftover from previous scenes.
self.clear_queues().await;
self.batch_modeling_cmd(
uuid::Uuid::new_v4(),
source_range,

View File

@ -6,7 +6,7 @@ use kittycad_modeling_cmds::coord::{System, KITTYCAD, OPENGL, VULKAN};
use crate::{
errors::KclErrorDetails,
execution::kcl_value::{UnitAngle, UnitLen},
execution::types::{UnitAngle, UnitLen},
parsing::ast::types::{Annotation, Expr, Node, ObjectProperty},
KclError, SourceRange,
};
@ -78,13 +78,16 @@ pub(super) fn expect_properties<'a>(
}
pub(super) fn expect_ident(expr: &Expr) -> Result<&str, KclError> {
match expr {
Expr::Identifier(id) => Ok(&id.name),
e => Err(KclError::Semantic(KclErrorDetails {
message: "Unexpected settings value, expected a simple name, e.g., `mm`".to_owned(),
source_ranges: vec![e.into()],
})),
if let Expr::Name(name) = expr {
if let Some(name) = name.local_ident() {
return Ok(*name);
}
}
Err(KclError::Semantic(KclErrorDetails {
message: "Unexpected settings value, expected a simple name, e.g., `mm`".to_owned(),
source_ranges: vec![expr.into()],
}))
}
pub(super) fn get_impl(annotations: &[Node<Annotation>], source_range: SourceRange) -> Result<Option<Impl>, KclError> {

View File

@ -2,7 +2,7 @@ use indexmap::IndexMap;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use super::{kcl_value::NumericType, ArtifactId, KclValue};
use super::{types::NumericType, ArtifactId, KclValue};
use crate::{docs::StdLibFn, std::get_stdlib_fn, SourceRange};
/// A CAD modeling operation for display in the feature tree, AKA operations

View File

@ -1,16 +1,19 @@
use std::collections::HashMap;
use async_recursion::async_recursion;
use indexmap::IndexMap;
use super::kcl_value::TypeDef;
use crate::{
engine::ExecutionKind,
errors::{KclError, KclErrorDetails},
execution::{
annotations,
cad_op::{OpArg, OpKclValue, Operation},
kcl_value::{FunctionSource, NumericType, RuntimeType},
kcl_value::FunctionSource,
memory,
state::ModuleState,
types::{NumericType, RuntimeType},
BodyType, EnvironmentRef, ExecState, ExecutorContext, KclValue, Metadata, PlaneType, TagEngineInfo,
TagIdentifier,
},
@ -18,7 +21,7 @@ use crate::{
parsing::ast::types::{
Annotation, ArrayExpression, ArrayRangeExpression, BinaryExpression, BinaryOperator, BinaryPart, BodyItem,
CallExpression, CallExpressionKw, Expr, FunctionExpression, IfExpression, ImportPath, ImportSelector,
ItemVisibility, LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, Node, NodeRef,
ItemVisibility, LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, Name, Node, NodeRef,
ObjectExpression, PipeExpression, Program, TagDeclarator, Type, UnaryExpression, UnaryOperator,
},
source_range::SourceRange,
@ -55,7 +58,9 @@ impl ExecutorContext {
for annotation in annotations {
if annotation.name() == Some(annotations::SETTINGS) {
if matches!(body_type, BodyType::Root) {
exec_state.mod_local.settings.update_from_annotation(annotation)?;
if exec_state.mod_local.settings.update_from_annotation(annotation)? {
exec_state.mod_local.explicit_length_units = true;
}
let new_units = exec_state.length_unit();
if !self.engine.execution_kind().await.is_isolated() {
self.engine
@ -96,7 +101,7 @@ impl ExecutorContext {
module_id: ModuleId,
path: &ModulePath,
) -> Result<(Option<KclValue>, EnvironmentRef, Vec<String>), KclError> {
crate::log::log(format!("enter module {path} {}", exec_state.stack()));
crate::log::log(format!("enter module {path} {} {exec_kind:?}", exec_state.stack()));
let old_units = exec_state.length_unit();
let original_execution = self.engine.replace_execution_kind(exec_kind).await;
@ -347,7 +352,7 @@ impl ExecutorContext {
let impl_kind = annotations::get_impl(&ty.outer_attrs, metadata.source_range)?.unwrap_or_default();
match impl_kind {
annotations::Impl::Rust => {
let std_path = match &exec_state.mod_local.settings.std_path {
let std_path = match &exec_state.mod_local.std_path {
Some(p) => p,
None => {
return Err(KclError::Semantic(KclErrorDetails {
@ -356,8 +361,9 @@ impl ExecutorContext {
}));
}
};
let (t, props) = crate::std::std_ty(std_path, &ty.name.name);
let value = KclValue::Type {
value: Some(crate::std::std_ty(std_path, &ty.name.name)),
value: TypeDef::RustRepr(t, props),
meta: vec![metadata],
};
exec_state
@ -376,12 +382,40 @@ impl ExecutorContext {
}
// Do nothing for primitive types, they get special treatment and their declarations are just for documentation.
annotations::Impl::Primitive => {}
annotations::Impl::Kcl => {
return Err(KclError::Semantic(KclErrorDetails {
message: "User-defined types are not yet supported.".to_owned(),
source_ranges: vec![metadata.source_range],
}));
}
annotations::Impl::Kcl => match &ty.alias {
Some(alias) => {
let value = KclValue::Type {
value: TypeDef::Alias(
RuntimeType::from_parsed(
alias.inner.clone(),
exec_state,
metadata.source_range,
)
.map_err(|e| KclError::Semantic(e.into()))?,
),
meta: vec![metadata],
};
exec_state
.mut_stack()
.add(
format!("{}{}", memory::TYPE_PREFIX, ty.name.name),
value,
metadata.source_range,
)
.map_err(|_| {
KclError::Semantic(KclErrorDetails {
message: format!("Redefinition of type {}.", ty.name.name),
source_ranges: vec![metadata.source_range],
})
})?;
}
None => {
return Err(KclError::Semantic(KclErrorDetails {
message: "User-defined types are not yet supported.".to_owned(),
source_ranges: vec![metadata.source_range],
}))
}
},
}
last_expr = None;
@ -534,15 +568,23 @@ impl ExecutorContext {
source_range: SourceRange,
) -> Result<Option<KclValue>, KclError> {
let path = exec_state.global.module_infos[&module_id].path.clone();
let repr = exec_state.global.module_infos[&module_id].take_repr();
let mut repr = exec_state.global.module_infos[&module_id].take_repr();
// DON'T EARLY RETURN! We need to restore the module repr
let result = match &repr {
let result = match &mut repr {
ModuleRepr::Root => Err(exec_state.circular_import_error(&path, source_range)),
ModuleRepr::Kcl(program, _) => self
.exec_module_from_ast(program, module_id, &path, exec_state, exec_kind, source_range)
.await
.map(|(val, _, _)| val),
ModuleRepr::Kcl(program, cached_items) => {
let result = self
.exec_module_from_ast(program, module_id, &path, exec_state, exec_kind, source_range)
.await;
match result {
Ok((val, env, items)) => {
*cached_items = Some((env, items));
Ok(val)
}
Err(e) => Err(e),
}
}
ModuleRepr::Foreign(geom) => super::import::send_to_engine(geom.clone(), self)
.await
.map(|geom| Some(KclValue::ImportedGeometry(geom))),
@ -596,10 +638,10 @@ impl ExecutorContext {
) -> Result<KclValue, KclError> {
let item = match init {
Expr::None(none) => KclValue::from(none),
Expr::Literal(literal) => KclValue::from_literal((**literal).clone(), &exec_state.mod_local.settings),
Expr::Literal(literal) => KclValue::from_literal((**literal).clone(), exec_state),
Expr::TagDeclarator(tag) => tag.execute(exec_state).await?,
Expr::Identifier(identifier) => {
let value = exec_state.stack().get(&identifier.name, identifier.into())?.clone();
Expr::Name(name) => {
let value = name.get_result(exec_state, self).await?.clone();
if let KclValue::Module { value: module_id, meta } = value {
self.exec_module_for_result(module_id, exec_state, ExecutionKind::Normal, metadata.source_range)
.await?
@ -627,10 +669,14 @@ impl ExecutorContext {
.unwrap_or(false);
if rust_impl {
if let Some(std_path) = &exec_state.mod_local.settings.std_path {
if let Some(std_path) = &exec_state.mod_local.std_path {
let (func, props) = crate::std::std_fn(std_path, statement_kind.expect_name());
KclValue::Function {
value: FunctionSource::Std { func, props },
value: FunctionSource::Std {
func,
props,
ast: function_expression.clone(),
},
meta: vec![metadata.to_owned()],
}
} else {
@ -642,7 +688,7 @@ impl ExecutorContext {
}
} else {
// Snapshotting memory here is crucial for semantics so that we close
// over variables. Variables defined lexically later shouldn't
// over variables. Variables defined lexically later shouldn't
// be available to the function body.
KclValue::Function {
value: FunctionSource::User {
@ -698,44 +744,36 @@ impl ExecutorContext {
let result = self
.execute_expr(&expr.expr, exec_state, metadata, &[], statement_kind)
.await?;
coerce(&result, &expr.ty, exec_state).ok_or_else(|| {
KclError::Semantic(KclErrorDetails {
message: format!(
"could not coerce {} value to type {}",
result.human_friendly_type(),
expr.ty
),
source_ranges: vec![expr.into()],
})
})?
coerce(&result, &expr.ty, exec_state, expr.into())?
}
};
Ok(item)
}
}
fn coerce(value: &KclValue, ty: &Node<Type>, exec_state: &mut ExecState) -> Option<KclValue> {
fn coerce(
value: &KclValue,
ty: &Node<Type>,
exec_state: &mut ExecState,
source_range: SourceRange,
) -> Result<KclValue, KclError> {
let ty = RuntimeType::from_parsed(ty.inner.clone(), exec_state, value.into())
.map_err(|e| {
exec_state.err(e);
})
.ok()??;
.map_err(|e| KclError::Semantic(e.into()))?;
value.coerce(&ty, exec_state)
value.coerce(&ty, exec_state).ok_or_else(|| {
KclError::Semantic(KclErrorDetails {
message: format!("could not coerce {} value to type {}", value.human_friendly_type(), ty),
source_ranges: vec![source_range],
})
})
}
impl BinaryPart {
#[async_recursion]
pub async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
match self {
BinaryPart::Literal(literal) => Ok(KclValue::from_literal(
(**literal).clone(),
&exec_state.mod_local.settings,
)),
BinaryPart::Identifier(identifier) => {
let value = exec_state.stack().get(&identifier.name, identifier.into())?;
Ok(value.clone())
}
BinaryPart::Literal(literal) => Ok(KclValue::from_literal((**literal).clone(), exec_state)),
BinaryPart::Name(name) => name.get_result(exec_state, ctx).await.cloned(),
BinaryPart::BinaryExpression(binary_expression) => binary_expression.get_result(exec_state, ctx).await,
BinaryPart::CallExpression(call_expression) => call_expression.execute(exec_state, ctx).await,
BinaryPart::CallExpressionKw(call_expression) => call_expression.execute(exec_state, ctx).await,
@ -746,6 +784,73 @@ impl BinaryPart {
}
}
impl Node<Name> {
async fn get_result<'a>(
&self,
exec_state: &'a mut ExecState,
ctx: &ExecutorContext,
) -> Result<&'a KclValue, KclError> {
if self.abs_path {
return Err(KclError::Semantic(KclErrorDetails {
message: "Absolute paths (names beginning with `::` are not yet supported)".to_owned(),
source_ranges: self.as_source_ranges(),
}));
}
if self.path.is_empty() {
return exec_state.stack().get(&self.name.name, self.into());
}
let mut mem_spec: Option<(EnvironmentRef, Vec<String>)> = None;
for p in &self.path {
let value = match mem_spec {
Some((env, exports)) => {
if !exports.contains(&p.name) {
return Err(KclError::Semantic(KclErrorDetails {
message: format!("Item {} not found in module's exported items", p.name),
source_ranges: p.as_source_ranges(),
}));
}
exec_state
.stack()
.memory
.get_from(&p.name, env, p.as_source_range(), 0)?
}
None => exec_state.stack().get(&p.name, self.into())?,
};
let KclValue::Module { value: module_id, .. } = value else {
return Err(KclError::Semantic(KclErrorDetails {
message: format!(
"Identifier in path must refer to a module, found {}",
value.human_friendly_type()
),
source_ranges: p.as_source_ranges(),
}));
};
mem_spec = Some(
ctx.exec_module_for_items(*module_id, exec_state, ExecutionKind::Normal, p.as_source_range())
.await?,
);
}
let (env, exports) = mem_spec.unwrap();
if !exports.contains(&self.name.name) {
return Err(KclError::Semantic(KclErrorDetails {
message: format!("Item {} not found in module's exported items", self.name.name),
source_ranges: self.name.as_source_ranges(),
}));
}
exec_state
.stack()
.memory
.get_from(&self.name.name, env, self.name.as_source_range(), 0)
}
}
impl Node<MemberExpression> {
fn get_result(&self, exec_state: &mut ExecState) -> Result<KclValue, KclError> {
let property = Property::try_from(self.computed, self.property.clone(), exec_state, self.into())?;
@ -1076,11 +1181,11 @@ async fn inner_execute_pipe_body(
impl Node<CallExpressionKw> {
#[async_recursion]
pub async fn execute(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
let fn_name = &self.callee.name;
let fn_name = &self.callee;
let callsite: SourceRange = self.into();
// Build a hashmap from argument labels to the final evaluated values.
let mut fn_args = HashMap::with_capacity(self.arguments.len());
let mut fn_args = IndexMap::with_capacity(self.arguments.len());
for arg_expr in &self.arguments {
let source_range = SourceRange::from(arg_expr.arg.clone());
let metadata = Metadata { source_range };
@ -1120,6 +1225,7 @@ impl Node<CallExpressionKw> {
format!("`{fn_name}` is deprecated, see the docs for a recommended replacement"),
));
}
let op = if func.feature_tree_operation() {
let op_labeled_args = args
.kw_args
@ -1140,10 +1246,34 @@ impl Node<CallExpressionKw> {
None
};
let formals = func.args(false);
for (label, arg) in &args.kw_args.labeled {
match formals.iter().find(|p| &p.name == label) {
Some(p) => {
if !p.label_required {
exec_state.err(CompilationError::err(
arg.source_range,
format!(
"The function `{fn_name}` expects an unlabeled first parameter (`{label}`), but it is labelled in the call"
),
));
}
}
None => {
exec_state.err(CompilationError::err(
arg.source_range,
format!("`{label}` is not an argument of `{fn_name}`"),
));
}
}
}
// Attempt to call the function.
let mut return_value = {
// Don't early-return in this block.
exec_state.mut_stack().push_new_env_for_rust_call();
let result = func.std_lib_fn()(exec_state, args).await;
exec_state.mut_stack().pop_env();
if let Some(mut op) = op {
op.set_std_lib_call_is_error(result.is_err());
@ -1162,10 +1292,9 @@ impl Node<CallExpressionKw> {
Ok(return_value)
}
FunctionKind::UserDefined => {
let source_range = SourceRange::from(self);
// Clone the function so that we can use a mutable reference to
// exec_state.
let func = exec_state.stack().get(fn_name, source_range)?.clone();
let func = fn_name.get_result(exec_state, ctx).await?.clone();
// Track call operation.
let op_labeled_args = args
@ -1175,7 +1304,7 @@ impl Node<CallExpressionKw> {
.map(|(k, arg)| (k.clone(), OpArg::new(OpKclValue::from(&arg.value), arg.source_range)))
.collect();
exec_state.global.operations.push(Operation::UserDefinedFunctionCall {
name: Some(fn_name.clone()),
name: Some(fn_name.to_string()),
function_source_range: func.function_def_source_range().unwrap_or_default(),
unlabeled_arg: args
.kw_args
@ -1186,17 +1315,21 @@ impl Node<CallExpressionKw> {
source_range: callsite,
});
let return_value = func
.call_fn_kw(args, exec_state, ctx.clone(), callsite)
.await
.map_err(|e| {
// Add the call expression to the source ranges.
// TODO currently ignored by the frontend
e.add_source_ranges(vec![source_range])
})?;
let Some(fn_src) = func.as_fn() else {
return Err(KclError::Semantic(KclErrorDetails {
message: "cannot call this because it isn't a function".to_string(),
source_ranges: vec![callsite],
}));
};
let return_value = fn_src.call_kw(exec_state, ctx, args, callsite).await.map_err(|e| {
// Add the call expression to the source ranges.
// TODO currently ignored by the frontend
e.add_source_ranges(vec![callsite])
})?;
let result = return_value.ok_or_else(move || {
let mut source_ranges: Vec<SourceRange> = vec![source_range];
let mut source_ranges: Vec<SourceRange> = vec![callsite];
// We want to send the source range of the original function.
if let KclValue::Function { meta, .. } = func {
source_ranges = meta.iter().map(|m| m.source_range).collect();
@ -1219,7 +1352,7 @@ impl Node<CallExpressionKw> {
impl Node<CallExpression> {
#[async_recursion]
pub async fn execute(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
let fn_name = &self.callee.name;
let fn_name = &self.callee;
let callsite = SourceRange::from(self);
let mut fn_args: Vec<Arg> = Vec::with_capacity(self.arguments.len());
@ -1244,6 +1377,7 @@ impl Node<CallExpression> {
format!("`{fn_name}` is deprecated, see the docs for a recommended replacement"),
));
}
let op = if func.feature_tree_operation() {
let op_labeled_args = func
.args(false)
@ -1300,11 +1434,11 @@ impl Node<CallExpression> {
let source_range = SourceRange::from(self);
// Clone the function so that we can use a mutable reference to
// exec_state.
let func = exec_state.stack().get(fn_name, source_range)?.clone();
let func = fn_name.get_result(exec_state, ctx).await?.clone();
// Track call operation.
exec_state.global.operations.push(Operation::UserDefinedFunctionCall {
name: Some(fn_name.clone()),
name: Some(fn_name.to_string()),
function_source_range: func.function_def_source_range().unwrap_or_default(),
unlabeled_arg: None,
// TODO: Add the arguments for legacy positional parameters.
@ -1312,14 +1446,17 @@ impl Node<CallExpression> {
source_range: callsite,
});
let return_value = func
.call_fn(fn_args, exec_state, ctx.clone(), source_range)
.await
.map_err(|e| {
// Add the call expression to the source ranges.
// TODO currently ignored by the frontend
e.add_source_ranges(vec![source_range])
})?;
let Some(fn_src) = func.as_fn() else {
return Err(KclError::Semantic(KclErrorDetails {
message: "cannot call this because it isn't a function".to_string(),
source_ranges: vec![source_range],
}));
};
let return_value = fn_src.call(exec_state, ctx, fn_args, source_range).await.map_err(|e| {
// Add the call expression to the source ranges.
// TODO currently ignored by the frontend
e.add_source_ranges(vec![source_range])
})?;
let result = return_value.ok_or_else(move || {
let mut source_ranges: Vec<SourceRange> = vec![source_range];
@ -1767,15 +1904,12 @@ fn assign_args_to_params(
return Err(err_wrong_number_args);
}
let mem = &mut exec_state.mod_local.stack;
let settings = &exec_state.mod_local.settings;
// Add the arguments to the memory. A new call frame should have already
// been created.
for (index, param) in function_expression.params.iter().enumerate() {
if let Some(arg) = args.get(index) {
// Argument was provided.
mem.add(
exec_state.mut_stack().add(
param.identifier.name.clone(),
arg.value.clone(),
(&param.identifier).into(),
@ -1785,11 +1919,10 @@ fn assign_args_to_params(
if let Some(ref default_val) = param.default_value {
// If the corresponding parameter is optional,
// then it's fine, the user doesn't need to supply it.
mem.add(
param.identifier.name.clone(),
KclValue::from_default_param(default_val.clone(), settings),
(&param.identifier).into(),
)?;
let value = KclValue::from_default_param(default_val.clone(), exec_state);
exec_state
.mut_stack()
.add(param.identifier.name.clone(), value, (&param.identifier).into())?;
} else {
// But if the corresponding parameter was required,
// then the user has called with too few arguments.
@ -1805,11 +1938,30 @@ fn assign_args_to_params_kw(
mut args: crate::std::args::KwArgs,
exec_state: &mut ExecState,
) -> Result<(), KclError> {
for (label, arg) in &args.labeled {
match function_expression.params.iter().find(|p| &p.identifier.name == label) {
Some(p) => {
if !p.labeled {
exec_state.err(CompilationError::err(
arg.source_range,
format!(
"This function expects an unlabeled first parameter (`{label}`), but it is labelled in the call"
),
));
}
}
None => {
exec_state.err(CompilationError::err(
arg.source_range,
format!("`{label}` is not an argument of this function"),
));
}
}
}
// Add the arguments to the memory. A new call frame should have already
// been created.
let source_ranges = vec![function_expression.into()];
let mem = &mut exec_state.mod_local.stack;
let settings = &exec_state.mod_local.settings;
for param in function_expression.params.iter() {
if param.labeled {
@ -1817,7 +1969,7 @@ fn assign_args_to_params_kw(
let arg_val = match arg {
Some(arg) => arg.value.clone(),
None => match param.default_value {
Some(ref default_val) => KclValue::from_default_param(default_val.clone(), settings),
Some(ref default_val) => KclValue::from_default_param(default_val.clone(), exec_state),
None => {
return Err(KclError::Semantic(KclErrorDetails {
source_ranges,
@ -1829,7 +1981,9 @@ fn assign_args_to_params_kw(
}
},
};
mem.add(param.identifier.name.clone(), arg_val, (&param.identifier).into())?;
exec_state
.mut_stack()
.add(param.identifier.name.clone(), arg_val, (&param.identifier).into())?;
} else {
let Some(unlabeled) = args.unlabeled.take() else {
let param_name = &param.identifier.name;
@ -1846,17 +2000,18 @@ fn assign_args_to_params_kw(
})
});
};
mem.add(
exec_state.mut_stack().add(
param.identifier.name.clone(),
unlabeled.value.clone(),
(&param.identifier).into(),
)?;
}
}
Ok(())
}
pub(crate) async fn call_user_defined_function(
async fn call_user_defined_function(
args: Vec<Arg>,
memory: EnvironmentRef,
function_expression: NodeRef<'_, FunctionExpression>,
@ -1889,7 +2044,7 @@ pub(crate) async fn call_user_defined_function(
result
}
pub(crate) async fn call_user_defined_function_kw(
async fn call_user_defined_function_kw(
args: crate::std::args::KwArgs,
memory: EnvironmentRef,
function_expression: NodeRef<'_, FunctionExpression>,
@ -1927,35 +2082,138 @@ impl FunctionSource {
&self,
exec_state: &mut ExecState,
ctx: &ExecutorContext,
args: Vec<Arg>,
source_range: SourceRange,
mut args: Vec<Arg>,
callsite: SourceRange,
) -> Result<Option<KclValue>, KclError> {
match self {
FunctionSource::Std { func, props } => {
FunctionSource::Std { props, .. } => {
if args.len() <= 1 {
let args = crate::std::Args::new_kw(
KwArgs {
unlabeled: args.pop(),
labeled: IndexMap::new(),
},
callsite,
ctx.clone(),
exec_state.mod_local.pipe_value.clone().map(|v| Arg::new(v, callsite)),
);
self.call_kw(exec_state, ctx, args, callsite).await
} else {
Err(KclError::Semantic(KclErrorDetails {
message: format!("{} requires its arguments to be labelled", props.name),
source_ranges: vec![callsite],
}))
}
}
FunctionSource::User { ast, memory, .. } => {
call_user_defined_function(args, *memory, ast, exec_state, ctx).await
}
FunctionSource::None => unreachable!(),
}
}
pub async fn call_kw(
&self,
exec_state: &mut ExecState,
ctx: &ExecutorContext,
mut args: crate::std::Args,
callsite: SourceRange,
) -> Result<Option<KclValue>, KclError> {
match self {
FunctionSource::Std { func, ast, props } => {
if props.deprecated {
exec_state.warn(CompilationError::err(
source_range,
callsite,
format!(
"`{}` is deprecated, see the docs for a recommended replacement",
props.name
),
));
}
let args = crate::std::Args::new(
args,
source_range,
ctx.clone(),
exec_state
.mod_local
.pipe_value
.clone()
.map(|v| Arg::new(v, source_range)),
);
func(exec_state, args).await.map(Some)
for (label, arg) in &mut args.kw_args.labeled {
match ast.params.iter().find(|p| &p.identifier.name == label) {
Some(p) => {
if !p.labeled {
exec_state.err(CompilationError::err(
arg.source_range,
format!(
"The function `{}` expects an unlabeled first parameter (`{label}`), but it is labelled in the call",
props.name
),
));
}
if let Some(ty) = &p.type_ {
arg.value = arg
.value
.coerce(
&RuntimeType::from_parsed(ty.inner.clone(), exec_state, arg.source_range)
.unwrap(),
exec_state,
)
.ok_or_else(|| {
KclError::Semantic(KclErrorDetails {
message: format!(
"{label} requires a value with type `{}`, but found {}",
ty.inner,
arg.value.human_friendly_type()
),
source_ranges: vec![callsite],
})
})?;
}
}
None => {
exec_state.err(CompilationError::err(
arg.source_range,
format!("`{label}` is not an argument of `{}`", props.name),
));
}
}
}
if let Some(arg) = &mut args.kw_args.unlabeled {
if let Some(p) = ast.params.iter().find(|p| !p.labeled) {
if let Some(ty) = &p.type_ {
arg.value = arg
.value
.coerce(
&RuntimeType::from_parsed(ty.inner.clone(), exec_state, arg.source_range).unwrap(),
exec_state,
)
.ok_or_else(|| {
KclError::Semantic(KclErrorDetails {
message: format!(
"The input argument of {} requires a value with type `{}`, but found {}",
props.name,
ty.inner,
arg.value.human_friendly_type()
),
source_ranges: vec![callsite],
})
})?;
}
}
}
// Attempt to call the function.
exec_state.mut_stack().push_new_env_for_rust_call();
let mut result = {
// Don't early-return in this block.
let result = func(exec_state, args).await;
exec_state.mut_stack().pop_env();
// TODO support recording op into the feature tree
result
}?;
update_memory_for_tags_of_geometry(&mut result, exec_state)?;
Ok(Some(result))
}
FunctionSource::User { ast, memory, .. } => {
call_user_defined_function(args, *memory, ast, exec_state, ctx).await
call_user_defined_function_kw(args.kw_args, *memory, ast, exec_state, ctx).await
}
FunctionSource::None => unreachable!(),
}

View File

@ -83,16 +83,17 @@ pub struct ImportedGeometry {
#[ts(export)]
#[serde(tag = "type", rename_all = "camelCase")]
#[allow(clippy::vec_box)]
pub enum SolidOrImportedGeometry {
pub enum SolidOrSketchOrImportedGeometry {
ImportedGeometry(Box<ImportedGeometry>),
SolidSet(Vec<Solid>),
SketchSet(Vec<Sketch>),
}
impl From<SolidOrImportedGeometry> for crate::execution::KclValue {
fn from(value: SolidOrImportedGeometry) -> Self {
impl From<SolidOrSketchOrImportedGeometry> for crate::execution::KclValue {
fn from(value: SolidOrSketchOrImportedGeometry) -> Self {
match value {
SolidOrImportedGeometry::ImportedGeometry(s) => crate::execution::KclValue::ImportedGeometry(*s),
SolidOrImportedGeometry::SolidSet(mut s) => {
SolidOrSketchOrImportedGeometry::ImportedGeometry(s) => crate::execution::KclValue::ImportedGeometry(*s),
SolidOrSketchOrImportedGeometry::SolidSet(mut s) => {
if s.len() == 1 {
crate::execution::KclValue::Solid {
value: Box::new(s.pop().unwrap()),
@ -103,7 +104,22 @@ impl From<SolidOrImportedGeometry> for crate::execution::KclValue {
.into_iter()
.map(|s| crate::execution::KclValue::Solid { value: Box::new(s) })
.collect(),
ty: crate::execution::PrimitiveType::Solid,
ty: crate::execution::types::RuntimeType::solid(),
}
}
}
SolidOrSketchOrImportedGeometry::SketchSet(mut s) => {
if s.len() == 1 {
crate::execution::KclValue::Sketch {
value: Box::new(s.pop().unwrap()),
}
} else {
crate::execution::KclValue::HomArray {
value: s
.into_iter()
.map(|s| crate::execution::KclValue::Sketch { value: Box::new(s) })
.collect(),
ty: crate::execution::types::RuntimeType::sketch(),
}
}
}
@ -111,11 +127,12 @@ impl From<SolidOrImportedGeometry> for crate::execution::KclValue {
}
}
impl SolidOrImportedGeometry {
impl SolidOrSketchOrImportedGeometry {
pub(crate) fn ids(&self) -> Vec<uuid::Uuid> {
match self {
SolidOrImportedGeometry::ImportedGeometry(s) => vec![s.id],
SolidOrImportedGeometry::SolidSet(s) => s.iter().map(|s| s.id).collect(),
SolidOrSketchOrImportedGeometry::ImportedGeometry(s) => vec![s.id],
SolidOrSketchOrImportedGeometry::SolidSet(s) => s.iter().map(|s| s.id).collect(),
SolidOrSketchOrImportedGeometry::SketchSet(s) => s.iter().map(|s| s.id).collect(),
}
}
}
@ -135,6 +152,8 @@ pub struct Helix {
pub angle_start: f64,
/// Is the helix rotation counter clockwise?
pub ccw: bool,
/// The cylinder the helix was created on.
pub cylinder_id: Option<uuid::Uuid>,
pub units: UnitLen,
#[serde(skip)]
pub meta: Vec<Metadata>,

View File

@ -17,7 +17,7 @@ use uuid::Uuid;
use crate::{
errors::{KclError, KclErrorDetails},
execution::{annotations, kcl_value::UnitLen, ExecState, ExecutorContext, ImportedGeometry},
execution::{annotations, types::UnitLen, ExecState, ExecutorContext, ImportedGeometry},
fs::FileSystem,
parsing::ast::types::{Annotation, Node},
source_range::SourceRange,

View File

@ -1,29 +1,21 @@
use std::{collections::HashMap, fmt};
use std::collections::HashMap;
use anyhow::Result;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde::Serialize;
use super::{
memory::{self, EnvironmentRef},
MetaSettings, Point3d,
};
use super::{types::UnitLen, EnvironmentRef, ExecState, MetaSettings};
use crate::{
errors::KclErrorDetails,
execution::{
ExecState, ExecutorContext, Face, Helix, ImportedGeometry, Metadata, Plane, Sketch, Solid, TagIdentifier,
annotations::{SETTINGS, SETTINGS_UNIT_LENGTH},
types::{NumericType, PrimitiveType, RuntimeType},
Face, Helix, ImportedGeometry, Metadata, Plane, Sketch, Solid, TagIdentifier,
},
parsing::{
ast::types::{
DefaultParamVal, FunctionExpression, KclNone, Literal, LiteralValue, Node,
PrimitiveType as AstPrimitiveType, TagDeclarator, TagNode, Type,
},
token::NumericSuffix,
},
std::{
args::{Arg, FromKclValue},
StdFnProps,
parsing::ast::types::{
DefaultParamVal, FunctionExpression, KclNone, Literal, LiteralValue, Node, TagDeclarator, TagNode,
},
std::StdFnProps,
CompilationError, KclError, ModuleId, SourceRange,
};
@ -65,7 +57,7 @@ pub enum KclValue {
value: Vec<KclValue>,
// The type of values, not the array type.
#[serde(skip)]
ty: PrimitiveType,
ty: RuntimeType,
},
Object {
value: KclObjectFields,
@ -105,7 +97,7 @@ pub enum KclValue {
#[ts(skip)]
Type {
#[serde(skip)]
value: Option<(PrimitiveType, StdFnProps)>,
value: TypeDef,
#[serde(skip)]
meta: Vec<Metadata>,
},
@ -122,6 +114,7 @@ pub enum FunctionSource {
None,
Std {
func: crate::std::StdFn,
ast: crate::parsing::ast::types::BoxNode<FunctionExpression>,
props: StdFnProps,
},
User {
@ -142,6 +135,12 @@ impl JsonSchema for FunctionSource {
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum TypeDef {
RustRepr(PrimitiveType, StdFnProps),
Alias(RuntimeType),
}
impl From<Vec<Sketch>> for KclValue {
fn from(mut eg: Vec<Sketch>) -> Self {
if eg.len() == 1 {
@ -154,7 +153,7 @@ impl From<Vec<Sketch>> for KclValue {
.into_iter()
.map(|s| KclValue::Sketch { value: Box::new(s) })
.collect(),
ty: crate::execution::PrimitiveType::Sketch,
ty: RuntimeType::Primitive(PrimitiveType::Sketch),
}
}
}
@ -169,7 +168,7 @@ impl From<Vec<Solid>> for KclValue {
} else {
KclValue::HomArray {
value: eg.into_iter().map(|s| KclValue::Solid { value: Box::new(s) }).collect(),
ty: crate::execution::PrimitiveType::Solid,
ty: RuntimeType::Primitive(PrimitiveType::Solid),
}
}
}
@ -310,22 +309,38 @@ impl KclValue {
}
}
pub(crate) fn from_literal(literal: Node<Literal>, settings: &MetaSettings) -> Self {
pub(crate) fn from_literal(literal: Node<Literal>, exec_state: &mut ExecState) -> Self {
let meta = vec![literal.metadata()];
match literal.inner.value {
LiteralValue::Number { value, suffix } => KclValue::Number {
value,
meta,
ty: NumericType::from_parsed(suffix, settings),
},
LiteralValue::Number { value, suffix } => {
let ty = NumericType::from_parsed(suffix, &exec_state.mod_local.settings);
if let NumericType::Default { len, .. } = &ty {
if !exec_state.mod_local.explicit_length_units && *len != UnitLen::Mm {
exec_state.warn(
CompilationError::err(
literal.as_source_range(),
"Project-wide units are deprecated. Prefer to use per-file default units.",
)
.with_suggestion(
"Fix by adding per-file settings",
format!("@{SETTINGS}({SETTINGS_UNIT_LENGTH} = {len})\n"),
// Insert at the start of the file.
Some(SourceRange::new(0, 0, literal.module_id)),
crate::errors::Tag::Deprecated,
),
);
}
}
KclValue::Number { value, meta, ty }
}
LiteralValue::String(value) => KclValue::String { value, meta },
LiteralValue::Bool(value) => KclValue::Bool { value, meta },
}
}
pub(crate) fn from_default_param(param: DefaultParamVal, settings: &MetaSettings) -> Self {
pub(crate) fn from_default_param(param: DefaultParamVal, exec_state: &mut ExecState) -> Self {
match param {
DefaultParamVal::Literal(lit) => Self::from_literal(lit, settings),
DefaultParamVal::Literal(lit) => Self::from_literal(lit, exec_state),
DefaultParamVal::KclNone(none) => KclValue::KclNone {
value: none,
meta: Default::default(),
@ -553,347 +568,13 @@ impl KclValue {
Ok(*b)
}
/// True if `self` has a type which is a subtype of `ty` without coercion.
pub fn has_type(&self, ty: &RuntimeType) -> bool {
let Some(self_ty) = self.principal_type() else {
return false;
};
self_ty.subtype(ty)
}
/// Coerce `self` to a new value which has `ty` as it's closest supertype.
///
/// If the result is Some, then:
/// - result.principal_type().unwrap().subtype(ty)
///
/// If self.principal_type() == ty then result == self
pub fn coerce(&self, ty: &RuntimeType, exec_state: &mut ExecState) -> Option<KclValue> {
match ty {
RuntimeType::Primitive(ty) => self.coerce_to_primitive_type(ty, exec_state),
RuntimeType::Array(ty, len) => self.coerce_to_array_type(ty, *len, exec_state),
RuntimeType::Tuple(tys) => self.coerce_to_tuple_type(tys, exec_state),
RuntimeType::Union(tys) => self.coerce_to_union_type(tys, exec_state),
RuntimeType::Object(tys) => self.coerce_to_object_type(tys, exec_state),
}
}
fn coerce_to_primitive_type(&self, ty: &PrimitiveType, exec_state: &mut ExecState) -> Option<KclValue> {
let value = match self {
KclValue::MixedArray { value, .. } | KclValue::HomArray { value, .. } if value.len() == 1 => &value[0],
_ => self,
};
match ty {
// TODO numeric type coercions
PrimitiveType::Number(_ty) => match value {
KclValue::Number { .. } => Some(value.clone()),
_ => None,
},
PrimitiveType::String => match value {
KclValue::String { .. } => Some(value.clone()),
_ => None,
},
PrimitiveType::Boolean => match value {
KclValue::Bool { .. } => Some(value.clone()),
_ => None,
},
PrimitiveType::Sketch => match value {
KclValue::Sketch { .. } => Some(value.clone()),
_ => None,
},
PrimitiveType::Solid => match value {
KclValue::Solid { .. } => Some(value.clone()),
_ => None,
},
PrimitiveType::Plane => match value {
KclValue::Plane { .. } => Some(value.clone()),
KclValue::Object { value, meta } => {
let origin = value.get("origin").and_then(Point3d::from_kcl_val)?;
let x_axis = value.get("xAxis").and_then(Point3d::from_kcl_val)?;
let y_axis = value.get("yAxis").and_then(Point3d::from_kcl_val)?;
let z_axis = value.get("zAxis").and_then(Point3d::from_kcl_val)?;
let id = exec_state.mod_local.id_generator.next_uuid();
let plane = Plane {
id,
artifact_id: id.into(),
origin,
x_axis,
y_axis,
z_axis,
value: super::PlaneType::Uninit,
// TODO use length unit from origin
units: exec_state.length_unit(),
meta: meta.clone(),
};
Some(KclValue::Plane { value: Box::new(plane) })
}
_ => None,
},
PrimitiveType::ImportedGeometry => match value {
KclValue::ImportedGeometry { .. } => Some(value.clone()),
_ => None,
},
}
}
fn coerce_to_array_type(&self, ty: &PrimitiveType, len: ArrayLen, exec_state: &mut ExecState) -> Option<KclValue> {
pub fn as_fn(&self) -> Option<&FunctionSource> {
match self {
KclValue::HomArray { value, ty: aty } => {
// TODO could check types of values individually
if aty != ty {
return None;
}
let value = match len {
ArrayLen::None => value.clone(),
ArrayLen::NonEmpty => {
if value.is_empty() {
return None;
}
value.clone()
}
ArrayLen::Known(n) => {
if n != value.len() {
return None;
}
value[..n].to_vec()
}
};
Some(KclValue::HomArray { value, ty: ty.clone() })
}
KclValue::MixedArray { value, .. } => {
let value = match len {
ArrayLen::None => value.clone(),
ArrayLen::NonEmpty => {
if value.is_empty() {
return None;
}
value.clone()
}
ArrayLen::Known(n) => {
if n != value.len() {
return None;
}
value[..n].to_vec()
}
};
let rt = RuntimeType::Primitive(ty.clone());
let value = value
.iter()
.map(|v| v.coerce(&rt, exec_state))
.collect::<Option<Vec<_>>>()?;
Some(KclValue::HomArray { value, ty: ty.clone() })
}
KclValue::KclNone { .. } if len.satisfied(0) => Some(KclValue::HomArray {
value: Vec::new(),
ty: ty.clone(),
}),
value if len.satisfied(1) => {
if value.has_type(&RuntimeType::Primitive(ty.clone())) {
Some(KclValue::HomArray {
value: vec![value.clone()],
ty: ty.clone(),
})
} else {
None
}
}
KclValue::Function { value, .. } => Some(value),
_ => None,
}
}
fn coerce_to_tuple_type(&self, tys: &[PrimitiveType], exec_state: &mut ExecState) -> Option<KclValue> {
match self {
KclValue::MixedArray { value, .. } | KclValue::HomArray { value, .. } => {
if value.len() < tys.len() {
return None;
}
let mut result = Vec::new();
for (i, t) in tys.iter().enumerate() {
result.push(value[i].coerce_to_primitive_type(t, exec_state)?);
}
Some(KclValue::MixedArray {
value: result,
meta: Vec::new(),
})
}
KclValue::KclNone { meta, .. } if tys.is_empty() => Some(KclValue::MixedArray {
value: Vec::new(),
meta: meta.clone(),
}),
value if tys.len() == 1 => {
if value.has_type(&RuntimeType::Primitive(tys[0].clone())) {
Some(KclValue::MixedArray {
value: vec![value.clone()],
meta: Vec::new(),
})
} else {
None
}
}
_ => None,
}
}
fn coerce_to_union_type(&self, tys: &[RuntimeType], exec_state: &mut ExecState) -> Option<KclValue> {
for t in tys {
if let Some(v) = self.coerce(t, exec_state) {
return Some(v);
}
}
None
}
fn coerce_to_object_type(&self, tys: &[(String, RuntimeType)], _exec_state: &mut ExecState) -> Option<KclValue> {
match self {
KclValue::Object { value, .. } => {
for (s, t) in tys {
// TODO coerce fields
if !value.get(s)?.has_type(t) {
return None;
}
}
// TODO remove non-required fields
Some(self.clone())
}
_ => None,
}
}
pub fn principal_type(&self) -> Option<RuntimeType> {
match self {
KclValue::Bool { .. } => Some(RuntimeType::Primitive(PrimitiveType::Boolean)),
KclValue::Number { ty, .. } => Some(RuntimeType::Primitive(PrimitiveType::Number(ty.clone()))),
KclValue::String { .. } => Some(RuntimeType::Primitive(PrimitiveType::String)),
KclValue::Object { value, .. } => {
let properties = value
.iter()
.map(|(k, v)| v.principal_type().map(|t| (k.clone(), t)))
.collect::<Option<Vec<_>>>()?;
Some(RuntimeType::Object(properties))
}
KclValue::Plane { .. } => Some(RuntimeType::Primitive(PrimitiveType::Plane)),
KclValue::Sketch { .. } => Some(RuntimeType::Primitive(PrimitiveType::Sketch)),
KclValue::Solid { .. } => Some(RuntimeType::Primitive(PrimitiveType::Solid)),
KclValue::ImportedGeometry(..) => Some(RuntimeType::Primitive(PrimitiveType::ImportedGeometry)),
KclValue::MixedArray { value, .. } => Some(RuntimeType::Tuple(
value
.iter()
.map(|v| v.principal_type().and_then(RuntimeType::primitive))
.collect::<Option<Vec<_>>>()?,
)),
KclValue::HomArray { ty, value, .. } => Some(RuntimeType::Array(ty.clone(), ArrayLen::Known(value.len()))),
KclValue::Face { .. } => None,
KclValue::Helix { .. }
| KclValue::Function { .. }
| KclValue::Module { .. }
| KclValue::TagIdentifier(_)
| KclValue::TagDeclarator(_)
| KclValue::KclNone { .. }
| KclValue::Type { .. }
| KclValue::Uuid { .. } => None,
}
}
/// If this memory item is a function, call it with the given arguments, return its val as Ok.
/// If it's not a function, return Err.
pub async fn call_fn(
&self,
args: Vec<Arg>,
exec_state: &mut ExecState,
ctx: ExecutorContext,
source_range: SourceRange,
) -> Result<Option<KclValue>, KclError> {
match self {
KclValue::Function {
value: FunctionSource::Std { func, props },
..
} => {
if props.deprecated {
exec_state.warn(CompilationError::err(
source_range,
format!(
"`{}` is deprecated, see the docs for a recommended replacement",
props.name
),
));
}
exec_state.mut_stack().push_new_env_for_rust_call();
let args = crate::std::Args::new(
args,
source_range,
ctx.clone(),
exec_state
.mod_local
.pipe_value
.clone()
.map(|v| Arg::new(v, source_range)),
);
let result = func(exec_state, args).await.map(Some);
exec_state.mut_stack().pop_env();
result
}
KclValue::Function {
value: FunctionSource::User { ast, memory, .. },
..
} => crate::execution::exec_ast::call_user_defined_function(args, *memory, ast, exec_state, &ctx).await,
_ => Err(KclError::Semantic(KclErrorDetails {
message: "cannot call this because it isn't a function".to_string(),
source_ranges: vec![source_range],
})),
}
}
/// If this is a function, call it by applying keyword arguments.
/// If it's not a function, returns an error.
pub async fn call_fn_kw(
&self,
args: crate::std::Args,
exec_state: &mut ExecState,
ctx: ExecutorContext,
callsite: SourceRange,
) -> Result<Option<KclValue>, KclError> {
match self {
KclValue::Function {
value: FunctionSource::Std { func: _, props },
..
} => {
if props.deprecated {
exec_state.warn(CompilationError::err(
callsite,
format!(
"`{}` is deprecated, see the docs for a recommended replacement",
props.name
),
));
}
todo!("Implement KCL stdlib fns with keyword args");
}
KclValue::Function {
value: FunctionSource::User { ast, memory, .. },
..
} => {
crate::execution::exec_ast::call_user_defined_function_kw(args.kw_args, *memory, ast, exec_state, &ctx)
.await
}
_ => Err(KclError::Semantic(KclErrorDetails {
message: "cannot call this because it isn't a function".to_string(),
source_ranges: vec![callsite],
})),
}
}
pub fn value_str(&self) -> Option<String> {
match self {
KclValue::Bool { value, .. } => Some(format!("{value}")),
@ -919,447 +600,3 @@ impl KclValue {
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum RuntimeType {
Primitive(PrimitiveType),
Array(PrimitiveType, ArrayLen),
Union(Vec<RuntimeType>),
Tuple(Vec<PrimitiveType>),
Object(Vec<(String, RuntimeType)>),
}
impl RuntimeType {
pub fn from_parsed(
value: Type,
exec_state: &mut ExecState,
source_range: SourceRange,
) -> Result<Option<Self>, CompilationError> {
Ok(match value {
Type::Primitive(pt) => {
PrimitiveType::from_parsed(pt, exec_state, source_range)?.map(RuntimeType::Primitive)
}
Type::Array(pt) => {
PrimitiveType::from_parsed(pt, exec_state, source_range)?.map(|t| RuntimeType::Array(t, ArrayLen::None))
}
Type::Object { properties } => properties
.into_iter()
.map(|p| {
let pt = match p.type_ {
Some(t) => t,
None => return Ok(None),
};
Ok(RuntimeType::from_parsed(pt.inner, exec_state, source_range)?
.map(|ty| (p.identifier.inner.name, ty)))
})
.collect::<Result<Option<Vec<_>>, CompilationError>>()?
.map(RuntimeType::Object),
})
}
pub fn human_friendly_type(&self) -> String {
match self {
RuntimeType::Primitive(ty) => ty.to_string(),
RuntimeType::Array(ty, ArrayLen::None) => format!("an array of {}", ty.display_multiple()),
RuntimeType::Array(ty, ArrayLen::NonEmpty) => format!("one or more {}", ty.display_multiple()),
RuntimeType::Array(ty, ArrayLen::Known(n)) => format!("an array of {n} {}", ty.display_multiple()),
RuntimeType::Union(tys) => tys
.iter()
.map(Self::human_friendly_type)
.collect::<Vec<_>>()
.join(" or "),
RuntimeType::Tuple(tys) => format!(
"an array with values of types ({})",
tys.iter().map(PrimitiveType::to_string).collect::<Vec<_>>().join(", ")
),
RuntimeType::Object(_) => format!("an object with fields {}", self),
}
}
// Subtype with no coercion, including refining numeric types.
fn subtype(&self, sup: &RuntimeType) -> bool {
use RuntimeType::*;
match (self, sup) {
(Primitive(t1), Primitive(t2)) => t1 == t2,
// TODO arrays could be covariant
(Array(t1, l1), Array(t2, l2)) => t1 == t2 && l1.subtype(*l2),
(Tuple(t1), Tuple(t2)) => t1 == t2,
(Tuple(t1), Array(t2, l2)) => (l2.satisfied(t1.len())) && t1.iter().all(|t| t == t2),
(Union(ts1), Union(ts2)) => ts1.iter().all(|t| ts2.contains(t)),
(t1, Union(ts2)) => ts2.contains(t1),
// TODO record subtyping - subtype can be larger, fields can be covariant.
(Object(t1), Object(t2)) => t1 == t2,
_ => false,
}
}
fn primitive(self) -> Option<PrimitiveType> {
match self {
RuntimeType::Primitive(t) => Some(t),
_ => None,
}
}
}
impl fmt::Display for RuntimeType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RuntimeType::Primitive(t) => t.fmt(f),
RuntimeType::Array(t, l) => match l {
ArrayLen::None => write!(f, "[{t}]"),
ArrayLen::NonEmpty => write!(f, "[{t}; 1+]"),
ArrayLen::Known(n) => write!(f, "[{t}; {n}]"),
},
RuntimeType::Tuple(ts) => write!(
f,
"[{}]",
ts.iter().map(|t| t.to_string()).collect::<Vec<_>>().join(", ")
),
RuntimeType::Union(ts) => write!(
f,
"{}",
ts.iter().map(|t| t.to_string()).collect::<Vec<_>>().join(" | ")
),
RuntimeType::Object(items) => write!(
f,
"{{ {} }}",
items
.iter()
.map(|(n, t)| format!("{n}: {t}"))
.collect::<Vec<_>>()
.join(", ")
),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ArrayLen {
None,
NonEmpty,
Known(usize),
}
impl ArrayLen {
pub fn subtype(self, other: ArrayLen) -> bool {
match (self, other) {
(_, ArrayLen::None) => true,
(ArrayLen::NonEmpty, ArrayLen::NonEmpty) => true,
(ArrayLen::Known(size), ArrayLen::NonEmpty) if size > 0 => true,
(ArrayLen::Known(s1), ArrayLen::Known(s2)) if s1 == s2 => true,
_ => false,
}
}
/// True if the length constraint is satisfied by the supplied length.
fn satisfied(self, len: usize) -> bool {
match self {
ArrayLen::None => true,
ArrayLen::NonEmpty => len > 0,
ArrayLen::Known(s) => len == s,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum PrimitiveType {
Number(NumericType),
String,
Boolean,
Sketch,
Solid,
Plane,
ImportedGeometry,
}
impl PrimitiveType {
fn from_parsed(
value: AstPrimitiveType,
exec_state: &mut ExecState,
source_range: SourceRange,
) -> Result<Option<Self>, CompilationError> {
Ok(match value {
AstPrimitiveType::String => Some(PrimitiveType::String),
AstPrimitiveType::Boolean => Some(PrimitiveType::Boolean),
AstPrimitiveType::Number(suffix) => Some(PrimitiveType::Number(NumericType::from_parsed(
suffix,
&exec_state.mod_local.settings,
))),
AstPrimitiveType::Named(name) => {
let ty_val = exec_state
.stack()
.get(&format!("{}{}", memory::TYPE_PREFIX, name.name), source_range)
.map_err(|_| CompilationError::err(source_range, format!("Unknown type: {}", name.name)))?;
let (ty, _) = match ty_val {
KclValue::Type { value: Some(ty), .. } => ty,
_ => unreachable!(),
};
Some(ty.clone())
}
_ => None,
})
}
fn display_multiple(&self) -> String {
match self {
PrimitiveType::Number(NumericType::Known(unit)) => format!("numbers({unit})"),
PrimitiveType::Number(_) => "numbers".to_owned(),
PrimitiveType::String => "strings".to_owned(),
PrimitiveType::Boolean => "bools".to_owned(),
PrimitiveType::Sketch => "Sketches".to_owned(),
PrimitiveType::Solid => "Solids".to_owned(),
PrimitiveType::Plane => "Planes".to_owned(),
PrimitiveType::ImportedGeometry => "imported geometries".to_owned(),
}
}
}
impl fmt::Display for PrimitiveType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PrimitiveType::Number(NumericType::Known(unit)) => write!(f, "number({unit})"),
PrimitiveType::Number(_) => write!(f, "number"),
PrimitiveType::String => write!(f, "string"),
PrimitiveType::Boolean => write!(f, "bool"),
PrimitiveType::Sketch => write!(f, "Sketch"),
PrimitiveType::Solid => write!(f, "Solid"),
PrimitiveType::Plane => write!(f, "Plane"),
PrimitiveType::ImportedGeometry => write!(f, "imported geometry"),
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type")]
pub enum NumericType {
// Specified by the user (directly or indirectly)
Known(UnitType),
// Unspecified, using defaults
Default { len: UnitLen, angle: UnitAngle },
// Exceeded the ability of the type system to track.
Unknown,
// Type info has been explicitly cast away.
Any,
}
impl NumericType {
pub fn count() -> Self {
NumericType::Known(UnitType::Count)
}
/// Combine two types when we expect them to be equal.
pub fn combine_eq(self, other: &NumericType) -> NumericType {
if &self == other {
self
} else {
NumericType::Unknown
}
}
/// Combine n types when we expect them to be equal.
///
/// Precondition: tys.len() > 0
pub fn combine_n_eq(tys: &[NumericType]) -> NumericType {
let ty0 = tys[0].clone();
for t in &tys[1..] {
if t != &ty0 {
return NumericType::Unknown;
}
}
ty0
}
/// Combine two types in addition-like operations.
pub fn combine_add(a: NumericType, b: NumericType) -> NumericType {
if a == b {
return a;
}
NumericType::Unknown
}
/// Combine two types in multiplication-like operations.
pub fn combine_mul(a: NumericType, b: NumericType) -> NumericType {
if a == NumericType::count() {
return b;
}
if b == NumericType::count() {
return a;
}
NumericType::Unknown
}
/// Combine two types in division-like operations.
pub fn combine_div(a: NumericType, b: NumericType) -> NumericType {
if b == NumericType::count() {
return a;
}
NumericType::Unknown
}
pub fn from_parsed(suffix: NumericSuffix, settings: &super::MetaSettings) -> Self {
match suffix {
NumericSuffix::None => NumericType::Default {
len: settings.default_length_units,
angle: settings.default_angle_units,
},
NumericSuffix::Count => NumericType::Known(UnitType::Count),
NumericSuffix::Mm => NumericType::Known(UnitType::Length(UnitLen::Mm)),
NumericSuffix::Cm => NumericType::Known(UnitType::Length(UnitLen::Cm)),
NumericSuffix::M => NumericType::Known(UnitType::Length(UnitLen::M)),
NumericSuffix::Inch => NumericType::Known(UnitType::Length(UnitLen::Inches)),
NumericSuffix::Ft => NumericType::Known(UnitType::Length(UnitLen::Feet)),
NumericSuffix::Yd => NumericType::Known(UnitType::Length(UnitLen::Yards)),
NumericSuffix::Deg => NumericType::Known(UnitType::Angle(UnitAngle::Degrees)),
NumericSuffix::Rad => NumericType::Known(UnitType::Angle(UnitAngle::Radians)),
}
}
}
impl From<UnitLen> for NumericType {
fn from(value: UnitLen) -> Self {
NumericType::Known(UnitType::Length(value))
}
}
impl From<UnitAngle> for NumericType {
fn from(value: UnitAngle) -> Self {
NumericType::Known(UnitType::Angle(value))
}
}
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type")]
pub enum UnitType {
Count,
Length(UnitLen),
Angle(UnitAngle),
}
impl std::fmt::Display for UnitType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
UnitType::Count => write!(f, "_"),
UnitType::Length(l) => l.fmt(f),
UnitType::Angle(a) => a.fmt(f),
}
}
}
// TODO called UnitLen so as not to clash with UnitLength in settings)
/// A unit of length.
#[derive(Debug, Default, Clone, Copy, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Eq)]
#[ts(export)]
#[serde(tag = "type")]
pub enum UnitLen {
#[default]
Mm,
Cm,
M,
Inches,
Feet,
Yards,
}
impl std::fmt::Display for UnitLen {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
UnitLen::Mm => write!(f, "mm"),
UnitLen::Cm => write!(f, "cm"),
UnitLen::M => write!(f, "m"),
UnitLen::Inches => write!(f, "in"),
UnitLen::Feet => write!(f, "ft"),
UnitLen::Yards => write!(f, "yd"),
}
}
}
impl TryFrom<NumericSuffix> for UnitLen {
type Error = ();
fn try_from(suffix: NumericSuffix) -> std::result::Result<Self, Self::Error> {
match suffix {
NumericSuffix::Mm => Ok(Self::Mm),
NumericSuffix::Cm => Ok(Self::Cm),
NumericSuffix::M => Ok(Self::M),
NumericSuffix::Inch => Ok(Self::Inches),
NumericSuffix::Ft => Ok(Self::Feet),
NumericSuffix::Yd => Ok(Self::Yards),
_ => Err(()),
}
}
}
impl From<crate::UnitLength> for UnitLen {
fn from(unit: crate::UnitLength) -> Self {
match unit {
crate::UnitLength::Cm => UnitLen::Cm,
crate::UnitLength::Ft => UnitLen::Feet,
crate::UnitLength::In => UnitLen::Inches,
crate::UnitLength::M => UnitLen::M,
crate::UnitLength::Mm => UnitLen::Mm,
crate::UnitLength::Yd => UnitLen::Yards,
}
}
}
impl From<UnitLen> for crate::UnitLength {
fn from(unit: UnitLen) -> Self {
match unit {
UnitLen::Cm => crate::UnitLength::Cm,
UnitLen::Feet => crate::UnitLength::Ft,
UnitLen::Inches => crate::UnitLength::In,
UnitLen::M => crate::UnitLength::M,
UnitLen::Mm => crate::UnitLength::Mm,
UnitLen::Yards => crate::UnitLength::Yd,
}
}
}
impl From<UnitLen> for kittycad_modeling_cmds::units::UnitLength {
fn from(unit: UnitLen) -> Self {
match unit {
UnitLen::Cm => kittycad_modeling_cmds::units::UnitLength::Centimeters,
UnitLen::Feet => kittycad_modeling_cmds::units::UnitLength::Feet,
UnitLen::Inches => kittycad_modeling_cmds::units::UnitLength::Inches,
UnitLen::M => kittycad_modeling_cmds::units::UnitLength::Meters,
UnitLen::Mm => kittycad_modeling_cmds::units::UnitLength::Millimeters,
UnitLen::Yards => kittycad_modeling_cmds::units::UnitLength::Yards,
}
}
}
/// A unit of angle.
#[derive(Debug, Default, Clone, Copy, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Eq)]
#[ts(export)]
#[serde(tag = "type")]
pub enum UnitAngle {
#[default]
Degrees,
Radians,
}
impl std::fmt::Display for UnitAngle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
UnitAngle::Degrees => write!(f, "deg"),
UnitAngle::Radians => write!(f, "rad"),
}
}
}
impl TryFrom<NumericSuffix> for UnitAngle {
type Error = ();
fn try_from(suffix: NumericSuffix) -> std::result::Result<Self, Self::Error> {
match suffix {
NumericSuffix::Deg => Ok(Self::Degrees),
NumericSuffix::Rad => Ok(Self::Radians),
_ => Err(()),
}
}
}

View File

@ -1055,7 +1055,7 @@ mod env {
#[cfg(test)]
mod test {
use super::*;
use crate::execution::kcl_value::{FunctionSource, NumericType};
use crate::execution::{kcl_value::FunctionSource, types::NumericType};
fn sr() -> SourceRange {
SourceRange::default()

View File

@ -15,7 +15,7 @@ pub(crate) use import::{
import_foreign, send_to_engine as send_import_to_engine, PreImportedGeometry, ZOO_COORD_SYSTEM,
};
use indexmap::IndexMap;
pub use kcl_value::{KclObjectFields, KclValue, PrimitiveType, UnitAngle, UnitLen};
pub use kcl_value::{KclObjectFields, KclValue};
use kcmc::{
each_cmd as mcmd,
ok_response::{output::TakeSnapshot, OkModelingCmdResponse},
@ -35,6 +35,7 @@ use crate::{
execution::{
artifact::build_artifact_graph,
cache::{CacheInformation, CacheResult},
types::{UnitAngle, UnitLen},
},
fs::FileManager,
modules::{ModuleId, ModulePath},
@ -56,6 +57,7 @@ mod import;
pub(crate) mod kcl_value;
mod memory;
mod state;
pub(crate) mod types;
/// Outcome of executing a program. This is used in TS.
#[derive(Debug, Clone, Serialize, ts_rs::TS)]
@ -740,27 +742,9 @@ impl ExecutorContext {
.map_err(KclErrorWithOutputs::no_outputs)?;
let default_planes = self.engine.get_default_planes().read().await.clone();
let env_ref = self
let result = self
.execute_and_build_graph(&program.ast, exec_state, preserve_mem)
.await
.map_err(|e| {
let module_id_to_module_path: IndexMap<ModuleId, ModulePath> = exec_state
.global
.path_to_source_id
.iter()
.map(|(k, v)| ((*v), k.clone()))
.collect();
KclErrorWithOutputs::new(
e,
exec_state.global.operations.clone(),
exec_state.global.artifact_commands.clone(),
exec_state.global.artifact_graph.clone(),
module_id_to_module_path,
exec_state.global.id_to_source.clone(),
default_planes,
)
})?;
.await;
crate::log::log(format!(
"Post interpretation KCL memory stats: {:#?}",
@ -768,6 +752,25 @@ impl ExecutorContext {
));
crate::log::log(format!("Engine stats: {:?}", self.engine.stats()));
let env_ref = result.map_err(|e| {
let module_id_to_module_path: IndexMap<ModuleId, ModulePath> = exec_state
.global
.path_to_source_id
.iter()
.map(|(k, v)| ((*v), k.clone()))
.collect();
KclErrorWithOutputs::new(
e,
exec_state.global.operations.clone(),
exec_state.global.artifact_commands.clone(),
exec_state.global.artifact_graph.clone(),
module_id_to_module_path,
exec_state.global.id_to_source.clone(),
default_planes,
)
})?;
if !self.is_mock() {
let mut mem = exec_state.stack().deep_clone();
mem.restore_env(env_ref);
@ -802,6 +805,10 @@ impl ExecutorContext {
)
.await;
// If we errored out and early-returned, there might be commands which haven't been executed
// and should be dropped.
self.engine.clear_queues().await;
// Move the artifact commands and responses to simplify cache management
// and error creation.
exec_state
@ -847,8 +854,7 @@ impl ExecutorContext {
.await?;
let (module_memory, _) = self
.exec_module_for_items(id, exec_state, ExecutionKind::Isolated, source_range)
.await
.unwrap();
.await?;
exec_state.mut_stack().memory.set_std(module_memory);
}
@ -1002,7 +1008,11 @@ mod tests {
use pretty_assertions::assert_eq;
use super::*;
use crate::{errors::KclErrorDetails, execution::memory::Stack, ModuleId};
use crate::{
errors::{KclErrorDetails, Severity},
execution::memory::Stack,
ModuleId,
};
/// Convenience function to get a JSON value from memory and unwrap.
#[track_caller]
@ -1409,6 +1419,22 @@ const answer = returnX()"#;
assert!(errs.is_empty());
}
#[tokio::test(flavor = "multi_thread")]
async fn type_aliases() {
let text = r#"type MyTy = [number; 2]
fn foo(x: MyTy) {
return x[0]
}
foo([0, 1])
type Other = MyTy | Helix
"#;
let result = parse_execute(text).await.unwrap();
let errs = result.exec_state.errors();
assert!(errs.is_empty());
}
#[tokio::test(flavor = "multi_thread")]
async fn test_cannot_shebang_in_fn() {
let ast = r#"
@ -1589,6 +1615,34 @@ const inInches = 2.0 * inch()"#;
);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_unit_suggest() {
let src = "foo = 42";
let program = crate::Program::parse_no_errs(src).unwrap();
let ctx = ExecutorContext {
engine: Arc::new(Box::new(
crate::engine::conn_mock::EngineConnection::new().await.unwrap(),
)),
fs: Arc::new(crate::fs::FileManager::new()),
stdlib: Arc::new(crate::std::StdLib::new()),
settings: ExecutorSettings {
units: UnitLength::Ft,
..Default::default()
},
context_type: ContextType::Mock,
};
let mut exec_state = ExecState::new(&ctx);
ctx.run(&program, &mut exec_state).await.unwrap();
let errs = exec_state.errors();
assert_eq!(errs.len(), 1, "{errs:?}");
let warn = &errs[0];
assert_eq!(warn.severity, Severity::Warning);
assert_eq!(
warn.apply_suggestion(src).unwrap(),
"@settings(defaultLengthUnit = ft)\nfoo = 42"
)
}
#[tokio::test(flavor = "multi_thread")]
async fn test_zero_param_fn() {
let ast = r#"const sigmaAllow = 35000 // psi
@ -1606,6 +1660,18 @@ const bracket = startSketchOn(XY)
parse_execute(ast).await.unwrap();
}
#[tokio::test(flavor = "multi_thread")]
async fn test_bad_arg_count_std() {
let ast = "startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> profileStartX()";
assert!(parse_execute(ast)
.await
.unwrap_err()
.message()
.contains("Expected a sketch argument"));
}
#[tokio::test(flavor = "multi_thread")]
async fn test_unary_operator_not_succeeds() {
let ast = r#"

View File

@ -12,10 +12,9 @@ use crate::{
execution::{
annotations,
id_generator::IdGenerator,
kcl_value,
memory::{ProgramMemory, Stack},
Artifact, ArtifactCommand, ArtifactGraph, ArtifactId, EnvironmentRef, ExecOutcome, ExecutorSettings, KclValue,
Operation, UnitAngle, UnitLen,
types, Artifact, ArtifactCommand, ArtifactGraph, ArtifactId, EnvironmentRef, ExecOutcome, ExecutorSettings,
KclValue, Operation, UnitAngle, UnitLen,
},
modules::{ModuleId, ModuleInfo, ModuleLoader, ModulePath, ModuleRepr, ModuleSource},
parsing::ast::types::Annotation,
@ -73,6 +72,8 @@ pub(super) struct ModuleState {
pub module_exports: Vec<String>,
/// Settings specified from annotations.
pub settings: MetaSettings,
pub(super) explicit_length_units: bool,
pub(super) std_path: Option<String>,
}
impl ExecState {
@ -301,10 +302,11 @@ impl ModuleState {
stack: memory.new_stack(),
pipe_value: Default::default(),
module_exports: Default::default(),
explicit_length_units: false,
std_path,
settings: MetaSettings {
default_length_units: exec_settings.units.into(),
default_angle_units: Default::default(),
std_path,
},
}
}
@ -314,28 +316,29 @@ impl ModuleState {
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct MetaSettings {
pub default_length_units: kcl_value::UnitLen,
pub default_angle_units: kcl_value::UnitAngle,
pub std_path: Option<String>,
pub default_length_units: types::UnitLen,
pub default_angle_units: types::UnitAngle,
}
impl MetaSettings {
pub(crate) fn update_from_annotation(
&mut self,
annotation: &crate::parsing::ast::types::Node<Annotation>,
) -> Result<(), KclError> {
) -> Result<bool, KclError> {
let properties = annotations::expect_properties(annotations::SETTINGS, annotation)?;
let mut updated_len = false;
for p in properties {
match &*p.inner.key.name {
annotations::SETTINGS_UNIT_LENGTH => {
let value = annotations::expect_ident(&p.inner.value)?;
let value = kcl_value::UnitLen::from_str(value, annotation.as_source_range())?;
let value = types::UnitLen::from_str(value, annotation.as_source_range())?;
self.default_length_units = value;
updated_len = true;
}
annotations::SETTINGS_UNIT_ANGLE => {
let value = annotations::expect_ident(&p.inner.value)?;
let value = kcl_value::UnitAngle::from_str(value, annotation.as_source_range())?;
let value = types::UnitAngle::from_str(value, annotation.as_source_range())?;
self.default_angle_units = value;
}
name => {
@ -351,6 +354,6 @@ impl MetaSettings {
}
}
Ok(())
Ok(updated_len)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,7 @@ pub fn lint_should_be_offset_plane(node: Node) -> Result<Vec<Discovered>> {
return Ok(vec![]);
};
if call.inner.callee.inner.name != "startSketchOn" {
if call.inner.callee.inner.name.name != "startSketchOn" {
return Ok(vec![]);
}

View File

@ -62,7 +62,7 @@ pub fn lint_call_expressions(exp: Node) -> Result<Vec<Discovered>> {
return Ok(vec![]);
};
match stdlib.get_either(&exp.callee.name) {
match stdlib.get_either(&exp.callee) {
FunctionKind::Core(func) => lint_too_many_args_std_lib_function(func, exp),
_ => Ok(vec![]),
}

View File

@ -6,8 +6,13 @@ use dhat::{HeapStats, Profiler};
use web_time::Instant;
const LOG_ENV_VAR: &str = "ZOO_LOG";
const FORCE_LOGGING: bool = false;
lazy_static::lazy_static! {
static ref ENABLED: bool = {
if FORCE_LOGGING {
return true;
}
let env_var = env::var(LOG_ENV_VAR);
let Ok(env_var) = env_var else {
return false;

View File

@ -105,16 +105,19 @@ impl Expr {
// TODO: LSP hover information for values/types. https://github.com/KittyCAD/modeling-app/issues/1126
Expr::None(_) => None,
Expr::Literal(_) => None,
Expr::Identifier(id) => {
if id.contains(pos) {
let name = id.name.clone();
Some(Hover::Variable {
ty: opts
.vars
Expr::Name(name) => {
if name.contains(pos) {
let ty = if let Some(name) = name.local_ident() {
opts.vars
.as_ref()
.and_then(|vars| vars.get(&name).and_then(Clone::clone)),
name,
range: id.as_source_range().to_lsp_range(code),
.and_then(|vars| vars.get(&**name).and_then(Clone::clone))
} else {
None
};
Some(Hover::Variable {
ty,
name: name.to_string(),
range: name.as_source_range().to_lsp_range(code),
})
} else {
None
@ -137,7 +140,7 @@ impl BinaryPart {
fn get_hover_value_for_position(&self, pos: usize, code: &str, opts: &HoverOpts) -> Option<Hover> {
match self {
BinaryPart::Literal(_literal) => None,
BinaryPart::Identifier(_identifier) => None,
BinaryPart::Name(_identifier) => None,
BinaryPart::BinaryExpression(binary_expression) => {
binary_expression.get_hover_value_for_position(pos, code, opts)
}
@ -163,7 +166,7 @@ impl CallExpression {
let callee_source_range: SourceRange = self.callee.clone().into();
if callee_source_range.contains(pos) {
return Some(Hover::Function {
name: self.callee.name.clone(),
name: self.callee.to_string(),
range: callee_source_range.to_lsp_range(code),
});
}
@ -173,7 +176,7 @@ impl CallExpression {
if source_range.contains(pos) {
return if opts.prefer_sig {
Some(Hover::Signature {
name: self.callee.name.clone(),
name: self.callee.to_string(),
parameter_index: index as u32,
range: source_range.to_lsp_range(code),
})
@ -192,7 +195,7 @@ impl CallExpressionKw {
let callee_source_range: SourceRange = self.callee.clone().into();
if callee_source_range.contains(pos) {
return Some(Hover::Function {
name: self.callee.name.clone(),
name: self.callee.to_string(),
range: callee_source_range.to_lsp_range(code),
});
}
@ -202,7 +205,7 @@ impl CallExpressionKw {
if source_range.contains(pos) {
return if opts.prefer_sig {
Some(Hover::Signature {
name: self.callee.name.clone(),
name: self.callee.to_string(),
parameter_index: index as u32,
range: source_range.to_lsp_range(code),
})
@ -215,7 +218,7 @@ impl CallExpressionKw {
if id.as_source_range().contains(pos) {
return Some(Hover::KwArg {
name: id.name.clone(),
callee_name: self.callee.name.clone(),
callee_name: self.callee.to_string(),
range: id.as_source_range().to_lsp_range(code),
});
}
@ -344,8 +347,8 @@ impl Node<Type> {
let range = self.as_source_range();
if range.contains(pos) {
match &self.inner {
Type::Array(t) | Type::Primitive(t) => {
let mut name = t.to_string();
Type::Array { ty, .. } | Type::Primitive(ty) => {
let mut name = ty.to_string();
if name.ends_with(')') {
name.truncate(name.find('(').unwrap());
}
@ -379,7 +382,7 @@ impl FunctionExpression {
if let Some(value) = self.body.get_expr_for_position(pos) {
let mut vars = opts.vars.clone().unwrap_or_default();
for arg in &self.params {
let ty = arg.type_.as_ref().map(|ty| ty.recast(&FormatOptions::default(), 0));
let ty = arg.type_.as_ref().map(|ty| ty.to_string());
vars.insert(arg.identifier.inner.name.clone(), ty);
}
return value.get_hover_value_for_position(

View File

@ -523,7 +523,7 @@ impl Backend {
None => token_type_index,
};
if self.stdlib_completions.contains_key(&call_expr.callee.name) {
if self.stdlib_completions.contains_key(&call_expr.callee.name.name) {
// This is a stdlib function.
return get_modifier(vec![SemanticTokenModifier::DEFAULT_LIBRARY]);
}

View File

@ -726,7 +726,7 @@ async fn test_kcl_lsp_completions_tags() {
uri: "file:///test.kcl".try_into().unwrap(),
language_id: "kcl".to_string(),
version: 1,
text: r#"part001 = startSketchOn('XY')
text: r#"part001 = startSketchOn(XY)
|> startProfileAt([11.19, 28.35], %)
|> line(end = [28.67, -13.25], tag = $here)
|> line(end = [-4.12, -22.81])
@ -1078,7 +1078,7 @@ async fn test_kcl_lsp_signature_help() {
content_changes: vec![tower_lsp::lsp_types::TextDocumentContentChangeEvent {
range: None,
range_length: None,
text: "startSketchOn('XY')".to_string(),
text: "startSketchOn(XY)".to_string(),
}],
})
.await;
@ -1123,7 +1123,7 @@ async fn test_kcl_lsp_semantic_tokens() {
uri: "file:///test.kcl".try_into().unwrap(),
language_id: "kcl".to_string(),
version: 1,
text: "startSketchOn('XY')".to_string(),
text: "startSketchOn(XY)".to_string(),
},
})
.await;
@ -1153,13 +1153,13 @@ async fn test_kcl_lsp_semantic_tokens() {
.get_semantic_token_type_index(&SemanticTokenType::FUNCTION)
.unwrap()
);
assert_eq!(semantic_tokens.data[1].length, 4);
assert_eq!(semantic_tokens.data[1].length, 2);
assert_eq!(semantic_tokens.data[1].delta_start, 14);
assert_eq!(semantic_tokens.data[1].delta_line, 0);
assert_eq!(
semantic_tokens.data[1].token_type,
server
.get_semantic_token_type_index(&SemanticTokenType::STRING)
.get_semantic_token_type_index(&SemanticTokenType::VARIABLE)
.unwrap()
);
} else {
@ -1216,7 +1216,7 @@ async fn test_kcl_lsp_semantic_tokens_with_modifiers() {
uri: "file:///test.kcl".try_into().unwrap(),
language_id: "kcl".to_string(),
version: 1,
text: r#"part001 = startSketchOn('XY')
text: r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20], tag = $seg01)
@ -1479,7 +1479,7 @@ async fn test_kcl_lsp_document_symbol() {
language_id: "kcl".to_string(),
version: 1,
text: r#"myVar = 1
startSketchOn('XY')"#
startSketchOn(XY)"#
.to_string(),
},
})
@ -1518,7 +1518,7 @@ async fn test_kcl_lsp_document_symbol_tag() {
uri: "file:///test.kcl".try_into().unwrap(),
language_id: "kcl".to_string(),
version: 1,
text: r#"part001 = startSketchOn('XY')
text: r#"part001 = startSketchOn(XY)
|> startProfileAt([11.19, 28.35], %)
|> line(end = [28.67, -13.25], tag = $here)
|> line(end = [-4.12, -22.81])
@ -1564,7 +1564,7 @@ async fn test_kcl_lsp_formatting() {
uri: "file:///test.kcl".try_into().unwrap(),
language_id: "kcl".to_string(),
version: 1,
text: r#"startSketchOn('XY')
text: r#"startSketchOn(XY)
|> startProfileAt([0,0], %)"#
.to_string(),
},
@ -1595,7 +1595,7 @@ async fn test_kcl_lsp_formatting() {
assert_eq!(formatting.len(), 1);
assert_eq!(
formatting[0].new_text,
r#"startSketchOn('XY')
r#"startSketchOn(XY)
|> startProfileAt([0, 0], %)"#
);
}
@ -1621,7 +1621,7 @@ thickness = 0.25
overHangLength = .4
// Sketch and revolve the inside bearing piece
insideRevolve = startSketchOn('XZ')
insideRevolve = startSketchOn(XZ)
|> startProfileAt([insideDia / 2, 0], %)
|> line(end = [0, thickness + sphereDia / 2])
|> line(end = [overHangLength, 0])
@ -1635,7 +1635,7 @@ insideRevolve = startSketchOn('XZ')
|> revolve({ axis: 'y' }, %)
// Sketch and revolve one of the balls and duplicate it using a circular pattern. (This is currently a workaround, we have a bug with rotating on a sketch that touches the rotation axis)
sphere = startSketchOn('XZ')
sphere = startSketchOn(XZ)
|> startProfileAt([
0.05 + insideDia / 2 + thickness,
0 - 0.05
@ -1657,7 +1657,7 @@ sphere = startSketchOn('XZ')
)
// Sketch and revolve the outside bearing
outsideRevolve = startSketchOn('XZ')
outsideRevolve = startSketchOn(XZ)
|> startProfileAt([
insideDia / 2 + thickness + sphereDia,
0
@ -1714,7 +1714,6 @@ outsideRevolve = startSketchOn('XZ')
r#"// Ball Bearing
// A ball bearing is a type of rolling-element bearing that uses balls to maintain the separation between the bearing races. The primary purpose of a ball bearing is to reduce rotational friction and support radial and axial loads.
// Define constants like ball diameter, inside diameter, overhange length, and thickness
sphereDia = 0.5
insideDia = 1
@ -1722,7 +1721,7 @@ thickness = 0.25
overHangLength = .4
// Sketch and revolve the inside bearing piece
insideRevolve = startSketchOn('XZ')
insideRevolve = startSketchOn(XZ)
|> startProfileAt([insideDia / 2, 0], %)
|> line(end = [0, thickness + sphereDia / 2])
|> line(end = [overHangLength, 0])
@ -1736,7 +1735,7 @@ insideRevolve = startSketchOn('XZ')
|> revolve({ axis = 'y' }, %)
// Sketch and revolve one of the balls and duplicate it using a circular pattern. (This is currently a workaround, we have a bug with rotating on a sketch that touches the rotation axis)
sphere = startSketchOn('XZ')
sphere = startSketchOn(XZ)
|> startProfileAt([
0.05 + insideDia / 2 + thickness,
0 - 0.05
@ -1758,7 +1757,7 @@ sphere = startSketchOn('XZ')
)
// Sketch and revolve the outside bearing
outsideRevolve = startSketchOn('XZ')
outsideRevolve = startSketchOn(XZ)
|> startProfileAt([
insideDia / 2 + thickness + sphereDia,
0
@ -1901,7 +1900,7 @@ async fn test_kcl_lsp_diagnostic_has_errors() {
assert_eq!(diagnostics.full_document_diagnostic_report.items.len(), 1);
assert_eq!(
diagnostics.full_document_diagnostic_report.items[0].message,
"lexical: found unknown token ';'"
"Unexpected token: ;"
);
} else {
panic!("Expected full diagnostics");
@ -2008,7 +2007,7 @@ async fn test_copilot_lsp_completions_raw() {
let completions = server
.get_completions(
"kcl".to_string(),
r#"bracket = startSketchOn('XY')
r#"bracket = startSketchOn(XY)
|> startProfileAt([0, 0], %)
"#
.to_string(),
@ -2027,7 +2026,7 @@ async fn test_copilot_lsp_completions_raw() {
let completions_hit_cache = server
.get_completions(
"kcl".to_string(),
r#"bracket = startSketchOn('XY')
r#"bracket = startSketchOn(XY)
|> startProfileAt([0, 0], %)
"#
.to_string(),
@ -2067,7 +2066,7 @@ async fn test_copilot_lsp_completions() {
path: "file:///test.copilot".to_string(),
position: crate::lsp::copilot::types::CopilotPosition { line: 3, character: 3 },
relative_path: "test.copilot".to_string(),
source: r#"bracket = startSketchOn('XY')
source: r#"bracket = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> close()
@ -2326,7 +2325,7 @@ async fn kcl_test_kcl_lsp_update_units() {
let server = kcl_lsp_server(true).await.unwrap();
let same_text = r#"fn cube = (pos, scale) => {
sg = startSketchOn('XY')
sg = startSketchOn(XY)
|> startProfileAt(pos, %)
|> line(end = [0, scale])
|> line(end = [scale, 0])
@ -2461,7 +2460,7 @@ async fn kcl_test_kcl_lsp_diagnostics_on_execution_error() {
uri: "file:///test.kcl".try_into().unwrap(),
language_id: "kcl".to_string(),
version: 1,
text: r#"part001 = startSketchOn('XY')
text: r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
@ -2482,7 +2481,7 @@ async fn kcl_test_kcl_lsp_diagnostics_on_execution_error() {
assert_diagnostic_count(server.diagnostics_map.get("file:///test.kcl").as_deref(), 1);
// Update the text.
let new_text = r#"part001 = startSketchOn('XY')
let new_text = r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
@ -2520,7 +2519,7 @@ async fn kcl_test_kcl_lsp_full_to_empty_file_updates_ast_and_memory() {
uri: "file:///test.kcl".try_into().unwrap(),
language_id: "kcl".to_string(),
version: 1,
text: r#"part001 = startSketchOn('XY')
text: r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
@ -2563,7 +2562,7 @@ async fn kcl_test_kcl_lsp_full_to_empty_file_updates_ast_and_memory() {
async fn kcl_test_kcl_lsp_code_unchanged_but_has_diagnostics_reexecute() {
let server = kcl_lsp_server(true).await.unwrap();
let code = r#"part001 = startSketchOn('XY')
let code = r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
@ -2649,7 +2648,7 @@ async fn kcl_test_kcl_lsp_code_unchanged_but_has_diagnostics_reexecute() {
async fn kcl_test_kcl_lsp_code_and_ast_unchanged_but_has_diagnostics_reexecute() {
let server = kcl_lsp_server(true).await.unwrap();
let code = r#"part001 = startSketchOn('XY')
let code = r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
@ -2724,7 +2723,7 @@ async fn kcl_test_kcl_lsp_code_and_ast_unchanged_but_has_diagnostics_reexecute()
async fn kcl_test_kcl_lsp_code_and_ast_units_unchanged_but_has_diagnostics_reexecute_on_unit_change() {
let server = kcl_lsp_server(true).await.unwrap();
let code = r#"part001 = startSketchOn('XY')
let code = r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
@ -2802,7 +2801,7 @@ async fn kcl_test_kcl_lsp_code_and_ast_units_unchanged_but_has_diagnostics_reexe
async fn kcl_test_kcl_lsp_code_and_ast_units_unchanged_but_has_memory_reexecute_on_unit_change() {
let server = kcl_lsp_server(true).await.unwrap();
let code = r#"part001 = startSketchOn('XY')
let code = r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
@ -2859,7 +2858,7 @@ async fn kcl_test_kcl_lsp_code_and_ast_units_unchanged_but_has_memory_reexecute_
async fn kcl_test_kcl_lsp_cant_execute_set() {
let server = kcl_lsp_server(true).await.unwrap();
let code = r#"part001 = startSketchOn('XY')
let code = r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
@ -2989,7 +2988,7 @@ async fn test_kcl_lsp_folding() {
uri: "file:///test.kcl".try_into().unwrap(),
language_id: "kcl".to_string(),
version: 1,
text: r#"startSketchOn('XY')
text: r#"startSketchOn(XY)
|> startProfileAt([0,0], %)"#
.to_string(),
},
@ -3014,12 +3013,12 @@ async fn test_kcl_lsp_folding() {
assert_eq!(
folding.first().unwrap().clone(),
tower_lsp::lsp_types::FoldingRange {
start_line: 19,
start_line: 17,
start_character: None,
end_line: 67,
end_line: 65,
end_character: None,
kind: Some(tower_lsp::lsp_types::FoldingRangeKind::Region),
collapsed_text: Some("startSketchOn('XY')".to_string())
collapsed_text: Some("startSketchOn(XY)".to_string())
}
);
}
@ -3028,7 +3027,7 @@ async fn test_kcl_lsp_folding() {
async fn kcl_test_kcl_lsp_code_with_parse_error_and_ast_unchanged_but_has_diagnostics_reparse() {
let server = kcl_lsp_server(false).await.unwrap();
let code = r#"part001 = startSketchOn('XY')
let code = r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
@ -3083,7 +3082,7 @@ async fn kcl_test_kcl_lsp_code_with_lint_and_ast_unchanged_but_has_diagnostics_r
let server = kcl_lsp_server(false).await.unwrap();
let code = r#"LINT = 1
part001 = startSketchOn('XY')
part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
@ -3137,7 +3136,7 @@ async fn kcl_test_kcl_lsp_code_with_lint_and_parse_error_and_ast_unchanged_but_h
let server = kcl_lsp_server(false).await.unwrap();
let code = r#"LINT = 1
part001 = startSketchOn('XY')
part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
@ -3192,7 +3191,7 @@ async fn kcl_test_kcl_lsp_code_lint_and_ast_unchanged_but_has_diagnostics_reexec
let server = kcl_lsp_server(true).await.unwrap();
let code = r#"LINT = 1
part001 = startSketchOn('XY')
part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20], tag = $seg01)
@ -3251,7 +3250,7 @@ async fn kcl_test_kcl_lsp_code_lint_reexecute_new_lint() {
let server = kcl_lsp_server(true).await.unwrap();
let code = r#"LINT = 1
part001 = startSketchOn('XY')
part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20], tag = $seg01)
@ -3290,7 +3289,7 @@ part001 = startSketchOn('XY')
content_changes: vec![tower_lsp::lsp_types::TextDocumentContentChangeEvent {
range: None,
range_length: None,
text: r#"part001 = startSketchOn('XY')
text: r#"part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20], tag = $seg01)
@ -3318,7 +3317,7 @@ async fn kcl_test_kcl_lsp_code_lint_reexecute_new_ast_error() {
let server = kcl_lsp_server(true).await.unwrap();
let code = r#"LINT = 1
part001 = startSketchOn('XY')
part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20], tag = $seg01)
@ -3357,7 +3356,7 @@ part001 = startSketchOn('XY')
content_changes: vec![tower_lsp::lsp_types::TextDocumentContentChangeEvent {
range: None,
range_length: None,
text: r#"part001 = startSketchOn('XY')
text: r#"part001 = startSketchOn(XY)
|> ^^^^startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20], tag = $seg01)
@ -3385,7 +3384,7 @@ async fn kcl_test_kcl_lsp_code_lint_reexecute_had_lint_new_parse_error() {
let server = kcl_lsp_server(true).await.unwrap();
let code = r#"LINT = 1
part001 = startSketchOn('XY')
part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
@ -3432,7 +3431,7 @@ part001 = startSketchOn('XY')
content_changes: vec![tower_lsp::lsp_types::TextDocumentContentChangeEvent {
range: None,
range_length: None,
text: r#"part001 = startSketchOn('XY')
text: r#"part001 = startSketchOn(XY)
|> ^^^^startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
@ -3468,7 +3467,7 @@ async fn kcl_test_kcl_lsp_code_lint_reexecute_had_lint_new_execution_error() {
let server = kcl_lsp_server(true).await.unwrap();
let code = r#"LINT = 1
part001 = startSketchOn('XY')
part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0])
|> line(end = [0, 20])
@ -3520,7 +3519,7 @@ part001 = startSketchOn('XY')
range: None,
range_length: None,
text: r#"LINT = 1
part001 = startSketchOn('XY')
part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line(end = [20, 0], tag = $seg01)
|> line(end = [0, 20], tag = $seg01)

View File

@ -87,6 +87,7 @@ pub(crate) fn read_std(mod_name: &str) -> Option<&'static str> {
match mod_name {
"prelude" => Some(include_str!("../std/prelude.kcl")),
"math" => Some(include_str!("../std/math.kcl")),
"sketch" => Some(include_str!("../std/sketch.kcl")),
_ => None,
}
}

View File

@ -4,7 +4,7 @@ use crate::parsing::ast::types::{
Annotation, ArrayExpression, ArrayRangeExpression, Ascription, BinaryExpression, BinaryPart, BodyItem,
CallExpression, CallExpressionKw, DefaultParamVal, ElseIf, Expr, ExpressionStatement, FunctionExpression,
Identifier, IfExpression, ImportItem, ImportSelector, ImportStatement, ItemVisibility, KclNone, LabelledExpression,
Literal, LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, ObjectExpression, ObjectProperty,
Literal, LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, Name, ObjectExpression, ObjectProperty,
Parameter, PipeExpression, PipeSubstitution, PrimitiveType, Program, ReturnStatement, TagDeclarator, Type,
TypeDeclaration, UnaryExpression, VariableDeclaration, VariableDeclarator, VariableKind,
};
@ -128,7 +128,7 @@ impl Expr {
pub fn compute_digest(&mut self) -> Digest {
match self {
Expr::Literal(lit) => lit.compute_digest(),
Expr::Identifier(id) => id.compute_digest(),
Expr::Name(id) => id.compute_digest(),
Expr::TagDeclarator(tag) => tag.compute_digest(),
Expr::BinaryExpression(be) => be.compute_digest(),
Expr::FunctionExpression(fe) => fe.compute_digest(),
@ -157,7 +157,7 @@ impl BinaryPart {
pub fn compute_digest(&mut self) -> Digest {
match self {
BinaryPart::Literal(lit) => lit.compute_digest(),
BinaryPart::Identifier(id) => id.compute_digest(),
BinaryPart::Name(id) => id.compute_digest(),
BinaryPart::BinaryExpression(be) => be.compute_digest(),
BinaryPart::CallExpression(ce) => ce.compute_digest(),
BinaryPart::CallExpressionKw(ce) => ce.compute_digest(),
@ -194,9 +194,21 @@ impl Type {
hasher.update(b"FnArgType::Primitive");
hasher.update(prim.compute_digest())
}
Type::Array(prim) => {
Type::Array { ty, len } => {
hasher.update(b"FnArgType::Array");
hasher.update(prim.compute_digest())
hasher.update(ty.compute_digest());
match len {
crate::execution::types::ArrayLen::None => {}
crate::execution::types::ArrayLen::NonEmpty => hasher.update(usize::MAX.to_ne_bytes()),
crate::execution::types::ArrayLen::Known(n) => hasher.update(n.to_ne_bytes()),
}
}
Type::Union { tys } => {
hasher.update(b"FnArgType::Union");
hasher.update(tys.len().to_ne_bytes());
for t in tys.iter_mut() {
hasher.update(t.compute_digest());
}
}
Type::Object { properties } => {
hasher.update(b"FnArgType::Object");
@ -300,6 +312,9 @@ impl TypeDeclaration {
hasher.update(a.compute_digest());
}
}
if let Some(alias) = &mut slf.alias {
hasher.update(alias.compute_digest());
}
});
}
@ -362,6 +377,17 @@ impl Identifier {
});
}
impl Name {
compute_digest!(|slf, hasher| {
hasher.update(slf.name.compute_digest());
for p in &mut slf.path {
hasher.update(p.compute_digest());
}
if slf.abs_path {
hasher.update([1]);
}
});
}
impl TagDeclarator {
compute_digest!(|slf, hasher| {
let name = slf.name.as_bytes();

View File

@ -23,7 +23,7 @@ impl Expr {
pub fn module_id(&self) -> ModuleId {
match self {
Expr::Literal(literal) => literal.module_id,
Expr::Identifier(identifier) => identifier.module_id,
Expr::Name(identifier) => identifier.module_id,
Expr::TagDeclarator(tag) => tag.module_id,
Expr::BinaryExpression(binary_expression) => binary_expression.module_id,
Expr::FunctionExpression(function_expression) => function_expression.module_id,
@ -48,7 +48,7 @@ impl BinaryPart {
pub fn module_id(&self) -> ModuleId {
match self {
BinaryPart::Literal(literal) => literal.module_id,
BinaryPart::Identifier(identifier) => identifier.module_id,
BinaryPart::Name(identifier) => identifier.module_id,
BinaryPart::BinaryExpression(binary_expression) => binary_expression.module_id,
BinaryPart::CallExpression(call_expression) => call_expression.module_id,
BinaryPart::CallExpressionKw(call_expression) => call_expression.module_id,

View File

@ -25,6 +25,13 @@ impl LiteralValue {
suffix: NumericSuffix::None,
}
}
pub fn string_value(&self) -> Option<&str> {
match self {
Self::String(s) => Some(s),
_ => None,
}
}
}
impl fmt::Display for LiteralValue {

View File

@ -25,7 +25,7 @@ pub use crate::parsing::ast::types::{
use crate::{
docs::StdLibFn,
errors::KclError,
execution::{annotations, KclValue, Metadata, TagIdentifier},
execution::{annotations, types::ArrayLen, KclValue, Metadata, TagIdentifier},
parsing::{ast::digest::Digest, token::NumericSuffix, PIPE_OPERATOR},
source_range::SourceRange,
ModuleId,
@ -35,6 +35,7 @@ mod condition;
mod literal_value;
mod none;
#[derive(Debug)]
pub enum Definition<'a> {
Variable(&'a VariableDeclarator),
Import(NodeRef<'a, ImportStatement>),
@ -53,6 +54,12 @@ pub struct Node<T> {
pub module_id: ModuleId,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub outer_attrs: NodeList<Annotation>,
// Some comments are kept here, some are kept in NonCodeMeta, and some are ignored. See how each
// node is parsed to check for certain. In any case, only comments which are strongly associated
// with an item are kept here.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub pre_comments: Vec<String>,
pub comment_start: usize,
}
impl<T: JsonSchema> schemars::JsonSchema for Node<T> {
@ -85,6 +92,20 @@ impl<T> Node<T> {
end,
module_id,
outer_attrs: Vec::new(),
pre_comments: Vec::new(),
comment_start: start,
}
}
pub fn new_node(start: usize, end: usize, module_id: ModuleId, inner: T) -> Self {
Self {
inner,
start,
end,
module_id,
outer_attrs: Vec::new(),
pre_comments: Vec::new(),
comment_start: start,
}
}
@ -95,6 +116,8 @@ impl<T> Node<T> {
end: 0,
module_id: ModuleId::default(),
outer_attrs: Vec::new(),
pre_comments: Vec::new(),
comment_start: 0,
}
}
@ -105,6 +128,8 @@ impl<T> Node<T> {
end,
module_id,
outer_attrs: Vec::new(),
pre_comments: Vec::new(),
comment_start: start,
})
}
@ -126,13 +151,32 @@ impl<T> Node<T> {
self.start <= pos && pos <= self.end
}
pub fn map<U>(self, f: fn(T) -> U) -> Node<U> {
pub fn map<U>(self, f: impl Fn(T) -> U) -> Node<U> {
Node {
inner: f(self.inner),
start: self.start,
end: self.end,
module_id: self.module_id,
outer_attrs: self.outer_attrs,
pre_comments: self.pre_comments,
comment_start: self.comment_start,
}
}
pub fn set_comments(&mut self, comments: Vec<String>, start: usize) {
self.pre_comments = comments;
self.comment_start = start;
}
pub fn map_ref<'a, U: 'a>(&'a self, f: fn(&'a T) -> U) -> Node<U> {
Node {
inner: f(&self.inner),
start: self.start,
end: self.end,
module_id: self.module_id,
outer_attrs: self.outer_attrs.clone(),
pre_comments: self.pre_comments.clone(),
comment_start: self.start,
}
}
}
@ -373,6 +417,26 @@ impl Program {
if self.non_code_meta.in_comment(pos) {
return true;
}
for item in &self.body {
let r = item.comment_range();
eprintln!("item {r:?}");
if pos >= r.0 && pos < r.1 {
return true;
}
if pos < r.0 {
break;
}
}
for n in &self.inner_attrs {
if pos >= n.comment_start && pos < n.start {
return true;
}
if pos < n.comment_start {
break;
}
}
let item = self.get_body_item_for_position(pos);
// Recurse over the item.
@ -660,6 +724,36 @@ impl BodyItem {
BodyItem::ReturnStatement(node) => &mut node.outer_attrs,
}
}
pub(crate) fn set_comments(&mut self, comments: Vec<String>, start: usize) {
match self {
BodyItem::ImportStatement(node) => node.set_comments(comments, start),
BodyItem::ExpressionStatement(node) => node.set_comments(comments, start),
BodyItem::VariableDeclaration(node) => node.set_comments(comments, start),
BodyItem::TypeDeclaration(node) => node.set_comments(comments, start),
BodyItem::ReturnStatement(node) => node.set_comments(comments, start),
}
}
pub(crate) fn get_comments(&self) -> &[String] {
match self {
BodyItem::ImportStatement(node) => &node.pre_comments,
BodyItem::ExpressionStatement(node) => &node.pre_comments,
BodyItem::VariableDeclaration(node) => &node.pre_comments,
BodyItem::TypeDeclaration(node) => &node.pre_comments,
BodyItem::ReturnStatement(node) => &node.pre_comments,
}
}
pub(crate) fn comment_range(&self) -> (usize, usize) {
match self {
BodyItem::ImportStatement(node) => (node.comment_start, node.start),
BodyItem::ExpressionStatement(node) => (node.comment_start, node.start),
BodyItem::VariableDeclaration(node) => (node.comment_start, node.start),
BodyItem::TypeDeclaration(node) => (node.comment_start, node.start),
BodyItem::ReturnStatement(node) => (node.comment_start, node.start),
}
}
}
impl From<BodyItem> for SourceRange {
@ -681,7 +775,7 @@ impl From<&BodyItem> for SourceRange {
#[allow(clippy::large_enum_variant)]
pub enum Expr {
Literal(BoxNode<Literal>),
Identifier(BoxNode<Identifier>),
Name(BoxNode<Name>),
TagDeclarator(BoxNode<TagDeclarator>),
BinaryExpression(BoxNode<BinaryExpression>),
FunctionExpression(BoxNode<FunctionExpression>),
@ -733,7 +827,7 @@ impl Expr {
Expr::FunctionExpression(_func_exp) => None,
Expr::CallExpression(_call_exp) => None,
Expr::CallExpressionKw(_call_exp) => None,
Expr::Identifier(_ident) => None,
Expr::Name(_ident) => None,
Expr::TagDeclarator(_tag) => None,
Expr::PipeExpression(pipe_exp) => Some(&pipe_exp.non_code_meta),
Expr::UnaryExpression(_unary_exp) => None,
@ -761,7 +855,7 @@ impl Expr {
Expr::FunctionExpression(ref mut func_exp) => func_exp.replace_value(source_range, new_value),
Expr::CallExpression(ref mut call_exp) => call_exp.replace_value(source_range, new_value),
Expr::CallExpressionKw(ref mut call_exp) => call_exp.replace_value(source_range, new_value),
Expr::Identifier(_) => {}
Expr::Name(_) => {}
Expr::TagDeclarator(_) => {}
Expr::PipeExpression(ref mut pipe_exp) => pipe_exp.replace_value(source_range, new_value),
Expr::UnaryExpression(ref mut unary_exp) => unary_exp.replace_value(source_range, new_value),
@ -776,7 +870,7 @@ impl Expr {
pub fn start(&self) -> usize {
match self {
Expr::Literal(literal) => literal.start,
Expr::Identifier(identifier) => identifier.start,
Expr::Name(identifier) => identifier.start,
Expr::TagDeclarator(tag) => tag.start,
Expr::BinaryExpression(binary_expression) => binary_expression.start,
Expr::FunctionExpression(function_expression) => function_expression.start,
@ -799,7 +893,7 @@ impl Expr {
pub fn end(&self) -> usize {
match self {
Expr::Literal(literal) => literal.end,
Expr::Identifier(identifier) => identifier.end,
Expr::Name(identifier) => identifier.end,
Expr::TagDeclarator(tag) => tag.end,
Expr::BinaryExpression(binary_expression) => binary_expression.end,
Expr::FunctionExpression(function_expression) => function_expression.end,
@ -823,7 +917,7 @@ impl Expr {
fn rename_identifiers(&mut self, old_name: &str, new_name: &str) {
match self {
Expr::Literal(_literal) => {}
Expr::Identifier(ref mut identifier) => identifier.rename(old_name, new_name),
Expr::Name(ref mut identifier) => identifier.rename(old_name, new_name),
Expr::TagDeclarator(ref mut tag) => tag.rename(old_name, new_name),
Expr::BinaryExpression(ref mut binary_expression) => {
binary_expression.rename_identifiers(old_name, new_name)
@ -853,7 +947,7 @@ impl Expr {
pub fn get_constraint_level(&self) -> ConstraintLevel {
match self {
Expr::Literal(literal) => literal.get_constraint_level(),
Expr::Identifier(identifier) => identifier.get_constraint_level(),
Expr::Name(identifier) => identifier.get_constraint_level(),
Expr::TagDeclarator(tag) => tag.get_constraint_level(),
Expr::BinaryExpression(binary_expression) => binary_expression.get_constraint_level(),
@ -886,35 +980,6 @@ impl Expr {
}
}
/// Describe this expression's type for a human, for typechecking.
/// This is a best-effort function, it's OK to give a shitty string here (but we should work on improving it)
pub fn human_friendly_type(&self) -> &'static str {
match self {
Expr::Literal(node) => match node.inner.value {
LiteralValue::Number { .. } => "number",
LiteralValue::String(_) => "string (text)",
LiteralValue::Bool(_) => "boolean (true/false value)",
},
Expr::Identifier(_) => "named constant",
Expr::TagDeclarator(_) => "tag declarator",
Expr::BinaryExpression(_) => "expression",
Expr::FunctionExpression(_) => "function definition",
Expr::CallExpression(_) => "function call",
Expr::CallExpressionKw(_) => "function call",
Expr::PipeExpression(_) => "pipeline of function calls",
Expr::PipeSubstitution(_) => "left-hand side of a |> pipeline",
Expr::ArrayExpression(_) => "array",
Expr::ArrayRangeExpression(_) => "array",
Expr::ObjectExpression(_) => "object",
Expr::MemberExpression(_) => "property of an object/array",
Expr::UnaryExpression(_) => "expression",
Expr::IfExpression(_) => "if expression",
Expr::LabelledExpression(_) => "labelled expression",
Expr::AscribedExpression(_) => "type-ascribed expression",
Expr::None(_) => "none",
}
}
pub fn literal_bool(&self) -> Option<bool> {
match self {
Expr::Literal(lit) => match lit.value {
@ -947,7 +1012,7 @@ impl Expr {
pub fn ident_name(&self) -> Option<&str> {
match self {
Expr::Identifier(ident) => Some(&ident.name),
Expr::Name(ident) => Some(&ident.name.name),
_ => None,
}
}
@ -1021,7 +1086,7 @@ impl Ascription {
#[serde(tag = "type")]
pub enum BinaryPart {
Literal(BoxNode<Literal>),
Identifier(BoxNode<Identifier>),
Name(BoxNode<Name>),
BinaryExpression(BoxNode<BinaryExpression>),
CallExpression(BoxNode<CallExpression>),
CallExpressionKw(BoxNode<CallExpressionKw>),
@ -1047,7 +1112,7 @@ impl BinaryPart {
pub fn get_constraint_level(&self) -> ConstraintLevel {
match self {
BinaryPart::Literal(literal) => literal.get_constraint_level(),
BinaryPart::Identifier(identifier) => identifier.get_constraint_level(),
BinaryPart::Name(identifier) => identifier.get_constraint_level(),
BinaryPart::BinaryExpression(binary_expression) => binary_expression.get_constraint_level(),
BinaryPart::CallExpression(call_expression) => call_expression.get_constraint_level(),
BinaryPart::CallExpressionKw(call_expression) => call_expression.get_constraint_level(),
@ -1060,7 +1125,7 @@ impl BinaryPart {
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Expr) {
match self {
BinaryPart::Literal(_) => {}
BinaryPart::Identifier(_) => {}
BinaryPart::Name(_) => {}
BinaryPart::BinaryExpression(ref mut binary_expression) => {
binary_expression.replace_value(source_range, new_value)
}
@ -1081,7 +1146,7 @@ impl BinaryPart {
pub fn start(&self) -> usize {
match self {
BinaryPart::Literal(literal) => literal.start,
BinaryPart::Identifier(identifier) => identifier.start,
BinaryPart::Name(identifier) => identifier.start,
BinaryPart::BinaryExpression(binary_expression) => binary_expression.start,
BinaryPart::CallExpression(call_expression) => call_expression.start,
BinaryPart::CallExpressionKw(call_expression) => call_expression.start,
@ -1094,7 +1159,7 @@ impl BinaryPart {
pub fn end(&self) -> usize {
match self {
BinaryPart::Literal(literal) => literal.end,
BinaryPart::Identifier(identifier) => identifier.end,
BinaryPart::Name(identifier) => identifier.end,
BinaryPart::BinaryExpression(binary_expression) => binary_expression.end,
BinaryPart::CallExpression(call_expression) => call_expression.end,
BinaryPart::CallExpressionKw(call_expression) => call_expression.end,
@ -1108,7 +1173,7 @@ impl BinaryPart {
fn rename_identifiers(&mut self, old_name: &str, new_name: &str) {
match self {
BinaryPart::Literal(_literal) => {}
BinaryPart::Identifier(ref mut identifier) => identifier.rename(old_name, new_name),
BinaryPart::Name(ref mut identifier) => identifier.rename(old_name, new_name),
BinaryPart::BinaryExpression(ref mut binary_expression) => {
binary_expression.rename_identifiers(old_name, new_name)
}
@ -1171,6 +1236,23 @@ pub enum CommentStyle {
Block,
}
impl CommentStyle {
pub fn render_comment(&self, comment: &str) -> String {
match self {
CommentStyle::Line => {
let comment = comment.trim();
let mut result = "//".to_owned();
if !comment.is_empty() && !comment.starts_with('/') {
result.push(' ');
}
result.push_str(comment);
result
}
CommentStyle::Block => format!("/* {comment} */"),
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type", rename_all = "camelCase")]
@ -1186,9 +1268,9 @@ pub enum NonCodeValue {
},
/// A block comment.
/// An example of this is the following:
/// ```python,no_run
/// ```no_run
/// /* This is a
/// block comment */
/// block comment */
/// 1 + 1
/// ```
/// Now this is important. The block comment is attached to the next line.
@ -1320,13 +1402,13 @@ impl Annotation {
pub fn new_from_meta_settings(settings: &crate::execution::MetaSettings) -> Annotation {
let mut properties: Vec<Node<ObjectProperty>> = vec![ObjectProperty::new(
Identifier::new(annotations::SETTINGS_UNIT_LENGTH),
Expr::Identifier(Box::new(Identifier::new(&settings.default_length_units.to_string()))),
Expr::Name(Box::new(Name::new(&settings.default_length_units.to_string()))),
)];
if settings.default_angle_units != Default::default() {
properties.push(ObjectProperty::new(
Identifier::new(annotations::SETTINGS_UNIT_ANGLE),
Expr::Identifier(Box::new(Identifier::new(&settings.default_angle_units.to_string()))),
Expr::Name(Box::new(Name::new(&settings.default_angle_units.to_string()))),
));
}
Annotation {
@ -1591,7 +1673,7 @@ pub struct ExpressionStatement {
#[ts(export)]
#[serde(tag = "type")]
pub struct CallExpression {
pub callee: Node<Identifier>,
pub callee: Node<Name>,
pub arguments: Vec<Expr>,
#[serde(default, skip_serializing_if = "Option::is_none")]
@ -1603,7 +1685,7 @@ pub struct CallExpression {
#[ts(export)]
#[serde(rename_all = "camelCase", tag = "type")]
pub struct CallExpressionKw {
pub callee: Node<Identifier>,
pub callee: Node<Name>,
pub unlabeled: Option<Expr>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub arguments: Vec<LabeledArg>,
@ -1677,7 +1759,7 @@ impl Node<CallExpressionKw> {
impl CallExpression {
pub fn new(name: &str, arguments: Vec<Expr>) -> Result<Node<Self>, KclError> {
Ok(Node::no_src(Self {
callee: Identifier::new(name),
callee: Name::new(name),
arguments,
digest: None,
}))
@ -1709,7 +1791,7 @@ impl CallExpression {
impl CallExpressionKw {
pub fn new(name: &str, unlabeled: Option<Expr>, arguments: Vec<LabeledArg>) -> Result<Node<Self>, KclError> {
Ok(Node::no_src(Self {
callee: Identifier::new(name),
callee: Name::new(name),
unlabeled,
arguments,
digest: None,
@ -1797,6 +1879,7 @@ pub struct TypeDeclaration {
pub args: Option<NodeList<Identifier>>,
#[serde(default, skip_serializing_if = "ItemVisibility::is_default")]
pub visibility: ItemVisibility,
pub alias: Option<Node<Type>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
@ -2119,6 +2202,99 @@ impl Identifier {
}
}
/// A qualified name, e.g., `foo`, `bar::foo`, or `::bar::foo`.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type")]
pub struct Name {
pub name: Node<Identifier>,
// The qualifying parts of the name.
pub path: NodeList<Identifier>,
// The path starts with `::`.
pub abs_path: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
pub digest: Option<Digest>,
}
impl Node<Name> {
pub fn get_constraint_level(&self) -> ConstraintLevel {
match &*self.name.name {
"XY" | "XZ" | "YZ" => ConstraintLevel::None {
source_ranges: vec![self.into()],
},
_ => ConstraintLevel::Full {
source_ranges: vec![self.into()],
},
}
}
}
impl Name {
pub fn new(name: &str) -> Node<Self> {
Node::no_src(Name {
name: Node::no_src(Identifier {
name: name.to_string(),
digest: None,
}),
path: Vec::new(),
abs_path: false,
digest: None,
})
}
pub fn local_ident(&self) -> Option<Node<&str>> {
if self.path.is_empty() && !self.abs_path {
Some(self.name.map_ref(|n| &n.name))
} else {
None
}
}
/// Rename all identifiers that have the old name to the new given name.
fn rename(&mut self, old_name: &str, new_name: &str) {
if let Some(n) = self.local_ident() {
if n.inner == old_name {
self.name.name = new_name.to_owned();
}
}
}
}
impl From<Node<Identifier>> for Node<Name> {
fn from(value: Node<Identifier>) -> Self {
let start = value.start;
let end = value.end;
let mod_id = value.module_id;
Node::new(
Name {
name: value,
path: Vec::new(),
abs_path: false,
digest: None,
},
start,
end,
mod_id,
)
}
}
impl fmt::Display for Name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.abs_path {
f.write_str("::")?;
}
for p in &self.path {
f.write_str(&p.name)?;
f.write_str("::")?;
}
f.write_str(&self.name.name)
}
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Eq)]
#[ts(export)]
#[serde(tag = "type")]
@ -2926,7 +3102,14 @@ pub enum Type {
/// A primitive type.
Primitive(PrimitiveType),
// An array of a primitive type.
Array(PrimitiveType),
Array {
ty: PrimitiveType,
len: ArrayLen,
},
// Union/enum types
Union {
tys: NodeList<PrimitiveType>,
},
// An object type.
Object {
properties: Vec<Parameter>,
@ -2937,7 +3120,22 @@ impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Type::Primitive(primitive_type) => primitive_type.fmt(f),
Type::Array(primitive_type) => write!(f, "[{primitive_type}]"),
Type::Array { ty, len } => {
write!(f, "[{ty}")?;
match len {
ArrayLen::None => {}
ArrayLen::NonEmpty => write!(f, "; 1+")?,
ArrayLen::Known(n) => write!(f, "; {n}")?,
}
write!(f, "]")
}
Type::Union { tys } => {
write!(
f,
"{}",
tys.iter().map(|t| t.to_string()).collect::<Vec<_>>().join(" | ")
)
}
Type::Object { properties } => {
write!(f, "{{")?;
let mut first = true;
@ -3363,11 +3561,11 @@ mod tests {
#[test]
fn test_get_lsp_folding_ranges() {
let code = r#"const part001 = startSketchOn('XY')
let code = r#"const part001 = startSketchOn(XY)
|> startProfileAt([0.0000000000, 5.0000000000], %)
|> line([0.4900857016, -0.0240763666], %)
startSketchOn('XY')
startSketchOn(XY)
|> startProfileAt([0.0000000000, 5.0000000000], %)
|> line([0.4900857016, -0.0240763666], %)
@ -3386,20 +3584,17 @@ ghi("things")
let program = crate::parsing::top_level_parse(code).unwrap();
let folding_ranges = program.get_lsp_folding_ranges();
assert_eq!(folding_ranges.len(), 3);
assert_eq!(folding_ranges[0].start_line, 29);
assert_eq!(folding_ranges[0].end_line, 134);
assert_eq!(folding_ranges[0].start_line, 27);
assert_eq!(folding_ranges[0].end_line, 132);
assert_eq!(
folding_ranges[0].collapsed_text,
Some("part001 = startSketchOn('XY')".to_string())
Some("part001 = startSketchOn(XY)".to_string())
);
assert_eq!(folding_ranges[1].start_line, 155);
assert_eq!(folding_ranges[1].end_line, 254);
assert_eq!(
folding_ranges[1].collapsed_text,
Some("startSketchOn('XY')".to_string())
);
assert_eq!(folding_ranges[2].start_line, 384);
assert_eq!(folding_ranges[2].end_line, 403);
assert_eq!(folding_ranges[1].start_line, 151);
assert_eq!(folding_ranges[1].end_line, 250);
assert_eq!(folding_ranges[1].collapsed_text, Some("startSketchOn(XY)".to_string()));
assert_eq!(folding_ranges[2].start_line, 380);
assert_eq!(folding_ranges[2].end_line, 399);
assert_eq!(folding_ranges[2].collapsed_text, Some("fn ghi(x) {".to_string()));
}
@ -3526,11 +3721,17 @@ const cylinder = startSketchOn('-XZ')
assert_eq!(params.len(), 3);
assert_eq!(
params[0].type_.as_ref().unwrap().inner,
Type::Array(PrimitiveType::Number(NumericSuffix::None))
Type::Array {
ty: PrimitiveType::Number(NumericSuffix::None),
len: ArrayLen::None
}
);
assert_eq!(
params[1].type_.as_ref().unwrap().inner,
Type::Array(PrimitiveType::String)
Type::Array {
ty: PrimitiveType::String,
len: ArrayLen::None
}
);
assert_eq!(
params[2].type_.as_ref().unwrap().inner,
@ -3558,7 +3759,10 @@ const cylinder = startSketchOn('-XZ')
assert_eq!(params.len(), 3);
assert_eq!(
params[0].type_.as_ref().unwrap().inner,
Type::Array(PrimitiveType::Number(NumericSuffix::None))
Type::Array {
ty: PrimitiveType::Number(NumericSuffix::None),
len: ArrayLen::None
}
);
assert_eq!(
params[1].type_.as_ref().unwrap().inner,
@ -3594,7 +3798,15 @@ const cylinder = startSketchOn('-XZ')
56,
module_id,
),
type_: Some(Node::new(Type::Array(PrimitiveType::String), 59, 65, module_id)),
type_: Some(Node::new(
Type::Array {
ty: PrimitiveType::String,
len: ArrayLen::None
},
59,
65,
module_id
)),
default_value: None,
labeled: true,
digest: None
@ -3675,7 +3887,15 @@ const cylinder = startSketchOn('-XZ')
34,
module_id,
),
type_: Some(Node::new(Type::Array(PrimitiveType::String), 37, 43, module_id)),
type_: Some(Node::new(
Type::Array {
ty: PrimitiveType::String,
len: ArrayLen::None
},
37,
43,
module_id
)),
default_value: None,
labeled: true,
digest: None
@ -3840,7 +4060,7 @@ const cylinder = startSketchOn('-XZ')
async fn test_parse_get_meta_settings_inch() {
let some_program_string = r#"@settings(defaultLengthUnit = inch)
startSketchOn('XY')"#;
startSketchOn(XY)"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let result = program.meta_settings().unwrap();
assert!(result.is_some());
@ -3848,7 +4068,7 @@ startSketchOn('XY')"#;
assert_eq!(
meta_settings.default_length_units,
crate::execution::kcl_value::UnitLen::Inches
crate::execution::types::UnitLen::Inches
);
}
@ -3856,7 +4076,7 @@ startSketchOn('XY')"#;
async fn test_parse_get_meta_settings_inch_to_mm() {
let some_program_string = r#"@settings(defaultLengthUnit = inch)
startSketchOn('XY')"#;
startSketchOn(XY)"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let result = program.meta_settings().unwrap();
assert!(result.is_some());
@ -3864,13 +4084,13 @@ startSketchOn('XY')"#;
assert_eq!(
meta_settings.default_length_units,
crate::execution::kcl_value::UnitLen::Inches
crate::execution::types::UnitLen::Inches
);
// Edit the ast.
let new_program = program
.change_meta_settings(crate::execution::MetaSettings {
default_length_units: crate::execution::kcl_value::UnitLen::Mm,
default_length_units: crate::execution::types::UnitLen::Mm,
..Default::default()
})
.unwrap();
@ -3879,10 +4099,7 @@ startSketchOn('XY')"#;
assert!(result.is_some());
let meta_settings = result.unwrap();
assert_eq!(
meta_settings.default_length_units,
crate::execution::kcl_value::UnitLen::Mm
);
assert_eq!(meta_settings.default_length_units, crate::execution::types::UnitLen::Mm);
let formatted = new_program.recast(&Default::default(), 0);
@ -3890,15 +4107,14 @@ startSketchOn('XY')"#;
formatted,
r#"@settings(defaultLengthUnit = mm)
startSketchOn('XY')
startSketchOn(XY)
"#
);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_parse_get_meta_settings_nothing_to_mm() {
let some_program_string = r#"startSketchOn('XY')"#;
let some_program_string = r#"startSketchOn(XY)"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let result = program.meta_settings().unwrap();
assert!(result.is_none());
@ -3906,7 +4122,7 @@ startSketchOn('XY')
// Edit the ast.
let new_program = program
.change_meta_settings(crate::execution::MetaSettings {
default_length_units: crate::execution::kcl_value::UnitLen::Mm,
default_length_units: crate::execution::types::UnitLen::Mm,
..Default::default()
})
.unwrap();
@ -3915,17 +4131,15 @@ startSketchOn('XY')
assert!(result.is_some());
let meta_settings = result.unwrap();
assert_eq!(
meta_settings.default_length_units,
crate::execution::kcl_value::UnitLen::Mm
);
assert_eq!(meta_settings.default_length_units, crate::execution::types::UnitLen::Mm);
let formatted = new_program.recast(&Default::default(), 0);
assert_eq!(
formatted,
r#"@settings(defaultLengthUnit = mm)
startSketchOn('XY')
startSketchOn(XY)
"#
);
}

View File

@ -60,11 +60,8 @@ pub fn parse_tokens(mut tokens: TokenStream) -> ParseResult {
return Node::<Program>::default().into();
}
// Check all the tokens are whitespace or comments.
if tokens
.iter()
.all(|t| t.token_type.is_whitespace() || t.token_type.is_comment())
{
// Check all the tokens are whitespace.
if tokens.iter().all(|t| t.token_type.is_whitespace()) {
return Node::<Program>::default().into();
}
@ -146,6 +143,32 @@ impl From<KclError> for ParseResult {
}
}
const STR_DEPRECATIONS: [(&str, &str); 6] = [
("XY", "XY"),
("XZ", "XZ"),
("YZ", "YZ"),
("-XY", "-XY"),
("-XZ", "-XZ"),
("-YZ", "-YZ"),
];
const FN_DEPRECATIONS: [(&str, &str); 3] = [("pi", "PI"), ("e", "E"), ("tau", "TAU")];
const CONST_DEPRECATIONS: [(&str, &str); 0] = [];
#[derive(Clone, Copy)]
pub enum DeprecationKind {
String,
Function,
Const,
}
pub fn deprecation(s: &str, kind: DeprecationKind) -> Option<&'static str> {
match kind {
DeprecationKind::String => STR_DEPRECATIONS.iter().find_map(|(a, b)| (*a == s).then_some(*b)),
DeprecationKind::Function => FN_DEPRECATIONS.iter().find_map(|(a, b)| (*a == s).then_some(*b)),
DeprecationKind::Const => CONST_DEPRECATIONS.iter().find_map(|(a, b)| (*a == s).then_some(*b)),
}
}
#[cfg(test)]
mod tests {
macro_rules! parse_and_lex {

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
@ -14,7 +14,8 @@ expression: actual
},
"raw": "1",
"start": 0,
"end": 1
"end": 1,
"commentStart": 0
},
"right": {
"type": "Literal",
@ -25,8 +26,10 @@ expression: actual
},
"raw": "2",
"start": 4,
"end": 5
"end": 5,
"commentStart": 4
},
"start": 0,
"end": 5
"end": 5,
"commentStart": 0
}

View File

@ -1,5 +1,5 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
@ -14,7 +14,8 @@ expression: actual
},
"raw": "1",
"start": 0,
"end": 1
"end": 1,
"commentStart": 0
},
"right": {
"type": "Literal",
@ -25,8 +26,10 @@ expression: actual
},
"raw": "2",
"start": 2,
"end": 3
"end": 3,
"commentStart": 2
},
"start": 0,
"end": 3
"end": 3,
"commentStart": 0
}

View File

@ -1,5 +1,5 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
@ -14,7 +14,8 @@ expression: actual
},
"raw": "1",
"start": 0,
"end": 1
"end": 1,
"commentStart": 0
},
"right": {
"type": "Literal",
@ -25,8 +26,10 @@ expression: actual
},
"raw": "2",
"start": 3,
"end": 4
"end": 4,
"commentStart": 3
},
"start": 0,
"end": 4
"end": 4,
"commentStart": 0
}

View File

@ -1,5 +1,5 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
@ -14,7 +14,8 @@ expression: actual
},
"raw": "1",
"start": 0,
"end": 1
"end": 1,
"commentStart": 0
},
"right": {
"type": "BinaryExpression",
@ -29,7 +30,8 @@ expression: actual
},
"raw": "2",
"start": 4,
"end": 5
"end": 5,
"commentStart": 4
},
"right": {
"type": "Literal",
@ -40,11 +42,14 @@ expression: actual
},
"raw": "3",
"start": 8,
"end": 9
"end": 9,
"commentStart": 8
},
"start": 4,
"end": 9
"end": 9,
"commentStart": 4
},
"start": 0,
"end": 9
"end": 9,
"commentStart": 0
}

View File

@ -1,5 +1,5 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
@ -14,7 +14,8 @@ expression: actual
},
"raw": "1",
"start": 0,
"end": 1
"end": 1,
"commentStart": 0
},
"right": {
"type": "BinaryExpression",
@ -29,7 +30,8 @@ expression: actual
},
"raw": "2",
"start": 6,
"end": 7
"end": 7,
"commentStart": 6
},
"right": {
"type": "Literal",
@ -40,11 +42,14 @@ expression: actual
},
"raw": "3",
"start": 10,
"end": 11
"end": 11,
"commentStart": 10
},
"start": 6,
"end": 11
"end": 11,
"commentStart": 6
},
"start": 0,
"end": 11
"end": 11,
"commentStart": 0
}

View File

@ -1,5 +1,5 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
@ -18,7 +18,8 @@ expression: actual
},
"raw": "1",
"start": 0,
"end": 1
"end": 1,
"commentStart": 0
},
"right": {
"type": "BinaryExpression",
@ -33,7 +34,8 @@ expression: actual
},
"raw": "2",
"start": 6,
"end": 7
"end": 7,
"commentStart": 6
},
"right": {
"type": "Literal",
@ -44,13 +46,16 @@ expression: actual
},
"raw": "3",
"start": 10,
"end": 11
"end": 11,
"commentStart": 10
},
"start": 6,
"end": 11
"end": 11,
"commentStart": 6
},
"start": 0,
"end": 11
"end": 11,
"commentStart": 0
},
"right": {
"type": "Literal",
@ -61,8 +66,10 @@ expression: actual
},
"raw": "4",
"start": 16,
"end": 17
"end": 17,
"commentStart": 16
},
"start": 0,
"end": 17
"end": 17,
"commentStart": 0
}

View File

@ -1,5 +1,5 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
@ -14,7 +14,8 @@ expression: actual
},
"raw": "1",
"start": 0,
"end": 1
"end": 1,
"commentStart": 0
},
"right": {
"type": "BinaryExpression",
@ -33,7 +34,8 @@ expression: actual
},
"raw": "2",
"start": 6,
"end": 7
"end": 7,
"commentStart": 6
},
"right": {
"type": "Literal",
@ -44,10 +46,12 @@ expression: actual
},
"raw": "3",
"start": 10,
"end": 11
"end": 11,
"commentStart": 10
},
"start": 6,
"end": 11
"end": 11,
"commentStart": 6
},
"right": {
"type": "Literal",
@ -58,11 +62,14 @@ expression: actual
},
"raw": "4",
"start": 16,
"end": 17
"end": 17,
"commentStart": 16
},
"start": 6,
"end": 17
"end": 17,
"commentStart": 6
},
"start": 0,
"end": 17
"end": 17,
"commentStart": 0
}

View File

@ -1,5 +1,5 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
@ -14,7 +14,8 @@ expression: actual
},
"raw": "1",
"start": 0,
"end": 1
"end": 1,
"commentStart": 0
},
"right": {
"type": "BinaryExpression",
@ -37,7 +38,8 @@ expression: actual
},
"raw": "2",
"start": 7,
"end": 8
"end": 8,
"commentStart": 7
},
"right": {
"type": "Literal",
@ -48,10 +50,12 @@ expression: actual
},
"raw": "3",
"start": 11,
"end": 12
"end": 12,
"commentStart": 11
},
"start": 7,
"end": 12
"end": 12,
"commentStart": 7
},
"right": {
"type": "Literal",
@ -62,10 +66,12 @@ expression: actual
},
"raw": "4",
"start": 17,
"end": 18
"end": 18,
"commentStart": 17
},
"start": 7,
"end": 18
"end": 18,
"commentStart": 7
},
"right": {
"type": "Literal",
@ -76,11 +82,14 @@ expression: actual
},
"raw": "5",
"start": 21,
"end": 22
"end": 22,
"commentStart": 21
},
"start": 7,
"end": 22
"end": 22,
"commentStart": 7
},
"start": 0,
"end": 22
"end": 22,
"commentStart": 0
}

View File

@ -1,5 +1,5 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
@ -14,7 +14,8 @@ expression: actual
},
"raw": "1",
"start": 0,
"end": 1
"end": 1,
"commentStart": 0
},
"right": {
"type": "BinaryExpression",
@ -29,7 +30,8 @@ expression: actual
},
"raw": "2",
"start": 8,
"end": 9
"end": 9,
"commentStart": 8
},
"right": {
"type": "Literal",
@ -40,11 +42,14 @@ expression: actual
},
"raw": "3",
"start": 12,
"end": 13
"end": 13,
"commentStart": 12
},
"start": 8,
"end": 13
"end": 13,
"commentStart": 8
},
"start": 0,
"end": 13
"end": 13,
"commentStart": 0
}

View File

@ -1,5 +1,5 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
@ -18,31 +18,60 @@ expression: actual
"type": "BinaryExpression",
"operator": "*",
"left": {
"type": "Identifier",
"type": "Identifier",
"name": "distance",
"type": "Name",
"type": "Name",
"name": {
"type": "Identifier",
"name": "distance",
"start": 0,
"end": 8,
"commentStart": 0
},
"path": [],
"abs_path": false,
"start": 0,
"end": 8
"end": 8,
"commentStart": 0
},
"right": {
"type": "Identifier",
"type": "Identifier",
"name": "p",
"type": "Name",
"type": "Name",
"name": {
"type": "Identifier",
"name": "p",
"start": 11,
"end": 12,
"commentStart": 11
},
"path": [],
"abs_path": false,
"start": 11,
"end": 12
"end": 12,
"commentStart": 11
},
"start": 0,
"end": 12
"end": 12,
"commentStart": 0
},
"right": {
"type": "Identifier",
"type": "Identifier",
"name": "FOS",
"type": "Name",
"type": "Name",
"name": {
"type": "Identifier",
"name": "FOS",
"start": 15,
"end": 18,
"commentStart": 15
},
"path": [],
"abs_path": false,
"start": 15,
"end": 18
"end": 18,
"commentStart": 15
},
"start": 0,
"end": 18
"end": 18,
"commentStart": 0
},
"right": {
"type": "Literal",
@ -53,32 +82,54 @@ expression: actual
},
"raw": "6",
"start": 21,
"end": 22
"end": 22,
"commentStart": 21
},
"start": 0,
"end": 22
"end": 22,
"commentStart": 0
},
"right": {
"type": "BinaryExpression",
"type": "BinaryExpression",
"operator": "*",
"left": {
"type": "Identifier",
"type": "Identifier",
"name": "sigmaAllow",
"type": "Name",
"type": "Name",
"name": {
"type": "Identifier",
"name": "sigmaAllow",
"start": 26,
"end": 36,
"commentStart": 26
},
"path": [],
"abs_path": false,
"start": 26,
"end": 36
"end": 36,
"commentStart": 26
},
"right": {
"type": "Identifier",
"type": "Identifier",
"name": "width",
"type": "Name",
"type": "Name",
"name": {
"type": "Identifier",
"name": "width",
"start": 39,
"end": 44,
"commentStart": 39
},
"path": [],
"abs_path": false,
"start": 39,
"end": 44
"end": 44,
"commentStart": 39
},
"start": 26,
"end": 44
"end": 44,
"commentStart": 26
},
"start": 0,
"end": 44
"end": 44,
"commentStart": 0
}

View File

@ -1,5 +1,5 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
@ -14,7 +14,8 @@ expression: actual
},
"raw": "2",
"start": 0,
"end": 1
"end": 1,
"commentStart": 0
},
"right": {
"type": "Literal",
@ -25,8 +26,10 @@ expression: actual
},
"raw": "3",
"start": 7,
"end": 8
"end": 8,
"commentStart": 7
},
"start": 0,
"end": 8
"end": 8,
"commentStart": 0
}

View File

@ -5,9 +5,12 @@ expression: actual
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 170,
"id": {
"commentStart": 0,
"end": 9,
"name": "boxSketch",
"start": 0,
@ -18,19 +21,38 @@ expression: actual
{
"arguments": [
{
"abs_path": false,
"commentStart": 26,
"end": 28,
"name": "XY",
"name": {
"commentStart": 26,
"end": 28,
"name": "XY",
"start": 26,
"type": "Identifier"
},
"path": [],
"start": 26,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
],
"callee": {
"abs_path": false,
"commentStart": 12,
"end": 25,
"name": "startSketchOn",
"name": {
"commentStart": 12,
"end": 25,
"name": "startSketchOn",
"start": 12,
"type": "Identifier"
},
"path": [],
"start": 12,
"type": "Identifier"
"type": "Name"
},
"commentStart": 12,
"end": 29,
"start": 12,
"type": "CallExpression",
@ -39,8 +61,10 @@ expression: actual
{
"arguments": [
{
"commentStart": 52,
"elements": [
{
"commentStart": 53,
"end": 54,
"raw": "0",
"start": 53,
@ -52,6 +76,7 @@ expression: actual
}
},
{
"commentStart": 56,
"end": 57,
"raw": "0",
"start": 56,
@ -69,6 +94,7 @@ expression: actual
"type": "ArrayExpression"
},
{
"commentStart": 60,
"end": 61,
"start": 60,
"type": "PipeSubstitution",
@ -76,11 +102,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 37,
"end": 51,
"name": "startProfileAt",
"name": {
"commentStart": 37,
"end": 51,
"name": "startProfileAt",
"start": 37,
"type": "Identifier"
},
"path": [],
"start": 37,
"type": "Identifier"
"type": "Name"
},
"commentStart": 37,
"end": 62,
"start": 37,
"type": "CallExpression",
@ -89,8 +125,10 @@ expression: actual
{
"arguments": [
{
"commentStart": 75,
"elements": [
{
"commentStart": 76,
"end": 77,
"raw": "0",
"start": 76,
@ -102,6 +140,7 @@ expression: actual
}
},
{
"commentStart": 79,
"end": 81,
"raw": "10",
"start": 79,
@ -119,6 +158,7 @@ expression: actual
"type": "ArrayExpression"
},
{
"commentStart": 84,
"end": 85,
"start": 84,
"type": "PipeSubstitution",
@ -126,11 +166,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 70,
"end": 74,
"name": "line",
"name": {
"commentStart": 70,
"end": 74,
"name": "line",
"start": 70,
"type": "Identifier"
},
"path": [],
"start": 70,
"type": "Identifier"
"type": "Name"
},
"commentStart": 70,
"end": 86,
"start": 70,
"type": "CallExpression",
@ -139,9 +189,11 @@ expression: actual
{
"arguments": [
{
"commentStart": 108,
"elements": [
{
"argument": {
"commentStart": 110,
"end": 111,
"raw": "5",
"start": 110,
@ -152,6 +204,7 @@ expression: actual
"suffix": "None"
}
},
"commentStart": 109,
"end": 111,
"operator": "-",
"start": 109,
@ -159,6 +212,7 @@ expression: actual
"type": "UnaryExpression"
},
{
"commentStart": 113,
"end": 114,
"raw": "5",
"start": 113,
@ -176,6 +230,7 @@ expression: actual
"type": "ArrayExpression"
},
{
"commentStart": 117,
"end": 118,
"start": 117,
"type": "PipeSubstitution",
@ -183,11 +238,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 94,
"end": 107,
"name": "tangentialArc",
"name": {
"commentStart": 94,
"end": 107,
"name": "tangentialArc",
"start": 94,
"type": "Identifier"
},
"path": [],
"start": 94,
"type": "Identifier"
"type": "Name"
},
"commentStart": 94,
"end": 119,
"start": 94,
"type": "CallExpression",
@ -196,8 +261,10 @@ expression: actual
{
"arguments": [
{
"commentStart": 132,
"elements": [
{
"commentStart": 133,
"end": 134,
"raw": "5",
"start": 133,
@ -210,6 +277,7 @@ expression: actual
},
{
"argument": {
"commentStart": 137,
"end": 139,
"raw": "15",
"start": 137,
@ -220,6 +288,7 @@ expression: actual
"suffix": "None"
}
},
"commentStart": 136,
"end": 139,
"operator": "-",
"start": 136,
@ -233,6 +302,7 @@ expression: actual
"type": "ArrayExpression"
},
{
"commentStart": 142,
"end": 143,
"start": 142,
"type": "PipeSubstitution",
@ -240,11 +310,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 127,
"end": 131,
"name": "line",
"name": {
"commentStart": 127,
"end": 131,
"name": "line",
"start": 127,
"type": "Identifier"
},
"path": [],
"start": 127,
"type": "Identifier"
"type": "Name"
},
"commentStart": 127,
"end": 144,
"start": 127,
"type": "CallExpression",
@ -255,12 +335,14 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 160,
"end": 166,
"name": "length",
"start": 160,
"type": "Identifier"
},
"arg": {
"commentStart": 167,
"end": 169,
"raw": "10",
"start": 167,
@ -274,11 +356,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 152,
"end": 159,
"name": "extrude",
"name": {
"commentStart": 152,
"end": 159,
"name": "extrude",
"start": 152,
"type": "Identifier"
},
"path": [],
"start": 152,
"type": "Identifier"
"type": "Name"
},
"commentStart": 152,
"end": 170,
"start": 152,
"type": "CallExpressionKw",
@ -286,6 +378,7 @@ expression: actual
"unlabeled": null
}
],
"commentStart": 12,
"end": 170,
"start": 12,
"type": "PipeExpression",
@ -301,6 +394,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 171,
"start": 0
}

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 11,
"id": {
"commentStart": 0,
"end": 2,
"name": "sg",
"start": 0,
@ -15,12 +18,22 @@ expression: actual
},
"init": {
"argument": {
"abs_path": false,
"commentStart": 6,
"end": 11,
"name": "scale",
"name": {
"commentStart": 6,
"end": 11,
"name": "scale",
"start": 6,
"type": "Identifier"
},
"path": [],
"start": 6,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
},
"commentStart": 5,
"end": 11,
"operator": "-",
"start": 5,
@ -37,6 +50,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 11,
"start": 0
}

View File

@ -5,20 +5,24 @@ expression: actual
{
"body": [
{
"commentStart": 0,
"end": 27,
"expression": {
"arguments": [
{
"type": "LabeledArg",
"label": {
"commentStart": 5,
"end": 16,
"name": "endAbsolute",
"start": 5,
"type": "Identifier"
},
"arg": {
"commentStart": 19,
"elements": [
{
"commentStart": 20,
"end": 21,
"raw": "0",
"start": 20,
@ -31,6 +35,7 @@ expression: actual
},
{
"argument": {
"commentStart": 24,
"end": 25,
"raw": "1",
"start": 24,
@ -41,6 +46,7 @@ expression: actual
"suffix": "None"
}
},
"commentStart": 23,
"end": 25,
"operator": "-",
"start": 23,
@ -56,11 +62,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 4,
"name": "line",
"name": {
"commentStart": 0,
"end": 4,
"name": "line",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Identifier"
"type": "Name"
},
"commentStart": 0,
"end": 27,
"start": 0,
"type": "CallExpressionKw",
@ -72,6 +88,7 @@ expression: actual
"type": "ExpressionStatement"
}
],
"commentStart": 0,
"end": 27,
"start": 0
}

View File

@ -1,21 +1,26 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 17,
"id": {
"commentStart": 0,
"end": 7,
"name": "myArray",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 10,
"end": 17,
"endElement": {
"commentStart": 14,
"end": 16,
"raw": "10",
"start": 14,
@ -29,6 +34,7 @@ expression: actual
"endInclusive": true,
"start": 10,
"startElement": {
"commentStart": 11,
"end": 12,
"raw": "0",
"start": 11,
@ -52,6 +58,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 17,
"start": 0
}

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 5,
"declaration": {
"commentStart": 8,
"end": 57,
"id": {
"commentStart": 8,
"end": 24,
"name": "firstPrimeNumber",
"start": 8,
@ -18,6 +21,7 @@ expression: actual
"body": [
{
"argument": {
"commentStart": 50,
"end": 51,
"raw": "2",
"start": 50,
@ -28,15 +32,18 @@ expression: actual
"suffix": "None"
}
},
"commentStart": 43,
"end": 51,
"start": 43,
"type": "ReturnStatement",
"type": "ReturnStatement"
}
],
"commentStart": 33,
"end": 57,
"start": 33
},
"commentStart": 27,
"end": 57,
"params": [],
"start": 27,
@ -53,15 +60,26 @@ expression: actual
"type": "VariableDeclaration"
},
{
"commentStart": 62,
"end": 80,
"expression": {
"arguments": [],
"callee": {
"abs_path": false,
"commentStart": 62,
"end": 78,
"name": "firstPrimeNumber",
"name": {
"commentStart": 62,
"end": 78,
"name": "firstPrimeNumber",
"start": 62,
"type": "Identifier"
},
"path": [],
"start": 62,
"type": "Identifier"
"type": "Name"
},
"commentStart": 62,
"end": 80,
"start": 62,
"type": "CallExpression",
@ -72,6 +90,7 @@ expression: actual
"type": "ExpressionStatement"
}
],
"commentStart": 0,
"end": 80,
"start": 0
}

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 3,
"end": 49,
"id": {
"commentStart": 3,
"end": 8,
"name": "thing",
"start": 3,
@ -18,6 +21,7 @@ expression: actual
"body": [
{
"argument": {
"commentStart": 39,
"end": 43,
"raw": "true",
"start": 39,
@ -25,20 +29,24 @@ expression: actual
"type": "Literal",
"value": true
},
"commentStart": 32,
"end": 43,
"start": 32,
"type": "ReturnStatement",
"type": "ReturnStatement"
}
],
"commentStart": 22,
"end": 49,
"start": 22
},
"commentStart": 11,
"end": 49,
"params": [
{
"type": "Parameter",
"identifier": {
"commentStart": 12,
"end": 17,
"name": "param",
"start": 12,
@ -60,10 +68,12 @@ expression: actual
"type": "VariableDeclaration"
},
{
"commentStart": 54,
"end": 66,
"expression": {
"arguments": [
{
"commentStart": 60,
"end": 65,
"raw": "false",
"start": 60,
@ -73,11 +83,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 54,
"end": 59,
"name": "thing",
"name": {
"commentStart": 54,
"end": 59,
"name": "thing",
"start": 54,
"type": "Identifier"
},
"path": [],
"start": 54,
"type": "Identifier"
"type": "Name"
},
"commentStart": 54,
"end": 66,
"start": 54,
"type": "CallExpression",
@ -88,6 +108,7 @@ expression: actual
"type": "ExpressionStatement"
}
],
"commentStart": 0,
"end": 66,
"start": 0
}

View File

@ -5,9 +5,12 @@ expression: actual
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 230,
"id": {
"commentStart": 0,
"end": 8,
"name": "mySketch",
"start": 0,
@ -18,19 +21,38 @@ expression: actual
{
"arguments": [
{
"abs_path": false,
"commentStart": 25,
"end": 27,
"name": "XY",
"name": {
"commentStart": 25,
"end": 27,
"name": "XY",
"start": 25,
"type": "Identifier"
},
"path": [],
"start": 25,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
],
"callee": {
"abs_path": false,
"commentStart": 11,
"end": 24,
"name": "startSketchOn",
"name": {
"commentStart": 11,
"end": 24,
"name": "startSketchOn",
"start": 11,
"type": "Identifier"
},
"path": [],
"start": 11,
"type": "Identifier"
"type": "Name"
},
"commentStart": 11,
"end": 28,
"start": 11,
"type": "CallExpression",
@ -39,8 +61,10 @@ expression: actual
{
"arguments": [
{
"commentStart": 55,
"elements": [
{
"commentStart": 56,
"end": 57,
"raw": "0",
"start": 56,
@ -52,6 +76,7 @@ expression: actual
}
},
{
"commentStart": 58,
"end": 59,
"raw": "0",
"start": 58,
@ -69,6 +94,7 @@ expression: actual
"type": "ArrayExpression"
},
{
"commentStart": 62,
"end": 63,
"start": 62,
"type": "PipeSubstitution",
@ -76,11 +102,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 40,
"end": 54,
"name": "startProfileAt",
"name": {
"commentStart": 40,
"end": 54,
"name": "startProfileAt",
"start": 40,
"type": "Identifier"
},
"path": [],
"start": 40,
"type": "Identifier"
"type": "Name"
},
"commentStart": 40,
"end": 64,
"start": 40,
"type": "CallExpression",
@ -91,14 +127,17 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 81,
"end": 92,
"name": "endAbsolute",
"start": 81,
"type": "Identifier"
},
"arg": {
"commentStart": 95,
"elements": [
{
"commentStart": 96,
"end": 97,
"raw": "0",
"start": 96,
@ -110,6 +149,7 @@ expression: actual
}
},
{
"commentStart": 99,
"end": 100,
"raw": "1",
"start": 99,
@ -130,12 +170,14 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 103,
"end": 106,
"name": "tag",
"start": 103,
"type": "Identifier"
},
"arg": {
"commentStart": 109,
"end": 116,
"start": 109,
"type": "TagDeclarator",
@ -145,11 +187,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 76,
"end": 80,
"name": "line",
"name": {
"commentStart": 76,
"end": 80,
"name": "line",
"start": 76,
"type": "Identifier"
},
"path": [],
"start": 76,
"type": "Identifier"
"type": "Name"
},
"commentStart": 76,
"end": 117,
"start": 76,
"type": "CallExpressionKw",
@ -161,14 +213,17 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 134,
"end": 145,
"name": "endAbsolute",
"start": 134,
"type": "Identifier"
},
"arg": {
"commentStart": 148,
"elements": [
{
"commentStart": 149,
"end": 150,
"raw": "1",
"start": 149,
@ -180,6 +235,7 @@ expression: actual
}
},
{
"commentStart": 152,
"end": 153,
"raw": "1",
"start": 152,
@ -199,11 +255,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 129,
"end": 133,
"name": "line",
"name": {
"commentStart": 129,
"end": 133,
"name": "line",
"start": 129,
"type": "Identifier"
},
"path": [],
"start": 129,
"type": "Identifier"
"type": "Name"
},
"commentStart": 129,
"end": 155,
"start": 129,
"type": "CallExpressionKw",
@ -215,14 +281,17 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 172,
"end": 183,
"name": "endAbsolute",
"start": 172,
"type": "Identifier"
},
"arg": {
"commentStart": 186,
"elements": [
{
"commentStart": 187,
"end": 188,
"raw": "1",
"start": 187,
@ -234,6 +303,7 @@ expression: actual
}
},
{
"commentStart": 190,
"end": 191,
"raw": "0",
"start": 190,
@ -254,12 +324,14 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 194,
"end": 197,
"name": "tag",
"start": 194,
"type": "Identifier"
},
"arg": {
"commentStart": 200,
"end": 210,
"start": 200,
"type": "TagDeclarator",
@ -269,11 +341,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 167,
"end": 171,
"name": "line",
"name": {
"commentStart": 167,
"end": 171,
"name": "line",
"start": 167,
"type": "Identifier"
},
"path": [],
"start": 167,
"type": "Identifier"
"type": "Name"
},
"commentStart": 167,
"end": 211,
"start": 167,
"type": "CallExpressionKw",
@ -283,17 +365,28 @@ expression: actual
{
"arguments": [],
"callee": {
"abs_path": false,
"commentStart": 223,
"end": 228,
"name": "close",
"name": {
"commentStart": 223,
"end": 228,
"name": "close",
"start": 223,
"type": "Identifier"
},
"path": [],
"start": 223,
"type": "Identifier"
"type": "Name"
},
"commentStart": 223,
"end": 230,
"start": 223,
"type": "CallExpression",
"type": "CallExpression"
}
],
"commentStart": 11,
"end": 230,
"start": 11,
"type": "PipeExpression",
@ -309,6 +402,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 230,
"start": 0
}

View File

@ -5,9 +5,12 @@ expression: actual
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 97,
"id": {
"commentStart": 0,
"end": 8,
"name": "mySketch",
"start": 0,
@ -18,19 +21,38 @@ expression: actual
{
"arguments": [
{
"abs_path": false,
"commentStart": 25,
"end": 27,
"name": "XY",
"name": {
"commentStart": 25,
"end": 27,
"name": "XY",
"start": 25,
"type": "Identifier"
},
"path": [],
"start": 25,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
],
"callee": {
"abs_path": false,
"commentStart": 11,
"end": 24,
"name": "startSketchOn",
"name": {
"commentStart": 11,
"end": 24,
"name": "startSketchOn",
"start": 11,
"type": "Identifier"
},
"path": [],
"start": 11,
"type": "Identifier"
"type": "Name"
},
"commentStart": 11,
"end": 28,
"start": 11,
"type": "CallExpression",
@ -39,8 +61,10 @@ expression: actual
{
"arguments": [
{
"commentStart": 47,
"elements": [
{
"commentStart": 48,
"end": 49,
"raw": "0",
"start": 48,
@ -52,6 +76,7 @@ expression: actual
}
},
{
"commentStart": 50,
"end": 51,
"raw": "0",
"start": 50,
@ -69,6 +94,7 @@ expression: actual
"type": "ArrayExpression"
},
{
"commentStart": 54,
"end": 55,
"start": 54,
"type": "PipeSubstitution",
@ -76,11 +102,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 32,
"end": 46,
"name": "startProfileAt",
"name": {
"commentStart": 32,
"end": 46,
"name": "startProfileAt",
"start": 32,
"type": "Identifier"
},
"path": [],
"start": 32,
"type": "Identifier"
"type": "Name"
},
"commentStart": 32,
"end": 56,
"start": 32,
"type": "CallExpression",
@ -91,14 +127,17 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 65,
"end": 76,
"name": "endAbsolute",
"start": 65,
"type": "Identifier"
},
"arg": {
"commentStart": 79,
"elements": [
{
"commentStart": 80,
"end": 81,
"raw": "1",
"start": 80,
@ -110,6 +149,7 @@ expression: actual
}
},
{
"commentStart": 83,
"end": 84,
"raw": "1",
"start": 83,
@ -129,11 +169,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 60,
"end": 64,
"name": "line",
"name": {
"commentStart": 60,
"end": 64,
"name": "line",
"start": 60,
"type": "Identifier"
},
"path": [],
"start": 60,
"type": "Identifier"
"type": "Name"
},
"commentStart": 60,
"end": 86,
"start": 60,
"type": "CallExpressionKw",
@ -143,17 +193,28 @@ expression: actual
{
"arguments": [],
"callee": {
"abs_path": false,
"commentStart": 90,
"end": 95,
"name": "close",
"name": {
"commentStart": 90,
"end": 95,
"name": "close",
"start": 90,
"type": "Identifier"
},
"path": [],
"start": 90,
"type": "Identifier"
"type": "Name"
},
"commentStart": 90,
"end": 97,
"start": 90,
"type": "CallExpression",
"type": "CallExpression"
}
],
"commentStart": 11,
"end": 97,
"start": 11,
"type": "PipeExpression",
@ -169,6 +230,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 97,
"start": 0
}

View File

@ -5,9 +5,12 @@ expression: actual
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 49,
"id": {
"commentStart": 0,
"end": 5,
"name": "myBox",
"start": 0,
@ -18,19 +21,38 @@ expression: actual
{
"arguments": [
{
"abs_path": false,
"commentStart": 22,
"end": 24,
"name": "XY",
"name": {
"commentStart": 22,
"end": 24,
"name": "XY",
"start": 22,
"type": "Identifier"
},
"path": [],
"start": 22,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
],
"callee": {
"abs_path": false,
"commentStart": 8,
"end": 21,
"name": "startSketchOn",
"name": {
"commentStart": 8,
"end": 21,
"name": "startSketchOn",
"start": 8,
"type": "Identifier"
},
"path": [],
"start": 8,
"type": "Identifier"
"type": "Name"
},
"commentStart": 8,
"end": 25,
"start": 8,
"type": "CallExpression",
@ -39,13 +61,23 @@ expression: actual
{
"arguments": [
{
"abs_path": false,
"commentStart": 44,
"end": 45,
"name": "p",
"name": {
"commentStart": 44,
"end": 45,
"name": "p",
"start": 44,
"type": "Identifier"
},
"path": [],
"start": 44,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
},
{
"commentStart": 47,
"end": 48,
"start": 47,
"type": "PipeSubstitution",
@ -53,17 +85,28 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 29,
"end": 43,
"name": "startProfileAt",
"name": {
"commentStart": 29,
"end": 43,
"name": "startProfileAt",
"start": 29,
"type": "Identifier"
},
"path": [],
"start": 29,
"type": "Identifier"
"type": "Name"
},
"commentStart": 29,
"end": 49,
"start": 29,
"type": "CallExpression",
"type": "CallExpression"
}
],
"commentStart": 8,
"end": 49,
"start": 8,
"type": "PipeExpression",
@ -79,6 +122,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 49,
"start": 0
}

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 23,
"id": {
"commentStart": 0,
"end": 5,
"name": "myBox",
"start": 0,
@ -18,6 +21,7 @@ expression: actual
{
"arguments": [
{
"commentStart": 10,
"end": 11,
"raw": "1",
"start": 10,
@ -30,11 +34,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 8,
"end": 9,
"name": "f",
"name": {
"commentStart": 8,
"end": 9,
"name": "f",
"start": 8,
"type": "Identifier"
},
"path": [],
"start": 8,
"type": "Identifier"
"type": "Name"
},
"commentStart": 8,
"end": 12,
"start": 8,
"type": "CallExpression",
@ -43,6 +57,7 @@ expression: actual
{
"arguments": [
{
"commentStart": 18,
"end": 19,
"raw": "2",
"start": 18,
@ -54,6 +69,7 @@ expression: actual
}
},
{
"commentStart": 21,
"end": 22,
"start": 21,
"type": "PipeSubstitution",
@ -61,17 +77,28 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 16,
"end": 17,
"name": "g",
"name": {
"commentStart": 16,
"end": 17,
"name": "g",
"start": 16,
"type": "Identifier"
},
"path": [],
"start": 16,
"type": "Identifier"
"type": "Name"
},
"commentStart": 16,
"end": 23,
"start": 16,
"type": "CallExpression",
"type": "CallExpression"
}
],
"commentStart": 8,
"end": 23,
"start": 8,
"type": "PipeExpression",
@ -87,6 +114,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 23,
"start": 0
}

View File

@ -5,9 +5,12 @@ expression: actual
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 71,
"id": {
"commentStart": 0,
"end": 5,
"name": "myBox",
"start": 0,
@ -18,19 +21,38 @@ expression: actual
{
"arguments": [
{
"abs_path": false,
"commentStart": 22,
"end": 24,
"name": "XY",
"name": {
"commentStart": 22,
"end": 24,
"name": "XY",
"start": 22,
"type": "Identifier"
},
"path": [],
"start": 22,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
],
"callee": {
"abs_path": false,
"commentStart": 8,
"end": 21,
"name": "startSketchOn",
"name": {
"commentStart": 8,
"end": 21,
"name": "startSketchOn",
"start": 8,
"type": "Identifier"
},
"path": [],
"start": 8,
"type": "Identifier"
"type": "Name"
},
"commentStart": 8,
"end": 25,
"start": 8,
"type": "CallExpression",
@ -39,13 +61,23 @@ expression: actual
{
"arguments": [
{
"abs_path": false,
"commentStart": 44,
"end": 45,
"name": "p",
"name": {
"commentStart": 44,
"end": 45,
"name": "p",
"start": 44,
"type": "Identifier"
},
"path": [],
"start": 44,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
},
{
"commentStart": 47,
"end": 48,
"start": 47,
"type": "PipeSubstitution",
@ -53,11 +85,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 29,
"end": 43,
"name": "startProfileAt",
"name": {
"commentStart": 29,
"end": 43,
"name": "startProfileAt",
"start": 29,
"type": "Identifier"
},
"path": [],
"start": 29,
"type": "Identifier"
"type": "Name"
},
"commentStart": 29,
"end": 49,
"start": 29,
"type": "CallExpression",
@ -68,14 +110,17 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 58,
"end": 61,
"name": "end",
"start": 58,
"type": "Identifier"
},
"arg": {
"commentStart": 64,
"elements": [
{
"commentStart": 65,
"end": 66,
"raw": "0",
"start": 65,
@ -87,11 +132,20 @@ expression: actual
}
},
{
"abs_path": false,
"commentStart": 68,
"end": 69,
"name": "l",
"name": {
"commentStart": 68,
"end": 69,
"name": "l",
"start": 68,
"type": "Identifier"
},
"path": [],
"start": 68,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
],
"end": 70,
@ -102,11 +156,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 53,
"end": 57,
"name": "line",
"name": {
"commentStart": 53,
"end": 57,
"name": "line",
"start": 53,
"type": "Identifier"
},
"path": [],
"start": 53,
"type": "Identifier"
"type": "Name"
},
"commentStart": 53,
"end": 71,
"start": 53,
"type": "CallExpressionKw",
@ -114,6 +178,7 @@ expression: actual
"unlabeled": null
}
],
"commentStart": 8,
"end": 71,
"start": 8,
"type": "PipeExpression",
@ -129,6 +194,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 71,
"start": 0
}

View File

@ -5,20 +5,24 @@ expression: actual
{
"body": [
{
"commentStart": 0,
"end": 26,
"expression": {
"arguments": [
{
"type": "LabeledArg",
"label": {
"commentStart": 5,
"end": 16,
"name": "endAbsolute",
"start": 5,
"type": "Identifier"
},
"arg": {
"commentStart": 19,
"elements": [
{
"commentStart": 20,
"end": 21,
"raw": "0",
"start": 20,
@ -30,6 +34,7 @@ expression: actual
}
},
{
"commentStart": 23,
"end": 24,
"raw": "1",
"start": 23,
@ -49,11 +54,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 4,
"name": "line",
"name": {
"commentStart": 0,
"end": 4,
"name": "line",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Identifier"
"type": "Name"
},
"commentStart": 0,
"end": 26,
"start": 0,
"type": "CallExpressionKw",
@ -65,6 +80,7 @@ expression: actual
"type": "ExpressionStatement"
}
],
"commentStart": 0,
"end": 26,
"start": 0
}

View File

@ -5,9 +5,12 @@ expression: actual
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 56,
"id": {
"commentStart": 0,
"end": 8,
"name": "mySketch",
"start": 0,
@ -18,19 +21,38 @@ expression: actual
{
"arguments": [
{
"abs_path": false,
"commentStart": 25,
"end": 27,
"name": "XY",
"name": {
"commentStart": 25,
"end": 27,
"name": "XY",
"start": 25,
"type": "Identifier"
},
"path": [],
"start": 25,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
],
"callee": {
"abs_path": false,
"commentStart": 11,
"end": 24,
"name": "startSketchOn",
"name": {
"commentStart": 11,
"end": 24,
"name": "startSketchOn",
"start": 11,
"type": "Identifier"
},
"path": [],
"start": 11,
"type": "Identifier"
"type": "Name"
},
"commentStart": 11,
"end": 28,
"start": 11,
"type": "CallExpression",
@ -39,8 +61,10 @@ expression: actual
{
"arguments": [
{
"commentStart": 47,
"elements": [
{
"commentStart": 48,
"end": 49,
"raw": "0",
"start": 48,
@ -52,6 +76,7 @@ expression: actual
}
},
{
"commentStart": 50,
"end": 51,
"raw": "0",
"start": 50,
@ -69,6 +94,7 @@ expression: actual
"type": "ArrayExpression"
},
{
"commentStart": 54,
"end": 55,
"start": 54,
"type": "PipeSubstitution",
@ -76,17 +102,28 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 32,
"end": 46,
"name": "startProfileAt",
"name": {
"commentStart": 32,
"end": 46,
"name": "startProfileAt",
"start": 32,
"type": "Identifier"
},
"path": [],
"start": 32,
"type": "Identifier"
"type": "Name"
},
"commentStart": 32,
"end": 56,
"start": 32,
"type": "CallExpression",
"type": "CallExpression"
}
],
"commentStart": 11,
"end": 56,
"start": 11,
"type": "PipeExpression",
@ -102,6 +139,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 56,
"start": 0
}

View File

@ -1,14 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"end": 28,
"expression": {
"arguments": [
{
"commentStart": 4,
"end": 5,
"raw": "5",
"start": 4,
@ -20,6 +22,7 @@ expression: actual
}
},
{
"commentStart": 7,
"end": 14,
"raw": "\"hello\"",
"start": 7,
@ -28,19 +31,38 @@ expression: actual
"value": "hello"
},
{
"abs_path": false,
"commentStart": 16,
"end": 27,
"name": "aIdentifier",
"name": {
"commentStart": 16,
"end": 27,
"name": "aIdentifier",
"start": 16,
"type": "Identifier"
},
"path": [],
"start": 16,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 3,
"name": "log",
"name": {
"commentStart": 0,
"end": 3,
"name": "log",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Identifier"
"type": "Name"
},
"commentStart": 0,
"end": 28,
"start": 0,
"type": "CallExpression",
@ -51,6 +73,7 @@ expression: actual
"type": "ExpressionStatement"
}
],
"commentStart": 0,
"end": 28,
"start": 0
}

View File

@ -1,14 +1,17 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"end": 7,
"expression": {
"commentStart": 0,
"end": 7,
"left": {
"commentStart": 0,
"end": 1,
"raw": "5",
"start": 0,
@ -21,6 +24,7 @@ expression: actual
},
"operator": "+",
"right": {
"commentStart": 4,
"end": 7,
"raw": "\"a\"",
"start": 4,
@ -37,6 +41,7 @@ expression: actual
"type": "ExpressionStatement"
}
],
"commentStart": 0,
"end": 7,
"start": 0
}

View File

@ -1,16 +1,19 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"end": 15,
"expression": {
"arguments": [
{
"commentStart": 5,
"elements": [
{
"commentStart": 6,
"end": 7,
"raw": "0",
"start": 6,
@ -22,11 +25,20 @@ expression: actual
}
},
{
"abs_path": false,
"commentStart": 9,
"end": 10,
"name": "l",
"name": {
"commentStart": 9,
"end": 10,
"name": "l",
"start": 9,
"type": "Identifier"
},
"path": [],
"start": 9,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
],
"end": 11,
@ -35,6 +47,7 @@ expression: actual
"type": "ArrayExpression"
},
{
"commentStart": 13,
"end": 14,
"start": 13,
"type": "PipeSubstitution",
@ -42,11 +55,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 4,
"name": "line",
"name": {
"commentStart": 0,
"end": 4,
"name": "line",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Identifier"
"type": "Name"
},
"commentStart": 0,
"end": 15,
"start": 0,
"type": "CallExpression",
@ -57,6 +80,7 @@ expression: actual
"type": "ExpressionStatement"
}
],
"commentStart": 0,
"end": 15,
"start": 0
}

View File

@ -5,9 +5,12 @@ expression: actual
{
"body": [
{
"commentStart": 0,
"declaration": {
"end": 106,
"commentStart": 6,
"end": 104,
"id": {
"commentStart": 6,
"end": 14,
"name": "cylinder",
"start": 6,
@ -18,21 +21,39 @@ expression: actual
{
"arguments": [
{
"end": 35,
"raw": "'XY'",
"abs_path": false,
"commentStart": 31,
"end": 33,
"name": {
"commentStart": 31,
"end": 33,
"name": "XY",
"start": 31,
"type": "Identifier"
},
"path": [],
"start": 31,
"type": "Literal",
"type": "Literal",
"value": "XY"
"type": "Name",
"type": "Name"
}
],
"callee": {
"abs_path": false,
"commentStart": 17,
"end": 30,
"name": "startSketchOn",
"name": {
"commentStart": 17,
"end": 30,
"name": "startSketchOn",
"start": 17,
"type": "Identifier"
},
"path": [],
"start": 17,
"type": "Identifier"
"type": "Name"
},
"end": 36,
"commentStart": 17,
"end": 34,
"start": 17,
"type": "CallExpression",
"type": "CallExpression"
@ -42,17 +63,20 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"end": 57,
"commentStart": 49,
"end": 55,
"name": "center",
"start": 51,
"start": 49,
"type": "Identifier"
},
"arg": {
"commentStart": 57,
"elements": [
{
"end": 61,
"commentStart": 58,
"end": 59,
"raw": "0",
"start": 60,
"start": 58,
"type": "Literal",
"type": "Literal",
"value": {
@ -61,9 +85,10 @@ expression: actual
}
},
{
"end": 64,
"commentStart": 61,
"end": 62,
"raw": "0",
"start": 63,
"start": 61,
"type": "Literal",
"type": "Literal",
"value": {
@ -72,8 +97,8 @@ expression: actual
}
}
],
"end": 65,
"start": 59,
"end": 63,
"start": 57,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
@ -81,15 +106,17 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"end": 73,
"commentStart": 65,
"end": 71,
"name": "radius",
"start": 67,
"start": 65,
"type": "Identifier"
},
"arg": {
"end": 77,
"commentStart": 73,
"end": 75,
"raw": "22",
"start": 75,
"start": 73,
"type": "Literal",
"type": "Literal",
"value": {
@ -100,13 +127,23 @@ expression: actual
}
],
"callee": {
"end": 50,
"name": "circle",
"start": 44,
"type": "Identifier"
"abs_path": false,
"commentStart": 42,
"end": 48,
"name": {
"commentStart": 42,
"end": 48,
"name": "circle",
"start": 42,
"type": "Identifier"
},
"path": [],
"start": 42,
"type": "Name"
},
"end": 78,
"start": 44,
"commentStart": 42,
"end": 76,
"start": 42,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
@ -116,15 +153,17 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"end": 100,
"commentStart": 92,
"end": 98,
"name": "length",
"start": 94,
"start": 92,
"type": "Identifier"
},
"arg": {
"end": 105,
"commentStart": 101,
"end": 103,
"raw": "14",
"start": 103,
"start": 101,
"type": "Literal",
"type": "Literal",
"value": {
@ -135,19 +174,30 @@ expression: actual
}
],
"callee": {
"end": 93,
"name": "extrude",
"start": 86,
"type": "Identifier"
"abs_path": false,
"commentStart": 84,
"end": 91,
"name": {
"commentStart": 84,
"end": 91,
"name": "extrude",
"start": 84,
"type": "Identifier"
},
"path": [],
"start": 84,
"type": "Name"
},
"end": 106,
"start": 86,
"commentStart": 84,
"end": 104,
"start": 84,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
}
],
"end": 106,
"commentStart": 17,
"end": 104,
"start": 17,
"type": "PipeExpression",
"type": "PipeExpression"
@ -155,13 +205,14 @@ expression: actual
"start": 6,
"type": "VariableDeclarator"
},
"end": 106,
"end": 104,
"kind": "const",
"start": 0,
"type": "VariableDeclaration",
"type": "VariableDeclaration"
}
],
"end": 107,
"commentStart": 0,
"end": 105,
"start": 0
}

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 3,
"end": 49,
"id": {
"commentStart": 3,
"end": 4,
"name": "f",
"start": 3,
@ -20,13 +23,23 @@ expression: actual
"argument": {
"arguments": [
{
"abs_path": false,
"commentStart": 36,
"end": 41,
"name": "angle",
"name": {
"commentStart": 36,
"end": 41,
"name": "angle",
"start": 36,
"type": "Identifier"
},
"path": [],
"start": 36,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
},
{
"commentStart": 43,
"end": 46,
"raw": "360",
"start": 43,
@ -39,30 +52,44 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 28,
"end": 35,
"name": "default",
"name": {
"commentStart": 28,
"end": 35,
"name": "default",
"start": 28,
"type": "Identifier"
},
"path": [],
"start": 28,
"type": "Identifier"
"type": "Name"
},
"commentStart": 28,
"end": 47,
"start": 28,
"type": "CallExpression",
"type": "CallExpression"
},
"commentStart": 21,
"end": 47,
"start": 21,
"type": "ReturnStatement",
"type": "ReturnStatement"
}
],
"commentStart": 19,
"end": 49,
"start": 19
},
"commentStart": 7,
"end": 49,
"params": [
{
"type": "Parameter",
"identifier": {
"commentStart": 8,
"end": 13,
"name": "angle",
"start": 8,
@ -89,6 +116,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 49,
"start": 0
}

View File

@ -1,21 +1,26 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 4,
"end": 91,
"id": {
"commentStart": 4,
"end": 11,
"name": "numbers",
"start": 4,
"type": "Identifier"
},
"init": {
"commentStart": 14,
"elements": [
{
"commentStart": 28,
"end": 29,
"raw": "1",
"start": 28,
@ -27,6 +32,7 @@ expression: actual
}
},
{
"commentStart": 79,
"end": 80,
"raw": "3",
"start": 79,
@ -43,6 +49,7 @@ expression: actual
"nonCodeNodes": {
"1": [
{
"commentStart": 43,
"end": 48,
"start": 43,
"type": "NonCodeNode",
@ -55,6 +62,7 @@ expression: actual
],
"2": [
{
"commentStart": 61,
"end": 66,
"start": 61,
"type": "NonCodeNode",
@ -82,6 +90,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 91,
"start": 0
}

View File

@ -1,21 +1,26 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 4,
"end": 91,
"id": {
"commentStart": 4,
"end": 11,
"name": "numbers",
"start": 4,
"type": "Identifier"
},
"init": {
"commentStart": 14,
"elements": [
{
"commentStart": 28,
"end": 29,
"raw": "1",
"start": 28,
@ -27,6 +32,7 @@ expression: actual
}
},
{
"commentStart": 43,
"end": 44,
"raw": "2",
"start": 43,
@ -43,6 +49,7 @@ expression: actual
"nonCodeNodes": {
"2": [
{
"commentStart": 58,
"end": 63,
"start": 58,
"type": "NonCodeNode",
@ -55,6 +62,7 @@ expression: actual
],
"3": [
{
"commentStart": 76,
"end": 81,
"start": 76,
"type": "NonCodeNode",
@ -82,6 +90,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 91,
"start": 0
}

View File

@ -1,24 +1,29 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 4,
"end": 80,
"id": {
"commentStart": 4,
"end": 9,
"name": "props",
"start": 4,
"type": "Identifier"
},
"init": {
"commentStart": 12,
"end": 80,
"nonCodeMeta": {
"nonCodeNodes": {
"1": [
{
"commentStart": 44,
"end": 52,
"start": 44,
"type": "NonCodeNode",
@ -34,8 +39,10 @@ expression: actual
},
"properties": [
{
"commentStart": 26,
"end": 30,
"key": {
"commentStart": 26,
"end": 27,
"name": "a",
"start": 26,
@ -44,6 +51,7 @@ expression: actual
"start": 26,
"type": "ObjectProperty",
"value": {
"commentStart": 29,
"end": 30,
"raw": "1",
"start": 29,
@ -56,8 +64,10 @@ expression: actual
}
},
{
"commentStart": 65,
"end": 69,
"key": {
"commentStart": 65,
"end": 66,
"name": "c",
"start": 65,
@ -66,6 +76,7 @@ expression: actual
"start": 65,
"type": "ObjectProperty",
"value": {
"commentStart": 68,
"end": 69,
"raw": "3",
"start": 68,
@ -92,6 +103,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 80,
"start": 0
}

View File

@ -1,24 +1,29 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 4,
"end": 79,
"id": {
"commentStart": 4,
"end": 9,
"name": "props",
"start": 4,
"type": "Identifier"
},
"init": {
"commentStart": 12,
"end": 79,
"nonCodeMeta": {
"nonCodeNodes": {
"1": [
{
"commentStart": 44,
"end": 52,
"start": 44,
"type": "NonCodeNode",
@ -34,8 +39,10 @@ expression: actual
},
"properties": [
{
"commentStart": 26,
"end": 30,
"key": {
"commentStart": 26,
"end": 27,
"name": "a",
"start": 26,
@ -44,6 +51,7 @@ expression: actual
"start": 26,
"type": "ObjectProperty",
"value": {
"commentStart": 29,
"end": 30,
"raw": "1",
"start": 29,
@ -56,8 +64,10 @@ expression: actual
}
},
{
"commentStart": 65,
"end": 69,
"key": {
"commentStart": 65,
"end": 66,
"name": "c",
"start": 65,
@ -66,6 +76,7 @@ expression: actual
"start": 65,
"type": "ObjectProperty",
"value": {
"commentStart": 68,
"end": 69,
"raw": "3",
"start": 68,
@ -92,6 +103,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 79,
"start": 0
}

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 30,
"id": {
"commentStart": 0,
"end": 5,
"name": "myVar",
"start": 0,
@ -16,6 +19,7 @@ expression: actual
"init": {
"arguments": [
{
"commentStart": 12,
"end": 13,
"raw": "5",
"start": 12,
@ -30,6 +34,7 @@ expression: actual
"argument": {
"arguments": [
{
"commentStart": 24,
"end": 25,
"raw": "5",
"start": 24,
@ -41,6 +46,7 @@ expression: actual
}
},
{
"commentStart": 27,
"end": 28,
"raw": "4",
"start": 27,
@ -53,16 +59,27 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 17,
"end": 23,
"name": "legLen",
"name": {
"commentStart": 17,
"end": 23,
"name": "legLen",
"start": 17,
"type": "Identifier"
},
"path": [],
"start": 17,
"type": "Identifier"
"type": "Name"
},
"commentStart": 17,
"end": 29,
"start": 17,
"type": "CallExpression",
"type": "CallExpression"
},
"commentStart": 16,
"end": 29,
"operator": "-",
"start": 16,
@ -71,11 +88,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 8,
"end": 11,
"name": "min",
"name": {
"commentStart": 8,
"end": 11,
"name": "min",
"start": 8,
"type": "Identifier"
},
"path": [],
"start": 8,
"type": "Identifier"
"type": "Name"
},
"commentStart": 8,
"end": 30,
"start": 8,
"type": "CallExpression",
@ -91,6 +118,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 30,
"start": 0
}

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 1,
"declaration": {
"commentStart": 1,
"end": 126,
"id": {
"commentStart": 1,
"end": 10,
"name": "sketch001",
"start": 1,
@ -18,6 +21,7 @@ expression: actual
{
"arguments": [
{
"commentStart": 27,
"end": 31,
"raw": "'XY'",
"start": 27,
@ -27,11 +31,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 13,
"end": 26,
"name": "startSketchOn",
"name": {
"commentStart": 13,
"end": 26,
"name": "startSketchOn",
"start": 13,
"type": "Identifier"
},
"path": [],
"start": 13,
"type": "Identifier"
"type": "Name"
},
"commentStart": 13,
"end": 32,
"start": 13,
"type": "CallExpression",
@ -40,6 +54,7 @@ expression: actual
{
"arguments": [
{
"commentStart": 124,
"end": 125,
"start": 124,
"type": "PipeSubstitution",
@ -47,22 +62,34 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 109,
"end": 123,
"name": "startProfileAt",
"name": {
"commentStart": 109,
"end": 123,
"name": "startProfileAt",
"start": 109,
"type": "Identifier"
},
"path": [],
"start": 109,
"type": "Identifier"
"type": "Name"
},
"commentStart": 109,
"end": 126,
"start": 109,
"type": "CallExpression",
"type": "CallExpression"
}
],
"commentStart": 13,
"end": 126,
"nonCodeMeta": {
"nonCodeNodes": {
"0": [
{
"commentStart": 35,
"end": 46,
"start": 35,
"type": "NonCodeNode",
@ -73,6 +100,7 @@ expression: actual
}
},
{
"commentStart": 49,
"end": 68,
"start": 49,
"type": "NonCodeNode",
@ -83,6 +111,7 @@ expression: actual
}
},
{
"commentStart": 71,
"end": 92,
"start": 71,
"type": "NonCodeNode",
@ -93,6 +122,7 @@ expression: actual
}
},
{
"commentStart": 95,
"end": 103,
"start": 95,
"type": "NonCodeNode",
@ -120,6 +150,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 127,
"start": 0
}

View File

@ -1,23 +1,29 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 1,
"declaration": {
"commentStart": 1,
"end": 25,
"id": {
"commentStart": 1,
"end": 5,
"name": "my14",
"start": 1,
"type": "Identifier"
},
"init": {
"commentStart": 8,
"end": 25,
"left": {
"commentStart": 8,
"end": 13,
"left": {
"commentStart": 8,
"end": 9,
"raw": "4",
"start": 8,
@ -30,6 +36,7 @@ expression: actual
},
"operator": "^",
"right": {
"commentStart": 12,
"end": 13,
"raw": "2",
"start": 12,
@ -46,10 +53,13 @@ expression: actual
},
"operator": "-",
"right": {
"commentStart": 16,
"end": 25,
"left": {
"commentStart": 16,
"end": 21,
"left": {
"commentStart": 16,
"end": 17,
"raw": "3",
"start": 16,
@ -62,6 +72,7 @@ expression: actual
},
"operator": "^",
"right": {
"commentStart": 20,
"end": 21,
"raw": "2",
"start": 20,
@ -78,6 +89,7 @@ expression: actual
},
"operator": "*",
"right": {
"commentStart": 24,
"end": 25,
"raw": "2",
"start": 24,
@ -106,6 +118,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 26,
"start": 0
}

View File

@ -1,20 +1,25 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 68,
"id": {
"commentStart": 0,
"end": 1,
"name": "x",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 4,
"cond": {
"commentStart": 7,
"end": 11,
"raw": "true",
"start": 7,
@ -28,8 +33,10 @@ expression: actual
"final_else": {
"body": [
{
"commentStart": 57,
"end": 58,
"expression": {
"commentStart": 57,
"end": 58,
"raw": "4",
"start": 57,
@ -45,6 +52,7 @@ expression: actual
"type": "ExpressionStatement"
}
],
"commentStart": 57,
"end": 67,
"start": 57
},
@ -52,8 +60,10 @@ expression: actual
"then_val": {
"body": [
{
"commentStart": 26,
"end": 27,
"expression": {
"commentStart": 26,
"end": 27,
"raw": "3",
"start": 26,
@ -69,6 +79,7 @@ expression: actual
"type": "ExpressionStatement"
}
],
"commentStart": 26,
"end": 36,
"start": 26
},
@ -85,6 +96,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 68,
"start": 0
}

View File

@ -1,20 +1,25 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 115,
"id": {
"commentStart": 0,
"end": 1,
"name": "x",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 4,
"cond": {
"commentStart": 7,
"end": 11,
"raw": "true",
"start": 7,
@ -25,22 +30,42 @@ expression: actual
"digest": null,
"else_ifs": [
{
"commentStart": 38,
"cond": {
"arguments": [
{
"abs_path": false,
"commentStart": 51,
"end": 57,
"name": "radius",
"name": {
"commentStart": 51,
"end": 57,
"name": "radius",
"start": 51,
"type": "Identifier"
},
"path": [],
"start": 51,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
],
"callee": {
"abs_path": false,
"commentStart": 46,
"end": 50,
"name": "func",
"name": {
"commentStart": 46,
"end": 50,
"name": "func",
"start": 46,
"type": "Identifier"
},
"path": [],
"start": 46,
"type": "Identifier"
"type": "Name"
},
"commentStart": 46,
"end": 58,
"start": 46,
"type": "CallExpression",
@ -52,8 +77,10 @@ expression: actual
"then_val": {
"body": [
{
"commentStart": 73,
"end": 74,
"expression": {
"commentStart": 73,
"end": 74,
"raw": "4",
"start": 73,
@ -69,6 +96,7 @@ expression: actual
"type": "ExpressionStatement"
}
],
"commentStart": 59,
"end": 83,
"start": 59
},
@ -79,8 +107,10 @@ expression: actual
"final_else": {
"body": [
{
"commentStart": 104,
"end": 105,
"expression": {
"commentStart": 104,
"end": 105,
"raw": "5",
"start": 104,
@ -96,6 +126,7 @@ expression: actual
"type": "ExpressionStatement"
}
],
"commentStart": 104,
"end": 114,
"start": 104
},
@ -103,8 +134,10 @@ expression: actual
"then_val": {
"body": [
{
"commentStart": 26,
"end": 27,
"expression": {
"commentStart": 26,
"end": 27,
"raw": "3",
"start": 26,
@ -120,6 +153,7 @@ expression: actual
"type": "ExpressionStatement"
}
],
"commentStart": 26,
"end": 36,
"start": 26
},
@ -136,6 +170,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 115,
"start": 0
}

View File

@ -1,21 +1,26 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 4,
"end": 14,
"id": {
"commentStart": 4,
"end": 5,
"name": "x",
"start": 4,
"type": "Identifier"
},
"init": {
"commentStart": 8,
"end": 14,
"left": {
"commentStart": 8,
"end": 9,
"raw": "3",
"start": 8,
@ -28,6 +33,7 @@ expression: actual
},
"operator": "==",
"right": {
"commentStart": 13,
"end": 14,
"raw": "3",
"start": 13,
@ -52,6 +58,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 14,
"start": 0
}

View File

@ -1,21 +1,26 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 4,
"end": 14,
"id": {
"commentStart": 4,
"end": 5,
"name": "x",
"start": 4,
"type": "Identifier"
},
"init": {
"commentStart": 8,
"end": 14,
"left": {
"commentStart": 8,
"end": 9,
"raw": "3",
"start": 8,
@ -28,6 +33,7 @@ expression: actual
},
"operator": "!=",
"right": {
"commentStart": 13,
"end": 14,
"raw": "3",
"start": 13,
@ -52,6 +58,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 14,
"start": 0
}

View File

@ -1,19 +1,23 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 5,
"id": {
"commentStart": 0,
"end": 1,
"name": "x",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 4,
"end": 5,
"raw": "4",
"start": 4,
@ -34,6 +38,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 5,
"start": 0
}

View File

@ -1,24 +1,30 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 36,
"id": {
"commentStart": 0,
"end": 3,
"name": "obj",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 6,
"end": 36,
"properties": [
{
"commentStart": 7,
"end": 24,
"key": {
"commentStart": 7,
"end": 13,
"name": "center",
"start": 7,
@ -27,8 +33,10 @@ expression: actual
"start": 7,
"type": "ObjectProperty",
"value": {
"commentStart": 16,
"elements": [
{
"commentStart": 17,
"end": 19,
"raw": "10",
"start": 17,
@ -40,6 +48,7 @@ expression: actual
}
},
{
"commentStart": 21,
"end": 23,
"raw": "10",
"start": 21,
@ -58,8 +67,10 @@ expression: actual
}
},
{
"commentStart": 26,
"end": 35,
"key": {
"commentStart": 26,
"end": 32,
"name": "radius",
"start": 26,
@ -68,6 +79,7 @@ expression: actual
"start": 26,
"type": "ObjectProperty",
"value": {
"commentStart": 34,
"end": 35,
"raw": "5",
"start": 34,
@ -94,6 +106,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 36,
"start": 0
}

View File

@ -1,19 +1,23 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 5,
"id": {
"commentStart": 0,
"end": 1,
"name": "x",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 4,
"end": 5,
"raw": "3",
"start": 4,
@ -34,20 +38,26 @@ expression: actual
"type": "VariableDeclaration"
},
{
"commentStart": 14,
"declaration": {
"commentStart": 14,
"end": 30,
"id": {
"commentStart": 14,
"end": 17,
"name": "obj",
"start": 14,
"type": "Identifier"
},
"init": {
"commentStart": 20,
"end": 30,
"properties": [
{
"commentStart": 22,
"end": 23,
"key": {
"commentStart": 22,
"end": 23,
"name": "x",
"start": 22,
@ -56,16 +66,27 @@ expression: actual
"start": 22,
"type": "ObjectProperty",
"value": {
"abs_path": false,
"commentStart": 22,
"end": 23,
"name": "x",
"name": {
"commentStart": 22,
"end": 23,
"name": "x",
"start": 22,
"type": "Identifier"
},
"path": [],
"start": 22,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
},
{
"commentStart": 25,
"end": 29,
"key": {
"commentStart": 25,
"end": 26,
"name": "y",
"start": 25,
@ -74,6 +95,7 @@ expression: actual
"start": 25,
"type": "ObjectProperty",
"value": {
"commentStart": 28,
"end": 29,
"raw": "4",
"start": 28,
@ -100,6 +122,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 30,
"start": 0
}

View File

@ -1,12 +1,14 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"end": 4,
"expression": {
"commentStart": 0,
"end": 4,
"raw": "true",
"start": 0,
@ -19,6 +21,7 @@ expression: actual
"type": "ExpressionStatement"
}
],
"commentStart": 0,
"end": 4,
"start": 0
}

View File

@ -1,23 +1,34 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"end": 5,
"expression": {
"abs_path": false,
"commentStart": 0,
"end": 5,
"name": "truee",
"name": {
"commentStart": 0,
"end": 5,
"name": "truee",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "ExpressionStatement",
"type": "ExpressionStatement"
}
],
"commentStart": 0,
"end": 5,
"start": 0
}

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 9,
"id": {
"commentStart": 0,
"end": 1,
"name": "x",
"start": 0,
@ -15,6 +18,7 @@ expression: actual
},
"init": {
"argument": {
"commentStart": 5,
"end": 9,
"raw": "true",
"start": 5,
@ -22,6 +26,7 @@ expression: actual
"type": "Literal",
"value": true
},
"commentStart": 4,
"end": 9,
"operator": "!",
"start": 4,
@ -38,6 +43,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 9,
"start": 0
}

View File

@ -1,21 +1,26 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 16,
"id": {
"commentStart": 0,
"end": 1,
"name": "x",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 4,
"end": 16,
"left": {
"commentStart": 4,
"end": 8,
"raw": "true",
"start": 4,
@ -25,6 +30,7 @@ expression: actual
},
"operator": "&",
"right": {
"commentStart": 11,
"end": 16,
"raw": "false",
"start": 11,
@ -46,6 +52,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 16,
"start": 0
}

View File

@ -1,21 +1,26 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 16,
"id": {
"commentStart": 0,
"end": 1,
"name": "x",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 4,
"end": 16,
"left": {
"commentStart": 4,
"end": 8,
"raw": "true",
"start": 4,
@ -25,6 +30,7 @@ expression: actual
},
"operator": "|",
"right": {
"commentStart": 11,
"end": 16,
"raw": "false",
"start": 11,
@ -46,6 +52,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 16,
"start": 0
}

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 29,
"id": {
"commentStart": 0,
"end": 5,
"name": "myVar",
"start": 0,
@ -19,6 +22,7 @@ expression: actual
"argument": {
"arguments": [
{
"commentStart": 20,
"end": 21,
"raw": "5",
"start": 20,
@ -30,6 +34,7 @@ expression: actual
}
},
{
"commentStart": 23,
"end": 24,
"raw": "4",
"start": 23,
@ -42,16 +47,27 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 13,
"end": 19,
"name": "legLen",
"name": {
"commentStart": 13,
"end": 19,
"name": "legLen",
"start": 13,
"type": "Identifier"
},
"path": [],
"start": 13,
"type": "Identifier"
"type": "Name"
},
"commentStart": 13,
"end": 25,
"start": 13,
"type": "CallExpression",
"type": "CallExpression"
},
"commentStart": 12,
"end": 25,
"operator": "-",
"start": 12,
@ -59,6 +75,7 @@ expression: actual
"type": "UnaryExpression"
},
{
"commentStart": 27,
"end": 28,
"raw": "5",
"start": 27,
@ -71,11 +88,21 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 8,
"end": 11,
"name": "min",
"name": {
"commentStart": 8,
"end": 11,
"name": "min",
"start": 8,
"type": "Identifier"
},
"path": [],
"start": 8,
"type": "Identifier"
"type": "Name"
},
"commentStart": 8,
"end": 29,
"start": 8,
"type": "CallExpression",
@ -91,6 +118,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 29,
"start": 0
}

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 30,
"id": {
"commentStart": 0,
"end": 5,
"name": "myVar",
"start": 0,
@ -16,8 +19,10 @@ expression: actual
"init": {
"body": [
{
"commentStart": 8,
"end": 13,
"left": {
"commentStart": 8,
"end": 9,
"raw": "5",
"start": 8,
@ -30,6 +35,7 @@ expression: actual
},
"operator": "+",
"right": {
"commentStart": 12,
"end": 13,
"raw": "6",
"start": 12,
@ -47,6 +53,7 @@ expression: actual
{
"arguments": [
{
"commentStart": 24,
"end": 26,
"raw": "45",
"start": 24,
@ -58,6 +65,7 @@ expression: actual
}
},
{
"commentStart": 28,
"end": 29,
"start": 28,
"type": "PipeSubstitution",
@ -65,17 +73,28 @@ expression: actual
}
],
"callee": {
"abs_path": false,
"commentStart": 17,
"end": 23,
"name": "myFunc",
"name": {
"commentStart": 17,
"end": 23,
"name": "myFunc",
"start": 17,
"type": "Identifier"
},
"path": [],
"start": 17,
"type": "Identifier"
"type": "Name"
},
"commentStart": 17,
"end": 30,
"start": 17,
"type": "CallExpression",
"type": "CallExpression"
}
],
"commentStart": 8,
"end": 30,
"start": 8,
"type": "PipeExpression",
@ -91,6 +110,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 30,
"start": 0
}

View File

@ -1,28 +1,42 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 21,
"id": {
"commentStart": 0,
"end": 1,
"name": "x",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 4,
"end": 21,
"left": {
"argument": {
"abs_path": false,
"commentStart": 5,
"end": 9,
"name": "leg2",
"name": {
"commentStart": 5,
"end": 9,
"name": "leg2",
"start": 5,
"type": "Identifier"
},
"path": [],
"start": 5,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
},
"commentStart": 4,
"end": 9,
"operator": "-",
"start": 4,
@ -31,11 +45,20 @@ expression: actual
},
"operator": "+",
"right": {
"abs_path": false,
"commentStart": 12,
"end": 21,
"name": "thickness",
"name": {
"commentStart": 12,
"end": 21,
"name": "thickness",
"start": 12,
"type": "Identifier"
},
"path": [],
"start": 12,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
},
"start": 4,
"type": "BinaryExpression",
@ -51,6 +74,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 21,
"start": 0
}

View File

@ -1,21 +1,26 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 4,
"end": 18,
"id": {
"commentStart": 4,
"end": 5,
"name": "x",
"start": 4,
"type": "Identifier"
},
"init": {
"commentStart": 8,
"end": 18,
"left": {
"commentStart": 8,
"end": 9,
"raw": "1",
"start": 8,
@ -28,8 +33,10 @@ expression: actual
},
"operator": "*",
"right": {
"commentStart": 13,
"end": 18,
"left": {
"commentStart": 13,
"end": 14,
"raw": "3",
"start": 13,
@ -42,6 +49,7 @@ expression: actual
},
"operator": "-",
"right": {
"commentStart": 17,
"end": 18,
"raw": "4",
"start": 17,
@ -70,6 +78,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 18,
"start": 0
}

View File

@ -1,19 +1,23 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 5,
"id": {
"commentStart": 0,
"end": 1,
"name": "x",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 4,
"end": 5,
"raw": "1",
"start": 4,
@ -34,11 +38,13 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 34,
"nonCodeMeta": {
"nonCodeNodes": {
"0": [
{
"commentStart": 5,
"end": 34,
"start": 5,
"type": "NonCodeNode",

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 3,
"end": 58,
"id": {
"commentStart": 3,
"end": 4,
"name": "x",
"start": 3,
@ -18,12 +21,22 @@ expression: actual
"body": [
{
"argument": {
"abs_path": false,
"commentStart": 30,
"end": 32,
"name": "sg",
"name": {
"commentStart": 30,
"end": 32,
"name": "sg",
"start": 30,
"type": "Identifier"
},
"path": [],
"start": 30,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
},
"commentStart": 23,
"end": 32,
"start": 23,
"type": "ReturnStatement",
@ -31,21 +44,33 @@ expression: actual
},
{
"argument": {
"abs_path": false,
"commentStart": 48,
"end": 50,
"name": "sg",
"name": {
"commentStart": 48,
"end": 50,
"name": "sg",
"start": 48,
"type": "Identifier"
},
"path": [],
"start": 48,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
},
"commentStart": 41,
"end": 50,
"start": 41,
"type": "ReturnStatement",
"type": "ReturnStatement"
}
],
"commentStart": 13,
"end": 58,
"start": 13
},
"commentStart": 7,
"end": 58,
"params": [],
"start": 7,
@ -62,6 +87,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 58,
"start": 0
}

View File

@ -1,24 +1,30 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 20,
"id": {
"commentStart": 0,
"end": 3,
"name": "obj",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 6,
"end": 20,
"properties": [
{
"commentStart": 8,
"end": 12,
"key": {
"commentStart": 8,
"end": 9,
"name": "a",
"start": 8,
@ -27,6 +33,7 @@ expression: actual
"start": 8,
"type": "ObjectProperty",
"value": {
"commentStart": 11,
"end": 12,
"raw": "1",
"start": 11,
@ -39,8 +46,10 @@ expression: actual
}
},
{
"commentStart": 14,
"end": 18,
"key": {
"commentStart": 14,
"end": 15,
"name": "b",
"start": 14,
@ -49,6 +58,7 @@ expression: actual
"start": 14,
"type": "ObjectProperty",
"value": {
"commentStart": 17,
"end": 18,
"raw": "2",
"start": 17,
@ -75,17 +85,22 @@ expression: actual
"type": "VariableDeclaration"
},
{
"commentStart": 25,
"declaration": {
"commentStart": 25,
"end": 43,
"id": {
"commentStart": 25,
"end": 31,
"name": "height",
"start": 25,
"type": "Identifier"
},
"init": {
"commentStart": 34,
"end": 43,
"left": {
"commentStart": 34,
"end": 35,
"raw": "1",
"start": 34,
@ -98,9 +113,11 @@ expression: actual
},
"operator": "-",
"right": {
"commentStart": 38,
"computed": false,
"end": 43,
"object": {
"commentStart": 38,
"end": 41,
"name": "obj",
"start": 38,
@ -108,6 +125,7 @@ expression: actual
"type": "Identifier"
},
"property": {
"commentStart": 42,
"end": 43,
"name": "a",
"start": 42,
@ -132,6 +150,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 43,
"start": 0
}

View File

@ -1,24 +1,30 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 20,
"id": {
"commentStart": 0,
"end": 3,
"name": "obj",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 6,
"end": 20,
"properties": [
{
"commentStart": 8,
"end": 12,
"key": {
"commentStart": 8,
"end": 9,
"name": "a",
"start": 8,
@ -27,6 +33,7 @@ expression: actual
"start": 8,
"type": "ObjectProperty",
"value": {
"commentStart": 11,
"end": 12,
"raw": "1",
"start": 11,
@ -39,8 +46,10 @@ expression: actual
}
},
{
"commentStart": 14,
"end": 18,
"key": {
"commentStart": 14,
"end": 15,
"name": "b",
"start": 14,
@ -49,6 +58,7 @@ expression: actual
"start": 14,
"type": "ObjectProperty",
"value": {
"commentStart": 17,
"end": 18,
"raw": "2",
"start": 17,
@ -75,17 +85,22 @@ expression: actual
"type": "VariableDeclaration"
},
{
"commentStart": 26,
"declaration": {
"commentStart": 26,
"end": 47,
"id": {
"commentStart": 26,
"end": 32,
"name": "height",
"start": 26,
"type": "Identifier"
},
"init": {
"commentStart": 35,
"end": 47,
"left": {
"commentStart": 35,
"end": 36,
"raw": "1",
"start": 35,
@ -98,9 +113,11 @@ expression: actual
},
"operator": "-",
"right": {
"commentStart": 39,
"computed": false,
"end": 47,
"object": {
"commentStart": 39,
"end": 42,
"name": "obj",
"start": 39,
@ -108,6 +125,7 @@ expression: actual
"type": "Identifier"
},
"property": {
"commentStart": 43,
"end": 46,
"raw": "\"a\"",
"start": 43,
@ -133,6 +151,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 47,
"start": 0
}

View File

@ -1,24 +1,30 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 20,
"id": {
"commentStart": 0,
"end": 3,
"name": "obj",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 6,
"end": 20,
"properties": [
{
"commentStart": 8,
"end": 12,
"key": {
"commentStart": 8,
"end": 9,
"name": "a",
"start": 8,
@ -27,6 +33,7 @@ expression: actual
"start": 8,
"type": "ObjectProperty",
"value": {
"commentStart": 11,
"end": 12,
"raw": "1",
"start": 11,
@ -39,8 +46,10 @@ expression: actual
}
},
{
"commentStart": 14,
"end": 18,
"key": {
"commentStart": 14,
"end": 15,
"name": "b",
"start": 14,
@ -49,6 +58,7 @@ expression: actual
"start": 14,
"type": "ObjectProperty",
"value": {
"commentStart": 17,
"end": 18,
"raw": "2",
"start": 17,
@ -75,20 +85,26 @@ expression: actual
"type": "VariableDeclaration"
},
{
"commentStart": 25,
"declaration": {
"commentStart": 25,
"end": 46,
"id": {
"commentStart": 25,
"end": 31,
"name": "height",
"start": 25,
"type": "Identifier"
},
"init": {
"commentStart": 34,
"end": 46,
"left": {
"commentStart": 34,
"computed": false,
"end": 42,
"object": {
"commentStart": 34,
"end": 37,
"name": "obj",
"start": 34,
@ -96,6 +112,7 @@ expression: actual
"type": "Identifier"
},
"property": {
"commentStart": 38,
"end": 41,
"raw": "\"a\"",
"start": 38,
@ -109,6 +126,7 @@ expression: actual
},
"operator": "-",
"right": {
"commentStart": 45,
"end": 46,
"raw": "1",
"start": 45,
@ -133,6 +151,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 46,
"start": 0
}

View File

@ -1,24 +1,30 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 20,
"id": {
"commentStart": 0,
"end": 3,
"name": "obj",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 6,
"end": 20,
"properties": [
{
"commentStart": 8,
"end": 12,
"key": {
"commentStart": 8,
"end": 9,
"name": "a",
"start": 8,
@ -27,6 +33,7 @@ expression: actual
"start": 8,
"type": "ObjectProperty",
"value": {
"commentStart": 11,
"end": 12,
"raw": "1",
"start": 11,
@ -39,8 +46,10 @@ expression: actual
}
},
{
"commentStart": 14,
"end": 18,
"key": {
"commentStart": 14,
"end": 15,
"name": "b",
"start": 14,
@ -49,6 +58,7 @@ expression: actual
"start": 14,
"type": "ObjectProperty",
"value": {
"commentStart": 17,
"end": 18,
"raw": "2",
"start": 17,
@ -75,19 +85,25 @@ expression: actual
"type": "VariableDeclaration"
},
{
"commentStart": 25,
"declaration": {
"commentStart": 25,
"end": 51,
"id": {
"commentStart": 25,
"end": 31,
"name": "height",
"start": 25,
"type": "Identifier"
},
"init": {
"commentStart": 34,
"elements": [
{
"commentStart": 35,
"end": 47,
"left": {
"commentStart": 35,
"end": 36,
"raw": "1",
"start": 35,
@ -100,9 +116,11 @@ expression: actual
},
"operator": "-",
"right": {
"commentStart": 39,
"computed": false,
"end": 47,
"object": {
"commentStart": 39,
"end": 42,
"name": "obj",
"start": 39,
@ -110,6 +128,7 @@ expression: actual
"type": "Identifier"
},
"property": {
"commentStart": 43,
"end": 46,
"raw": "\"a\"",
"start": 43,
@ -126,6 +145,7 @@ expression: actual
"type": "BinaryExpression"
},
{
"commentStart": 49,
"end": 50,
"raw": "0",
"start": 49,
@ -152,6 +172,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 51,
"start": 0
}

View File

@ -5,9 +5,12 @@ expression: actual
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 23,
"id": {
"commentStart": 0,
"end": 3,
"name": "val",
"start": 0,
@ -18,42 +21,72 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 10,
"end": 11,
"name": "x",
"start": 10,
"type": "Identifier"
},
"arg": {
"abs_path": false,
"commentStart": 14,
"end": 15,
"name": "a",
"name": {
"commentStart": 14,
"end": 15,
"name": "a",
"start": 14,
"type": "Identifier"
},
"path": [],
"start": 14,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
},
{
"type": "LabeledArg",
"label": {
"commentStart": 17,
"end": 18,
"name": "y",
"start": 17,
"type": "Identifier"
},
"arg": {
"abs_path": false,
"commentStart": 21,
"end": 22,
"name": "b",
"name": {
"commentStart": 21,
"end": 22,
"name": "b",
"start": 21,
"type": "Identifier"
},
"path": [],
"start": 21,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 6,
"end": 9,
"name": "foo",
"name": {
"commentStart": 6,
"end": 9,
"name": "foo",
"start": 6,
"type": "Identifier"
},
"path": [],
"start": 6,
"type": "Identifier"
"type": "Name"
},
"commentStart": 6,
"end": 23,
"start": 6,
"type": "CallExpressionKw",
@ -70,6 +103,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 23,
"start": 0
}

View File

@ -5,9 +5,12 @@ expression: actual
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 21,
"id": {
"commentStart": 0,
"end": 3,
"name": "val",
"start": 0,
@ -16,6 +19,7 @@ expression: actual
"init": {
"body": [
{
"commentStart": 6,
"end": 7,
"raw": "1",
"start": 6,
@ -31,26 +35,46 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 13,
"end": 16,
"name": "arg",
"start": 13,
"type": "Identifier"
},
"arg": {
"abs_path": false,
"commentStart": 19,
"end": 20,
"name": "x",
"name": {
"commentStart": 19,
"end": 20,
"name": "x",
"start": 19,
"type": "Identifier"
},
"path": [],
"start": 19,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 11,
"end": 12,
"name": "f",
"name": {
"commentStart": 11,
"end": 12,
"name": "f",
"start": 11,
"type": "Identifier"
},
"path": [],
"start": 11,
"type": "Identifier"
"type": "Name"
},
"commentStart": 11,
"end": 21,
"start": 11,
"type": "CallExpressionKw",
@ -58,6 +82,7 @@ expression: actual
"unlabeled": null
}
],
"commentStart": 6,
"end": 21,
"start": 6,
"type": "PipeExpression",
@ -73,6 +98,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 21,
"start": 0
}

View File

@ -5,9 +5,12 @@ expression: actual
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 87,
"id": {
"commentStart": 0,
"end": 3,
"name": "val",
"start": 0,
@ -18,58 +21,98 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 22,
"end": 25,
"name": "arg",
"start": 22,
"type": "Identifier"
},
"arg": {
"abs_path": false,
"commentStart": 28,
"end": 29,
"name": "x",
"name": {
"commentStart": 28,
"end": 29,
"name": "x",
"start": 28,
"type": "Identifier"
},
"path": [],
"start": 28,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
},
{
"type": "LabeledArg",
"label": {
"commentStart": 44,
"end": 47,
"name": "foo",
"start": 44,
"type": "Identifier"
},
"arg": {
"abs_path": false,
"commentStart": 50,
"end": 51,
"name": "x",
"name": {
"commentStart": 50,
"end": 51,
"name": "x",
"start": 50,
"type": "Identifier"
},
"path": [],
"start": 50,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
},
{
"type": "LabeledArg",
"label": {
"commentStart": 66,
"end": 69,
"name": "bar",
"start": 66,
"type": "Identifier"
},
"arg": {
"abs_path": false,
"commentStart": 72,
"end": 73,
"name": "x",
"name": {
"commentStart": 72,
"end": 73,
"name": "x",
"start": 72,
"type": "Identifier"
},
"path": [],
"start": 72,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 6,
"end": 7,
"name": "f",
"name": {
"commentStart": 6,
"end": 7,
"name": "f",
"start": 6,
"type": "Identifier"
},
"path": [],
"start": 6,
"type": "Identifier"
"type": "Name"
},
"commentStart": 6,
"end": 87,
"start": 6,
"type": "CallExpressionKw",
@ -86,6 +129,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 87,
"start": 0
}

View File

@ -5,9 +5,12 @@ expression: actual
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 90,
"id": {
"commentStart": 0,
"end": 3,
"name": "val",
"start": 0,
@ -18,47 +21,78 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 22,
"end": 25,
"name": "arg",
"start": 22,
"type": "Identifier"
},
"arg": {
"abs_path": false,
"commentStart": 28,
"end": 29,
"name": "x",
"name": {
"commentStart": 28,
"end": 29,
"name": "x",
"start": 28,
"type": "Identifier"
},
"path": [],
"start": 28,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
},
{
"type": "LabeledArg",
"label": {
"commentStart": 69,
"end": 72,
"name": "bar",
"start": 69,
"type": "Identifier"
},
"arg": {
"abs_path": false,
"commentStart": 75,
"end": 76,
"name": "x",
"name": {
"commentStart": 75,
"end": 76,
"name": "x",
"start": 75,
"type": "Identifier"
},
"path": [],
"start": 75,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 6,
"end": 7,
"name": "f",
"name": {
"commentStart": 6,
"end": 7,
"name": "f",
"start": 6,
"type": "Identifier"
},
"path": [],
"start": 6,
"type": "Identifier"
"type": "Name"
},
"commentStart": 6,
"end": 90,
"nonCodeMeta": {
"nonCodeNodes": {
"1": [
{
"commentStart": 44,
"end": 55,
"start": 44,
"type": "NonCodeNode",
@ -87,6 +121,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 90,
"start": 0
}

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 3,
"end": 25,
"id": {
"commentStart": 3,
"end": 6,
"name": "foo",
"start": 3,
@ -18,6 +21,7 @@ expression: actual
"body": [
{
"argument": {
"commentStart": 22,
"end": 23,
"raw": "1",
"start": 22,
@ -28,20 +32,24 @@ expression: actual
"suffix": "None"
}
},
"commentStart": 15,
"end": 23,
"start": 15,
"type": "ReturnStatement",
"type": "ReturnStatement"
}
],
"commentStart": 13,
"end": 25,
"start": 13
},
"commentStart": 6,
"end": 25,
"params": [
{
"type": "Parameter",
"identifier": {
"commentStart": 7,
"end": 8,
"name": "x",
"start": 7,
@ -51,6 +59,7 @@ expression: actual
{
"type": "Parameter",
"identifier": {
"commentStart": 10,
"end": 11,
"name": "y",
"start": 10,
@ -72,6 +81,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 25,
"start": 0
}

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 3,
"end": 26,
"id": {
"commentStart": 3,
"end": 6,
"name": "foo",
"start": 3,
@ -18,6 +21,7 @@ expression: actual
"body": [
{
"argument": {
"commentStart": 23,
"end": 24,
"raw": "1",
"start": 23,
@ -28,20 +32,24 @@ expression: actual
"suffix": "None"
}
},
"commentStart": 16,
"end": 24,
"start": 16,
"type": "ReturnStatement",
"type": "ReturnStatement"
}
],
"commentStart": 14,
"end": 26,
"start": 14
},
"commentStart": 6,
"end": 26,
"params": [
{
"type": "Parameter",
"identifier": {
"commentStart": 8,
"end": 9,
"name": "x",
"start": 8,
@ -52,6 +60,7 @@ expression: actual
{
"type": "Parameter",
"identifier": {
"commentStart": 11,
"end": 12,
"name": "y",
"start": 11,
@ -73,6 +82,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 26,
"start": 0
}

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 3,
"end": 35,
"id": {
"commentStart": 3,
"end": 6,
"name": "foo",
"start": 3,
@ -18,6 +21,7 @@ expression: actual
"body": [
{
"argument": {
"commentStart": 32,
"end": 33,
"raw": "1",
"start": 32,
@ -28,26 +32,31 @@ expression: actual
"suffix": "None"
}
},
"commentStart": 25,
"end": 33,
"start": 25,
"type": "ReturnStatement",
"type": "ReturnStatement"
}
],
"commentStart": 23,
"end": 35,
"start": 23
},
"commentStart": 6,
"end": 35,
"params": [
{
"type": "Parameter",
"identifier": {
"commentStart": 7,
"end": 8,
"name": "x",
"start": 7,
"type": "Identifier"
},
"default_value": {
"commentStart": 20,
"end": 21,
"raw": "2",
"start": 20,
@ -74,6 +83,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 35,
"start": 0
}

View File

@ -1,13 +1,16 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 3,
"end": 27,
"id": {
"commentStart": 3,
"end": 6,
"name": "foo",
"start": 3,
@ -18,6 +21,7 @@ expression: actual
"body": [
{
"argument": {
"commentStart": 24,
"end": 25,
"raw": "1",
"start": 24,
@ -28,26 +32,31 @@ expression: actual
"suffix": "None"
}
},
"commentStart": 17,
"end": 25,
"start": 17,
"type": "ReturnStatement",
"type": "ReturnStatement"
}
],
"commentStart": 15,
"end": 27,
"start": 15
},
"commentStart": 6,
"end": 27,
"params": [
{
"type": "Parameter",
"identifier": {
"commentStart": 7,
"end": 8,
"name": "x",
"start": 7,
"type": "Identifier"
},
"default_value": {
"commentStart": 12,
"end": 13,
"raw": "2",
"start": 12,
@ -74,6 +83,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 27,
"start": 0
}

View File

@ -5,9 +5,12 @@ expression: actual
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 19,
"id": {
"commentStart": 0,
"end": 3,
"name": "val",
"start": 0,
@ -18,36 +21,65 @@ expression: actual
{
"type": "LabeledArg",
"label": {
"commentStart": 13,
"end": 14,
"name": "y",
"start": 13,
"type": "Identifier"
},
"arg": {
"abs_path": false,
"commentStart": 17,
"end": 18,
"name": "z",
"name": {
"commentStart": 17,
"end": 18,
"name": "z",
"start": 17,
"type": "Identifier"
},
"path": [],
"start": 17,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 6,
"end": 9,
"name": "foo",
"name": {
"commentStart": 6,
"end": 9,
"name": "foo",
"start": 6,
"type": "Identifier"
},
"path": [],
"start": 6,
"type": "Identifier"
"type": "Name"
},
"commentStart": 6,
"end": 19,
"start": 6,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": {
"abs_path": false,
"commentStart": 10,
"end": 11,
"name": "x",
"name": {
"commentStart": 10,
"end": 11,
"name": "x",
"start": 10,
"type": "Identifier"
},
"path": [],
"start": 10,
"type": "Identifier",
"type": "Identifier"
"type": "Name",
"type": "Name"
}
},
"start": 0,
@ -60,6 +92,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 19,
"start": 0
}

View File

@ -1,24 +1,30 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 20,
"id": {
"commentStart": 0,
"end": 3,
"name": "obj",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 6,
"end": 20,
"properties": [
{
"commentStart": 8,
"end": 12,
"key": {
"commentStart": 8,
"end": 9,
"name": "a",
"start": 8,
@ -27,6 +33,7 @@ expression: actual
"start": 8,
"type": "ObjectProperty",
"value": {
"commentStart": 11,
"end": 12,
"raw": "1",
"start": 11,
@ -39,8 +46,10 @@ expression: actual
}
},
{
"commentStart": 14,
"end": 18,
"key": {
"commentStart": 14,
"end": 15,
"name": "b",
"start": 14,
@ -49,6 +58,7 @@ expression: actual
"start": 14,
"type": "ObjectProperty",
"value": {
"commentStart": 17,
"end": 18,
"raw": "2",
"start": 17,
@ -75,22 +85,29 @@ expression: actual
"type": "VariableDeclaration"
},
{
"commentStart": 25,
"declaration": {
"commentStart": 25,
"end": 51,
"id": {
"commentStart": 25,
"end": 31,
"name": "height",
"start": 25,
"type": "Identifier"
},
"init": {
"commentStart": 34,
"elements": [
{
"commentStart": 35,
"end": 47,
"left": {
"commentStart": 35,
"computed": false,
"end": 43,
"object": {
"commentStart": 35,
"end": 38,
"name": "obj",
"start": 35,
@ -98,6 +115,7 @@ expression: actual
"type": "Identifier"
},
"property": {
"commentStart": 39,
"end": 42,
"raw": "\"a\"",
"start": 39,
@ -111,6 +129,7 @@ expression: actual
},
"operator": "-",
"right": {
"commentStart": 46,
"end": 47,
"raw": "1",
"start": 46,
@ -126,6 +145,7 @@ expression: actual
"type": "BinaryExpression"
},
{
"commentStart": 49,
"end": 50,
"raw": "0",
"start": 49,
@ -152,6 +172,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 51,
"start": 0
}

View File

@ -1,24 +1,30 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 20,
"id": {
"commentStart": 0,
"end": 3,
"name": "obj",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 6,
"end": 20,
"properties": [
{
"commentStart": 8,
"end": 12,
"key": {
"commentStart": 8,
"end": 9,
"name": "a",
"start": 8,
@ -27,6 +33,7 @@ expression: actual
"start": 8,
"type": "ObjectProperty",
"value": {
"commentStart": 11,
"end": 12,
"raw": "1",
"start": 11,
@ -39,8 +46,10 @@ expression: actual
}
},
{
"commentStart": 14,
"end": 18,
"key": {
"commentStart": 14,
"end": 15,
"name": "b",
"start": 14,
@ -49,6 +58,7 @@ expression: actual
"start": 14,
"type": "ObjectProperty",
"value": {
"commentStart": 17,
"end": 18,
"raw": "2",
"start": 17,
@ -75,22 +85,29 @@ expression: actual
"type": "VariableDeclaration"
},
{
"commentStart": 25,
"declaration": {
"commentStart": 25,
"end": 50,
"id": {
"commentStart": 25,
"end": 31,
"name": "height",
"start": 25,
"type": "Identifier"
},
"init": {
"commentStart": 34,
"elements": [
{
"commentStart": 35,
"end": 46,
"left": {
"commentStart": 35,
"computed": false,
"end": 43,
"object": {
"commentStart": 35,
"end": 38,
"name": "obj",
"start": 35,
@ -98,6 +115,7 @@ expression: actual
"type": "Identifier"
},
"property": {
"commentStart": 39,
"end": 42,
"raw": "\"a\"",
"start": 39,
@ -111,6 +129,7 @@ expression: actual
},
"operator": "-",
"right": {
"commentStart": 45,
"end": 46,
"raw": "1",
"start": 45,
@ -126,6 +145,7 @@ expression: actual
"type": "BinaryExpression"
},
{
"commentStart": 48,
"end": 49,
"raw": "0",
"start": 48,
@ -152,6 +172,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 50,
"start": 0
}

View File

@ -1,21 +1,26 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 18,
"id": {
"commentStart": 0,
"end": 6,
"name": "height",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 9,
"end": 18,
"left": {
"commentStart": 9,
"end": 10,
"raw": "1",
"start": 9,
@ -28,9 +33,11 @@ expression: actual
},
"operator": "-",
"right": {
"commentStart": 13,
"computed": false,
"end": 18,
"object": {
"commentStart": 13,
"end": 16,
"name": "obj",
"start": 13,
@ -38,6 +45,7 @@ expression: actual
"type": "Identifier"
},
"property": {
"commentStart": 17,
"end": 18,
"name": "a",
"start": 17,
@ -62,6 +70,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 18,
"start": 0
}

View File

@ -1,23 +1,29 @@
---
source: kcl/src/parsing/parser.rs
source: kcl-lib/src/parsing/parser.rs
expression: actual
---
{
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 15,
"id": {
"commentStart": 0,
"end": 3,
"name": "six",
"start": 0,
"type": "Identifier"
},
"init": {
"commentStart": 6,
"end": 15,
"left": {
"commentStart": 6,
"end": 11,
"left": {
"commentStart": 6,
"end": 7,
"raw": "1",
"start": 6,
@ -30,6 +36,7 @@ expression: actual
},
"operator": "+",
"right": {
"commentStart": 10,
"end": 11,
"raw": "2",
"start": 10,
@ -46,6 +53,7 @@ expression: actual
},
"operator": "+",
"right": {
"commentStart": 14,
"end": 15,
"raw": "3",
"start": 14,
@ -70,6 +78,7 @@ expression: actual
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 15,
"start": 0
}

Some files were not shown because too many files have changed in this diff Show More