fmt and move error stuff locally (#347)
* fmt Signed-off-by: Jess Frazelle <github@jessfraz.com> * some fixups for errors Signed-off-by: Jess Frazelle <github@jessfraz.com> * some fixups for errors Signed-off-by: Jess Frazelle <github@jessfraz.com> * bump version Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix tsc Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
@ -16,10 +16,8 @@ export const parser_wasm = (code: string): Program => {
|
|||||||
const parsed: RustKclError = JSON.parse(e.toString())
|
const parsed: RustKclError = JSON.parse(e.toString())
|
||||||
const kclError = new KCLError(
|
const kclError = new KCLError(
|
||||||
parsed.kind,
|
parsed.kind,
|
||||||
parsed.kind === 'invalid_expression' ? parsed.kind : parsed.msg,
|
parsed.msg,
|
||||||
parsed.kind === 'invalid_expression'
|
rangeTypeFix(parsed.sourceRanges)
|
||||||
? [[parsed.start, parsed.end]]
|
|
||||||
: rangeTypeFix(parsed.sourceRanges)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
console.log(kclError)
|
console.log(kclError)
|
||||||
@ -36,10 +34,8 @@ export async function asyncParser(code: string): Promise<Program> {
|
|||||||
const parsed: RustKclError = JSON.parse(e.toString())
|
const parsed: RustKclError = JSON.parse(e.toString())
|
||||||
const kclError = new KCLError(
|
const kclError = new KCLError(
|
||||||
parsed.kind,
|
parsed.kind,
|
||||||
parsed.kind === 'invalid_expression' ? parsed.kind : parsed.msg,
|
parsed.msg,
|
||||||
parsed.kind === 'invalid_expression'
|
rangeTypeFix(parsed.sourceRanges)
|
||||||
? [[parsed.start, parsed.end]]
|
|
||||||
: rangeTypeFix(parsed.sourceRanges)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
console.log(kclError)
|
console.log(kclError)
|
||||||
|
@ -146,10 +146,8 @@ export const _executor = async (
|
|||||||
const parsed: RustKclError = JSON.parse(e.toString())
|
const parsed: RustKclError = JSON.parse(e.toString())
|
||||||
const kclError = new KCLError(
|
const kclError = new KCLError(
|
||||||
parsed.kind,
|
parsed.kind,
|
||||||
parsed.kind === 'invalid_expression' ? parsed.kind : parsed.msg,
|
parsed.msg,
|
||||||
parsed.kind === 'invalid_expression'
|
rangeTypeFix(parsed.sourceRanges)
|
||||||
? [[parsed.start, parsed.end]]
|
|
||||||
: rangeTypeFix(parsed.sourceRanges)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
console.log(kclError)
|
console.log(kclError)
|
||||||
|
2
src/wasm-lib/Cargo.lock
generated
2
src/wasm-lib/Cargo.lock
generated
@ -947,7 +947,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bson",
|
"bson",
|
||||||
|
@ -35,10 +35,7 @@ struct StdlibMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn stdlib(
|
pub fn stdlib(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
attr: proc_macro::TokenStream,
|
|
||||||
item: proc_macro::TokenStream,
|
|
||||||
) -> proc_macro::TokenStream {
|
|
||||||
do_output(do_stdlib(attr.into(), item.into()))
|
do_output(do_stdlib(attr.into(), item.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,9 +47,7 @@ fn do_stdlib(
|
|||||||
do_stdlib_inner(metadata, attr, item)
|
do_stdlib_inner(metadata, attr, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_output(
|
fn do_output(res: Result<(proc_macro2::TokenStream, Vec<Error>), Error>) -> proc_macro::TokenStream {
|
||||||
res: Result<(proc_macro2::TokenStream, Vec<Error>), Error>,
|
|
||||||
) -> proc_macro::TokenStream {
|
|
||||||
match res {
|
match res {
|
||||||
Err(err) => err.to_compile_error().into(),
|
Err(err) => err.to_compile_error().into(),
|
||||||
Ok((stdlib_docs, errors)) => {
|
Ok((stdlib_docs, errors)) => {
|
||||||
@ -207,11 +202,7 @@ fn do_stdlib_inner(
|
|||||||
syn::FnArg::Typed(pat) => pat.ty.as_ref().into_token_stream(),
|
syn::FnArg::Typed(pat) => pat.ty.as_ref().into_token_stream(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let ty_string = ty
|
let ty_string = ty.to_string().replace('&', "").replace("mut", "").replace(' ', "");
|
||||||
.to_string()
|
|
||||||
.replace('&', "")
|
|
||||||
.replace("mut", "")
|
|
||||||
.replace(' ', "");
|
|
||||||
let ty_string = ty_string.trim().to_string();
|
let ty_string = ty_string.trim().to_string();
|
||||||
let ty_ident = if ty_string.starts_with("Vec<") {
|
let ty_ident = if ty_string.starts_with("Vec<") {
|
||||||
let ty_string = ty_string.trim_start_matches("Vec<").trim_end_matches('>');
|
let ty_string = ty_string.trim_start_matches("Vec<").trim_end_matches('>');
|
||||||
@ -370,8 +361,7 @@ fn extract_doc_from_attrs(attrs: &[syn::Attribute]) -> (Option<String>, Option<S
|
|||||||
if let syn::Meta::NameValue(nv) = &attr.meta {
|
if let syn::Meta::NameValue(nv) = &attr.meta {
|
||||||
if nv.path.is_ident(&doc) {
|
if nv.path.is_ident(&doc) {
|
||||||
if let syn::Expr::Lit(syn::ExprLit {
|
if let syn::Expr::Lit(syn::ExprLit {
|
||||||
lit: syn::Lit::Str(s),
|
lit: syn::Lit::Str(s), ..
|
||||||
..
|
|
||||||
}) = &nv.value
|
}) = &nv.value
|
||||||
{
|
{
|
||||||
return normalize_comment_string(s.value());
|
return normalize_comment_string(s.value());
|
||||||
@ -508,10 +498,7 @@ mod tests {
|
|||||||
let _expected = quote! {};
|
let _expected = quote! {};
|
||||||
|
|
||||||
assert!(errors.is_empty());
|
assert!(errors.is_empty());
|
||||||
expectorate::assert_contents(
|
expectorate::assert_contents("tests/lineTo.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||||
"tests/lineTo.gen",
|
|
||||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -540,9 +527,6 @@ mod tests {
|
|||||||
let _expected = quote! {};
|
let _expected = quote! {};
|
||||||
|
|
||||||
assert!(errors.is_empty());
|
assert!(errors.is_empty());
|
||||||
expectorate::assert_contents(
|
expectorate::assert_contents("tests/min.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||||
"tests/min.gen",
|
|
||||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
description = "KittyCAD Language"
|
description = "KittyCAD Language"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ pub trait ValueMeta {
|
|||||||
|
|
||||||
macro_rules! impl_value_meta {
|
macro_rules! impl_value_meta {
|
||||||
{$name:ident} => {
|
{$name:ident} => {
|
||||||
impl ValueMeta for $name {
|
impl crate::abstract_syntax_tree_types::ValueMeta for $name {
|
||||||
fn start(&self) -> usize {
|
fn start(&self) -> usize {
|
||||||
self.start
|
self.start
|
||||||
}
|
}
|
||||||
@ -86,6 +86,8 @@ macro_rules! impl_value_meta {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) use impl_value_meta;
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
pub fn start(&self) -> usize {
|
pub fn start(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
@ -192,16 +194,11 @@ impl BinaryPart {
|
|||||||
BinaryPart::BinaryExpression(binary_expression) => {
|
BinaryPart::BinaryExpression(binary_expression) => {
|
||||||
binary_expression.get_result(memory, pipe_info, stdlib, engine)
|
binary_expression.get_result(memory, pipe_info, stdlib, engine)
|
||||||
}
|
}
|
||||||
BinaryPart::CallExpression(call_expression) => {
|
BinaryPart::CallExpression(call_expression) => call_expression.execute(memory, pipe_info, stdlib, engine),
|
||||||
call_expression.execute(memory, pipe_info, stdlib, engine)
|
|
||||||
}
|
|
||||||
BinaryPart::UnaryExpression(unary_expression) => {
|
BinaryPart::UnaryExpression(unary_expression) => {
|
||||||
// Return an error this should not happen.
|
// Return an error this should not happen.
|
||||||
Err(KclError::Semantic(KclErrorDetails {
|
Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("UnaryExpression should not be a BinaryPart: {:?}", unary_expression),
|
||||||
"UnaryExpression should not be a BinaryPart: {:?}",
|
|
||||||
unary_expression
|
|
||||||
),
|
|
||||||
source_ranges: vec![unary_expression.into()],
|
source_ranges: vec![unary_expression.into()],
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -313,10 +310,7 @@ impl CallExpression {
|
|||||||
}
|
}
|
||||||
Value::PipeExpression(pipe_expression) => {
|
Value::PipeExpression(pipe_expression) => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("PipeExpression not implemented here: {:?}", pipe_expression),
|
||||||
"PipeExpression not implemented here: {:?}",
|
|
||||||
pipe_expression
|
|
||||||
),
|
|
||||||
source_ranges: vec![pipe_expression.into()],
|
source_ranges: vec![pipe_expression.into()],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -325,29 +319,20 @@ impl CallExpression {
|
|||||||
.get(&pipe_info.index - 1)
|
.get(&pipe_info.index - 1)
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
KclError::Semantic(KclErrorDetails {
|
KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("PipeSubstitution index out of bounds: {:?}", pipe_info),
|
||||||
"PipeSubstitution index out of bounds: {:?}",
|
|
||||||
pipe_info
|
|
||||||
),
|
|
||||||
source_ranges: vec![pipe_substitution.into()],
|
source_ranges: vec![pipe_substitution.into()],
|
||||||
})
|
})
|
||||||
})?
|
})?
|
||||||
.clone(),
|
.clone(),
|
||||||
Value::MemberExpression(member_expression) => {
|
Value::MemberExpression(member_expression) => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("MemberExpression not implemented here: {:?}", member_expression),
|
||||||
"MemberExpression not implemented here: {:?}",
|
|
||||||
member_expression
|
|
||||||
),
|
|
||||||
source_ranges: vec![member_expression.into()],
|
source_ranges: vec![member_expression.into()],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
Value::FunctionExpression(function_expression) => {
|
Value::FunctionExpression(function_expression) => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("FunctionExpression not implemented here: {:?}", function_expression),
|
||||||
"FunctionExpression not implemented here: {:?}",
|
|
||||||
function_expression
|
|
||||||
),
|
|
||||||
source_ranges: vec![function_expression.into()],
|
source_ranges: vec![function_expression.into()],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -363,14 +348,7 @@ impl CallExpression {
|
|||||||
if pipe_info.is_in_pipe {
|
if pipe_info.is_in_pipe {
|
||||||
pipe_info.index += 1;
|
pipe_info.index += 1;
|
||||||
pipe_info.previous_results.push(result);
|
pipe_info.previous_results.push(result);
|
||||||
execute_pipe_body(
|
execute_pipe_body(memory, &pipe_info.body.clone(), pipe_info, self.into(), stdlib, engine)
|
||||||
memory,
|
|
||||||
&pipe_info.body.clone(),
|
|
||||||
pipe_info,
|
|
||||||
self.into(),
|
|
||||||
stdlib,
|
|
||||||
engine,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
@ -390,14 +368,7 @@ impl CallExpression {
|
|||||||
pipe_info.index += 1;
|
pipe_info.index += 1;
|
||||||
pipe_info.previous_results.push(result);
|
pipe_info.previous_results.push(result);
|
||||||
|
|
||||||
execute_pipe_body(
|
execute_pipe_body(memory, &pipe_info.body.clone(), pipe_info, self.into(), stdlib, engine)
|
||||||
memory,
|
|
||||||
&pipe_info.body.clone(),
|
|
||||||
pipe_info,
|
|
||||||
self.into(),
|
|
||||||
stdlib,
|
|
||||||
engine,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
@ -533,28 +504,19 @@ impl ArrayExpression {
|
|||||||
}
|
}
|
||||||
Value::PipeSubstitution(pipe_substitution) => {
|
Value::PipeSubstitution(pipe_substitution) => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution),
|
||||||
"PipeSubstitution not implemented here: {:?}",
|
|
||||||
pipe_substitution
|
|
||||||
),
|
|
||||||
source_ranges: vec![pipe_substitution.into()],
|
source_ranges: vec![pipe_substitution.into()],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
Value::MemberExpression(member_expression) => {
|
Value::MemberExpression(member_expression) => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("MemberExpression not implemented here: {:?}", member_expression),
|
||||||
"MemberExpression not implemented here: {:?}",
|
|
||||||
member_expression
|
|
||||||
),
|
|
||||||
source_ranges: vec![member_expression.into()],
|
source_ranges: vec![member_expression.into()],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
Value::FunctionExpression(function_expression) => {
|
Value::FunctionExpression(function_expression) => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("FunctionExpression not implemented here: {:?}", function_expression),
|
||||||
"FunctionExpression not implemented here: {:?}",
|
|
||||||
function_expression
|
|
||||||
),
|
|
||||||
source_ranges: vec![function_expression.into()],
|
source_ranges: vec![function_expression.into()],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -619,28 +581,19 @@ impl ObjectExpression {
|
|||||||
}
|
}
|
||||||
Value::PipeSubstitution(pipe_substitution) => {
|
Value::PipeSubstitution(pipe_substitution) => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution),
|
||||||
"PipeSubstitution not implemented here: {:?}",
|
|
||||||
pipe_substitution
|
|
||||||
),
|
|
||||||
source_ranges: vec![pipe_substitution.into()],
|
source_ranges: vec![pipe_substitution.into()],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
Value::MemberExpression(member_expression) => {
|
Value::MemberExpression(member_expression) => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("MemberExpression not implemented here: {:?}", member_expression),
|
||||||
"MemberExpression not implemented here: {:?}",
|
|
||||||
member_expression
|
|
||||||
),
|
|
||||||
source_ranges: vec![member_expression.into()],
|
source_ranges: vec![member_expression.into()],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
Value::FunctionExpression(function_expression) => {
|
Value::FunctionExpression(function_expression) => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("FunctionExpression not implemented here: {:?}", function_expression),
|
||||||
"FunctionExpression not implemented here: {:?}",
|
|
||||||
function_expression
|
|
||||||
),
|
|
||||||
source_ranges: vec![function_expression.into()],
|
source_ranges: vec![function_expression.into()],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -712,10 +665,7 @@ impl MemberExpression {
|
|||||||
string
|
string
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected string literal for property name, found {:?}", value),
|
||||||
"Expected string literal for property name, found {:?}",
|
|
||||||
value
|
|
||||||
),
|
|
||||||
source_ranges: vec![literal.into()],
|
source_ranges: vec![literal.into()],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -837,10 +787,7 @@ impl BinaryExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_json_number_as_f64(
|
pub fn parse_json_number_as_f64(j: &serde_json::Value, source_range: SourceRange) -> Result<f64, KclError> {
|
||||||
j: &serde_json::Value,
|
|
||||||
source_range: SourceRange,
|
|
||||||
) -> Result<f64, KclError> {
|
|
||||||
if let serde_json::Value::Number(n) = &j {
|
if let serde_json::Value::Number(n) = &j {
|
||||||
n.as_f64().ok_or_else(|| {
|
n.as_f64().ok_or_else(|| {
|
||||||
KclError::Syntax(KclErrorDetails {
|
KclError::Syntax(KclErrorDetails {
|
||||||
|
@ -147,15 +147,9 @@ fn get_type_string_from_schema(schema: &schemars::schema::Schema) -> Result<(Str
|
|||||||
if let Some(array_val) = &o.array {
|
if let Some(array_val) = &o.array {
|
||||||
if let Some(schemars::schema::SingleOrVec::Single(items)) = &array_val.items {
|
if let Some(schemars::schema::SingleOrVec::Single(items)) = &array_val.items {
|
||||||
// Let's print out the object's properties.
|
// Let's print out the object's properties.
|
||||||
return Ok((
|
return Ok((format!("[{}]", get_type_string_from_schema(items)?.0), false));
|
||||||
format!("[{}]", get_type_string_from_schema(items)?.0),
|
|
||||||
false,
|
|
||||||
));
|
|
||||||
} else if let Some(items) = &array_val.contains {
|
} else if let Some(items) = &array_val.contains {
|
||||||
return Ok((
|
return Ok((format!("[{}]", get_type_string_from_schema(items)?.0), false));
|
||||||
format!("[{}]", get_type_string_from_schema(items)?.0),
|
|
||||||
false,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,7 @@ use crate::errors::{KclError, KclErrorDetails};
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EngineConnection {
|
pub struct EngineConnection {
|
||||||
tcp_write:
|
tcp_write: futures::stream::SplitSink<tokio_tungstenite::WebSocketStream<reqwest::Upgraded>, WsMsg>,
|
||||||
futures::stream::SplitSink<tokio_tungstenite::WebSocketStream<reqwest::Upgraded>, WsMsg>,
|
|
||||||
tcp_read_handle: tokio::task::JoinHandle<Result<()>>,
|
tcp_read_handle: tokio::task::JoinHandle<Result<()>>,
|
||||||
export_notifier: Arc<tokio::sync::Notify>,
|
export_notifier: Arc<tokio::sync::Notify>,
|
||||||
}
|
}
|
||||||
@ -50,10 +49,7 @@ impl EngineConnection {
|
|||||||
}
|
}
|
||||||
// Make sure it is a directory.
|
// Make sure it is a directory.
|
||||||
if !export_dir.is_dir() {
|
if !export_dir.is_dir() {
|
||||||
anyhow::bail!(
|
anyhow::bail!("Export directory is not a directory: {}", export_dir.display());
|
||||||
"Export directory is not a directory: {}",
|
|
||||||
export_dir.display()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let ws_stream = tokio_tungstenite::WebSocketStream::from_raw_socket(
|
let ws_stream = tokio_tungstenite::WebSocketStream::from_raw_socket(
|
||||||
@ -140,15 +136,14 @@ impl EngineConnection {
|
|||||||
source_range: crate::executor::SourceRange,
|
source_range: crate::executor::SourceRange,
|
||||||
cmd: kittycad::types::ModelingCmd,
|
cmd: kittycad::types::ModelingCmd,
|
||||||
) -> Result<(), KclError> {
|
) -> Result<(), KclError> {
|
||||||
futures::executor::block_on(
|
futures::executor::block_on(self.tcp_send(WebSocketRequest::ModelingCmdReq { cmd, cmd_id: id })).map_err(
|
||||||
self.tcp_send(WebSocketRequest::ModelingCmdReq { cmd, cmd_id: id }),
|
|e| {
|
||||||
)
|
KclError::Engine(KclErrorDetails {
|
||||||
.map_err(|e| {
|
message: format!("Failed to send modeling command: {}", e),
|
||||||
KclError::Engine(KclErrorDetails {
|
source_ranges: vec![source_range],
|
||||||
message: format!("Failed to send modeling command: {}", e),
|
})
|
||||||
source_ranges: vec![source_range],
|
},
|
||||||
})
|
)?;
|
||||||
})?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ pub enum KclError {
|
|||||||
#[error("undefined value: {0:?}")]
|
#[error("undefined value: {0:?}")]
|
||||||
UndefinedValue(KclErrorDetails),
|
UndefinedValue(KclErrorDetails),
|
||||||
#[error("invalid expression: {0:?}")]
|
#[error("invalid expression: {0:?}")]
|
||||||
InvalidExpression(crate::math_parser::MathExpression),
|
InvalidExpression(KclErrorDetails),
|
||||||
#[error("engine: {0:?}")]
|
#[error("engine: {0:?}")]
|
||||||
Engine(KclErrorDetails),
|
Engine(KclErrorDetails),
|
||||||
}
|
}
|
||||||
@ -34,6 +34,35 @@ pub struct KclErrorDetails {
|
|||||||
pub message: String,
|
pub message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl KclError {
|
||||||
|
/// Get the error message, line and column from the error and input code.
|
||||||
|
pub fn get_message_line_column(&self, input: &str) -> (String, Option<usize>, Option<usize>) {
|
||||||
|
let (type_, source_range, message) = match &self {
|
||||||
|
KclError::Syntax(e) => ("syntax", e.source_ranges.clone(), e.message.clone()),
|
||||||
|
KclError::Semantic(e) => ("semantic", e.source_ranges.clone(), e.message.clone()),
|
||||||
|
KclError::Type(e) => ("type", e.source_ranges.clone(), e.message.clone()),
|
||||||
|
KclError::Unimplemented(e) => ("unimplemented", e.source_ranges.clone(), e.message.clone()),
|
||||||
|
KclError::Unexpected(e) => ("unexpected", e.source_ranges.clone(), e.message.clone()),
|
||||||
|
KclError::ValueAlreadyDefined(e) => ("value already defined", e.source_ranges.clone(), e.message.clone()),
|
||||||
|
KclError::UndefinedValue(e) => ("undefined value", e.source_ranges.clone(), e.message.clone()),
|
||||||
|
KclError::InvalidExpression(e) => ("invalid expression", e.source_ranges.clone(), e.message.clone()),
|
||||||
|
KclError::Engine(e) => ("engine", e.source_ranges.clone(), e.message.clone()),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calculate the line and column of the error from the source range.
|
||||||
|
let (line, column) = if let Some(range) = source_range.first() {
|
||||||
|
let line = input[..range.0[0]].lines().count();
|
||||||
|
let column = input[..range.0[0]].lines().last().map(|l| l.len()).unwrap_or_default();
|
||||||
|
|
||||||
|
(Some(line), Some(column))
|
||||||
|
} else {
|
||||||
|
(None, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
(format!("{}: {}", type_, message), line, column)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This is different than to_string() in that it will serialize the Error
|
/// This is different than to_string() in that it will serialize the Error
|
||||||
/// the struct as JSON so we can deserialize it on the js side.
|
/// the struct as JSON so we can deserialize it on the js side.
|
||||||
impl From<KclError> for String {
|
impl From<KclError> for String {
|
||||||
|
@ -30,12 +30,7 @@ impl ProgramMemory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add to the program memory.
|
/// Add to the program memory.
|
||||||
pub fn add(
|
pub fn add(&mut self, key: &str, value: MemoryItem, source_range: SourceRange) -> Result<(), KclError> {
|
||||||
&mut self,
|
|
||||||
key: &str,
|
|
||||||
value: MemoryItem,
|
|
||||||
source_range: SourceRange,
|
|
||||||
) -> Result<(), KclError> {
|
|
||||||
if self.root.get(key).is_some() {
|
if self.root.get(key).is_some() {
|
||||||
return Err(KclError::ValueAlreadyDefined(KclErrorDetails {
|
return Err(KclError::ValueAlreadyDefined(KclErrorDetails {
|
||||||
message: format!("Cannot redefine {}", key),
|
message: format!("Cannot redefine {}", key),
|
||||||
@ -169,12 +164,7 @@ impl MemoryItem {
|
|||||||
memory: &ProgramMemory,
|
memory: &ProgramMemory,
|
||||||
engine: &mut EngineConnection,
|
engine: &mut EngineConnection,
|
||||||
) -> Result<Option<ProgramReturn>, KclError> {
|
) -> Result<Option<ProgramReturn>, KclError> {
|
||||||
if let MemoryItem::Function {
|
if let MemoryItem::Function { func, expression, meta } = self {
|
||||||
func,
|
|
||||||
expression,
|
|
||||||
meta,
|
|
||||||
} = self
|
|
||||||
{
|
|
||||||
if let Some(func) = func {
|
if let Some(func) = func {
|
||||||
func(args, memory, expression, meta, engine)
|
func(args, memory, expression, meta, engine)
|
||||||
} else {
|
} else {
|
||||||
@ -225,10 +215,7 @@ impl SketchGroup {
|
|||||||
if self.start.name == name {
|
if self.start.name == name {
|
||||||
Some(&self.start)
|
Some(&self.start)
|
||||||
} else {
|
} else {
|
||||||
self.value
|
self.value.iter().find(|p| p.get_name() == name).map(|p| p.get_base())
|
||||||
.iter()
|
|
||||||
.find(|p| p.get_name() == name)
|
|
||||||
.map(|p| p.get_base())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -523,8 +510,7 @@ pub fn execute(
|
|||||||
match arg {
|
match arg {
|
||||||
Value::Literal(literal) => args.push(literal.into()),
|
Value::Literal(literal) => args.push(literal.into()),
|
||||||
Value::Identifier(identifier) => {
|
Value::Identifier(identifier) => {
|
||||||
let memory_item =
|
let memory_item = memory.get(&identifier.name, identifier.into())?;
|
||||||
memory.get(&identifier.name, identifier.into())?;
|
|
||||||
args.push(memory_item.clone());
|
args.push(memory_item.clone());
|
||||||
}
|
}
|
||||||
// We do nothing for the rest.
|
// We do nothing for the rest.
|
||||||
@ -539,8 +525,7 @@ pub fn execute(
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
memory.return_ =
|
memory.return_ = Some(ProgramReturn::Arguments(call_expr.arguments.clone()));
|
||||||
Some(ProgramReturn::Arguments(call_expr.arguments.clone()));
|
|
||||||
} else if let Some(func) = memory.clone().root.get(&fn_name) {
|
} else if let Some(func) = memory.clone().root.get(&fn_name) {
|
||||||
func.call_fn(&args, memory, engine)?;
|
func.call_fn(&args, memory, engine)?;
|
||||||
} else {
|
} else {
|
||||||
@ -566,12 +551,7 @@ pub fn execute(
|
|||||||
memory.add(&var_name, value.clone(), source_range)?;
|
memory.add(&var_name, value.clone(), source_range)?;
|
||||||
}
|
}
|
||||||
Value::BinaryExpression(binary_expression) => {
|
Value::BinaryExpression(binary_expression) => {
|
||||||
let result = binary_expression.get_result(
|
let result = binary_expression.get_result(memory, &mut pipe_info, &stdlib, engine)?;
|
||||||
memory,
|
|
||||||
&mut pipe_info,
|
|
||||||
&stdlib,
|
|
||||||
engine,
|
|
||||||
)?;
|
|
||||||
memory.add(&var_name, result, source_range)?;
|
memory.add(&var_name, result, source_range)?;
|
||||||
}
|
}
|
||||||
Value::FunctionExpression(function_expression) => {
|
Value::FunctionExpression(function_expression) => {
|
||||||
@ -608,41 +588,28 @@ pub fn execute(
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Value::CallExpression(call_expression) => {
|
Value::CallExpression(call_expression) => {
|
||||||
let result =
|
let result = call_expression.execute(memory, &mut pipe_info, &stdlib, engine)?;
|
||||||
call_expression.execute(memory, &mut pipe_info, &stdlib, engine)?;
|
|
||||||
memory.add(&var_name, result, source_range)?;
|
memory.add(&var_name, result, source_range)?;
|
||||||
}
|
}
|
||||||
Value::PipeExpression(pipe_expression) => {
|
Value::PipeExpression(pipe_expression) => {
|
||||||
let result = pipe_expression.get_result(
|
let result = pipe_expression.get_result(memory, &mut pipe_info, &stdlib, engine)?;
|
||||||
memory,
|
|
||||||
&mut pipe_info,
|
|
||||||
&stdlib,
|
|
||||||
engine,
|
|
||||||
)?;
|
|
||||||
memory.add(&var_name, result, source_range)?;
|
memory.add(&var_name, result, source_range)?;
|
||||||
}
|
}
|
||||||
Value::PipeSubstitution(pipe_substitution) => {
|
Value::PipeSubstitution(pipe_substitution) => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!("pipe substitution not implemented for declaration of variable {}", var_name),
|
message: format!(
|
||||||
|
"pipe substitution not implemented for declaration of variable {}",
|
||||||
|
var_name
|
||||||
|
),
|
||||||
source_ranges: vec![pipe_substitution.into()],
|
source_ranges: vec![pipe_substitution.into()],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
Value::ArrayExpression(array_expression) => {
|
Value::ArrayExpression(array_expression) => {
|
||||||
let result = array_expression.execute(
|
let result = array_expression.execute(memory, &mut pipe_info, &stdlib, engine)?;
|
||||||
memory,
|
|
||||||
&mut pipe_info,
|
|
||||||
&stdlib,
|
|
||||||
engine,
|
|
||||||
)?;
|
|
||||||
memory.add(&var_name, result, source_range)?;
|
memory.add(&var_name, result, source_range)?;
|
||||||
}
|
}
|
||||||
Value::ObjectExpression(object_expression) => {
|
Value::ObjectExpression(object_expression) => {
|
||||||
let result = object_expression.execute(
|
let result = object_expression.execute(memory, &mut pipe_info, &stdlib, engine)?;
|
||||||
memory,
|
|
||||||
&mut pipe_info,
|
|
||||||
&stdlib,
|
|
||||||
engine,
|
|
||||||
)?;
|
|
||||||
memory.add(&var_name, result, source_range)?;
|
memory.add(&var_name, result, source_range)?;
|
||||||
}
|
}
|
||||||
Value::MemberExpression(member_expression) => {
|
Value::MemberExpression(member_expression) => {
|
||||||
@ -650,12 +617,7 @@ pub fn execute(
|
|||||||
memory.add(&var_name, result, source_range)?;
|
memory.add(&var_name, result, source_range)?;
|
||||||
}
|
}
|
||||||
Value::UnaryExpression(unary_expression) => {
|
Value::UnaryExpression(unary_expression) => {
|
||||||
let result = unary_expression.get_result(
|
let result = unary_expression.get_result(memory, &mut pipe_info, &stdlib, engine)?;
|
||||||
memory,
|
|
||||||
&mut pipe_info,
|
|
||||||
&stdlib,
|
|
||||||
engine,
|
|
||||||
)?;
|
|
||||||
memory.add(&var_name, result, source_range)?;
|
memory.add(&var_name, result, source_range)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -680,9 +642,10 @@ pub fn execute(
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
pub async fn parse_execute(code: &str) -> Result<ProgramMemory> {
|
pub async fn parse_execute(code: &str) -> Result<ProgramMemory> {
|
||||||
let tokens = crate::tokeniser::lexer(code);
|
let tokens = crate::tokeniser::lexer(code);
|
||||||
let program = crate::parser::abstract_syntax_tree(&tokens)?;
|
let program = crate::parser::abstract_syntax_tree(&tokens)?;
|
||||||
@ -730,23 +693,13 @@ show(part001)"#,
|
|||||||
let memory = parse_execute(&ast_fn("-1")).await.unwrap();
|
let memory = parse_execute(&ast_fn("-1")).await.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::json!(1.0 + 2.0f64.sqrt()),
|
serde_json::json!(1.0 + 2.0f64.sqrt()),
|
||||||
memory
|
memory.root.get("intersect").unwrap().get_json_value().unwrap()
|
||||||
.root
|
|
||||||
.get("intersect")
|
|
||||||
.unwrap()
|
|
||||||
.get_json_value()
|
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let memory = parse_execute(&ast_fn("0")).await.unwrap();
|
let memory = parse_execute(&ast_fn("0")).await.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::json!(1.0000000000000002),
|
serde_json::json!(1.0000000000000002),
|
||||||
memory
|
memory.root.get("intersect").unwrap().get_json_value().unwrap()
|
||||||
.root
|
|
||||||
.get("intersect")
|
|
||||||
.unwrap()
|
|
||||||
.get_json_value()
|
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::abstract_syntax_tree_types::{
|
use crate::{
|
||||||
BinaryExpression, BinaryPart, CallExpression, Identifier, Literal,
|
abstract_syntax_tree_types::{BinaryExpression, BinaryPart, CallExpression, Identifier, Literal, ValueMeta},
|
||||||
|
errors::{KclError, KclErrorDetails},
|
||||||
|
executor::SourceRange,
|
||||||
|
parser::{find_closing_brace, is_not_code_token, make_call_expression},
|
||||||
|
tokeniser::{Token, TokenType},
|
||||||
};
|
};
|
||||||
use crate::errors::{KclError, KclErrorDetails};
|
|
||||||
use crate::parser::{find_closing_brace, is_not_code_token, make_call_expression};
|
|
||||||
use crate::tokeniser::{Token, TokenType};
|
|
||||||
|
|
||||||
pub fn precedence(operator: &str) -> u8 {
|
pub fn precedence(operator: &str) -> u8 {
|
||||||
// might be useful for reference to make it match
|
// might be useful for reference to make it match
|
||||||
@ -182,6 +183,8 @@ pub struct ParenthesisToken {
|
|||||||
pub end: usize,
|
pub end: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate::abstract_syntax_tree_types::impl_value_meta!(ParenthesisToken);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
@ -195,10 +198,12 @@ pub struct ExtendedBinaryExpression {
|
|||||||
pub end_extended: Option<usize>,
|
pub end_extended: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate::abstract_syntax_tree_types::impl_value_meta!(ExtendedBinaryExpression);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
pub struct ExntendedLiteral {
|
pub struct ExtendedLiteral {
|
||||||
pub start: usize,
|
pub start: usize,
|
||||||
pub end: usize,
|
pub end: usize,
|
||||||
pub value: serde_json::Value,
|
pub value: serde_json::Value,
|
||||||
@ -207,11 +212,13 @@ pub struct ExntendedLiteral {
|
|||||||
pub end_extended: Option<usize>,
|
pub end_extended: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate::abstract_syntax_tree_types::impl_value_meta!(ExtendedLiteral);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
pub enum MathExpression {
|
pub enum MathExpression {
|
||||||
ExntendedLiteral(Box<ExntendedLiteral>),
|
ExtendedLiteral(Box<ExtendedLiteral>),
|
||||||
Identifier(Box<Identifier>),
|
Identifier(Box<Identifier>),
|
||||||
CallExpression(Box<CallExpression>),
|
CallExpression(Box<CallExpression>),
|
||||||
BinaryExpression(Box<BinaryExpression>),
|
BinaryExpression(Box<BinaryExpression>),
|
||||||
@ -219,6 +226,30 @@ pub enum MathExpression {
|
|||||||
ParenthesisToken(Box<ParenthesisToken>),
|
ParenthesisToken(Box<ParenthesisToken>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MathExpression {
|
||||||
|
pub fn start(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
MathExpression::ExtendedLiteral(literal) => literal.start(),
|
||||||
|
MathExpression::Identifier(identifier) => identifier.start(),
|
||||||
|
MathExpression::CallExpression(call_expression) => call_expression.start(),
|
||||||
|
MathExpression::BinaryExpression(binary_expression) => binary_expression.start(),
|
||||||
|
MathExpression::ExtendedBinaryExpression(extended_binary_expression) => extended_binary_expression.start(),
|
||||||
|
MathExpression::ParenthesisToken(parenthesis_token) => parenthesis_token.start(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
MathExpression::ExtendedLiteral(literal) => literal.end(),
|
||||||
|
MathExpression::Identifier(identifier) => identifier.end(),
|
||||||
|
MathExpression::CallExpression(call_expression) => call_expression.end(),
|
||||||
|
MathExpression::BinaryExpression(binary_expression) => binary_expression.end(),
|
||||||
|
MathExpression::ExtendedBinaryExpression(extended_binary_expression) => extended_binary_expression.end(),
|
||||||
|
MathExpression::ParenthesisToken(parenthesis_token) => parenthesis_token.end(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn build_tree(
|
fn build_tree(
|
||||||
reverse_polish_notation_tokens: &[Token],
|
reverse_polish_notation_tokens: &[Token],
|
||||||
stack: Vec<MathExpression>,
|
stack: Vec<MathExpression>,
|
||||||
@ -241,48 +272,47 @@ fn build_tree(
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
a => {
|
a => {
|
||||||
return Err(KclError::InvalidExpression(a.clone()));
|
return Err(KclError::InvalidExpression(KclErrorDetails {
|
||||||
|
source_ranges: vec![SourceRange([a.start(), a.end()])],
|
||||||
|
message: format!("{:?}", a),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
let current_token = &reverse_polish_notation_tokens[0];
|
let current_token = &reverse_polish_notation_tokens[0];
|
||||||
if current_token.token_type == TokenType::Number
|
if current_token.token_type == TokenType::Number || current_token.token_type == TokenType::String {
|
||||||
|| current_token.token_type == TokenType::String
|
|
||||||
{
|
|
||||||
let mut new_stack = stack;
|
let mut new_stack = stack;
|
||||||
new_stack.push(MathExpression::ExntendedLiteral(Box::new(
|
new_stack.push(MathExpression::ExtendedLiteral(Box::new(ExtendedLiteral {
|
||||||
ExntendedLiteral {
|
value: if current_token.token_type == TokenType::Number {
|
||||||
value: if current_token.token_type == TokenType::Number {
|
if let Ok(value) = current_token.value.parse::<i64>() {
|
||||||
if let Ok(value) = current_token.value.parse::<i64>() {
|
serde_json::Value::Number(value.into())
|
||||||
serde_json::Value::Number(value.into())
|
} else if let Ok(value) = current_token.value.parse::<f64>() {
|
||||||
} else if let Ok(value) = current_token.value.parse::<f64>() {
|
if let Some(n) = serde_json::Number::from_f64(value) {
|
||||||
if let Some(n) = serde_json::Number::from_f64(value) {
|
serde_json::Value::Number(n)
|
||||||
serde_json::Value::Number(n)
|
|
||||||
} else {
|
|
||||||
return Err(KclError::Syntax(KclErrorDetails {
|
|
||||||
source_ranges: vec![current_token.into()],
|
|
||||||
message: format!("Invalid float: {}", current_token.value),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::Syntax(KclErrorDetails {
|
return Err(KclError::Syntax(KclErrorDetails {
|
||||||
source_ranges: vec![current_token.into()],
|
source_ranges: vec![current_token.into()],
|
||||||
message: format!("Invalid integer: {}", current_token.value),
|
message: format!("Invalid float: {}", current_token.value),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut str_val = current_token.value.clone();
|
return Err(KclError::Syntax(KclErrorDetails {
|
||||||
str_val.remove(0);
|
source_ranges: vec![current_token.into()],
|
||||||
str_val.pop();
|
message: format!("Invalid integer: {}", current_token.value),
|
||||||
serde_json::Value::String(str_val)
|
}));
|
||||||
},
|
}
|
||||||
start: current_token.start,
|
} else {
|
||||||
end: current_token.end,
|
let mut str_val = current_token.value.clone();
|
||||||
raw: current_token.value.clone(),
|
str_val.remove(0);
|
||||||
end_extended: None,
|
str_val.pop();
|
||||||
start_extended: None,
|
serde_json::Value::String(str_val)
|
||||||
},
|
},
|
||||||
)));
|
start: current_token.start,
|
||||||
|
end: current_token.end,
|
||||||
|
raw: current_token.value.clone(),
|
||||||
|
end_extended: None,
|
||||||
|
start_extended: None,
|
||||||
|
})));
|
||||||
return build_tree(&reverse_polish_notation_tokens[1..], new_stack);
|
return build_tree(&reverse_polish_notation_tokens[1..], new_stack);
|
||||||
} else if current_token.token_type == TokenType::Word {
|
} else if current_token.token_type == TokenType::Word {
|
||||||
if reverse_polish_notation_tokens[1].token_type == TokenType::Brace
|
if reverse_polish_notation_tokens[1].token_type == TokenType::Brace
|
||||||
@ -293,10 +323,7 @@ fn build_tree(
|
|||||||
new_stack.push(MathExpression::CallExpression(Box::new(
|
new_stack.push(MathExpression::CallExpression(Box::new(
|
||||||
make_call_expression(reverse_polish_notation_tokens, 0)?.expression,
|
make_call_expression(reverse_polish_notation_tokens, 0)?.expression,
|
||||||
)));
|
)));
|
||||||
return build_tree(
|
return build_tree(&reverse_polish_notation_tokens[closing_brace + 1..], new_stack);
|
||||||
&reverse_polish_notation_tokens[closing_brace + 1..],
|
|
||||||
new_stack,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
let mut new_stack = stack;
|
let mut new_stack = stack;
|
||||||
new_stack.push(MathExpression::Identifier(Box::new(Identifier {
|
new_stack.push(MathExpression::Identifier(Box::new(Identifier {
|
||||||
@ -307,14 +334,12 @@ fn build_tree(
|
|||||||
return build_tree(&reverse_polish_notation_tokens[1..], new_stack);
|
return build_tree(&reverse_polish_notation_tokens[1..], new_stack);
|
||||||
} else if current_token.token_type == TokenType::Brace && current_token.value == "(" {
|
} else if current_token.token_type == TokenType::Brace && current_token.value == "(" {
|
||||||
let mut new_stack = stack;
|
let mut new_stack = stack;
|
||||||
new_stack.push(MathExpression::ParenthesisToken(Box::new(
|
new_stack.push(MathExpression::ParenthesisToken(Box::new(ParenthesisToken {
|
||||||
ParenthesisToken {
|
value: "(".to_string(),
|
||||||
value: "(".to_string(),
|
start: current_token.start,
|
||||||
start: current_token.start,
|
end: current_token.end,
|
||||||
end: current_token.end,
|
token_type: MathTokenType::Parenthesis,
|
||||||
token_type: MathTokenType::Parenthesis,
|
})));
|
||||||
},
|
|
||||||
)));
|
|
||||||
return build_tree(&reverse_polish_notation_tokens[1..], new_stack);
|
return build_tree(&reverse_polish_notation_tokens[1..], new_stack);
|
||||||
} else if current_token.token_type == TokenType::Brace && current_token.value == ")" {
|
} else if current_token.token_type == TokenType::Brace && current_token.value == ")" {
|
||||||
let inner_node: MathExpression = match &stack[stack.len() - 1] {
|
let inner_node: MathExpression = match &stack[stack.len() - 1] {
|
||||||
@ -340,14 +365,22 @@ fn build_tree(
|
|||||||
end_extended: None,
|
end_extended: None,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
MathExpression::ExntendedLiteral(literal) => {
|
MathExpression::ExtendedLiteral(literal) => MathExpression::ExtendedLiteral(literal.clone()),
|
||||||
MathExpression::ExntendedLiteral(literal.clone())
|
a => {
|
||||||
|
return Err(KclError::InvalidExpression(KclErrorDetails {
|
||||||
|
source_ranges: vec![current_token.into()],
|
||||||
|
message: format!("{:?}", a),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
a => return Err(KclError::InvalidExpression(a.clone())),
|
|
||||||
};
|
};
|
||||||
let paran = match &stack[stack.len() - 2] {
|
let paran = match &stack[stack.len() - 2] {
|
||||||
MathExpression::ParenthesisToken(paran) => paran.clone(),
|
MathExpression::ParenthesisToken(paran) => paran.clone(),
|
||||||
a => return Err(KclError::InvalidExpression(a.clone())),
|
a => {
|
||||||
|
return Err(KclError::InvalidExpression(KclErrorDetails {
|
||||||
|
source_ranges: vec![current_token.into()],
|
||||||
|
message: format!("{:?}", a),
|
||||||
|
}))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let expression = match inner_node {
|
let expression = match inner_node {
|
||||||
MathExpression::ExtendedBinaryExpression(bin_exp) => {
|
MathExpression::ExtendedBinaryExpression(bin_exp) => {
|
||||||
@ -372,17 +405,20 @@ fn build_tree(
|
|||||||
end_extended: Some(current_token.end),
|
end_extended: Some(current_token.end),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
MathExpression::ExntendedLiteral(literal) => {
|
MathExpression::ExtendedLiteral(literal) => MathExpression::ExtendedLiteral(Box::new(ExtendedLiteral {
|
||||||
MathExpression::ExntendedLiteral(Box::new(ExntendedLiteral {
|
value: literal.value.clone(),
|
||||||
value: literal.value.clone(),
|
start: literal.start,
|
||||||
start: literal.start,
|
end: literal.end,
|
||||||
end: literal.end,
|
raw: literal.raw.clone(),
|
||||||
raw: literal.raw.clone(),
|
end_extended: Some(current_token.end),
|
||||||
end_extended: Some(current_token.end),
|
start_extended: Some(paran.start),
|
||||||
start_extended: Some(paran.start),
|
})),
|
||||||
|
a => {
|
||||||
|
return Err(KclError::InvalidExpression(KclErrorDetails {
|
||||||
|
source_ranges: vec![current_token.into()],
|
||||||
|
message: format!("{:?}", a),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
a => return Err(KclError::InvalidExpression(a.clone())),
|
|
||||||
};
|
};
|
||||||
let mut new_stack = stack[0..stack.len() - 2].to_vec();
|
let mut new_stack = stack[0..stack.len() - 2].to_vec();
|
||||||
new_stack.push(expression);
|
new_stack.push(expression);
|
||||||
@ -399,7 +435,7 @@ fn build_tree(
|
|||||||
})),
|
})),
|
||||||
bin_exp.start_extended.unwrap_or(bin_exp.start),
|
bin_exp.start_extended.unwrap_or(bin_exp.start),
|
||||||
),
|
),
|
||||||
MathExpression::ExntendedLiteral(lit) => (
|
MathExpression::ExtendedLiteral(lit) => (
|
||||||
BinaryPart::Literal(Box::new(Literal {
|
BinaryPart::Literal(Box::new(Literal {
|
||||||
value: lit.value.clone(),
|
value: lit.value.clone(),
|
||||||
start: lit.start,
|
start: lit.start,
|
||||||
@ -409,13 +445,14 @@ fn build_tree(
|
|||||||
lit.start_extended.unwrap_or(lit.start),
|
lit.start_extended.unwrap_or(lit.start),
|
||||||
),
|
),
|
||||||
MathExpression::Identifier(ident) => (BinaryPart::Identifier(ident.clone()), ident.start),
|
MathExpression::Identifier(ident) => (BinaryPart::Identifier(ident.clone()), ident.start),
|
||||||
MathExpression::CallExpression(call) => {
|
MathExpression::CallExpression(call) => (BinaryPart::CallExpression(call.clone()), call.start),
|
||||||
(BinaryPart::CallExpression(call.clone()), call.start)
|
MathExpression::BinaryExpression(bin_exp) => (BinaryPart::BinaryExpression(bin_exp.clone()), bin_exp.start),
|
||||||
|
a => {
|
||||||
|
return Err(KclError::InvalidExpression(KclErrorDetails {
|
||||||
|
source_ranges: vec![current_token.into()],
|
||||||
|
message: format!("{:?}", a),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
MathExpression::BinaryExpression(bin_exp) => {
|
|
||||||
(BinaryPart::BinaryExpression(bin_exp.clone()), bin_exp.start)
|
|
||||||
}
|
|
||||||
a => return Err(KclError::InvalidExpression(a.clone())),
|
|
||||||
};
|
};
|
||||||
let right = match &stack[stack.len() - 1] {
|
let right = match &stack[stack.len() - 1] {
|
||||||
MathExpression::ExtendedBinaryExpression(bin_exp) => (
|
MathExpression::ExtendedBinaryExpression(bin_exp) => (
|
||||||
@ -428,7 +465,7 @@ fn build_tree(
|
|||||||
})),
|
})),
|
||||||
bin_exp.end_extended.unwrap_or(bin_exp.end),
|
bin_exp.end_extended.unwrap_or(bin_exp.end),
|
||||||
),
|
),
|
||||||
MathExpression::ExntendedLiteral(lit) => (
|
MathExpression::ExtendedLiteral(lit) => (
|
||||||
BinaryPart::Literal(Box::new(Literal {
|
BinaryPart::Literal(Box::new(Literal {
|
||||||
value: lit.value.clone(),
|
value: lit.value.clone(),
|
||||||
start: lit.start,
|
start: lit.start,
|
||||||
@ -438,13 +475,14 @@ fn build_tree(
|
|||||||
lit.end_extended.unwrap_or(lit.end),
|
lit.end_extended.unwrap_or(lit.end),
|
||||||
),
|
),
|
||||||
MathExpression::Identifier(ident) => (BinaryPart::Identifier(ident.clone()), ident.end),
|
MathExpression::Identifier(ident) => (BinaryPart::Identifier(ident.clone()), ident.end),
|
||||||
MathExpression::CallExpression(call) => {
|
MathExpression::CallExpression(call) => (BinaryPart::CallExpression(call.clone()), call.end),
|
||||||
(BinaryPart::CallExpression(call.clone()), call.end)
|
MathExpression::BinaryExpression(bin_exp) => (BinaryPart::BinaryExpression(bin_exp.clone()), bin_exp.end),
|
||||||
|
a => {
|
||||||
|
return Err(KclError::InvalidExpression(KclErrorDetails {
|
||||||
|
source_ranges: vec![current_token.into()],
|
||||||
|
message: format!("{:?}", a),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
MathExpression::BinaryExpression(bin_exp) => {
|
|
||||||
(BinaryPart::BinaryExpression(bin_exp.clone()), bin_exp.end)
|
|
||||||
}
|
|
||||||
a => return Err(KclError::InvalidExpression(a.clone())),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let right_end = match right.0.clone() {
|
let right_end = match right.0.clone() {
|
||||||
@ -458,11 +496,7 @@ fn build_tree(
|
|||||||
let tree = BinaryExpression {
|
let tree = BinaryExpression {
|
||||||
operator: current_token.value.clone(),
|
operator: current_token.value.clone(),
|
||||||
start: left.1,
|
start: left.1,
|
||||||
end: if right.1 > right_end {
|
end: if right.1 > right_end { right.1 } else { right_end },
|
||||||
right.1
|
|
||||||
} else {
|
|
||||||
right_end
|
|
||||||
},
|
|
||||||
left: left.0,
|
left: left.0,
|
||||||
right: right.0,
|
right: right.0,
|
||||||
};
|
};
|
||||||
@ -510,9 +544,10 @@ pub fn parse_expression(tokens: &[Token]) -> Result<BinaryExpression, KclError>
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_expression() {
|
fn test_parse_expression() {
|
||||||
let tokens = crate::tokeniser::lexer("1 + 2");
|
let tokens = crate::tokeniser::lexer("1 + 2");
|
||||||
@ -833,8 +868,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_reverse_polish_notation_complex() {
|
fn test_reverse_polish_notation_complex() {
|
||||||
let result =
|
let result = reverse_polish_notation(&crate::tokeniser::lexer("1 + 2 * 3"), &[], &[]).unwrap();
|
||||||
reverse_polish_notation(&crate::tokeniser::lexer("1 + 2 * 3"), &[], &[]).unwrap();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
vec![
|
vec![
|
||||||
@ -874,8 +908,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_reverse_polish_notation_complex_with_parentheses() {
|
fn test_reverse_polish_notation_complex_with_parentheses() {
|
||||||
let result =
|
let result = reverse_polish_notation(&crate::tokeniser::lexer("1 * ( 2 + 3 )"), &[], &[]).unwrap();
|
||||||
reverse_polish_notation(&crate::tokeniser::lexer("1 * ( 2 + 3 )"), &[], &[]).unwrap();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
vec![
|
vec![
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::abstract_syntax_tree_types::{
|
use crate::{
|
||||||
ArrayExpression, BinaryExpression, BinaryPart, BodyItem, CallExpression, ExpressionStatement,
|
abstract_syntax_tree_types::{
|
||||||
FunctionExpression, Identifier, Literal, LiteralIdentifier, MemberExpression, MemberObject,
|
ArrayExpression, BinaryExpression, BinaryPart, BodyItem, CallExpression, ExpressionStatement,
|
||||||
NoneCodeMeta, NoneCodeNode, ObjectExpression, ObjectKeyInfo, ObjectProperty, PipeExpression,
|
FunctionExpression, Identifier, Literal, LiteralIdentifier, MemberExpression, MemberObject, NoneCodeMeta,
|
||||||
PipeSubstitution, Program, ReturnStatement, UnaryExpression, Value, VariableDeclaration,
|
NoneCodeNode, ObjectExpression, ObjectKeyInfo, ObjectProperty, PipeExpression, PipeSubstitution, Program,
|
||||||
VariableDeclarator,
|
ReturnStatement, UnaryExpression, Value, VariableDeclaration, VariableDeclarator,
|
||||||
|
},
|
||||||
|
errors::{KclError, KclErrorDetails},
|
||||||
|
math_parser::parse_expression,
|
||||||
|
tokeniser::{Token, TokenType},
|
||||||
};
|
};
|
||||||
use crate::errors::{KclError, KclErrorDetails};
|
|
||||||
use crate::math_parser::parse_expression;
|
|
||||||
use crate::tokeniser::{Token, TokenType};
|
|
||||||
|
|
||||||
fn make_identifier(tokens: &[Token], index: usize) -> Identifier {
|
fn make_identifier(tokens: &[Token], index: usize) -> Identifier {
|
||||||
let current_token = &tokens[index];
|
let current_token = &tokens[index];
|
||||||
@ -79,10 +80,7 @@ fn make_none_code_node(tokens: &[Token], index: usize) -> (Option<NoneCodeNode>,
|
|||||||
find_end_of_non_code_node(tokens, index)
|
find_end_of_non_code_node(tokens, index)
|
||||||
};
|
};
|
||||||
let non_code_tokens = tokens[index..end_index].to_vec();
|
let non_code_tokens = tokens[index..end_index].to_vec();
|
||||||
let value = non_code_tokens
|
let value = non_code_tokens.iter().map(|t| t.value.clone()).collect::<String>();
|
||||||
.iter()
|
|
||||||
.map(|t| t.value.clone())
|
|
||||||
.collect::<String>();
|
|
||||||
|
|
||||||
let node = NoneCodeNode {
|
let node = NoneCodeNode {
|
||||||
start: current_token.start,
|
start: current_token.start,
|
||||||
@ -105,11 +103,7 @@ struct TokenReturnWithNonCode {
|
|||||||
non_code_node: Option<NoneCodeNode>,
|
non_code_node: Option<NoneCodeNode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_meaningful_token(
|
fn next_meaningful_token(tokens: &[Token], index: usize, offset: Option<usize>) -> TokenReturnWithNonCode {
|
||||||
tokens: &[Token],
|
|
||||||
index: usize,
|
|
||||||
offset: Option<usize>,
|
|
||||||
) -> TokenReturnWithNonCode {
|
|
||||||
let new_index = index + offset.unwrap_or(1);
|
let new_index = index + offset.unwrap_or(1);
|
||||||
let _token = tokens.get(new_index);
|
let _token = tokens.get(new_index);
|
||||||
let token = if let Some(token) = _token {
|
let token = if let Some(token) = _token {
|
||||||
@ -150,10 +144,7 @@ pub fn find_closing_brace(
|
|||||||
brace_count: usize,
|
brace_count: usize,
|
||||||
search_opening_brace: &str,
|
search_opening_brace: &str,
|
||||||
) -> Result<usize, KclError> {
|
) -> Result<usize, KclError> {
|
||||||
let closing_brace_map: HashMap<&str, &str> = [("(", ")"), ("{", "}"), ("[", "]")]
|
let closing_brace_map: HashMap<&str, &str> = [("(", ")"), ("{", "}"), ("[", "]")].iter().cloned().collect();
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
let current_token = &tokens[index];
|
let current_token = &tokens[index];
|
||||||
let mut search_opening_brace = search_opening_brace;
|
let mut search_opening_brace = search_opening_brace;
|
||||||
let is_first_call = search_opening_brace.is_empty() && brace_count == 0;
|
let is_first_call = search_opening_brace.is_empty() && brace_count == 0;
|
||||||
@ -169,11 +160,9 @@ pub fn find_closing_brace(
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let found_closing_brace =
|
let found_closing_brace = brace_count == 1 && current_token.value == closing_brace_map[search_opening_brace];
|
||||||
brace_count == 1 && current_token.value == closing_brace_map[search_opening_brace];
|
|
||||||
let found_another_opening_brace = current_token.value == search_opening_brace;
|
let found_another_opening_brace = current_token.value == search_opening_brace;
|
||||||
let found_another_closing_brace =
|
let found_another_closing_brace = current_token.value == closing_brace_map[search_opening_brace];
|
||||||
current_token.value == closing_brace_map[search_opening_brace];
|
|
||||||
if found_closing_brace {
|
if found_closing_brace {
|
||||||
return Ok(index);
|
return Ok(index);
|
||||||
}
|
}
|
||||||
@ -218,9 +207,7 @@ fn find_next_declaration_keyword(tokens: &[Token], index: usize) -> Result<Token
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if let Some(token_val) = next_token.token {
|
if let Some(token_val) = next_token.token {
|
||||||
if token_val.token_type == TokenType::Word
|
if token_val.token_type == TokenType::Word && (token_val.value == "const" || token_val.value == "fn") {
|
||||||
&& (token_val.value == "const" || token_val.value == "fn")
|
|
||||||
{
|
|
||||||
return Ok(TokenReturn {
|
return Ok(TokenReturn {
|
||||||
token: Some(token_val),
|
token: Some(token_val),
|
||||||
index: next_token.index,
|
index: next_token.index,
|
||||||
@ -275,8 +262,7 @@ fn has_pipe_operator(
|
|||||||
let current_token = &tokens[index];
|
let current_token = &tokens[index];
|
||||||
if current_token.token_type == TokenType::Brace && current_token.value == "{" {
|
if current_token.token_type == TokenType::Brace && current_token.value == "{" {
|
||||||
let closing_brace_index = find_closing_brace(tokens, index, 0, "")?;
|
let closing_brace_index = find_closing_brace(tokens, index, 0, "")?;
|
||||||
let token_after_closing_brace =
|
let token_after_closing_brace = next_meaningful_token(tokens, closing_brace_index, None);
|
||||||
next_meaningful_token(tokens, closing_brace_index, None);
|
|
||||||
if let Some(token_after_closing_brace_val) = token_after_closing_brace.token {
|
if let Some(token_after_closing_brace_val) = token_after_closing_brace.token {
|
||||||
if token_after_closing_brace_val.token_type == TokenType::Operator
|
if token_after_closing_brace_val.token_type == TokenType::Operator
|
||||||
&& token_after_closing_brace_val.value == "|>"
|
&& token_after_closing_brace_val.value == "|>"
|
||||||
@ -393,10 +379,7 @@ pub struct MemberExpressionReturn {
|
|||||||
pub last_index: usize,
|
pub last_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_member_expression(
|
fn make_member_expression(tokens: &[Token], index: usize) -> Result<MemberExpressionReturn, KclError> {
|
||||||
tokens: &[Token],
|
|
||||||
index: usize,
|
|
||||||
) -> Result<MemberExpressionReturn, KclError> {
|
|
||||||
let current_token = tokens[index].clone();
|
let current_token = tokens[index].clone();
|
||||||
let mut keys_info = collect_object_keys(tokens, index, None)?;
|
let mut keys_info = collect_object_keys(tokens, index, None)?;
|
||||||
let last_key = keys_info[keys_info.len() - 1].clone();
|
let last_key = keys_info[keys_info.len() - 1].clone();
|
||||||
@ -464,9 +447,7 @@ fn find_end_of_binary_expression(tokens: &[Token], index: usize) -> Result<usize
|
|||||||
}
|
}
|
||||||
let maybe_operator = next_meaningful_token(tokens, index, None);
|
let maybe_operator = next_meaningful_token(tokens, index, None);
|
||||||
if let Some(maybe_operator_token) = maybe_operator.token {
|
if let Some(maybe_operator_token) = maybe_operator.token {
|
||||||
if maybe_operator_token.token_type != TokenType::Operator
|
if maybe_operator_token.token_type != TokenType::Operator || maybe_operator_token.value == "|>" {
|
||||||
|| maybe_operator_token.value == "|>"
|
|
||||||
{
|
|
||||||
return Ok(index);
|
return Ok(index);
|
||||||
}
|
}
|
||||||
let next_right = next_meaningful_token(tokens, maybe_operator.index, None);
|
let next_right = next_meaningful_token(tokens, maybe_operator.index, None);
|
||||||
@ -502,10 +483,7 @@ fn make_value(tokens: &[Token], index: usize) -> Result<ValueReturn, KclError> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(KclError::Unimplemented(KclErrorDetails {
|
return Err(KclError::Unimplemented(KclErrorDetails {
|
||||||
source_ranges: vec![current_token.into()],
|
source_ranges: vec![current_token.into()],
|
||||||
message: format!(
|
message: format!("expression with token type {:?}", current_token.token_type),
|
||||||
"expression with token type {:?}",
|
|
||||||
current_token.token_type
|
|
||||||
),
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -564,9 +542,7 @@ fn make_value(tokens: &[Token], index: usize) -> Result<ValueReturn, KclError> {
|
|||||||
last_index: index,
|
last_index: index,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if current_token.token_type == TokenType::Number
|
if current_token.token_type == TokenType::Number || current_token.token_type == TokenType::String {
|
||||||
|| current_token.token_type == TokenType::String
|
|
||||||
{
|
|
||||||
let literal = make_literal(tokens, index)?;
|
let literal = make_literal(tokens, index)?;
|
||||||
return Ok(ValueReturn {
|
return Ok(ValueReturn {
|
||||||
value: Value::Literal(Box::new(literal)),
|
value: Value::Literal(Box::new(literal)),
|
||||||
@ -576,9 +552,7 @@ fn make_value(tokens: &[Token], index: usize) -> Result<ValueReturn, KclError> {
|
|||||||
|
|
||||||
if current_token.token_type == TokenType::Brace && current_token.value == "(" {
|
if current_token.token_type == TokenType::Brace && current_token.value == "(" {
|
||||||
let closing_brace_index = find_closing_brace(tokens, index, 0, "")?;
|
let closing_brace_index = find_closing_brace(tokens, index, 0, "")?;
|
||||||
return if let Some(arrow_token) =
|
return if let Some(arrow_token) = next_meaningful_token(tokens, closing_brace_index, None).token {
|
||||||
next_meaningful_token(tokens, closing_brace_index, None).token
|
|
||||||
{
|
|
||||||
if arrow_token.token_type == TokenType::Operator && arrow_token.value == "=>" {
|
if arrow_token.token_type == TokenType::Operator && arrow_token.value == "=>" {
|
||||||
let function_expression = make_function_expression(tokens, index)?;
|
let function_expression = make_function_expression(tokens, index)?;
|
||||||
Ok(ValueReturn {
|
Ok(ValueReturn {
|
||||||
@ -633,16 +607,12 @@ fn make_array_elements(
|
|||||||
let current_element = make_value(tokens, index)?;
|
let current_element = make_value(tokens, index)?;
|
||||||
let next_token = next_meaningful_token(tokens, current_element.last_index, None);
|
let next_token = next_meaningful_token(tokens, current_element.last_index, None);
|
||||||
if let Some(next_token_token) = next_token.token {
|
if let Some(next_token_token) = next_token.token {
|
||||||
let is_closing_brace =
|
let is_closing_brace = next_token_token.token_type == TokenType::Brace && next_token_token.value == "]";
|
||||||
next_token_token.token_type == TokenType::Brace && next_token_token.value == "]";
|
|
||||||
let is_comma = next_token_token.token_type == TokenType::Comma;
|
let is_comma = next_token_token.token_type == TokenType::Comma;
|
||||||
if !is_closing_brace && !is_comma {
|
if !is_closing_brace && !is_comma {
|
||||||
return Err(KclError::Syntax(KclErrorDetails {
|
return Err(KclError::Syntax(KclErrorDetails {
|
||||||
source_ranges: vec![next_token_token.clone().into()],
|
source_ranges: vec![next_token_token.clone().into()],
|
||||||
message: format!(
|
message: format!("Expected a comma or closing brace, found {:?}", next_token_token.value),
|
||||||
"Expected a comma or closing brace, found {:?}",
|
|
||||||
next_token_token.value
|
|
||||||
),
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
let next_call_index = if is_closing_brace {
|
let next_call_index = if is_closing_brace {
|
||||||
@ -711,10 +681,7 @@ fn make_pipe_body(
|
|||||||
} else {
|
} else {
|
||||||
return Err(KclError::Syntax(KclErrorDetails {
|
return Err(KclError::Syntax(KclErrorDetails {
|
||||||
source_ranges: vec![current_token.into()],
|
source_ranges: vec![current_token.into()],
|
||||||
message: format!(
|
message: format!("Expected a pipe value, found {:?}", current_token.token_type),
|
||||||
"Expected a pipe value, found {:?}",
|
|
||||||
current_token.token_type
|
|
||||||
),
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
let next_pipe = has_pipe_operator(tokens, index, None)?;
|
let next_pipe = has_pipe_operator(tokens, index, None)?;
|
||||||
@ -730,20 +697,13 @@ fn make_pipe_body(
|
|||||||
let mut _non_code_meta: NoneCodeMeta;
|
let mut _non_code_meta: NoneCodeMeta;
|
||||||
if let Some(node) = next_pipe.non_code_node {
|
if let Some(node) = next_pipe.non_code_node {
|
||||||
_non_code_meta = non_code_meta;
|
_non_code_meta = non_code_meta;
|
||||||
_non_code_meta
|
_non_code_meta.none_code_nodes.insert(previous_values.len(), node);
|
||||||
.none_code_nodes
|
|
||||||
.insert(previous_values.len(), node);
|
|
||||||
} else {
|
} else {
|
||||||
_non_code_meta = non_code_meta;
|
_non_code_meta = non_code_meta;
|
||||||
}
|
}
|
||||||
let mut _previous_values = previous_values;
|
let mut _previous_values = previous_values;
|
||||||
_previous_values.push(value);
|
_previous_values.push(value);
|
||||||
make_pipe_body(
|
make_pipe_body(tokens, next_pipe.index, _previous_values, Some(_non_code_meta))
|
||||||
tokens,
|
|
||||||
next_pipe.index,
|
|
||||||
_previous_values,
|
|
||||||
Some(_non_code_meta),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BinaryExpressionReturn {
|
struct BinaryExpressionReturn {
|
||||||
@ -751,10 +711,7 @@ struct BinaryExpressionReturn {
|
|||||||
last_index: usize,
|
last_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_binary_expression(
|
fn make_binary_expression(tokens: &[Token], index: usize) -> Result<BinaryExpressionReturn, KclError> {
|
||||||
tokens: &[Token],
|
|
||||||
index: usize,
|
|
||||||
) -> Result<BinaryExpressionReturn, KclError> {
|
|
||||||
let end_index = find_end_of_binary_expression(tokens, index)?;
|
let end_index = find_end_of_binary_expression(tokens, index)?;
|
||||||
let expression = parse_expression(&tokens[index..end_index + 1])?;
|
let expression = parse_expression(&tokens[index..end_index + 1])?;
|
||||||
Ok(BinaryExpressionReturn {
|
Ok(BinaryExpressionReturn {
|
||||||
@ -768,11 +725,7 @@ struct ArgumentsReturn {
|
|||||||
last_index: usize,
|
last_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_arguments(
|
fn make_arguments(tokens: &[Token], index: usize, previous_args: Vec<Value>) -> Result<ArgumentsReturn, KclError> {
|
||||||
tokens: &[Token],
|
|
||||||
index: usize,
|
|
||||||
previous_args: Vec<Value>,
|
|
||||||
) -> Result<ArgumentsReturn, KclError> {
|
|
||||||
let brace_or_comma_token = &tokens[index];
|
let brace_or_comma_token = &tokens[index];
|
||||||
let should_finish_recursion =
|
let should_finish_recursion =
|
||||||
brace_or_comma_token.token_type == TokenType::Brace && brace_or_comma_token.value == ")";
|
brace_or_comma_token.token_type == TokenType::Brace && brace_or_comma_token.value == ")";
|
||||||
@ -788,40 +741,28 @@ fn make_arguments(
|
|||||||
if let Some(next_brace_or_comma_token) = next_brace_or_comma.token {
|
if let Some(next_brace_or_comma_token) = next_brace_or_comma.token {
|
||||||
let is_identifier_or_literal = next_brace_or_comma_token.token_type == TokenType::Comma
|
let is_identifier_or_literal = next_brace_or_comma_token.token_type == TokenType::Comma
|
||||||
|| next_brace_or_comma_token.token_type == TokenType::Brace;
|
|| next_brace_or_comma_token.token_type == TokenType::Brace;
|
||||||
if argument_token_token.token_type == TokenType::Brace
|
if argument_token_token.token_type == TokenType::Brace && argument_token_token.value == "[" {
|
||||||
&& argument_token_token.value == "["
|
|
||||||
{
|
|
||||||
let array_expression = make_array_expression(tokens, argument_token.index)?;
|
let array_expression = make_array_expression(tokens, argument_token.index)?;
|
||||||
let next_comma_or_brace_token_index =
|
let next_comma_or_brace_token_index =
|
||||||
next_meaningful_token(tokens, array_expression.last_index, None).index;
|
next_meaningful_token(tokens, array_expression.last_index, None).index;
|
||||||
let mut _previous_args = previous_args;
|
let mut _previous_args = previous_args;
|
||||||
_previous_args.push(Value::ArrayExpression(Box::new(
|
_previous_args.push(Value::ArrayExpression(Box::new(array_expression.expression)));
|
||||||
array_expression.expression,
|
|
||||||
)));
|
|
||||||
return make_arguments(tokens, next_comma_or_brace_token_index, _previous_args);
|
return make_arguments(tokens, next_comma_or_brace_token_index, _previous_args);
|
||||||
}
|
}
|
||||||
if argument_token_token.token_type == TokenType::Operator
|
if argument_token_token.token_type == TokenType::Operator && argument_token_token.value == "-" {
|
||||||
&& argument_token_token.value == "-"
|
|
||||||
{
|
|
||||||
let unary_expression = make_unary_expression(tokens, argument_token.index)?;
|
let unary_expression = make_unary_expression(tokens, argument_token.index)?;
|
||||||
let next_comma_or_brace_token_index =
|
let next_comma_or_brace_token_index =
|
||||||
next_meaningful_token(tokens, unary_expression.last_index, None).index;
|
next_meaningful_token(tokens, unary_expression.last_index, None).index;
|
||||||
let mut _previous_args = previous_args;
|
let mut _previous_args = previous_args;
|
||||||
_previous_args.push(Value::UnaryExpression(Box::new(
|
_previous_args.push(Value::UnaryExpression(Box::new(unary_expression.expression)));
|
||||||
unary_expression.expression,
|
|
||||||
)));
|
|
||||||
return make_arguments(tokens, next_comma_or_brace_token_index, _previous_args);
|
return make_arguments(tokens, next_comma_or_brace_token_index, _previous_args);
|
||||||
}
|
}
|
||||||
if argument_token_token.token_type == TokenType::Brace
|
if argument_token_token.token_type == TokenType::Brace && argument_token_token.value == "{" {
|
||||||
&& argument_token_token.value == "{"
|
|
||||||
{
|
|
||||||
let object_expression = make_object_expression(tokens, argument_token.index)?;
|
let object_expression = make_object_expression(tokens, argument_token.index)?;
|
||||||
let next_comma_or_brace_token_index =
|
let next_comma_or_brace_token_index =
|
||||||
next_meaningful_token(tokens, object_expression.last_index, None).index;
|
next_meaningful_token(tokens, object_expression.last_index, None).index;
|
||||||
let mut _previous_args = previous_args;
|
let mut _previous_args = previous_args;
|
||||||
_previous_args.push(Value::ObjectExpression(Box::new(
|
_previous_args.push(Value::ObjectExpression(Box::new(object_expression.expression)));
|
||||||
object_expression.expression,
|
|
||||||
)));
|
|
||||||
return make_arguments(tokens, next_comma_or_brace_token_index, _previous_args);
|
return make_arguments(tokens, next_comma_or_brace_token_index, _previous_args);
|
||||||
}
|
}
|
||||||
if (argument_token_token.token_type == TokenType::Word
|
if (argument_token_token.token_type == TokenType::Word
|
||||||
@ -833,23 +774,17 @@ fn make_arguments(
|
|||||||
let next_comma_or_brace_token_index =
|
let next_comma_or_brace_token_index =
|
||||||
next_meaningful_token(tokens, binary_expression.last_index, None).index;
|
next_meaningful_token(tokens, binary_expression.last_index, None).index;
|
||||||
let mut _previous_args = previous_args;
|
let mut _previous_args = previous_args;
|
||||||
_previous_args.push(Value::BinaryExpression(Box::new(
|
_previous_args.push(Value::BinaryExpression(Box::new(binary_expression.expression)));
|
||||||
binary_expression.expression,
|
|
||||||
)));
|
|
||||||
return make_arguments(tokens, next_comma_or_brace_token_index, _previous_args);
|
return make_arguments(tokens, next_comma_or_brace_token_index, _previous_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !is_identifier_or_literal {
|
if !is_identifier_or_literal {
|
||||||
let binary_expression = make_binary_expression(tokens, next_brace_or_comma.index)?;
|
let binary_expression = make_binary_expression(tokens, next_brace_or_comma.index)?;
|
||||||
let mut _previous_args = previous_args;
|
let mut _previous_args = previous_args;
|
||||||
_previous_args.push(Value::BinaryExpression(Box::new(
|
_previous_args.push(Value::BinaryExpression(Box::new(binary_expression.expression)));
|
||||||
binary_expression.expression,
|
|
||||||
)));
|
|
||||||
return make_arguments(tokens, binary_expression.last_index, _previous_args);
|
return make_arguments(tokens, binary_expression.last_index, _previous_args);
|
||||||
}
|
}
|
||||||
if argument_token_token.token_type == TokenType::Operator
|
if argument_token_token.token_type == TokenType::Operator && argument_token_token.value == "%" {
|
||||||
&& argument_token_token.value == "%"
|
|
||||||
{
|
|
||||||
let value = Value::PipeSubstitution(Box::new(PipeSubstitution {
|
let value = Value::PipeSubstitution(Box::new(PipeSubstitution {
|
||||||
start: argument_token_token.start,
|
start: argument_token_token.start,
|
||||||
end: argument_token_token.end,
|
end: argument_token_token.end,
|
||||||
@ -864,28 +799,23 @@ fn make_arguments(
|
|||||||
&& next_brace_or_comma_token.value == "("
|
&& next_brace_or_comma_token.value == "("
|
||||||
{
|
{
|
||||||
let closing_brace = find_closing_brace(tokens, next_brace_or_comma.index, 0, "")?;
|
let closing_brace = find_closing_brace(tokens, next_brace_or_comma.index, 0, "")?;
|
||||||
return if let Some(token_after_closing_brace) =
|
return if let Some(token_after_closing_brace) = next_meaningful_token(tokens, closing_brace, None).token
|
||||||
next_meaningful_token(tokens, closing_brace, None).token
|
|
||||||
{
|
{
|
||||||
if token_after_closing_brace.token_type == TokenType::Operator
|
if token_after_closing_brace.token_type == TokenType::Operator
|
||||||
&& token_after_closing_brace.value != "|>"
|
&& token_after_closing_brace.value != "|>"
|
||||||
{
|
{
|
||||||
let binary_expression =
|
let binary_expression = make_binary_expression(tokens, argument_token.index)?;
|
||||||
make_binary_expression(tokens, argument_token.index)?;
|
|
||||||
let next_comma_or_brace_token_index =
|
let next_comma_or_brace_token_index =
|
||||||
next_meaningful_token(tokens, binary_expression.last_index, None).index;
|
next_meaningful_token(tokens, binary_expression.last_index, None).index;
|
||||||
let mut _previous_args = previous_args;
|
let mut _previous_args = previous_args;
|
||||||
_previous_args.push(Value::BinaryExpression(Box::new(
|
_previous_args.push(Value::BinaryExpression(Box::new(binary_expression.expression)));
|
||||||
binary_expression.expression,
|
|
||||||
)));
|
|
||||||
make_arguments(tokens, next_comma_or_brace_token_index, _previous_args)
|
make_arguments(tokens, next_comma_or_brace_token_index, _previous_args)
|
||||||
} else {
|
} else {
|
||||||
let call_expression = make_call_expression(tokens, argument_token.index)?;
|
let call_expression = make_call_expression(tokens, argument_token.index)?;
|
||||||
let next_comma_or_brace_token_index =
|
let next_comma_or_brace_token_index =
|
||||||
next_meaningful_token(tokens, call_expression.last_index, None).index;
|
next_meaningful_token(tokens, call_expression.last_index, None).index;
|
||||||
let mut _previous_args = previous_args;
|
let mut _previous_args = previous_args;
|
||||||
_previous_args
|
_previous_args.push(Value::CallExpression(Box::new(call_expression.expression)));
|
||||||
.push(Value::CallExpression(Box::new(call_expression.expression)));
|
|
||||||
make_arguments(tokens, next_comma_or_brace_token_index, _previous_args)
|
make_arguments(tokens, next_comma_or_brace_token_index, _previous_args)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -897,8 +827,7 @@ fn make_arguments(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if argument_token_token.token_type == TokenType::Word {
|
if argument_token_token.token_type == TokenType::Word {
|
||||||
let identifier =
|
let identifier = Value::Identifier(Box::new(make_identifier(tokens, argument_token.index)));
|
||||||
Value::Identifier(Box::new(make_identifier(tokens, argument_token.index)));
|
|
||||||
let mut _previous_args = previous_args;
|
let mut _previous_args = previous_args;
|
||||||
_previous_args.push(identifier);
|
_previous_args.push(identifier);
|
||||||
return make_arguments(tokens, next_brace_or_comma.index, _previous_args);
|
return make_arguments(tokens, next_brace_or_comma.index, _previous_args);
|
||||||
@ -909,9 +838,7 @@ fn make_arguments(
|
|||||||
let mut _previous_args = previous_args;
|
let mut _previous_args = previous_args;
|
||||||
_previous_args.push(literal);
|
_previous_args.push(literal);
|
||||||
return make_arguments(tokens, next_brace_or_comma.index, _previous_args);
|
return make_arguments(tokens, next_brace_or_comma.index, _previous_args);
|
||||||
} else if argument_token_token.token_type == TokenType::Brace
|
} else if argument_token_token.token_type == TokenType::Brace && argument_token_token.value == ")" {
|
||||||
&& argument_token_token.value == ")"
|
|
||||||
{
|
|
||||||
return make_arguments(tokens, argument_token.index, previous_args);
|
return make_arguments(tokens, argument_token.index, previous_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -938,10 +865,7 @@ pub struct CallExpressionResult {
|
|||||||
last_index: usize,
|
last_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_call_expression(
|
pub fn make_call_expression(tokens: &[Token], index: usize) -> Result<CallExpressionResult, KclError> {
|
||||||
tokens: &[Token],
|
|
||||||
index: usize,
|
|
||||||
) -> Result<CallExpressionResult, KclError> {
|
|
||||||
let current_token = tokens[index].clone();
|
let current_token = tokens[index].clone();
|
||||||
let brace_token = next_meaningful_token(tokens, index, None);
|
let brace_token = next_meaningful_token(tokens, index, None);
|
||||||
let callee = make_identifier(tokens, index);
|
let callee = make_identifier(tokens, index);
|
||||||
@ -1034,20 +958,14 @@ struct VariableDeclarationResult {
|
|||||||
last_index: usize,
|
last_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_variable_declaration(
|
fn make_variable_declaration(tokens: &[Token], index: usize) -> Result<VariableDeclarationResult, KclError> {
|
||||||
tokens: &[Token],
|
|
||||||
index: usize,
|
|
||||||
) -> Result<VariableDeclarationResult, KclError> {
|
|
||||||
let current_token = tokens[index].clone();
|
let current_token = tokens[index].clone();
|
||||||
let declaration_start_token = next_meaningful_token(tokens, index, None);
|
let declaration_start_token = next_meaningful_token(tokens, index, None);
|
||||||
let variable_declarators_result =
|
let variable_declarators_result = make_variable_declarators(tokens, declaration_start_token.index, vec![])?;
|
||||||
make_variable_declarators(tokens, declaration_start_token.index, vec![])?;
|
|
||||||
Ok(VariableDeclarationResult {
|
Ok(VariableDeclarationResult {
|
||||||
declaration: VariableDeclaration {
|
declaration: VariableDeclaration {
|
||||||
start: current_token.start,
|
start: current_token.start,
|
||||||
end: variable_declarators_result.declarations
|
end: variable_declarators_result.declarations[variable_declarators_result.declarations.len() - 1].end,
|
||||||
[variable_declarators_result.declarations.len() - 1]
|
|
||||||
.end,
|
|
||||||
kind: if current_token.value == "const" {
|
kind: if current_token.value == "const" {
|
||||||
"const".to_string()
|
"const".to_string()
|
||||||
} else if current_token.value == "fn" {
|
} else if current_token.value == "fn" {
|
||||||
@ -1066,18 +984,12 @@ pub struct ParamsResult {
|
|||||||
pub last_index: usize,
|
pub last_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_params(
|
fn make_params(tokens: &[Token], index: usize, previous_params: Vec<Identifier>) -> Result<ParamsResult, KclError> {
|
||||||
tokens: &[Token],
|
|
||||||
index: usize,
|
|
||||||
previous_params: Vec<Identifier>,
|
|
||||||
) -> Result<ParamsResult, KclError> {
|
|
||||||
let brace_or_comma_token = &tokens[index];
|
let brace_or_comma_token = &tokens[index];
|
||||||
let argument = next_meaningful_token(tokens, index, None);
|
let argument = next_meaningful_token(tokens, index, None);
|
||||||
if let Some(argument_token) = argument.token {
|
if let Some(argument_token) = argument.token {
|
||||||
let should_finish_recursion = (argument_token.token_type == TokenType::Brace
|
let should_finish_recursion = (argument_token.token_type == TokenType::Brace && argument_token.value == ")")
|
||||||
&& argument_token.value == ")")
|
|| (brace_or_comma_token.token_type == TokenType::Brace && brace_or_comma_token.value == ")");
|
||||||
|| (brace_or_comma_token.token_type == TokenType::Brace
|
|
||||||
&& brace_or_comma_token.value == ")");
|
|
||||||
if should_finish_recursion {
|
if should_finish_recursion {
|
||||||
return Ok(ParamsResult {
|
return Ok(ParamsResult {
|
||||||
params: previous_params,
|
params: previous_params,
|
||||||
@ -1102,10 +1014,7 @@ struct UnaryExpressionResult {
|
|||||||
last_index: usize,
|
last_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_unary_expression(
|
fn make_unary_expression(tokens: &[Token], index: usize) -> Result<UnaryExpressionResult, KclError> {
|
||||||
tokens: &[Token],
|
|
||||||
index: usize,
|
|
||||||
) -> Result<UnaryExpressionResult, KclError> {
|
|
||||||
let current_token = &tokens[index];
|
let current_token = &tokens[index];
|
||||||
let next_token = next_meaningful_token(tokens, index, None);
|
let next_token = next_meaningful_token(tokens, index, None);
|
||||||
let argument = make_value(tokens, next_token.index)?;
|
let argument = make_value(tokens, next_token.index)?;
|
||||||
@ -1120,17 +1029,11 @@ fn make_unary_expression(
|
|||||||
start: current_token.start,
|
start: current_token.start,
|
||||||
end: argument_token.end,
|
end: argument_token.end,
|
||||||
argument: match argument.value {
|
argument: match argument.value {
|
||||||
Value::BinaryExpression(binary_expression) => {
|
Value::BinaryExpression(binary_expression) => BinaryPart::BinaryExpression(binary_expression),
|
||||||
BinaryPart::BinaryExpression(binary_expression)
|
|
||||||
}
|
|
||||||
Value::Identifier(identifier) => BinaryPart::Identifier(identifier),
|
Value::Identifier(identifier) => BinaryPart::Identifier(identifier),
|
||||||
Value::Literal(literal) => BinaryPart::Literal(literal),
|
Value::Literal(literal) => BinaryPart::Literal(literal),
|
||||||
Value::UnaryExpression(unary_expression) => {
|
Value::UnaryExpression(unary_expression) => BinaryPart::UnaryExpression(unary_expression),
|
||||||
BinaryPart::UnaryExpression(unary_expression)
|
Value::CallExpression(call_expression) => BinaryPart::CallExpression(call_expression),
|
||||||
}
|
|
||||||
Value::CallExpression(call_expression) => {
|
|
||||||
BinaryPart::CallExpression(call_expression)
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(KclError::Syntax(KclErrorDetails {
|
return Err(KclError::Syntax(KclErrorDetails {
|
||||||
source_ranges: vec![current_token.into()],
|
source_ranges: vec![current_token.into()],
|
||||||
@ -1149,10 +1052,7 @@ struct ExpressionStatementResult {
|
|||||||
last_index: usize,
|
last_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_expression_statement(
|
fn make_expression_statement(tokens: &[Token], index: usize) -> Result<ExpressionStatementResult, KclError> {
|
||||||
tokens: &[Token],
|
|
||||||
index: usize,
|
|
||||||
) -> Result<ExpressionStatementResult, KclError> {
|
|
||||||
let current_token = &tokens[index];
|
let current_token = &tokens[index];
|
||||||
let next = next_meaningful_token(tokens, index, None);
|
let next = next_meaningful_token(tokens, index, None);
|
||||||
if let Some(next_token) = &next.token {
|
if let Some(next_token) = &next.token {
|
||||||
@ -1252,10 +1152,7 @@ struct ObjectExpressionResult {
|
|||||||
last_index: usize,
|
last_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_object_expression(
|
fn make_object_expression(tokens: &[Token], index: usize) -> Result<ObjectExpressionResult, KclError> {
|
||||||
tokens: &[Token],
|
|
||||||
index: usize,
|
|
||||||
) -> Result<ObjectExpressionResult, KclError> {
|
|
||||||
let opening_brace_token = &tokens[index];
|
let opening_brace_token = &tokens[index];
|
||||||
let first_property_token = next_meaningful_token(tokens, index, None);
|
let first_property_token = next_meaningful_token(tokens, index, None);
|
||||||
let object_properties = make_object_properties(tokens, first_property_token.index, vec![])?;
|
let object_properties = make_object_properties(tokens, first_property_token.index, vec![])?;
|
||||||
@ -1274,10 +1171,7 @@ struct ReturnStatementResult {
|
|||||||
last_index: usize,
|
last_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_return_statement(
|
fn make_return_statement(tokens: &[Token], index: usize) -> Result<ReturnStatementResult, KclError> {
|
||||||
tokens: &[Token],
|
|
||||||
index: usize,
|
|
||||||
) -> Result<ReturnStatementResult, KclError> {
|
|
||||||
let current_token = &tokens[index];
|
let current_token = &tokens[index];
|
||||||
let next_token = next_meaningful_token(tokens, index, None);
|
let next_token = next_meaningful_token(tokens, index, None);
|
||||||
let val = make_value(tokens, next_token.index)?;
|
let val = make_value(tokens, next_token.index)?;
|
||||||
@ -1329,9 +1223,7 @@ fn make_body(
|
|||||||
if previous_body.is_empty() {
|
if previous_body.is_empty() {
|
||||||
non_code_meta.start = next_token.non_code_node;
|
non_code_meta.start = next_token.non_code_node;
|
||||||
} else {
|
} else {
|
||||||
non_code_meta
|
non_code_meta.none_code_nodes.insert(previous_body.len(), node.clone());
|
||||||
.none_code_nodes
|
|
||||||
.insert(previous_body.len(), node.clone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return make_body(tokens, next_token.index, previous_body, non_code_meta);
|
return make_body(tokens, next_token.index, previous_body, non_code_meta);
|
||||||
@ -1339,18 +1231,14 @@ fn make_body(
|
|||||||
|
|
||||||
let next = next_meaningful_token(tokens, token_index, None);
|
let next = next_meaningful_token(tokens, token_index, None);
|
||||||
if let Some(node) = &next.non_code_node {
|
if let Some(node) = &next.non_code_node {
|
||||||
non_code_meta
|
non_code_meta.none_code_nodes.insert(previous_body.len(), node.clone());
|
||||||
.none_code_nodes
|
|
||||||
.insert(previous_body.len(), node.clone());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if token.token_type == TokenType::Word && (token.value == *"const" || token.value == "fn") {
|
if token.token_type == TokenType::Word && (token.value == *"const" || token.value == "fn") {
|
||||||
let declaration = make_variable_declaration(tokens, token_index)?;
|
let declaration = make_variable_declaration(tokens, token_index)?;
|
||||||
let next_thing = next_meaningful_token(tokens, declaration.last_index, None);
|
let next_thing = next_meaningful_token(tokens, declaration.last_index, None);
|
||||||
if let Some(node) = &next_thing.non_code_node {
|
if let Some(node) = &next_thing.non_code_node {
|
||||||
non_code_meta
|
non_code_meta.none_code_nodes.insert(previous_body.len(), node.clone());
|
||||||
.none_code_nodes
|
|
||||||
.insert(previous_body.len(), node.clone());
|
|
||||||
}
|
}
|
||||||
let mut _previous_body = previous_body;
|
let mut _previous_body = previous_body;
|
||||||
_previous_body.push(BodyItem::VariableDeclaration(VariableDeclaration {
|
_previous_body.push(BodyItem::VariableDeclaration(VariableDeclaration {
|
||||||
@ -1371,9 +1259,7 @@ fn make_body(
|
|||||||
let statement = make_return_statement(tokens, token_index)?;
|
let statement = make_return_statement(tokens, token_index)?;
|
||||||
let next_thing = next_meaningful_token(tokens, statement.last_index, None);
|
let next_thing = next_meaningful_token(tokens, statement.last_index, None);
|
||||||
if let Some(node) = &next_thing.non_code_node {
|
if let Some(node) = &next_thing.non_code_node {
|
||||||
non_code_meta
|
non_code_meta.none_code_nodes.insert(previous_body.len(), node.clone());
|
||||||
.none_code_nodes
|
|
||||||
.insert(previous_body.len(), node.clone());
|
|
||||||
}
|
}
|
||||||
let mut _previous_body = previous_body;
|
let mut _previous_body = previous_body;
|
||||||
_previous_body.push(BodyItem::ReturnStatement(ReturnStatement {
|
_previous_body.push(BodyItem::ReturnStatement(ReturnStatement {
|
||||||
@ -1390,16 +1276,11 @@ fn make_body(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(next_token) = next.token {
|
if let Some(next_token) = next.token {
|
||||||
if token.token_type == TokenType::Word
|
if token.token_type == TokenType::Word && next_token.token_type == TokenType::Brace && next_token.value == "(" {
|
||||||
&& next_token.token_type == TokenType::Brace
|
|
||||||
&& next_token.value == "("
|
|
||||||
{
|
|
||||||
let expression = make_expression_statement(tokens, token_index)?;
|
let expression = make_expression_statement(tokens, token_index)?;
|
||||||
let next_thing = next_meaningful_token(tokens, expression.last_index, None);
|
let next_thing = next_meaningful_token(tokens, expression.last_index, None);
|
||||||
if let Some(node) = &next_thing.non_code_node {
|
if let Some(node) = &next_thing.non_code_node {
|
||||||
non_code_meta
|
non_code_meta.none_code_nodes.insert(previous_body.len(), node.clone());
|
||||||
.none_code_nodes
|
|
||||||
.insert(previous_body.len(), node.clone());
|
|
||||||
}
|
}
|
||||||
let mut _previous_body = previous_body;
|
let mut _previous_body = previous_body;
|
||||||
_previous_body.push(BodyItem::ExpressionStatement(ExpressionStatement {
|
_previous_body.push(BodyItem::ExpressionStatement(ExpressionStatement {
|
||||||
@ -1422,9 +1303,7 @@ fn make_body(
|
|||||||
&& next_thing_token.token_type == TokenType::Operator
|
&& next_thing_token.token_type == TokenType::Operator
|
||||||
{
|
{
|
||||||
if let Some(node) = &next_thing.non_code_node {
|
if let Some(node) = &next_thing.non_code_node {
|
||||||
non_code_meta
|
non_code_meta.none_code_nodes.insert(previous_body.len(), node.clone());
|
||||||
.none_code_nodes
|
|
||||||
.insert(previous_body.len(), node.clone());
|
|
||||||
}
|
}
|
||||||
let expression = make_expression_statement(tokens, token_index)?;
|
let expression = make_expression_statement(tokens, token_index)?;
|
||||||
let mut _previous_body = previous_body;
|
let mut _previous_body = previous_body;
|
||||||
@ -1492,10 +1371,7 @@ struct FunctionExpressionResult {
|
|||||||
last_index: usize,
|
last_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_function_expression(
|
fn make_function_expression(tokens: &[Token], index: usize) -> Result<FunctionExpressionResult, KclError> {
|
||||||
tokens: &[Token],
|
|
||||||
index: usize,
|
|
||||||
) -> Result<FunctionExpressionResult, KclError> {
|
|
||||||
let current_token = &tokens[index];
|
let current_token = &tokens[index];
|
||||||
let closing_brace_index = find_closing_brace(tokens, index, 0, "")?;
|
let closing_brace_index = find_closing_brace(tokens, index, 0, "")?;
|
||||||
let arrow_token = next_meaningful_token(tokens, closing_brace_index, None);
|
let arrow_token = next_meaningful_token(tokens, closing_brace_index, None);
|
||||||
@ -1538,9 +1414,10 @@ pub fn abstract_syntax_tree(tokens: &[Token]) -> Result<Program, KclError> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_make_identifier() {
|
fn test_make_identifier() {
|
||||||
let tokens = crate::tokeniser::lexer("a");
|
let tokens = crate::tokeniser::lexer("a");
|
||||||
@ -1701,8 +1578,7 @@ const key = 'c'"#,
|
|||||||
Some(NoneCodeNode {
|
Some(NoneCodeNode {
|
||||||
start: 106,
|
start: 106,
|
||||||
end: 166,
|
end: 166,
|
||||||
value: " /* this is\n a comment\n spanning a few lines */\n "
|
value: " /* this is\n a comment\n spanning a few lines */\n ".to_string(),
|
||||||
.to_string(),
|
|
||||||
}),
|
}),
|
||||||
59,
|
59,
|
||||||
);
|
);
|
||||||
@ -2226,8 +2102,7 @@ const key = 'c'"#,
|
|||||||
4
|
4
|
||||||
);
|
);
|
||||||
|
|
||||||
let handles_non_zero_index =
|
let handles_non_zero_index = "(indexForBracketToRightOfThisIsTwo(shouldBeFour)AndNotThisSix)";
|
||||||
"(indexForBracketToRightOfThisIsTwo(shouldBeFour)AndNotThisSix)";
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
find_closing_brace(&crate::tokeniser::lexer(handles_non_zero_index), 2, 0, "").unwrap(),
|
find_closing_brace(&crate::tokeniser::lexer(handles_non_zero_index), 2, 0, "").unwrap(),
|
||||||
4
|
4
|
||||||
@ -2279,10 +2154,7 @@ const key = 'c'"#,
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
find_next_declaration_keyword(&tokens, 4).unwrap(),
|
find_next_declaration_keyword(&tokens, 4).unwrap(),
|
||||||
TokenReturn {
|
TokenReturn { token: None, index: 92 }
|
||||||
token: None,
|
|
||||||
index: 92,
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let tokens = crate::tokeniser::lexer(
|
let tokens = crate::tokeniser::lexer(
|
||||||
@ -2304,10 +2176,7 @@ const newVar = myVar + 1
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
find_next_declaration_keyword(&tokens, 14).unwrap(),
|
find_next_declaration_keyword(&tokens, 14).unwrap(),
|
||||||
TokenReturn {
|
TokenReturn { token: None, index: 19 }
|
||||||
token: None,
|
|
||||||
index: 19,
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2401,10 +2270,7 @@ const yo = myFunc(9()
|
|||||||
} |> rx(90, %)
|
} |> rx(90, %)
|
||||||
show(mySk1)"#;
|
show(mySk1)"#;
|
||||||
let tokens = crate::tokeniser::lexer(code);
|
let tokens = crate::tokeniser::lexer(code);
|
||||||
let token_with_my_path_index = tokens
|
let token_with_my_path_index = tokens.iter().position(|token| token.value == "myPath").unwrap();
|
||||||
.iter()
|
|
||||||
.position(|token| token.value == "myPath")
|
|
||||||
.unwrap();
|
|
||||||
// loop through getting the token and it's index
|
// loop through getting the token and it's index
|
||||||
let token_with_line_to_index_for_var_dec_index = tokens
|
let token_with_line_to_index_for_var_dec_index = tokens
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -2,18 +2,14 @@
|
|||||||
//! The inverse of parsing (which generates an AST from the source code)
|
//! The inverse of parsing (which generates an AST from the source code)
|
||||||
|
|
||||||
use crate::abstract_syntax_tree_types::{
|
use crate::abstract_syntax_tree_types::{
|
||||||
ArrayExpression, BinaryExpression, BinaryPart, BodyItem, CallExpression, FunctionExpression,
|
ArrayExpression, BinaryExpression, BinaryPart, BodyItem, CallExpression, FunctionExpression, Literal,
|
||||||
Literal, LiteralIdentifier, MemberExpression, MemberObject, ObjectExpression, PipeExpression,
|
LiteralIdentifier, MemberExpression, MemberObject, ObjectExpression, PipeExpression, Program, UnaryExpression,
|
||||||
Program, UnaryExpression, Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn recast_literal(literal: Literal) -> String {
|
fn recast_literal(literal: Literal) -> String {
|
||||||
if let serde_json::Value::String(value) = literal.value {
|
if let serde_json::Value::String(value) = literal.value {
|
||||||
let quote = if literal.raw.trim().starts_with('"') {
|
let quote = if literal.raw.trim().starts_with('"') { '"' } else { '\'' };
|
||||||
'"'
|
|
||||||
} else {
|
|
||||||
'\''
|
|
||||||
};
|
|
||||||
format!("{}{}{}", quote, value, quote)
|
format!("{}{}{}", quote, value, quote)
|
||||||
} else {
|
} else {
|
||||||
literal.value.to_string()
|
literal.value.to_string()
|
||||||
@ -39,16 +35,13 @@ fn recast_binary_expression(expression: BinaryExpression) -> String {
|
|||||||
|
|
||||||
let should_wrap_right = match expression.right.clone() {
|
let should_wrap_right = match expression.right.clone() {
|
||||||
BinaryPart::BinaryExpression(bin_exp) => {
|
BinaryPart::BinaryExpression(bin_exp) => {
|
||||||
precedence(&expression.operator) > precedence(&bin_exp.operator)
|
precedence(&expression.operator) > precedence(&bin_exp.operator) || expression.operator == "-"
|
||||||
|| expression.operator == "-"
|
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let should_wrap_left = match expression.left.clone() {
|
let should_wrap_left = match expression.left.clone() {
|
||||||
BinaryPart::BinaryExpression(bin_exp) => {
|
BinaryPart::BinaryExpression(bin_exp) => precedence(&expression.operator) > precedence(&bin_exp.operator),
|
||||||
precedence(&expression.operator) > precedence(&bin_exp.operator)
|
|
||||||
}
|
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -64,12 +57,8 @@ fn recast_binary_part(part: BinaryPart) -> String {
|
|||||||
match part {
|
match part {
|
||||||
BinaryPart::Literal(literal) => recast_literal(*literal),
|
BinaryPart::Literal(literal) => recast_literal(*literal),
|
||||||
BinaryPart::Identifier(identifier) => identifier.name,
|
BinaryPart::Identifier(identifier) => identifier.name,
|
||||||
BinaryPart::BinaryExpression(binary_expression) => {
|
BinaryPart::BinaryExpression(binary_expression) => recast_binary_expression(*binary_expression),
|
||||||
recast_binary_expression(*binary_expression)
|
BinaryPart::CallExpression(call_expression) => recast_call_expression(&call_expression, "", false),
|
||||||
}
|
|
||||||
BinaryPart::CallExpression(call_expression) => {
|
|
||||||
recast_call_expression(&call_expression, "", false)
|
|
||||||
}
|
|
||||||
_ => String::new(),
|
_ => String::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,15 +68,11 @@ fn recast_value(node: Value, _indentation: String, is_in_pipe_expression: bool)
|
|||||||
match node {
|
match node {
|
||||||
Value::BinaryExpression(bin_exp) => recast_binary_expression(*bin_exp),
|
Value::BinaryExpression(bin_exp) => recast_binary_expression(*bin_exp),
|
||||||
Value::ArrayExpression(array_exp) => recast_array_expression(&array_exp, &indentation),
|
Value::ArrayExpression(array_exp) => recast_array_expression(&array_exp, &indentation),
|
||||||
Value::ObjectExpression(ref obj_exp) => {
|
Value::ObjectExpression(ref obj_exp) => recast_object_expression(obj_exp, &indentation, is_in_pipe_expression),
|
||||||
recast_object_expression(obj_exp, &indentation, is_in_pipe_expression)
|
|
||||||
}
|
|
||||||
Value::MemberExpression(mem_exp) => recast_member_expression(*mem_exp),
|
Value::MemberExpression(mem_exp) => recast_member_expression(*mem_exp),
|
||||||
Value::Literal(literal) => recast_literal(*literal),
|
Value::Literal(literal) => recast_literal(*literal),
|
||||||
Value::FunctionExpression(func_exp) => recast_function(*func_exp),
|
Value::FunctionExpression(func_exp) => recast_function(*func_exp),
|
||||||
Value::CallExpression(call_exp) => {
|
Value::CallExpression(call_exp) => recast_call_expression(&call_exp, &indentation, is_in_pipe_expression),
|
||||||
recast_call_expression(&call_exp, &indentation, is_in_pipe_expression)
|
|
||||||
}
|
|
||||||
Value::Identifier(ident) => ident.name,
|
Value::Identifier(ident) => ident.name,
|
||||||
Value::PipeExpression(pipe_exp) => recast_pipe_expression(&pipe_exp),
|
Value::PipeExpression(pipe_exp) => recast_pipe_expression(&pipe_exp),
|
||||||
Value::UnaryExpression(unary_exp) => recast_unary_expression(*unary_exp),
|
Value::UnaryExpression(unary_exp) => recast_unary_expression(*unary_exp),
|
||||||
@ -124,11 +109,7 @@ fn recast_array_expression(expression: &ArrayExpression, indentation: &str) -> S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recast_object_expression(
|
fn recast_object_expression(expression: &ObjectExpression, indentation: &str, is_in_pipe_expression: bool) -> String {
|
||||||
expression: &ObjectExpression,
|
|
||||||
indentation: &str,
|
|
||||||
is_in_pipe_expression: bool,
|
|
||||||
) -> String {
|
|
||||||
let flat_recast = format!(
|
let flat_recast = format!(
|
||||||
"{{ {} }}",
|
"{{ {} }}",
|
||||||
expression
|
expression
|
||||||
@ -157,11 +138,7 @@ fn recast_object_expression(
|
|||||||
format!(
|
format!(
|
||||||
"{}: {}",
|
"{}: {}",
|
||||||
prop.key.name,
|
prop.key.name,
|
||||||
recast_value(
|
recast_value(prop.value.clone(), _indentation.clone(), is_in_pipe_expression)
|
||||||
prop.value.clone(),
|
|
||||||
_indentation.clone(),
|
|
||||||
is_in_pipe_expression
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
@ -173,11 +150,7 @@ fn recast_object_expression(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recast_call_expression(
|
fn recast_call_expression(expression: &CallExpression, indentation: &str, is_in_pipe_expression: bool) -> String {
|
||||||
expression: &CallExpression,
|
|
||||||
indentation: &str,
|
|
||||||
is_in_pipe_expression: bool,
|
|
||||||
) -> String {
|
|
||||||
format!(
|
format!(
|
||||||
"{}({})",
|
"{}({})",
|
||||||
expression.callee.name,
|
expression.callee.name,
|
||||||
@ -199,9 +172,7 @@ fn recast_argument(argument: Value, indentation: &str, is_in_pipe_expression: bo
|
|||||||
Value::ObjectExpression(object_exp) => {
|
Value::ObjectExpression(object_exp) => {
|
||||||
recast_object_expression(&object_exp, indentation, is_in_pipe_expression)
|
recast_object_expression(&object_exp, indentation, is_in_pipe_expression)
|
||||||
}
|
}
|
||||||
Value::CallExpression(call_exp) => {
|
Value::CallExpression(call_exp) => recast_call_expression(&call_exp, indentation, is_in_pipe_expression),
|
||||||
recast_call_expression(&call_exp, indentation, is_in_pipe_expression)
|
|
||||||
}
|
|
||||||
Value::FunctionExpression(function_exp) => recast_function(*function_exp),
|
Value::FunctionExpression(function_exp) => recast_function(*function_exp),
|
||||||
Value::PipeSubstitution(_) => "%".to_string(),
|
Value::PipeSubstitution(_) => "%".to_string(),
|
||||||
Value::UnaryExpression(unary_exp) => recast_unary_expression(*unary_exp),
|
Value::UnaryExpression(unary_exp) => recast_unary_expression(*unary_exp),
|
||||||
@ -222,9 +193,7 @@ fn recast_member_expression(expression: MemberExpression) -> String {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match expression.object {
|
match expression.object {
|
||||||
MemberObject::MemberExpression(member_exp) => {
|
MemberObject::MemberExpression(member_exp) => recast_member_expression(*member_exp) + key_str.as_str(),
|
||||||
recast_member_expression(*member_exp) + key_str.as_str()
|
|
||||||
}
|
|
||||||
MemberObject::Identifier(identifier) => identifier.name + key_str.as_str(),
|
MemberObject::Identifier(identifier) => identifier.name + key_str.as_str(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,9 +230,7 @@ fn recast_unary_expression(expression: UnaryExpression) -> String {
|
|||||||
let bin_part_val = match expression.argument {
|
let bin_part_val = match expression.argument {
|
||||||
BinaryPart::Literal(literal) => Value::Literal(literal),
|
BinaryPart::Literal(literal) => Value::Literal(literal),
|
||||||
BinaryPart::Identifier(identifier) => Value::Identifier(identifier),
|
BinaryPart::Identifier(identifier) => Value::Identifier(identifier),
|
||||||
BinaryPart::BinaryExpression(binary_expression) => {
|
BinaryPart::BinaryExpression(binary_expression) => Value::BinaryExpression(binary_expression),
|
||||||
Value::BinaryExpression(binary_expression)
|
|
||||||
}
|
|
||||||
BinaryPart::CallExpression(call_expression) => Value::CallExpression(call_expression),
|
BinaryPart::CallExpression(call_expression) => Value::CallExpression(call_expression),
|
||||||
BinaryPart::UnaryExpression(unary_expression) => Value::UnaryExpression(unary_expression),
|
BinaryPart::UnaryExpression(unary_expression) => Value::UnaryExpression(unary_expression),
|
||||||
};
|
};
|
||||||
@ -278,23 +245,13 @@ pub fn recast(ast: &Program, indentation: &str, is_with_block: bool) -> String {
|
|||||||
ast.body
|
ast.body
|
||||||
.iter()
|
.iter()
|
||||||
.map(|statement| match statement.clone() {
|
.map(|statement| match statement.clone() {
|
||||||
BodyItem::ExpressionStatement(expression_statement) => {
|
BodyItem::ExpressionStatement(expression_statement) => match expression_statement.expression {
|
||||||
match expression_statement.expression {
|
Value::BinaryExpression(binary_expression) => recast_binary_expression(*binary_expression),
|
||||||
Value::BinaryExpression(binary_expression) => {
|
Value::ArrayExpression(array_expression) => recast_array_expression(&array_expression, ""),
|
||||||
recast_binary_expression(*binary_expression)
|
Value::ObjectExpression(object_expression) => recast_object_expression(&object_expression, "", false),
|
||||||
}
|
Value::CallExpression(call_expression) => recast_call_expression(&call_expression, "", false),
|
||||||
Value::ArrayExpression(array_expression) => {
|
_ => "Expression".to_string(),
|
||||||
recast_array_expression(&array_expression, "")
|
},
|
||||||
}
|
|
||||||
Value::ObjectExpression(object_expression) => {
|
|
||||||
recast_object_expression(&object_expression, "", false)
|
|
||||||
}
|
|
||||||
Value::CallExpression(call_expression) => {
|
|
||||||
recast_call_expression(&call_expression, "", false)
|
|
||||||
}
|
|
||||||
_ => "Expression".to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BodyItem::VariableDeclaration(variable_declaration) => variable_declaration
|
BodyItem::VariableDeclaration(variable_declaration) => variable_declaration
|
||||||
.declarations
|
.declarations
|
||||||
.iter()
|
.iter()
|
||||||
@ -308,22 +265,16 @@ pub fn recast(ast: &Program, indentation: &str, is_with_block: bool) -> String {
|
|||||||
})
|
})
|
||||||
.collect::<String>(),
|
.collect::<String>(),
|
||||||
BodyItem::ReturnStatement(return_statement) => {
|
BodyItem::ReturnStatement(return_statement) => {
|
||||||
format!(
|
format!("return {}", recast_argument(return_statement.argument, "", false))
|
||||||
"return {}",
|
|
||||||
recast_argument(return_statement.argument, "", false)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(index, recast_str)| {
|
.map(|(index, recast_str)| {
|
||||||
let is_legit_custom_whitespace_or_comment =
|
let is_legit_custom_whitespace_or_comment = |str: String| str != " " && str != "\n" && str != " ";
|
||||||
|str: String| str != " " && str != "\n" && str != " ";
|
|
||||||
|
|
||||||
// determine the value of startString
|
// determine the value of startString
|
||||||
let last_white_space_or_comment = if index > 0 {
|
let last_white_space_or_comment = if index > 0 {
|
||||||
let tmp = if let Some(non_code_node) =
|
let tmp = if let Some(non_code_node) = ast.non_code_meta.none_code_nodes.get(&(index - 1)) {
|
||||||
ast.non_code_meta.none_code_nodes.get(&(index - 1))
|
|
||||||
{
|
|
||||||
non_code_node.value.clone()
|
non_code_node.value.clone()
|
||||||
} else {
|
} else {
|
||||||
" ".to_string()
|
" ".to_string()
|
||||||
@ -333,12 +284,11 @@ pub fn recast(ast: &Program, indentation: &str, is_with_block: bool) -> String {
|
|||||||
" ".to_string()
|
" ".to_string()
|
||||||
};
|
};
|
||||||
// indentation of this line will be covered by the previous if we're using a custom whitespace or comment
|
// indentation of this line will be covered by the previous if we're using a custom whitespace or comment
|
||||||
let mut start_string =
|
let mut start_string = if is_legit_custom_whitespace_or_comment(last_white_space_or_comment) {
|
||||||
if is_legit_custom_whitespace_or_comment(last_white_space_or_comment) {
|
String::new()
|
||||||
String::new()
|
} else {
|
||||||
} else {
|
indentation.to_owned()
|
||||||
indentation.to_owned()
|
};
|
||||||
};
|
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
if let Some(start) = ast.non_code_meta.start.clone() {
|
if let Some(start) = ast.non_code_meta.start.clone() {
|
||||||
start_string = start.value;
|
start_string = start.value;
|
||||||
@ -356,13 +306,10 @@ pub fn recast(ast: &Program, indentation: &str, is_with_block: bool) -> String {
|
|||||||
} else {
|
} else {
|
||||||
"\n".to_string()
|
"\n".to_string()
|
||||||
};
|
};
|
||||||
let mut custom_white_space_or_comment =
|
let mut custom_white_space_or_comment = match ast.non_code_meta.none_code_nodes.get(&index) {
|
||||||
match ast.non_code_meta.none_code_nodes.get(&index) {
|
Some(custom_white_space_or_comment) => custom_white_space_or_comment.value.clone(),
|
||||||
Some(custom_white_space_or_comment) => {
|
None => String::new(),
|
||||||
custom_white_space_or_comment.value.clone()
|
};
|
||||||
}
|
|
||||||
None => String::new(),
|
|
||||||
};
|
|
||||||
if !is_legit_custom_whitespace_or_comment(custom_white_space_or_comment.clone()) {
|
if !is_legit_custom_whitespace_or_comment(custom_white_space_or_comment.clone()) {
|
||||||
custom_white_space_or_comment = String::new();
|
custom_white_space_or_comment = String::new();
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
//! Functions related to extruding.
|
//! Functions related to extruding.
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use derive_docs::stdlib;
|
||||||
|
use schemars::JsonSchema;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{ExtrudeGroup, ExtrudeTransform, MemoryItem, SketchGroup},
|
executor::{ExtrudeGroup, ExtrudeTransform, MemoryItem, SketchGroup},
|
||||||
std::Args,
|
std::Args,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
|
||||||
use derive_docs::stdlib;
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
|
|
||||||
/// Extrudes by a given amount.
|
/// Extrudes by a given amount.
|
||||||
pub fn extrude(args: &mut Args) -> Result<MemoryItem, KclError> {
|
pub fn extrude(args: &mut Args) -> Result<MemoryItem, KclError> {
|
||||||
let (length, sketch_group) = args.get_number_sketch_group()?;
|
let (length, sketch_group) = args.get_number_sketch_group()?;
|
||||||
@ -23,11 +23,7 @@ pub fn extrude(args: &mut Args) -> Result<MemoryItem, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "extrude"
|
name = "extrude"
|
||||||
}]
|
}]
|
||||||
fn inner_extrude(
|
fn inner_extrude(length: f64, sketch_group: SketchGroup, args: &mut Args) -> Result<ExtrudeGroup, KclError> {
|
||||||
length: f64,
|
|
||||||
sketch_group: SketchGroup,
|
|
||||||
args: &mut Args,
|
|
||||||
) -> Result<ExtrudeGroup, KclError> {
|
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
|
|
||||||
let cmd = kittycad::types::ModelingCmd::Extrude {
|
let cmd = kittycad::types::ModelingCmd::Extrude {
|
||||||
@ -65,17 +61,15 @@ fn inner_get_extrude_wall_transform(
|
|||||||
extrude_group: ExtrudeGroup,
|
extrude_group: ExtrudeGroup,
|
||||||
args: &mut Args,
|
args: &mut Args,
|
||||||
) -> Result<ExtrudeTransform, KclError> {
|
) -> Result<ExtrudeTransform, KclError> {
|
||||||
let surface = extrude_group
|
let surface = extrude_group.get_path_by_name(surface_name).ok_or_else(|| {
|
||||||
.get_path_by_name(surface_name)
|
KclError::Type(KclErrorDetails {
|
||||||
.ok_or_else(|| {
|
message: format!(
|
||||||
KclError::Type(KclErrorDetails {
|
"Expected a surface name that exists in the given ExtrudeGroup, found `{}`",
|
||||||
message: format!(
|
surface_name
|
||||||
"Expected a surface name that exists in the given ExtrudeGroup, found `{}`",
|
),
|
||||||
surface_name
|
source_ranges: vec![args.source_range],
|
||||||
),
|
})
|
||||||
source_ranges: vec![args.source_range],
|
})?;
|
||||||
})
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(ExtrudeTransform {
|
Ok(ExtrudeTransform {
|
||||||
position: surface.get_position(),
|
position: surface.get_position(),
|
||||||
|
@ -68,16 +68,10 @@ impl StdLib {
|
|||||||
|
|
||||||
let mut fns = HashMap::new();
|
let mut fns = HashMap::new();
|
||||||
for internal_fn_name in &internal_fn_names {
|
for internal_fn_name in &internal_fn_names {
|
||||||
fns.insert(
|
fns.insert(internal_fn_name.name().to_string(), internal_fn_name.std_lib_fn());
|
||||||
internal_fn_name.name().to_string(),
|
|
||||||
internal_fn_name.std_lib_fn(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self { internal_fn_names, fns }
|
||||||
internal_fn_names,
|
|
||||||
fns,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,22 +89,14 @@ pub struct Args<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Args<'a> {
|
impl<'a> Args<'a> {
|
||||||
pub fn new(
|
pub fn new(args: Vec<MemoryItem>, source_range: SourceRange, engine: &'a mut EngineConnection) -> Self {
|
||||||
args: Vec<MemoryItem>,
|
|
||||||
source_range: SourceRange,
|
|
||||||
engine: &'a mut EngineConnection,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
args,
|
args,
|
||||||
source_range,
|
source_range,
|
||||||
engine,
|
engine,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn send_modeling_cmd(
|
pub fn send_modeling_cmd(&mut self, id: uuid::Uuid, cmd: kittycad::types::ModelingCmd) -> Result<(), KclError> {
|
||||||
&mut self,
|
|
||||||
id: uuid::Uuid,
|
|
||||||
cmd: kittycad::types::ModelingCmd,
|
|
||||||
) -> Result<(), KclError> {
|
|
||||||
self.engine.send_modeling_cmd(id, self.source_range, cmd)
|
self.engine.send_modeling_cmd(id, self.source_range, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,14 +110,14 @@ impl<'a> Args<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn make_user_val_from_f64(&self, f: f64) -> Result<MemoryItem, KclError> {
|
fn make_user_val_from_f64(&self, f: f64) -> Result<MemoryItem, KclError> {
|
||||||
self.make_user_val_from_json(serde_json::Value::Number(
|
self.make_user_val_from_json(serde_json::Value::Number(serde_json::Number::from_f64(f).ok_or_else(
|
||||||
serde_json::Number::from_f64(f).ok_or_else(|| {
|
|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!("Failed to convert `{}` to a number", f),
|
message: format!("Failed to convert `{}` to a number", f),
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
})
|
})
|
||||||
})?,
|
},
|
||||||
))
|
)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_number_array(&self) -> Result<Vec<f64>, KclError> {
|
fn get_number_array(&self) -> Result<Vec<f64>, KclError> {
|
||||||
@ -164,10 +150,7 @@ impl<'a> Args<'a> {
|
|||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a string as the first argument, found `{:?}`", self.args),
|
||||||
"Expected a string as the first argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
})
|
})
|
||||||
})?
|
})?
|
||||||
@ -177,20 +160,14 @@ impl<'a> Args<'a> {
|
|||||||
s.to_string()
|
s.to_string()
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::Type(KclErrorDetails {
|
return Err(KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a string as the first argument, found `{:?}`", self.args),
|
||||||
"Expected a string as the first argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
let second_value = self.args.get(1).ok_or_else(|| {
|
let second_value = self.args.get(1).ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a SketchGroup as the second argument, found `{:?}`", self.args),
|
||||||
"Expected a SketchGroup as the second argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
@ -199,10 +176,7 @@ impl<'a> Args<'a> {
|
|||||||
sg.clone()
|
sg.clone()
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::Type(KclErrorDetails {
|
return Err(KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a SketchGroup as the second argument, found `{:?}`", self.args),
|
||||||
"Expected a SketchGroup as the second argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
@ -213,10 +187,7 @@ impl<'a> Args<'a> {
|
|||||||
fn get_sketch_group(&self) -> Result<SketchGroup, KclError> {
|
fn get_sketch_group(&self) -> Result<SketchGroup, KclError> {
|
||||||
let first_value = self.args.first().ok_or_else(|| {
|
let first_value = self.args.first().ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a SketchGroup as the first argument, found `{:?}`", self.args),
|
||||||
"Expected a SketchGroup as the first argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
@ -225,10 +196,7 @@ impl<'a> Args<'a> {
|
|||||||
sg.clone()
|
sg.clone()
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::Type(KclErrorDetails {
|
return Err(KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a SketchGroup as the first argument, found `{:?}`", self.args),
|
||||||
"Expected a SketchGroup as the first argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
@ -242,10 +210,7 @@ impl<'a> Args<'a> {
|
|||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a struct as the first argument, found `{:?}`", self.args),
|
||||||
"Expected a struct as the first argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
})
|
})
|
||||||
})?
|
})?
|
||||||
@ -261,18 +226,13 @@ impl<'a> Args<'a> {
|
|||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_data_and_sketch_group<T: serde::de::DeserializeOwned>(
|
fn get_data_and_sketch_group<T: serde::de::DeserializeOwned>(&self) -> Result<(T, SketchGroup), KclError> {
|
||||||
&self,
|
|
||||||
) -> Result<(T, SketchGroup), KclError> {
|
|
||||||
let first_value = self
|
let first_value = self
|
||||||
.args
|
.args
|
||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a struct as the first argument, found `{:?}`", self.args),
|
||||||
"Expected a struct as the first argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
})
|
})
|
||||||
})?
|
})?
|
||||||
@ -287,10 +247,7 @@ impl<'a> Args<'a> {
|
|||||||
|
|
||||||
let second_value = self.args.get(1).ok_or_else(|| {
|
let second_value = self.args.get(1).ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a SketchGroup as the second argument, found `{:?}`", self.args),
|
||||||
"Expected a SketchGroup as the second argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
@ -299,10 +256,7 @@ impl<'a> Args<'a> {
|
|||||||
sg.clone()
|
sg.clone()
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::Type(KclErrorDetails {
|
return Err(KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a SketchGroup as the second argument, found `{:?}`", self.args),
|
||||||
"Expected a SketchGroup as the second argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
@ -310,9 +264,7 @@ impl<'a> Args<'a> {
|
|||||||
Ok((data, sketch_group))
|
Ok((data, sketch_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_segment_name_to_number_sketch_group(
|
fn get_segment_name_to_number_sketch_group(&self) -> Result<(String, f64, SketchGroup), KclError> {
|
||||||
&self,
|
|
||||||
) -> Result<(String, f64, SketchGroup), KclError> {
|
|
||||||
// Iterate over our args, the first argument should be a UserVal with a string value.
|
// Iterate over our args, the first argument should be a UserVal with a string value.
|
||||||
// The second argument should be a number.
|
// The second argument should be a number.
|
||||||
// The third argument should be a SketchGroup.
|
// The third argument should be a SketchGroup.
|
||||||
@ -321,10 +273,7 @@ impl<'a> Args<'a> {
|
|||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a string as the first argument, found `{:?}`", self.args),
|
||||||
"Expected a string as the first argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
})
|
})
|
||||||
})?
|
})?
|
||||||
@ -334,10 +283,7 @@ impl<'a> Args<'a> {
|
|||||||
s.to_string()
|
s.to_string()
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::Type(KclErrorDetails {
|
return Err(KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a string as the first argument, found `{:?}`", self.args),
|
||||||
"Expected a string as the first argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
@ -347,10 +293,7 @@ impl<'a> Args<'a> {
|
|||||||
.get(1)
|
.get(1)
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a number as the second argument, found `{:?}`", self.args),
|
||||||
"Expected a number as the second argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
})
|
})
|
||||||
})?
|
})?
|
||||||
@ -360,10 +303,7 @@ impl<'a> Args<'a> {
|
|||||||
|
|
||||||
let third_value = self.args.get(2).ok_or_else(|| {
|
let third_value = self.args.get(2).ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a SketchGroup as the third argument, found `{:?}`", self.args),
|
||||||
"Expected a SketchGroup as the third argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
@ -372,10 +312,7 @@ impl<'a> Args<'a> {
|
|||||||
sg.clone()
|
sg.clone()
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::Type(KclErrorDetails {
|
return Err(KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a SketchGroup as the third argument, found `{:?}`", self.args),
|
||||||
"Expected a SketchGroup as the third argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
@ -391,10 +328,7 @@ impl<'a> Args<'a> {
|
|||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a number as the first argument, found `{:?}`", self.args),
|
||||||
"Expected a number as the first argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
})
|
})
|
||||||
})?
|
})?
|
||||||
@ -404,10 +338,7 @@ impl<'a> Args<'a> {
|
|||||||
|
|
||||||
let second_value = self.args.get(1).ok_or_else(|| {
|
let second_value = self.args.get(1).ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a SketchGroup as the second argument, found `{:?}`", self.args),
|
||||||
"Expected a SketchGroup as the second argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
@ -416,10 +347,7 @@ impl<'a> Args<'a> {
|
|||||||
sg.clone()
|
sg.clone()
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::Type(KclErrorDetails {
|
return Err(KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a SketchGroup as the second argument, found `{:?}`", self.args),
|
||||||
"Expected a SketchGroup as the second argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
@ -435,10 +363,7 @@ impl<'a> Args<'a> {
|
|||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a string as the first argument, found `{:?}`", self.args),
|
||||||
"Expected a string as the first argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
})
|
})
|
||||||
})?
|
})?
|
||||||
@ -448,10 +373,7 @@ impl<'a> Args<'a> {
|
|||||||
s.to_string()
|
s.to_string()
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::Type(KclErrorDetails {
|
return Err(KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!("Expected a string as the first argument, found `{:?}`", self.args),
|
||||||
"Expected a string as the first argument, found `{:?}`",
|
|
||||||
self.args
|
|
||||||
),
|
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
@ -589,11 +511,7 @@ mod tests {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.push_str(&format!(
|
buf.push_str(&format!("\t* [`{}`](#{})\n", internal_fn.name(), internal_fn.name()));
|
||||||
"\t* [`{}`](#{})\n",
|
|
||||||
internal_fn.name(),
|
|
||||||
internal_fn.name()
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.push_str("\n\n");
|
buf.push_str("\n\n");
|
||||||
@ -632,10 +550,7 @@ mod tests {
|
|||||||
for arg in internal_fn.args() {
|
for arg in internal_fn.args() {
|
||||||
let (format, should_be_indented) = arg.get_type_string().unwrap();
|
let (format, should_be_indented) = arg.get_type_string().unwrap();
|
||||||
if let Some(description) = arg.description() {
|
if let Some(description) = arg.description() {
|
||||||
fn_docs.push_str(&format!(
|
fn_docs.push_str(&format!("* `{}`: `{}` - {}\n", arg.name, arg.type_, description));
|
||||||
"* `{}`: `{}` - {}\n",
|
|
||||||
arg.name, arg.type_, description
|
|
||||||
));
|
|
||||||
} else {
|
} else {
|
||||||
fn_docs.push_str(&format!("* `{}`: `{}`\n", arg.name, arg.type_));
|
fn_docs.push_str(&format!("* `{}`: `{}`\n", arg.name, arg.type_));
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
//! Functions related to line segments.
|
//! Functions related to line segments.
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use derive_docs::stdlib;
|
||||||
|
use schemars::JsonSchema;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{MemoryItem, SketchGroup},
|
executor::{MemoryItem, SketchGroup},
|
||||||
std::{utils::get_angle, Args},
|
std::{utils::get_angle, Args},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
|
||||||
use derive_docs::stdlib;
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
|
|
||||||
/// Returns the segment end of x.
|
/// Returns the segment end of x.
|
||||||
pub fn segment_end_x(args: &mut Args) -> Result<MemoryItem, KclError> {
|
pub fn segment_end_x(args: &mut Args) -> Result<MemoryItem, KclError> {
|
||||||
let (segment_name, sketch_group) = args.get_segment_name_sketch_group()?;
|
let (segment_name, sketch_group) = args.get_segment_name_sketch_group()?;
|
||||||
@ -22,22 +22,16 @@ pub fn segment_end_x(args: &mut Args) -> Result<MemoryItem, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "segEndX",
|
name = "segEndX",
|
||||||
}]
|
}]
|
||||||
fn inner_segment_end_x(
|
fn inner_segment_end_x(segment_name: &str, sketch_group: SketchGroup, args: &mut Args) -> Result<f64, KclError> {
|
||||||
segment_name: &str,
|
let line = sketch_group.get_base_by_name_or_start(segment_name).ok_or_else(|| {
|
||||||
sketch_group: SketchGroup,
|
KclError::Type(KclErrorDetails {
|
||||||
args: &mut Args,
|
message: format!(
|
||||||
) -> Result<f64, KclError> {
|
"Expected a segment name that exists in the given SketchGroup, found `{}`",
|
||||||
let line = sketch_group
|
segment_name
|
||||||
.get_base_by_name_or_start(segment_name)
|
),
|
||||||
.ok_or_else(|| {
|
source_ranges: vec![args.source_range],
|
||||||
KclError::Type(KclErrorDetails {
|
})
|
||||||
message: format!(
|
})?;
|
||||||
"Expected a segment name that exists in the given SketchGroup, found `{}`",
|
|
||||||
segment_name
|
|
||||||
),
|
|
||||||
source_ranges: vec![args.source_range],
|
|
||||||
})
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(line.to[0])
|
Ok(line.to[0])
|
||||||
}
|
}
|
||||||
@ -54,22 +48,16 @@ pub fn segment_end_y(args: &mut Args) -> Result<MemoryItem, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "segEndY",
|
name = "segEndY",
|
||||||
}]
|
}]
|
||||||
fn inner_segment_end_y(
|
fn inner_segment_end_y(segment_name: &str, sketch_group: SketchGroup, args: &mut Args) -> Result<f64, KclError> {
|
||||||
segment_name: &str,
|
let line = sketch_group.get_base_by_name_or_start(segment_name).ok_or_else(|| {
|
||||||
sketch_group: SketchGroup,
|
KclError::Type(KclErrorDetails {
|
||||||
args: &mut Args,
|
message: format!(
|
||||||
) -> Result<f64, KclError> {
|
"Expected a segment name that exists in the given SketchGroup, found `{}`",
|
||||||
let line = sketch_group
|
segment_name
|
||||||
.get_base_by_name_or_start(segment_name)
|
),
|
||||||
.ok_or_else(|| {
|
source_ranges: vec![args.source_range],
|
||||||
KclError::Type(KclErrorDetails {
|
})
|
||||||
message: format!(
|
})?;
|
||||||
"Expected a segment name that exists in the given SketchGroup, found `{}`",
|
|
||||||
segment_name
|
|
||||||
),
|
|
||||||
source_ranges: vec![args.source_range],
|
|
||||||
})
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(line.to[1])
|
Ok(line.to[1])
|
||||||
}
|
}
|
||||||
@ -145,11 +133,7 @@ pub fn segment_length(args: &mut Args) -> Result<MemoryItem, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "segLen",
|
name = "segLen",
|
||||||
}]
|
}]
|
||||||
fn inner_segment_length(
|
fn inner_segment_length(segment_name: &str, sketch_group: SketchGroup, args: &mut Args) -> Result<f64, KclError> {
|
||||||
segment_name: &str,
|
|
||||||
sketch_group: SketchGroup,
|
|
||||||
args: &mut Args,
|
|
||||||
) -> Result<f64, KclError> {
|
|
||||||
let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| {
|
let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!(
|
||||||
@ -178,11 +162,7 @@ pub fn segment_angle(args: &mut Args) -> Result<MemoryItem, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "segAng",
|
name = "segAng",
|
||||||
}]
|
}]
|
||||||
fn inner_segment_angle(
|
fn inner_segment_angle(segment_name: &str, sketch_group: SketchGroup, args: &mut Args) -> Result<f64, KclError> {
|
||||||
segment_name: &str,
|
|
||||||
sketch_group: SketchGroup,
|
|
||||||
args: &mut Args,
|
|
||||||
) -> Result<f64, KclError> {
|
|
||||||
let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| {
|
let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
message: format!(
|
message: format!(
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! Functions related to sketching.
|
//! Functions related to sketching.
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use kittycad::types::{ModelingCmd, Point3D};
|
use kittycad::types::{ModelingCmd, Point3D};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
@ -14,8 +15,6 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
|
||||||
|
|
||||||
/// Data to draw a line to a point.
|
/// Data to draw a line to a point.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
@ -44,11 +43,7 @@ pub fn line_to(args: &mut Args) -> Result<MemoryItem, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "lineTo",
|
name = "lineTo",
|
||||||
}]
|
}]
|
||||||
fn inner_line_to(
|
fn inner_line_to(data: LineToData, sketch_group: SketchGroup, args: &Args) -> Result<SketchGroup, KclError> {
|
||||||
data: LineToData,
|
|
||||||
sketch_group: SketchGroup,
|
|
||||||
args: &Args,
|
|
||||||
) -> Result<SketchGroup, KclError> {
|
|
||||||
let from = sketch_group.get_coords_from_paths()?;
|
let from = sketch_group.get_coords_from_paths()?;
|
||||||
let to = match data {
|
let to = match data {
|
||||||
LineToData::PointWithTag { to, .. } => to,
|
LineToData::PointWithTag { to, .. } => to,
|
||||||
@ -106,18 +101,11 @@ pub fn x_line_to(args: &mut Args) -> Result<MemoryItem, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "xLineTo",
|
name = "xLineTo",
|
||||||
}]
|
}]
|
||||||
fn inner_x_line_to(
|
fn inner_x_line_to(data: AxisLineToData, sketch_group: SketchGroup, args: &Args) -> Result<SketchGroup, KclError> {
|
||||||
data: AxisLineToData,
|
|
||||||
sketch_group: SketchGroup,
|
|
||||||
args: &Args,
|
|
||||||
) -> Result<SketchGroup, KclError> {
|
|
||||||
let from = sketch_group.get_coords_from_paths()?;
|
let from = sketch_group.get_coords_from_paths()?;
|
||||||
|
|
||||||
let line_to_data = match data {
|
let line_to_data = match data {
|
||||||
AxisLineToData::PointWithTag { to, tag } => LineToData::PointWithTag {
|
AxisLineToData::PointWithTag { to, tag } => LineToData::PointWithTag { to: [to, from.y], tag },
|
||||||
to: [to, from.y],
|
|
||||||
tag,
|
|
||||||
},
|
|
||||||
AxisLineToData::Point(data) => LineToData::Point([data, from.y]),
|
AxisLineToData::Point(data) => LineToData::Point([data, from.y]),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -138,18 +126,11 @@ pub fn y_line_to(args: &mut Args) -> Result<MemoryItem, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "yLineTo",
|
name = "yLineTo",
|
||||||
}]
|
}]
|
||||||
fn inner_y_line_to(
|
fn inner_y_line_to(data: AxisLineToData, sketch_group: SketchGroup, args: &Args) -> Result<SketchGroup, KclError> {
|
||||||
data: AxisLineToData,
|
|
||||||
sketch_group: SketchGroup,
|
|
||||||
args: &Args,
|
|
||||||
) -> Result<SketchGroup, KclError> {
|
|
||||||
let from = sketch_group.get_coords_from_paths()?;
|
let from = sketch_group.get_coords_from_paths()?;
|
||||||
|
|
||||||
let line_to_data = match data {
|
let line_to_data = match data {
|
||||||
AxisLineToData::PointWithTag { to, tag } => LineToData::PointWithTag {
|
AxisLineToData::PointWithTag { to, tag } => LineToData::PointWithTag { to: [from.x, to], tag },
|
||||||
to: [from.x, to],
|
|
||||||
tag,
|
|
||||||
},
|
|
||||||
AxisLineToData::Point(data) => LineToData::Point([from.x, data]),
|
AxisLineToData::Point(data) => LineToData::Point([from.x, data]),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -207,11 +188,7 @@ pub fn line(args: &mut Args) -> Result<MemoryItem, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "line",
|
name = "line",
|
||||||
}]
|
}]
|
||||||
fn inner_line(
|
fn inner_line(data: LineData, sketch_group: SketchGroup, args: &mut Args) -> Result<SketchGroup, KclError> {
|
||||||
data: LineData,
|
|
||||||
sketch_group: SketchGroup,
|
|
||||||
args: &mut Args,
|
|
||||||
) -> Result<SketchGroup, KclError> {
|
|
||||||
let from = sketch_group.get_coords_from_paths()?;
|
let from = sketch_group.get_coords_from_paths()?;
|
||||||
|
|
||||||
let default = [0.2, 1.0];
|
let default = [0.2, 1.0];
|
||||||
@ -289,11 +266,7 @@ pub fn x_line(args: &mut Args) -> Result<MemoryItem, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "xLine",
|
name = "xLine",
|
||||||
}]
|
}]
|
||||||
fn inner_x_line(
|
fn inner_x_line(data: AxisLineData, sketch_group: SketchGroup, args: &mut Args) -> Result<SketchGroup, KclError> {
|
||||||
data: AxisLineData,
|
|
||||||
sketch_group: SketchGroup,
|
|
||||||
args: &mut Args,
|
|
||||||
) -> Result<SketchGroup, KclError> {
|
|
||||||
let line_data = match data {
|
let line_data = match data {
|
||||||
AxisLineData::LengthWithTag { length, tag } => LineData::PointWithTag {
|
AxisLineData::LengthWithTag { length, tag } => LineData::PointWithTag {
|
||||||
to: PointOrDefault::Point([length, 0.0]),
|
to: PointOrDefault::Point([length, 0.0]),
|
||||||
@ -318,11 +291,7 @@ pub fn y_line(args: &mut Args) -> Result<MemoryItem, KclError> {
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "yLine",
|
name = "yLine",
|
||||||
}]
|
}]
|
||||||
fn inner_y_line(
|
fn inner_y_line(data: AxisLineData, sketch_group: SketchGroup, args: &mut Args) -> Result<SketchGroup, KclError> {
|
||||||
data: AxisLineData,
|
|
||||||
sketch_group: SketchGroup,
|
|
||||||
args: &mut Args,
|
|
||||||
) -> Result<SketchGroup, KclError> {
|
|
||||||
let line_data = match data {
|
let line_data = match data {
|
||||||
AxisLineData::LengthWithTag { length, tag } => LineData::PointWithTag {
|
AxisLineData::LengthWithTag { length, tag } => LineData::PointWithTag {
|
||||||
to: PointOrDefault::Point([0.0, length]),
|
to: PointOrDefault::Point([0.0, length]),
|
||||||
@ -373,9 +342,7 @@ fn inner_angled_line(
|
|||||||
let from = sketch_group.get_coords_from_paths()?;
|
let from = sketch_group.get_coords_from_paths()?;
|
||||||
let (angle, length) = match &data {
|
let (angle, length) = match &data {
|
||||||
AngledLineData::AngleWithTag { angle, length, .. } => (*angle, *length),
|
AngledLineData::AngleWithTag { angle, length, .. } => (*angle, *length),
|
||||||
AngledLineData::AngleAndLength(angle_and_length) => {
|
AngledLineData::AngleAndLength(angle_and_length) => (angle_and_length[0], angle_and_length[1]),
|
||||||
(angle_and_length[0], angle_and_length[1])
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let to: [f64; 2] = [
|
let to: [f64; 2] = [
|
||||||
from.x + length * f64::cos(angle * std::f64::consts::PI / 180.0),
|
from.x + length * f64::cos(angle * std::f64::consts::PI / 180.0),
|
||||||
@ -424,9 +391,7 @@ fn inner_angled_line_of_x_length(
|
|||||||
) -> Result<SketchGroup, KclError> {
|
) -> Result<SketchGroup, KclError> {
|
||||||
let (angle, length) = match &data {
|
let (angle, length) = match &data {
|
||||||
AngledLineData::AngleWithTag { angle, length, .. } => (*angle, *length),
|
AngledLineData::AngleWithTag { angle, length, .. } => (*angle, *length),
|
||||||
AngledLineData::AngleAndLength(angle_and_length) => {
|
AngledLineData::AngleAndLength(angle_and_length) => (angle_and_length[0], angle_and_length[1]),
|
||||||
(angle_and_length[0], angle_and_length[1])
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let to = get_y_component(angle, length);
|
let to = get_y_component(angle, length);
|
||||||
@ -494,10 +459,7 @@ fn inner_angled_line_to_x(
|
|||||||
|
|
||||||
let new_sketch_group = inner_line_to(
|
let new_sketch_group = inner_line_to(
|
||||||
if let AngledLineToData::AngleWithTag { tag, .. } = data {
|
if let AngledLineToData::AngleWithTag { tag, .. } = data {
|
||||||
LineToData::PointWithTag {
|
LineToData::PointWithTag { to: [x_to, y_to], tag }
|
||||||
to: [x_to, y_to],
|
|
||||||
tag,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
LineToData::Point([x_to, y_to])
|
LineToData::Point([x_to, y_to])
|
||||||
},
|
},
|
||||||
@ -527,9 +489,7 @@ fn inner_angled_line_of_y_length(
|
|||||||
) -> Result<SketchGroup, KclError> {
|
) -> Result<SketchGroup, KclError> {
|
||||||
let (angle, length) = match &data {
|
let (angle, length) = match &data {
|
||||||
AngledLineData::AngleWithTag { angle, length, .. } => (*angle, *length),
|
AngledLineData::AngleWithTag { angle, length, .. } => (*angle, *length),
|
||||||
AngledLineData::AngleAndLength(angle_and_length) => {
|
AngledLineData::AngleAndLength(angle_and_length) => (angle_and_length[0], angle_and_length[1]),
|
||||||
(angle_and_length[0], angle_and_length[1])
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let to = get_x_component(angle, length);
|
let to = get_x_component(angle, length);
|
||||||
@ -579,10 +539,7 @@ fn inner_angled_line_to_y(
|
|||||||
|
|
||||||
let new_sketch_group = inner_line_to(
|
let new_sketch_group = inner_line_to(
|
||||||
if let AngledLineToData::AngleWithTag { tag, .. } = data {
|
if let AngledLineToData::AngleWithTag { tag, .. } = data {
|
||||||
LineToData::PointWithTag {
|
LineToData::PointWithTag { to: [x_to, y_to], tag }
|
||||||
to: [x_to, y_to],
|
|
||||||
tag,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
LineToData::Point([x_to, y_to])
|
LineToData::Point([x_to, y_to])
|
||||||
},
|
},
|
||||||
@ -610,8 +567,7 @@ pub struct AngeledLineThatIntersectsData {
|
|||||||
|
|
||||||
/// Draw an angled line that intersects with a given line.
|
/// Draw an angled line that intersects with a given line.
|
||||||
pub fn angled_line_that_intersects(args: &mut Args) -> Result<MemoryItem, KclError> {
|
pub fn angled_line_that_intersects(args: &mut Args) -> Result<MemoryItem, KclError> {
|
||||||
let (data, sketch_group): (AngeledLineThatIntersectsData, SketchGroup) =
|
let (data, sketch_group): (AngeledLineThatIntersectsData, SketchGroup) = args.get_data_and_sketch_group()?;
|
||||||
args.get_data_and_sketch_group()?;
|
|
||||||
let new_sketch_group = inner_angled_line_that_intersects(data, sketch_group, args)?;
|
let new_sketch_group = inner_angled_line_that_intersects(data, sketch_group, args)?;
|
||||||
Ok(MemoryItem::SketchGroup(new_sketch_group))
|
Ok(MemoryItem::SketchGroup(new_sketch_group))
|
||||||
}
|
}
|
||||||
@ -763,10 +719,10 @@ fn inner_close(sketch_group: SketchGroup, args: &mut Args) -> Result<SketchGroup
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use crate::std::sketch::{LineData, PointOrDefault};
|
|
||||||
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use crate::std::sketch::{LineData, PointOrDefault};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deserialize_line_data() {
|
fn test_deserialize_line_data() {
|
||||||
let mut str_json = "\"default\"".to_string();
|
let mut str_json = "\"default\"".to_string();
|
||||||
|
@ -44,7 +44,10 @@ pub fn normalize_rad(angle: f64) -> f64 {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// assert_eq!(kcl_lib::std::utils::delta_angle(std::f64::consts::PI/8.0, std::f64::consts::PI/4.0), std::f64::consts::PI/8.0);
|
/// assert_eq!(
|
||||||
|
/// kcl_lib::std::utils::delta_angle(std::f64::consts::PI / 8.0, std::f64::consts::PI / 4.0),
|
||||||
|
/// std::f64::consts::PI / 8.0
|
||||||
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn delta_angle(from_angle: f64, to_angle: f64) -> f64 {
|
pub fn delta_angle(from_angle: f64, to_angle: f64) -> f64 {
|
||||||
@ -69,8 +72,14 @@ pub fn delta_angle(from_angle: f64, to_angle: f64) -> f64 {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// assert_eq!(kcl_lib::std::utils::distance_between_points(&[0.0, 0.0], &[0.0, 5.0]), 5.0);
|
/// assert_eq!(
|
||||||
/// assert_eq!(kcl_lib::std::utils::distance_between_points(&[0.0, 0.0], &[3.0, 4.0]), 5.0);
|
/// kcl_lib::std::utils::distance_between_points(&[0.0, 0.0], &[0.0, 5.0]),
|
||||||
|
/// 5.0
|
||||||
|
/// );
|
||||||
|
/// assert_eq!(
|
||||||
|
/// kcl_lib::std::utils::distance_between_points(&[0.0, 0.0], &[3.0, 4.0]),
|
||||||
|
/// 5.0
|
||||||
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn distance_between_points(point_a: &[f64; 2], point_b: &[f64; 2]) -> f64 {
|
pub fn distance_between_points(point_a: &[f64; 2], point_b: &[f64; 2]) -> f64 {
|
||||||
@ -82,11 +91,7 @@ pub fn distance_between_points(point_a: &[f64; 2], point_b: &[f64; 2]) -> f64 {
|
|||||||
((y2 - y1).powi(2) + (x2 - x1).powi(2)).sqrt()
|
((y2 - y1).powi(2) + (x2 - x1).powi(2)).sqrt()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculate_intersection_of_two_lines(
|
pub fn calculate_intersection_of_two_lines(line1: &[[f64; 2]; 2], line2_angle: f64, line2_point: [f64; 2]) -> [f64; 2] {
|
||||||
line1: &[[f64; 2]; 2],
|
|
||||||
line2_angle: f64,
|
|
||||||
line2_point: [f64; 2],
|
|
||||||
) -> [f64; 2] {
|
|
||||||
let line2_point_b = [
|
let line2_point_b = [
|
||||||
line2_point[0] + f64::cos(line2_angle * std::f64::consts::PI / 180.0) * 10.0,
|
line2_point[0] + f64::cos(line2_angle * std::f64::consts::PI / 180.0) * 10.0,
|
||||||
line2_point[1] + f64::sin(line2_angle * std::f64::consts::PI / 180.0) * 10.0,
|
line2_point[1] + f64::sin(line2_angle * std::f64::consts::PI / 180.0) * 10.0,
|
||||||
@ -117,27 +122,17 @@ pub fn intersection_with_parallel_line(
|
|||||||
line2_angle: f64,
|
line2_angle: f64,
|
||||||
line2_point: [f64; 2],
|
line2_point: [f64; 2],
|
||||||
) -> [f64; 2] {
|
) -> [f64; 2] {
|
||||||
calculate_intersection_of_two_lines(
|
calculate_intersection_of_two_lines(&offset_line(line1_offset, line1[0], line1[1]), line2_angle, line2_point)
|
||||||
&offset_line(line1_offset, line1[0], line1[1]),
|
|
||||||
line2_angle,
|
|
||||||
line2_point,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn offset_line(offset: f64, p1: [f64; 2], p2: [f64; 2]) -> [[f64; 2]; 2] {
|
fn offset_line(offset: f64, p1: [f64; 2], p2: [f64; 2]) -> [[f64; 2]; 2] {
|
||||||
if p1[0] == p2[0] {
|
if p1[0] == p2[0] {
|
||||||
let direction = (p1[1] - p2[1]).signum();
|
let direction = (p1[1] - p2[1]).signum();
|
||||||
return [
|
return [[p1[0] + offset * direction, p1[1]], [p2[0] + offset * direction, p2[1]]];
|
||||||
[p1[0] + offset * direction, p1[1]],
|
|
||||||
[p2[0] + offset * direction, p2[1]],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
if p1[1] == p2[1] {
|
if p1[1] == p2[1] {
|
||||||
let direction = (p2[0] - p1[0]).signum();
|
let direction = (p2[0] - p1[0]).signum();
|
||||||
return [
|
return [[p1[0], p1[1] + offset * direction], [p2[0], p2[1] + offset * direction]];
|
||||||
[p1[0], p1[1] + offset * direction],
|
|
||||||
[p2[0], p2[1] + offset * direction],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
let x_offset = offset / f64::sin(f64::atan2(p1[1] - p2[1], p1[0] - p2[0]));
|
let x_offset = offset / f64::sin(f64::atan2(p1[1] - p2[1], p1[0] - p2[0]));
|
||||||
[[p1[0] + x_offset, p1[1]], [p2[0] + x_offset, p2[1]]]
|
[[p1[0] + x_offset, p1[1]], [p2[0] + x_offset, p2[1]]]
|
||||||
@ -168,9 +163,10 @@ pub fn get_x_component(angle_degree: f64, y_component: f64) -> [f64; 2] {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
// Here you can bring your functions into scope
|
// Here you can bring your functions into scope
|
||||||
use super::{get_x_component, get_y_component};
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use super::{get_x_component, get_y_component};
|
||||||
|
|
||||||
static EACH_QUAD: [(i32, [i32; 2]); 12] = [
|
static EACH_QUAD: [(i32, [i32; 2]); 12] = [
|
||||||
(-315, [1, 1]),
|
(-315, [1, 1]),
|
||||||
(-225, [-1, 1]),
|
(-225, [-1, 1]),
|
||||||
|
@ -46,8 +46,7 @@ lazy_static! {
|
|||||||
static ref WHITESPACE: Regex = Regex::new(r"\s+").unwrap();
|
static ref WHITESPACE: Regex = Regex::new(r"\s+").unwrap();
|
||||||
static ref WORD: Regex = Regex::new(r"^[a-zA-Z_][a-zA-Z0-9_]*").unwrap();
|
static ref WORD: Regex = Regex::new(r"^[a-zA-Z_][a-zA-Z0-9_]*").unwrap();
|
||||||
static ref STRING: Regex = Regex::new(r#"^"([^"\\]|\\.)*"|'([^'\\]|\\.)*'"#).unwrap();
|
static ref STRING: Regex = Regex::new(r#"^"([^"\\]|\\.)*"|'([^'\\]|\\.)*'"#).unwrap();
|
||||||
static ref OPERATOR: Regex =
|
static ref OPERATOR: Regex = Regex::new(r"^(>=|<=|==|=>|!= |\|>|\*|\+|-|/|%|=|<|>|\||\^)").unwrap();
|
||||||
Regex::new(r"^(>=|<=|==|=>|!= |\|>|\*|\+|-|/|%|=|<|>|\||\^)").unwrap();
|
|
||||||
static ref BLOCK_START: Regex = Regex::new(r"^\{").unwrap();
|
static ref BLOCK_START: Regex = Regex::new(r"^\{").unwrap();
|
||||||
static ref BLOCK_END: Regex = Regex::new(r"^\}").unwrap();
|
static ref BLOCK_END: Regex = Regex::new(r"^\}").unwrap();
|
||||||
static ref PARAN_START: Regex = Regex::new(r"^\(").unwrap();
|
static ref PARAN_START: Regex = Regex::new(r"^\(").unwrap();
|
||||||
@ -114,9 +113,7 @@ fn is_block_comment(character: &str) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn match_first(str: &str, regex: &Regex) -> Option<String> {
|
fn match_first(str: &str, regex: &Regex) -> Option<String> {
|
||||||
regex
|
regex.find(str).map(|the_match| the_match.as_str().to_string())
|
||||||
.find(str)
|
|
||||||
.map(|the_match| the_match.as_str().to_string())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_token(token_type: TokenType, value: &str, start: usize) -> Token {
|
fn make_token(token_type: TokenType, value: &str, start: usize) -> Token {
|
||||||
@ -251,11 +248,7 @@ fn return_token_at_index(str: &str, start_index: usize) -> Option<Token> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn lexer(str: &str) -> Vec<Token> {
|
pub fn lexer(str: &str) -> Vec<Token> {
|
||||||
fn recursively_tokenise(
|
fn recursively_tokenise(str: &str, current_index: usize, previous_tokens: Vec<Token>) -> Vec<Token> {
|
||||||
str: &str,
|
|
||||||
current_index: usize,
|
|
||||||
previous_tokens: Vec<Token>,
|
|
||||||
) -> Vec<Token> {
|
|
||||||
if current_index >= str.len() {
|
if current_index >= str.len() {
|
||||||
return previous_tokens;
|
return previous_tokens;
|
||||||
}
|
}
|
||||||
@ -273,9 +266,10 @@ pub fn lexer(str: &str) -> Vec<Token> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn is_number_test() {
|
fn is_number_test() {
|
||||||
assert!(is_number("1"));
|
assert!(is_number("1"));
|
||||||
|
6
src/wasm-lib/rustfmt.toml
Normal file
6
src/wasm-lib/rustfmt.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
max_width = 120
|
||||||
|
edition = "2018"
|
||||||
|
format_code_in_doc_comments = true
|
||||||
|
format_strings = false
|
||||||
|
imports_granularity = "Crate"
|
||||||
|
group_imports = "StdExternalCrate"
|
@ -14,20 +14,14 @@ pub async fn execute_wasm(
|
|||||||
// deserialize the ast from a stringified json
|
// deserialize the ast from a stringified json
|
||||||
let program: kcl_lib::abstract_syntax_tree_types::Program =
|
let program: kcl_lib::abstract_syntax_tree_types::Program =
|
||||||
serde_json::from_str(program_str).map_err(|e| e.to_string())?;
|
serde_json::from_str(program_str).map_err(|e| e.to_string())?;
|
||||||
let mut mem: kcl_lib::executor::ProgramMemory =
|
let mut mem: kcl_lib::executor::ProgramMemory = serde_json::from_str(memory_str).map_err(|e| e.to_string())?;
|
||||||
serde_json::from_str(memory_str).map_err(|e| e.to_string())?;
|
|
||||||
|
|
||||||
let mut engine = kcl_lib::engine::EngineConnection::new(manager)
|
let mut engine = kcl_lib::engine::EngineConnection::new(manager)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| format!("{:?}", e))?;
|
.map_err(|e| format!("{:?}", e))?;
|
||||||
|
|
||||||
let memory = kcl_lib::executor::execute(
|
let memory = kcl_lib::executor::execute(program, &mut mem, kcl_lib::executor::BodyType::Root, &mut engine)
|
||||||
program,
|
.map_err(String::from)?;
|
||||||
&mut mem,
|
|
||||||
kcl_lib::executor::BodyType::Root,
|
|
||||||
&mut engine,
|
|
||||||
)
|
|
||||||
.map_err(String::from)?;
|
|
||||||
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
||||||
// gloo-serialize crate instead.
|
// gloo-serialize crate instead.
|
||||||
JsValue::from_serde(&memory).map_err(|e| e.to_string())
|
JsValue::from_serde(&memory).map_err(|e| e.to_string())
|
||||||
@ -38,20 +32,14 @@ pub fn deserialize_files(data: &[u8]) -> Result<JsValue, JsError> {
|
|||||||
let ws_resp: kittycad::types::WebSocketResponse = bson::from_slice(data)?;
|
let ws_resp: kittycad::types::WebSocketResponse = bson::from_slice(data)?;
|
||||||
|
|
||||||
if !ws_resp.success {
|
if !ws_resp.success {
|
||||||
return Err(JsError::new(&format!(
|
return Err(JsError::new(&format!("Server returned error: {:?}", ws_resp.errors)));
|
||||||
"Server returned error: {:?}",
|
|
||||||
ws_resp.errors
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(kittycad::types::OkWebSocketResponseData::Export { files }) = ws_resp.resp {
|
if let Some(kittycad::types::OkWebSocketResponseData::Export { files }) = ws_resp.resp {
|
||||||
return Ok(JsValue::from_serde(&files)?);
|
return Ok(JsValue::from_serde(&files)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(JsError::new(&format!(
|
Err(JsError::new(&format!("Invalid response type, got: {:?}", ws_resp)))
|
||||||
"Invalid response type, got: {:?}",
|
|
||||||
ws_resp
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// wasm_bindgen wrapper for lexer
|
// wasm_bindgen wrapper for lexer
|
||||||
|
Reference in New Issue
Block a user