@@ -15,6 +15,9 @@ pub struct NodeId(pub usize);
1515#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
1616pub struct BlockId ( pub usize ) ;
1717
18+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
19+ pub struct PipelineId ( pub usize ) ;
20+
1821#[ derive( Debug , Clone ) ]
1922pub struct Block {
2023 pub nodes : Vec < NodeId > ,
@@ -26,6 +29,32 @@ impl Block {
2629 }
2730}
2831
32+ // Pipeline just contains a list of expressions
33+ //
34+ // It's not allowed if there is only one element in pipeline, in that
35+ // case, it's just an expression.
36+ //
37+ // Making such restriction can reduce indirect access on expression, which
38+ // can improve performance in parse time.
39+ #[ derive( Debug , Clone , PartialEq ) ]
40+ pub struct Pipeline {
41+ pub nodes : Vec < NodeId > ,
42+ }
43+
44+ impl Pipeline {
45+ pub fn new ( nodes : Vec < NodeId > ) -> Self {
46+ debug_assert ! (
47+ nodes. len( ) > 1 ,
48+ "a pipeline must contain at least 2 nodes, or else it's actually an expression"
49+ ) ;
50+ Self { nodes }
51+ }
52+
53+ pub fn get_expressions ( & self ) -> & Vec < NodeId > {
54+ & self . nodes
55+ }
56+ }
57+
2958#[ derive( Debug , Clone , PartialEq ) ]
3059pub enum BlockContext {
3160 /// This block is a whole block of code not wrapped in curlies (e.g., a file)
@@ -54,6 +83,19 @@ pub enum BarewordContext {
5483 Call ,
5584}
5685
86+ enum AssignmentOrExpression {
87+ Assignment ( NodeId ) ,
88+ Expression ( NodeId ) ,
89+ }
90+
91+ impl AssignmentOrExpression {
92+ fn get_node_id ( & self ) -> NodeId {
93+ match self {
94+ AssignmentOrExpression :: Assignment ( i) | AssignmentOrExpression :: Expression ( i) => * i,
95+ }
96+ }
97+ }
98+
5799// TODO: All nodes with Vec<...> should be moved to their own ID (like BlockId) to allow Copy trait
58100#[ derive( Debug , PartialEq , Clone ) ]
59101pub enum AstNode {
@@ -196,6 +238,7 @@ pub enum AstNode {
196238 field : NodeId ,
197239 } ,
198240 Block ( BlockId ) ,
241+ Pipeline ( PipelineId ) ,
199242 If {
200243 condition : NodeId ,
201244 then_block : NodeId ,
@@ -261,17 +304,57 @@ impl Parser {
261304 self . compiler
262305 }
263306
264- pub fn expression_or_assignment ( & mut self ) -> NodeId {
307+ pub fn expression ( & mut self ) -> NodeId {
265308 let _span = span ! ( ) ;
266- self . math_expression ( true )
309+ self . math_expression ( false ) . get_node_id ( )
267310 }
268311
269- pub fn expression ( & mut self ) -> NodeId {
312+ fn pipeline ( & mut self , first_element : NodeId , span_start : usize ) -> NodeId {
313+ let mut expressions = vec ! [ first_element] ;
314+ while self . is_pipe ( ) {
315+ self . pipe ( ) ;
316+ // maybe a new time
317+ if self . is_newline ( ) {
318+ self . tokens . advance ( )
319+ }
320+ expressions. push ( self . expression ( ) ) ;
321+ }
322+ self . compiler . pipelines . push ( Pipeline :: new ( expressions) ) ;
323+ let span_end = self . position ( ) ;
324+ self . create_node (
325+ AstNode :: Pipeline ( PipelineId ( self . compiler . pipelines . len ( ) - 1 ) ) ,
326+ span_start,
327+ span_end,
328+ )
329+ }
330+ pub fn pipeline_or_expression_or_assignment ( & mut self ) -> NodeId {
331+ // get the first expression
270332 let _span = span ! ( ) ;
271- self . math_expression ( false )
333+ let span_start = self . position ( ) ;
334+ let first = self . math_expression ( true ) ;
335+ let first_id = first. get_node_id ( ) ;
336+ if let AssignmentOrExpression :: Assignment ( _) = & first {
337+ return first_id;
338+ }
339+ // pipeline with one element is an expression actually
340+ if !self . is_pipe ( ) {
341+ return first_id;
342+ }
343+ self . pipeline ( first_id, span_start)
272344 }
273345
274- pub fn math_expression ( & mut self , allow_assignment : bool ) -> NodeId {
346+ pub fn pipeline_or_expression ( & mut self ) -> NodeId {
347+ let _span = span ! ( ) ;
348+ let span_start = self . position ( ) ;
349+ let first_id = self . expression ( ) ;
350+ // pipeline with one element is an expression actually.
351+ if !self . is_pipe ( ) {
352+ return first_id;
353+ }
354+ self . pipeline ( first_id, span_start)
355+ }
356+
357+ fn math_expression ( & mut self , allow_assignment : bool ) -> AssignmentOrExpression {
275358 let _span = span ! ( ) ;
276359 let mut expr_stack = Vec :: < ( NodeId , NodeId ) > :: new ( ) ;
277360
@@ -281,9 +364,9 @@ impl Parser {
281364
282365 // Check for special forms
283366 if self . is_keyword ( b"if" ) {
284- return self . if_expression ( ) ;
367+ return AssignmentOrExpression :: Expression ( self . if_expression ( ) ) ;
285368 } else if self . is_keyword ( b"match" ) {
286- return self . match_expression ( ) ;
369+ return AssignmentOrExpression :: Expression ( self . match_expression ( ) ) ;
287370 }
288371 // TODO
289372 // } else if self.is_keyword(b"where") {
@@ -298,18 +381,18 @@ impl Parser {
298381 }
299382 let op = self . operator ( ) ;
300383
301- let rhs = self . expression ( ) ;
384+ let rhs = self . pipeline_or_expression ( ) ;
302385 let span_end = self . get_span_end ( rhs) ;
303386
304- return self . create_node (
387+ return AssignmentOrExpression :: Assignment ( self . create_node (
305388 AstNode :: BinaryOp {
306389 lhs : leftmost,
307390 op,
308391 rhs,
309392 } ,
310393 span_start,
311394 span_end,
312- ) ;
395+ ) ) ;
313396 }
314397
315398 while self . has_tokens ( ) {
@@ -380,7 +463,7 @@ impl Parser {
380463 ) ;
381464 }
382465
383- leftmost
466+ AssignmentOrExpression :: Expression ( leftmost)
384467 }
385468
386469 pub fn simple_expression ( & mut self , bareword_context : BarewordContext ) -> NodeId {
@@ -1153,7 +1236,7 @@ impl Parser {
11531236
11541237 self . equals ( ) ;
11551238
1156- let initializer = self . expression ( ) ;
1239+ let initializer = self . pipeline_or_expression ( ) ;
11571240
11581241 let span_end = self . get_span_end ( initializer) ;
11591242
@@ -1190,7 +1273,7 @@ impl Parser {
11901273
11911274 self . equals ( ) ;
11921275
1193- let initializer = self . expression ( ) ;
1276+ let initializer = self . pipeline_or_expression ( ) ;
11941277
11951278 let span_end = self . get_span_end ( initializer) ;
11961279
@@ -1259,19 +1342,19 @@ impl Parser {
12591342 code_body. push ( self . alias_statement ( ) ) ;
12601343 } else {
12611344 let exp_span_start = self . position ( ) ;
1262- let expression = self . expression_or_assignment ( ) ;
1263- let exp_span_end = self . get_span_end ( expression ) ;
1345+ let pipeline = self . pipeline_or_expression_or_assignment ( ) ;
1346+ let exp_span_end = self . get_span_end ( pipeline ) ;
12641347
12651348 if self . is_semicolon ( ) {
12661349 // This is a statement, not an expression
12671350 self . tokens . advance ( ) ;
12681351 code_body. push ( self . create_node (
1269- AstNode :: Statement ( expression ) ,
1352+ AstNode :: Statement ( pipeline ) ,
12701353 exp_span_start,
12711354 exp_span_end,
12721355 ) )
12731356 } else {
1274- code_body. push ( expression ) ;
1357+ code_body. push ( pipeline ) ;
12751358 }
12761359 }
12771360 }
0 commit comments