Просмотр исходного кода

Start adding var decls to semantics. (#2447)

This is just the declaration, without initialization. Partly breaking it out because I'm changing the placeholder builtin types.

Might also need to separate out storage of the var from the name bind.
Jon Ross-Perkins 3 лет назад
Родитель
Сommit
30960d11a9

+ 6 - 4
toolchain/semantics/semantics_builtin_kind.def

@@ -20,11 +20,13 @@ CARBON_SEMANTICS_BUILTIN_KIND(TypeType)
 // for future type checking.
 CARBON_SEMANTICS_BUILTIN_KIND(InvalidType)
 
-// The type of an integer literal.
-CARBON_SEMANTICS_BUILTIN_KIND(IntegerLiteralType)
+// The type of integers and integer literals, currently always i32. Long-term
+// we may not want it this way, but for now this is the approach.
+CARBON_SEMANTICS_BUILTIN_KIND(IntegerType)
 
-// The type of a real literal.
-CARBON_SEMANTICS_BUILTIN_KIND(RealLiteralType)
+// The type of reals and real literals, currently always f64. Long-term
+// we may not want it this way, but for now this is the approach.
+CARBON_SEMANTICS_BUILTIN_KIND(RealType)
 
 // Keep invalid last, so that we can use values as array indices without needing
 // an invalid entry.

+ 6 - 7
toolchain/semantics/semantics_ir.cpp

@@ -39,16 +39,15 @@ auto SemanticsIR::MakeBuiltinIR() -> SemanticsIR {
       << "InvalidType's type must be self-referential.";
 
   auto integer_literal_type = semantics.AddNode(
-      block_id, SemanticsNode::MakeBuiltin(
-                    SemanticsBuiltinKind::IntegerLiteralType(), type_type));
-  semantics
-      .cross_references_[SemanticsBuiltinKind::IntegerLiteralType().AsInt()] =
+      block_id, SemanticsNode::MakeBuiltin(SemanticsBuiltinKind::IntegerType(),
+                                           type_type));
+  semantics.cross_references_[SemanticsBuiltinKind::IntegerType().AsInt()] =
       SemanticsCrossReference(BuiltinIR, block_id, integer_literal_type);
 
   auto real_literal_type = semantics.AddNode(
-      block_id, SemanticsNode::MakeBuiltin(
-                    SemanticsBuiltinKind::RealLiteralType(), type_type));
-  semantics.cross_references_[SemanticsBuiltinKind::RealLiteralType().AsInt()] =
+      block_id,
+      SemanticsNode::MakeBuiltin(SemanticsBuiltinKind::RealType(), type_type));
+  semantics.cross_references_[SemanticsBuiltinKind::RealType().AsInt()] =
       SemanticsCrossReference(BuiltinIR, block_id, real_literal_type);
 
   CARBON_CHECK(semantics.node_blocks_.size() == 1)

+ 2 - 2
toolchain/semantics/semantics_node.h

