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