PennMUSH 1.8.3p12
authorRick L Bird <nveid@yahoo.com>
Sat, 14 May 2011 16:57:23 +0000 (12:57 -0400)
committerRick L Bird <nveid@yahoo.com>
Sat, 14 May 2011 16:57:23 +0000 (12:57 -0400)
Author: allthecoolkidshaveone <allthecoolkidshaveone@ba372814-4f39-11de-9ad6-1127a62b9fcd>
Date:   Sat Jan 2 04:12:32 2010 +0000

    Issue 175: llocks() returning a list of lock names

Author: allthecoolkidshaveone <allthecoolkidshaveone@ba372814-4f39-11de-9ad6-1127a62b9fcd>
Date:   Sat Jan 2 02:45:01 2010 +0000

   The lock optimizer now handles a few trivial things like svn
   status -qfoo
Fixes #203
Fixes #177

src/boolexp.c
src/function.c
src/fundb.c

index f47b0ac0d186849f636fabbb4630553739c76a87..8e10b4baa7db4a6b4e95c5219391b7a2cae63419 100644 (file)
@@ -325,9 +325,8 @@ static size_t
 offset_to_string(struct bvm_asm *a, int c);
 static struct bvm_asmnode *
 insn_after_label(struct bvm_asm *a, int label);
-static void
-opt_thread_jumps(struct bvm_asm *a);
-static void
+static void optimize_bvm_ast(struct boolexp_node *);
+ static void
 optimize_bvm_asm(struct bvm_asm *a);
 static boolexp
 emit_bytecode(struct bvm_asm *a, int derefs);
@@ -1672,18 +1671,106 @@ insn_after_label(struct bvm_asm *a, int label)
   return NULL;
 }
 
-/** Avoid jumps that lead straight to another jump. If the second jump
- * is on the same condition as the first one, jump instead to its
- * destination. If it's the opposite condition, jump instead to the
- * first instruction after the second jump to avoid the useless
- * conditional check. 
- * \param a the assembler list to thread. */
+/** Do some trivial optimizations at the syntax tree level. Some of
+ * these catch things that no normal person would do with a lock, but
+ * might be created artificially at some point in the future -- for
+ * example, if we ever go through and replace reference to a deleted
+ * object with #false in locks.
+ *
+ * Current optimizations:
+ *
+ * Turn =#123|+#123 into the equivalent #123 (Won't work with
+ * =#123|+#123|foo); doing so is probably overkill.)
+ * Turn !!foo into foo
+ * Turn !#TRUE into #FALSE and vis versa
+ *
+ * Possible future additions:
+ * Change foo&#FALSE&bar into #FALSE
+ * Change foo|#TRUE|bar into #TRUE
+ *
+ *  \param ast the syntax tree to transform
+ */
+static void
+optimize_bvm_ast(struct boolexp_node *ast)
+{
+  struct boolexp_node *temp;
+
+  if (!ast)
+    return;
+  switch (ast->type) {
+  case BOOLEXP_OR:
+    if (((ast->data.sub.a->type == BOOLEXP_IS && ast->data.sub.b->type == BOOLEXP_CARRY)
+        || (ast->data.sub.a->type == BOOLEXP_CARRY && ast->data.sub.b->type == BOOLEXP_IS))
+       && (ast->data.sub.a->thing == ast->data.sub.b->thing)) {
+      /* Turn =#123|+#123 into #123 */
+
+      dbref thing = ast->data.sub.a->thing;
+
+      free_bool(ast->data.sub.a);
+      free_bool(ast->data.sub.b);
+      ast->type = BOOLEXP_CONST;
+      ast->thing = thing;
+      ast->data.sub.a = ast->data.sub.b = NULL;
+    } else {
+      optimize_bvm_ast(ast->data.sub.a);
+      optimize_bvm_ast(ast->data.sub.b);
+    }
+    break;     
+  case BOOLEXP_AND:
+    optimize_bvm_ast(ast->data.sub.a);
+    optimize_bvm_ast(ast->data.sub.b);
+    break;
+  case BOOLEXP_NOT:
+    temp = ast->data.n;
+    if (temp->type == BOOLEXP_NOT) {
+      /* Turn !!foo into foo */
+      struct boolexp_node *n = temp->data.n;
+      free_bool(temp);
+      ast->type = n->type;
+      ast->thing = n->thing;
+      ast->data = n->data;
+      free_bool(n);
+      optimize_bvm_ast(ast);
+    } else if (temp->type == BOOLEXP_BOOL) {
+      /* Turn !#true into #false */
+      ast->type = BOOLEXP_BOOL;
+      ast->thing = !temp->thing;
+      ast->data.n = NULL;
+      free_bool(temp);      
+    } else
+      optimize_bvm_ast(ast->data.n);
+    break;
+  default:
+    (void)0; /* Nothing to do. */
+  }
+}
+
+/** Do some trivial optimizations of boolexp vm assembly. 
+ *
+ *
+ * Current optimizations: Thread jumping
+ *
+ * Possible future additions:
+ * Just-in-time compiling of locks to machine code? Raevnos did this once as a proof of concept.
+ *
+ *  \param a the assembler list to transform.
+ */
 static void
