Merge branch 'main' into kurt-6846
This commit is contained in:
40
.github/ci-cd-scripts/upload-results.sh
vendored
40
.github/ci-cd-scripts/upload-results.sh
vendored
@ -1,13 +1,41 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME:-}}"
|
||||
COMMIT="${CI_COMMIT_SHA:-${GITHUB_SHA:-}}"
|
||||
if [ -z "${TAB_API_URL:-}" ] || [ -z "${TAB_API_KEY:-}" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
curl --request POST \
|
||||
project="https://github.com/KittyCAD/modeling-app"
|
||||
branch="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME:-}}"
|
||||
commit="${CI_COMMIT_SHA:-${GITHUB_SHA:-}}"
|
||||
|
||||
echo "Uploading batch results"
|
||||
curl --silent --request POST \
|
||||
--header "X-API-Key: ${TAB_API_KEY}" \
|
||||
--form "project=https://github.com/KittyCAD/modeling-app" \
|
||||
--form "branch=${BRANCH}" \
|
||||
--form "commit=${COMMIT}" \
|
||||
--form "project=${project}" \
|
||||
--form "branch=${branch}" \
|
||||
--form "commit=${commit}" \
|
||||
--form "tests=@test-results/junit.xml" \
|
||||
--form "CI_COMMIT_SHA=${CI_COMMIT_SHA:-}" \
|
||||
--form "CI_PR_NUMBER=${CI_PR_NUMBER:-}" \
|
||||
--form "GITHUB_BASE_REF=${GITHUB_BASE_REF:-}" \
|
||||
--form "GITHUB_EVENT_NAME=${GITHUB_EVENT_NAME:-}" \
|
||||
--form "GITHUB_HEAD_REF=${GITHUB_HEAD_REF:-}" \
|
||||
--form "GITHUB_REF_NAME=${GITHUB_REF_NAME:-}" \
|
||||
--form "GITHUB_REF=${GITHUB_REF:-}" \
|
||||
--form "GITHUB_SHA=${GITHUB_SHA:-}" \
|
||||
--form "GITHUB_WORKFLOW=${GITHUB_WORKFLOW:-}" \
|
||||
--form "RUNNER_ARCH=${RUNNER_ARCH:-}" \
|
||||
${TAB_API_URL}/api/results/bulk
|
||||
|
||||
echo
|
||||
echo "Sharing updated report"
|
||||
curl --silent --request POST \
|
||||
--header "Content-Type: application/json" \
|
||||
--header "X-API-Key: ${TAB_API_KEY}" \
|
||||
--data "{
|
||||
\"project\": \"${project}\",
|
||||
\"branch\": \"${branch}\",
|
||||
\"commit\": \"${commit}\"
|
||||
}" \
|
||||
${TAB_API_URL}/api/share
|
||||
|
2
.github/workflows/cargo-test.yml
vendored
2
.github/workflows/cargo-test.yml
vendored
@ -188,6 +188,8 @@ jobs:
|
||||
env:
|
||||
TAB_API_URL: ${{ secrets.TAB_API_URL }}
|
||||
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
||||
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
run-wasm-tests:
|
||||
name: Run wasm tests
|
||||
strategy:
|
||||
|
@ -18,10 +18,10 @@ use crate::{
|
||||
},
|
||||
modules::{ModuleId, ModulePath, ModuleRepr},
|
||||
parsing::ast::types::{
|
||||
Annotation, ArrayExpression, ArrayRangeExpression, BinaryExpression, BinaryOperator, BinaryPart, BodyItem,
|
||||
CallExpressionKw, Expr, FunctionExpression, IfExpression, ImportPath, ImportSelector, ItemVisibility,
|
||||
LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, Name, Node, NodeRef, ObjectExpression,
|
||||
PipeExpression, Program, TagDeclarator, Type, UnaryExpression, UnaryOperator,
|
||||
Annotation, ArrayExpression, ArrayRangeExpression, AscribedExpression, BinaryExpression, BinaryOperator,
|
||||
BinaryPart, BodyItem, CallExpressionKw, Expr, FunctionExpression, IfExpression, ImportPath, ImportSelector,
|
||||
ItemVisibility, LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, Name, Node, NodeRef,
|
||||
ObjectExpression, PipeExpression, Program, TagDeclarator, Type, UnaryExpression, UnaryOperator,
|
||||
},
|
||||
source_range::SourceRange,
|
||||
std::{
|
||||
@ -707,17 +707,25 @@ impl ExecutorContext {
|
||||
// TODO this lets us use the label as a variable name, but not as a tag in most cases
|
||||
result
|
||||
}
|
||||
Expr::AscribedExpression(expr) => {
|
||||
let result = self
|
||||
.execute_expr(&expr.expr, exec_state, metadata, &[], statement_kind)
|
||||
.await?;
|
||||
apply_ascription(&result, &expr.ty, exec_state, expr.into())?
|
||||
}
|
||||
Expr::AscribedExpression(expr) => expr.get_result(exec_state, self).await?,
|
||||
};
|
||||
Ok(item)
|
||||
}
|
||||
}
|
||||
|
||||
impl Node<AscribedExpression> {
|
||||
#[async_recursion]
|
||||
pub async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
|
||||
let metadata = Metadata {
|
||||
source_range: SourceRange::from(self),
|
||||
};
|
||||
let result = ctx
|
||||
.execute_expr(&self.expr, exec_state, &metadata, &[], StatementKind::Expression)
|
||||
.await?;
|
||||
apply_ascription(&result, &self.ty, exec_state, self.into())
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_ascription(
|
||||
value: &KclValue,
|
||||
ty: &Node<Type>,
|
||||
@ -758,6 +766,7 @@ impl BinaryPart {
|
||||
BinaryPart::UnaryExpression(unary_expression) => unary_expression.get_result(exec_state, ctx).await,
|
||||
BinaryPart::MemberExpression(member_expression) => member_expression.get_result(exec_state),
|
||||
BinaryPart::IfExpression(e) => e.get_result(exec_state, ctx).await,
|
||||
BinaryPart::AscribedExpression(e) => e.get_result(exec_state, ctx).await,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2638,4 +2647,10 @@ sketch001 = startSketchOn(XY)
|
||||
|
||||
parse_execute(ast).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn ascription_in_binop() {
|
||||
let ast = r#"foo = tan(0): number(rad) - 4deg"#;
|
||||
parse_execute(ast).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -150,6 +150,7 @@ impl BinaryPart {
|
||||
unary_expression.get_hover_value_for_position(pos, code, opts)
|
||||
}
|
||||
BinaryPart::IfExpression(e) => e.get_hover_value_for_position(pos, code, opts),
|
||||
BinaryPart::AscribedExpression(e) => e.expr.get_hover_value_for_position(pos, code, opts),
|
||||
BinaryPart::MemberExpression(member_expression) => {
|
||||
member_expression.get_hover_value_for_position(pos, code, opts)
|
||||
}
|
||||
|
@ -162,6 +162,7 @@ impl BinaryPart {
|
||||
BinaryPart::UnaryExpression(ue) => ue.compute_digest(),
|
||||
BinaryPart::MemberExpression(me) => me.compute_digest(),
|
||||
BinaryPart::IfExpression(e) => e.compute_digest(),
|
||||
BinaryPart::AscribedExpression(e) => e.compute_digest(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ impl BinaryPart {
|
||||
BinaryPart::UnaryExpression(unary_expression) => unary_expression.module_id,
|
||||
BinaryPart::MemberExpression(member_expression) => member_expression.module_id,
|
||||
BinaryPart::IfExpression(e) => e.module_id,
|
||||
BinaryPart::AscribedExpression(e) => e.module_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1215,6 +1215,7 @@ impl From<&BinaryPart> for Expr {
|
||||
BinaryPart::UnaryExpression(unary_expression) => Expr::UnaryExpression(unary_expression.clone()),
|
||||
BinaryPart::MemberExpression(member_expression) => Expr::MemberExpression(member_expression.clone()),
|
||||
BinaryPart::IfExpression(e) => Expr::IfExpression(e.clone()),
|
||||
BinaryPart::AscribedExpression(e) => Expr::AscribedExpression(e.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1281,6 +1282,7 @@ pub enum BinaryPart {
|
||||
UnaryExpression(BoxNode<UnaryExpression>),
|
||||
MemberExpression(BoxNode<MemberExpression>),
|
||||
IfExpression(BoxNode<IfExpression>),
|
||||
AscribedExpression(BoxNode<AscribedExpression>),
|
||||
}
|
||||
|
||||
impl From<BinaryPart> for SourceRange {
|
||||
@ -1306,6 +1308,7 @@ impl BinaryPart {
|
||||
BinaryPart::UnaryExpression(unary_expression) => unary_expression.get_constraint_level(),
|
||||
BinaryPart::MemberExpression(member_expression) => member_expression.get_constraint_level(),
|
||||
BinaryPart::IfExpression(e) => e.get_constraint_level(),
|
||||
BinaryPart::AscribedExpression(e) => e.expr.get_constraint_level(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1324,6 +1327,7 @@ impl BinaryPart {
|
||||
}
|
||||
BinaryPart::MemberExpression(_) => {}
|
||||
BinaryPart::IfExpression(e) => e.replace_value(source_range, new_value),
|
||||
BinaryPart::AscribedExpression(e) => e.expr.replace_value(source_range, new_value),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1336,6 +1340,7 @@ impl BinaryPart {
|
||||
BinaryPart::UnaryExpression(unary_expression) => unary_expression.start,
|
||||
BinaryPart::MemberExpression(member_expression) => member_expression.start,
|
||||
BinaryPart::IfExpression(e) => e.start,
|
||||
BinaryPart::AscribedExpression(e) => e.start,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1348,6 +1353,7 @@ impl BinaryPart {
|
||||
BinaryPart::UnaryExpression(unary_expression) => unary_expression.end,
|
||||
BinaryPart::MemberExpression(member_expression) => member_expression.end,
|
||||
BinaryPart::IfExpression(e) => e.end,
|
||||
BinaryPart::AscribedExpression(e) => e.end,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1369,6 +1375,7 @@ impl BinaryPart {
|
||||
member_expression.rename_identifiers(old_name, new_name)
|
||||
}
|
||||
BinaryPart::IfExpression(ref mut if_expression) => if_expression.rename_identifiers(old_name, new_name),
|
||||
BinaryPart::AscribedExpression(ref mut e) => e.expr.rename_identifiers(old_name, new_name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -582,6 +582,26 @@ fn binary_operator(i: &mut TokenSlice) -> PResult<BinaryOperator> {
|
||||
"<=" => BinaryOperator::Lte,
|
||||
"|" => BinaryOperator::Or,
|
||||
"&" => BinaryOperator::And,
|
||||
"||" => {
|
||||
ParseContext::err(
|
||||
CompilationError::err(
|
||||
token.as_source_range(),
|
||||
"`||` is not an operator, did you mean to use `|`?",
|
||||
)
|
||||
.with_suggestion("Replace `||` with `|`", "|", None, Tag::None),
|
||||
);
|
||||
BinaryOperator::Or
|
||||
}
|
||||
"&&" => {
|
||||
ParseContext::err(
|
||||
CompilationError::err(
|
||||
token.as_source_range(),
|
||||
"`&&` is not an operator, did you mean to use `&`?",
|
||||
)
|
||||
.with_suggestion("Replace `&&` with `&`", "&", None, Tag::None),
|
||||
);
|
||||
BinaryOperator::And
|
||||
}
|
||||
_ => {
|
||||
return Err(CompilationError::fatal(
|
||||
token.as_source_range(),
|
||||
@ -611,8 +631,7 @@ fn operand(i: &mut TokenSlice) -> PResult<BinaryPart> {
|
||||
| Expr::ArrayExpression(_)
|
||||
| Expr::ArrayRangeExpression(_)
|
||||
| Expr::ObjectExpression(_)
|
||||
| Expr::LabelledExpression(..)
|
||||
| Expr::AscribedExpression(..) => return Err(CompilationError::fatal(source_range, TODO_783)),
|
||||
| Expr::LabelledExpression(..) => return Err(CompilationError::fatal(source_range, TODO_783)),
|
||||
Expr::None(_) => {
|
||||
return Err(CompilationError::fatal(
|
||||
source_range,
|
||||
@ -638,6 +657,7 @@ fn operand(i: &mut TokenSlice) -> PResult<BinaryPart> {
|
||||
Expr::CallExpressionKw(x) => BinaryPart::CallExpressionKw(x),
|
||||
Expr::MemberExpression(x) => BinaryPart::MemberExpression(x),
|
||||
Expr::IfExpression(x) => BinaryPart::IfExpression(x),
|
||||
Expr::AscribedExpression(x) => BinaryPart::AscribedExpression(x),
|
||||
};
|
||||
Ok(expr)
|
||||
})
|
||||
@ -2048,7 +2068,7 @@ fn expr_allowed_in_pipe_expr(i: &mut TokenSlice) -> PResult<Expr> {
|
||||
}
|
||||
|
||||
fn possible_operands(i: &mut TokenSlice) -> PResult<Expr> {
|
||||
alt((
|
||||
let mut expr = alt((
|
||||
unary_expression.map(Box::new).map(Expr::UnaryExpression),
|
||||
bool_value.map(Expr::Literal),
|
||||
member_expression.map(Box::new).map(Expr::MemberExpression),
|
||||
@ -2061,7 +2081,14 @@ fn possible_operands(i: &mut TokenSlice) -> PResult<Expr> {
|
||||
.context(expected(
|
||||
"a KCL value which can be used as an argument/operand to an operator",
|
||||
))
|
||||
.parse_next(i)
|
||||
.parse_next(i)?;
|
||||
|
||||
let ty = opt((colon, opt(whitespace), argument_type)).parse_next(i)?;
|
||||
if let Some((_, _, ty)) = ty {
|
||||
expr = Expr::AscribedExpression(Box::new(AscribedExpression::new(expr, ty)))
|
||||
}
|
||||
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
/// Parse an item visibility specifier, e.g. export.
|
||||
@ -4511,6 +4538,13 @@ export fn cos(num: number(rad)): number(_) {}"#;
|
||||
assert_eq!(errs.len(), 3, "found: {errs:#?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_double_and() {
|
||||
let (_, errs) = assert_no_fatal("foo = true && false");
|
||||
assert_eq!(errs.len(), 1, "found: {errs:#?}");
|
||||
assert!(errs[0].message.contains("`&&`") && errs[0].message.contains("`&`") && errs[0].suggestion.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_type_ascription() {
|
||||
let (_, errs) = assert_no_fatal("a + b: number");
|
||||
|
@ -181,7 +181,7 @@ fn word(i: &mut Input<'_>) -> PResult<Token> {
|
||||
|
||||
fn operator(i: &mut Input<'_>) -> PResult<Token> {
|
||||
let (value, range) = alt((
|
||||
">=", "<=", "==", "=>", "!=", "|>", "*", "+", "-", "/", "%", "=", "<", ">", r"\", "^", "|", "&",
|
||||
">=", "<=", "==", "=>", "!=", "|>", "*", "+", "-", "/", "%", "=", "<", ">", r"\", "^", "||", "&&", "|", "&",
|
||||
))
|
||||
.with_span()
|
||||
.parse_next(i)?;
|
||||
|
@ -2,11 +2,11 @@ use std::fmt::Write;
|
||||
|
||||
use crate::parsing::{
|
||||
ast::types::{
|
||||
Annotation, ArrayExpression, ArrayRangeExpression, BinaryExpression, BinaryOperator, BinaryPart, BodyItem,
|
||||
CallExpressionKw, CommentStyle, DefaultParamVal, Expr, FormatOptions, FunctionExpression, IfExpression,
|
||||
ImportSelector, ImportStatement, ItemVisibility, LabeledArg, Literal, LiteralIdentifier, LiteralValue,
|
||||
MemberExpression, MemberObject, Node, NonCodeNode, NonCodeValue, ObjectExpression, Parameter, PipeExpression,
|
||||
Program, TagDeclarator, TypeDeclaration, UnaryExpression, VariableDeclaration, VariableKind,
|
||||
Annotation, ArrayExpression, ArrayRangeExpression, AscribedExpression, BinaryExpression, BinaryOperator,
|
||||
BinaryPart, BodyItem, CallExpressionKw, CommentStyle, DefaultParamVal, Expr, FormatOptions, FunctionExpression,
|
||||
IfExpression, ImportSelector, ImportStatement, ItemVisibility, LabeledArg, Literal, LiteralIdentifier,
|
||||
LiteralValue, MemberExpression, MemberObject, Node, NonCodeNode, NonCodeValue, ObjectExpression, Parameter,
|
||||
PipeExpression, Program, TagDeclarator, TypeDeclaration, UnaryExpression, VariableDeclaration, VariableKind,
|
||||
},
|
||||
deprecation, DeprecationKind, PIPE_OPERATOR,
|
||||
};
|
||||
@ -308,18 +308,7 @@ impl Expr {
|
||||
result += &e.label.name;
|
||||
result
|
||||
}
|
||||
Expr::AscribedExpression(e) => {
|
||||
let mut result = e.expr.recast(options, indentation_level, ctxt);
|
||||
if matches!(
|
||||
e.expr,
|
||||
Expr::BinaryExpression(..) | Expr::PipeExpression(..) | Expr::UnaryExpression(..)
|
||||
) {
|
||||
result = format!("({result})");
|
||||
}
|
||||
result += ": ";
|
||||
result += &e.ty.to_string();
|
||||
result
|
||||
}
|
||||
Expr::AscribedExpression(e) => e.recast(options, indentation_level, ctxt),
|
||||
Expr::None(_) => {
|
||||
unimplemented!("there is no literal None, see https://github.com/KittyCAD/modeling-app/issues/1115")
|
||||
}
|
||||
@ -327,6 +316,21 @@ impl Expr {
|
||||
}
|
||||
}
|
||||
|
||||
impl AscribedExpression {
|
||||
fn recast(&self, options: &FormatOptions, indentation_level: usize, ctxt: ExprContext) -> String {
|
||||
let mut result = self.expr.recast(options, indentation_level, ctxt);
|
||||
if matches!(
|
||||
self.expr,
|
||||
Expr::BinaryExpression(..) | Expr::PipeExpression(..) | Expr::UnaryExpression(..)
|
||||
) {
|
||||
result = format!("({result})");
|
||||
}
|
||||
result += ": ";
|
||||
result += &self.ty.to_string();
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl BinaryPart {
|
||||
fn recast(&self, options: &FormatOptions, indentation_level: usize) -> String {
|
||||
match &self {
|
||||
@ -345,6 +349,7 @@ impl BinaryPart {
|
||||
BinaryPart::UnaryExpression(unary_expression) => unary_expression.recast(options),
|
||||
BinaryPart::MemberExpression(member_expression) => member_expression.recast(),
|
||||
BinaryPart::IfExpression(e) => e.recast(options, indentation_level, ExprContext::Other),
|
||||
BinaryPart::AscribedExpression(e) => e.recast(options, indentation_level, ExprContext::Other),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -722,6 +727,7 @@ impl UnaryExpression {
|
||||
| BinaryPart::Name(_)
|
||||
| BinaryPart::MemberExpression(_)
|
||||
| BinaryPart::IfExpression(_)
|
||||
| BinaryPart::AscribedExpression(_)
|
||||
| BinaryPart::CallExpressionKw(_) => {
|
||||
format!("{}{}", &self.operator, self.argument.recast(options, 0))
|
||||
}
|
||||
|
@ -221,6 +221,7 @@ impl<'tree> From<&'tree types::BinaryPart> for Node<'tree> {
|
||||
types::BinaryPart::UnaryExpression(ue) => ue.as_ref().into(),
|
||||
types::BinaryPart::MemberExpression(me) => me.as_ref().into(),
|
||||
types::BinaryPart::IfExpression(e) => e.as_ref().into(),
|
||||
types::BinaryPart::AscribedExpression(e) => e.as_ref().into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user