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:
Jess Frazelle
2023-08-29 14:12:48 -07:00
committed by GitHub
parent 18db6f2dc1
commit 023af60781
21 changed files with 444 additions and 873 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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",

View File

@ -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(),
);
} }
} }

View File

@ -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"

View File

@ -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 {

View File

@ -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,
));
} }
} }

View File

@ -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(())
} }
} }

View File

@ -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 {

View File

@ -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()
); );
} }

View File

@ -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![

View File

@ -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()

View File

@ -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();
} }

View File

@ -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(),

View File

@ -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_));
} }

View File

@ -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!(

View File

@ -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();

View File

@ -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]),

View File

@ -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"));

View 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"

View File

@ -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