-opt_thread_jumps(struct bvm_asm *a)
+optimize_bvm_asm(struct bvm_asm *a)
 {
   struct bvm_asmnode *n, *target;
+  
+  if (!a)
+    return;
 
   for (n = a->head; n;) {
+
+    /* Avoid jumps that lead straight to another jump. If the second
+     * jump is on the same condition as the first one, jump instead to its
+     * destination. If it's the opposite condition, jump instead to the
+     * first instruction after the second jump to avoid the useless
+     * conditional check.
+     */
     if (n->op == OP_JMPT || n->op == OP_JMPF) {
       target = insn_after_label(a, n->arg);
       if (target && (target->op == OP_JMPT || target->op == OP_JMPF)) {
@@ -1698,8 +1785,7 @@ opt_thread_jumps(struct bvm_asm *a)
           struct bvm_asmnode *newlbl;
           newlbl = slab_malloc(bvm_asmnode_slab, NULL);
           if (!newlbl)
-            mush_panic(T
-                       ("Unable to allocate memory for boolexp asm node!"));
+            mush_panic(T("Unable to allocate memory for boolexp asm node!"));
           newlbl->op = OP_LABEL;
           n->arg = newlbl->arg = gen_label_id(a);
           if (target->next)
@@ -1717,17 +1803,6 @@ opt_thread_jumps(struct bvm_asm *a)
   }
 }
 
-/** Do some trivial optimizations.  
- * \param a the assembler list to transform.
- */
-static void
-optimize_bvm_asm(struct bvm_asm *a)
-{
-  if (!a)
-    return;
-  opt_thread_jumps(a);
-}
-
 /** Turn assembly into bytecode. 
  * \param a the assembly list to emit.
  * \param the compiled bytecode.
@@ -1834,6 +1909,7 @@ parse_boolexp_d(dbref player, const char *buf, lock_type ltype, int derefs)
   ast = parse_boolexp_E();
   if (!ast)
     return TRUE_BOOLEXP;
+  optimize_bvm_ast(ast);
   bvasm = generate_bvm_asm(ast);
   if (!bvasm) {
     free_boolexp_node(ast);
index 0b7ee594ea1c366264426a53e8c4d70cf7a57423..dd368ba25ec58500b57f577ae38e3f6f3870a455 100644 (file)
@@ -500,7 +500,7 @@ FUNTAB flist[] = {
   {"LIT", fun_lit, 1, -1, FN_LITERAL},
   {"LJUST", fun_ljust, 2, 3, FN_REG},
   {"LLOCKFLAGS", fun_lockflags, 0, 1, FN_REG},
-  {"LLOCKS", fun_locks, 1, 1, FN_REG},
+  {"LLOCKS", fun_locks, 0, 1, FN_REG},
   {"LMATH", fun_lmath, 2, 3, FN_REG},
   {"LNUM", fun_lnum, 1, 4, FN_REG},
   {"LOC", fun_loc, 1, 1, FN_REG},
index b3e4604adc0af737a969e935b38147c1f3918f43..0477824921b3540da91537c4efbc2923a7c6890c 100644 (file)
@@ -1127,13 +1127,30 @@ get_locktype(str)
   return upcasestr(str);
 }
 
+extern lock_list lock_types[];
 /* ARGSUSED */
 FUNCTION(fun_locks)
 {
-  dbref thing = match_thing(executor, args[0]);
+  dbref thing;
   lock_list *ll;
   const lock_list *p;
-  int first = 1;
+  bool first = 1;
+
+  if (nargs == 0) {
+    /* List all builtin lock names */
+    int n;
+
+    for (n = 0; lock_types[n].type; n++) {
+      if (!first)
+       safe_chr(' ', buff, bp);
+      else
+       first = 0;
+      safe_str(lock_types[n].type, buff, bp);
+    }
+    return;
+  }
+
+  thing = match_thing(executor, args[0]);
 
   if (!GoodObject(thing)) {
     safe_str(T(e_notvis), buff, bp);
@@ -1152,6 +1169,7 @@ FUNCTION(fun_locks)
   }
 }
 
+
 /* ARGSUSED */
 FUNCTION(fun_lockflags)
 {