From 0817184cf9dd93381d2cdb2983c1905b56b75038 Mon Sep 17 00:00:00 2001 From: Glyphack Date: Wed, 27 Sep 2023 21:07:50 +0200 Subject: [PATCH] Parse coroutines Fix: #122 --- parser/src/parser/ast.rs | 36 + parser/src/parser/parser.rs | 171 ++--- ...rser__parser__parser__tests__complete.snap | 674 ------------------ ...__parser__tests__one_liners@for.py-2.snap} | 1 + ...__parser__tests__one_liners@for.py-3.snap} | 1 + ...__parser__tests__one_liners@for.py-4.snap} | 7 +- ...r__parser__tests__one_liners@for.py-5.snap | 50 ++ ...r__parser__tests__one_liners@for.py-6.snap | 50 ++ ...er__parser__tests__one_liners@for.py.snap} | 1 + ..._tests__one_liners@function_def.py-10.snap | 48 ++ ..._tests__one_liners@function_def.py-11.snap | 73 ++ ...__tests__one_liners@function_def.py-2.snap | 48 ++ ...__tests__one_liners@function_def.py-3.snap | 73 ++ ...__tests__one_liners@function_def.py-4.snap | 75 ++ ...__tests__one_liners@function_def.py-5.snap | 73 ++ ...__tests__one_liners@function_def.py-6.snap | 58 ++ ...__tests__one_liners@function_def.py-7.snap | 168 +++++ ...__tests__one_liners@function_def.py-8.snap | 58 ++ ...__tests__one_liners@function_def.py-9.snap | 48 ++ ...er__tests__one_liners@function_def.py.snap | 48 ++ ..._parser__tests__one_liners@with.py-2.snap} | 1 + ..._parser__tests__one_liners@with.py-3.snap} | 1 + ..._parser__tests__one_liners@with.py-4.snap} | 1 + ...__parser__tests__one_liners@with.py-5.snap | 59 ++ ...__parser__tests__one_liners@with.py-6.snap | 85 +++ ...__parser__tests__one_liners@with.py-7.snap | 107 +++ ...r__parser__tests__one_liners@with.py.snap} | 1 + parser/src/parser/statement.rs | 1 + parser/test_data/inputs/one_liners/for.py | 17 + .../inputs/one_liners/function_def.py | 27 + parser/test_data/inputs/one_liners/with.py | 17 + typechecker/src/ast_visitor.rs | 98 +-- typechecker/src/ast_visitor_generic.rs | 15 + typechecker/src/ast_visitor_immut.rs | 28 + typechecker/src/nodes.rs | 3 + typechecker/src/semantic_analyzer.rs | 27 + typechecker/src/type_check/checker.rs | 3 + typechecker/src/type_check/type_evaluator.rs | 4 + 38 files changed, 1409 insertions(+), 847 deletions(-) delete mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__complete.snap rename parser/src/parser/snapshots/{enderpy_python_parser__parser__parser__tests__for_statement-2.snap => enderpy_python_parser__parser__parser__tests__one_liners@for.py-2.snap} (95%) rename parser/src/parser/snapshots/{enderpy_python_parser__parser__parser__tests__for_statement-3.snap => enderpy_python_parser__parser__parser__tests__one_liners@for.py-3.snap} (98%) rename parser/src/parser/snapshots/{enderpy_python_parser__parser__parser__tests__for_statement-4.snap => enderpy_python_parser__parser__parser__tests__one_liners@for.py-4.snap} (97%) create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-5.snap create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-6.snap rename parser/src/parser/snapshots/{enderpy_python_parser__parser__parser__tests__for_statement.snap => enderpy_python_parser__parser__parser__tests__one_liners@for.py.snap} (95%) create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-10.snap create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-11.snap create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-2.snap create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-3.snap create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-4.snap create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-5.snap create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-6.snap create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-7.snap create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-8.snap create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-9.snap create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py.snap rename parser/src/parser/snapshots/{enderpy_python_parser__parser__parser__tests__with_statement-2.snap => enderpy_python_parser__parser__parser__tests__one_liners@with.py-2.snap} (96%) rename parser/src/parser/snapshots/{enderpy_python_parser__parser__parser__tests__with_statement-3.snap => enderpy_python_parser__parser__parser__tests__one_liners@with.py-3.snap} (97%) rename parser/src/parser/snapshots/{enderpy_python_parser__parser__parser__tests__with_statement-4.snap => enderpy_python_parser__parser__parser__tests__one_liners@with.py-4.snap} (97%) create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-5.snap create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-6.snap create mode 100644 parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-7.snap rename parser/src/parser/snapshots/{enderpy_python_parser__parser__parser__tests__with_statement.snap => enderpy_python_parser__parser__parser__tests__one_liners@with.py.snap} (95%) create mode 100644 parser/test_data/inputs/one_liners/for.py create mode 100644 parser/test_data/inputs/one_liners/function_def.py create mode 100644 parser/test_data/inputs/one_liners/with.py diff --git a/parser/src/parser/ast.rs b/parser/src/parser/ast.rs index 3a569111..92c3d624 100644 --- a/parser/src/parser/ast.rs +++ b/parser/src/parser/ast.rs @@ -58,10 +58,13 @@ pub enum Statement { IfStatement(If), WhileStatement(While), ForStatement(For), + AsyncForStatement(AsyncFor), WithStatement(With), + AsyncWithStatement(AsyncWith), TryStatement(Try), TryStarStatement(TryStar), FunctionDef(FunctionDef), + AsyncFunctionDef(AsyncFunctionDef), ClassDef(ClassDef), Match(Match), } @@ -87,10 +90,13 @@ impl GetNode for Statement { Statement::IfStatement(s) => s.node, Statement::WhileStatement(s) => s.node, Statement::ForStatement(s) => s.node, + Statement::AsyncForStatement(s) => s.node, Statement::WithStatement(s) => s.node, + Statement::AsyncWithStatement(s) => s.node, Statement::TryStatement(s) => s.node, Statement::TryStarStatement(s) => s.node, Statement::FunctionDef(s) => s.node, + Statement::AsyncFunctionDef(s) => s.node, Statement::ClassDef(s) => s.node, Statement::Match(s) => s.node, } @@ -646,6 +652,16 @@ pub struct For { pub orelse: Vec, } +// https://docs.python.org/3/library/ast.html#ast.AsyncFor +#[derive(Debug, Clone)] +pub struct AsyncFor { + pub node: Node, + pub target: Box, + pub iter: Box, + pub body: Vec, + pub orelse: Vec, +} + // https://docs.python.org/3/library/ast.html#ast.With #[derive(Debug, Clone)] pub struct With { @@ -654,6 +670,14 @@ pub struct With { pub body: Vec, } +// https://docs.python.org/3/library/ast.html#ast.AsyncWith +#[derive(Debug, Clone)] +pub struct AsyncWith { + pub node: Node, + pub items: Vec, + pub body: Vec, +} + // https://docs.python.org/3/library/ast.html#ast.withitem // can be used for With #[derive(Debug, Clone)] @@ -704,6 +728,18 @@ pub struct FunctionDef { pub type_comment: Option, } +// https://docs.python.org/3/library/ast.html#ast.AsyncFunctionDef +#[derive(Debug, Clone)] +pub struct AsyncFunctionDef { + pub node: Node, + pub name: String, + pub args: Arguments, + pub body: Vec, + pub decorator_list: Vec, + pub returns: Option>, + pub type_comment: Option, +} + // https://docs.python.org/3/library/ast.html#ast.ClassDef #[derive(Debug, Clone)] pub struct ClassDef { diff --git a/parser/src/parser/parser.rs b/parser/src/parser/parser.rs index c705eade..fd65c008 100644 --- a/parser/src/parser/parser.rs +++ b/parser/src/parser/parser.rs @@ -4,7 +4,7 @@ use crate::lexer::lexer::Lexer; use crate::parser::ast::*; use crate::parser::string::{extract_string_inside, is_string}; use crate::token::{Kind, Token, TokenValue}; -use miette::{bail, Result}; +use miette::Result; use super::diagnostics; use super::expression::{is_atom, is_iterable}; @@ -240,6 +240,20 @@ impl Parser { Kind::Identifier if self.cur_token().value.to_string() == "match" => { self.parse_match_statement() } + Kind::Async => { + if matches!(self.peek_kind(), Ok(Kind::Def)) { + self.parse_function_definition(vec![]) + } else if matches!(self.peek_kind(), Ok(Kind::For)) { + self.parse_for_statement() + } else if matches!(self.peek_kind(), Ok(Kind::With)) { + self.parse_with_statement() + } else { + let node = self.start_node(); + let kind = self.cur_kind(); + self.bump_any(); + Err(self.unepxted_token(node, kind).err().unwrap()) + } + } _ => { let range = self.finish_node(self.start_node()); Err( @@ -348,6 +362,7 @@ impl Parser { fn parse_for_statement(&mut self) -> Result { let node = self.start_node(); + let is_async = self.eat(Kind::Async); self.bump(Kind::For); let target = Box::new(self.parse_target_list()?); self.expect(Kind::In)?; @@ -378,17 +393,28 @@ impl Parser { self.bump(Kind::Dedent); - Ok(Statement::ForStatement(For { - node: self.finish_node(node), - target, - iter, - body, - orelse, - })) + if is_async { + Ok(Statement::AsyncForStatement(AsyncFor { + node: self.finish_node(node), + target, + iter, + body, + orelse, + })) + } else { + Ok(Statement::ForStatement(For { + node: self.finish_node(node), + target, + iter, + body, + orelse, + })) + } } fn parse_with_statement(&mut self) -> Result { let node = self.start_node(); + let is_async = self.eat(Kind::Async); self.bump(Kind::With); let items = self.parse_with_items()?; self.expect(Kind::Colon)?; @@ -396,11 +422,19 @@ impl Parser { self.bump(Kind::Dedent); - Ok(Statement::WithStatement(With { - node: self.finish_node(node), - items, - body, - })) + if is_async { + Ok(Statement::AsyncWithStatement(AsyncWith { + node: self.finish_node(node), + items, + body, + })) + } else { + Ok(Statement::WithStatement(With { + node: self.finish_node(node), + items, + body, + })) + } } fn parse_with_items(&mut self) -> Result> { @@ -523,6 +557,7 @@ impl Parser { // later we can extract the node for first decorator // and start the node from there let node = self.start_node(); + let is_async = self.eat(Kind::Async); self.expect(Kind::Def)?; let name = self.cur_token().value.to_string(); self.expect(Kind::Identifier)?; @@ -538,18 +573,29 @@ impl Parser { self.expect(Kind::Colon)?; let body = self.parse_suite()?; - - Ok(Statement::FunctionDef(FunctionDef { - node: self.finish_node(node), - name, - args, - body, - decorator_list: decorators, - // TODO: return type - returns: return_type, - // TODO: type comment - type_comment: None, - })) + if is_async { + Ok(Statement::AsyncFunctionDef(AsyncFunctionDef { + node: self.finish_node(node), + name, + args, + body, + decorator_list: decorators, + returns: return_type, + type_comment: None, + })) + } else { + Ok(Statement::FunctionDef(FunctionDef { + node: self.finish_node(node), + name, + args, + body, + decorator_list: decorators, + // TODO: return type + returns: return_type, + // TODO: type comment + type_comment: None, + })) + } } fn parse_decorated_function_def_or_class_def(&mut self) -> Result { @@ -3354,52 +3400,6 @@ else: } } - #[test] - fn test_for_statement() { - for test_case in &[ - "for a in b: pass", - "for a in b: - pass", - "for a in range(10): - a = 1 -else: - b = 1", - "for a in range(10), range(10): - a = 1 -", - ] { - let mut parser = Parser::new(test_case.to_string()); - let program = parser.parse(); - - insta::with_settings!({ - description => test_case.to_string(), // the template source code - omit_expression => true // do not include the default expression - }, { - assert_debug_snapshot!(program); - }); - } - } - - #[test] - fn test_with_statement() { - for test_case in &[ - "with a: pass", - "with a as b: pass", - "with a as b, c as d: pass", - "with (a as b, c as d): pass", - ] { - let mut parser = Parser::new(test_case.to_string()); - let program = parser.parse(); - - insta::with_settings!({ - description => test_case.to_string(), // the template source code - omit_expression => true // do not include the default expression - }, { - assert_debug_snapshot!(program); - }); - } - } - #[test] fn test_try_statement() { for test_case in &[ @@ -3447,35 +3447,6 @@ except *Exception as e: } } - #[test] - fn test_func_def_statement() { - for test_case in &[ - "def a(): pass", - "def a(): - pass", - "def a(a, b, c): pass", - "def a(a, *b, **c): pass", - "def a(a, - b, - c): pass", - "@decor -def a(): pass", - "@decor -def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g): pass", - "def func() -> None: pass", - ] { - let mut parser = Parser::new(test_case.to_string()); - let program = parser.parse(); - - insta::with_settings!({ - description => test_case.to_string(), // the template source code - omit_expression => true // do not include the default expression - }, { - assert_debug_snapshot!(program); - }); - } - } - #[test] fn test_ellipsis_statement() { for test_case in &[ diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__complete.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__complete.snap deleted file mode 100644 index 90715736..00000000 --- a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__complete.snap +++ /dev/null @@ -1,674 +0,0 @@ ---- -source: parser/src/parser/parser.rs -description: "def _handle_ticker_index(symbol):\n ticker_index = symbols_data.get_ticker_index(symbol)\n\n if ticker_index is None:\n market_symbol = get_symbol_info(symbol)\n if market_symbol is not None:\n symbols_data.append_symbol_to_file(market_symbol)\n ticker_index = market_symbol.index\n return ticker_index\n\n\ndef _extract_ticker_client_types_data(ticker_index: str) -> List:\n url = TSE_CLIENT_TYPE_DATA_URL.format(ticker_index)\n with requests_retry_session() as session:\n response = session.get(url, timeout=5)\n data = response.text.split(';')\n return data\n" -input_file: parser/test_data/inputs/functions.py ---- -Module { - node: Node { - start: 0, - end: 609, - }, - body: [ - FunctionDef( - FunctionDef { - node: Node { - start: 0, - end: 609, - }, - name: "_handle_ticker_index", - args: Arguments { - node: Node { - start: 25, - end: 31, - }, - posonlyargs: [], - args: [ - Arg { - node: Node { - start: 25, - end: 31, - }, - arg: "symbol", - annotation: None, - }, - ], - vararg: None, - kwonlyargs: [], - kw_defaults: [], - kwarg: None, - defaults: [], - }, - body: [ - AssignStatement( - Assign { - node: Node { - start: 38, - end: 90, - }, - targets: [ - Name( - Name { - node: Node { - start: 38, - end: 50, - }, - id: "ticker_index", - }, - ), - ], - value: Call( - Call { - node: Node { - start: 53, - end: 90, - }, - func: Attribute( - Attribute { - node: Node { - start: 53, - end: 82, - }, - value: Name( - Name { - node: Node { - start: 53, - end: 65, - }, - id: "symbols_data", - }, - ), - attr: "get_ticker_index", - }, - ), - args: [ - Name( - Name { - node: Node { - start: 83, - end: 89, - }, - id: "symbol", - }, - ), - ], - keywords: [], - starargs: None, - kwargs: None, - }, - ), - }, - ), - IfStatement( - If { - node: Node { - start: 99, - end: 342, - }, - test: Compare( - Compare { - node: Node { - start: 99, - end: 119, - }, - left: Name( - Name { - node: Node { - start: 99, - end: 111, - }, - id: "ticker_index", - }, - ), - ops: [ - Is, - ], - comparators: [ - Constant( - Constant { - node: Node { - start: 115, - end: 119, - }, - value: None, - }, - ), - ], - }, - ), - body: [ - AssignStatement( - Assign { - node: Node { - start: 129, - end: 168, - }, - targets: [ - Name( - Name { - node: Node { - start: 129, - end: 142, - }, - id: "market_symbol", - }, - ), - ], - value: Call( - Call { - node: Node { - start: 145, - end: 168, - }, - func: Name( - Name { - node: Node { - start: 145, - end: 160, - }, - id: "get_symbol_info", - }, - ), - args: [ - Name( - Name { - node: Node { - start: 161, - end: 167, - }, - id: "symbol", - }, - ), - ], - keywords: [], - starargs: None, - kwargs: None, - }, - ), - }, - ), - IfStatement( - If { - node: Node { - start: 180, - end: 320, - }, - test: Compare( - Compare { - node: Node { - start: 180, - end: 205, - }, - left: Name( - Name { - node: Node { - start: 180, - end: 193, - }, - id: "market_symbol", - }, - ), - ops: [ - IsNot, - ], - comparators: [ - Constant( - Constant { - node: Node { - start: 201, - end: 205, - }, - value: None, - }, - ), - ], - }, - ), - body: [ - ExpressionStatement( - Call( - Call { - node: Node { - start: 219, - end: 268, - }, - func: Attribute( - Attribute { - node: Node { - start: 219, - end: 253, - }, - value: Name( - Name { - node: Node { - start: 219, - end: 231, - }, - id: "symbols_data", - }, - ), - attr: "append_symbol_to_file", - }, - ), - args: [ - Name( - Name { - node: Node { - start: 254, - end: 267, - }, - id: "market_symbol", - }, - ), - ], - keywords: [], - starargs: None, - kwargs: None, - }, - ), - ), - AssignStatement( - Assign { - node: Node { - start: 281, - end: 315, - }, - targets: [ - Name( - Name { - node: Node { - start: 281, - end: 293, - }, - id: "ticker_index", - }, - ), - ], - value: Attribute( - Attribute { - node: Node { - start: 296, - end: 315, - }, - value: Name( - Name { - node: Node { - start: 296, - end: 309, - }, - id: "market_symbol", - }, - ), - attr: "index", - }, - ), - }, - ), - ], - orelse: [], - }, - ), - Return( - Return { - node: Node { - start: 320, - end: 339, - }, - value: Some( - Name( - Name { - node: Node { - start: 327, - end: 339, - }, - id: "ticker_index", - }, - ), - ), - }, - ), - ], - orelse: [], - }, - ), - FunctionDef( - FunctionDef { - node: Node { - start: 342, - end: 609, - }, - name: "_extract_ticker_client_types_data", - args: Arguments { - node: Node { - start: 380, - end: 397, - }, - posonlyargs: [], - args: [ - Arg { - node: Node { - start: 380, - end: 397, - }, - arg: "ticker_index", - annotation: Some( - Name( - Name { - node: Node { - start: 394, - end: 397, - }, - id: "str", - }, - ), - ), - }, - ], - vararg: None, - kwonlyargs: [], - kw_defaults: [], - kwarg: None, - defaults: [], - }, - body: [ - AssignStatement( - Assign { - node: Node { - start: 412, - end: 463, - }, - targets: [ - Name( - Name { - node: Node { - start: 412, - end: 415, - }, - id: "url", - }, - ), - ], - value: Call( - Call { - node: Node { - start: 418, - end: 463, - }, - func: Attribute( - Attribute { - node: Node { - start: 418, - end: 449, - }, - value: Name( - Name { - node: Node { - start: 418, - end: 442, - }, - id: "TSE_CLIENT_TYPE_DATA_URL", - }, - ), - attr: "format", - }, - ), - args: [ - Name( - Name { - node: Node { - start: 450, - end: 462, - }, - id: "ticker_index", - }, - ), - ], - keywords: [], - starargs: None, - kwargs: None, - }, - ), - }, - ), - WithStatement( - With { - node: Node { - start: 468, - end: 561, - }, - items: [ - WithItem { - node: Node { - start: 473, - end: 508, - }, - context_expr: Call( - Call { - node: Node { - start: 473, - end: 497, - }, - func: Name( - Name { - node: Node { - start: 473, - end: 495, - }, - id: "requests_retry_session", - }, - ), - args: [], - keywords: [], - starargs: None, - kwargs: None, - }, - ), - optional_vars: Some( - Name( - Name { - node: Node { - start: 501, - end: 508, - }, - id: "session", - }, - ), - ), - }, - ], - body: [ - AssignStatement( - Assign { - node: Node { - start: 518, - end: 556, - }, - targets: [ - Name( - Name { - node: Node { - start: 518, - end: 526, - }, - id: "response", - }, - ), - ], - value: Call( - Call { - node: Node { - start: 529, - end: 556, - }, - func: Attribute( - Attribute { - node: Node { - start: 529, - end: 540, - }, - value: Name( - Name { - node: Node { - start: 529, - end: 536, - }, - id: "session", - }, - ), - attr: "get", - }, - ), - args: [ - Name( - Name { - node: Node { - start: 541, - end: 544, - }, - id: "url", - }, - ), - ], - keywords: [ - Keyword { - node: Node { - start: 546, - end: 555, - }, - arg: Some( - "timeout", - ), - value: Constant( - Constant { - node: Node { - start: 554, - end: 555, - }, - value: Int( - "5", - ), - }, - ), - }, - ], - starargs: None, - kwargs: None, - }, - ), - }, - ), - ], - }, - ), - AssignStatement( - Assign { - node: Node { - start: 561, - end: 592, - }, - targets: [ - Name( - Name { - node: Node { - start: 561, - end: 565, - }, - id: "data", - }, - ), - ], - value: Call( - Call { - node: Node { - start: 568, - end: 592, - }, - func: Attribute( - Attribute { - node: Node { - start: 568, - end: 587, - }, - value: Attribute( - Attribute { - node: Node { - start: 568, - end: 581, - }, - value: Name( - Name { - node: Node { - start: 568, - end: 576, - }, - id: "response", - }, - ), - attr: "text", - }, - ), - attr: "split", - }, - ), - args: [ - Constant( - Constant { - node: Node { - start: 588, - end: 591, - }, - value: Str( - ";", - ), - }, - ), - ], - keywords: [], - starargs: None, - kwargs: None, - }, - ), - }, - ), - Return( - Return { - node: Node { - start: 597, - end: 608, - }, - value: Some( - Name( - Name { - node: Node { - start: 604, - end: 608, - }, - id: "data", - }, - ), - ), - }, - ), - ], - decorator_list: [], - returns: Some( - Name( - Name { - node: Node { - start: 402, - end: 406, - }, - id: "List", - }, - ), - ), - type_comment: None, - }, - ), - ], - decorator_list: [], - returns: None, - type_comment: None, - }, - ), - ], -} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__for_statement-2.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-2.snap similarity index 95% rename from parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__for_statement-2.snap rename to parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-2.snap index aa888acc..9885f2a3 100644 --- a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__for_statement-2.snap +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-2.snap @@ -1,6 +1,7 @@ --- source: parser/src/parser/parser.rs description: "for a in b:\n pass" +input_file: parser/test_data/inputs/one_liners/for.py --- Module { node: Node { diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__for_statement-3.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-3.snap similarity index 98% rename from parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__for_statement-3.snap rename to parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-3.snap index e7084f8c..698d0f37 100644 --- a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__for_statement-3.snap +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-3.snap @@ -1,6 +1,7 @@ --- source: parser/src/parser/parser.rs description: "for a in range(10):\n a = 1\nelse:\n b = 1" +input_file: parser/test_data/inputs/one_liners/for.py --- Module { node: Node { diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__for_statement-4.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-4.snap similarity index 97% rename from parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__for_statement-4.snap rename to parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-4.snap index ce74a13c..cfbc1ae8 100644 --- a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__for_statement-4.snap +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-4.snap @@ -1,18 +1,19 @@ --- source: parser/src/parser/parser.rs -description: "for a in range(10), range(10):\n a = 1\n" +description: "for a in range(10), range(10):\n a = 1" +input_file: parser/test_data/inputs/one_liners/for.py --- Module { node: Node { start: 0, - end: 41, + end: 40, }, body: [ ForStatement( For { node: Node { start: 0, - end: 41, + end: 40, }, target: Name( Name { diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-5.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-5.snap new file mode 100644 index 00000000..9a0bd543 --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-5.snap @@ -0,0 +1,50 @@ +--- +source: parser/src/parser/parser.rs +description: "async for a in b: pass" +input_file: parser/test_data/inputs/one_liners/for.py +--- +Module { + node: Node { + start: 0, + end: 22, + }, + body: [ + AsyncForStatement( + AsyncFor { + node: Node { + start: 0, + end: 22, + }, + target: Name( + Name { + node: Node { + start: 10, + end: 11, + }, + id: "a", + }, + ), + iter: Name( + Name { + node: Node { + start: 15, + end: 16, + }, + id: "b", + }, + ), + body: [ + Pass( + Pass { + node: Node { + start: 18, + end: 22, + }, + }, + ), + ], + orelse: [], + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-6.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-6.snap new file mode 100644 index 00000000..96938042 --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py-6.snap @@ -0,0 +1,50 @@ +--- +source: parser/src/parser/parser.rs +description: "async for a in b:\n pass\n" +input_file: parser/test_data/inputs/one_liners/for.py +--- +Module { + node: Node { + start: 0, + end: 27, + }, + body: [ + AsyncForStatement( + AsyncFor { + node: Node { + start: 0, + end: 27, + }, + target: Name( + Name { + node: Node { + start: 10, + end: 11, + }, + id: "a", + }, + ), + iter: Name( + Name { + node: Node { + start: 15, + end: 16, + }, + id: "b", + }, + ), + body: [ + Pass( + Pass { + node: Node { + start: 22, + end: 26, + }, + }, + ), + ], + orelse: [], + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__for_statement.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py.snap similarity index 95% rename from parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__for_statement.snap rename to parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py.snap index 2f4049db..89ac4106 100644 --- a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__for_statement.snap +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@for.py.snap @@ -1,6 +1,7 @@ --- source: parser/src/parser/parser.rs description: "for a in b: pass" +input_file: parser/test_data/inputs/one_liners/for.py --- Module { node: Node { diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-10.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-10.snap new file mode 100644 index 00000000..1597cbb4 --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-10.snap @@ -0,0 +1,48 @@ +--- +source: parser/src/parser/parser.rs +description: "async def a():\n pass" +input_file: parser/test_data/inputs/one_liners/function_def.py +--- +Module { + node: Node { + start: 0, + end: 23, + }, + body: [ + AsyncFunctionDef( + AsyncFunctionDef { + node: Node { + start: 0, + end: 23, + }, + name: "a", + args: Arguments { + node: Node { + start: 12, + end: 12, + }, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [], + kw_defaults: [], + kwarg: None, + defaults: [], + }, + body: [ + Pass( + Pass { + node: Node { + start: 19, + end: 23, + }, + }, + ), + ], + decorator_list: [], + returns: None, + type_comment: None, + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-11.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-11.snap new file mode 100644 index 00000000..8481336f --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-11.snap @@ -0,0 +1,73 @@ +--- +source: parser/src/parser/parser.rs +description: "async def a(a, b, c): pass\n" +input_file: parser/test_data/inputs/one_liners/function_def.py +--- +Module { + node: Node { + start: 0, + end: 27, + }, + body: [ + AsyncFunctionDef( + AsyncFunctionDef { + node: Node { + start: 0, + end: 27, + }, + name: "a", + args: Arguments { + node: Node { + start: 12, + end: 19, + }, + posonlyargs: [], + args: [ + Arg { + node: Node { + start: 12, + end: 13, + }, + arg: "a", + annotation: None, + }, + Arg { + node: Node { + start: 15, + end: 16, + }, + arg: "b", + annotation: None, + }, + Arg { + node: Node { + start: 18, + end: 19, + }, + arg: "c", + annotation: None, + }, + ], + vararg: None, + kwonlyargs: [], + kw_defaults: [], + kwarg: None, + defaults: [], + }, + body: [ + Pass( + Pass { + node: Node { + start: 22, + end: 26, + }, + }, + ), + ], + decorator_list: [], + returns: None, + type_comment: None, + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-2.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-2.snap new file mode 100644 index 00000000..69e00b23 --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-2.snap @@ -0,0 +1,48 @@ +--- +source: parser/src/parser/parser.rs +description: "def a():\n pass" +input_file: parser/test_data/inputs/one_liners/function_def.py +--- +Module { + node: Node { + start: 0, + end: 17, + }, + body: [ + FunctionDef( + FunctionDef { + node: Node { + start: 0, + end: 17, + }, + name: "a", + args: Arguments { + node: Node { + start: 6, + end: 6, + }, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [], + kw_defaults: [], + kwarg: None, + defaults: [], + }, + body: [ + Pass( + Pass { + node: Node { + start: 13, + end: 17, + }, + }, + ), + ], + decorator_list: [], + returns: None, + type_comment: None, + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-3.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-3.snap new file mode 100644 index 00000000..1a7e2202 --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-3.snap @@ -0,0 +1,73 @@ +--- +source: parser/src/parser/parser.rs +description: "def a(a, b, c): pass" +input_file: parser/test_data/inputs/one_liners/function_def.py +--- +Module { + node: Node { + start: 0, + end: 20, + }, + body: [ + FunctionDef( + FunctionDef { + node: Node { + start: 0, + end: 20, + }, + name: "a", + args: Arguments { + node: Node { + start: 6, + end: 13, + }, + posonlyargs: [], + args: [ + Arg { + node: Node { + start: 6, + end: 7, + }, + arg: "a", + annotation: None, + }, + Arg { + node: Node { + start: 9, + end: 10, + }, + arg: "b", + annotation: None, + }, + Arg { + node: Node { + start: 12, + end: 13, + }, + arg: "c", + annotation: None, + }, + ], + vararg: None, + kwonlyargs: [], + kw_defaults: [], + kwarg: None, + defaults: [], + }, + body: [ + Pass( + Pass { + node: Node { + start: 16, + end: 20, + }, + }, + ), + ], + decorator_list: [], + returns: None, + type_comment: None, + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-4.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-4.snap new file mode 100644 index 00000000..704d2258 --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-4.snap @@ -0,0 +1,75 @@ +--- +source: parser/src/parser/parser.rs +description: "def a(a, *b, **c): pass" +input_file: parser/test_data/inputs/one_liners/function_def.py +--- +Module { + node: Node { + start: 0, + end: 23, + }, + body: [ + FunctionDef( + FunctionDef { + node: Node { + start: 0, + end: 23, + }, + name: "a", + args: Arguments { + node: Node { + start: 6, + end: 16, + }, + posonlyargs: [], + args: [ + Arg { + node: Node { + start: 6, + end: 7, + }, + arg: "a", + annotation: None, + }, + ], + vararg: Some( + Arg { + node: Node { + start: 10, + end: 11, + }, + arg: "b", + annotation: None, + }, + ), + kwonlyargs: [], + kw_defaults: [], + kwarg: Some( + Arg { + node: Node { + start: 15, + end: 16, + }, + arg: "c", + annotation: None, + }, + ), + defaults: [], + }, + body: [ + Pass( + Pass { + node: Node { + start: 19, + end: 23, + }, + }, + ), + ], + decorator_list: [], + returns: None, + type_comment: None, + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-5.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-5.snap new file mode 100644 index 00000000..7cf968e6 --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-5.snap @@ -0,0 +1,73 @@ +--- +source: parser/src/parser/parser.rs +description: "def a(a,\nb,\nc): pass" +input_file: parser/test_data/inputs/one_liners/function_def.py +--- +Module { + node: Node { + start: 0, + end: 20, + }, + body: [ + FunctionDef( + FunctionDef { + node: Node { + start: 0, + end: 20, + }, + name: "a", + args: Arguments { + node: Node { + start: 6, + end: 13, + }, + posonlyargs: [], + args: [ + Arg { + node: Node { + start: 6, + end: 7, + }, + arg: "a", + annotation: None, + }, + Arg { + node: Node { + start: 9, + end: 10, + }, + arg: "b", + annotation: None, + }, + Arg { + node: Node { + start: 12, + end: 13, + }, + arg: "c", + annotation: None, + }, + ], + vararg: None, + kwonlyargs: [], + kw_defaults: [], + kwarg: None, + defaults: [], + }, + body: [ + Pass( + Pass { + node: Node { + start: 16, + end: 20, + }, + }, + ), + ], + decorator_list: [], + returns: None, + type_comment: None, + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-6.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-6.snap new file mode 100644 index 00000000..83a015bb --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-6.snap @@ -0,0 +1,58 @@ +--- +source: parser/src/parser/parser.rs +description: "@decor\ndef a(): pass" +input_file: parser/test_data/inputs/one_liners/function_def.py +--- +Module { + node: Node { + start: 0, + end: 20, + }, + body: [ + FunctionDef( + FunctionDef { + node: Node { + start: 7, + end: 20, + }, + name: "a", + args: Arguments { + node: Node { + start: 13, + end: 13, + }, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [], + kw_defaults: [], + kwarg: None, + defaults: [], + }, + body: [ + Pass( + Pass { + node: Node { + start: 16, + end: 20, + }, + }, + ), + ], + decorator_list: [ + Name( + Name { + node: Node { + start: 1, + end: 6, + }, + id: "decor", + }, + ), + ], + returns: None, + type_comment: None, + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-7.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-7.snap new file mode 100644 index 00000000..3ae33238 --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-7.snap @@ -0,0 +1,168 @@ +--- +source: parser/src/parser/parser.rs +description: "@decor\ndef f(a: 'annotation', b=1, c=2, *d, e, f=3, **g): pass" +input_file: parser/test_data/inputs/one_liners/function_def.py +--- +Module { + node: Node { + start: 0, + end: 62, + }, + body: [ + FunctionDef( + FunctionDef { + node: Node { + start: 7, + end: 62, + }, + name: "f", + args: Arguments { + node: Node { + start: 13, + end: 55, + }, + posonlyargs: [], + args: [ + Arg { + node: Node { + start: 13, + end: 28, + }, + arg: "a", + annotation: Some( + Constant( + Constant { + node: Node { + start: 16, + end: 28, + }, + value: Str( + "annotation", + ), + }, + ), + ), + }, + Arg { + node: Node { + start: 30, + end: 33, + }, + arg: "b", + annotation: None, + }, + Arg { + node: Node { + start: 35, + end: 38, + }, + arg: "c", + annotation: None, + }, + ], + vararg: Some( + Arg { + node: Node { + start: 41, + end: 42, + }, + arg: "d", + annotation: None, + }, + ), + kwonlyargs: [ + Arg { + node: Node { + start: 44, + end: 45, + }, + arg: "e", + annotation: None, + }, + Arg { + node: Node { + start: 47, + end: 50, + }, + arg: "f", + annotation: None, + }, + ], + kw_defaults: [ + None, + Some( + Constant( + Constant { + node: Node { + start: 49, + end: 50, + }, + value: Int( + "3", + ), + }, + ), + ), + ], + kwarg: Some( + Arg { + node: Node { + start: 54, + end: 55, + }, + arg: "g", + annotation: None, + }, + ), + defaults: [ + Constant( + Constant { + node: Node { + start: 32, + end: 33, + }, + value: Int( + "1", + ), + }, + ), + Constant( + Constant { + node: Node { + start: 37, + end: 38, + }, + value: Int( + "2", + ), + }, + ), + ], + }, + body: [ + Pass( + Pass { + node: Node { + start: 58, + end: 62, + }, + }, + ), + ], + decorator_list: [ + Name( + Name { + node: Node { + start: 1, + end: 6, + }, + id: "decor", + }, + ), + ], + returns: None, + type_comment: None, + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-8.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-8.snap new file mode 100644 index 00000000..03a50ab2 --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-8.snap @@ -0,0 +1,58 @@ +--- +source: parser/src/parser/parser.rs +description: "def func() -> None: pass" +input_file: parser/test_data/inputs/one_liners/function_def.py +--- +Module { + node: Node { + start: 0, + end: 24, + }, + body: [ + FunctionDef( + FunctionDef { + node: Node { + start: 0, + end: 24, + }, + name: "func", + args: Arguments { + node: Node { + start: 9, + end: 9, + }, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [], + kw_defaults: [], + kwarg: None, + defaults: [], + }, + body: [ + Pass( + Pass { + node: Node { + start: 20, + end: 24, + }, + }, + ), + ], + decorator_list: [], + returns: Some( + Constant( + Constant { + node: Node { + start: 14, + end: 18, + }, + value: None, + }, + ), + ), + type_comment: None, + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-9.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-9.snap new file mode 100644 index 00000000..074fe35f --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py-9.snap @@ -0,0 +1,48 @@ +--- +source: parser/src/parser/parser.rs +description: "async def a(): pass" +input_file: parser/test_data/inputs/one_liners/function_def.py +--- +Module { + node: Node { + start: 0, + end: 19, + }, + body: [ + AsyncFunctionDef( + AsyncFunctionDef { + node: Node { + start: 0, + end: 19, + }, + name: "a", + args: Arguments { + node: Node { + start: 12, + end: 12, + }, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [], + kw_defaults: [], + kwarg: None, + defaults: [], + }, + body: [ + Pass( + Pass { + node: Node { + start: 15, + end: 19, + }, + }, + ), + ], + decorator_list: [], + returns: None, + type_comment: None, + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py.snap new file mode 100644 index 00000000..c84d7c5c --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@function_def.py.snap @@ -0,0 +1,48 @@ +--- +source: parser/src/parser/parser.rs +description: "def a(): pass" +input_file: parser/test_data/inputs/one_liners/function_def.py +--- +Module { + node: Node { + start: 0, + end: 13, + }, + body: [ + FunctionDef( + FunctionDef { + node: Node { + start: 0, + end: 13, + }, + name: "a", + args: Arguments { + node: Node { + start: 6, + end: 6, + }, + posonlyargs: [], + args: [], + vararg: None, + kwonlyargs: [], + kw_defaults: [], + kwarg: None, + defaults: [], + }, + body: [ + Pass( + Pass { + node: Node { + start: 9, + end: 13, + }, + }, + ), + ], + decorator_list: [], + returns: None, + type_comment: None, + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__with_statement-2.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-2.snap similarity index 96% rename from parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__with_statement-2.snap rename to parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-2.snap index 27665dd5..a5b102ef 100644 --- a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__with_statement-2.snap +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-2.snap @@ -1,6 +1,7 @@ --- source: parser/src/parser/parser.rs description: "with a as b: pass" +input_file: parser/test_data/inputs/one_liners/with.py --- Module { node: Node { diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__with_statement-3.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-3.snap similarity index 97% rename from parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__with_statement-3.snap rename to parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-3.snap index 5cf6d65e..dad6a150 100644 --- a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__with_statement-3.snap +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-3.snap @@ -1,6 +1,7 @@ --- source: parser/src/parser/parser.rs description: "with a as b, c as d: pass" +input_file: parser/test_data/inputs/one_liners/with.py --- Module { node: Node { diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__with_statement-4.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-4.snap similarity index 97% rename from parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__with_statement-4.snap rename to parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-4.snap index 37d9a181..72e0a603 100644 --- a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__with_statement-4.snap +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-4.snap @@ -1,6 +1,7 @@ --- source: parser/src/parser/parser.rs description: "with (a as b, c as d): pass" +input_file: parser/test_data/inputs/one_liners/with.py --- Module { node: Node { diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-5.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-5.snap new file mode 100644 index 00000000..65a915e7 --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-5.snap @@ -0,0 +1,59 @@ +--- +source: parser/src/parser/parser.rs +description: "async with a as b: pass" +input_file: parser/test_data/inputs/one_liners/with.py +--- +Module { + node: Node { + start: 0, + end: 23, + }, + body: [ + AsyncWithStatement( + AsyncWith { + node: Node { + start: 0, + end: 23, + }, + items: [ + WithItem { + node: Node { + start: 11, + end: 17, + }, + context_expr: Name( + Name { + node: Node { + start: 11, + end: 12, + }, + id: "a", + }, + ), + optional_vars: Some( + Name( + Name { + node: Node { + start: 16, + end: 17, + }, + id: "b", + }, + ), + ), + }, + ], + body: [ + Pass( + Pass { + node: Node { + start: 19, + end: 23, + }, + }, + ), + ], + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-6.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-6.snap new file mode 100644 index 00000000..039908b2 --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-6.snap @@ -0,0 +1,85 @@ +--- +source: parser/src/parser/parser.rs +description: "async with a as b, c as d:\n pass" +input_file: parser/test_data/inputs/one_liners/with.py +--- +Module { + node: Node { + start: 0, + end: 35, + }, + body: [ + AsyncWithStatement( + AsyncWith { + node: Node { + start: 0, + end: 35, + }, + items: [ + WithItem { + node: Node { + start: 11, + end: 17, + }, + context_expr: Name( + Name { + node: Node { + start: 11, + end: 12, + }, + id: "a", + }, + ), + optional_vars: Some( + Name( + Name { + node: Node { + start: 16, + end: 17, + }, + id: "b", + }, + ), + ), + }, + WithItem { + node: Node { + start: 19, + end: 25, + }, + context_expr: Name( + Name { + node: Node { + start: 19, + end: 20, + }, + id: "c", + }, + ), + optional_vars: Some( + Name( + Name { + node: Node { + start: 24, + end: 25, + }, + id: "d", + }, + ), + ), + }, + ], + body: [ + Pass( + Pass { + node: Node { + start: 31, + end: 35, + }, + }, + ), + ], + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-7.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-7.snap new file mode 100644 index 00000000..244f9f7a --- /dev/null +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py-7.snap @@ -0,0 +1,107 @@ +--- +source: parser/src/parser/parser.rs +description: "async with (\n a as b, c as d\n):\n a = 1\n" +input_file: parser/test_data/inputs/one_liners/with.py +--- +Module { + node: Node { + start: 0, + end: 49, + }, + body: [ + AsyncWithStatement( + AsyncWith { + node: Node { + start: 0, + end: 49, + }, + items: [ + WithItem { + node: Node { + start: 21, + end: 27, + }, + context_expr: Name( + Name { + node: Node { + start: 21, + end: 22, + }, + id: "a", + }, + ), + optional_vars: Some( + Name( + Name { + node: Node { + start: 26, + end: 27, + }, + id: "b", + }, + ), + ), + }, + WithItem { + node: Node { + start: 29, + end: 35, + }, + context_expr: Name( + Name { + node: Node { + start: 29, + end: 30, + }, + id: "c", + }, + ), + optional_vars: Some( + Name( + Name { + node: Node { + start: 34, + end: 35, + }, + id: "d", + }, + ), + ), + }, + ], + body: [ + AssignStatement( + Assign { + node: Node { + start: 43, + end: 48, + }, + targets: [ + Name( + Name { + node: Node { + start: 43, + end: 44, + }, + id: "a", + }, + ), + ], + value: Constant( + Constant { + node: Node { + start: 47, + end: 48, + }, + value: Int( + "1", + ), + }, + ), + }, + ), + ], + }, + ), + ], +} diff --git a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__with_statement.snap b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py.snap similarity index 95% rename from parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__with_statement.snap rename to parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py.snap index 75491ea2..850e3ea8 100644 --- a/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__with_statement.snap +++ b/parser/src/parser/snapshots/enderpy_python_parser__parser__parser__tests__one_liners@with.py.snap @@ -1,6 +1,7 @@ --- source: parser/src/parser/parser.rs description: "with a: pass" +input_file: parser/test_data/inputs/one_liners/with.py --- Module { node: Node { diff --git a/parser/src/parser/statement.rs b/parser/src/parser/statement.rs index 88b1da50..a5c15fa4 100644 --- a/parser/src/parser/statement.rs +++ b/parser/src/parser/statement.rs @@ -12,6 +12,7 @@ pub fn is_at_compound_statement(token: &Token) -> bool { | Kind::Class // Decorators | Kind::MatrixMul => true, + | Kind::Async => true, _ => false, }; if kind_is_statement { diff --git a/parser/test_data/inputs/one_liners/for.py b/parser/test_data/inputs/one_liners/for.py new file mode 100644 index 00000000..193b63d9 --- /dev/null +++ b/parser/test_data/inputs/one_liners/for.py @@ -0,0 +1,17 @@ +for a in b: pass + +for a in b: + pass + +for a in range(10): + a = 1 +else: + b = 1 + +for a in range(10), range(10): + a = 1 + +async for a in b: pass + +async for a in b: + pass diff --git a/parser/test_data/inputs/one_liners/function_def.py b/parser/test_data/inputs/one_liners/function_def.py new file mode 100644 index 00000000..03fc019f --- /dev/null +++ b/parser/test_data/inputs/one_liners/function_def.py @@ -0,0 +1,27 @@ +def a(): pass + +def a(): + pass + +def a(a, b, c): pass + +def a(a, *b, **c): pass + +def a(a, +b, +c): pass + +@decor +def a(): pass + +@decor +def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g): pass + +def func() -> None: pass + +async def a(): pass + +async def a(): + pass + +async def a(a, b, c): pass diff --git a/parser/test_data/inputs/one_liners/with.py b/parser/test_data/inputs/one_liners/with.py new file mode 100644 index 00000000..e9c07da2 --- /dev/null +++ b/parser/test_data/inputs/one_liners/with.py @@ -0,0 +1,17 @@ +with a: pass + +with a as b: pass + +with a as b, c as d: pass + +with (a as b, c as d): pass + +async with a as b: pass + +async with a as b, c as d: + pass + +async with ( + a as b, c as d +): + a = 1 diff --git a/typechecker/src/ast_visitor.rs b/typechecker/src/ast_visitor.rs index 0fbae96b..4e6dbb7a 100644 --- a/typechecker/src/ast_visitor.rs +++ b/typechecker/src/ast_visitor.rs @@ -1,76 +1,6 @@ use enderpy_python_parser::ast::*; use enderpy_python_parser as parser; -// pub trait FileVisitor: StmtVisitor + ExprVisitor { -// fn visit_file(&mut self, f: &EnderpyFile) -> T { -// self.visit_module(&f.ast) -// } -// fn visit_module(&mut self, m: &Module) -> T { -// for stmt in m.body { -// self.visit_stmt(stmt) -// } -// } -// } -// -// pub trait StmtVisitor { -// fn visit_stmt(&mut self, s: &Statement) -> T; -// fn visit_expr(&mut self, e: &Expression) -> T; -// fn visit_import(&mut self, i: &Import) -> T; -// fn visit_import_from(&mut self, i: &ImportFrom) -> T; -// fn visit_alias(&mut self, a: &Alias) -> T; -// fn visit_assign(&mut self, a: &Assign) -> T; -// fn visit_ann_assign(&mut self, a: &AnnAssign) -> T; -// fn visit_aug_assign(&mut self, a: &AugAssign) -> T; -// fn visit_assert(&mut self, a: &Assert) -> T; -// fn visit_pass(&mut self, p: &Pass) -> T; -// fn visit_delete(&mut self, d: &Delete) -> T; -// fn visit_return(&mut self, r: &Return) -> T; -// fn visit_raise(&mut self, r: &Raise) -> T; -// fn visit_break(&mut self, b: &Break) -> T; -// fn visit_continue(&mut self, c: &Continue) -> T; -// fn visit_global(&mut self, g: &Global) -> T; -// fn visit_nonlocal(&mut self, n: &Nonlocal) -> T; -// fn visit_if(&mut self, i: &If) -> T; -// fn visit_while(&mut self, w: &While) -> T; -// fn visit_for(&mut self, f: &For) -> T; -// fn visit_with(&mut self, w: &With) -> T; -// fn visit_try(&mut self, t: &Try) -> T; -// fn visit_try_star(&mut self, t: &TryStar) -> T; -// fn visit_function_def(&mut self, f: &FunctionDef) -> T; -// fn visit_class_def(&mut self, c: &ClassDef) -> T; -// fn visit_match(&mut self, m: &Match) -> T; -// } -// -// pub trait ExprVisitor { -// fn visit_constant(&mut self, c: &Constant) -> T; -// fn visit_list(&mut self, l: &List) -> T; -// fn visit_tuple(&mut self, t: &Tuple) -> T; -// fn visit_dict(&mut self, d: &Dict) -> T; -// fn visit_set(&mut self, s: &Set) -> T; -// fn visit_name(&mut self, n: &Name) -> T; -// fn visit_bool_op(&mut self, b: &BoolOperation) -> T; -// fn visit_unary_op(&mut self, u: &UnaryOperation) -> T; -// fn visit_bin_op(&mut self, b: &BinOp) -> T; -// fn visit_named_expr(&mut self, n: &NamedExpression) -> T; -// fn visit_yield(&mut self, y: &Yield) -> T; -// fn visit_yield_from(&mut self, y: &YieldFrom) -> T; -// fn visit_starred(&mut self, s: &Starred) -> T; -// fn visit_generator(&mut self, g: &Generator) -> T; -// fn visit_list_comp(&mut self, l: &ListComp) -> T; -// fn visit_set_comp(&mut self, s: &SetComp) -> T; -// fn visit_dict_comp(&mut self, d: &DictComp) -> T; -// fn visit_attribute(&mut self, a: &Attribute) -> T; -// fn visit_subscript(&mut self, s: &Subscript) -> T; -// fn visit_slice(&mut self, s: &Slice) -> T; -// fn visit_call(&mut self, c: &Call) -> T; -// fn visit_await(&mut self, a: &Await) -> T; -// fn visit_compare(&mut self, c: &Compare) -> T; -// fn visit_lambda(&mut self, l: &Lambda) -> T; -// fn visit_if_exp(&mut self, i: &IfExp) -> T; -// fn visit_joined_str(&mut self, j: &JoinedStr) -> T; -// fn visit_formatted_value(&mut self, f: &FormattedValue) -> T; -// } - /// A visitor that traverses the AST and calls the visit method for each node /// This is useful for visitors that only need to visit a few nodes /// and don't want to implement all the methods. @@ -103,6 +33,9 @@ pub trait TraversalVisitor { Statement::FunctionDef(f) => self.visit_function_def(f), Statement::ClassDef(c) => self.visit_class_def(c), Statement::Match(m) => self.visit_match(m), + Statement::AsyncForStatement(f) => self.visit_async_for(f), + Statement::AsyncWithStatement(w) => self.visit_async_with(w), + Statement::AsyncFunctionDef(f) => self.visit_async_function_def(f), } } fn visit_expr(&mut self, e: &Expression) { @@ -165,6 +98,12 @@ pub trait TraversalVisitor { } } + fn visit_async_for(&mut self, f: &parser::ast::AsyncFor) { + for stmt in &f.body { + self.visit_stmt(stmt); + } + } + fn visit_with(&mut self, w: &parser::ast::With) { for stmt in &w.body { self.visit_stmt(stmt); @@ -178,6 +117,19 @@ pub trait TraversalVisitor { } } + fn visit_async_with(&mut self, w: &parser::ast::AsyncWith) { + for stmt in &w.body { + self.visit_stmt(stmt); + } + for with_items in &w.items { + self.visit_expr(&with_items.context_expr); + match &with_items.optional_vars { + Some(items) => self.visit_expr(items), + None => (), + } + } + } + fn visit_try(&mut self, t: &parser::ast::Try) { for stmt in &t.body { self.visit_stmt(stmt); @@ -220,6 +172,12 @@ pub trait TraversalVisitor { } } + fn visit_async_function_def(&mut self, f: &parser::ast::AsyncFunctionDef) { + for stmt in &f.body { + self.visit_stmt(stmt); + } + } + fn visit_class_def(&mut self, c: &parser::ast::ClassDef) { for stmt in &c.body { self.visit_stmt(stmt); diff --git a/typechecker/src/ast_visitor_generic.rs b/typechecker/src/ast_visitor_generic.rs index 6a58ac80..b3214c35 100644 --- a/typechecker/src/ast_visitor_generic.rs +++ b/typechecker/src/ast_visitor_generic.rs @@ -35,6 +35,9 @@ pub trait TraversalVisitorImmutGeneric { Statement::FunctionDef(f) => self.visit_function_def(f), Statement::ClassDef(c) => self.visit_class_def(c), Statement::Match(m) => self.visit_match(m), + Statement::AsyncForStatement(f) => self.visit_async_for(f), + Statement::AsyncWithStatement(w) => self.visit_async_with(w), + Statement::AsyncFunctionDef(f) => self.visit_async_function_def(f), } } fn visit_expr(&self, e: &Expression) -> T { @@ -88,10 +91,18 @@ pub trait TraversalVisitorImmutGeneric { todo!(); } + fn visit_async_for(&self, f: &parser::ast::AsyncFor) -> T { + todo!(); + } + fn visit_with(&self, w: &parser::ast::With) -> T { todo!(); } + fn visit_async_with(&self, w: &parser::ast::AsyncWith) -> T { + todo!(); + } + fn visit_try(&self, t: &parser::ast::Try) -> T { todo!(); } @@ -104,6 +115,10 @@ pub trait TraversalVisitorImmutGeneric { todo!(); } + fn visit_async_function_def(&self, f: &parser::ast::AsyncFunctionDef) -> T { + todo!(); + } + fn visit_class_def(&self, c: &parser::ast::ClassDef) -> T { todo!(); } diff --git a/typechecker/src/ast_visitor_immut.rs b/typechecker/src/ast_visitor_immut.rs index 4b86b5c1..025fdaac 100644 --- a/typechecker/src/ast_visitor_immut.rs +++ b/typechecker/src/ast_visitor_immut.rs @@ -32,6 +32,9 @@ pub trait TraversalVisitorImmut { Statement::FunctionDef(f) => self.visit_function_def(f), Statement::ClassDef(c) => self.visit_class_def(c), Statement::Match(m) => self.visit_match(m), + Statement::AsyncForStatement(f) => self.visit_async_for(f), + Statement::AsyncWithStatement(w) => self.visit_async_with(w), + Statement::AsyncFunctionDef(f) => self.visit_async_function_def(f), } } fn visit_expr(&self, e: &Expression) { @@ -94,6 +97,12 @@ pub trait TraversalVisitorImmut { } } + fn visit_async_for(&self, f: &parser::ast::AsyncFor) { + for stmt in &f.body { + self.visit_stmt(stmt); + } + } + fn visit_with(&self, w: &parser::ast::With) { for stmt in &w.body { self.visit_stmt(stmt); @@ -107,6 +116,19 @@ pub trait TraversalVisitorImmut { } } + fn visit_async_with(&self, w: &parser::ast::AsyncWith) { + for stmt in &w.body { + self.visit_stmt(stmt); + } + for with_items in &w.items { + self.visit_expr(&with_items.context_expr); + match &with_items.optional_vars { + Some(items) => self.visit_expr(items), + None => (), + } + } + } + fn visit_try(&self, t: &parser::ast::Try) { for stmt in &t.body { self.visit_stmt(stmt); @@ -149,6 +171,12 @@ pub trait TraversalVisitorImmut { } } + fn visit_async_function_def(&self, f: &parser::ast::AsyncFunctionDef) { + for stmt in &f.body { + self.visit_stmt(stmt); + } + } + fn visit_class_def(&self, c: &parser::ast::ClassDef) { for stmt in &c.body { self.visit_stmt(stmt); diff --git a/typechecker/src/nodes.rs b/typechecker/src/nodes.rs index 7b334f05..bc0e8a00 100755 --- a/typechecker/src/nodes.rs +++ b/typechecker/src/nodes.rs @@ -79,6 +79,9 @@ impl<'a> TraversalVisitor for EnderpyFile { Statement::FunctionDef(f) => self.visit_function_def(f), Statement::ClassDef(c) => self.visit_class_def(c), Statement::Match(m) => self.visit_match(m), + Statement::AsyncForStatement(f) => self.visit_async_for(f), + Statement::AsyncWithStatement(w) => self.visit_async_with(w), + Statement::AsyncFunctionDef(f) => self.visit_async_function_def(f), } } diff --git a/typechecker/src/semantic_analyzer.rs b/typechecker/src/semantic_analyzer.rs index b2e9faf5..fc73bf0b 100644 --- a/typechecker/src/semantic_analyzer.rs +++ b/typechecker/src/semantic_analyzer.rs @@ -1,5 +1,6 @@ use enderpy_python_parser::ast::Expression; use enderpy_python_parser as parser; +use parser::ast::Statement; use crate::{ ast_visitor::TraversalVisitor, @@ -241,6 +242,9 @@ impl TraversalVisitor for SemanticAnalyzer { parser::ast::Statement::FunctionDef(f) => self.visit_function_def(f), parser::ast::Statement::ClassDef(c) => self.visit_class_def(c), parser::ast::Statement::Match(m) => self.visit_match(m), + Statement::AsyncForStatement(f) => self.visit_async_for(f), + Statement::AsyncWithStatement(w) => self.visit_async_with(w), + Statement::AsyncFunctionDef(f) => self.visit_async_function_def(f), } } @@ -318,6 +322,12 @@ impl TraversalVisitor for SemanticAnalyzer { } } + fn visit_async_for(&mut self, f: &parser::ast::AsyncFor) { + for stmt in &f.body { + self.visit_stmt(stmt); + } + } + fn visit_with(&mut self, w: &parser::ast::With) { for stmt in &w.body { self.visit_stmt(stmt); @@ -331,6 +341,19 @@ impl TraversalVisitor for SemanticAnalyzer { } } + fn visit_async_with(&mut self, w: &parser::ast::AsyncWith) { + for stmt in &w.body { + self.visit_stmt(stmt); + } + for with_items in &w.items { + self.visit_expr(&with_items.context_expr); + match &with_items.optional_vars { + Some(items) => self.visit_expr(items), + None => (), + } + } + } + fn visit_try(&mut self, t: &parser::ast::Try) { for stmt in &t.body { self.visit_stmt(stmt); @@ -408,6 +431,10 @@ impl TraversalVisitor for SemanticAnalyzer { self.create_symbol(f.name.clone(), function_declaration); } + fn visit_async_function_def(&mut self, f: &parser::ast::AsyncFunctionDef) { + todo!() + } + fn visit_class_def(&mut self, c: &parser::ast::ClassDef) { let declaration_path = DeclarationPath { module_name: self.file.module_name.clone(), diff --git a/typechecker/src/type_check/checker.rs b/typechecker/src/type_check/checker.rs index e3d2d85e..5baa5108 100644 --- a/typechecker/src/type_check/checker.rs +++ b/typechecker/src/type_check/checker.rs @@ -99,6 +99,9 @@ impl<'a> TraversalVisitor for TypeChecker<'a> { Statement::FunctionDef(f) => self.visit_function_def(f), Statement::ClassDef(c) => self.visit_class_def(c), Statement::Match(m) => self.visit_match(m), + Statement::AsyncForStatement(f) => self.visit_async_for(f), + Statement::AsyncWithStatement(w) => self.visit_async_with(w), + Statement::AsyncFunctionDef(f) => self.visit_async_function_def(f), } } diff --git a/typechecker/src/type_check/type_evaluator.rs b/typechecker/src/type_check/type_evaluator.rs index d65d7a5c..ad44f76e 100755 --- a/typechecker/src/type_check/type_evaluator.rs +++ b/typechecker/src/type_check/type_evaluator.rs @@ -4,6 +4,7 @@ use miette::{bail, miette, Result}; use enderpy_python_parser::ast; use enderpy_python_parser as parser; +use parser::ast::Statement; use crate::{ ast_visitor_generic::TraversalVisitorImmutGeneric, @@ -273,6 +274,9 @@ impl TraversalVisitorImmutGeneric for TypeEvaluator { ast::Statement::FunctionDef(f) => self.visit_function_def(f), ast::Statement::ClassDef(c) => self.visit_class_def(c), ast::Statement::Match(m) => self.visit_match(m), + Statement::AsyncForStatement(f) => self.visit_async_for(f), + Statement::AsyncWithStatement(w) => self.visit_async_with(w), + Statement::AsyncFunctionDef(f) => self.visit_async_function_def(f), } }