From 85626f9fbca084e4ff2792f261931108a2e228e2 Mon Sep 17 00:00:00 2001
From: Recolic Keghart <root@recolic.net>
Date: Sun, 15 Dec 2019 01:48:48 +0800
Subject: [PATCH] >  Manual commit:  Finished expr test gen. U201614531 recolic
 Linux RECOLICPC 5.4.2-arch1-1 #1 SMP PREEMPT Thu, 05 Dec 2019 12:29:40 +0000
 x86_64 GNU/Linux  01:48:48 up 3 days,  9:07,  1 user,  load average: 0.83,
 1.31, 1.24 69a22b1db808ab4796bd38efb2e0838c972396e5

---
 nemu/src/monitor/debug/expr.cc  |  1 -
 nemu/tools/gen-expr/Makefile    |  4 ++--
 nemu/tools/gen-expr/gen-expr.cc | 38 +++++++++++++++++++++++++++++----
 3 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/nemu/src/monitor/debug/expr.cc b/nemu/src/monitor/debug/expr.cc
index 4a09ceb..9d42827 100644
--- a/nemu/src/monitor/debug/expr.cc
+++ b/nemu/src/monitor/debug/expr.cc
@@ -105,7 +105,6 @@ uint32_t expr(char *e, bool *success) {
     return 0;
   }
 
-  /* TODO: Insert codes to evaluate the expression. */
   try {
     auto res = parse_one(std::string(e));
     *success = true;
diff --git a/nemu/tools/gen-expr/Makefile b/nemu/tools/gen-expr/Makefile
index 2da6083..28955a6 100644
--- a/nemu/tools/gen-expr/Makefile
+++ b/nemu/tools/gen-expr/Makefile
@@ -1,7 +1,7 @@
 APP=gen-expr
 
-$(APP): gen-expr.c
-	gcc -O2 -Wall -Werror -o $@ $<
+$(APP): gen-expr.cc
+	g++ -O2 -Wall -o $@ $< -g
 
 .PHONY: clean
 clean:
diff --git a/nemu/tools/gen-expr/gen-expr.cc b/nemu/tools/gen-expr/gen-expr.cc
index 1ac1592..d72f3d2 100644
--- a/nemu/tools/gen-expr/gen-expr.cc
+++ b/nemu/tools/gen-expr/gen-expr.cc
@@ -5,14 +5,45 @@
 #include <assert.h>
 #include <string.h>
 
+#include <string>
+#include <array>
+#include <random>
+#include <chrono>
+
+static std::mt19937 rand_generator(std::chrono::system_clock::now().time_since_epoch().count());
+
+#define RANDFLOAT ((float)(rand_generator() % (1<<30)) / (float)(1<<30))
+static std::string do_gen_rand_expr(int depth) {
+  if(depth > 64) {
+    return std::to_string(rand() % 100);
+  }
+  if(RANDFLOAT < 0.4) {
+    auto op = std::array<std::string, 16> {"+", "-", "*", "==", "!=", "&&"} [rand() % 6];
+    return do_gen_rand_expr(depth+1) + op + do_gen_rand_expr(depth+1);
+  }
+  if(RANDFLOAT < 0.4) {
+    return "(" + do_gen_rand_expr(depth+1) + ")";
+  }
+  if(RANDFLOAT < 0.2) {
+    auto tmp = do_gen_rand_expr(depth+1);
+    if(tmp[0] != '-') tmp = '-' + tmp;
+    return tmp;
+  }
+  return std::to_string(rand() % 10000);
+}
+#undef RANDFLOAT
+
 // this should be enough
 static char buf[65536];
 static inline void gen_rand_expr() {
-  buf[0] = '\0';
+  auto res = do_gen_rand_expr(0);
+  while(res.size() > 512 || res.size() < 16)
+    res = do_gen_rand_expr(0);
+  strcpy(buf, res.c_str());
 }
 
 static char code_buf[65536];
-static char *code_format =
+static const char *code_format =
 "#include <stdio.h>\n"
 "int main() { "
 "  unsigned result = %s; "
@@ -21,8 +52,6 @@ static char *code_format =
 "}";
 
 int main(int argc, char *argv[]) {
-  int seed = time(0);
-  srand(seed);
   int loop = 1;
   if (argc > 1) {
     sscanf(argv[1], "%d", &loop);
@@ -38,6 +67,7 @@ int main(int argc, char *argv[]) {
     fputs(code_buf, fp);
     fclose(fp);
 
+    // One test one compile: extremely slow, unusable.
     int ret = system("gcc .code.c -o .expr");
     if (ret != 0) continue;
 
-- 
GitLab