|
@@ -9,6 +9,7 @@
|
|
|
|
|
|
|
|
#include "common/vlog.h"
|
|
#include "common/vlog.h"
|
|
|
#include "llvm/Support/PrettyStackTrace.h"
|
|
#include "llvm/Support/PrettyStackTrace.h"
|
|
|
|
|
+#include "toolchain/diagnostics/diagnostic_kind.h"
|
|
|
#include "toolchain/lexer/token_kind.h"
|
|
#include "toolchain/lexer/token_kind.h"
|
|
|
#include "toolchain/lexer/tokenized_buffer.h"
|
|
#include "toolchain/lexer/tokenized_buffer.h"
|
|
|
#include "toolchain/parser/parse_node_kind.h"
|
|
#include "toolchain/parser/parse_node_kind.h"
|
|
@@ -320,7 +321,7 @@ auto SemanticsParseTreeHandler::HandleCallExpression(ParseTree::Node parse_node)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
auto callable_id = name_node.GetAsFunctionDeclaration();
|
|
auto callable_id = name_node.GetAsFunctionDeclaration();
|
|
|
- auto callable = semantics_->callables_[callable_id.index];
|
|
|
|
|
|
|
+ auto callable = semantics_->GetCallable(callable_id);
|
|
|
|
|
|
|
|
if (!TryTypeConversionOnArgs(call_expr_parse_node, ir_id, refs_id,
|
|
if (!TryTypeConversionOnArgs(call_expr_parse_node, ir_id, refs_id,
|
|
|
name_node.parse_node(),
|
|
name_node.parse_node(),
|
|
@@ -474,6 +475,7 @@ auto SemanticsParseTreeHandler::HandleFunctionDefinition(
|
|
|
auto decl_id =
|
|
auto decl_id =
|
|
|
node_stack_.PopForNodeId(ParseNodeKind::FunctionDefinitionStart);
|
|
node_stack_.PopForNodeId(ParseNodeKind::FunctionDefinitionStart);
|
|
|
|
|
|
|
|
|
|
+ return_scope_stack_.pop_back();
|
|
|
PopScope();
|
|
PopScope();
|
|
|
auto block_id = node_block_stack_.Pop();
|
|
auto block_id = node_block_stack_.Pop();
|
|
|
AddNode(SemanticsNode::MakeFunctionDefinition(parse_node, decl_id, block_id));
|
|
AddNode(SemanticsNode::MakeFunctionDefinition(parse_node, decl_id, block_id));
|
|
@@ -484,14 +486,21 @@ auto SemanticsParseTreeHandler::HandleFunctionDefinition(
|
|
|
|
|
|
|
|
auto SemanticsParseTreeHandler::HandleFunctionDefinitionStart(
|
|
auto SemanticsParseTreeHandler::HandleFunctionDefinitionStart(
|
|
|
ParseTree::Node parse_node) -> bool {
|
|
ParseTree::Node parse_node) -> bool {
|
|
|
|
|
+ SemanticsNodeId return_type_id = SemanticsNodeId::Invalid;
|
|
|
|
|
+ if (parse_tree_->node_kind(node_stack_.PeekParseNode()) ==
|
|
|
|
|
+ ParseNodeKind::ReturnType) {
|
|
|
|
|
+ return_type_id = node_stack_.PopForNodeId(ParseNodeKind::ReturnType);
|
|
|
|
|
+ }
|
|
|
node_stack_.PopForSoloParseNode(ParseNodeKind::ParameterList);
|
|
node_stack_.PopForSoloParseNode(ParseNodeKind::ParameterList);
|
|
|
auto [param_ir_id, param_refs_id] = finished_params_stack_.pop_back_val();
|
|
auto [param_ir_id, param_refs_id] = finished_params_stack_.pop_back_val();
|
|
|
auto name_node = node_stack_.PopForSoloParseNode(ParseNodeKind::DeclaredName);
|
|
auto name_node = node_stack_.PopForSoloParseNode(ParseNodeKind::DeclaredName);
|
|
|
auto fn_node =
|
|
auto fn_node =
|
|
|
node_stack_.PopForSoloParseNode(ParseNodeKind::FunctionIntroducer);
|
|
node_stack_.PopForSoloParseNode(ParseNodeKind::FunctionIntroducer);
|
|
|
|
|
|
|
|
- auto callable_id = semantics_->AddCallable(
|
|
|
|
|
- {.param_ir_id = param_ir_id, .param_refs_id = param_refs_id});
|
|
|
|
|
|
|
+ auto callable_id =
|
|
|
|
|
+ semantics_->AddCallable({.param_ir_id = param_ir_id,
|
|
|
|
|
+ .param_refs_id = param_refs_id,
|
|
|
|
|
+ .return_type_id = return_type_id});
|
|
|
auto decl_id =
|
|
auto decl_id =
|
|
|
AddNode(SemanticsNode::MakeFunctionDeclaration(fn_node, callable_id));
|
|
AddNode(SemanticsNode::MakeFunctionDeclaration(fn_node, callable_id));
|
|
|
// TODO: Propagate the type of the function.
|
|
// TODO: Propagate the type of the function.
|
|
@@ -499,6 +508,7 @@ auto SemanticsParseTreeHandler::HandleFunctionDefinitionStart(
|
|
|
|
|
|
|
|
node_block_stack_.Push();
|
|
node_block_stack_.Push();
|
|
|
PushScope();
|
|
PushScope();
|
|
|
|
|
+ return_scope_stack_.push_back(decl_id);
|
|
|
node_stack_.Push(parse_node, decl_id);
|
|
node_stack_.Push(parse_node, decl_id);
|
|
|
|
|
|
|
|
return true;
|
|
return true;
|
|
@@ -772,14 +782,57 @@ auto SemanticsParseTreeHandler::HandlePrefixOperator(ParseTree::Node parse_node)
|
|
|
|
|
|
|
|
auto SemanticsParseTreeHandler::HandleReturnStatement(
|
|
auto SemanticsParseTreeHandler::HandleReturnStatement(
|
|
|
ParseTree::Node parse_node) -> bool {
|
|
ParseTree::Node parse_node) -> bool {
|
|
|
|
|
+ CARBON_CHECK(!return_scope_stack_.empty());
|
|
|
|
|
+ const auto& fn_node = semantics_->GetNode(return_scope_stack_.back());
|
|
|
|
|
+ const auto callable =
|
|
|
|
|
+ semantics_->GetCallable(fn_node.GetAsFunctionDeclaration());
|
|
|
|
|
+
|
|
|
if (parse_tree_->node_kind(node_stack_.PeekParseNode()) ==
|
|
if (parse_tree_->node_kind(node_stack_.PeekParseNode()) ==
|
|
|
ParseNodeKind::ReturnStatementStart) {
|
|
ParseNodeKind::ReturnStatementStart) {
|
|
|
node_stack_.PopAndDiscardSoloParseNode(ParseNodeKind::ReturnStatementStart);
|
|
node_stack_.PopAndDiscardSoloParseNode(ParseNodeKind::ReturnStatementStart);
|
|
|
|
|
+
|
|
|
|
|
+ if (callable.return_type_id.is_valid()) {
|
|
|
|
|
+ // TODO: Stringify types, add a note pointing at the return
|
|
|
|
|
+ // type's parse node.
|
|
|
|
|
+ CARBON_DIAGNOSTIC(ReturnStatementMissingExpression, Error,
|
|
|
|
|
+ "Must return a {0}.", SemanticsNodeId);
|
|
|
|
|
+ emitter_
|
|
|
|
|
+ ->Build(parse_node, ReturnStatementMissingExpression,
|
|
|
|
|
+ callable.return_type_id)
|
|
|
|
|
+ .Emit();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
AddNodeAndPush(parse_node, SemanticsNode::MakeReturn(parse_node));
|
|
AddNodeAndPush(parse_node, SemanticsNode::MakeReturn(parse_node));
|
|
|
} else {
|
|
} else {
|
|
|
- auto arg = node_stack_.PopForNodeId();
|
|
|
|
|
|
|
+ const auto arg = node_stack_.PopForNodeId();
|
|
|
auto arg_type = semantics_->GetType(arg);
|
|
auto arg_type = semantics_->GetType(arg);
|
|
|
node_stack_.PopAndDiscardSoloParseNode(ParseNodeKind::ReturnStatementStart);
|
|
node_stack_.PopAndDiscardSoloParseNode(ParseNodeKind::ReturnStatementStart);
|
|
|
|
|
+
|
|
|
|
|
+ if (!callable.return_type_id.is_valid()) {
|
|
|
|
|
+ CARBON_DIAGNOSTIC(
|
|
|
|
|
+ ReturnStatementDisallowExpression, Error,
|
|
|
|
|
+ "No return expression should be provided in this context.");
|
|
|
|
|
+ CARBON_DIAGNOSTIC(ReturnStatementImplicitNote, Note,
|
|
|
|
|
+ "There was no return type provided.");
|
|
|
|
|
+ emitter_->Build(parse_node, ReturnStatementDisallowExpression)
|
|
|
|
|
+ .Note(fn_node.parse_node(), ReturnStatementImplicitNote)
|
|
|
|
|
+ .Emit();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const auto new_type = CanTypeConvert(arg_type, callable.return_type_id);
|
|
|
|
|
+ if (!new_type.is_valid()) {
|
|
|
|
|
+ // TODO: Stringify types, add a note pointing at the return
|
|
|
|
|
+ // type's parse node.
|
|
|
|
|
+ CARBON_DIAGNOSTIC(ReturnStatementTypeMismatch, Error,
|
|
|
|
|
+ "Cannot convert {0} to {1}.", SemanticsNodeId,
|
|
|
|
|
+ SemanticsNodeId);
|
|
|
|
|
+ emitter_
|
|
|
|
|
+ ->Build(parse_node, ReturnStatementTypeMismatch, arg_type,
|
|
|
|
|
+ callable.return_type_id)
|
|
|
|
|
+ .Emit();
|
|
|
|
|
+ }
|
|
|
|
|
+ arg_type = new_type;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
AddNodeAndPush(parse_node, SemanticsNode::MakeReturnExpression(
|
|
AddNodeAndPush(parse_node, SemanticsNode::MakeReturnExpression(
|
|
|
parse_node, arg_type, arg));
|
|
parse_node, arg_type, arg));
|
|
|
}
|
|
}
|
|
@@ -795,8 +848,9 @@ auto SemanticsParseTreeHandler::HandleReturnStatementStart(
|
|
|
|
|
|
|
|
auto SemanticsParseTreeHandler::HandleReturnType(ParseTree::Node parse_node)
|
|
auto SemanticsParseTreeHandler::HandleReturnType(ParseTree::Node parse_node)
|
|
|
-> bool {
|
|
-> bool {
|
|
|
- emitter_->Emit(parse_node, SemanticsTodo, "HandleReturnType");
|
|
|
|
|
- return false;
|
|
|
|
|
|
|
+ // Propagate the type expression.
|
|
|
|
|
+ node_stack_.Push(parse_node, node_stack_.PopForNodeId());
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
auto SemanticsParseTreeHandler::HandleSelfDeducedParameter(
|
|
auto SemanticsParseTreeHandler::HandleSelfDeducedParameter(
|