More types stuff (#5901)
* parse union and fancy array types Signed-off-by: Nick Cameron <nrc@ncameron.org> * type aliases Signed-off-by: Nick Cameron <nrc@ncameron.org> * Treat Helix and Face as primitive types Signed-off-by: Nick Cameron <nrc@ncameron.org> * code motion: factor our execution::types module Signed-off-by: Nick Cameron <nrc@ncameron.org> * Tests for type coercion and subtyping Signed-off-by: Nick Cameron <nrc@ncameron.org> * Add Point2D/3D to std Signed-off-by: Nick Cameron <nrc@ncameron.org> * Rebasing and fixes Signed-off-by: Nick Cameron <nrc@ncameron.org> --------- Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
@ -8,9 +8,10 @@ use crate::{
|
||||
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,
|
||||
},
|
||||
@ -29,6 +30,8 @@ use crate::{
|
||||
CompilationError,
|
||||
};
|
||||
|
||||
use super::kcl_value::TypeDef;
|
||||
|
||||
enum StatementKind<'a> {
|
||||
Declaration { name: &'a str },
|
||||
Expression,
|
||||
@ -304,8 +307,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
|
||||
@ -324,12 +328,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;
|
||||
@ -646,30 +678,28 @@ 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 {
|
||||
|
Reference in New Issue
Block a user