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

Extends carbon to generate random number to make samples more interesting (#1643)

Implements the Rand function to carbon

Co-authored-by: m new <michael.burzan@outlook.de>
pmqtt 3 лет назад
Родитель
Сommit
df93623741

+ 1 - 0
common/fuzzing/carbon.proto

@@ -91,6 +91,7 @@ message IntrinsicExpression {
     Print = 1;
     Alloc = 2;
     Dealloc = 3;
+    Rand = 4;
   }
   optional Intrinsic intrinsic = 1;
   optional TupleLiteralExpression argument = 2;

+ 3 - 0
common/fuzzing/proto_to_carbon.cpp

@@ -306,6 +306,9 @@ static auto ExpressionToCarbon(const Fuzzing::Expression& expression,
         case Fuzzing::IntrinsicExpression::Dealloc:
           out << "__intrinsic_delete";
           break;
+        case Fuzzing::IntrinsicExpression::Rand:
+          out << "__intrinsic_rand";
+          break;
       }
       TupleLiteralExpressionToCarbon(intrinsic.argument(), out);
     } break;

+ 6 - 1
explorer/ast/expression.cpp

@@ -29,7 +29,8 @@ auto IntrinsicExpression::FindIntrinsic(std::string_view name,
   static const auto& intrinsic_map = *new std::map<std::string_view, Intrinsic>(
       {{"print", Intrinsic::Print},
        {"new", Intrinsic::Alloc},
-       {"delete", Intrinsic::Dealloc}});
+       {"delete", Intrinsic::Dealloc},
+       {"rand", Intrinsic::Rand}});
   name.remove_prefix(std::strlen("__intrinsic_"));
   auto it = intrinsic_map.find(name);
   if (it == intrinsic_map.end()) {
@@ -175,6 +176,7 @@ void Expression::Print(llvm::raw_ostream& out) const {
         out << "Print" << iexp.args();
         break;
       }
+
       out << "intrinsic_";
       switch (iexp.intrinsic()) {
         case IntrinsicExpression::Intrinsic::Print:
@@ -186,6 +188,9 @@ void Expression::Print(llvm::raw_ostream& out) const {
         case IntrinsicExpression::Intrinsic::Dealloc:
           out << "delete";
           break;
+        case IntrinsicExpression::Intrinsic::Rand:
+          out << "rand";
+          break;
       }
       out << iexp.args();
       break;

+ 1 - 1
explorer/ast/expression.h

@@ -664,7 +664,7 @@ class ValueLiteral : public Expression {
 
 class IntrinsicExpression : public Expression {
  public:
-  enum class Intrinsic { Print, Alloc, Dealloc };
+  enum class Intrinsic { Print, Alloc, Dealloc, Rand };
 
   // Returns the enumerator corresponding to the intrinsic named `name`,
   // or raises a fatal compile error if there is no such enumerator.

+ 4 - 0
explorer/data/prelude.carbon

@@ -106,6 +106,10 @@ external impl i32 as ModWith(i32) where .Result == i32 {
 //   __intrinsic_print(format_str);
 // }
 
+fn Rand(low: i32, high: i32) -> i32{
+    return __intrinsic_rand(low,high);
+}
+
 class Heap {
   fn New[T:! Type, me: Self](x : T) -> T* {
     return __intrinsic_new(x);

+ 3 - 0
explorer/fuzzing/ast_to_proto.cpp

@@ -239,6 +239,9 @@ static auto ExpressionToProto(const Expression& expression)
         case IntrinsicExpression::Intrinsic::Dealloc:
           intrinsic_proto->set_intrinsic(Fuzzing::IntrinsicExpression::Dealloc);
           break;
+        case IntrinsicExpression::Intrinsic::Rand:
+          intrinsic_proto->set_intrinsic(Fuzzing::IntrinsicExpression::Rand);
+          break;
       }
       *intrinsic_proto->mutable_argument() =
           TupleLiteralExpressionToProto(intrinsic.args());

+ 13 - 0
explorer/interpreter/interpreter.cpp

@@ -7,6 +7,7 @@
 #include <iterator>
 #include <map>
 #include <optional>
+#include <random>
 #include <utility>
 #include <variant>
 #include <vector>
@@ -30,6 +31,8 @@ using llvm::isa;
 
 namespace Carbon {
 
+static std::mt19937 generator(12);
+
 // Constructs an ActionStack suitable for the specified phase.
 static auto MakeTodo(Phase phase, Nonnull<Heap*> heap) -> ActionStack {
   switch (phase) {
@@ -1156,6 +1159,16 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
       }
       // { {n :: C, E, F} :: S, H} -> { {n' :: C, E, F} :: S, H}
       switch (cast<IntrinsicExpression>(exp).intrinsic()) {
+        case IntrinsicExpression::Intrinsic::Rand: {
+          const auto& args = cast<TupleValue>(*act.results()[0]).elements();
+          CARBON_CHECK(args.size() == 2);
+
+          const auto& low = cast<IntValue>(*args[0]).value();
+          const auto& high = cast<IntValue>(*args[1]).value();
+          std::uniform_int_distribution<> distr(low, high);
+          int r = distr(generator);
+          return todo_.FinishAction(arena_->New<IntValue>(r));
+        }
         case IntrinsicExpression::Intrinsic::Print: {
           const auto& args = cast<TupleValue>(*act.results()[0]).elements();
           CARBON_ASSIGN_OR_RETURN(

+ 17 - 0
explorer/interpreter/type_checker.cpp

@@ -2203,6 +2203,23 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
       CARBON_RETURN_IF_ERROR(TypeCheckExp(&intrinsic_exp.args(), impl_scope));
       const auto& args = intrinsic_exp.args().fields();
       switch (cast<IntrinsicExpression>(*e).intrinsic()) {
+        case IntrinsicExpression::Intrinsic::Rand: {
+          if (args.size() != 2) {
+            return CompilationError(e->source_loc())
+                   << "Rand takes 2 arguments, received " << args.size();
+          }
+          CARBON_RETURN_IF_ERROR(ExpectExactType(
+              e->source_loc(), "Rand argument 0", arena_->New<IntType>(),
+              &args[0]->static_type(), impl_scope));
+
+          CARBON_RETURN_IF_ERROR(ExpectExactType(
+              e->source_loc(), "Rand argument 1", arena_->New<IntType>(),
+              &args[1]->static_type(), impl_scope));
+
+          e->set_static_type(arena_->New<IntType>());
+
+          return Success();
+        }
         case IntrinsicExpression::Intrinsic::Print:
           // TODO: Remove Print special casing once we have variadics or
           // overloads. Here, that's the name Print instead of __intrinsic_print

+ 25 - 0
explorer/testdata/random/random.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
+//
+// 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: 0
+
+package ExplorerTest api;
+fn test(para: i32)->Bool{
+  return true;
+}
+fn Main() -> i32 {
+  var i : i32 = Rand(0,100);
+  var j : i32 = Rand(0,100);
+  if(i == j){
+    Print("HALLO WELT");
+  }else{
+    Print("Nice!");
+  }
+  return 0;
+}