From 444196a5d9790de63a664c233d9f5098cca7692d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?=
 <grubba@grubba.org>
Date: Mon, 8 Nov 1999 01:00:26 +0100
Subject: [PATCH] First version. The rules for F_FOR aren't fully ported yet.

Rev: src/treeopt.in:1.1
---
 .gitattributes |   1 +
 src/treeopt.in | 424 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 425 insertions(+)
 create mode 100644 src/treeopt.in

diff --git a/.gitattributes b/.gitattributes
index 461ec7d7e0..1c2546c2d3 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -487,6 +487,7 @@ testfont binary
 /src/threads.c foreign_ident
 /src/threads.h foreign_ident
 /src/time_stuff.h foreign_ident
+/src/treeopt.in foreign_ident
 /src/version.c foreign_ident
 /src/version.h foreign_ident
 /tutorial/manpages foreign_ident
diff --git a/src/treeopt.in b/src/treeopt.in
new file mode 100644
index 0000000000..3556d54174
--- /dev/null
+++ b/src/treeopt.in
@@ -0,0 +1,424 @@
+// -*- c-mode -*-
+//
+// $Id: treeopt.in,v 1.1 1999/11/08 00:00:26 grubba Exp $
+//
+// The tree optimizer
+//
+// Henrik Grubbström 1999-11-06
+
+0 = F_APPLY(1 = F_CONSTANT
+	    [u.sval.type == T_FUNCTION]
+	    [u.sval.subtype == FUNCTION_BUILTIN]
+	    [u.sval.u.efun->optimize], *):
+
+{
+  if ((tmp = $1->u.sval.u.efun->optimize($0))) {
+    $$ = tmp;
+  }
+}
+;
+
+F_CAST(-,*):
+  -;
+
+F_CAST[type == void_type_string](F_CONSTANT, *):
+  -;
+
+F_CAST[type == void_type_string](F_COMMA_EXPR(0, F_CONSTANT), *):
+{
+  $$ = mkcastnode(void_type_string, $0);
+}
+;
+
+F_CAST[type == void_type_string]
+      (F_APPLY(F_CONSTANT[(node_info & OPT_SIDE_EFFECT|
+				       OPT_ASSIGNMENT|
+				       OPT_TRY_OPTIMIZE) == OPT_TRY_OPTIMIZE],
+	       F_ARG_LIST(1, 2)), *):
+{
+  $$ = mkcastnode(void_type_string,
+		  mknode(F_COMMA_EXPR, $1, $2));
+}
+;
+
+F_CAST[type == void_type_string]
+      (F_APPLY(F_CONSTANT[(node_info & OPT_SIDE_EFFECT|
+			   OPT_ASSIGNMENT|
+			   OPT_TRY_OPTIMIZE) == OPT_TRY_OPTIMIZE],
+	       0), *):
+	$0;
+
+// FCAST[0 = type](1 = *[0], *): 1;
+
+F_RANGE(*, F_ARG_LIST(*, F_CONSTANT[u.sval.type == T_INT]
+                                   [u.sval.u.integer <= 0])):
+{
+  yywarning("Range end is not positive.");
+}
+;
+
+F_RANGE(*, F_ARG_LIST(*, F_CONSTANT[u.sval.type == T_FLOAT]
+				   [u.sval.u.float_number <= 0.0])):
+{
+  yywarning("Range end is not positive.");
+}
+;
+
+F_COMMA_EXPR(-, 0):
+  $0;
+
+F_COMMA_EXPR(0, -):
+  $0;
+
+F_COMMA_EXPR(F_CONSTANT, 0):
+  $0;
+
+F_COMMA_EXPR(F_COMMA_EXPR(0, F_CONSTANT), 1):
+  F_COMMA_EXPR($0, $1);
+
+F_COMMA_EXPR(F_ARG_LIST(0, 1), 2):
+  F_COMMA_EXPR(F_COMMA_EXPR($0, $1), $2);
+
+// Ensure that the result value is at the top-node, to ensure
+// proper optimization.
+F_COMMA_EXPR(0, F_COMMA_EXPR(1, 2)):
+  F_COMMA_EXPR(F_COMMA_EXPR($0, $1), $2);
+
+// Is really the OPT_CASE needded for the following three?
+F_COMMA_EXPR(0 = F_RETURN, *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_COMMA_EXPR(0 = F_CONTINUE, *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_COMMA_EXPR(0 = F_BREAK, *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_COMMA_EXPR(0 = F_COMMA_EXPR(*, F_RETURN), *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_COMMA_EXPR(0 = F_COMMA_EXPR(*, F_CONSTANT), *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_COMMA_EXPR(0 = F_COMMA_EXPR(*, F_BREAK), *[!(tree_info & OPT_CASE)]):
+  $0;
+
+
+F_ARG_LIST(-, 0):
+  $0;
+
+F_ARG_LIST(0, -):
+  $0;
+
+// Is really the OPT_CASE needded for the following three?
+F_ARG_LIST(0 = F_RETURN, *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_ARG_LIST(0 = F_CONTINUE, *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_ARG_LIST(0 = F_BREAK, *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_ARG_LIST(0 = F_COMMA_EXPR(*, F_RETURN), *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_ARG_LIST(0 = F_COMMA_EXPR(*, F_CONSTANT), *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_ARG_LIST(0 = F_COMMA_EXPR(*, F_BREAK), *[!(tree_info & OPT_CASE)]):
+  $0;
+
+
+F_LVALUE_LIST(-, 0):
+  $0;
+
+F_LVALUE_LIST(0, -):
+  $0;
+
+// Is really the OPT_CASE needded for the following three?
+F_LVALUE_LIST(0 = F_RETURN, *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_LVALUE_LIST(0 = F_CONTINUE, *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_LVALUE_LIST(0 = F_BREAK, *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_LVALUE_LIST(0 = F_COMMA_EXPR(*, F_RETURN), *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_LVALUE_LIST(0 = F_COMMA_EXPR(*, F_CONSTANT), *[!(tree_info & OPT_CASE)]):
+  $0;
+
+F_LVALUE_LIST(0 = F_COMMA_EXPR(*, F_BREAK), *[!(tree_info & OPT_CASE)]):
+  $0;
+
+
+F_LOR(-, 0):
+  $0;
+
+F_LOR(0, -):
+  $0;
+
+F_LOR(F_NOT(0, *), F_NOT(1, *)):
+  F_NOT(F_LAND($0, $1), -);
+
+F_LOR(0 = F_ASSIGN(*, 1), 2):
+{
+  if (node_is_false($1)) {
+    $$ = mknode(F_COMMA_EXPR, $0, $2);
+  }
+  if (node_is_true($1)) {
+    $$ = $0;
+  }
+}
+;
+
+F_LOR(0, 1 = F_CONSTANT):
+{
+  if (node_is_false($1)) {
+    $$ = $0;
+  }
+}
+;
+
+F_LOR(0, 1):
+{
+  if (node_is_false($0)) {
+    $$ = $1;
+  }
+  if (node_is_true($0)) {
+    $$ = $0;
+  }
+}
+;
+
+
+F_LAND(-, 0):
+  -;
+
+F_LAND(0, -):
+  F_COMMA_EXPR($0, 0);
+
+F_LAND(F_NOT(0, *), F_NOT(1, *)):
+  F_NOT(F_LOR($0, $1), -);
+
+F_LAND(0 = F_ASSIGN(*, 1), 2):
+{
+  if (node_is_true($1)) {
+    $$ = mknode(F_COMMA_EXPR, $0, $2);
+  }
+  if (node_is_false($1)) {
+    $$ = $0;
+  }
+}
+;
+
+F_LAND(0, 1):
+{
+  if (node_is_true($0)) {
+    $$ = $1;
+  }
+  if (node_is_false($0)) {
+    $$ = $0;
+  }
+  if (node_is_false($1)) {
+    $$ = mknode(F_COMMA_EXPR, $0, $1);
+  }
+}
+;
+
+
+'?'(F_NOT(0, *), ':'(1, 2)):
+  '?'($0, ':'($2, $1));
+
+'?'(0, ':'(1, 2)):
+{
+  if (node_is_true($0)) {
+    $$ = $1;
+  }
+  if (node_is_false($0)) {
+    $$ = $2;
+  }
+}
+;
+
+
+F_NOT(-, *):
+  1;
+
+F_NOT(F_LT(0, 1), *):
+  F_GE($0, $1);
+
+F_NOT(F_GT(0, 1), *):
+  F_LE($0, $1);
+
+F_NOT(F_LE(0, 1), *):
+  F_GT($0, $1);
+
+F_NOT(F_GE(0, 1), *):
+  F_LT($0, $1);
+
+F_NOT(F_EQ(0, 1), *):
+  F_NE($0, $1);
+
+F_NOT(F_NE(0, 1), *):
+  F_EQ($0, $1);
+
+
+F_ADD_EQ(0, 1 = F_CONSTANT[u.sval.type == T_INT]):
+{
+  /* a += 0  ->  a */
+  if (!$1->u.sval.u.integer) {
+    $$ = $0;
+  }
+
+  /* a += 1  ->  ++a */
+  if ($1->u.sval.u.integer == 1) {
+    $$ = mknode(F_INC, $0, 0);
+  }
+
+  /* a += -1  ->  --a */
+  if ($1->u.sval.u.integer == -1) {
+    $$ = mknode(F_DEC, $0, 0);
+  }
+}
+;
+
+F_SUB_EQ(0, 1 = F_CONSTANT[u.sval.type == T_INT]):
+{
+  /* a -= 0  ->  a */
+  if (!$1->u.sval.u.integer) {
+    $$ = $0;
+  }
+
+  /* a -= 1  ->  --a */
+  if ($1->u.sval.u.integer == 1) {
+    $$ = mknode(F_DEC, $0, 0);
+  }
+
+  /* a -= -1  ->  ++a */
+  if ($1->u.sval.u.integer == -1) {
+    $$ = mknode(F_INC, $0, 0);
+  }
+}
+;
+
+F_ARROW(0 = F_CONSTANT[u.sval.type == T_OBJECT]
+	    [u.sval.u.object->prog],
+	1 = F_CONSTANT[u.sval.type == T_STRING]):
+{
+  if (find_identifier("`->", $0->u.sval.u.object->prog) == -1) {
+    int i = find_shared_string_identifier($1->u.sval.u.string,
+					  $0->u.sval.u.object->prog);
+    if (i) {
+      struct identifier *id = ID_FROM_INT($0->u.sval.u.object->prog, i);
+      if (IDENTIFIER_IS_VARIABLE(id->identifier_flags)) break;
+    }
+    ref_push_object($0->u.sval.u.object);
+    ref_push_string($1->u.sval.u.string);
+    f_index(2);
+    tmp = mksvaluenode(sp-1);
+    pop_stack();
+    $$ = tmp;
+  }
+}
+;
+
+F_FOR(-, *):
+  -;
+
+F_FOR(0, ':'(-, -)):
+  F_FOR($0, -);
+
+F_FOR(0, -):
+{
+  if (node_is_true($0)) {
+    $$ = mknode(F_FOR($0, mknode(':',
+				 mkefuncallnode("sleep", mkintnode(255)),
+				 0)));
+  }
+  if (node_is_false($0)) {
+    $$ = 0;
+  }
+}
+;
+
+F_FOR(0, *):
+{
+  if (node_is_false($0)) {
+    $$ = 0;
+  }
+}
+;
+
+F_FOR(F_INC(0, *), -):
+  F_INC_NEQ_LOOP(F_VAL_LVAL(0, $0), -);
+F_FOR(F_INC(0, *), ':'(-, 1[!(tree_info & OPT_CONTINUE)])):
+  F_INC_NEQ_LOOP(F_VAL_LVAL(0, $0), $1);
+F_FOR(F_INC(0, *), ':'(1[!(tree_info & OPT_CONTINUE)], -)):
+  F_INC_NEQ_LOOP(F_VAL_LVAL(0, $0), $1);
+F_FOR(F_INC(0, *), ':'(1[!(tree_info & OPT_CONTINUE)],
+		       2[!(tree_info & OPT_CONTINUE)])):
+  F_INC_NEQ_LOOP(F_VAL_LVAL(0, $0), F_COMMA_EXPR($1, $2));
+
+F_FOR(F_POST_INC(0, *), -):
+  F_INC_NEQ_LOOP(F_VAL_LVAL(1, $0), -);
+F_FOR(F_POST_INC(0, *), ':'(-, 1[!(tree_info & OPT_CONTINUE)])):
+  F_INC_NEQ_LOOP(F_VAL_LVAL(1, $0), $1);
+F_FOR(F_POST_INC(0, *), ':'(1[!(tree_info & OPT_CONTINUE)], -)):
+  F_INC_NEQ_LOOP(F_VAL_LVAL(1, $0), $1);
+F_FOR(F_POST_INC(0, *), ':'(1[!(tree_info & OPT_CONTINUE)],
+		            2[!(tree_info & OPT_CONTINUE)])):
+  F_INC_NEQ_LOOP(F_VAL_LVAL(1, $0), F_COMMA_EXPR($1, $2));
+
+F_FOR(F_DEC(0, *), -):
+  F_DEC_NEQ_LOOP(F_VAL_LVAL(0, $0), -);
+F_FOR(F_DEC(0, *), ':'(-, 1[!(tree_info & OPT_CONTINUE)])):
+  F_DEC_NEQ_LOOP(F_VAL_LVAL(0, $0), $1);
+F_FOR(F_DEC(0, *), ':'(1[!(tree_info & OPT_CONTINUE)], -)):
+  F_DEC_NEQ_LOOP(F_VAL_LVAL(0, $0), $1);
+F_FOR(F_DEC(0, *), ':'(1[!(tree_info & OPT_CONTINUE)],
+		       2[!(tree_info & OPT_CONTINUE)])):
+  F_DEC_NEQ_LOOP(F_VAL_LVAL(0, $0), F_COMMA_EXPR($1, $2));
+
+F_FOR(F_POST_DEC(0, *), -):
+  F_DEC_NEQ_LOOP(F_VAL_LVAL(F_NEG(1, -), $0), -);
+F_FOR(F_POST_DEC(0, *), ':'(-, 1[!(tree_info & OPT_CONTINUE)])):
+  F_DEC_NEQ_LOOP(F_VAL_LVAL(F_NEG(1, -), $0), $1);
+F_FOR(F_POST_DEC(0, *), ':'(1[!(tree_info & OPT_CONTINUE)], -)):
+  F_DEC_NEQ_LOOP(F_VAL_LVAL(F_NEG(1, -), $0), $1);
+F_FOR(F_POSTDEC(0, *), ':'(1[!(tree_info & OPT_CONTINUE)],
+                           2[!(tree_info & OPT_CONTINUE)])):
+  F_DEC_NEQ_LOOP(F_VAL_LVAL(F_NEG(1, -), $0), F_COMMA_EXPR($1, $2));
+
+F_FOR(0, ':'(1, F_CAST[type == void_type_string](2, *))):
+  F_FOR($0, ':'($1, $2));
+
+F_FOR(F_APPLY(0 = F_CONSTANT[u.sval.type == T_FUNCTION]
+                            [u.sval.subtype == FUNCTION_BUILTIN],
+              1),
+      ':'(2, 3)):
+{
+  int oper;
+  if ($0->u.sval.u.efun->function == f_gt)
+    oper = F_GT;
+  else if ($0->u.sval.u.efun->function == f_ge)
+    oper = F_GE;
+  else if ($0->u.sval.u.efun->function == f_lt)
+    oper = F_LT;
+  else if ($0->u.sval.u.efun->function == f_le)
+    oper = F_LE;
+  else if ($0->u.sval.u.efun->function == f_ne)
+    oper = F_NE;
+  else
+    goto end_for_apply;
+
+  if (count_args($1) != 2) goto end_for_apply;
+
+
+end_for_apply:
+}
+;
-- 
GitLab