1use crate::{script::SimpletonLiteral, Reference};
2use intuicio_core::{function::FunctionQuery, registry::Registry, types::TypeQuery};
3use intuicio_nodes::nodes::{
4 Node, NodeDefinition, NodePin, NodeSuggestion, NodeTypeInfo, PropertyValue,
5 ResponseSuggestionNode,
6};
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10pub struct SimpletonNodeTypeInfo;
11
12impl SimpletonNodeTypeInfo {}
13
14impl NodeTypeInfo for SimpletonNodeTypeInfo {
15 fn type_query(&self) -> TypeQuery {
16 TypeQuery::of::<Reference>()
17 }
18
19 fn are_compatible(&self, _: &Self) -> bool {
20 true
21 }
22}
23
24impl std::fmt::Display for SimpletonNodeTypeInfo {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 write!(f, "reflect::Reference",)
27 }
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub enum SimpletonExpressionNodes {
32 FindStruct {
33 name: String,
34 module_name: String,
35 },
36 FindFunction {
37 name: String,
38 module_name: String,
39 },
40 Closure {
41 captures: Vec<String>,
42 arguments: Vec<String>,
43 },
44 Literal(SimpletonLiteral),
45 GetVariable {
46 name: String,
47 },
48 CallFunction {
49 name: String,
50 module_name: String,
51 },
52 GetField {
53 name: String,
54 },
55 GetArrayItem,
56 GetMapIndex,
57}
58
59#[derive(Debug, Default, Clone, Serialize, Deserialize)]
60pub enum SimpletonNodes {
61 #[default]
62 Start,
63 CreateVariable {
64 name: String,
65 },
66 AssignValue,
67 Expression(SimpletonExpressionNodes),
68 Return,
69 IfElse,
70 While,
71 For {
72 variable: String,
73 },
74}
75
76impl NodeDefinition for SimpletonNodes {
77 type TypeInfo = SimpletonNodeTypeInfo;
78
79 fn node_label(&self, _: &Registry) -> String {
80 match self {
81 SimpletonNodes::Start => "Start".to_owned(),
82 SimpletonNodes::CreateVariable { .. } => "Create variable".to_owned(),
83 SimpletonNodes::AssignValue => "Assign value".to_owned(),
84 SimpletonNodes::Expression(expression) => match expression {
85 SimpletonExpressionNodes::FindStruct { .. } => "Find struct".to_owned(),
86 SimpletonExpressionNodes::FindFunction { .. } => "Find function".to_owned(),
87 SimpletonExpressionNodes::Closure { .. } => "Closure".to_owned(),
88 SimpletonExpressionNodes::Literal(literal) => match literal {
89 SimpletonLiteral::Null => "Null literal".to_owned(),
90 SimpletonLiteral::Boolean(_) => "Boolean literal".to_owned(),
91 SimpletonLiteral::Integer(_) => "Integer literal".to_owned(),
92 SimpletonLiteral::Real(_) => "Real number literal".to_owned(),
93 SimpletonLiteral::Text(_) => "Text literal".to_owned(),
94 SimpletonLiteral::Array { .. } => "Array literal".to_owned(),
95 SimpletonLiteral::Map { .. } => "Map literal".to_owned(),
96 SimpletonLiteral::Object { .. } => "Object literal".to_owned(),
97 },
98 SimpletonExpressionNodes::GetVariable { .. } => "Get variable".to_owned(),
99 SimpletonExpressionNodes::CallFunction { .. } => "Call function".to_owned(),
100 SimpletonExpressionNodes::GetField { .. } => "Get field".to_owned(),
101 SimpletonExpressionNodes::GetArrayItem => "Get array item".to_owned(),
102 SimpletonExpressionNodes::GetMapIndex => "Get map item".to_owned(),
103 },
104 SimpletonNodes::Return => "Return value".to_owned(),
105 SimpletonNodes::IfElse => "If-else branch".to_owned(),
106 SimpletonNodes::While => "While loop".to_owned(),
107 SimpletonNodes::For { .. } => "For loop".to_owned(),
108 }
109 }
110
111 fn node_pins_in(&self, registry: &Registry) -> Vec<NodePin<Self::TypeInfo>> {
112 match self {
113 SimpletonNodes::Start => vec![],
114 SimpletonNodes::CreateVariable { .. } => {
115 vec![
116 NodePin::execute("In", false),
117 NodePin::parameter("Value", SimpletonNodeTypeInfo),
118 NodePin::property("Name"),
119 ]
120 }
121 SimpletonNodes::AssignValue => vec![
122 NodePin::execute("In", false),
123 NodePin::parameter("Object", SimpletonNodeTypeInfo),
124 NodePin::parameter("Value", SimpletonNodeTypeInfo),
125 ],
126 SimpletonNodes::Expression(expression) => match expression {
127 SimpletonExpressionNodes::FindStruct { .. } => {
128 vec![NodePin::property("Name"), NodePin::property("Module name")]
129 }
130 SimpletonExpressionNodes::FindFunction { .. } => {
131 vec![NodePin::property("Name"), NodePin::property("Module name")]
132 }
133 SimpletonExpressionNodes::Closure { .. } => vec![
134 NodePin::property("Captures"),
135 NodePin::property("Arguments"),
136 ],
137 SimpletonExpressionNodes::Literal(literal) => match literal {
138 SimpletonLiteral::Null => vec![],
139 SimpletonLiteral::Array { items } => (0..items.len())
140 .map(|index| {
141 NodePin::parameter(format!("Value #{}", index), SimpletonNodeTypeInfo)
142 })
143 .collect(),
144 SimpletonLiteral::Map { items } => (0..items.len())
145 .flat_map(|index| {
146 [
147 NodePin::property(format!("Key #{}", index)),
148 NodePin::parameter(
149 format!("Value #{}", index),
150 SimpletonNodeTypeInfo,
151 ),
152 ]
153 })
154 .collect(),
155 SimpletonLiteral::Object { fields, .. } => {
156 let mut result =
157 vec![NodePin::property("Name"), NodePin::property("Module name")];
158 result.extend((0..fields.len()).flat_map(|index| {
159 [
160 NodePin::property(format!("Field #{}", index)),
161 NodePin::parameter(
162 format!("Value #{}", index),
163 SimpletonNodeTypeInfo,
164 ),
165 ]
166 }));
167 result
168 }
169 _ => vec![NodePin::property("Value")],
170 },
171 SimpletonExpressionNodes::GetVariable { .. } => vec![NodePin::property("Name")],
172 SimpletonExpressionNodes::CallFunction { name, module_name } => {
173 let mut result =
174 vec![NodePin::property("Name"), NodePin::property("Module name")];
175 if let Some(function) = registry.find_function(FunctionQuery {
176 name: Some(name.into()),
177 module_name: Some(module_name.into()),
178 ..Default::default()
179 }) {
180 result.extend(function.signature().inputs.iter().flat_map(|input| {
181 [NodePin::parameter(&input.name, SimpletonNodeTypeInfo)]
182 }));
183 }
184 result
185 }
186 SimpletonExpressionNodes::GetField { .. } => vec![NodePin::property("Name")],
187 SimpletonExpressionNodes::GetArrayItem => {
188 vec![NodePin::parameter("Index", SimpletonNodeTypeInfo)]
189 }
190 SimpletonExpressionNodes::GetMapIndex => {
191 vec![NodePin::parameter("Key", SimpletonNodeTypeInfo)]
192 }
193 },
194 SimpletonNodes::Return => vec![
195 NodePin::execute("In", false),
196 NodePin::parameter("Value", SimpletonNodeTypeInfo),
197 ],
198 SimpletonNodes::IfElse => vec![
199 NodePin::execute("In", false),
200 NodePin::parameter("Condition", SimpletonNodeTypeInfo),
201 ],
202 SimpletonNodes::While => vec![
203 NodePin::execute("In", false),
204 NodePin::parameter("Condition", SimpletonNodeTypeInfo),
205 ],
206 SimpletonNodes::For { .. } => vec![
207 NodePin::execute("In", false),
208 NodePin::parameter("Iterator", SimpletonNodeTypeInfo),
209 NodePin::property("Variable"),
210 ],
211 }
212 }
213
214 fn node_pins_out(&self, _: &Registry) -> Vec<NodePin<Self::TypeInfo>> {
215 match self {
216 SimpletonNodes::Expression(_) => {
217 vec![NodePin::parameter("Result", SimpletonNodeTypeInfo)]
218 }
219 SimpletonNodes::Return => vec![],
220 SimpletonNodes::IfElse => vec![
221 NodePin::execute("Out", false),
222 NodePin::execute("Success body", true),
223 NodePin::execute("Failure body", true),
224 ],
225 SimpletonNodes::While | SimpletonNodes::For { .. } => vec![
226 NodePin::execute("Out", false),
227 NodePin::execute("Iteration body", true),
228 ],
229 _ => vec![NodePin::execute("Out", false)],
230 }
231 }
232
233 fn node_is_start(&self, _: &Registry) -> bool {
234 matches!(self, Self::Start)
235 }
236
237 fn node_suggestions(
238 x: i64,
239 y: i64,
240 _: NodeSuggestion<Self>,
241 registry: &Registry,
242 ) -> Vec<ResponseSuggestionNode<Self>> {
243 vec![
244 ResponseSuggestionNode::new(
245 "Variable",
246 Node::new(
247 x,
248 y,
249 SimpletonNodes::CreateVariable {
250 name: "variable".to_owned(),
251 },
252 ),
253 registry,
254 ),
255 ResponseSuggestionNode::new(
256 "Variable",
257 Node::new(x, y, SimpletonNodes::AssignValue),
258 registry,
259 ),
260 ResponseSuggestionNode::new(
261 "Type",
262 Node::new(
263 x,
264 y,
265 SimpletonNodes::Expression(SimpletonExpressionNodes::FindStruct {
266 name: "Integer".to_owned(),
267 module_name: "math".to_owned(),
268 }),
269 ),
270 registry,
271 ),
272 ResponseSuggestionNode::new(
273 "Type",
274 Node::new(
275 x,
276 y,
277 SimpletonNodes::Expression(SimpletonExpressionNodes::FindFunction {
278 name: "add".to_owned(),
279 module_name: "math".to_owned(),
280 }),
281 ),
282 registry,
283 ),
284 ResponseSuggestionNode::new(
285 "Type",
286 Node::new(
287 x,
288 y,
289 SimpletonNodes::Expression(SimpletonExpressionNodes::Closure {
290 captures: vec![],
291 arguments: vec![],
292 }),
293 ),
294 registry,
295 ),
296 ResponseSuggestionNode::new(
297 "Literal",
298 Node::new(
299 x,
300 y,
301 SimpletonNodes::Expression(SimpletonExpressionNodes::Literal(
302 SimpletonLiteral::Null,
303 )),
304 ),
305 registry,
306 ),
307 ResponseSuggestionNode::new(
308 "Literal",
309 Node::new(
310 x,
311 y,
312 SimpletonNodes::Expression(SimpletonExpressionNodes::Literal(
313 SimpletonLiteral::Boolean(false),
314 )),
315 ),
316 registry,
317 ),
318 ResponseSuggestionNode::new(
319 "Literal",
320 Node::new(
321 x,
322 y,
323 SimpletonNodes::Expression(SimpletonExpressionNodes::Literal(
324 SimpletonLiteral::Integer(0),
325 )),
326 ),
327 registry,
328 ),
329 ResponseSuggestionNode::new(
330 "Literal",
331 Node::new(
332 x,
333 y,
334 SimpletonNodes::Expression(SimpletonExpressionNodes::Literal(
335 SimpletonLiteral::Real(0.0),
336 )),
337 ),
338 registry,
339 ),
340 ResponseSuggestionNode::new(
341 "Literal",
342 Node::new(
343 x,
344 y,
345 SimpletonNodes::Expression(SimpletonExpressionNodes::Literal(
346 SimpletonLiteral::Text("text".to_owned()),
347 )),
348 ),
349 registry,
350 ),
351 ResponseSuggestionNode::new(
352 "Literal",
353 Node::new(
354 x,
355 y,
356 SimpletonNodes::Expression(SimpletonExpressionNodes::Literal(
357 SimpletonLiteral::Array { items: vec![] },
358 )),
359 ),
360 registry,
361 ),
362 ResponseSuggestionNode::new(
363 "Literal",
364 Node::new(
365 x,
366 y,
367 SimpletonNodes::Expression(SimpletonExpressionNodes::Literal(
368 SimpletonLiteral::Map { items: vec![] },
369 )),
370 ),
371 registry,
372 ),
373 ResponseSuggestionNode::new(
374 "Literal",
375 Node::new(
376 x,
377 y,
378 SimpletonNodes::Expression(SimpletonExpressionNodes::Literal(
379 SimpletonLiteral::Object {
380 name: "Integer".to_owned(),
381 module_name: "math".to_owned(),
382 fields: vec![],
383 },
384 )),
385 ),
386 registry,
387 ),
388 ResponseSuggestionNode::new(
389 "Access",
390 Node::new(
391 x,
392 y,
393 SimpletonNodes::Expression(SimpletonExpressionNodes::GetVariable {
394 name: "variable".to_owned(),
395 }),
396 ),
397 registry,
398 ),
399 ResponseSuggestionNode::new(
400 "Call",
401 Node::new(
402 x,
403 y,
404 SimpletonNodes::Expression(SimpletonExpressionNodes::CallFunction {
405 name: "add".to_owned(),
406 module_name: "math".to_owned(),
407 }),
408 ),
409 registry,
410 ),
411 ResponseSuggestionNode::new(
412 "Access",
413 Node::new(
414 x,
415 y,
416 SimpletonNodes::Expression(SimpletonExpressionNodes::GetField {
417 name: "field".to_owned(),
418 }),
419 ),
420 registry,
421 ),
422 ResponseSuggestionNode::new(
423 "Access",
424 Node::new(
425 x,
426 y,
427 SimpletonNodes::Expression(SimpletonExpressionNodes::GetArrayItem),
428 ),
429 registry,
430 ),
431 ResponseSuggestionNode::new(
432 "Access",
433 Node::new(
434 x,
435 y,
436 SimpletonNodes::Expression(SimpletonExpressionNodes::GetMapIndex),
437 ),
438 registry,
439 ),
440 ResponseSuggestionNode::new(
441 "Statement",
442 Node::new(x, y, SimpletonNodes::Return),
443 registry,
444 ),
445 ResponseSuggestionNode::new("Scope", Node::new(x, y, SimpletonNodes::IfElse), registry),
446 ResponseSuggestionNode::new("Scope", Node::new(x, y, SimpletonNodes::While), registry),
447 ResponseSuggestionNode::new(
448 "Scope",
449 Node::new(
450 x,
451 y,
452 SimpletonNodes::For {
453 variable: "item".to_owned(),
454 },
455 ),
456 registry,
457 ),
458 ]
459 }
460
461 fn get_property(&self, property_name: &str) -> Option<PropertyValue> {
462 match self {
463 SimpletonNodes::CreateVariable { name } => match property_name {
464 "Name" => PropertyValue::new(name).ok(),
465 _ => None,
466 },
467 SimpletonNodes::Expression(expression) => match expression {
468 SimpletonExpressionNodes::FindStruct { name, module_name }
469 | SimpletonExpressionNodes::FindFunction { name, module_name }
470 | SimpletonExpressionNodes::CallFunction { name, module_name } => {
471 match property_name {
472 "Name" => PropertyValue::new(name).ok(),
473 "Module name" => PropertyValue::new(module_name).ok(),
474 _ => None,
475 }
476 }
477 SimpletonExpressionNodes::Closure {
478 captures,
479 arguments,
480 } => match property_name {
481 "Captures" => PropertyValue::new(captures).ok(),
482 "Arguments" => PropertyValue::new(arguments).ok(),
483 _ => None,
484 },
485 SimpletonExpressionNodes::Literal(literal) => match literal {
486 SimpletonLiteral::Null => None,
487 SimpletonLiteral::Boolean(value) => match property_name {
488 "Value" => PropertyValue::new(value).ok(),
489 _ => None,
490 },
491 SimpletonLiteral::Integer(value) => match property_name {
492 "Value" => PropertyValue::new(value).ok(),
493 _ => None,
494 },
495 SimpletonLiteral::Real(value) => match property_name {
496 "Value" => PropertyValue::new(value).ok(),
497 _ => None,
498 },
499 SimpletonLiteral::Text(value) => match property_name {
500 "Value" => PropertyValue::new(value).ok(),
501 _ => None,
502 },
503 SimpletonLiteral::Array { .. } => None,
504 SimpletonLiteral::Map { items } => property_name
505 .strip_prefix("Key #")
506 .and_then(|property_name| {
507 property_name
508 .parse::<usize>()
509 .ok()
510 .and_then(|index| items.get(index))
511 .and_then(|(value, _)| PropertyValue::new(value).ok())
512 }),
513 SimpletonLiteral::Object {
514 name,
515 module_name,
516 fields,
517 } => match property_name {
518 "Name" => PropertyValue::new(name).ok(),
519 "Module name" => PropertyValue::new(module_name).ok(),
520 _ => property_name
521 .strip_prefix("Field #")
522 .and_then(|property_name| {
523 property_name
524 .parse::<usize>()
525 .ok()
526 .and_then(|index| fields.get(index))
527 .and_then(|(value, _)| PropertyValue::new(value).ok())
528 }),
529 },
530 },
531 SimpletonExpressionNodes::GetVariable { name }
532 | SimpletonExpressionNodes::GetField { name } => match property_name {
533 "Name" => PropertyValue::new(name).ok(),
534 _ => None,
535 },
536 _ => None,
537 },
538 SimpletonNodes::For { variable } => match property_name {
539 "Variable" => PropertyValue::new(variable).ok(),
540 _ => None,
541 },
542 _ => None,
543 }
544 }
545
546 fn set_property(&mut self, property_name: &str, property_value: PropertyValue) {
547 match self {
548 SimpletonNodes::CreateVariable { name } => {
549 if property_name == "Name" {
550 if let Ok(v) = property_value.get_exact() {
551 *name = v;
552 }
553 }
554 }
555 SimpletonNodes::Expression(expression) => match expression {
556 SimpletonExpressionNodes::FindStruct { name, module_name }
557 | SimpletonExpressionNodes::FindFunction { name, module_name }
558 | SimpletonExpressionNodes::CallFunction { name, module_name } => {
559 match property_name {
560 "Name" => {
561 if let Ok(v) = property_value.get_exact() {
562 *name = v;
563 }
564 }
565 "Module name" => {
566 if let Ok(v) = property_value.get_exact() {
567 *module_name = v;
568 }
569 }
570 _ => {}
571 }
572 }
573 SimpletonExpressionNodes::Closure {
574 captures,
575 arguments,
576 } => match property_name {
577 "Captures" => {
578 if let Ok(v) = property_value.get_exact() {
579 *captures = v;
580 }
581 }
582 "Arguments" => {
583 if let Ok(v) = property_value.get_exact() {
584 *arguments = v;
585 }
586 }
587 _ => {}
588 },
589 SimpletonExpressionNodes::Literal(literal) => match literal {
590 SimpletonLiteral::Null => {}
591 SimpletonLiteral::Boolean(value) => {
592 if property_name == "Value" {
593 if let Ok(v) = property_value.get_exact() {
594 *value = v;
595 }
596 }
597 }
598 SimpletonLiteral::Integer(value) => {
599 if property_name == "Value" {
600 if let Ok(v) = property_value.get_exact() {
601 *value = v;
602 }
603 }
604 }
605 SimpletonLiteral::Real(value) => {
606 if property_name == "Value" {
607 if let Ok(v) = property_value.get_exact() {
608 *value = v;
609 }
610 }
611 }
612 SimpletonLiteral::Text(value) => {
613 if property_name == "Value" {
614 if let Ok(v) = property_value.get_exact() {
615 *value = v;
616 }
617 }
618 }
619 SimpletonLiteral::Array { .. } => {}
620 SimpletonLiteral::Map { items } => {
621 if let Some(property_name) = property_name.strip_prefix("Key #") {
622 if let Ok(v) = property_value.get_exact() {
623 if let Some((value, _)) = property_name
624 .parse::<usize>()
625 .ok()
626 .and_then(|index| items.get_mut(index))
627 {
628 *value = v;
629 }
630 }
631 }
632 }
633 SimpletonLiteral::Object {
634 name,
635 module_name,
636 fields,
637 } => match property_name {
638 "Name" => {
639 if let Ok(v) = property_value.get_exact() {
640 *name = v;
641 }
642 }
643 "Module name" => {
644 if let Ok(v) = property_value.get_exact() {
645 *module_name = v;
646 }
647 }
648 _ => {
649 if let Some(property_name) = property_name.strip_prefix("Field #") {
650 if let Ok(v) = property_value.get_exact() {
651 if let Some((value, _)) = property_name
652 .parse::<usize>()
653 .ok()
654 .and_then(|index| fields.get_mut(index))
655 {
656 *value = v;
657 }
658 }
659 }
660 }
661 },
662 },
663 SimpletonExpressionNodes::GetVariable { name }
664 | SimpletonExpressionNodes::GetField { name } => {
665 if property_name == "Name" {
666 if let Ok(v) = property_value.get_exact::<String>() {
667 *name = v;
668 }
669 }
670 }
671 _ => {}
672 },
673 SimpletonNodes::For { variable } => {
674 if property_name == "Variable" {
675 if let Ok(v) = property_value.get_exact::<String>() {
676 *variable = v;
677 }
678 }
679 }
680 _ => {}
681 }
682 }
683}
684
685