Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ pub enum AstNode {
env: bool,
wrapped: bool,
},
Extern {
name: NodeId,
params: NodeId,
},
Params(Vec<NodeId>),
Param {
name: NodeId,
Expand Down Expand Up @@ -246,6 +250,11 @@ pub enum AstNode {
then_block: NodeId,
else_block: Option<NodeId>,
},
Try {
try_block: NodeId,
catch_block: Option<NodeId>,
finally_block: Option<NodeId>,
},
Match {
target: NodeId,
match_arms: Vec<(NodeId, NodeId)>,
Expand Down Expand Up @@ -369,6 +378,8 @@ impl Parser {
return AssignmentOrExpression::Expression(self.if_expression());
} else if self.is_keyword(b"match") {
return AssignmentOrExpression::Expression(self.match_expression());
} else if self.is_keyword(b"try") {
return AssignmentOrExpression::Expression(self.try_expression());
}
// TODO
// } else if self.is_keyword(b"where") {
Expand Down Expand Up @@ -943,6 +954,52 @@ impl Parser {
)
}

pub fn try_expression(&mut self) -> NodeId {
let _span = span!();
let span_start = self.position();

self.keyword(b"try");

let try_block = self.block(BlockContext::Curlies);
let mut span_end = self.get_span_end(try_block);
self.skip_newlines();

// catch
let catch_block = if self.is_keyword(b"catch") {
self.tokens.advance();
self.skip_newlines();

let block = self.block(BlockContext::Curlies);
span_end = self.get_span_end(block);

Some(block)
} else {
None
};

// finally
let finally_block = if self.is_keyword(b"finally") {
self.tokens.advance();
self.skip_newlines();

let block = self.block(BlockContext::Curlies);
span_end = self.get_span_end(block);
Some(block)
} else {
None
};

self.create_node(
AstNode::Try {
try_block,
catch_block,
finally_block,
},
span_start,
span_end,
)
}

// directly ripped from `type_params` just changed delimiters
// FIXME: simplify if appropriate
pub fn signature_params(&mut self, params_context: ParamsContext) -> NodeId {
Expand Down Expand Up @@ -1247,6 +1304,26 @@ impl Parser {
)
}

pub fn extern_statement(&mut self) -> NodeId {
let _span = span!();
let span_start = self.position();

self.keyword(b"extern");

let name = match self.tokens.peek() {
(Token::Bareword, span) => self.advance_node(AstNode::Name, span),
(Token::DoubleQuotedString | Token::SingleQuotedString, span) => {
self.advance_node(AstNode::String, span)
}
_ => return self.error("expected def name"),
};

let params = self.signature_params(ParamsContext::Squares);
let span_end = self.position();

self.create_node(AstNode::Extern { name, params }, span_start, span_end)
}

// TODO: Deduplicate code between let/mut/const assignments
pub fn let_statement(&mut self) -> NodeId {
let _span = span!();
Expand Down Expand Up @@ -1372,6 +1449,8 @@ impl Parser {
code_body.push(self.break_statement());
} else if self.is_keyword(b"alias") {
code_body.push(self.alias_statement());
} else if self.is_keyword(b"extern") {
code_body.push(self.extern_statement());
} else {
let exp_span_start = self.position();
let pipeline = self.pipeline_or_expression_or_assignment();
Expand Down
32 changes: 32 additions & 0 deletions src/snapshots/new_nu_parser__test__node_output@extern.nu.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
source: src/test.rs
expression: evaluate_example(path)
input_file: tests/extern.nu
---
==== COMPILER ====
0: Name (7 to 11) "echo"
1: Name (13 to 17) "text"
2: Name (19 to 25) "string"
3: Type { name: NodeId(2), args: None, optional: false } (19 to 25)
4: Param { name: NodeId(1), ty: Some(NodeId(3)) } (13 to 25)
5: Params([NodeId(4)]) (12 to 26)
6: Extern { name: NodeId(0), params: NodeId(5) } (0 to 26)
7: Block(BlockId(0)) (0 to 27)
==== SCOPE ====
0: Frame Scope, node_id: NodeId(7) (empty)
==== TYPES ====
0: unknown
1: unknown
2: unknown
3: unknown
4: unknown
5: unknown
6: unknown
7: unknown
==== TYPE ERRORS ====
Error (NodeId 6): Expected statement to typecheck, got 'Extern { name: NodeId(0), params: NodeId(5) }'
==== IR ====
register_count: 0
file_count: 0
==== IR ERRORS ====
Error (NodeId 6): node Extern { name: NodeId(0), params: NodeId(5) } not suported yet
97 changes: 97 additions & 0 deletions src/snapshots/new_nu_parser__test__node_output@try.nu.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
source: src/test.rs
expression: evaluate_example(path)
input_file: tests/try.nu
---
==== COMPILER ====
0: Int (10 to 11) "1"
1: Divide (12 to 13)
2: Int (14 to 15) "0"
3: BinaryOp { lhs: NodeId(0), op: NodeId(1), rhs: NodeId(2) } (10 to 15)
4: Block(BlockId(0)) (4 to 17)
5: Try { try_block: NodeId(4), catch_block: None, finally_block: None } (0 to 17)
6: Int (29 to 30) "1"
7: Divide (31 to 32)
8: Int (33 to 34) "0"
9: BinaryOp { lhs: NodeId(6), op: NodeId(7), rhs: NodeId(8) } (29 to 34)
10: Block(BlockId(1)) (23 to 37)
11: Name (49 to 54) "print"
12: String (55 to 59) ""aa""
13: Call { parts: [NodeId(11), NodeId(12)] } (55 to 59)
14: Block(BlockId(2)) (43 to 61)
15: Try { try_block: NodeId(10), catch_block: Some(NodeId(14)), finally_block: None } (19 to 61)
16: Int (73 to 74) "1"
17: Divide (75 to 76)
18: Int (77 to 78) "0"
19: BinaryOp { lhs: NodeId(16), op: NodeId(17), rhs: NodeId(18) } (73 to 78)
20: Block(BlockId(3)) (67 to 81)
21: Name (95 to 100) "print"
22: String (101 to 105) ""bb""
23: Call { parts: [NodeId(21), NodeId(22)] } (101 to 105)
24: Block(BlockId(4)) (89 to 107)
25: Try { try_block: NodeId(20), catch_block: None, finally_block: Some(NodeId(24)) } (63 to 107)
26: Int (119 to 120) "1"
27: Divide (121 to 122)
28: Int (123 to 124) "0"
29: BinaryOp { lhs: NodeId(26), op: NodeId(27), rhs: NodeId(28) } (119 to 124)
30: Block(BlockId(5)) (113 to 127)
31: Int (139 to 141) "22"
32: Block(BlockId(6)) (133 to 144)
33: Name (158 to 163) "print"
34: String (164 to 168) ""bb""
35: Call { parts: [NodeId(33), NodeId(34)] } (164 to 168)
36: Block(BlockId(7)) (152 to 170)
37: Try { try_block: NodeId(30), catch_block: Some(NodeId(32)), finally_block: Some(NodeId(36)) } (109 to 170)
38: Block(BlockId(8)) (0 to 172)
==== SCOPE ====
0: Frame Scope, node_id: NodeId(38) (empty)
==== TYPES ====
0: unknown
1: unknown
2: unknown
3: unknown
4: unknown
5: unknown
6: unknown
7: unknown
8: unknown
9: unknown
10: unknown
11: unknown
12: unknown
13: unknown
14: unknown
15: unknown
16: unknown
17: unknown
18: unknown
19: unknown
20: unknown
21: unknown
22: unknown
23: unknown
24: unknown
25: unknown
26: unknown
27: unknown
28: unknown
29: unknown
30: unknown
31: unknown
32: unknown
33: unknown
34: unknown
35: unknown
36: unknown
37: unknown
38: unknown
==== TYPE ERRORS ====
Error (NodeId 5): Expected statement to typecheck, got 'Try { try_block: NodeId(4), catch_block: None, finally_block: None }'
Error (NodeId 15): Expected statement to typecheck, got 'Try { try_block: NodeId(10), catch_block: Some(NodeId(14)), finally_block: None }'
Error (NodeId 25): Expected statement to typecheck, got 'Try { try_block: NodeId(20), catch_block: None, finally_block: Some(NodeId(24)) }'
Error (NodeId 37): Expected statement to typecheck, got 'Try { try_block: NodeId(30), catch_block: Some(NodeId(32)), finally_block: Some(NodeId(36)) }'
==== IR ====
register_count: 0
file_count: 0
==== IR ERRORS ====
Error (NodeId 5): node Try { try_block: NodeId(4), catch_block: None, finally_block: None } not suported yet
1 change: 1 addition & 0 deletions tests/extern.nu
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
extern echo [text: string]
24 changes: 24 additions & 0 deletions tests/try.nu
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
try {
1 / 0
}

try {
1 / 0
} catch {
print "aa"
}

try {
1 / 0
} finally {
print "bb"
}

try {
1 / 0
} catch {
22
} finally {
print "bb"
}