-
Notifications
You must be signed in to change notification settings - Fork 9
Parse command return types #46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4e111ae
c2d77b5
a823fee
2c44371
1e4d40a
7374a0e
56bd2e1
c0f670e
374e409
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| --- | ||
| source: src/test.rs | ||
| expression: evaluate_example(path) | ||
| input_file: tests/def_return_type.nu | ||
| --- | ||
| ==== 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) | ||
| 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) | ||
| 9: InOutType(NodeId(3), NodeId(8)) (14 to 35) | ||
| 10: InOutTypes([NodeId(9)]) (14 to 35) | ||
| 11: List([]) (37 to 38) | ||
| 12: Block(BlockId(0)) (35 to 41) | ||
| 13: Def { name: NodeId(0), params: NodeId(1), return_ty: Some(NodeId(10)), block: NodeId(12) } (0 to 41) | ||
| 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) | ||
| 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) | ||
| 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) | ||
| 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) | ||
| 31: InOutType(NodeId(25), NodeId(30)) (82 to 99) | ||
| 32: InOutTypes([NodeId(23), NodeId(31)]) (56 to 101) | ||
| 33: List([]) (103 to 104) | ||
| 34: Block(BlockId(1)) (101 to 107) | ||
| 35: Def { name: NodeId(14), params: NodeId(15), return_ty: Some(NodeId(32)), block: NodeId(34) } (42 to 107) | ||
| 36: Block(BlockId(2)) (0 to 108) | ||
| ==== SCOPE ==== | ||
| 0: Frame Scope, node_id: NodeId(36) | ||
| decls: [ bar: NodeId(14), foo: NodeId(0) ] | ||
| 1: Frame Scope, node_id: NodeId(12) (empty) | ||
| 2: Frame Scope, node_id: NodeId(34) (empty) | ||
| ==== TYPES ==== | ||
| 0: unknown | ||
| 1: forbidden | ||
| 2: unknown | ||
| 3: unknown | ||
| 4: unknown | ||
| 5: unknown | ||
| 6: any | ||
| 7: forbidden | ||
| 8: unknown | ||
| 9: unknown | ||
| 10: unknown | ||
| 11: list<any> | ||
| 12: list<any> | ||
| 13: () | ||
| 14: unknown | ||
| 15: forbidden | ||
| 16: unknown | ||
| 17: unknown | ||
| 18: unknown | ||
| 19: unknown | ||
| 20: string | ||
| 21: forbidden | ||
| 22: unknown | ||
| 23: unknown | ||
| 24: unknown | ||
| 25: unknown | ||
| 26: unknown | ||
| 27: unknown | ||
| 28: int | ||
| 29: forbidden | ||
| 30: unknown | ||
| 31: unknown | ||
| 32: unknown | ||
| 33: list<any> | ||
| 34: list<any> | ||
| 35: () | ||
| 36: () |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -626,10 +626,46 @@ impl<'a> Typechecker<'a> { | |
| &mut self, | ||
| name: NodeId, | ||
| params: NodeId, | ||
| _return_ty: Option<NodeId>, | ||
| return_ty: Option<NodeId>, | ||
| block: NodeId, | ||
| node_id: NodeId, | ||
| ) { | ||
| let return_ty = return_ty | ||
| .map(|ty| { | ||
| let AstNode::InOutTypes(types) = self.compiler.get_node(ty) else { | ||
| panic!("internal error: return type is not a return type"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This pattern is repeated a lot and is kind of unwieldy. It could use some helper or API refactor. Just a note for the future.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah. I was thinking about a macro
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking along the lines that if we made each AST node its own type, we could use generics, similar to this solution. That would also allow us to deduplicate all the I'm not a fan of macros since they have different syntax from the rest of Rust, and they can make code hard to read, but sometimes they're helpful. |
||
| }; | ||
| types | ||
| .iter() | ||
| .map(|ty| { | ||
| let AstNode::InOutType(in_ty, out_ty) = self.compiler.get_node(*ty) else { | ||
| panic!("internal error: return type is not a return type"); | ||
| }; | ||
| let AstNode::Type { | ||
| name: in_name, | ||
| params: in_params, | ||
| optional: in_optional, | ||
| } = *self.compiler.get_node(*in_ty) | ||
| else { | ||
| panic!("internal error: type is not a type"); | ||
| }; | ||
| let AstNode::Type { | ||
| name: out_name, | ||
| params: out_params, | ||
| 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), | ||
| } | ||
| }) | ||
| .collect::<Vec<_>>() | ||
| }) | ||
| .unwrap_or_default(); | ||
|
|
||
| self.typecheck_node(params); | ||
| self.typecheck_node(block); | ||
| self.set_node_type_id(node_id, NONE_TYPE); | ||
|
|
@@ -641,10 +677,15 @@ impl<'a> Typechecker<'a> { | |
| .get(&name) | ||
| .expect("missing declared decl"); | ||
|
|
||
| self.decl_types[decl_id.0] = vec![InOutType { | ||
| in_type: ANY_TYPE, | ||
| out_type: self.type_id_of(block), | ||
| }]; | ||
| if return_ty.is_empty() { | ||
| self.decl_types[decl_id.0] = vec![InOutType { | ||
| in_type: ANY_TYPE, | ||
| out_type: self.type_id_of(block), | ||
| }]; | ||
| } else { | ||
| // TODO check that block output type matches expected type | ||
| self.decl_types[decl_id.0] = return_ty; | ||
| } | ||
| } | ||
|
|
||
| fn typecheck_alias(&mut self, new_name: NodeId, old_name: NodeId, node_id: NodeId) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| def foo [ ] : nothing -> list<any> { [] } | ||
| def bar [ ] : [ string -> list<string>, int -> list<int> ] { [] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the
return_tycan be renamed toinout_typesor similar at this point.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I'll update
Defif I make a PR in the future related to it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#51