Parcourir la source

Semantics & Lowering for simple assignment. (#3058)

Co-authored-by: Farzana Ahmed Siddique <fasiddique@google.com>
Farzana Ahmed Siddique il y a 2 ans
Parent
commit
ce459d4da7

+ 37 - 0
toolchain/lowering/testdata/operators/assignment.carbon

@@ -0,0 +1,37 @@
+// 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
+// CHECK:STDOUT: ; ModuleID = 'assignment.carbon'
+// CHECK:STDOUT: source_filename = "assignment.carbon"
+// CHECK:STDOUT:
+// CHECK:STDOUT: %TupleLiteralType = type { {}, {} }
+// CHECK:STDOUT: %TupleLiteralType.0 = type { i32, i32 }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @Main() {
+// CHECK:STDOUT:   %var = alloca i32, align 4
+// CHECK:STDOUT:   store i32 12, ptr %var, align 4
+// CHECK:STDOUT:   store i32 -7, ptr %var, align 4
+// CHECK:STDOUT:   %TupleLiteralValue = alloca %TupleLiteralType, align 8
+// CHECK:STDOUT:   %1 = getelementptr inbounds %TupleLiteralType, ptr %TupleLiteralValue, i32 0, i32 0
+// CHECK:STDOUT:   store {} zeroinitializer, ptr %1, align 1
+// CHECK:STDOUT:   %2 = getelementptr inbounds %TupleLiteralType, ptr %TupleLiteralValue, i32 0, i32 1
+// CHECK:STDOUT:   store {} zeroinitializer, ptr %2, align 1
+// CHECK:STDOUT:   %var1 = alloca %TupleLiteralType.0, align 8
+// CHECK:STDOUT:   %TupleLiteralValue2 = alloca %TupleLiteralType.0, align 8
+// CHECK:STDOUT:   %3 = getelementptr inbounds %TupleLiteralType.0, ptr %TupleLiteralValue2, i32 0, i32 0
+// CHECK:STDOUT:   store i32 1, ptr %3, align 4
+// CHECK:STDOUT:   %4 = getelementptr inbounds %TupleLiteralType.0, ptr %TupleLiteralValue2, i32 0, i32 1
+// CHECK:STDOUT:   store i32 2, ptr %4, align 4
+// CHECK:STDOUT:   %5 = load %TupleLiteralType.0, ptr %TupleLiteralValue2, align 4
+// CHECK:STDOUT:   store %TupleLiteralType.0 %5, ptr %var1, align 4
+// CHECK:STDOUT:   ret void
+// CHECK:STDOUT: }
+
+fn Main() {
+  var a: i32 = 12;
+  a = 9;
+  var b: (i32, i32);
+  b = (1, 2);
+}

+ 9 - 1
toolchain/semantics/semantics_handle_operator.cpp

@@ -51,7 +51,15 @@ auto SemanticsHandleInfixOperator(SemanticsContext& context,
               resume_block_id));
       return true;
     }
-
+    case TokenKind::Equal: {
+      // TODO: handle complex assignment expression such as `a += 1`.
+      // TODO: check if lhs node is assignable.
+      context.ImplicitAsRequired(
+          parse_node, rhs_id, context.semantics_ir().GetNode(lhs_id).type_id());
+      context.AddNodeAndPush(
+          parse_node, SemanticsNode::Assign::Make(parse_node, lhs_id, rhs_id));
+      return true;
+    }
     default:
       return context.TODO(parse_node, llvm::formatv("Handle {0}", token_kind));
   }

+ 55 - 0
toolchain/semantics/testdata/operators/assignment.carbon

