fmt and move error stuff locally (#347)

* fmt

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* some fixups for errors

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* some fixups for errors

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* bump version

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix tsc

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
Jess Frazelle
2023-08-29 14:12:48 -07:00
committed by GitHub
parent 18db6f2dc1
commit 023af60781
21 changed files with 444 additions and 873 deletions

View File

@ -16,10 +16,8 @@ export const parser_wasm = (code: string): Program => {
const parsed: RustKclError = JSON.parse(e.toString())
const 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)

View File

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

View File

@ -947,7 +947,7 @@ dependencies = [
[[package]]
name = "kcl-lib"
version = "0.1.0"
version = "0.1.1"
dependencies = [
"anyhow",
"bson",

View File

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

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-lib"
description = "KittyCAD Language"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
license = "MIT"

View File

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

View File

@ -147,15 +147,9 @@ fn get_type_string_from_schema(schema: &schemars::schema::Schema) -> Result<(Str
if let Some(array_val) = &o.array {
if let Some(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));
}
}

View File

@ -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| {
KclError::Engine(KclErrorDetails {
message: format!("Failed to send modeling command: {}", e),
source_ranges: vec![source_range],
})
})?;
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(())
}
}

View File

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

View File

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

View File

@ -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,48 +272,47 @@ 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 {
value: if current_token.token_type == TokenType::Number {
if let Ok(value) = current_token.value.parse::<i64>() {
serde_json::Value::Number(value.into())
} else if let Ok(value) = current_token.value.parse::<f64>() {
if let Some(n) = serde_json::Number::from_f64(value) {
serde_json::Value::Number(n)
} else {
return Err(KclError::Syntax(KclErrorDetails {
source_ranges: vec![current_token.into()],
message: format!("Invalid float: {}", current_token.value),
}));
}
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())
} else if let Ok(value) = current_token.value.parse::<f64>() {
if let Some(n) = serde_json::Number::from_f64(value) {
serde_json::Value::Number(n)
} else {
return Err(KclError::Syntax(KclErrorDetails {
source_ranges: vec![current_token.into()],
message: format!("Invalid integer: {}", current_token.value),
message: format!("Invalid float: {}", current_token.value),
}));
}
} else {
let mut str_val = current_token.value.clone();
str_val.remove(0);
str_val.pop();
serde_json::Value::String(str_val)
},
start: current_token.start,
end: current_token.end,
raw: current_token.value.clone(),
end_extended: None,
start_extended: None,
return Err(KclError::Syntax(KclErrorDetails {
source_ranges: vec![current_token.into()],
message: format!("Invalid integer: {}", current_token.value),
}));
}
} else {
let mut str_val = current_token.value.clone();
str_val.remove(0);
str_val.pop();
serde_json::Value::String(str_val)
},
)));
start: current_token.start,
end: current_token.end,
raw: current_token.value.clone(),
end_extended: None,
start_extended: None,
})));
return build_tree(&reverse_polish_notation_tokens[1..], new_stack);
} 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 {
value: "(".to_string(),
start: current_token.start,
end: current_token.end,
token_type: MathTokenType::Parenthesis,
},
)));
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 {
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),
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![

View File

@ -1,15 +1,16 @@
use std::collections::HashMap;
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,
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,
},
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()

View File

@ -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)
}
_ => "Expression".to_string(),
}
}
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,12 +284,11 @@ 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) {
String::new()
} else {
indentation.to_owned()
};
let mut start_string = if is_legit_custom_whitespace_or_comment(last_white_space_or_comment) {
String::new()
} else {
indentation.to_owned()
};
if index == 0 {
if let Some(start) = ast.non_code_meta.start.clone() {
start_string = start.value;
@ -356,13 +306,10 @@ 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()
}
None => String::new(),
};
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()) {
custom_white_space_or_comment = String::new();
}

View File

@ -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,17 +61,15 @@ 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(|| {
KclError::Type(KclErrorDetails {
message: format!(
"Expected a surface name that exists in the given ExtrudeGroup, found `{}`",
surface_name
),
source_ranges: vec![args.source_range],
})
})?;
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 `{}`",
surface_name
),
source_ranges: vec![args.source_range],
})
})?;
Ok(ExtrudeTransform {
position: surface.get_position(),

View File

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

View File

@ -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,22 +22,16 @@ 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(|| {
KclError::Type(KclErrorDetails {
message: format!(
"Expected a segment name that exists in the given SketchGroup, found `{}`",
segment_name
),
source_ranges: vec![args.source_range],
})
})?;
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 `{}`",
segment_name
),
source_ranges: vec![args.source_range],
})
})?;
Ok(line.to[0])
}
@ -54,22 +48,16 @@ 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(|| {
KclError::Type(KclErrorDetails {
message: format!(
"Expected a segment name that exists in the given SketchGroup, found `{}`",
segment_name
),
source_ranges: vec![args.source_range],
})
})?;
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 `{}`",
segment_name
),
source_ranges: vec![args.source_range],
})
})?;
Ok(line.to[1])
}
@ -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!(

View File

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

View File

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

View File

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

View File

@ -0,0 +1,6 @@
max_width = 120
edition = "2018"
format_code_in_doc_comments = true
format_strings = false
imports_granularity = "Crate"
group_imports = "StdExternalCrate"

View File

@ -14,20 +14,14 @@ pub async fn execute_wasm(
// deserialize the ast from a stringified json
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,
)
.map_err(String::from)?;
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.
JsValue::from_serde(&memory).map_err(|e| e.to_string())
@ -38,20 +32,14 @@ pub fn deserialize_files(data: &[u8]) -> Result<JsValue, JsError> {
let ws_resp: kittycad::types::WebSocketResponse = bson::from_slice(data)?;
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