Support types in the standard library (#5651)

* Parse an unparse type decls (and refactor impl attributes slightly)

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Remove special treatment of geometric types from parser and executor

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Generate docs for std types

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Hover tool-tips for types and fixup the frontend

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Fixes

Signed-off-by: Nick Cameron <nrc@ncameron.org>

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
Nick Cameron
2025-03-08 03:53:34 +13:00
committed by GitHub
parent 79d37d360a
commit 5d25f4a0e5
175 changed files with 2023 additions and 1647 deletions

View File

@ -285,6 +285,50 @@ impl ExecutorContext {
}
last_expr = None;
}
BodyItem::TypeDeclaration(ty) => {
let metadata = Metadata::from(&**ty);
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 {
Some(p) => p,
None => {
return Err(KclError::Semantic(KclErrorDetails {
message: "User-defined types are not yet supported.".to_owned(),
source_ranges: vec![metadata.source_range],
}));
}
};
let value = KclValue::Type {
value: Some(crate::std::std_ty(std_path, &ty.name.name)),
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],
})
})?;
}
// 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],
}));
}
}
last_expr = None;
}
BodyItem::ReturnStatement(return_statement) => {
let metadata = Metadata::from(return_statement);
@ -519,21 +563,9 @@ impl ExecutorContext {
}
Expr::BinaryExpression(binary_expression) => binary_expression.get_result(exec_state, self).await?,
Expr::FunctionExpression(function_expression) => {
let mut rust_impl = false;
for attr in annotations {
if attr.name.is_some() || attr.properties.is_none() {
continue;
}
for p in attr.properties.as_ref().unwrap() {
if &*p.key.name == "impl" {
if let Some(s) = p.value.ident_name() {
if s == "std_rust" {
rust_impl = true;
}
}
}
}
}
let rust_impl = annotations::get_impl(annotations, metadata.source_range)?
.map(|s| s == annotations::Impl::Rust)
.unwrap_or(false);
if rust_impl {
if let Some(std_path) = &exec_state.mod_local.settings.std_path {
@ -623,7 +655,12 @@ impl ExecutorContext {
}
fn coerce(value: KclValue, ty: &Node<Type>, exec_state: &mut ExecState) -> Result<KclValue, KclValue> {
let ty = RuntimeType::from_parsed(ty.inner.clone(), &exec_state.mod_local.settings).ok_or_else(|| value.clone())?;
let ty = RuntimeType::from_parsed(ty.inner.clone(), exec_state, (&value).into())
.map_err(|e| {
exec_state.err(e);
value.clone()
})?
.ok_or_else(|| value.clone())?;
if value.has_type(&ty) {
return Ok(value);
}