@@ -0,0 +1,55 @@
+// 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
+// CHECK:STDOUT: cross_reference_irs_size: 1
+// CHECK:STDOUT: functions: [
+// CHECK:STDOUT:   {name: str0, param_refs: block0, body: {block2}}},
+// CHECK:STDOUT: ]
+// CHECK:STDOUT: integer_literals: [
+// CHECK:STDOUT:   12,
+// CHECK:STDOUT:   -7,
+// CHECK:STDOUT: ]
+// CHECK:STDOUT: real_literals: [
+// CHECK:STDOUT: ]
+// CHECK:STDOUT: strings: [
+// CHECK:STDOUT:   Main,
+// CHECK:STDOUT:   a,
+// CHECK:STDOUT: ]
+// CHECK:STDOUT: types: [
+// CHECK:STDOUT:   nodeIntegerType,
+// CHECK:STDOUT: ]
+// CHECK:STDOUT: type_blocks: [
+// CHECK:STDOUT: ]
+// CHECK:STDOUT: nodes: [
+// CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type0},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type0},
+// CHECK:STDOUT:   {kind: Assign, arg0: node+1, arg1: node+3},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type0},
+// CHECK:STDOUT:   {kind: Assign, arg0: node+1, arg1: node+5},
+// CHECK:STDOUT:   {kind: Return},
+// CHECK:STDOUT: ]
+// CHECK:STDOUT: node_blocks: [
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:   ],
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:     node+0,
+// CHECK:STDOUT:   ],
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:     node+1,
+// CHECK:STDOUT:     node+2,
+// CHECK:STDOUT:     node+3,
+// CHECK:STDOUT:     node+4,
+// CHECK:STDOUT:     node+5,
+// CHECK:STDOUT:     node+6,
+// CHECK:STDOUT:     node+7,
+// CHECK:STDOUT:   ],
+// CHECK:STDOUT: ]
+
+fn Main() {
+  var a: i32 = 12;
+  a = 9;
+}

+ 59 - 0
toolchain/semantics/testdata/operators/fail_type_mismatch_assignment.carbon

@@ -0,0 +1,59 @@
+// 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
+// CHECK:STDOUT: cross_reference_irs_size: 1
+// CHECK:STDOUT: functions: [
+// CHECK:STDOUT:   {name: str0, param_refs: block0, body: {block2}}},
+// CHECK:STDOUT: ]
+// CHECK:STDOUT: integer_literals: [
+// CHECK:STDOUT:   3,
+// CHECK:STDOUT: ]
+// CHECK:STDOUT: real_literals: [
+// CHECK:STDOUT:   {mantissa: 56, exponent: -1, is_decimal: 1},
+// CHECK:STDOUT: ]
+// CHECK:STDOUT: strings: [
+// CHECK:STDOUT:   Main,
+// CHECK:STDOUT:   a,
+// CHECK:STDOUT: ]
+// CHECK:STDOUT: types: [
+// CHECK:STDOUT:   nodeIntegerType,
+// CHECK:STDOUT:   nodeFloatingPointType,
+// CHECK:STDOUT: ]
+// CHECK:STDOUT: type_blocks: [
+// CHECK:STDOUT: ]
+// CHECK:STDOUT: nodes: [
+// CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type0},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type0},
+// CHECK:STDOUT:   {kind: Assign, arg0: node+1, arg1: node+3},
+// CHECK:STDOUT:   {kind: RealLiteral, arg0: real0, type: type1},
+// CHECK:STDOUT:   {kind: Assign, arg0: node+1, arg1: node+5},
+// CHECK:STDOUT:   {kind: Return},
+// CHECK:STDOUT: ]
+// CHECK:STDOUT: node_blocks: [
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:   ],
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:     node+0,
+// CHECK:STDOUT:   ],
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:     node+1,
+// CHECK:STDOUT:     node+2,
+// CHECK:STDOUT:     node+3,
+// CHECK:STDOUT:     node+4,
+// CHECK:STDOUT:     node+5,
+// CHECK:STDOUT:     node+6,
+// CHECK:STDOUT:     node+7,
+// CHECK:STDOUT:   ],
+// CHECK:STDOUT: ]
+
+fn Main() {
+  var a: i32 = 3;
+  // CHECK:STDERR: fail_type_mismatch_assignment.carbon:[[@LINE+3]]:5: Cannot implicitly convert from `f64` to `i32`.
+  // CHECK:STDERR:   a = 5.6;
+  // CHECK:STDERR:     ^
+  a = 5.6;
+}