diff --git a/src/parser.rs b/src/parser.rs index fa2512c..57ec49d 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -61,9 +61,10 @@ pub enum AstNode { Name, Type { name: NodeId, - params: Option, + args: Option, optional: bool, }, + TypeArgs(Vec), Variable, // Booleans @@ -611,19 +612,12 @@ impl Parser { // Explicit closure case if self.is_pipe() { - let args = Some(self.signature_params(ParamsContext::Pipes)); + let params = Some(self.signature_params(ParamsContext::Pipes)); let block = self.block(BlockContext::Closure); self.rcurly(); span_end = self.position(); - return self.create_node( - AstNode::Closure { - params: args, - block, - }, - span_start, - span_end, - ); + return self.create_node(AstNode::Closure { params, block }, span_start, span_end); } let rollback_point = self.get_rollback_point(); @@ -927,11 +921,11 @@ impl Parser { self.create_node(AstNode::Params(param_list), span_start, span_end) } - pub fn type_params(&mut self) -> NodeId { + pub fn type_args(&mut self) -> NodeId { let _span = span!(); let span_start = self.position(); let span_end; - let param_list = { + let arg_list = { self.less_than(); let mut output = vec![]; @@ -955,17 +949,17 @@ impl Parser { output }; - self.create_node(AstNode::Params(param_list), span_start, span_end) + self.create_node(AstNode::TypeArgs(arg_list), span_start, span_end) } pub fn typename(&mut self) -> NodeId { let _span = span!(); if let (Token::Bareword, span) = self.tokens.peek() { let name = self.name(); - let mut params = None; + let mut args = None; if self.is_less_than() { // We have generics - params = Some(self.type_params()); + args = Some(self.type_args()); } let optional = if self.is_question_mark() { @@ -979,7 +973,7 @@ impl Parser { self.create_node( AstNode::Type { name, - params, + args, optional, }, span.start, diff --git a/src/snapshots/new_nu_parser__test__node_output@calls.nu.snap b/src/snapshots/new_nu_parser__test__node_output@calls.nu.snap index 01b2108..44cef22 100644 --- a/src/snapshots/new_nu_parser__test__node_output@calls.nu.snap +++ b/src/snapshots/new_nu_parser__test__node_output@calls.nu.snap @@ -2,7 +2,6 @@ source: src/test.rs expression: evaluate_example(path) input_file: tests/calls.nu -snapshot_kind: text --- ==== COMPILER ==== 0: Name (0 to 4) "spam" @@ -16,15 +15,15 @@ snapshot_kind: text 8: Name (28 to 36) "existing" 9: Name (38 to 39) "a" 10: Name (41 to 47) "string" -11: Type { name: NodeId(10), params: None, optional: false } (41 to 47) +11: Type { name: NodeId(10), args: None, optional: false } (41 to 47) 12: Param { name: NodeId(9), ty: Some(NodeId(11)) } (38 to 47) 13: Name (49 to 50) "b" 14: Name (52 to 58) "string" -15: Type { name: NodeId(14), params: None, optional: false } (52 to 58) +15: Type { name: NodeId(14), args: None, optional: false } (52 to 58) 16: Param { name: NodeId(13), ty: Some(NodeId(15)) } (49 to 58) 17: Name (60 to 61) "c" 18: Name (63 to 66) "int" -19: Type { name: NodeId(18), params: None, optional: false } (63 to 66) +19: Type { name: NodeId(18), args: None, optional: false } (63 to 66) 20: Param { name: NodeId(17), ty: Some(NodeId(19)) } (60 to 66) 21: Params([NodeId(12), NodeId(16), NodeId(20)]) (37 to 67) 22: Variable (72 to 74) "$a" diff --git a/src/snapshots/new_nu_parser__test__node_output@closure3.nu.snap b/src/snapshots/new_nu_parser__test__node_output@closure3.nu.snap index 20bd057..670e39c 100644 --- a/src/snapshots/new_nu_parser__test__node_output@closure3.nu.snap +++ b/src/snapshots/new_nu_parser__test__node_output@closure3.nu.snap @@ -2,17 +2,16 @@ source: src/test.rs expression: evaluate_example(path) input_file: tests/closure3.nu -snapshot_kind: text --- ==== COMPILER ==== 0: Variable (4 to 11) "closure" 1: Name (16 to 17) "a" 2: Name (19 to 22) "int" -3: Type { name: NodeId(2), params: None, optional: false } (19 to 22) +3: Type { name: NodeId(2), args: None, optional: false } (19 to 22) 4: Param { name: NodeId(1), ty: Some(NodeId(3)) } (16 to 22) 5: Name (24 to 25) "b" 6: Name (27 to 30) "int" -7: Type { name: NodeId(6), params: None, optional: false } (27 to 30) +7: Type { name: NodeId(6), args: None, optional: false } (27 to 30) 8: Param { name: NodeId(5), ty: Some(NodeId(7)) } (24 to 30) 9: Params([NodeId(4), NodeId(8)]) (15 to 31) 10: Variable (32 to 34) "$a" diff --git a/src/snapshots/new_nu_parser__test__node_output@def.nu.snap b/src/snapshots/new_nu_parser__test__node_output@def.nu.snap index fbda6c4..9ae1b61 100644 --- a/src/snapshots/new_nu_parser__test__node_output@def.nu.snap +++ b/src/snapshots/new_nu_parser__test__node_output@def.nu.snap @@ -2,7 +2,6 @@ source: src/test.rs expression: evaluate_example(path) input_file: tests/def.nu -snapshot_kind: text --- ==== COMPILER ==== 0: Name (4 to 7) "foo" @@ -10,17 +9,17 @@ snapshot_kind: text 2: Param { name: NodeId(1), ty: None } (9 to 10) 3: Name (11 to 12) "y" 4: Name (14 to 17) "int" -5: Type { name: NodeId(4), params: None, optional: false } (14 to 17) +5: Type { name: NodeId(4), args: None, optional: false } (14 to 17) 6: Param { name: NodeId(3), ty: Some(NodeId(5)) } (11 to 17) 7: Name (19 to 20) "z" 8: Name (22 to 26) "list" 9: Name (27 to 31) "list" 10: Name (32 to 35) "int" -11: Type { name: NodeId(10), params: None, optional: false } (32 to 35) -12: Params([NodeId(11)]) (31 to 36) -13: Type { name: NodeId(9), params: Some(NodeId(12)), optional: false } (27 to 31) -14: Params([NodeId(13)]) (26 to 37) -15: Type { name: NodeId(8), params: Some(NodeId(14)), optional: false } (22 to 26) +11: Type { name: NodeId(10), args: None, optional: false } (32 to 35) +12: TypeArgs([NodeId(11)]) (31 to 36) +13: Type { name: NodeId(9), args: Some(NodeId(12)), optional: false } (27 to 31) +14: TypeArgs([NodeId(13)]) (26 to 37) +15: Type { name: NodeId(8), args: Some(NodeId(14)), optional: false } (22 to 26) 16: Param { name: NodeId(7), ty: Some(NodeId(15)) } (19 to 26) 17: Params([NodeId(2), NodeId(6), NodeId(16)]) (8 to 39) 18: Variable (44 to 46) "$x" diff --git a/src/snapshots/new_nu_parser__test__node_output@def_return_type.nu.snap b/src/snapshots/new_nu_parser__test__node_output@def_return_type.nu.snap index 7a0e8e9..707220c 100644 --- a/src/snapshots/new_nu_parser__test__node_output@def_return_type.nu.snap +++ b/src/snapshots/new_nu_parser__test__node_output@def_return_type.nu.snap @@ -2,18 +2,17 @@ source: src/test.rs expression: evaluate_example(path) input_file: tests/def_return_type.nu -snapshot_kind: text --- ==== COMPILER ==== 0: Name (4 to 7) "foo" 1: Params([]) (8 to 11) 2: Name (14 to 21) "nothing" -3: Type { name: NodeId(2), params: None, optional: false } (14 to 21) +3: Type { name: NodeId(2), args: None, optional: false } (14 to 21) 4: Name (25 to 29) "list" 5: Name (30 to 33) "any" -6: Type { name: NodeId(5), params: None, optional: false } (30 to 33) -7: Params([NodeId(6)]) (29 to 34) -8: Type { name: NodeId(4), params: Some(NodeId(7)), optional: false } (25 to 29) +6: Type { name: NodeId(5), args: None, optional: false } (30 to 33) +7: TypeArgs([NodeId(6)]) (29 to 34) +8: Type { name: NodeId(4), args: Some(NodeId(7)), optional: false } (25 to 29) 9: InOutType(NodeId(3), NodeId(8)) (14 to 35) 10: InOutTypes([NodeId(9)]) (14 to 35) 11: List([]) (37 to 38) @@ -22,20 +21,20 @@ snapshot_kind: text 14: Name (46 to 49) "bar" 15: Params([]) (50 to 53) 16: Name (58 to 64) "string" -17: Type { name: NodeId(16), params: None, optional: false } (58 to 64) +17: Type { name: NodeId(16), args: None, optional: false } (58 to 64) 18: Name (68 to 72) "list" 19: Name (73 to 79) "string" -20: Type { name: NodeId(19), params: None, optional: false } (73 to 79) -21: Params([NodeId(20)]) (72 to 80) -22: Type { name: NodeId(18), params: Some(NodeId(21)), optional: false } (68 to 72) +20: Type { name: NodeId(19), args: None, optional: false } (73 to 79) +21: TypeArgs([NodeId(20)]) (72 to 80) +22: Type { name: NodeId(18), args: Some(NodeId(21)), optional: false } (68 to 72) 23: InOutType(NodeId(17), NodeId(22)) (58 to 80) 24: Name (82 to 85) "int" -25: Type { name: NodeId(24), params: None, optional: false } (82 to 85) +25: Type { name: NodeId(24), args: None, optional: false } (82 to 85) 26: Name (89 to 93) "list" 27: Name (94 to 97) "int" -28: Type { name: NodeId(27), params: None, optional: false } (94 to 97) -29: Params([NodeId(28)]) (93 to 98) -30: Type { name: NodeId(26), params: Some(NodeId(29)), optional: false } (89 to 93) +28: Type { name: NodeId(27), args: None, optional: false } (94 to 97) +29: TypeArgs([NodeId(28)]) (93 to 98) +30: Type { name: NodeId(26), args: Some(NodeId(29)), optional: false } (89 to 93) 31: InOutType(NodeId(25), NodeId(30)) (82 to 99) 32: InOutTypes([NodeId(23), NodeId(31)]) (56 to 101) 33: List([]) (103 to 104) diff --git a/src/snapshots/new_nu_parser__test__node_output@invalid_types.nu.snap b/src/snapshots/new_nu_parser__test__node_output@invalid_types.nu.snap index 84a69aa..50d2e5c 100644 --- a/src/snapshots/new_nu_parser__test__node_output@invalid_types.nu.snap +++ b/src/snapshots/new_nu_parser__test__node_output@invalid_types.nu.snap @@ -2,18 +2,17 @@ source: src/test.rs expression: evaluate_example(path) input_file: tests/invalid_types.nu -snapshot_kind: text --- ==== COMPILER ==== 0: Name (4 to 7) "foo" 1: Name (9 to 10) "x" 2: Name (12 to 16) "list" 3: Name (17 to 20) "int" -4: Type { name: NodeId(3), params: None, optional: false } (17 to 20) +4: Type { name: NodeId(3), args: None, optional: false } (17 to 20) 5: Name (22 to 28) "string" -6: Type { name: NodeId(5), params: None, optional: false } (22 to 28) -7: Params([NodeId(4), NodeId(6)]) (16 to 29) -8: Type { name: NodeId(2), params: Some(NodeId(7)), optional: false } (12 to 16) +6: Type { name: NodeId(5), args: None, optional: false } (22 to 28) +7: TypeArgs([NodeId(4), NodeId(6)]) (16 to 29) +8: Type { name: NodeId(2), args: Some(NodeId(7)), optional: false } (12 to 16) 9: Param { name: NodeId(1), ty: Some(NodeId(8)) } (9 to 16) 10: Params([NodeId(9)]) (8 to 30) 11: Variable (33 to 35) "$x" @@ -22,8 +21,8 @@ snapshot_kind: text 14: Name (42 to 45) "bar" 15: Name (47 to 48) "y" 16: Name (50 to 54) "list" -17: Params([]) (54 to 56) -18: Type { name: NodeId(16), params: Some(NodeId(17)), optional: false } (50 to 54) +17: TypeArgs([]) (54 to 56) +18: Type { name: NodeId(16), args: Some(NodeId(17)), optional: false } (50 to 54) 19: Param { name: NodeId(15), ty: Some(NodeId(18)) } (47 to 54) 20: Params([NodeId(19)]) (46 to 57) 21: Variable (60 to 62) "$y" @@ -64,8 +63,8 @@ snapshot_kind: text 23: () 24: () ==== TYPE ERRORS ==== -Error (NodeId 7): list must have only one type parameter (to allow selection of types, use oneof -- WIP) -Error (NodeId 17): list must have one type parameter +Error (NodeId 7): list must have only one type argument (to allow selection of types, use oneof -- WIP) +Error (NodeId 17): list must have one type argument ==== IR ==== register_count: 0 file_count: 0 diff --git a/src/snapshots/new_nu_parser__test__node_output@let_mismatch.nu.snap b/src/snapshots/new_nu_parser__test__node_output@let_mismatch.nu.snap index d7abbf5..e851998 100644 --- a/src/snapshots/new_nu_parser__test__node_output@let_mismatch.nu.snap +++ b/src/snapshots/new_nu_parser__test__node_output@let_mismatch.nu.snap @@ -2,33 +2,32 @@ source: src/test.rs expression: evaluate_example(path) input_file: tests/let_mismatch.nu -snapshot_kind: text --- ==== COMPILER ==== 0: Variable (4 to 5) "x" 1: Name (7 to 13) "number" -2: Type { name: NodeId(1), params: None, optional: false } (7 to 13) +2: Type { name: NodeId(1), args: None, optional: false } (7 to 13) 3: Int (16 to 18) "10" 4: Let { variable_name: NodeId(0), ty: Some(NodeId(2)), initializer: NodeId(3), is_mutable: false } (0 to 18) 5: Variable (32 to 33) "y" 6: Name (35 to 38) "any" -7: Type { name: NodeId(6), params: None, optional: false } (35 to 38) +7: Type { name: NodeId(6), args: None, optional: false } (35 to 38) 8: String (41 to 47) ""spam"" 9: Let { variable_name: NodeId(5), ty: Some(NodeId(7)), initializer: NodeId(8), is_mutable: false } (28 to 47) 10: Variable (60 to 61) "z" 11: Name (63 to 69) "string" -12: Type { name: NodeId(11), params: None, optional: false } (63 to 69) +12: Type { name: NodeId(11), args: None, optional: false } (63 to 69) 13: Int (72 to 75) "123" 14: Let { variable_name: NodeId(10), ty: Some(NodeId(12)), initializer: NodeId(13), is_mutable: false } (56 to 75) 15: Variable (91 to 92) "w" 16: Name (94 to 98) "list" 17: Name (99 to 103) "list" 18: Name (104 to 107) "int" -19: Type { name: NodeId(18), params: None, optional: false } (104 to 107) -20: Params([NodeId(19)]) (103 to 108) -21: Type { name: NodeId(17), params: Some(NodeId(20)), optional: false } (99 to 103) -22: Params([NodeId(21)]) (98 to 109) -23: Type { name: NodeId(16), params: Some(NodeId(22)), optional: false } (94 to 98) +19: Type { name: NodeId(18), args: None, optional: false } (104 to 107) +20: TypeArgs([NodeId(19)]) (103 to 108) +21: Type { name: NodeId(17), args: Some(NodeId(20)), optional: false } (99 to 103) +22: TypeArgs([NodeId(21)]) (98 to 109) +23: Type { name: NodeId(16), args: Some(NodeId(22)), optional: false } (94 to 98) 24: String (116 to 119) "'a'" 25: List([NodeId(24)]) (114 to 120) 26: List([NodeId(25)]) (112 to 122) diff --git a/src/snapshots/new_nu_parser__test__node_output@mut_.nu.snap b/src/snapshots/new_nu_parser__test__node_output@mut_.nu.snap index fdda7b3..a366991 100644 --- a/src/snapshots/new_nu_parser__test__node_output@mut_.nu.snap +++ b/src/snapshots/new_nu_parser__test__node_output@mut_.nu.snap @@ -2,12 +2,11 @@ source: src/test.rs expression: evaluate_example(path) input_file: tests/mut_.nu -snapshot_kind: text --- ==== COMPILER ==== 0: Variable (4 to 5) "x" 1: Name (7 to 10) "int" -2: Type { name: NodeId(1), params: None, optional: false } (7 to 10) +2: Type { name: NodeId(1), args: None, optional: false } (7 to 10) 3: Int (13 to 16) "123" 4: Let { variable_name: NodeId(0), ty: Some(NodeId(2)), initializer: NodeId(3), is_mutable: true } (0 to 16) 5: Variable (18 to 20) "$x" diff --git a/src/typechecker.rs b/src/typechecker.rs index c5d4ae5..d2b1562 100644 --- a/src/typechecker.rs +++ b/src/typechecker.rs @@ -225,12 +225,19 @@ impl<'a> Typechecker<'a> { } AstNode::Type { name, - params, + args, optional, } => { - let ty_id = self.typecheck_type(name, params, optional); + let ty_id = self.typecheck_type(name, args, optional); self.set_node_type_id(node_id, ty_id); } + AstNode::TypeArgs(ref args) => { + for arg in args { + self.typecheck_node(*arg); + } + // Type argument lists are not supposed to be evaluated + self.set_node_type_id(node_id, FORBIDDEN_TYPE); + } AstNode::List(ref items) => { if let Some(first_id) = items.first() { self.typecheck_node(*first_id); @@ -643,7 +650,7 @@ impl<'a> Typechecker<'a> { }; let AstNode::Type { name: in_name, - params: in_params, + args: in_args, optional: in_optional, } = *self.compiler.get_node(*in_ty) else { @@ -651,15 +658,15 @@ impl<'a> Typechecker<'a> { }; let AstNode::Type { name: out_name, - params: out_params, + args: out_args, optional: out_optional, } = *self.compiler.get_node(*out_ty) else { panic!("internal error: type is not a type"); }; InOutType { - in_type: self.typecheck_type(in_name, in_params, in_optional), - out_type: self.typecheck_type(out_name, out_params, out_optional), + in_type: self.typecheck_type(in_name, in_args, in_optional), + out_type: self.typecheck_type(out_name, out_args, out_optional), } }) .collect::>() @@ -767,7 +774,7 @@ impl<'a> Typechecker<'a> { fn typecheck_type( &mut self, name_id: NodeId, - params_id: Option, + args_id: Option, _optional: bool, ) -> TypeId { let name = self.compiler.get_span_contents(name_id); @@ -778,24 +785,24 @@ impl<'a> Typechecker<'a> { // b"binary" => SyntaxShape::Binary, // b"block" => // not possible to pass blocks b"list" => { - if let Some(params_id) = params_id { - self.typecheck_node(params_id); + if let Some(args_id) = args_id { + self.typecheck_node(args_id); - if let AstNode::Params(params) = self.compiler.get_node(params_id) { - if params.len() > 1 { + if let AstNode::TypeArgs(args) = self.compiler.get_node(args_id) { + if args.len() > 1 { let types = - String::from_utf8_lossy(self.compiler.get_span_contents(params_id)); - self.error(format!("list must have only one type parameter (to allow selection of types, use oneof{} -- WIP)", types), params_id); + String::from_utf8_lossy(self.compiler.get_span_contents(args_id)); + self.error(format!("list must have only one type argument (to allow selection of types, use oneof{} -- WIP)", types), args_id); self.push_type(Type::List(UNKNOWN_TYPE)) - } else if params.is_empty() { - self.error("list must have one type parameter", params_id); + } else if args.is_empty() { + self.error("list must have one type argument", args_id); self.push_type(Type::List(UNKNOWN_TYPE)) } else { - let params_ty_id = self.type_id_of(params[0]); - self.push_type(Type::List(params_ty_id)) + let args_ty_id = self.type_id_of(args[0]); + self.push_type(Type::List(args_ty_id)) } } else { - panic!("params are not params"); + panic!("args are not args"); } } else { LIST_ANY_TYPE