Skip to content

Commit

Permalink
Adds division to multiplicative expression. (#2091)
Browse files Browse the repository at this point in the history
* Multiplication and division have the same priority.
* A new builtin interface DivWith is added.
* In some tests expecting a compilation error (syntax error), the error
  message now says it is expecting SLASH or binary *.
  • Loading branch information
junheecho authored Sep 19, 2022
1 parent 57cc4c6 commit 69d4363
Show file tree
Hide file tree
Showing 15 changed files with 89 additions and 8 deletions.
1 change: 1 addition & 0 deletions common/fuzzing/carbon.proto
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ message OperatorExpression {
Greater = 22;
GreaterEq = 23;
NotEq = 24;
Div = 25;
}
optional Operator op = 1;
repeated Expression arguments = 2;
Expand Down
4 changes: 4 additions & 0 deletions common/fuzzing/proto_to_carbon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ static auto OperatorToCarbon(const Fuzzing::OperatorExpression& operator_expr,
BinaryOperatorToCarbon(arg0, " * ", arg1, out);
break;

case Fuzzing::OperatorExpression::Div:
BinaryOperatorToCarbon(arg0, " / ", arg1, out);
break;

case Fuzzing::OperatorExpression::Mod:
BinaryOperatorToCarbon(arg0, " % ", arg1, out);
break;
Expand Down
2 changes: 2 additions & 0 deletions explorer/ast/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ auto ToString(Operator op) -> std::string_view {
return "<<";
case Operator::BitShiftRight:
return ">>";
case Operator::Div:
return "/";
case Operator::Neg:
case Operator::Sub:
return "-";
Expand Down
1 change: 1 addition & 0 deletions explorer/ast/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ enum class Operator {
BitShiftRight,
Complement,
Deref,
Div,
Eq,
Less,
LessEq,
Expand Down
10 changes: 10 additions & 0 deletions explorer/data/prelude.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,13 @@ interface MulWith(U:! Type) {
}
// TODO: constraint Mul { ... }

interface DivWith(U:! Type) {
// TODO: = Self
let Result:! Type;
fn Op[me: Self](other: U) -> Result;
}
// TODO: constraint Div { ... }

interface ModWith(U:! Type) {
// TODO: = Self
let Result:! Type;
Expand All @@ -337,6 +344,9 @@ external impl i32 as SubWith(i32) where .Result == i32 {
external impl i32 as MulWith(i32) where .Result == i32 {
fn Op[me: i32](other: i32) -> i32 { return me * other; }
}
external impl i32 as DivWith(i32) where .Result == i32 {
fn Op[me: i32](other: i32) -> i32 { return me / other; }
}
external impl i32 as ModWith(i32) where .Result == i32 {
fn Op[me: i32](other: i32) -> i32 { return me % other; }
}
Expand Down
2 changes: 2 additions & 0 deletions explorer/fuzzing/ast_to_proto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ static auto OperatorToProtoEnum(const Operator op)
return Fuzzing::OperatorExpression::GreaterEq;
case Operator::Mul:
return Fuzzing::OperatorExpression::Mul;
case Operator::Div:
return Fuzzing::OperatorExpression::Div;
case Operator::Mod:
return Fuzzing::OperatorExpression::Mod;
case Operator::Or:
Expand Down
12 changes: 7 additions & 5 deletions explorer/interpreter/builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class Builtins {
AddWith,
SubWith,
MulWith,
DivWith,
ModWith,

// Bitwise and shift.
Expand All @@ -64,6 +65,7 @@ class Builtins {
static constexpr Builtin AddWith = Builtin::AddWith;
static constexpr Builtin SubWith = Builtin::SubWith;
static constexpr Builtin MulWith = Builtin::MulWith;
static constexpr Builtin DivWith = Builtin::DivWith;
static constexpr Builtin ModWith = Builtin::ModWith;
static constexpr Builtin BitComplement = Builtin::BitComplement;
static constexpr Builtin BitAndWith = Builtin::BitAndWith;
Expand All @@ -88,11 +90,11 @@ class Builtins {
private:
static constexpr int NumBuiltins = static_cast<int>(Builtin::Last) + 1;
static constexpr const char* BuiltinNames[NumBuiltins] = {
"As", "ImplicitAs", "EqWith", "LessWith",
"LessEqWith", "GreaterWith", "GreaterEqWith", "CompareWith",
"Negate", "AddWith", "SubWith", "MulWith",
"ModWith", "BitComplement", "BitAndWith", "BitOrWith",
"BitXorWith", "LeftShiftWith", "RightShiftWith"};
"As", "ImplicitAs", "EqWith", "LessWith",
"LessEqWith", "GreaterWith", "GreaterEqWith", "CompareWith",
"Negate", "AddWith", "SubWith", "MulWith",
"DivWith", "ModWith", "BitComplement", "BitAndWith",
"BitOrWith", "BitXorWith", "LeftShiftWith", "RightShiftWith"};

std::optional<Nonnull<const Declaration*>> builtins_[NumBuiltins] = {};
};
Expand Down
3 changes: 3 additions & 0 deletions explorer/interpreter/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ auto Interpreter::EvalPrim(Operator op, Nonnull<const Value*> static_type,
case Operator::Mul:
return arena_->New<IntValue>(cast<IntValue>(*args[0]).value() *
cast<IntValue>(*args[1]).value());
case Operator::Div:
return arena_->New<IntValue>(cast<IntValue>(*args[0]).value() /
cast<IntValue>(*args[1]).value());
case Operator::Mod:
return arena_->New<IntValue>(cast<IntValue>(*args[0]).value() %
cast<IntValue>(*args[1]).value());
Expand Down
2 changes: 2 additions & 0 deletions explorer/interpreter/type_checker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2061,6 +2061,8 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
return handle_binary_arithmetic(Builtins::SubWith);
case Operator::Mul:
return handle_binary_arithmetic(Builtins::MulWith);
case Operator::Div:
return handle_binary_arithmetic(Builtins::DivWith);
case Operator::Mod:
return handle_binary_arithmetic(Builtins::ModWith);
case Operator::BitwiseAnd:
Expand Down
6 changes: 6 additions & 0 deletions explorer/syntax/parser.ypp
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,12 @@ multiplicative_expression:
context.source_loc(), Operator::Mul,
std::vector<Nonnull<Expression*>>({$1, $3}));
}
| multiplicative_lhs SLASH simple_binary_operand
{
$$ = arena->New<OperatorExpression>(
context.source_loc(), Operator::Div,
std::vector<Nonnull<Expression*>>({$1, $3}));
}
;
additive_operand:
simple_binary_operand
Expand Down
2 changes: 1 addition & 1 deletion explorer/testdata/basic_syntax/fail_missing_var.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ package ExplorerTest api;

fn Main() -> i32 {
// error
// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_missing_var.carbon:[[@LINE+1]]: syntax error, unexpected COLON, expecting EQUAL or SEMICOLON
// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_missing_var.carbon:[[@LINE+1]]: syntax error, unexpected COLON, expecting SLASH or binary *
x : i32;
return 1;
}
2 changes: 1 addition & 1 deletion explorer/testdata/basic_syntax/fail_var_named_self.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn Main() -> i32 {
// Error: can't use keyword `Self` as the name of a variable.
// TODO: Current error message is unclear, better would be to say
// something like: unexpected `Self`, expecting identifier
// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_var_named_self.carbon:[[@LINE+1]]: syntax error, unexpected COLON, expecting EQUAL or SEMICOLON
// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_var_named_self.carbon:[[@LINE+1]]: syntax error, unexpected COLON, expecting SLASH or binary *
var Self : i32 = 0;
return Self;
}
2 changes: 1 addition & 1 deletion explorer/testdata/let/fail_local_named_self.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ package ExplorerTest api;

fn Main() -> i32 {
// Error: Can't use keyword `Self` as the name of a local.
// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/let/fail_local_named_self.carbon:[[@LINE+1]]: syntax error, unexpected COLON, expecting EQUAL
// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/let/fail_local_named_self.carbon:[[@LINE+1]]: syntax error, unexpected COLON, expecting SLASH or binary *
let Self: auto = 10;
return 0;
}
24 changes: 24 additions & 0 deletions explorer/testdata/operators/div.carbon
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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
//
// RUN: %{explorer} %s 2>&1 | \
// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s
// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \
// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s
// AUTOUPDATE: %{explorer} %s
// CHECK: result: 2

package ExplorerTest api;

class A { var n: i32; }

external impl A as DivWith(i32) where .Result == A {
fn Op[me: Self](rhs: i32) -> A { return {.n = me.n / rhs}; }
}

fn Main() -> i32 {
var a: A = {.n = 8};
a = a / 3;
return a.n;
}
24 changes: 24 additions & 0 deletions explorer/testdata/operators/div_builtin.carbon
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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
//
// RUN: %{explorer} %s 2>&1 | \
// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s
// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \
// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s
// AUTOUPDATE: %{explorer} %s
// CHECK: Interface: 2
// CHECK: Op: 2
// CHECK: result: 0

package ExplorerTest api;

fn Main() -> i32 {
var lhs: i32 = 8;
var rhs: i32 = 3;
// Make sure that both the interface and operator work with i32. These rely on
// builtin arithmetic more directly.
Print("Interface: {0}", lhs.(DivWith(i32).Op)(rhs));
Print("Op: {0}", lhs / rhs);
return 0;
}

0 comments on commit 69d4363

Please sign in to comment.