@@ -148,7 +148,7 @@ class SemanticsNode {
       -> SemanticsNode {
     return SemanticsNode(parse_node, SemanticsNodeKind::IntegerLiteral(),
                          SemanticsNodeId::MakeBuiltinReference(
-                             SemanticsBuiltinKind::IntegerLiteralType()),
+                             SemanticsBuiltinKind::IntegerType()),
                          integer.index);
   }
   auto GetAsIntegerLiteral() const -> SemanticsIntegerLiteralId {
@@ -159,7 +159,7 @@ class SemanticsNode {
   static auto MakeRealLiteral(ParseTree::Node parse_node) -> SemanticsNode {
     return SemanticsNode(parse_node, SemanticsNodeKind::RealLiteral(),
                          SemanticsNodeId::MakeBuiltinReference(
-                             SemanticsBuiltinKind::RealLiteralType()));
+                             SemanticsBuiltinKind::RealType()));
   }
   auto GetAsRealLiteral() const -> NoArgs {
     CARBON_CHECK(kind_ == SemanticsNodeKind::RealLiteral());

+ 50 - 1
toolchain/semantics/semantics_parse_tree_handler.cpp

@@ -98,14 +98,23 @@ auto SemanticsParseTreeHandler::Build() -> void {
         HandleParameterList(parse_node);
         break;
       }
+      case ParseNodeKind::PatternBinding(): {
+        HandlePatternBinding(parse_node);
+        break;
+      }
       case ParseNodeKind::ReturnStatement(): {
         HandleReturnStatement(parse_node);
         break;
       }
+      case ParseNodeKind::VariableDeclaration(): {
+        HandleVariableDeclaration(parse_node);
+        break;
+      }
       case ParseNodeKind::DeclaredName():
       case ParseNodeKind::FunctionIntroducer():
       case ParseNodeKind::ParameterListStart():
-      case ParseNodeKind::ReturnStatementStart(): {
+      case ParseNodeKind::ReturnStatementStart():
+      case ParseNodeKind::VariableIntroducer(): {
         // The token has no action, but we still track it for the stack.
         Push(parse_node);
         break;
@@ -144,6 +153,16 @@ auto SemanticsParseTreeHandler::Push(ParseTree::Node parse_node,
   node_stack_.push_back({parse_node, node_id});
 }
 
+auto SemanticsParseTreeHandler::Push(ParseTree::Node parse_node,
+                                     SemanticsNodeId node_id) -> void {
+  CARBON_VLOG() << "Push " << node_stack_.size() << ": "
+                << parse_tree_->node_kind(parse_node) << " -> " << node_id
+                << "\n";
+  CARBON_CHECK(node_stack_.size() < (1 << 20))
+      << "Excessive stack size: likely infinite loop";
+  node_stack_.push_back({parse_node, node_id});
+}
+
 auto SemanticsParseTreeHandler::Pop(ParseNodeKind pop_parse_kind) -> void {
   auto back = node_stack_.pop_back_val();
   auto parse_kind = parse_tree_->node_kind(back.parse_node);
@@ -262,6 +281,13 @@ auto SemanticsParseTreeHandler::HandleLiteral(ParseTree::Node parse_node)
       Push(parse_node, SemanticsNode::MakeRealLiteral(parse_node));
       break;
     }
+    case TokenKind::IntegerTypeLiteral(): {
+      auto text = tokens_->GetTokenText(token);
+      CARBON_CHECK(text == "i32") << "Currently only i32 is allowed";
+      Push(parse_node, SemanticsNodeId::MakeBuiltinReference(
+                           SemanticsBuiltinKind::IntegerType()));
+      break;
+    }
     default:
       CARBON_FATAL() << "Unhandled kind: " << token_kind.Name();
   }
@@ -277,6 +303,20 @@ auto SemanticsParseTreeHandler::HandleParameterList(ParseTree::Node parse_node)
   Push(parse_node);
 }
 
+auto SemanticsParseTreeHandler::HandlePatternBinding(ParseTree::Node parse_node)
+    -> void {
+  // TODO: Create storage for the type, use that for the bind instead of the
+  // type itself.
+  auto type_id = PopWithResult();
+
+  auto name_node = node_stack_.back().parse_node;
+  auto name = AddIdentifier(name_node);
+  node_stack_.pop_back();
+
+  Push(parse_node,
+       AddNode(SemanticsNode::MakeBindName(name_node, name, type_id)));
+}
+
 auto SemanticsParseTreeHandler::HandleReturnStatement(
     ParseTree::Node parse_node) -> void {
   if (parse_tree_->node_kind(node_stack_.back().parse_node) ==
@@ -292,4 +332,13 @@ auto SemanticsParseTreeHandler::HandleReturnStatement(
   }
 }
 
+auto SemanticsParseTreeHandler::HandleVariableDeclaration(
+    ParseTree::Node parse_node) -> void {
+  // TODO: Initializers would assign to the PatternBinding, but this code
+  // doesn't handle it right now.
+  PopWithResult();
+  Pop(ParseNodeKind::VariableIntroducer());
+  Push(parse_node);
+}
+
 }  // namespace Carbon

+ 8 - 3
toolchain/semantics/semantics_parse_tree_handler.h

@@ -46,14 +46,17 @@ class SemanticsParseTreeHandler {
   // Adds a node to the current block, returning the produced ID.
   auto AddNode(SemanticsNode node) -> SemanticsNodeId;
 
-  // Pushes a parse tree onto the stack. Used when there is no IR generated by
-  // the node.
+  // Pushes a parse tree node onto the stack. Used when there is no IR generated
+  // by the node.
   auto Push(ParseTree::Node parse_node) -> void;
 
-  // Pushes a parse tree onto the stack, storing the SemanticsNode as the
+  // Pushes a parse tree node onto the stack, storing the SemanticsNode as the
   // result.
   auto Push(ParseTree::Node parse_node, SemanticsNode node) -> void;
 
+  // Pushes a parse tree node onto the stack with an already-built node ID.
+  auto Push(ParseTree::Node parse_node, SemanticsNodeId node_id) -> void;
+
   // Pops the top of the stack, verifying that it's the expected kind.
   auto Pop(ParseNodeKind pop_parse_kind) -> void;
 
@@ -72,7 +75,9 @@ class SemanticsParseTreeHandler {
   auto HandleInfixOperator(ParseTree::Node parse_node) -> void;
   auto HandleLiteral(ParseTree::Node parse_node) -> void;
   auto HandleParameterList(ParseTree::Node parse_node) -> void;
+  auto HandlePatternBinding(ParseTree::Node parse_node) -> void;
   auto HandleReturnStatement(ParseTree::Node parse_node) -> void;
+  auto HandleVariableDeclaration(ParseTree::Node parse_node) -> void;
 
   // Tokens for getting data on literals.
   const TokenizedBuffer* tokens_;

+ 25 - 0
toolchain/semantics/testdata/var/decl.carbon

@@ -0,0 +1,25 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// AUTOUPDATE
+// RUN: %{carbon-run-semantics}
+// CHECK:STDOUT: cross_reference_irs.size == 2,
+// CHECK:STDOUT: cross_references = {
+// CHECK:STDOUT:   node_xref0 = xref(ir0, block0, node0);
+// CHECK:STDOUT:   node_xref1 = xref(ir0, block0, node1);
+// CHECK:STDOUT:   node_xref2 = xref(ir0, block0, node2);
+// CHECK:STDOUT:   node_xref3 = xref(ir0, block0, node3);
+// CHECK:STDOUT: },
+// CHECK:STDOUT: identifiers = {
+// CHECK:STDOUT:   ident0 = "x";
+// CHECK:STDOUT: },
+// CHECK:STDOUT: integer_literals = {
+// CHECK:STDOUT: },
+// CHECK:STDOUT: node_blocks = {
+// CHECK:STDOUT:   block0 = {
+// CHECK:STDOUT:     node0 = BindName(ident0, node_xref2);
+// CHECK:STDOUT:   },
+// CHECK:STDOUT: }
+
+var x: i32;

+ 33 - 0
toolchain/semantics/testdata/var/global_decl.carbon

@@ -0,0 +1,33 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// AUTOUPDATE
+// RUN: %{carbon-run-semantics}
+// CHECK:STDOUT: cross_reference_irs.size == 2,
+// CHECK:STDOUT: cross_references = {
+// CHECK:STDOUT:   node_xref0 = xref(ir0, block0, node0);
+// CHECK:STDOUT:   node_xref1 = xref(ir0, block0, node1);
+// CHECK:STDOUT:   node_xref2 = xref(ir0, block0, node2);
+// CHECK:STDOUT:   node_xref3 = xref(ir0, block0, node3);
+// CHECK:STDOUT: },
+// CHECK:STDOUT: identifiers = {
+// CHECK:STDOUT:   ident0 = "Main";
+// CHECK:STDOUT:   ident1 = "x";
+// CHECK:STDOUT: },
+// CHECK:STDOUT: integer_literals = {
+// CHECK:STDOUT: },
+// CHECK:STDOUT: node_blocks = {
+// CHECK:STDOUT:   block0 = {
+// CHECK:STDOUT:     node0 = FunctionDeclaration();
+// CHECK:STDOUT:     node1 = BindName(ident0, node0);
+// CHECK:STDOUT:     node2 = FunctionDefinition(node0, block1);
+// CHECK:STDOUT:   },
+// CHECK:STDOUT:   block1 = {
+// CHECK:STDOUT:     node0 = BindName(ident1, node_xref2);
+// CHECK:STDOUT:   },
+// CHECK:STDOUT: }
+
+fn Main() {
+  var x: i32;
+}