1use serde::{Deserialize, Serialize};
30use std::fmt;
31
32#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
50pub struct Comment {
51 pub kind: CommentKind,
53 pub span: Span,
55}
56
57impl Comment {
58 #[must_use]
60 pub fn new(kind: CommentKind, span: Span) -> Self {
61 Self { kind, span }
62 }
63}
64
65#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
72pub enum CommentKind {
73 Line(String),
75 Doc(String),
77 Block(String),
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
102pub struct Span {
103 pub start: usize,
105 pub end: usize,
107}
108impl Span {
109 #[must_use]
126 pub fn new(start: usize, end: usize) -> Self {
127 Self { start, end }
128 }
129 #[must_use]
156 pub fn merge(self, other: Self) -> Self {
157 Self {
158 start: self.start.min(other.start),
159 end: self.end.max(other.end),
160 }
161 }
162}
163#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
181pub struct CatchClause {
182 pub pattern: Pattern,
184 pub body: Box<Expr>,
186}
187
188#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
190pub struct ComprehensionClause {
191 pub variable: String,
193 pub iterable: Box<Expr>,
195 pub condition: Option<Box<Expr>>,
197}
198
199#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
231pub struct Expr {
232 pub kind: ExprKind,
234 pub span: Span,
236 pub attributes: Vec<Attribute>,
238 pub leading_comments: Vec<Comment>,
243 pub trailing_comment: Option<Comment>,
248}
249impl Expr {
250 #[must_use]
271 pub fn new(kind: ExprKind, span: Span) -> Self {
272 Self {
273 kind,
274 span,
275 attributes: Vec::new(),
276 leading_comments: Vec::new(),
277 trailing_comment: None,
278 }
279 }
280
281 #[must_use]
312 pub fn with_comments(
313 kind: ExprKind,
314 span: Span,
315 leading_comments: Vec<Comment>,
316 trailing_comment: Option<Comment>,
317 ) -> Self {
318 Self {
319 kind,
320 span,
321 attributes: Vec::new(),
322 leading_comments,
323 trailing_comment,
324 }
325 }
326 #[must_use]
350 pub fn with_attributes(kind: ExprKind, span: Span, attributes: Vec<Attribute>) -> Self {
351 Self {
352 kind,
353 span,
354 attributes,
355 leading_comments: Vec::new(),
356 trailing_comment: None,
357 }
358 }
359}
360#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
395pub enum ExprKind {
396 Literal(Literal),
398 Identifier(String),
400 QualifiedName {
402 module: String,
404 name: String,
406 },
407 StringInterpolation {
409 parts: Vec<StringPart>,
411 },
412 Binary {
414 left: Box<Expr>,
416 op: BinaryOp,
418 right: Box<Expr>,
420 },
421 Unary {
423 op: UnaryOp,
425 operand: Box<Expr>,
427 },
428 Throw {
430 expr: Box<Expr>,
432 },
433 TryCatch {
435 try_block: Box<Expr>,
437 catch_clauses: Vec<CatchClause>,
439 finally_block: Option<Box<Expr>>,
441 },
442 Ok {
443 value: Box<Expr>,
444 },
445 Err {
446 error: Box<Expr>,
447 },
448 Some {
449 value: Box<Expr>,
450 },
451 None,
452 TypeCast {
453 expr: Box<Expr>,
454 target_type: String,
455 },
456 Ternary {
458 condition: Box<Expr>,
459 true_expr: Box<Expr>,
460 false_expr: Box<Expr>,
461 },
462 Try {
463 expr: Box<Expr>,
464 },
465 Await {
466 expr: Box<Expr>,
467 },
468 Spawn {
469 actor: Box<Expr>,
470 },
471 AsyncBlock {
472 body: Box<Expr>,
473 },
474 If {
475 condition: Box<Expr>,
476 then_branch: Box<Expr>,
477 else_branch: Option<Box<Expr>>,
478 },
479 IfLet {
480 pattern: Pattern,
481 expr: Box<Expr>,
482 then_branch: Box<Expr>,
483 else_branch: Option<Box<Expr>>,
484 },
485 Let {
486 name: String,
487 type_annotation: Option<Type>,
488 value: Box<Expr>,
489 body: Box<Expr>,
490 is_mutable: bool,
491 else_block: Option<Box<Expr>>, },
493 LetPattern {
494 pattern: Pattern,
495 type_annotation: Option<Type>,
496 value: Box<Expr>,
497 body: Box<Expr>,
498 is_mutable: bool,
499 else_block: Option<Box<Expr>>, },
501 Function {
502 name: String,
503 type_params: Vec<String>,
504 params: Vec<Param>,
505 return_type: Option<Type>,
506 body: Box<Expr>,
507 is_async: bool,
508 is_pub: bool,
509 },
510 Lambda {
511 params: Vec<Param>,
512 body: Box<Expr>,
513 },
514 AsyncLambda {
515 params: Vec<String>,
516 body: Box<Expr>,
517 },
518 Struct {
519 name: String,
520 type_params: Vec<String>,
521 fields: Vec<StructField>,
522 derives: Vec<String>, is_pub: bool,
524 },
525 TupleStruct {
526 name: String,
527 type_params: Vec<String>,
528 fields: Vec<Type>, derives: Vec<String>,
530 is_pub: bool,
531 },
532 Class {
533 name: String,
534 type_params: Vec<String>,
535 superclass: Option<String>, traits: Vec<String>, fields: Vec<StructField>,
538 constructors: Vec<Constructor>, methods: Vec<ClassMethod>,
540 constants: Vec<ClassConstant>, properties: Vec<ClassProperty>, derives: Vec<String>, decorators: Vec<Decorator>, is_pub: bool,
545 is_sealed: bool, is_abstract: bool, },
548 Enum {
549 name: String,
550 type_params: Vec<String>,
551 variants: Vec<EnumVariant>,
552 is_pub: bool,
553 },
554 StructLiteral {
555 name: String,
556 fields: Vec<(String, Expr)>,
557 base: Option<Box<Expr>>, },
559 ObjectLiteral {
560 fields: Vec<ObjectField>,
561 },
562 FieldAccess {
563 object: Box<Expr>,
564 field: String,
565 },
566 OptionalFieldAccess {
567 object: Box<Expr>,
568 field: String,
569 },
570 IndexAccess {
571 object: Box<Expr>,
572 index: Box<Expr>,
573 },
574 Slice {
575 object: Box<Expr>,
576 start: Option<Box<Expr>>,
577 end: Option<Box<Expr>>,
578 },
579 Trait {
580 name: String,
581 type_params: Vec<String>,
582 associated_types: Vec<String>, methods: Vec<TraitMethod>,
584 is_pub: bool,
585 },
586 Impl {
587 type_params: Vec<String>,
588 trait_name: Option<String>,
589 for_type: String,
590 methods: Vec<ImplMethod>,
591 is_pub: bool,
592 },
593 Actor {
594 name: String,
595 state: Vec<StructField>,
596 handlers: Vec<ActorHandler>,
597 },
598 Send {
599 actor: Box<Expr>,
600 message: Box<Expr>,
601 },
602 Command {
603 program: String,
604 args: Vec<String>,
605 env: Vec<(String, String)>,
606 working_dir: Option<String>,
607 },
608 Ask {
609 actor: Box<Expr>,
610 message: Box<Expr>,
611 timeout: Option<Box<Expr>>,
612 },
613 ActorSend {
615 actor: Box<Expr>,
616 message: Box<Expr>,
617 },
618 ActorQuery {
620 actor: Box<Expr>,
621 message: Box<Expr>,
622 },
623 Call {
624 func: Box<Expr>,
625 args: Vec<Expr>,
626 },
627 Macro {
628 name: String,
629 args: Vec<Expr>,
630 },
631 MethodCall {
632 receiver: Box<Expr>,
633 method: String,
634 args: Vec<Expr>,
635 },
636 OptionalMethodCall {
637 receiver: Box<Expr>,
638 method: String,
639 args: Vec<Expr>,
640 },
641 Block(Vec<Expr>),
642 Pipeline {
643 expr: Box<Expr>,
644 stages: Vec<PipelineStage>,
645 },
646 Match {
647 expr: Box<Expr>,
648 arms: Vec<MatchArm>,
649 },
650 List(Vec<Expr>),
651 Set(Vec<Expr>),
652 ArrayInit {
653 value: Box<Expr>,
654 size: Box<Expr>,
655 },
656 Tuple(Vec<Expr>),
657 Spread {
658 expr: Box<Expr>,
659 },
660 ListComprehension {
661 element: Box<Expr>,
662 clauses: Vec<ComprehensionClause>,
663 },
664 SetComprehension {
665 element: Box<Expr>,
666 clauses: Vec<ComprehensionClause>,
667 },
668 DictComprehension {
669 key: Box<Expr>,
670 value: Box<Expr>,
671 clauses: Vec<ComprehensionClause>,
672 },
673 DataFrame {
674 columns: Vec<DataFrameColumn>,
675 },
676 DataFrameOperation {
677 source: Box<Expr>,
678 operation: DataFrameOp,
679 },
680 For {
681 label: Option<String>,
682 var: String, pattern: Option<Pattern>, iter: Box<Expr>,
685 body: Box<Expr>,
686 },
687 While {
688 label: Option<String>,
689 condition: Box<Expr>,
690 body: Box<Expr>,
691 },
692 WhileLet {
693 label: Option<String>,
694 pattern: Pattern,
695 expr: Box<Expr>,
696 body: Box<Expr>,
697 },
698 Loop {
699 label: Option<String>,
700 body: Box<Expr>,
701 },
702 Range {
703 start: Box<Expr>,
704 end: Box<Expr>,
705 inclusive: bool,
706 },
707 Module {
708 name: String,
709 body: Box<Expr>,
710 },
711 Break {
712 label: Option<String>,
713 value: Option<Box<Expr>>,
714 },
715 Continue {
716 label: Option<String>,
717 },
718 Return {
719 value: Option<Box<Expr>>,
720 },
721 Assign {
722 target: Box<Expr>,
723 value: Box<Expr>,
724 },
725 CompoundAssign {
726 target: Box<Expr>,
727 op: BinaryOp,
728 value: Box<Expr>,
729 },
730 PreIncrement {
731 target: Box<Expr>,
732 },
733 PostIncrement {
734 target: Box<Expr>,
735 },
736 PreDecrement {
737 target: Box<Expr>,
738 },
739 PostDecrement {
740 target: Box<Expr>,
741 },
742 Extension {
743 target_type: String,
744 methods: Vec<ImplMethod>,
745 },
746 Import {
748 module: String,
749 items: Option<Vec<String>>,
750 },
751 ImportAll {
753 module: String,
754 alias: String,
755 },
756 ImportDefault {
758 module: String,
759 name: String,
760 },
761 Export {
763 expr: Box<Expr>,
764 is_default: bool,
765 },
766 ExportList {
768 names: Vec<String>,
769 },
770 ReExport {
772 items: Vec<String>,
773 module: String,
774 },
775 ExportDefault {
777 expr: Box<Expr>,
778 },
779 TypeAlias {
781 name: String,
782 target_type: Type,
783 },
784 MacroInvocation {
786 name: String,
787 args: Vec<Expr>,
788 },
789}
790#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
809pub enum Literal {
810 Integer(i64, Option<String>),
812 Float(f64),
814 String(String),
816 Bool(bool),
818 Char(char),
820 Byte(u8),
822 Unit,
824 Null,
826}
827impl Literal {
828 pub fn from_value(value: &crate::runtime::interpreter::Value) -> Self {
830 use crate::runtime::interpreter::Value;
831 match value {
832 Value::Integer(i) => Literal::Integer(*i, None),
833 Value::Float(f) => Literal::Float(*f),
834 Value::String(s) => Literal::String(s.to_string()),
835 Value::Bool(b) => Literal::Bool(*b),
836 Value::Nil => Literal::Unit,
837 _ => Literal::Unit, }
839 }
840}
841#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
843pub enum StringPart {
844 Text(String),
846 Expr(Box<Expr>),
848 ExprWithFormat {
850 expr: Box<Expr>,
851 format_spec: String,
852 },
853}
854#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
875pub enum BinaryOp {
876 Add,
878 Subtract,
879 Multiply,
880 Divide,
881 Modulo,
882 Power,
883 Equal,
885 NotEqual,
886 Less,
887 LessEqual,
888 Greater,
889 GreaterEqual,
890 Gt, And,
893 Or,
894 NullCoalesce,
895 BitwiseAnd,
897 BitwiseOr,
898 BitwiseXor,
899 LeftShift,
900 RightShift,
901 Send, }
904#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
924pub enum UnaryOp {
925 Not,
926 Negate,
927 BitwiseNot,
928 Reference,
929 MutableReference, Deref,
931}
932#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
947pub struct Param {
948 pub pattern: Pattern,
950 pub ty: Type,
952 pub span: Span,
954 pub is_mutable: bool,
956 pub default_value: Option<Box<Expr>>,
958}
959impl Param {
960 #[must_use]
964 pub fn name(&self) -> String {
965 self.pattern.primary_name()
966 }
967}
968
969#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
970pub enum Visibility {
971 Private,
972 Public,
973 PubCrate,
974 PubSuper,
975 Protected, }
977
978impl Visibility {
979 pub fn is_public(&self) -> bool {
980 matches!(
981 self,
982 Visibility::Public | Visibility::PubCrate | Visibility::PubSuper
983 )
984 }
985}
986
987#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
988pub struct StructField {
989 pub name: String,
990 pub ty: Type,
991 pub visibility: Visibility,
992 pub is_mut: bool, pub default_value: Option<Expr>, pub decorators: Vec<Decorator>, }
996#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
997pub struct EnumVariant {
998 pub name: String,
999 pub kind: EnumVariantKind,
1000 pub discriminant: Option<i64>, }
1002
1003#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1004pub enum EnumVariantKind {
1005 Unit, Tuple(Vec<Type>), Struct(Vec<StructField>), }
1009#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1010pub enum ObjectField {
1011 KeyValue { key: String, value: Expr },
1012 Spread { expr: Expr },
1013}
1014#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1015pub struct TraitMethod {
1016 pub name: String,
1017 pub params: Vec<Param>,
1018 pub return_type: Option<Type>,
1019 pub body: Option<Box<Expr>>, pub is_pub: bool,
1021}
1022#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1023pub struct ImplMethod {
1024 pub name: String,
1025 pub params: Vec<Param>,
1026 pub return_type: Option<Type>,
1027 pub body: Box<Expr>,
1028 pub is_pub: bool,
1029}
1030#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1031pub struct ActorHandler {
1032 pub message_type: String,
1033 pub params: Vec<Param>,
1034 pub body: Box<Expr>,
1035}
1036
1037#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1038pub struct ClassMethod {
1039 pub name: String,
1040 pub params: Vec<Param>,
1041 pub return_type: Option<Type>,
1042 pub body: Box<Expr>,
1043 pub is_pub: bool,
1044 pub is_static: bool, pub is_override: bool, pub is_final: bool, pub is_abstract: bool, pub self_type: SelfType, }
1050
1051#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1052pub struct ClassConstant {
1053 pub name: String,
1054 pub ty: Type,
1055 pub value: Expr,
1056 pub is_pub: bool,
1057}
1058
1059#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1060pub struct ClassProperty {
1061 pub name: String,
1062 pub ty: Type,
1063 pub getter: Option<Box<Expr>>,
1064 pub setter: Option<PropertySetter>,
1065 pub is_pub: bool,
1066}
1067
1068#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1069pub struct PropertySetter {
1070 pub param_name: String,
1071 pub body: Box<Expr>,
1072}
1073
1074#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1075pub enum SelfType {
1076 None, Owned, Borrowed, MutBorrowed, }
1081
1082#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1083pub struct Constructor {
1084 pub name: Option<String>, pub params: Vec<Param>,
1086 pub return_type: Option<Type>, pub body: Box<Expr>,
1088 pub is_pub: bool,
1089}
1090#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1117pub struct Type {
1118 pub kind: TypeKind,
1120 pub span: Span,
1122}
1123#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1128pub enum TypeKind {
1129 Named(String),
1130 Generic {
1131 base: String,
1132 params: Vec<Type>,
1133 },
1134 Optional(Box<Type>),
1135 List(Box<Type>),
1136 Array {
1137 elem_type: Box<Type>,
1138 size: usize,
1139 },
1140 Tuple(Vec<Type>),
1141 Function {
1142 params: Vec<Type>,
1143 ret: Box<Type>,
1144 },
1145 DataFrame {
1146 columns: Vec<(String, Type)>,
1147 },
1148 Series {
1149 dtype: Box<Type>,
1150 },
1151 Reference {
1152 is_mut: bool,
1153 lifetime: Option<String>,
1154 inner: Box<Type>,
1155 },
1156}
1157#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1158pub struct PipelineStage {
1159 pub op: Box<Expr>,
1160 pub span: Span,
1161}
1162#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1178pub struct MatchArm {
1179 pub pattern: Pattern,
1181 pub guard: Option<Box<Expr>>,
1183 pub body: Box<Expr>,
1185 pub span: Span,
1187}
1188#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1217pub enum Pattern {
1218 Wildcard,
1219 Literal(Literal),
1220 Identifier(String),
1221 QualifiedName(Vec<String>), Tuple(Vec<Pattern>),
1223 List(Vec<Pattern>),
1224 Struct {
1225 name: String,
1226 fields: Vec<StructPatternField>,
1227 has_rest: bool,
1228 },
1229 TupleVariant {
1230 path: Vec<String>, patterns: Vec<Pattern>, }, Range {
1234 start: Box<Pattern>,
1235 end: Box<Pattern>,
1236 inclusive: bool,
1237 },
1238 Or(Vec<Pattern>),
1239 Rest, RestNamed(String), AtBinding {
1242 name: String,
1243 pattern: Box<Pattern>,
1244 }, WithDefault {
1246 pattern: Box<Pattern>,
1247 default: Box<Expr>,
1248 }, Mut(Box<Pattern>), Ok(Box<Pattern>),
1251 Err(Box<Pattern>),
1252 Some(Box<Pattern>),
1253 None,
1254}
1255impl Pattern {
1256 #[must_use]
1259 pub fn primary_name(&self) -> String {
1260 match self {
1261 Pattern::Identifier(name) => name.clone(),
1262 Pattern::QualifiedName(path) => path.join("::"),
1263 Pattern::Tuple(patterns) => {
1264 patterns
1266 .first()
1267 .map_or_else(|| "_tuple".to_string(), Pattern::primary_name)
1268 }
1269 Pattern::List(patterns) => {
1270 patterns
1272 .first()
1273 .map_or_else(|| "_list".to_string(), Pattern::primary_name)
1274 }
1275 Pattern::Struct { name, fields, .. } => {
1276 if name.is_empty() {
1278 fields
1279 .first()
1280 .map_or_else(|| "_struct".to_string(), |f| f.name.clone())
1281 } else {
1282 name.clone()
1283 }
1284 }
1285 Pattern::TupleVariant { path, patterns } => {
1286 patterns
1288 .first()
1289 .map_or_else(|| path.join("::"), Pattern::primary_name)
1290 }
1291 Pattern::Ok(inner) | Pattern::Err(inner) | Pattern::Some(inner) => inner.primary_name(),
1292 Pattern::None => "_none".to_string(),
1293 Pattern::Or(patterns) => {
1294 patterns
1296 .first()
1297 .map_or_else(|| "_or".to_string(), Pattern::primary_name)
1298 }
1299 Pattern::Wildcard => "_".to_string(),
1300 Pattern::Rest => "_rest".to_string(),
1301 Pattern::RestNamed(name) => name.clone(),
1302 Pattern::AtBinding { name, .. } => name.clone(),
1303 Pattern::WithDefault { pattern, .. } => pattern.primary_name(),
1304 Pattern::Mut(inner) => inner.primary_name(),
1305 Pattern::Literal(lit) => format!("_literal_{lit:?}"),
1306 Pattern::Range { .. } => "_range".to_string(),
1307 }
1308 }
1309}
1310#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1315pub struct StructPatternField {
1316 pub name: String,
1318 pub pattern: Option<Pattern>,
1320}
1321#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1335pub struct ErrorTypeDef {
1336 pub name: String,
1338 pub fields: Vec<StructField>,
1340 pub extends: Option<String>,
1342}
1343#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1365pub struct Attribute {
1366 pub name: String,
1367 pub args: Vec<String>,
1368 pub span: Span,
1369}
1370
1371#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1373pub struct Decorator {
1374 pub name: String,
1375 pub args: Vec<String>,
1376}
1377#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1378pub struct DataFrameColumn {
1379 pub name: String,
1380 pub values: Vec<Expr>,
1381}
1382#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1397pub enum DataFrameOp {
1398 Filter(Box<Expr>),
1399 Select(Vec<String>),
1400 GroupBy(Vec<String>),
1401 Sort(Vec<String>),
1402 Join {
1403 other: Box<Expr>,
1404 on: Vec<String>,
1405 how: JoinType,
1406 },
1407 Aggregate(Vec<AggregateOp>),
1408 Limit(usize),
1409 Head(usize),
1410 Tail(usize),
1411}
1412#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1413pub enum JoinType {
1414 Inner,
1415 Left,
1416 Right,
1417 Outer,
1418}
1419#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1420pub enum ImportItem {
1421 Named(String),
1423 Aliased { name: String, alias: String },
1425 Wildcard,
1427}
1428impl ImportItem {
1429 pub fn is_url_import(path: &str) -> bool {
1431 path.starts_with("https://") || path.starts_with("http://")
1432 }
1433}
1434#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1435pub enum AggregateOp {
1436 Sum(String),
1437 Mean(String),
1438 Min(String),
1439 Max(String),
1440 Count(String),
1441 Std(String),
1442 Var(String),
1443}
1444impl fmt::Display for BinaryOp {
1445 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1446 match self {
1447 Self::Add => write!(f, "+"),
1448 Self::Subtract => write!(f, "-"),
1449 Self::Multiply => write!(f, "*"),
1450 Self::Divide => write!(f, "/"),
1451 Self::Modulo => write!(f, "%"),
1452 Self::Power => write!(f, "**"),
1453 Self::Equal => write!(f, "=="),
1454 Self::NotEqual => write!(f, "!="),
1455 Self::Less => write!(f, "<"),
1456 Self::LessEqual => write!(f, "<="),
1457 Self::Greater => write!(f, ">"),
1458 Self::GreaterEqual => write!(f, ">="),
1459 Self::And => write!(f, "&&"),
1460 Self::Or => write!(f, "||"),
1461 Self::NullCoalesce => write!(f, "??"),
1462 Self::BitwiseAnd => write!(f, "&"),
1463 Self::BitwiseOr => write!(f, "|"),
1464 Self::BitwiseXor => write!(f, "^"),
1465 Self::LeftShift => write!(f, "<<"),
1466 Self::RightShift => write!(f, ">>"),
1467 Self::Gt => write!(f, ">"),
1468 Self::Send => write!(f, "!"),
1469 }
1470 }
1471}
1472impl fmt::Display for UnaryOp {
1473 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1474 match self {
1475 Self::Not => write!(f, "!"),
1476 Self::Negate => write!(f, "-"),
1477 Self::BitwiseNot => write!(f, "~"),
1478 Self::Reference => write!(f, "&"),
1479 Self::MutableReference => write!(f, "&mut "), Self::Deref => write!(f, "*"),
1481 }
1482 }
1483}
1484#[cfg(test)]
1485#[allow(clippy::unwrap_used, clippy::panic, clippy::expect_used)]
1486mod tests {
1487 use super::*;
1488 use proptest::prelude::*;
1489 proptest! {
1490 #[test]
1491 fn test_span_merge(start1 in 0usize..1000, end1 in 0usize..1000,
1492 start2 in 0usize..1000, end2 in 0usize..1000) {
1493 let span1 = Span::new(start1, end1);
1494 let span2 = Span::new(start2, end2);
1495 let merged = span1.merge(span2);
1496 prop_assert!(merged.start <= span1.start);
1497 prop_assert!(merged.start <= span2.start);
1498 prop_assert!(merged.end >= span1.end);
1499 prop_assert!(merged.end >= span2.end);
1500 }
1501 }
1502 #[test]
1503 fn test_ast_size() {
1504 let expr_size = std::mem::size_of::<Expr>();
1506 let kind_size = std::mem::size_of::<ExprKind>();
1507 assert!(expr_size <= 400, "Expr too large: {expr_size} bytes");
1511 assert!(kind_size <= 280, "ExprKind too large: {kind_size} bytes");
1512 }
1513 #[test]
1514 fn test_span_creation() {
1515 let span = Span::new(10, 20);
1516 assert_eq!(span.start, 10);
1517 assert_eq!(span.end, 20);
1518 }
1519 #[test]
1520 fn test_span_merge_simple() {
1521 let span1 = Span::new(5, 10);
1522 let span2 = Span::new(8, 15);
1523 let merged = span1.merge(span2);
1524 assert_eq!(merged.start, 5);
1525 assert_eq!(merged.end, 15);
1526 }
1527 #[test]
1528 fn test_span_merge_disjoint() {
1529 let span1 = Span::new(0, 5);
1530 let span2 = Span::new(10, 15);
1531 let merged = span1.merge(span2);
1532 assert_eq!(merged.start, 0);
1533 assert_eq!(merged.end, 15);
1534 }
1535 #[test]
1536 fn test_expr_creation() {
1537 let span = Span::new(0, 10);
1538 let expr = Expr::new(ExprKind::Literal(Literal::Integer(42, None)), span);
1539 assert_eq!(expr.span.start, 0);
1540 assert_eq!(expr.span.end, 10);
1541 match expr.kind {
1542 ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 42),
1543 _ => panic!("Wrong expression kind"),
1544 }
1545 }
1546 #[test]
1547 fn test_literal_variants() {
1548 let literals = vec![
1549 Literal::Integer(42, None),
1550 #[allow(clippy::approx_constant)]
1551 Literal::Float(3.14), Literal::String("hello".to_string()),
1553 Literal::Bool(true),
1554 Literal::Unit,
1555 ];
1556 for lit in literals {
1557 let expr = Expr::new(ExprKind::Literal(lit.clone()), Span::new(0, 0));
1558 match expr.kind {
1559 ExprKind::Literal(l) => assert_eq!(l, lit),
1560 _ => panic!("Expected literal"),
1561 }
1562 }
1563 }
1564 #[test]
1565 fn test_binary_op_display() {
1566 assert_eq!(BinaryOp::Add.to_string(), "+");
1567 assert_eq!(BinaryOp::Subtract.to_string(), "-");
1568 assert_eq!(BinaryOp::Multiply.to_string(), "*");
1569 assert_eq!(BinaryOp::Divide.to_string(), "/");
1570 assert_eq!(BinaryOp::Modulo.to_string(), "%");
1571 assert_eq!(BinaryOp::Power.to_string(), "**");
1572 assert_eq!(BinaryOp::Equal.to_string(), "==");
1573 assert_eq!(BinaryOp::NotEqual.to_string(), "!=");
1574 assert_eq!(BinaryOp::Less.to_string(), "<");
1575 assert_eq!(BinaryOp::LessEqual.to_string(), "<=");
1576 assert_eq!(BinaryOp::Greater.to_string(), ">");
1577 assert_eq!(BinaryOp::GreaterEqual.to_string(), ">=");
1578 assert_eq!(BinaryOp::And.to_string(), "&&");
1579 assert_eq!(BinaryOp::Or.to_string(), "||");
1580 assert_eq!(BinaryOp::BitwiseAnd.to_string(), "&");
1581 assert_eq!(BinaryOp::BitwiseOr.to_string(), "|");
1582 assert_eq!(BinaryOp::BitwiseXor.to_string(), "^");
1583 assert_eq!(BinaryOp::LeftShift.to_string(), "<<");
1584 }
1585 #[test]
1586 fn test_unary_op_display() {
1587 assert_eq!(UnaryOp::Not.to_string(), "!");
1588 assert_eq!(UnaryOp::Negate.to_string(), "-");
1589 assert_eq!(UnaryOp::BitwiseNot.to_string(), "~");
1590 assert_eq!(UnaryOp::Reference.to_string(), "&");
1591 }
1592 #[test]
1593 fn test_binary_expression() {
1594 let left = Box::new(Expr::new(
1595 ExprKind::Literal(Literal::Integer(1, None)),
1596 Span::new(0, 1),
1597 ));
1598 let right = Box::new(Expr::new(
1599 ExprKind::Literal(Literal::Integer(2, None)),
1600 Span::new(4, 5),
1601 ));
1602 let expr = Expr::new(
1603 ExprKind::Binary {
1604 left,
1605 op: BinaryOp::Add,
1606 right,
1607 },
1608 Span::new(0, 5),
1609 );
1610 match expr.kind {
1611 ExprKind::Binary {
1612 left: l,
1613 op,
1614 right: r,
1615 } => {
1616 assert_eq!(op, BinaryOp::Add);
1617 match l.kind {
1618 ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 1),
1619 _ => panic!("Wrong left operand"),
1620 }
1621 match r.kind {
1622 ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 2),
1623 _ => panic!("Wrong right operand"),
1624 }
1625 }
1626 _ => panic!("Expected binary expression"),
1627 }
1628 }
1629 #[test]
1630 fn test_unary_expression() {
1631 let operand = Box::new(Expr::new(
1632 ExprKind::Literal(Literal::Bool(true)),
1633 Span::new(1, 5),
1634 ));
1635 let expr = Expr::new(
1636 ExprKind::Unary {
1637 op: UnaryOp::Not,
1638 operand,
1639 },
1640 Span::new(0, 5),
1641 );
1642 match expr.kind {
1643 ExprKind::Unary { op, operand } => {
1644 assert_eq!(op, UnaryOp::Not);
1645 match operand.kind {
1646 ExprKind::Literal(Literal::Bool(b)) => assert!(b),
1647 _ => panic!("Wrong operand"),
1648 }
1649 }
1650 _ => panic!("Expected unary expression"),
1651 }
1652 }
1653 #[test]
1654 fn test_if_expression() {
1655 let condition = Box::new(Expr::new(
1656 ExprKind::Literal(Literal::Bool(true)),
1657 Span::new(3, 7),
1658 ));
1659 let then_branch = Box::new(Expr::new(
1660 ExprKind::Literal(Literal::Integer(1, None)),
1661 Span::new(10, 11),
1662 ));
1663 let else_branch = Some(Box::new(Expr::new(
1664 ExprKind::Literal(Literal::Integer(2, None)),
1665 Span::new(17, 18),
1666 )));
1667 let expr = Expr::new(
1668 ExprKind::If {
1669 condition,
1670 then_branch,
1671 else_branch,
1672 },
1673 Span::new(0, 18),
1674 );
1675 match expr.kind {
1676 ExprKind::If {
1677 condition: c,
1678 then_branch: t,
1679 else_branch: e,
1680 } => {
1681 match c.kind {
1682 ExprKind::Literal(Literal::Bool(b)) => assert!(b),
1683 _ => panic!("Wrong condition"),
1684 }
1685 match t.kind {
1686 ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 1),
1687 _ => panic!("Wrong then branch"),
1688 }
1689 assert!(e.is_some());
1690 if let Some(else_expr) = e {
1691 match else_expr.kind {
1692 ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 2),
1693 _ => panic!("Wrong else branch"),
1694 }
1695 }
1696 }
1697 _ => panic!("Expected if expression"),
1698 }
1699 }
1700 #[test]
1701 fn test_let_expression() {
1702 let value = Box::new(Expr::new(
1703 ExprKind::Literal(Literal::Integer(42, None)),
1704 Span::new(8, 10),
1705 ));
1706 let body = Box::new(Expr::new(
1707 ExprKind::Identifier("x".to_string()),
1708 Span::new(14, 15),
1709 ));
1710 let expr = Expr::new(
1711 ExprKind::Let {
1712 name: "x".to_string(),
1713 type_annotation: None,
1714 value,
1715 body,
1716 is_mutable: false,
1717 else_block: None,
1718 },
1719 Span::new(0, 15),
1720 );
1721 match expr.kind {
1722 ExprKind::Let {
1723 name,
1724 value: v,
1725 body: b,
1726 ..
1727 } => {
1728 assert_eq!(name, "x");
1729 match v.kind {
1730 ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 42),
1731 _ => panic!("Wrong value"),
1732 }
1733 match b.kind {
1734 ExprKind::Identifier(id) => assert_eq!(id, "x"),
1735 _ => panic!("Wrong body"),
1736 }
1737 }
1738 _ => panic!("Expected let expression"),
1739 }
1740 }
1741 #[test]
1742 fn test_function_expression() {
1743 let params = vec![Param {
1744 pattern: Pattern::Identifier("x".to_string()),
1745 ty: Type {
1746 kind: TypeKind::Named("i32".to_string()),
1747 span: Span::new(10, 13),
1748 },
1749 span: Span::new(8, 13),
1750 is_mutable: false,
1751 default_value: None,
1752 }];
1753 let body = Box::new(Expr::new(
1754 ExprKind::Identifier("x".to_string()),
1755 Span::new(20, 21),
1756 ));
1757 let expr = Expr::new(
1758 ExprKind::Function {
1759 name: "identity".to_string(),
1760 type_params: vec![],
1761 params,
1762 return_type: Some(Type {
1763 kind: TypeKind::Named("i32".to_string()),
1764 span: Span::new(16, 19),
1765 }),
1766 body,
1767 is_async: false,
1768 is_pub: false,
1769 },
1770 Span::new(0, 22),
1771 );
1772 match expr.kind {
1773 ExprKind::Function {
1774 name,
1775 params: p,
1776 return_type,
1777 body: b,
1778 ..
1779 } => {
1780 assert_eq!(name, "identity");
1781 assert_eq!(p.len(), 1);
1782 assert_eq!(p[0].name(), "x");
1783 assert!(return_type.is_some());
1784 match b.kind {
1785 ExprKind::Identifier(id) => assert_eq!(id, "x"),
1786 _ => panic!("Wrong body"),
1787 }
1788 }
1789 _ => panic!("Expected function expression"),
1790 }
1791 }
1792 #[test]
1793 fn test_call_expression() {
1794 let func = Box::new(Expr::new(
1795 ExprKind::Identifier("add".to_string()),
1796 Span::new(0, 3),
1797 ));
1798 let args = vec![
1799 Expr::new(
1800 ExprKind::Literal(Literal::Integer(1, None)),
1801 Span::new(4, 5),
1802 ),
1803 Expr::new(
1804 ExprKind::Literal(Literal::Integer(2, None)),
1805 Span::new(7, 8),
1806 ),
1807 ];
1808 let expr = Expr::new(ExprKind::Call { func, args }, Span::new(0, 9));
1809 match expr.kind {
1810 ExprKind::Call { func: f, args: a } => {
1811 match f.kind {
1812 ExprKind::Identifier(name) => assert_eq!(name, "add"),
1813 _ => panic!("Wrong function"),
1814 }
1815 assert_eq!(a.len(), 2);
1816 }
1817 _ => panic!("Expected call expression"),
1818 }
1819 }
1820 #[test]
1821 fn test_block_expression() {
1822 let exprs = vec![
1823 Expr::new(
1824 ExprKind::Literal(Literal::Integer(1, None)),
1825 Span::new(2, 3),
1826 ),
1827 Expr::new(
1828 ExprKind::Literal(Literal::Integer(2, None)),
1829 Span::new(5, 6),
1830 ),
1831 ];
1832 let expr = Expr::new(ExprKind::Block(exprs), Span::new(0, 8));
1833 match expr.kind {
1834 ExprKind::Block(block) => {
1835 assert_eq!(block.len(), 2);
1836 }
1837 _ => panic!("Expected block expression"),
1838 }
1839 }
1840 #[test]
1841 fn test_list_expression() {
1842 let items = vec![
1843 Expr::new(
1844 ExprKind::Literal(Literal::Integer(1, None)),
1845 Span::new(1, 2),
1846 ),
1847 Expr::new(
1848 ExprKind::Literal(Literal::Integer(2, None)),
1849 Span::new(4, 5),
1850 ),
1851 Expr::new(
1852 ExprKind::Literal(Literal::Integer(3, None)),
1853 Span::new(7, 8),
1854 ),
1855 ];
1856 let expr = Expr::new(ExprKind::List(items), Span::new(0, 9));
1857 match expr.kind {
1858 ExprKind::List(list) => {
1859 assert_eq!(list.len(), 3);
1860 }
1861 _ => panic!("Expected list expression"),
1862 }
1863 }
1864 #[test]
1865 fn test_for_expression() {
1866 let iter = Box::new(Expr::new(
1867 ExprKind::Range {
1868 start: Box::new(Expr::new(
1869 ExprKind::Literal(Literal::Integer(0, None)),
1870 Span::new(10, 11),
1871 )),
1872 end: Box::new(Expr::new(
1873 ExprKind::Literal(Literal::Integer(10, None)),
1874 Span::new(13, 15),
1875 )),
1876 inclusive: false,
1877 },
1878 Span::new(10, 15),
1879 ));
1880 let body = Box::new(Expr::new(
1881 ExprKind::Identifier("i".to_string()),
1882 Span::new(20, 21),
1883 ));
1884 let expr = Expr::new(
1885 ExprKind::For {
1886 label: None,
1887 var: "i".to_string(),
1888 pattern: None,
1889 iter,
1890 body,
1891 },
1892 Span::new(0, 22),
1893 );
1894 match expr.kind {
1895 ExprKind::For {
1896 label: None,
1897 var,
1898 iter: it,
1899 body: b,
1900 ..
1901 } => {
1902 assert_eq!(var, "i");
1903 match it.kind {
1904 ExprKind::Range { .. } => {}
1905 _ => panic!("Wrong iterator"),
1906 }
1907 match b.kind {
1908 ExprKind::Identifier(id) => assert_eq!(id, "i"),
1909 _ => panic!("Wrong body"),
1910 }
1911 }
1912 _ => panic!("Expected for expression"),
1913 }
1914 }
1915 #[test]
1916 fn test_range_expression() {
1917 let start = Box::new(Expr::new(
1918 ExprKind::Literal(Literal::Integer(1, None)),
1919 Span::new(0, 1),
1920 ));
1921 let end = Box::new(Expr::new(
1922 ExprKind::Literal(Literal::Integer(10, None)),
1923 Span::new(3, 5),
1924 ));
1925 let expr = Expr::new(
1926 ExprKind::Range {
1927 start,
1928 end,
1929 inclusive: false,
1930 },
1931 Span::new(0, 5),
1932 );
1933 match expr.kind {
1934 ExprKind::Range {
1935 start: s,
1936 end: e,
1937 inclusive,
1938 } => {
1939 assert!(!inclusive);
1940 match s.kind {
1941 ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 1),
1942 _ => panic!("Wrong start"),
1943 }
1944 match e.kind {
1945 ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 10),
1946 _ => panic!("Wrong end"),
1947 }
1948 }
1949 _ => panic!("Expected range expression"),
1950 }
1951 }
1952 #[test]
1971 fn test_pipeline_expression() {
1972 let expr_start = Box::new(Expr::new(
1973 ExprKind::List(vec![
1974 Expr::new(
1975 ExprKind::Literal(Literal::Integer(1, None)),
1976 Span::new(1, 2),
1977 ),
1978 Expr::new(
1979 ExprKind::Literal(Literal::Integer(2, None)),
1980 Span::new(4, 5),
1981 ),
1982 ]),
1983 Span::new(0, 6),
1984 ));
1985 let stages = vec![PipelineStage {
1986 op: Box::new(Expr::new(
1987 ExprKind::Identifier("filter".to_string()),
1988 Span::new(10, 16),
1989 )),
1990 span: Span::new(10, 16),
1991 }];
1992 let expr = Expr::new(
1993 ExprKind::Pipeline {
1994 expr: expr_start,
1995 stages,
1996 },
1997 Span::new(0, 16),
1998 );
1999 match expr.kind {
2000 ExprKind::Pipeline { expr: e, stages: s } => {
2001 assert_eq!(s.len(), 1);
2002 match e.kind {
2003 ExprKind::List(list) => assert_eq!(list.len(), 2),
2004 _ => panic!("Wrong pipeline start"),
2005 }
2006 }
2007 _ => panic!("Expected pipeline expression"),
2008 }
2009 }
2010 #[test]
2011 fn test_match_expression() {
2012 let expr_to_match = Box::new(Expr::new(
2013 ExprKind::Identifier("x".to_string()),
2014 Span::new(6, 7),
2015 ));
2016 let arms = vec![
2017 MatchArm {
2018 pattern: Pattern::Literal(Literal::Integer(1, None)),
2019 guard: None,
2020 body: Box::new(Expr::new(
2021 ExprKind::Literal(Literal::String("one".to_string())),
2022 Span::new(15, 20),
2023 )),
2024 span: Span::new(10, 20),
2025 },
2026 MatchArm {
2027 pattern: Pattern::Wildcard,
2028 guard: None,
2029 body: Box::new(Expr::new(
2030 ExprKind::Literal(Literal::String("other".to_string())),
2031 Span::new(28, 35),
2032 )),
2033 span: Span::new(25, 35),
2034 },
2035 ];
2036 let expr = Expr::new(
2037 ExprKind::Match {
2038 expr: expr_to_match,
2039 arms,
2040 },
2041 Span::new(0, 36),
2042 );
2043 match expr.kind {
2044 ExprKind::Match { expr: e, arms: a } => {
2045 assert_eq!(a.len(), 2);
2046 match e.kind {
2047 ExprKind::Identifier(id) => assert_eq!(id, "x"),
2048 _ => panic!("Wrong match expression"),
2049 }
2050 }
2051 _ => panic!("Expected match expression"),
2052 }
2053 }
2054 #[test]
2055 fn test_pattern_variants() {
2056 let patterns = vec![
2057 Pattern::Wildcard,
2058 Pattern::Literal(Literal::Integer(42, None)),
2059 Pattern::Identifier("x".to_string()),
2060 Pattern::Tuple(vec![
2061 Pattern::Literal(Literal::Integer(1, None)),
2062 Pattern::Identifier("x".to_string()),
2063 ]),
2064 Pattern::List(vec![
2065 Pattern::Literal(Literal::Integer(1, None)),
2066 Pattern::Literal(Literal::Integer(2, None)),
2067 ]),
2068 Pattern::Struct {
2069 name: "Point".to_string(),
2070 fields: vec![StructPatternField {
2071 name: "x".to_string(),
2072 pattern: Some(Pattern::Identifier("x".to_string())),
2073 }],
2074 has_rest: false,
2075 },
2076 Pattern::Range {
2077 start: Box::new(Pattern::Literal(Literal::Integer(1, None))),
2078 end: Box::new(Pattern::Literal(Literal::Integer(10, None))),
2079 inclusive: true,
2080 },
2081 Pattern::Or(vec![
2082 Pattern::Literal(Literal::Integer(1, None)),
2083 Pattern::Literal(Literal::Integer(2, None)),
2084 ]),
2085 Pattern::Rest,
2086 ];
2087 for pattern in patterns {
2088 match pattern {
2089 Pattern::Tuple(list) | Pattern::List(list) => assert!(!list.is_empty()),
2090 Pattern::Struct { fields, .. } => assert!(!fields.is_empty()),
2091 Pattern::Or(patterns) => assert!(!patterns.is_empty()),
2092 Pattern::Range { .. }
2093 | Pattern::Wildcard
2094 | Pattern::Literal(_)
2095 | Pattern::Identifier(_)
2096 | Pattern::Rest
2097 | Pattern::RestNamed(_)
2098 | Pattern::Ok(_)
2099 | Pattern::Err(_)
2100 | Pattern::Some(_)
2101 | Pattern::None
2102 | Pattern::QualifiedName(_)
2103 | Pattern::AtBinding { .. }
2104 | Pattern::WithDefault { .. }
2105 | Pattern::Mut(_)
2106 | Pattern::TupleVariant { .. } => {} }
2108 }
2109 }
2110 #[test]
2111 fn test_type_kinds() {
2112 let types = vec![
2113 Type {
2114 kind: TypeKind::Named("i32".to_string()),
2115 span: Span::new(0, 3),
2116 },
2117 Type {
2118 kind: TypeKind::Optional(Box::new(Type {
2119 kind: TypeKind::Named("String".to_string()),
2120 span: Span::new(0, 6),
2121 })),
2122 span: Span::new(0, 7),
2123 },
2124 Type {
2125 kind: TypeKind::List(Box::new(Type {
2126 kind: TypeKind::Named("f64".to_string()),
2127 span: Span::new(1, 4),
2128 })),
2129 span: Span::new(0, 5),
2130 },
2131 Type {
2132 kind: TypeKind::Function {
2133 params: vec![Type {
2134 kind: TypeKind::Named("i32".to_string()),
2135 span: Span::new(0, 3),
2136 }],
2137 ret: Box::new(Type {
2138 kind: TypeKind::Named("String".to_string()),
2139 span: Span::new(7, 13),
2140 }),
2141 },
2142 span: Span::new(0, 13),
2143 },
2144 ];
2145 for ty in types {
2146 match ty.kind {
2147 TypeKind::Named(name) => assert!(!name.is_empty()),
2148 TypeKind::Generic { base, params } => {
2149 assert!(!base.is_empty());
2150 assert!(!params.is_empty());
2151 }
2152 TypeKind::Optional(_) | TypeKind::List(_) | TypeKind::Series { .. } => {}
2153 TypeKind::Function { params, .. } => assert!(!params.is_empty()),
2154 TypeKind::DataFrame { columns } => assert!(!columns.is_empty()),
2155 TypeKind::Tuple(ref types) => assert!(!types.is_empty()),
2156 TypeKind::Reference {
2157 is_mut: _,
2158 lifetime: _,
2159 ref inner,
2160 } => {
2161 if let TypeKind::Named(ref name) = inner.kind {
2163 assert!(!name.is_empty());
2164 }
2165 }
2166 TypeKind::Array { elem_type: _, size } => {
2167 assert!(size > 0);
2169 }
2170 }
2171 }
2172 }
2173 #[test]
2174 fn test_param_creation() {
2175 let param = Param {
2176 pattern: Pattern::Identifier("count".to_string()),
2177 ty: Type {
2178 kind: TypeKind::Named("usize".to_string()),
2179 span: Span::new(6, 11),
2180 },
2181 span: Span::new(0, 11),
2182 is_mutable: false,
2183 default_value: None,
2184 };
2185 assert_eq!(param.name(), "count");
2186 match param.ty.kind {
2187 TypeKind::Named(name) => assert_eq!(name, "usize"),
2188 _ => panic!("Wrong type kind"),
2189 }
2190 }
2191
2192 #[test]
2193 fn test_string_interpolation_parts() {
2194 let parts = vec![
2196 StringPart::Text("Hello, ".to_string()),
2197 StringPart::Expr(Box::new(Expr::new(
2198 ExprKind::Identifier("name".to_string()),
2199 Span::new(8, 12),
2200 ))),
2201 StringPart::Text("!".to_string()),
2202 ];
2203
2204 let expr = Expr::new(ExprKind::StringInterpolation { parts }, Span::new(0, 13));
2205
2206 if let ExprKind::StringInterpolation { parts } = expr.kind {
2207 assert_eq!(parts.len(), 3);
2208 match &parts[0] {
2209 StringPart::Text(s) => assert_eq!(s, "Hello, "),
2210 _ => panic!("Expected static part"),
2211 }
2212 match &parts[1] {
2213 StringPart::Expr(e) => {
2214 if let ExprKind::Identifier(id) = &e.kind {
2215 assert_eq!(id, "name");
2216 }
2217 }
2218 _ => panic!("Expected dynamic part"),
2219 }
2220 }
2221 }
2222
2223 #[test]
2224 fn test_async_function_creation() {
2225 let func = Expr::new(
2227 ExprKind::Function {
2228 name: "fetch_data".to_string(),
2229 type_params: vec![],
2230 params: vec![],
2231 return_type: None,
2232 body: Box::new(Expr::new(
2233 ExprKind::Await {
2234 expr: Box::new(Expr::new(
2235 ExprKind::Identifier("api_call".to_string()),
2236 Span::new(0, 8),
2237 )),
2238 },
2239 Span::new(0, 14),
2240 )),
2241 is_async: true,
2242 is_pub: false,
2243 },
2244 Span::new(0, 30),
2245 );
2246
2247 if let ExprKind::Function { is_async, body, .. } = func.kind {
2248 assert!(is_async);
2249 if let ExprKind::Await { .. } = body.kind {
2250 } else {
2252 panic!("Expected await in async function");
2253 }
2254 }
2255 }
2256
2257 #[test]
2258 fn test_try_catch_finally() {
2259 let try_catch = Expr::new(
2261 ExprKind::TryCatch {
2262 try_block: Box::new(Expr::new(
2263 ExprKind::Identifier("risky_operation".to_string()),
2264 Span::new(4, 19),
2265 )),
2266 catch_clauses: vec![CatchClause {
2267 pattern: Pattern::Identifier("e".to_string()),
2268 body: Box::new(Expr::new(
2269 ExprKind::Identifier("handle_error".to_string()),
2270 Span::new(25, 37),
2271 )),
2272 }],
2273 finally_block: Some(Box::new(Expr::new(
2274 ExprKind::Identifier("cleanup".to_string()),
2275 Span::new(45, 52),
2276 ))),
2277 },
2278 Span::new(0, 52),
2279 );
2280
2281 if let ExprKind::TryCatch {
2282 catch_clauses,
2283 finally_block,
2284 ..
2285 } = try_catch.kind
2286 {
2287 assert_eq!(catch_clauses.len(), 1);
2288 assert!(finally_block.is_some());
2289 }
2290 }
2291
2292 #[test]
2293 fn test_result_option_types() {
2294 let ok_val = Expr::new(
2296 ExprKind::Ok {
2297 value: Box::new(Expr::new(
2298 ExprKind::Literal(Literal::Integer(42, None)),
2299 Span::new(3, 5),
2300 )),
2301 },
2302 Span::new(0, 6),
2303 );
2304
2305 let err_val = Expr::new(
2306 ExprKind::Err {
2307 error: Box::new(Expr::new(
2308 ExprKind::Literal(Literal::String("error".to_string())),
2309 Span::new(4, 11),
2310 )),
2311 },
2312 Span::new(0, 12),
2313 );
2314
2315 let some_val = Expr::new(
2316 ExprKind::Some {
2317 value: Box::new(Expr::new(
2318 ExprKind::Literal(Literal::Integer(1, None)),
2319 Span::new(5, 6),
2320 )),
2321 },
2322 Span::new(0, 7),
2323 );
2324
2325 let none_val = Expr::new(ExprKind::None, Span::new(0, 4));
2326
2327 assert!(matches!(ok_val.kind, ExprKind::Ok { .. }));
2328 assert!(matches!(err_val.kind, ExprKind::Err { .. }));
2329 assert!(matches!(some_val.kind, ExprKind::Some { .. }));
2330 assert!(matches!(none_val.kind, ExprKind::None));
2331 }
2332
2333 #[test]
2358 fn test_destructuring_patterns() {
2359 let tuple_pattern = Pattern::Tuple(vec![
2361 Pattern::Identifier("x".to_string()),
2362 Pattern::Identifier("y".to_string()),
2363 Pattern::Rest,
2364 ]);
2365
2366 let struct_pattern = Pattern::Struct {
2367 name: "User".to_string(),
2368 fields: vec![
2369 StructPatternField {
2370 name: "name".to_string(),
2371 pattern: Some(Pattern::Identifier("n".to_string())),
2372 },
2373 StructPatternField {
2374 name: "age".to_string(),
2375 pattern: None,
2376 },
2377 ],
2378 has_rest: true,
2379 };
2380
2381 if let Pattern::Tuple(elements) = tuple_pattern {
2382 assert_eq!(elements.len(), 3);
2383 assert!(matches!(elements[2], Pattern::Rest));
2384 }
2385
2386 if let Pattern::Struct {
2387 fields, has_rest, ..
2388 } = struct_pattern
2389 {
2390 assert_eq!(fields.len(), 2);
2391 assert!(has_rest);
2392 }
2393 }
2394
2395 #[test]
2396 fn test_qualified_names() {
2397 let qualified = Expr::new(
2399 ExprKind::QualifiedName {
2400 module: "std".to_string(),
2401 name: "println".to_string(),
2402 },
2403 Span::new(0, 11),
2404 );
2405
2406 if let ExprKind::QualifiedName { module, name } = qualified.kind {
2407 assert_eq!(module, "std");
2408 assert_eq!(name, "println");
2409 }
2410 }
2411
2412 #[test]
2426 fn test_decorator_attributes() {
2427 let decorated = Expr::with_attributes(
2429 ExprKind::Function {
2430 name: "test_func".to_string(),
2431 type_params: vec![],
2432 params: vec![],
2433 return_type: None,
2434 body: Box::new(Expr::new(ExprKind::Literal(Literal::Unit), Span::new(0, 0))),
2435 is_async: false,
2436 is_pub: false,
2437 },
2438 Span::new(0, 20),
2439 vec![
2440 Attribute {
2441 name: "test".to_string(),
2442 args: vec![],
2443 span: Span::new(0, 5),
2444 },
2445 Attribute {
2446 name: "bench".to_string(),
2447 args: vec![],
2448 span: Span::new(0, 6),
2449 },
2450 ],
2451 );
2452
2453 assert_eq!(decorated.attributes.len(), 2);
2454 assert_eq!(decorated.attributes[0].name, "test");
2455 assert_eq!(decorated.attributes[1].name, "bench");
2456 }
2457
2458 #[test]
2461 fn test_dataframe_operations() {
2462 let df = Expr::new(
2464 ExprKind::DataFrame {
2465 columns: vec![
2466 DataFrameColumn {
2467 name: "name".to_string(),
2468 values: vec![
2469 Expr::new(
2470 ExprKind::Literal(Literal::String("Alice".to_string())),
2471 Span::new(0, 7),
2472 ),
2473 Expr::new(
2474 ExprKind::Literal(Literal::String("Bob".to_string())),
2475 Span::new(8, 13),
2476 ),
2477 ],
2478 },
2479 DataFrameColumn {
2480 name: "age".to_string(),
2481 values: vec![
2482 Expr::new(
2483 ExprKind::Literal(Literal::Integer(25, None)),
2484 Span::new(14, 16),
2485 ),
2486 Expr::new(
2487 ExprKind::Literal(Literal::Integer(30, None)),
2488 Span::new(17, 19),
2489 ),
2490 ],
2491 },
2492 ],
2493 },
2494 Span::new(0, 50),
2495 );
2496
2497 if let ExprKind::DataFrame { columns } = df.kind {
2498 assert_eq!(columns.len(), 2);
2499 assert_eq!(columns[0].name, "name");
2500 assert_eq!(columns[0].values.len(), 2);
2501 assert_eq!(columns[1].name, "age");
2502 assert_eq!(columns[1].values.len(), 2);
2503 }
2504 }
2505
2506 #[test]
2507 fn test_type_cast_operations() {
2508 let cast = Expr::new(
2510 ExprKind::TypeCast {
2511 expr: Box::new(Expr::new(
2512 ExprKind::Literal(Literal::Integer(42, None)),
2513 Span::new(0, 2),
2514 )),
2515 target_type: "f64".to_string(),
2516 },
2517 Span::new(0, 10),
2518 );
2519
2520 if let ExprKind::TypeCast { target_type, .. } = cast.kind {
2521 assert_eq!(target_type, "f64");
2522 }
2523 }
2524
2525 #[test]
2526 fn test_binary_operators_complete() {
2527 let ops = vec![
2529 BinaryOp::Add,
2530 BinaryOp::Subtract,
2531 BinaryOp::Multiply,
2532 BinaryOp::Divide,
2533 BinaryOp::Modulo,
2534 BinaryOp::Power,
2535 BinaryOp::Equal,
2536 BinaryOp::NotEqual,
2537 BinaryOp::Less,
2538 BinaryOp::Greater,
2539 BinaryOp::LessEqual,
2540 BinaryOp::GreaterEqual,
2541 BinaryOp::And,
2542 BinaryOp::Or,
2543 BinaryOp::BitwiseAnd,
2545 BinaryOp::BitwiseOr,
2546 BinaryOp::BitwiseXor,
2547 BinaryOp::LeftShift,
2548 ];
2550
2551 for op in ops {
2552 let expr = Expr::new(
2553 ExprKind::Binary {
2554 left: Box::new(Expr::new(
2555 ExprKind::Literal(Literal::Integer(1, None)),
2556 Span::new(0, 1),
2557 )),
2558 op,
2559 right: Box::new(Expr::new(
2560 ExprKind::Literal(Literal::Integer(2, None)),
2561 Span::new(2, 3),
2562 )),
2563 },
2564 Span::new(0, 3),
2565 );
2566
2567 if let ExprKind::Binary { op: test_op, .. } = expr.kind {
2568 assert_eq!(test_op, op);
2569 }
2570 }
2571 }
2572
2573 #[test]
2574 fn test_span_operations() {
2575 let span1 = Span::new(0, 10);
2577 let span2 = Span::new(5, 15);
2578 let merged = span1.merge(span2);
2579
2580 assert_eq!(merged.start, 0);
2581 assert_eq!(merged.end, 15);
2582
2583 let merged2 = span2.merge(span1);
2585 assert_eq!(merged2.start, 0);
2586 assert_eq!(merged2.end, 15);
2587 }
2588
2589 #[test]
2590 fn test_pattern_with_default() {
2591 let pattern = Pattern::WithDefault {
2593 pattern: Box::new(Pattern::Identifier("count".to_string())),
2594 default: Box::new(Expr::new(
2595 ExprKind::Literal(Literal::Integer(0, None)),
2596 Span::new(0, 1),
2597 )),
2598 };
2599
2600 if let Pattern::WithDefault { pattern, default } = pattern {
2601 match *pattern {
2602 Pattern::Identifier(name) => assert_eq!(name, "count"),
2603 _ => panic!("Expected identifier pattern"),
2604 }
2605 match default.kind {
2606 ExprKind::Literal(Literal::Integer(val, None)) => assert_eq!(val, 0),
2607 _ => panic!("Expected integer literal"),
2608 }
2609 }
2610 }
2611
2612 #[test]
2615 fn test_mutable_parameter() {
2616 let param = Param {
2618 pattern: Pattern::Identifier("data".to_string()),
2619 ty: Type {
2620 kind: TypeKind::List(Box::new(Type {
2621 kind: TypeKind::Named("i32".to_string()),
2622 span: Span::new(0, 3),
2623 })),
2624 span: Span::new(0, 6),
2625 },
2626 span: Span::new(0, 10),
2627 is_mutable: true,
2628 default_value: None,
2629 };
2630
2631 assert!(param.is_mutable);
2632 assert_eq!(param.name(), "data");
2633 }
2634
2635 #[test]
2636 fn test_reference_types() {
2637 let ref_type = Type {
2639 kind: TypeKind::Reference {
2640 is_mut: false,
2641 lifetime: None,
2642 inner: Box::new(Type {
2643 kind: TypeKind::Named("String".to_string()),
2644 span: Span::new(1, 7),
2645 }),
2646 },
2647 span: Span::new(0, 7),
2648 };
2649
2650 let mut_ref_type = Type {
2651 kind: TypeKind::Reference {
2652 is_mut: true,
2653 lifetime: None,
2654 inner: Box::new(Type {
2655 kind: TypeKind::Named("Vec".to_string()),
2656 span: Span::new(4, 7),
2657 }),
2658 },
2659 span: Span::new(0, 7),
2660 };
2661
2662 if let TypeKind::Reference {
2663 is_mut,
2664 lifetime: _,
2665 inner,
2666 } = ref_type.kind
2667 {
2668 assert!(!is_mut);
2669 if let TypeKind::Named(name) = inner.kind {
2670 assert_eq!(name, "String");
2671 }
2672 }
2673
2674 if let TypeKind::Reference { is_mut, .. } = mut_ref_type.kind {
2675 assert!(is_mut);
2676 }
2677 }
2678
2679 #[test]
2681 fn test_all_expr_kinds_systematic() {
2682 let literals = vec![
2686 ExprKind::Literal(Literal::Integer(42, None)),
2687 ExprKind::Literal(Literal::Float(3.15)),
2688 ExprKind::Literal(Literal::Bool(true)),
2689 ExprKind::Literal(Literal::Bool(false)),
2690 ExprKind::Literal(Literal::String("test".to_string())),
2691 ExprKind::Literal(Literal::Char('a')),
2692 ExprKind::Literal(Literal::Unit),
2693 ];
2694
2695 for literal in literals {
2696 let expr = Expr {
2697 kind: literal,
2698 span: Span::new(0, 1),
2699 attributes: vec![],
2700 leading_comments: vec![],
2701 trailing_comment: None,
2702 };
2703 assert!(matches!(expr.kind, ExprKind::Literal(_)));
2705 }
2706
2707 let left = Box::new(Expr {
2709 kind: ExprKind::Literal(Literal::Integer(1, None)),
2710 span: Span::new(0, 1),
2711 attributes: vec![],
2712 leading_comments: vec![],
2713 trailing_comment: None,
2714 });
2715 let right = Box::new(Expr {
2716 kind: ExprKind::Literal(Literal::Integer(2, None)),
2717 span: Span::new(2, 3),
2718 attributes: vec![],
2719 leading_comments: vec![],
2720 trailing_comment: None,
2721 });
2722
2723 let binary_ops = vec![
2724 BinaryOp::Add,
2725 BinaryOp::Subtract,
2726 BinaryOp::Multiply,
2727 BinaryOp::Divide,
2728 BinaryOp::Modulo,
2729 BinaryOp::Power,
2730 BinaryOp::Equal,
2731 BinaryOp::NotEqual,
2732 BinaryOp::Less,
2733 BinaryOp::LessEqual,
2734 BinaryOp::Greater,
2735 BinaryOp::GreaterEqual,
2736 BinaryOp::Gt,
2737 BinaryOp::And,
2738 BinaryOp::Or,
2739 BinaryOp::BitwiseAnd,
2740 BinaryOp::BitwiseOr,
2741 BinaryOp::BitwiseXor,
2742 BinaryOp::LeftShift,
2743 BinaryOp::NullCoalesce,
2744 ];
2745
2746 for op in binary_ops {
2747 let binary_expr = ExprKind::Binary {
2748 op,
2749 left: left.clone(),
2750 right: right.clone(),
2751 };
2752 let expr = Expr {
2753 kind: binary_expr,
2754 span: Span::new(0, 3),
2755 attributes: vec![],
2756 leading_comments: vec![],
2757 trailing_comment: None,
2758 };
2759 assert!(matches!(expr.kind, ExprKind::Binary { .. }));
2760 }
2761
2762 let operand = Box::new(Expr {
2764 kind: ExprKind::Literal(Literal::Integer(42, None)),
2765 span: Span::new(1, 3),
2766 attributes: vec![],
2767 leading_comments: vec![],
2768 trailing_comment: None,
2769 });
2770
2771 let unary_ops = vec![
2772 UnaryOp::Not,
2773 UnaryOp::Negate,
2774 UnaryOp::BitwiseNot,
2775 UnaryOp::Reference,
2776 ];
2777
2778 for op in unary_ops {
2779 let unary_expr = ExprKind::Unary {
2780 op,
2781 operand: operand.clone(),
2782 };
2783 let expr = Expr {
2784 kind: unary_expr,
2785 span: Span::new(0, 3),
2786 attributes: vec![],
2787 leading_comments: vec![],
2788 trailing_comment: None,
2789 };
2790 assert!(matches!(expr.kind, ExprKind::Unary { .. }));
2791 }
2792 }
2793
2794 #[test]
2795 fn test_all_type_kinds_comprehensive() {
2796 let type_kinds = vec![
2799 TypeKind::Named("String".to_string()),
2800 TypeKind::Generic {
2801 base: "Vec".to_string(),
2802 params: vec![Type {
2803 kind: TypeKind::Named("i32".to_string()),
2804 span: Span::new(0, 3),
2805 }],
2806 },
2807 TypeKind::Function {
2808 params: vec![Type {
2809 kind: TypeKind::Named("i32".to_string()),
2810 span: Span::new(0, 3),
2811 }],
2812 ret: Box::new(Type {
2813 kind: TypeKind::Named("String".to_string()),
2814 span: Span::new(7, 13),
2815 }),
2816 },
2817 TypeKind::Tuple(vec![
2818 Type {
2819 kind: TypeKind::Named("i32".to_string()),
2820 span: Span::new(0, 3),
2821 },
2822 Type {
2823 kind: TypeKind::Named("String".to_string()),
2824 span: Span::new(5, 11),
2825 },
2826 ]),
2827 TypeKind::Array {
2828 elem_type: Box::new(Type {
2829 kind: TypeKind::Named("i32".to_string()),
2830 span: Span::new(0, 3),
2831 }),
2832 size: 10,
2833 },
2834 TypeKind::Reference {
2835 is_mut: false,
2836 lifetime: None,
2837 inner: Box::new(Type {
2838 kind: TypeKind::Named("String".to_string()),
2839 span: Span::new(1, 7),
2840 }),
2841 },
2842 TypeKind::Reference {
2843 is_mut: true,
2844 lifetime: None,
2845 inner: Box::new(Type {
2846 kind: TypeKind::Named("String".to_string()),
2847 span: Span::new(5, 11),
2848 }),
2849 },
2850 TypeKind::Optional(Box::new(Type {
2851 kind: TypeKind::Named("i32".to_string()),
2852 span: Span::new(0, 3),
2853 })),
2854 TypeKind::List(Box::new(Type {
2855 kind: TypeKind::Named("String".to_string()),
2856 span: Span::new(0, 6),
2857 })),
2858 TypeKind::DataFrame {
2859 columns: vec![
2860 (
2861 "id".to_string(),
2862 Type {
2863 kind: TypeKind::Named("i32".to_string()),
2864 span: Span::new(0, 3),
2865 },
2866 ),
2867 (
2868 "name".to_string(),
2869 Type {
2870 kind: TypeKind::Named("String".to_string()),
2871 span: Span::new(0, 6),
2872 },
2873 ),
2874 ],
2875 },
2876 TypeKind::Series {
2877 dtype: Box::new(Type {
2878 kind: TypeKind::Named("f64".to_string()),
2879 span: Span::new(0, 3),
2880 }),
2881 },
2882 ];
2883
2884 for type_kind in type_kinds {
2885 let ty = Type {
2886 kind: type_kind,
2887 span: Span::new(0, 10),
2888 };
2889 assert!(ty.span.start <= ty.span.end);
2891 }
2892 }
2893
2894 #[test]
2895 fn test_all_pattern_kinds_comprehensive() {
2896 let patterns = vec![
2899 Pattern::Wildcard,
2900 Pattern::Literal(Literal::Integer(42, None)),
2901 Pattern::Literal(Literal::String("test".to_string())),
2902 Pattern::Literal(Literal::Bool(true)),
2903 Pattern::Identifier("variable".to_string()),
2904 Pattern::QualifiedName(vec!["Module".to_string(), "Type".to_string()]),
2905 Pattern::Tuple(vec![
2906 Pattern::Identifier("x".to_string()),
2907 Pattern::Identifier("y".to_string()),
2908 ]),
2909 Pattern::List(vec![
2910 Pattern::Identifier("head".to_string()),
2911 Pattern::Wildcard,
2912 ]),
2913 Pattern::Struct {
2914 name: "Point".to_string(),
2915 fields: vec![
2916 StructPatternField {
2917 name: "x".to_string(),
2918 pattern: Some(Pattern::Identifier("x_val".to_string())),
2919 },
2920 StructPatternField {
2921 name: "y".to_string(),
2922 pattern: None, },
2924 ],
2925 has_rest: false,
2926 },
2927 Pattern::Struct {
2928 name: "Point".to_string(),
2929 fields: vec![],
2930 has_rest: true, },
2932 ];
2933
2934 for pattern in patterns {
2935 match pattern {
2937 Pattern::Wildcard => {}
2938 Pattern::Literal(_) => {}
2939 Pattern::Identifier(ref name) => assert!(!name.is_empty()),
2940 Pattern::QualifiedName(ref names) => assert!(!names.is_empty()),
2941 Pattern::Tuple(ref patterns) => assert!(!patterns.is_empty()),
2942 Pattern::List(ref patterns) => assert!(!patterns.is_empty()),
2943 Pattern::Struct { ref name, .. } => assert!(!name.is_empty()),
2944 _ => {} }
2946 }
2947 }
2948
2949 #[test]
2950 fn test_complex_expr_constructions() {
2951 let complex_call = ExprKind::Call {
2955 func: Box::new(Expr {
2956 kind: ExprKind::FieldAccess {
2957 object: Box::new(Expr {
2958 kind: ExprKind::Identifier("obj".to_string()),
2959 span: Span::new(0, 3),
2960 attributes: vec![],
2961 leading_comments: vec![],
2962 trailing_comment: None,
2963 }),
2964 field: "method".to_string(),
2965 },
2966 span: Span::new(0, 10),
2967 attributes: vec![],
2968 leading_comments: vec![],
2969 trailing_comment: None,
2970 }),
2971 args: vec![
2972 Expr {
2973 kind: ExprKind::Literal(Literal::Integer(42, None)),
2974 span: Span::new(11, 13),
2975 attributes: vec![],
2976 leading_comments: vec![],
2977 trailing_comment: None,
2978 },
2979 Expr {
2980 kind: ExprKind::Literal(Literal::String("arg".to_string())),
2981 span: Span::new(15, 20),
2982 attributes: vec![],
2983 leading_comments: vec![],
2984 trailing_comment: None,
2985 },
2986 ],
2987 };
2988
2989 let expr = Expr {
2990 kind: complex_call,
2991 span: Span::new(0, 21),
2992 attributes: vec![],
2993 leading_comments: vec![],
2994 trailing_comment: None,
2995 };
2996 assert!(matches!(expr.kind, ExprKind::Call { .. }));
2997
2998 let complex_if = ExprKind::If {
3000 condition: Box::new(Expr {
3001 kind: ExprKind::Binary {
3002 op: BinaryOp::Greater,
3003 left: Box::new(Expr {
3004 kind: ExprKind::Identifier("x".to_string()),
3005 span: Span::new(3, 4),
3006 attributes: vec![],
3007 leading_comments: vec![],
3008 trailing_comment: None,
3009 }),
3010 right: Box::new(Expr {
3011 kind: ExprKind::Literal(Literal::Integer(0, None)),
3012 span: Span::new(7, 8),
3013 attributes: vec![],
3014 leading_comments: vec![],
3015 trailing_comment: None,
3016 }),
3017 },
3018 span: Span::new(3, 8),
3019 attributes: vec![],
3020 leading_comments: vec![],
3021 trailing_comment: None,
3022 }),
3023 then_branch: Box::new(Expr {
3024 kind: ExprKind::Block(vec![Expr {
3025 kind: ExprKind::Literal(Literal::String("positive".to_string())),
3026 span: Span::new(11, 21),
3027 attributes: vec![],
3028 leading_comments: vec![],
3029 trailing_comment: None,
3030 }]),
3031 span: Span::new(9, 23),
3032 attributes: vec![],
3033 leading_comments: vec![],
3034 trailing_comment: None,
3035 }),
3036 else_branch: Some(Box::new(Expr {
3037 kind: ExprKind::Literal(Literal::String("negative".to_string())),
3038 span: Span::new(29, 39),
3039 attributes: vec![],
3040 leading_comments: vec![],
3041 trailing_comment: None,
3042 })),
3043 };
3044
3045 let if_expr = Expr {
3046 kind: complex_if,
3047 span: Span::new(0, 40),
3048 attributes: vec![],
3049 leading_comments: vec![],
3050 trailing_comment: None,
3051 };
3052 assert!(matches!(if_expr.kind, ExprKind::If { .. }));
3053 }
3054
3055 #[test]
3056 fn test_attribute_and_span_coverage() {
3057 let attributes = vec![
3061 Attribute {
3062 name: "inline".to_string(),
3063 args: vec![],
3064 span: Span::new(0, 8),
3065 },
3066 Attribute {
3067 name: "deprecated".to_string(),
3068 args: vec!["Use new_function instead".to_string()],
3069 span: Span::new(0, 40),
3070 },
3071 Attribute {
3072 name: "derive".to_string(),
3073 args: vec!["Debug".to_string(), "Clone".to_string()],
3074 span: Span::new(0, 20),
3075 },
3076 ];
3077
3078 for attr in attributes {
3079 assert!(!attr.name.is_empty());
3080 assert!(attr.span.start <= attr.span.end);
3081 }
3082
3083 let expr_with_attrs = Expr::with_attributes(
3085 ExprKind::Literal(Literal::Integer(42, None)),
3086 Span::new(0, 2),
3087 vec![Attribute {
3088 name: "test_attr".to_string(),
3089 args: vec![],
3090 span: Span::new(0, 10),
3091 }],
3092 );
3093
3094 assert_eq!(expr_with_attrs.attributes.len(), 1);
3095 assert_eq!(expr_with_attrs.attributes[0].name, "test_attr");
3096
3097 let span1 = Span::new(0, 10);
3099 let span2 = Span::new(5, 15);
3100
3101 assert_eq!(span1.start, 0);
3102 assert_eq!(span1.end, 10);
3103 assert!(span1.start <= span1.end);
3104 assert!(span2.start <= span2.end);
3105
3106 let default_span = Span::default();
3108 assert_eq!(default_span.start, 0);
3109 assert_eq!(default_span.end, 0);
3110 }
3111
3112 #[test]
3113 fn test_all_remaining_expr_kinds() {
3114 let list_expr = ExprKind::List(vec![
3118 Expr {
3119 kind: ExprKind::Literal(Literal::Integer(1, None)),
3120 span: Span::new(1, 2),
3121 attributes: vec![],
3122 leading_comments: vec![],
3123 trailing_comment: None,
3124 },
3125 Expr {
3126 kind: ExprKind::Literal(Literal::Integer(2, None)),
3127 span: Span::new(4, 5),
3128 attributes: vec![],
3129 leading_comments: vec![],
3130 trailing_comment: None,
3131 },
3132 ]);
3133
3134 let tuple_expr = ExprKind::Tuple(vec![
3135 Expr {
3136 kind: ExprKind::Literal(Literal::String("first".to_string())),
3137 span: Span::new(1, 8),
3138 attributes: vec![],
3139 leading_comments: vec![],
3140 trailing_comment: None,
3141 },
3142 Expr {
3143 kind: ExprKind::Literal(Literal::Integer(42, None)),
3144 span: Span::new(10, 12),
3145 attributes: vec![],
3146 leading_comments: vec![],
3147 trailing_comment: None,
3148 },
3149 ]);
3150
3151 let assign_expr = ExprKind::Assign {
3153 target: Box::new(Expr {
3154 kind: ExprKind::Identifier("x".to_string()),
3155 span: Span::new(0, 1),
3156 attributes: vec![],
3157 leading_comments: vec![],
3158 trailing_comment: None,
3159 }),
3160 value: Box::new(Expr {
3161 kind: ExprKind::Literal(Literal::Integer(42, None)),
3162 span: Span::new(4, 6),
3163 attributes: vec![],
3164 leading_comments: vec![],
3165 trailing_comment: None,
3166 }),
3167 };
3168
3169 let func_expr = ExprKind::Function {
3171 name: "add".to_string(),
3172 type_params: vec![],
3173 params: vec![
3174 Param {
3175 pattern: Pattern::Identifier("a".to_string()),
3176 ty: Type {
3177 kind: TypeKind::Named("i32".to_string()),
3178 span: Span::new(0, 3),
3179 },
3180 default_value: None,
3181 is_mutable: false,
3182 span: Span::new(0, 5),
3183 },
3184 Param {
3185 pattern: Pattern::Identifier("b".to_string()),
3186 ty: Type {
3187 kind: TypeKind::Named("i32".to_string()),
3188 span: Span::new(0, 3),
3189 },
3190 default_value: None,
3191 is_mutable: false,
3192 span: Span::new(0, 5),
3193 },
3194 ],
3195 return_type: Some(Type {
3196 kind: TypeKind::Named("i32".to_string()),
3197 span: Span::new(0, 3),
3198 }),
3199 body: Box::new(Expr {
3200 kind: ExprKind::Binary {
3201 op: BinaryOp::Add,
3202 left: Box::new(Expr {
3203 kind: ExprKind::Identifier("a".to_string()),
3204 span: Span::new(0, 1),
3205 attributes: vec![],
3206 leading_comments: vec![],
3207 trailing_comment: None,
3208 }),
3209 right: Box::new(Expr {
3210 kind: ExprKind::Identifier("b".to_string()),
3211 span: Span::new(4, 5),
3212 attributes: vec![],
3213 leading_comments: vec![],
3214 trailing_comment: None,
3215 }),
3216 },
3217 span: Span::new(0, 5),
3218 attributes: vec![],
3219 leading_comments: vec![],
3220 trailing_comment: None,
3221 }),
3222 is_async: false,
3223 is_pub: false,
3224 };
3225
3226 let expressions = vec![list_expr, tuple_expr, assign_expr, func_expr];
3228
3229 for expr_kind in expressions {
3230 let expr = Expr {
3231 kind: expr_kind,
3232 span: Span::new(0, 10),
3233 attributes: vec![],
3234 leading_comments: vec![],
3235 trailing_comment: None,
3236 };
3237 assert!(expr.span.start <= expr.span.end);
3239 }
3240 }
3241}