cb22561995-10-11Fredrik Hübinette (Hubbe) /*\
06983f1996-09-22Fredrik Hübinette (Hubbe) ||| This file a part of Pike, and is copyright by Fredrik Hubinette ||| Pike is distributed as GPL (General Public License)
cb22561995-10-11Fredrik Hübinette (Hubbe) ||| See the files COPYING and DISCLAIMER for more information. \*/
54db6c1999-03-27Henrik Grubbström (Grubba) /**/
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h"
aee2d32000-09-12Henrik Grubbström (Grubba) RCSID("$Id: las.c,v 1.210 2000/09/12 17:06:38 grubba Exp $");
419ede1996-11-13Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "language.h" #include "interpret.h" #include "las.h" #include "array.h" #include "object.h" #include "stralloc.h" #include "dynamic_buffer.h" #include "lex.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "pike_types.h" #include "constants.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "mapping.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "multiset.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "error.h" #include "docode.h" #include "main.h"
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #include "pike_memory.h"
6891181996-08-06Fredrik Hübinette (Hubbe) #include "operators.h"
a29e021996-10-15Fredrik Hübinette (Hubbe) #include "callback.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
9c6f7d1997-04-15Fredrik Hübinette (Hubbe) #include "peep.h"
5d2bb21998-01-26Henrik Grubbström (Grubba) #include "builtin_functions.h"
63c6751998-04-09Fredrik Hübinette (Hubbe) #include "cyclic.h"
011ad31999-10-22Fredrik Hübinette (Hubbe) #include "block_alloc.h"
f76b4c2000-05-11Henrik Grubbström (Grubba) #include "opcodes.h"
5267b71995-08-09Fredrik Hübinette (Hubbe)  #define LASDEBUG int lasdebug=0; static node *eval(node *); static void optimize(node *n);
969a291999-11-17Henrik Grubbström (Grubba) static node *localopt(node *n);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
c3c7031996-12-04Fredrik Hübinette (Hubbe) int cumulative_parse_error=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) extern char *get_type_name(int);
e82b301997-01-29Fredrik Hübinette (Hubbe) #define MAX_GLOBAL 2048
5267b71995-08-09Fredrik Hübinette (Hubbe) 
84191b1999-11-23Henrik Grubbström (Grubba) /* #define yywarning my_yyerror */
55a20a1999-11-17Henrik Grubbström (Grubba) int car_is_node(node *n)
5267b71995-08-09Fredrik Hübinette (Hubbe) { switch(n->token) {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  case F_EXTERNAL:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_IDENTIFIER:
4218011999-01-31Fredrik Hübinette (Hubbe)  case F_TRAMPOLINE:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CONSTANT: case F_LOCAL: return 0; default:
046afe1999-11-11Henrik Grubbström (Grubba)  return !!_CAR(n);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
55a20a1999-11-17Henrik Grubbström (Grubba) int cdr_is_node(node *n)
5267b71995-08-09Fredrik Hübinette (Hubbe) { switch(n->token) {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  case F_EXTERNAL:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_IDENTIFIER:
4218011999-01-31Fredrik Hübinette (Hubbe)  case F_TRAMPOLINE:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CONSTANT: case F_LOCAL: return 0; default:
046afe1999-11-11Henrik Grubbström (Grubba)  return !!_CDR(n);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
cbe8f32000-07-10Henrik Grubbström (Grubba) int node_is_leaf(node *n) { switch(n->token) { case F_EXTERNAL: case F_IDENTIFIER: case F_TRAMPOLINE: case F_CONSTANT: case F_LOCAL: return 1; } return 0; }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
3c0c281998-01-26Fredrik Hübinette (Hubbe) void check_tree(node *n, int depth) {
ae7cc02000-09-12Henrik Grubbström (Grubba)  node *orig_n = n; node *parent;
3c0c281998-01-26Fredrik Hübinette (Hubbe)  if(!d_flag) return;
ae7cc02000-09-12Henrik Grubbström (Grubba)  if (!n) return;
046afe1999-11-11Henrik Grubbström (Grubba) 
ae7cc02000-09-12Henrik Grubbström (Grubba)  parent = n->parent; n->parent = NULL; while(n) { if(n->token==USHRT_MAX) fatal("Free node in tree.\n"); check_node_hash(n); switch(n->token) {
01d4902000-07-11Fredrik Hübinette (Hubbe)  case F_EXTERNAL: if(n->type) {
ff88db2000-07-12Henrik Grubbström (Grubba)  int parent_id = n->u.integer.a;
01d4902000-07-11Fredrik Hübinette (Hubbe)  int id_no = n->u.integer.b;
da77e22000-09-08Fredrik Hübinette (Hubbe)  struct program_state *state = Pike_compiler;
ff88db2000-07-12Henrik Grubbström (Grubba)  while (state && (state->new_program->id != parent_id)) { state = state->previous; } if (state) { struct identifier *id = ID_FROM_INT(state->new_program, id_no);
01d4902000-07-11Fredrik Hübinette (Hubbe)  if (id) { #ifdef PIKE_DEBUG
cfe1fe2000-09-09Fredrik Hübinette (Hubbe)  /* FIXME: This test crashes on valid code because the type of the * identifier can change in pass 2 - Hubbe */
01d4902000-07-11Fredrik Hübinette (Hubbe)  if(id->type != n->type) { printf("Type of external node is not matching it's identifier.\nid->type: "); simple_describe_type(id->type); printf("\nn->type : "); simple_describe_type(n->type); printf("\n"); fatal("Type of external node is not matching it's identifier.\n"); } #endif } } }
ae7cc02000-09-12Henrik Grubbström (Grubba)  } if(d_flag<2) break;
01d4902000-07-11Fredrik Hübinette (Hubbe) 
0e58d22000-09-12Henrik Grubbström (Grubba)  if(!(depth & 1023)) { node *q; for(q=n->parent;q;q=q->parent) if(q->parent==n) fatal("Cyclic node structure found.\n");
ae7cc02000-09-12Henrik Grubbström (Grubba)  }
889d232000-09-12Henrik Grubbström (Grubba) 
ae7cc02000-09-12Henrik Grubbström (Grubba)  if(car_is_node(n))
889d232000-09-12Henrik Grubbström (Grubba)  {
ae7cc02000-09-12Henrik Grubbström (Grubba)  /* Check CAR */ #ifdef SHARED_NODES CAR(n)->parent = n; #else /* !SHARED_NODES */ if(CAR(n)->parent != n) fatal("Parent is wrong.\n"); #endif /* SHARED_NODES */ depth++; n = CAR(n); continue;
889d232000-09-12Henrik Grubbström (Grubba)  }
3c0c281998-01-26Fredrik Hübinette (Hubbe) 
ae7cc02000-09-12Henrik Grubbström (Grubba)  if(cdr_is_node(n)) { /* Check CDR */ #ifdef SHARED_NODES CDR(n)->parent = n; #else /* !SHARED_NODES */ if(CDR(n)->parent != n) fatal("Parent is wrong.\n");
f1af891999-12-14Henrik Grubbström (Grubba) #endif /* !SHARED_NODES */
3c0c281998-01-26Fredrik Hübinette (Hubbe) 
ae7cc02000-09-12Henrik Grubbström (Grubba)  depth++; n = CDR(n); continue; }
3c0c281998-01-26Fredrik Hübinette (Hubbe) 
ae7cc02000-09-12Henrik Grubbström (Grubba)  while(n->parent && (!cdr_is_node(n->parent) || (CDR(n->parent) == n))) { /* Backtrack */ n = n->parent; depth--; } if (n->parent && cdr_is_node(n->parent)) { /* Jump to the sibling */ #ifdef SHARED_NODES CDR(n->parent)->parent = n->parent; #else /* !SHARED_NODES */ if(CDR(n->parent)->parent != n->parent) fatal("Parent is wrong.\n");
f1af891999-12-14Henrik Grubbström (Grubba) #endif /* !SHARED_NODES */
ae7cc02000-09-12Henrik Grubbström (Grubba)  n = CDR(n->parent); continue; } break; }
3c0c281998-01-26Fredrik Hübinette (Hubbe) 
ae7cc02000-09-12Henrik Grubbström (Grubba)  if (n != orig_n) { fprintf(stderr, "check_tree() lost track.\n"); d_flag = 0; fprintf(stderr, "n:"); print_tree(n); fprintf(stderr, "orig_n:"); print_tree(orig_n); fatal("check_tree() lost track.\n");
3c0c281998-01-26Fredrik Hübinette (Hubbe)  }
ae7cc02000-09-12Henrik Grubbström (Grubba)  n->parent = parent;
3c0c281998-01-26Fredrik Hübinette (Hubbe) } #endif
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
5267b71995-08-09Fredrik Hübinette (Hubbe) INT32 count_args(node *n) {
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  int a,b;
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(n,0);
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!n) return 0; switch(n->token) {
920d201999-11-06Henrik Grubbström (Grubba)  case F_COMMA_EXPR:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_VAL_LVAL: case F_ARG_LIST:
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  a=count_args(CAR(n)); if(a==-1) return -1; b=count_args(CDR(n)); if(b==-1) return -1; return a+b;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CAST: if(n->type == void_type_string) return 0; else return count_args(CAR(n));
84191b1999-11-23Henrik Grubbström (Grubba)  case F_SOFT_CAST: return count_args(CAR(n));
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CASE: case F_FOR: case F_DO: case F_INC_LOOP: case F_DEC_LOOP: case F_DEC_NEQ_LOOP: case F_INC_NEQ_LOOP: case F_BREAK: case F_RETURN: case F_CONTINUE: case F_FOREACH: return 0; case '?': { int tmp1,tmp2;
e260681996-04-11Fredrik Hübinette (Hubbe)  tmp1=count_args(CADR(n)); tmp2=count_args(CDDR(n));
ae7cc02000-09-12Henrik Grubbström (Grubba)  if(tmp1==-1 || tmp2==-1) return -1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(tmp1 < tmp2) return tmp1; return tmp2; }
b95bef1996-03-29Fredrik Hübinette (Hubbe)  case F_PUSH_ARRAY: return -1;
cd06162000-03-01Fredrik Hübinette (Hubbe)  case F_APPLY: if(CAR(n)->token == F_CONSTANT && CAR(n)->u.sval.type == T_FUNCTION && CAR(n)->u.sval.subtype == FUNCTION_BUILTIN && n->type == void_type_string) return 0; return 1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  default: if(n->type == void_type_string) return 0; return 1; } }
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
61e9a01998-01-25Fredrik Hübinette (Hubbe) struct pike_string *find_return_type(node *n) { struct pike_string *a,*b;
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(n,0);
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  if(!n) return 0;
5aff211999-12-14Henrik Grubbström (Grubba)  if (n->token == F_RETURN) { if (CAR(n)) { if (CAR(n)->type) { copy_shared_string(a, CAR(n)->type); } else { #ifdef PIKE_DEBUG if (l_flag > 2) { fprintf(stderr, "Return with untyped argument.\n"); print_tree(n); } #endif /* PIKE_DEBUG */ copy_shared_string(a, mixed_type_string); } } else { copy_shared_string(a, zero_type_string); } return a; }
61e9a01998-01-25Fredrik Hübinette (Hubbe)  if(!(n->tree_info & OPT_RETURN)) return 0;
5aff211999-12-14Henrik Grubbström (Grubba) 
61e9a01998-01-25Fredrik Hübinette (Hubbe)  if(car_is_node(n)) a=find_return_type(CAR(n)); else a=0; if(cdr_is_node(n)) b=find_return_type(CDR(n)); else b=0; if(a) {
33b4a61999-12-14Henrik Grubbström (Grubba)  if(b) { if (a != b) { struct pike_string *res = or_pike_types(a, b, 1); free_string(a); free_string(b); return res; }
5aff211999-12-14Henrik Grubbström (Grubba)  free_string(b); }
61e9a01998-01-25Fredrik Hübinette (Hubbe)  return a; }
5aff211999-12-14Henrik Grubbström (Grubba)  return b;
61e9a01998-01-25Fredrik Hübinette (Hubbe) }
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  #define NODES 256
011ad31999-10-22Fredrik Hübinette (Hubbe) #undef BLOCK_ALLOC_NEXT #define BLOCK_ALLOC_NEXT u.node.a
01a9572000-02-03Henrik Grubbström (Grubba) BLOCK_ALLOC(node_s, NODES)
a8ef6e1996-12-03Fredrik Hübinette (Hubbe) 
011ad31999-10-22Fredrik Hübinette (Hubbe) #undef BLOCK_ALLOC_NEXT #define BLOCK_ALLOC_NEXT next
a8ef6e1996-12-03Fredrik Hübinette (Hubbe) 
046afe1999-11-11Henrik Grubbström (Grubba) #ifdef SHARED_NODES struct node_hash_table node_hash;
93b7202000-08-14Henrik Grubbström (Grubba) static size_t hash_node(node *n)
046afe1999-11-11Henrik Grubbström (Grubba) { return hashmem((unsigned char *)&(n->token), sizeof(node) - OFFSETOF(node_s, token), sizeof(node)); } static void add_node(node *n) {
93b7202000-08-14Henrik Grubbström (Grubba)  size_t hval = n->hash % node_hash.size;
046afe1999-11-11Henrik Grubbström (Grubba)  n->next = node_hash.table[hval]; node_hash.table[hval] = n; } static void sub_node(node *n) { node *prior; if (!node_hash.size) { return; } prior = node_hash.table[n->hash % node_hash.size]; if (!prior) { return; } if (prior == n) { node_hash.table[n->hash % node_hash.size] = n->next; } else { while(prior && (prior->next != n)) { prior = prior->next; } if (!prior) { return; } prior->next = n->next; } } static node *freeze_node(node *orig) {
93b7202000-08-14Henrik Grubbström (Grubba)  size_t hash = hash_node(orig);
969a291999-11-17Henrik Grubbström (Grubba)  node *n;
046afe1999-11-11Henrik Grubbström (Grubba) 
a836c01999-11-12Henrik Grubbström (Grubba)  /* free_node() wants a correct hash */ orig->hash = hash; if (orig->node_info & OPT_NOT_SHARED) { /* No need to have this node in the hash-table. */ /* add_node(orig); */
bf4f7d1999-11-12Henrik Grubbström (Grubba)  return check_node_hash(dmalloc_touch(node *, orig));
a836c01999-11-12Henrik Grubbström (Grubba)  }
969a291999-11-17Henrik Grubbström (Grubba)  /* Mark this node as a possible duplicate */ orig->node_info |= OPT_DEFROSTED; /* Make sure we don't find ourselves */ sub_node(orig); n = node_hash.table[hash % node_hash.size];
046afe1999-11-11Henrik Grubbström (Grubba)  while (n) { if ((n->hash == hash) && !MEMCMP(&(n->token), &(orig->token), sizeof(node) - OFFSETOF(node_s, token))) {
889d232000-09-12Henrik Grubbström (Grubba)  if (orig->type && (orig->type != n->type)) { if (n->type) { /* Use the new type if it's stricter. */ if (pike_types_le(orig->type, n->type)) { free_string(n->type); copy_shared_string(n->type, orig->type); } } else { /* This probably doesn't happen, but... */ copy_shared_string(n->type, orig->type); } }
a836c01999-11-12Henrik Grubbström (Grubba)  free_node(dmalloc_touch(node *, orig));
046afe1999-11-11Henrik Grubbström (Grubba)  n->refs++;
bf4f7d1999-11-12Henrik Grubbström (Grubba)  return check_node_hash(dmalloc_touch(node *, n));
046afe1999-11-11Henrik Grubbström (Grubba)  } n = n->next; }
969a291999-11-17Henrik Grubbström (Grubba)  orig->node_info &= ~OPT_DEFROSTED;
a836c01999-11-12Henrik Grubbström (Grubba)  add_node(dmalloc_touch(node *, orig));
da77e22000-09-08Fredrik Hübinette (Hubbe)  check_tree(orig,0);
bf4f7d1999-11-12Henrik Grubbström (Grubba)  return check_node_hash(orig);
046afe1999-11-11Henrik Grubbström (Grubba) } #else /* !SHARED_NODES */
01d4902000-07-11Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG static node *freeze_node(node *orig) {
2cb6782000-07-18Henrik Grubbström (Grubba)  check_tree(orig, 0);
01d4902000-07-11Fredrik Hübinette (Hubbe)  return orig; }
ff88db2000-07-12Henrik Grubbström (Grubba) #else /* !PIKE_DEBUG */
01d4902000-07-11Fredrik Hübinette (Hubbe) #define freeze_node(X) (X)
ff88db2000-07-12Henrik Grubbström (Grubba) #endif /* PIKE_DEBUG */
046afe1999-11-11Henrik Grubbström (Grubba) #endif /* SHARED_NODES */
a44a2c1998-05-01Henrik Grubbström (Grubba) void free_all_nodes(void)
a8ef6e1996-12-03Fredrik Hübinette (Hubbe) {
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(!Pike_compiler->compiler_frame)
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  { node *tmp;
011ad31999-10-22Fredrik Hübinette (Hubbe)  struct node_s_block *tmp2;
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  int e=0;
c3c7031996-12-04Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifndef PIKE_DEBUG
c3c7031996-12-04Fredrik Hübinette (Hubbe)  if(cumulative_parse_error)
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  {
3c0c281998-01-26Fredrik Hübinette (Hubbe) #endif
c3c7031996-12-04Fredrik Hübinette (Hubbe) 
011ad31999-10-22Fredrik Hübinette (Hubbe)  for(tmp2=node_s_blocks;tmp2;tmp2=tmp2->next) e+=NODES;
046afe1999-11-11Henrik Grubbström (Grubba)  for(tmp=free_node_ss;tmp;tmp=_CAR(tmp)) e--;
c3c7031996-12-04Fredrik Hübinette (Hubbe)  if(e)
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  {
c3c7031996-12-04Fredrik Hübinette (Hubbe)  int e2=e;
011ad31999-10-22Fredrik Hübinette (Hubbe)  for(tmp2=node_s_blocks;tmp2;tmp2=tmp2->next)
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  {
c3c7031996-12-04Fredrik Hübinette (Hubbe)  for(e=0;e<NODES;e++) {
046afe1999-11-11Henrik Grubbström (Grubba)  for(tmp=free_node_ss;tmp;tmp=_CAR(tmp))
011ad31999-10-22Fredrik Hübinette (Hubbe)  if(tmp==tmp2->x+e)
c3c7031996-12-04Fredrik Hübinette (Hubbe)  break; if(!tmp) {
011ad31999-10-22Fredrik Hübinette (Hubbe)  tmp=tmp2->x+e;
cbe8f32000-07-10Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG
c3c7031996-12-04Fredrik Hübinette (Hubbe)  if(!cumulative_parse_error) {
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr,"Free node at %p, (%s:%d) (token=%d).\n", tmp, tmp->current_file->str, tmp->line_number, tmp->token);
011ad31999-10-22Fredrik Hübinette (Hubbe) 
a4033e2000-04-14Fredrik Hübinette (Hubbe)  debug_malloc_dump_references(tmp,0,2,0);
011ad31999-10-22Fredrik Hübinette (Hubbe) 
3c0c281998-01-26Fredrik Hübinette (Hubbe)  if(tmp->token==F_CONSTANT) print_tree(tmp);
c3c7031996-12-04Fredrik Hübinette (Hubbe)  }
046afe1999-11-11Henrik Grubbström (Grubba)  /* else */
c3c7031996-12-04Fredrik Hübinette (Hubbe) #endif { /* Free the node and be happy */ /* Make sure we don't free any nodes twice */
046afe1999-11-11Henrik Grubbström (Grubba)  if(car_is_node(tmp)) _CAR(tmp)=0; if(cdr_is_node(tmp)) _CDR(tmp)=0; #ifdef SHARED_NODES tmp->hash = hash_node(tmp);
cf4df01999-11-12Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if (l_flag > 3) { fprintf(stderr, "Freeing node that had %d refs.\n", tmp->refs); } #endif /* PIKE_DEBUG */
046afe1999-11-11Henrik Grubbström (Grubba)  /* Force the node to be freed. */ tmp->refs = 1; #endif /* SHARED_NODES */
3c0c281998-01-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(tmp->type);
c3c7031996-12-04Fredrik Hübinette (Hubbe)  free_node(tmp); } } }
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  }
046afe1999-11-11Henrik Grubbström (Grubba) #if defined(PIKE_DEBUG)
c3c7031996-12-04Fredrik Hübinette (Hubbe)  if(!cumulative_parse_error) fatal("Failed to free %d nodes when compiling!\n",e2); #endif
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifndef PIKE_DEBUG
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  }
3c0c281998-01-26Fredrik Hübinette (Hubbe) #endif
011ad31999-10-22Fredrik Hübinette (Hubbe)  free_all_node_s_blocks();
c3c7031996-12-04Fredrik Hübinette (Hubbe)  cumulative_parse_error=0;
046afe1999-11-11Henrik Grubbström (Grubba)  #ifdef SHARED_NODES MEMSET(node_hash.table, 0, sizeof(node *) * node_hash.size); #endif /* SHARED_NODES */
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  } }
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
a836c01999-11-12Henrik Grubbström (Grubba) void debug_free_node(node *n)
5267b71995-08-09Fredrik Hübinette (Hubbe) { if(!n) return;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
1b5eb41998-11-17Fredrik Hübinette (Hubbe)  if(l_flag>9) print_tree(n);
046afe1999-11-11Henrik Grubbström (Grubba)  #ifdef SHARED_NODES {
93b7202000-08-14Henrik Grubbström (Grubba)  size_t hash;
046afe1999-11-11Henrik Grubbström (Grubba)  if ((hash = hash_node(n)) != n->hash) {
8fd0192000-08-15Henrik Grubbström (Grubba)  fprintf(stderr, "Hash-value is bad 0x%08lx != 0x%08lx\n",
93b7202000-08-14Henrik Grubbström (Grubba)  DO_NOT_WARN((unsigned long)hash), DO_NOT_WARN((unsigned long)n->hash));
046afe1999-11-11Henrik Grubbström (Grubba)  print_tree(n); fatal("token:%d, car:%p cdr:%p file:%s line:%d\n",
a836c01999-11-12Henrik Grubbström (Grubba)  n->token, _CAR(n), _CDR(n), n->current_file->str, n->line_number);
046afe1999-11-11Henrik Grubbström (Grubba)  } } #endif /* SHARED_NODES */ #endif /* PIKE_DEBUG */ #ifdef SHARED_NODES
a836c01999-11-12Henrik Grubbström (Grubba)  if (dmalloc_touch(node *, n) && --(n->refs)) {
046afe1999-11-11Henrik Grubbström (Grubba)  return; }
a836c01999-11-12Henrik Grubbström (Grubba)  sub_node(dmalloc_touch(node *, n));
046afe1999-11-11Henrik Grubbström (Grubba) #endif /* SHARED_NODES */
1b5eb41998-11-17Fredrik Hübinette (Hubbe) 
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(n->token) {
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  case USHRT_MAX: fatal("Freeing node again!\n"); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CONSTANT: free_svalue(&(n->u.sval)); break; default: if(car_is_node(n)) free_node(CAR(n)); if(cdr_is_node(n)) free_node(CDR(n)); }
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  n->token=USHRT_MAX; if(n->type) free_string(n->type);
454d541999-09-18Fredrik Hübinette (Hubbe)  if(n->name) free_string(n->name);
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
3c0c281998-01-26Fredrik Hübinette (Hubbe)  if(n->current_file) free_string(n->current_file); #endif
011ad31999-10-22Fredrik Hübinette (Hubbe)  really_free_node_s(n);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
046afe1999-11-11Henrik Grubbström (Grubba) node *debug_check_node_hash(node *n) { #if defined(PIKE_DEBUG) && defined(SHARED_NODES) if (n && (n->hash != hash_node(n))) {
bf4f7d1999-11-12Henrik Grubbström (Grubba)  fprintf(stderr,"Bad node hash at %p, (%s:%d) (token=%d).\n", n, n->current_file->str, n->line_number, n->token);
f76b4c2000-05-11Henrik Grubbström (Grubba)  debug_malloc_dump_references(n,0,0,0);
bf4f7d1999-11-12Henrik Grubbström (Grubba)  print_tree(n);
046afe1999-11-11Henrik Grubbström (Grubba)  fatal("Bad node hash!\n"); } #endif /* PIKE_DEBUG && SHARED_NODES */ return n; }
5267b71995-08-09Fredrik Hübinette (Hubbe) /* here starts routines to make nodes */
a836c01999-11-12Henrik Grubbström (Grubba) static node *debug_mkemptynode(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
011ad31999-10-22Fredrik Hübinette (Hubbe)  node *res=alloc_node_s();
046afe1999-11-11Henrik Grubbström (Grubba)  #ifdef SHARED_NODES MEMSET(res, 0, sizeof(node)); res->hash = 0; res->refs = 1; #endif /* SHARED_NODES */
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  res->token=0;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  res->line_number=lex.current_line;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
3c0c281998-01-26Fredrik Hübinette (Hubbe)  copy_shared_string(res->current_file, lex.current_file); #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  res->type=0;
454d541999-09-18Fredrik Hübinette (Hubbe)  res->name=0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  res->node_info=0; res->tree_info=0; res->parent=0; return res; }
a836c01999-11-12Henrik Grubbström (Grubba) #define mkemptynode() dmalloc_touch(node *, debug_mkemptynode()) node *debug_mknode(short token, node *a, node *b)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node *res;
046afe1999-11-11Henrik Grubbström (Grubba)  #if defined(PIKE_DEBUG) && !defined(SHARED_NODES)
a836c01999-11-12Henrik Grubbström (Grubba)  if(b && a==b)
32e2af1998-11-17Fredrik Hübinette (Hubbe)  fatal("mknode: a and be are the same!\n");
84191b1999-11-23Henrik Grubbström (Grubba)  if ((token == F_CAST) || (token == F_SOFT_CAST))
f68afd1999-11-20Henrik Grubbström (Grubba)  fatal("Attempt to create a cast-node with mknode()!\n");
32e2af1998-11-17Fredrik Hübinette (Hubbe) #endif
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(a,0); check_tree(b,0);
046afe1999-11-11Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  res = mkemptynode();
a836c01999-11-12Henrik Grubbström (Grubba)  _CAR(res) = dmalloc_touch(node *, a); _CDR(res) = dmalloc_touch(node *, b);
5267b71995-08-09Fredrik Hübinette (Hubbe)  res->node_info = 0; res->tree_info = 0;
046afe1999-11-11Henrik Grubbström (Grubba)  if(a) { a->parent = res; } if(b) { b->parent = res; }
ba6d6c1998-04-19Fredrik Hübinette (Hubbe) 
046afe1999-11-11Henrik Grubbström (Grubba)  res->token = token; res->type = 0; #ifdef SHARED_NODES { node *res2 = freeze_node(res); if (res2 != res) {
a836c01999-11-12Henrik Grubbström (Grubba)  return dmalloc_touch(node *, res2);
046afe1999-11-11Henrik Grubbström (Grubba)  } } #endif /* SHARED_NODES */
ba6d6c1998-04-19Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(token) { case F_CATCH: res->node_info |= OPT_SIDE_EFFECT;
b464611999-11-14Henrik Grubbström (Grubba)  if (a) { res->tree_info |= a->tree_info & ~OPT_BREAK; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case F_APPLY:
e260681996-04-11Fredrik Hübinette (Hubbe)  {
1ef5572000-08-30Henrik Grubbström (Grubba)  unsigned INT16 opt_flags = OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND; struct identifier *i = NULL; if (a) { switch(a->token) { case F_CONSTANT: if (a->u.sval.type == T_FUNCTION) { if (a->u.sval.subtype == FUNCTION_BUILTIN) { opt_flags = a->u.sval.u.efun->flags; } else if (a->u.sval.u.object->prog) { i = ID_FROM_INT(a->u.sval.u.object->prog, a->u.sval.subtype); } else { yyerror("Calling function in destructed module."); } } break; case F_EXTERNAL: { struct program_state *state = Pike_compiler; int program_id = a->u.integer.a; while (state && (state->new_program->id != program_id)) { state = state->previous; } if (state) { i = ID_FROM_INT(state->new_program, a->u.integer.b); } else { yyerror("Parent has left."); } } break; case F_LOCAL: /* FIXME: Should lookup functions in the local scope. */ default: res->tree_info |= a->tree_info; } if (i && IDENTIFIER_IS_FUNCTION(i->identifier_flags)) { res->node_info |= i->opt_flags; } else { res->node_info |= opt_flags; } } else { res->node_info |= opt_flags; } if(b) res->tree_info |= b->tree_info;
e260681996-04-11Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  break;
2a8cd81999-11-18Henrik Grubbström (Grubba)  case F_POP_VALUE: copy_shared_string(res->type, void_type_string); if(a) res->tree_info |= a->tree_info; if(b) res->tree_info |= b->tree_info; break;
6369f61999-03-11Fredrik Hübinette (Hubbe)  case F_MAGIC_SET_INDEX:
b464611999-11-14Henrik Grubbström (Grubba)  res->node_info |= OPT_ASSIGNMENT; /* FALL_THROUGH */ case F_MAGIC_INDEX: res->node_info |= OPT_EXTERNAL_DEPEND;
f9abcf1999-09-16Fredrik Hübinette (Hubbe)  break;
6369f61999-03-11Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  case F_UNDEFINED: res->node_info |= OPT_EXTERNAL_DEPEND | OPT_SIDE_EFFECT; break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_RETURN: res->node_info |= OPT_RETURN; break; case F_BREAK: res->node_info |= OPT_BREAK; break; case F_CONTINUE: res->node_info |= OPT_CONTINUE; break; case F_DEFAULT: case F_CASE: res->node_info |= OPT_CASE; break;
b464611999-11-14Henrik Grubbström (Grubba)  case F_INC_LOOP: case F_INC_NEQ_LOOP: case F_DEC_LOOP: case F_DEC_NEQ_LOOP: res->node_info |= OPT_ASSIGNMENT; if (a) { res->tree_info |= a->tree_info; } if (b) { res->tree_info |= (b->tree_info & ~(OPT_BREAK|OPT_CONTINUE)); } break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_SSCANF: if(!b || count_args(b) == 0) break;
b464611999-11-14Henrik Grubbström (Grubba)  res->node_info |= OPT_ASSIGNMENT; break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_ASSIGN:
b464611999-11-14Henrik Grubbström (Grubba)  case F_MOD_EQ: case F_AND_EQ: case F_MULT_EQ: case F_ADD_EQ: case F_SUB_EQ: case F_DIV_EQ: case F_LSH_EQ: case F_RSH_EQ: case F_XOR_EQ: case F_OR_EQ: res->node_info |= OPT_ASSIGNMENT; if (a) { res->tree_info |= a->tree_info; } if (b) { res->tree_info |= b->tree_info; } break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_INC: case F_DEC: case F_POST_INC: case F_POST_DEC: res->node_info |= OPT_ASSIGNMENT;
b464611999-11-14Henrik Grubbström (Grubba)  if (a) { res->tree_info |= a->tree_info; }
ba6d6c1998-04-19Fredrik Hübinette (Hubbe)  break;
046afe1999-11-11Henrik Grubbström (Grubba)  default: if(a) res->tree_info |= a->tree_info; if(b) res->tree_info |= b->tree_info;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
f68afd1999-11-20Henrik Grubbström (Grubba)  /* We try to optimize most things, but argument lists are hard... */ if(token != F_ARG_LIST && (a || b)) res->node_info |= OPT_TRY_OPTIMIZE;
b464611999-11-14Henrik Grubbström (Grubba)  res->tree_info |= res->node_info;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
9e52381998-03-01Fredrik Hübinette (Hubbe)  if(d_flag > 3) verify_shared_strings_tables(); #endif
01d4902000-07-11Fredrik Hübinette (Hubbe)  check_tree(res,0);
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(!Pike_compiler->num_parse_error && Pike_compiler->compiler_pass==2)
3c0c281998-01-26Fredrik Hübinette (Hubbe)  {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  optimize(res);
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(res,0); }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
66d51c1997-03-04Fredrik Hübinette (Hubbe)  if(d_flag > 3) verify_shared_strings_tables(); #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  return res; }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkstrnode(struct pike_string *str)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node *res = mkemptynode(); res->token = F_CONSTANT; copy_shared_string(res->type, string_type_string); res->node_info = 0; res->u.sval.type = T_STRING; #ifdef __CHECKER__ res->u.sval.subtype = 0; #endif copy_shared_string(res->u.sval.u.string, str);
046afe1999-11-11Henrik Grubbström (Grubba)  return freeze_node(res);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkintnode(int nr)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node *res = mkemptynode(); res->token = F_CONSTANT; res->node_info = 0; res->u.sval.type = T_INT; res->u.sval.subtype = NUMBER_NUMBER; res->u.sval.u.integer = nr;
b660c81999-03-01Fredrik Hübinette (Hubbe)  res->type=get_type_of_svalue( & res->u.sval);
046afe1999-11-11Henrik Grubbström (Grubba)  return freeze_node(res); }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mknewintnode(int nr)
046afe1999-11-11Henrik Grubbström (Grubba) { node *res = mkemptynode(); res->token = F_CONSTANT;
a836c01999-11-12Henrik Grubbström (Grubba)  res->node_info = OPT_NOT_SHARED;
046afe1999-11-11Henrik Grubbström (Grubba)  res->u.sval.type = T_INT; res->u.sval.subtype = NUMBER_NUMBER; res->u.sval.u.integer = nr; res->type=get_type_of_svalue( & res->u.sval); #ifdef SHARED_NODES res->refs = 1; res->hash = hash_node(res); #endif /* SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe)  return res; }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkfloatnode(FLOAT_TYPE foo)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node *res = mkemptynode(); res->token = F_CONSTANT; copy_shared_string(res->type, float_type_string); res->u.sval.type = T_FLOAT; #ifdef __CHECKER__ res->u.sval.subtype = 0; #endif res->u.sval.u.float_number = foo;
046afe1999-11-11Henrik Grubbström (Grubba)  return freeze_node(res);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
a5787d1999-03-03Fredrik Hübinette (Hubbe) 
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkprgnode(struct program *p)
a5787d1999-03-03Fredrik Hübinette (Hubbe) { struct svalue s; s.u.program=p;
046afe1999-11-11Henrik Grubbström (Grubba)  s.type = T_PROGRAM; #ifdef __CHECKER__ s.subtype = 0; #endif
a5787d1999-03-03Fredrik Hübinette (Hubbe)  return mkconstantsvaluenode(&s); }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkapplynode(node *func,node *args)
5267b71995-08-09Fredrik Hübinette (Hubbe) { return mknode(F_APPLY, func, args); }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkefuncallnode(char *function, node *args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct pike_string *name;
45e8a81997-01-26Fredrik Hübinette (Hubbe)  node *n;
5267b71995-08-09Fredrik Hübinette (Hubbe)  name = findstring(function);
2816052000-03-30Fredrik Hübinette (Hubbe)  if(!name || !(n=find_module_identifier(name,0)))
5267b71995-08-09Fredrik Hübinette (Hubbe)  { my_yyerror("Internally used efun undefined: %s",function); return mkintnode(0); }
046afe1999-11-11Henrik Grubbström (Grubba)  n = mkapplynode(n, args);
45e8a81997-01-26Fredrik Hübinette (Hubbe)  return n;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkopernode(char *oper_id, node *arg1, node *arg2)
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) { if(arg1 && arg2) arg1=mknode(F_ARG_LIST,arg1,arg2); return mkefuncallnode(oper_id, arg1); }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mklocalnode(int var, int depth)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
4218011999-01-31Fredrik Hübinette (Hubbe)  struct compiler_frame *f; int e;
5267b71995-08-09Fredrik Hübinette (Hubbe)  node *res = mkemptynode(); res->token = F_LOCAL;
4218011999-01-31Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  f=Pike_compiler->compiler_frame;
4218011999-01-31Fredrik Hübinette (Hubbe)  for(e=0;e<depth;e++) f=f->previous; copy_shared_string(res->type, f->variable[var].type);
a836c01999-11-12Henrik Grubbström (Grubba)  res->node_info = OPT_NOT_CONST | OPT_NOT_SHARED; res->tree_info = res->node_info;
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef __CHECKER__
046afe1999-11-11Henrik Grubbström (Grubba)  _CDR(res) = 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
4218011999-01-31Fredrik Hübinette (Hubbe)  res->u.integer.a = var; res->u.integer.b = depth;
046afe1999-11-11Henrik Grubbström (Grubba)  #ifdef SHARED_NODES
a836c01999-11-12Henrik Grubbström (Grubba)  /* FIXME: Not common-subexpression optimized. * Node would need to contain a ref to the current function, * and to the current program. */
046afe1999-11-11Henrik Grubbström (Grubba)  res->hash = hash_node(res); /* return freeze_node(res); */ #endif /* SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe)  return res; }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkidentifiernode(int i)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
342fef2000-08-23Fredrik Hübinette (Hubbe) #if 1
da77e22000-09-08Fredrik Hübinette (Hubbe)  node *res = mkexternalnode(Pike_compiler->new_program, i); check_tree(res,0); return res;
342fef2000-08-23Fredrik Hübinette (Hubbe) #else
5267b71995-08-09Fredrik Hübinette (Hubbe)  node *res = mkemptynode(); res->token = F_IDENTIFIER;
bad5162000-06-23Fredrik Hübinette (Hubbe)  copy_shared_string(res->type, ID_FROM_INT(Pike_compiler->new_program, i)->type);
5267b71995-08-09Fredrik Hübinette (Hubbe)  /* FIXME */
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(IDENTIFIER_IS_CONSTANT(ID_FROM_INT(Pike_compiler->new_program, i)->identifier_flags))
3856c31996-11-25Fredrik Hübinette (Hubbe)  { res->node_info = OPT_EXTERNAL_DEPEND; }else{ res->node_info = OPT_NOT_CONST; }
66d51c1997-03-04Fredrik Hübinette (Hubbe)  res->tree_info=res->node_info;
5267b71995-08-09Fredrik Hübinette (Hubbe)  #ifdef __CHECKER__
588aa31999-11-11Henrik Grubbström (Grubba)  _CDR(res) = 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
046afe1999-11-11Henrik Grubbström (Grubba)  res->u.id.number = i; #ifdef SHARED_NODES
bad5162000-06-23Fredrik Hübinette (Hubbe)  res->u.id.prog = Pike_compiler->new_program;
046afe1999-11-11Henrik Grubbström (Grubba) #endif /* SHARED_NODES */ res = freeze_node(res);
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(res,0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return res;
342fef2000-08-23Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) }
bf4f7d1999-11-12Henrik Grubbström (Grubba) node *debug_mktrampolinenode(int i) { node *res = mkemptynode(); res->token = F_TRAMPOLINE;
bad5162000-06-23Fredrik Hübinette (Hubbe)  copy_shared_string(res->type, ID_FROM_INT(Pike_compiler->new_program, i)->type);
bf4f7d1999-11-12Henrik Grubbström (Grubba)  /* FIXME */
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(IDENTIFIER_IS_CONSTANT(ID_FROM_INT(Pike_compiler->new_program, i)->identifier_flags))
bf4f7d1999-11-12Henrik Grubbström (Grubba)  { res->node_info = OPT_EXTERNAL_DEPEND; }else{ res->node_info = OPT_NOT_CONST; } res->tree_info=res->node_info; #ifdef __CHECKER__ _CDR(res) = 0; #endif res->u.id.number = i; #ifdef SHARED_NODES
bad5162000-06-23Fredrik Hübinette (Hubbe)  res->u.id.prog = Pike_compiler->new_program;
bf4f7d1999-11-12Henrik Grubbström (Grubba) #endif /* SHARED_NODES */ res = freeze_node(res); check_tree(res,0); return res; }
ff88db2000-07-12Henrik Grubbström (Grubba) node *debug_mkexternalnode(struct program *parent_prog, int i)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) { node *res = mkemptynode();
ff88db2000-07-12Henrik Grubbström (Grubba)  struct identifier *id;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  res->token = F_EXTERNAL;
5c604d2000-07-12Martin Stjernholm  id = ID_FROM_INT(parent_prog, i);
01d4902000-07-11Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(d_flag) { check_string(id->type); check_string(id->name); } #endif
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  copy_shared_string(res->type, id->type); /* FIXME */
0f3e462000-07-11Henrik Grubbström (Grubba)  if(IDENTIFIER_IS_CONSTANT(id->identifier_flags))
6d22541998-01-28Fredrik Hübinette (Hubbe)  { res->node_info = OPT_EXTERNAL_DEPEND; }else{ res->node_info = OPT_NOT_CONST; }
046afe1999-11-11Henrik Grubbström (Grubba)  res->tree_info = res->node_info;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  #ifdef __CHECKER__
046afe1999-11-11Henrik Grubbström (Grubba)  _CDR(res) = 0;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #endif
ff88db2000-07-12Henrik Grubbström (Grubba)  res->u.integer.a = parent_prog->id;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  res->u.integer.b = i;
1994251999-09-06Fredrik Hübinette (Hubbe)  /* Bzot-i-zot */
342fef2000-08-23Fredrik Hübinette (Hubbe)  if(parent_prog != Pike_compiler->new_program) Pike_compiler->new_program->flags |= PROGRAM_USES_PARENT;
1994251999-09-06Fredrik Hübinette (Hubbe) 
da77e22000-09-08Fredrik Hübinette (Hubbe)  res=freeze_node(res); #ifdef PIKE_DEBUG
cfe1fe2000-09-09Fredrik Hübinette (Hubbe)  /* FIXME: This test crashes on valid code because the type of the * identifier can change in pass 2 -Hubbe */ if(d_flag && id->type != res->type)
da77e22000-09-08Fredrik Hübinette (Hubbe)  { printf("Type of external node is not matching it's identifier.\nid->type: "); simple_describe_type(id->type); printf("\nres->type : "); simple_describe_type(res->type); printf("\n"); fatal("Type of external node is not matching it's identifier.\n"); } #endif return res;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkcastnode(struct pike_string *type,node *n)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node *res;
046afe1999-11-11Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!n) return 0;
046afe1999-11-11Henrik Grubbström (Grubba) 
1d480f1999-11-23Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG
f68afd1999-11-20Henrik Grubbström (Grubba)  if (!type) { fatal("Casting to no type!\n"); }
1d480f1999-11-23Henrik Grubbström (Grubba) #endif /* PIKE_DEBUG */
f68afd1999-11-20Henrik Grubbström (Grubba) 
22dd601999-11-18Henrik Grubbström (Grubba)  if (type == void_type_string) return mknode(F_POP_VALUE, n, 0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(type==n->type) return n;
046afe1999-11-11Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  res = mkemptynode(); res->token = F_CAST; copy_shared_string(res->type,type); if(match_types(object_type_string, type) || match_types(object_type_string, type)) res->node_info |= OPT_SIDE_EFFECT;
7cbf2c1999-12-14Henrik Grubbström (Grubba)  res->tree_info |= n->tree_info;
046afe1999-11-11Henrik Grubbström (Grubba)  _CAR(res) = n;
cbe8f32000-07-10Henrik Grubbström (Grubba)  _CDR(res) = mktypenode(type);
046afe1999-11-11Henrik Grubbström (Grubba) 
bf4f7d1999-11-12Henrik Grubbström (Grubba)  n->parent = res;
046afe1999-11-11Henrik Grubbström (Grubba)  return freeze_node(res);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1d480f1999-11-23Henrik Grubbström (Grubba) node *debug_mksoftcastnode(struct pike_string *type,node *n) { node *res; if(!n) return 0; #ifdef PIKE_DEBUG if (!type) { fatal("Soft cast to no type!\n"); } #endif /* PIKE_DEBUG */
bad5162000-06-23Fredrik Hübinette (Hubbe)  if (Pike_compiler->compiler_pass == 2) {
1fcad41999-12-30Henrik Grubbström (Grubba)  if (type == void_type_string) { yywarning("Soft cast to void."); return mknode(F_POP_VALUE, n, 0); }
1d480f1999-11-23Henrik Grubbström (Grubba) 
1fcad41999-12-30Henrik Grubbström (Grubba)  if(type==n->type) {
1d480f1999-11-23Henrik Grubbström (Grubba)  struct pike_string *t1 = describe_type(type);
1fcad41999-12-30Henrik Grubbström (Grubba)  yywarning("Soft cast to %s is a noop.", t1->str);
1d480f1999-11-23Henrik Grubbström (Grubba)  free_string(t1);
1fcad41999-12-30Henrik Grubbström (Grubba)  return n; } if (n->type) { if (!check_soft_cast(type, n->type)) { struct pike_string *t1 = describe_type(type); struct pike_string *t2 = describe_type(n->type); yywarning("Soft cast to %s isn't a restriction of %s.", t1->str, t2->str); free_string(t2); free_string(t1); } /* FIXME: check_soft_cast() is weaker than pike_types_le() * The resulting type should probably be the and between the old * and the new type. */
1d480f1999-11-23Henrik Grubbström (Grubba)  } }
1fcad41999-12-30Henrik Grubbström (Grubba) 
1d480f1999-11-23Henrik Grubbström (Grubba)  res = mkemptynode(); res->token = F_SOFT_CAST;
cbe8f32000-07-10Henrik Grubbström (Grubba)  copy_shared_string(res->type, type);
1d480f1999-11-23Henrik Grubbström (Grubba) 
7cbf2c1999-12-14Henrik Grubbström (Grubba)  res->tree_info |= n->tree_info;
1d480f1999-11-23Henrik Grubbström (Grubba)  _CAR(res) = n;
cbe8f32000-07-10Henrik Grubbström (Grubba)  _CDR(res) = mktypenode(type);
1d480f1999-11-23Henrik Grubbström (Grubba)  n->parent = res; return freeze_node(res); }
591c0c1997-01-19Fredrik Hübinette (Hubbe) void resolv_constant(node *n) { struct identifier *i;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  struct program *p; INT32 numid;
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(n,0);
591c0c1997-01-19Fredrik Hübinette (Hubbe)  if(!n) { push_int(0); }else{ switch(n->token) { case F_CONSTANT: push_svalue(& n->u.sval);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  return;
591c0c1997-01-19Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  case F_EXTERNAL:
591c0c1997-01-19Fredrik Hübinette (Hubbe)  {
342fef2000-08-23Fredrik Hübinette (Hubbe)  struct program_state *state = Pike_compiler;
ff88db2000-07-12Henrik Grubbström (Grubba)  while (state && (state->new_program->id != n->u.integer.a)) { state = state->previous; } if(!state) { yyerror("Failed to resolv external constant"); push_int(0); return; } p = state->new_program; numid=n->u.integer.b;
591c0c1997-01-19Fredrik Hübinette (Hubbe)  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  break; case F_IDENTIFIER:
bad5162000-06-23Fredrik Hübinette (Hubbe)  p=Pike_compiler->new_program;
046afe1999-11-11Henrik Grubbström (Grubba)  numid=n->u.id.number;
591c0c1997-01-19Fredrik Hübinette (Hubbe)  break; case F_LOCAL:
9250a61998-07-20Henrik Grubbström (Grubba)  /* FIXME: Ought to have the name of the identifier in the message. */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  yyerror("Expected constant, got local variable"); push_int(0); return;
591c0c1997-01-19Fredrik Hübinette (Hubbe)  case F_GLOBAL:
9250a61998-07-20Henrik Grubbström (Grubba)  /* FIXME: Ought to have the name of the identifier in the message. */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  yyerror("Expected constant, got global variable"); push_int(0); return;
b69ede1998-04-09Fredrik Hübinette (Hubbe)  case F_UNDEFINED:
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->compiler_pass==2) {
9250a61998-07-20Henrik Grubbström (Grubba)  /* FIXME: Ought to have the name of the identifier in the message. */
b69ede1998-04-09Fredrik Hübinette (Hubbe)  yyerror("Expected constant, got undefined identifier");
9250a61998-07-20Henrik Grubbström (Grubba)  }
b69ede1998-04-09Fredrik Hübinette (Hubbe)  push_int(0); return;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  default:
c5c2ff1999-07-06Fredrik Hübinette (Hubbe)  { char fnord[1000]; if(is_const(n)) {
93b7202000-08-14Henrik Grubbström (Grubba)  ptrdiff_t args=eval_low(n);
c5c2ff1999-07-06Fredrik Hübinette (Hubbe)  if(args==1) return; if(args!=-1) { if(!args) { yyerror("Expected constant, got void expression"); }else{ yyerror("Possible internal error!!!");
93b7202000-08-14Henrik Grubbström (Grubba)  pop_n_elems(DO_NOT_WARN(args-1));
c5c2ff1999-07-06Fredrik Hübinette (Hubbe)  return; } } } sprintf(fnord,"Expected constant, got something else (%d)",n->token); yyerror(fnord);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  push_int(0); return; }
c5c2ff1999-07-06Fredrik Hübinette (Hubbe)  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  i=ID_FROM_INT(p, numid);
086acc1999-09-11Fredrik Hübinette (Hubbe)  /* Warning: * This code doesn't produce function pointers for class constants, * which can be harmful... * /Hubbe */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(IDENTIFIER_IS_CONSTANT(i->identifier_flags)) {
e945ee2000-02-09Fredrik Hübinette (Hubbe)  if(i->func.offset != -1) { push_svalue(&PROG_FROM_INT(p, numid)->constants[i->func.offset].sval); }else{
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->compiler_pass!=1)
e945ee2000-02-09Fredrik Hübinette (Hubbe)  yyerror("Constant is not defined yet."); push_int(0); }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }else{
9250a61998-07-20Henrik Grubbström (Grubba)  my_yyerror("Identifier '%s' is not a constant", i->name->str);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  push_int(0);
591c0c1997-01-19Fredrik Hübinette (Hubbe)  } } }
086acc1999-09-11Fredrik Hübinette (Hubbe) /* Leaves a function or object on the stack */ void resolv_class(node *n)
61e9a01998-01-25Fredrik Hübinette (Hubbe) {
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(n,0);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  resolv_constant(n);
cd86322000-07-06Fredrik Hübinette (Hubbe)  switch(Pike_sp[-1].type)
61e9a01998-01-25Fredrik Hübinette (Hubbe)  { case T_OBJECT:
cd86322000-07-06Fredrik Hübinette (Hubbe)  if(!Pike_sp[-1].u.object->prog)
61e9a01998-01-25Fredrik Hübinette (Hubbe)  { pop_stack(); push_int(0); }else{ f_object_program(1); } break;
01a9572000-02-03Henrik Grubbström (Grubba) 
086acc1999-09-11Fredrik Hübinette (Hubbe)  default:
bad5162000-06-23Fredrik Hübinette (Hubbe)  if (Pike_compiler->compiler_pass!=1)
a786431999-11-18Martin Stjernholm  yyerror("Illegal program identifier");
086acc1999-09-11Fredrik Hübinette (Hubbe)  pop_stack(); push_int(0); case T_FUNCTION: case T_PROGRAM: break; } } /* This one always leaves a program if possible */ void resolv_program(node *n) { check_tree(n,0); resolv_class(n);
cd86322000-07-06Fredrik Hübinette (Hubbe)  switch(Pike_sp[-1].type)
086acc1999-09-11Fredrik Hübinette (Hubbe)  {
61e9a01998-01-25Fredrik Hübinette (Hubbe)  case T_FUNCTION:
cd86322000-07-06Fredrik Hübinette (Hubbe)  if(program_from_function(Pike_sp-1))
61e9a01998-01-25Fredrik Hübinette (Hubbe)  break; default:
bad5162000-06-23Fredrik Hübinette (Hubbe)  if (Pike_compiler->compiler_pass!=1)
a786431999-11-18Martin Stjernholm  yyerror("Illegal program identifier");
61e9a01998-01-25Fredrik Hübinette (Hubbe)  pop_stack(); push_int(0); case T_PROGRAM: break; } }
fae37d1998-08-30Henrik Grubbström (Grubba) node *index_node(node *n, char *node_name, struct pike_string *id)
591c0c1997-01-19Fredrik Hübinette (Hubbe) { node *ret; JMP_BUF tmp;
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(n,0);
591c0c1997-01-19Fredrik Hübinette (Hubbe)  if(SETJMP(tmp)) { ONERROR tmp;
cbe8f32000-07-10Henrik Grubbström (Grubba)  struct svalue s;
591c0c1997-01-19Fredrik Hübinette (Hubbe)  SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!");
cbe8f32000-07-10Henrik Grubbström (Grubba)  assign_svalue_no_free(Pike_sp++, &throw_value); assign_svalue_no_free(&s, &throw_value);
591c0c1997-01-19Fredrik Hübinette (Hubbe)  APPLY_MASTER("handle_error", 1); pop_stack(); UNSET_ONERROR(tmp);
fae37d1998-08-30Henrik Grubbström (Grubba)  if (node_name) { my_yyerror("Couldn't index module '%s'.", node_name); } else { yyerror("Couldn't index module."); }
cbe8f32000-07-10Henrik Grubbström (Grubba)  if ((s.type == T_ARRAY) && s.u.array->size && (s.u.array->item[0].type == T_STRING)) { /* Old-style backtrace */ my_yyerror("Error: '%s'.", s.u.array->item[0].u.string->str); } else if (s.type == T_OBJECT) { struct generic_error_struct *ge; if ((ge = (struct generic_error_struct *) get_storage(s.u.object, generic_error_program))) { my_yyerror("Error: '%s'.", ge->desc->str); } } free_svalue(&s);
591c0c1997-01-19Fredrik Hübinette (Hubbe)  }else{ resolv_constant(n);
cd86322000-07-06Fredrik Hübinette (Hubbe)  switch(Pike_sp[-1].type)
d6aef21997-02-27Fredrik Hübinette (Hubbe)  {
1470d81997-02-27Fredrik Hübinette (Hubbe)  case T_INT:
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(!Pike_compiler->num_parse_error) {
fae37d1998-08-30Henrik Grubbström (Grubba)  if (node_name) {
16addb1999-12-10Henrik Grubbström (Grubba)  my_yyerror("Failed to index module '%s' with '%s' " "(module doesn't exist?)", node_name, id->str);
fae37d1998-08-30Henrik Grubbström (Grubba)  } else {
16addb1999-12-10Henrik Grubbström (Grubba)  my_yyerror("Failed to index module with '%s' " "(module doesn't exist?)", id->str);
fae37d1998-08-30Henrik Grubbström (Grubba)  } }
1470d81997-02-27Fredrik Hübinette (Hubbe)  break; case T_FLOAT: case T_STRING: case T_ARRAY:
fae37d1998-08-30Henrik Grubbström (Grubba)  if (node_name) { my_yyerror("Failed to index module '%s' (Not a module?)", node_name); } else { yyerror("Failed to index module (Not a module?)"); }
e319bb1997-02-28Fredrik Hübinette (Hubbe)  pop_stack(); push_int(0);
1470d81997-02-27Fredrik Hübinette (Hubbe)  break; default:
63c6751998-04-09Fredrik Hübinette (Hubbe)  {
93b7202000-08-14Henrik Grubbström (Grubba)  ptrdiff_t c;
63c6751998-04-09Fredrik Hübinette (Hubbe)  DECLARE_CYCLIC();
93b7202000-08-14Henrik Grubbström (Grubba)  c = (ptrdiff_t)BEGIN_CYCLIC(Pike_sp[-1].u.refs, id);
14bb592000-05-06Fredrik Hübinette (Hubbe)  if(c>1)
7485201997-02-27Fredrik Hübinette (Hubbe)  {
63c6751998-04-09Fredrik Hübinette (Hubbe)  my_yyerror("Recursive module dependency in '%s'.",id->str); pop_stack(); push_int(0); }else{
14bb592000-05-06Fredrik Hübinette (Hubbe)  SET_CYCLIC_RET(c+1);
63c6751998-04-09Fredrik Hübinette (Hubbe)  ref_push_string(id);
a70ee01999-05-01Henrik Grubbström (Grubba)  {
cd86322000-07-06Fredrik Hübinette (Hubbe)  struct svalue *save_sp = Pike_sp-2;
a70ee01999-05-01Henrik Grubbström (Grubba)  JMP_BUF recovery; if (SETJMP(recovery)) { /* f_index() threw an error! * * FIXME: Report the error thrown. */
cd86322000-07-06Fredrik Hübinette (Hubbe)  if (Pike_sp > save_sp) { pop_n_elems(Pike_sp - save_sp); } else if (Pike_sp != save_sp) {
a70ee01999-05-01Henrik Grubbström (Grubba)  fatal("f_index() munged stack!\n"); } push_int(0);
cd86322000-07-06Fredrik Hübinette (Hubbe)  Pike_sp[-1].subtype = NUMBER_UNDEFINED;
a70ee01999-05-01Henrik Grubbström (Grubba)  } else { f_index(2); }
cc20e31999-05-01Henrik Grubbström (Grubba)  UNSETJMP(recovery);
a70ee01999-05-01Henrik Grubbström (Grubba)  }
63c6751998-04-09Fredrik Hübinette (Hubbe) 
cd86322000-07-06Fredrik Hübinette (Hubbe)  if(Pike_sp[-1].type == T_INT && !Pike_sp[-1].u.integer && Pike_sp[-1].subtype==NUMBER_UNDEFINED)
63c6751998-04-09Fredrik Hübinette (Hubbe)  {
fae37d1998-08-30Henrik Grubbström (Grubba)  if (node_name) { my_yyerror("Index '%s' not present in module '%s'.", id->str, node_name); } else { my_yyerror("Index '%s' not present in module.", id->str); }
63c6751998-04-09Fredrik Hübinette (Hubbe)  }
7485201997-02-27Fredrik Hübinette (Hubbe)  }
14bb592000-05-06Fredrik Hübinette (Hubbe)  END_CYCLIC();
d6aef21997-02-27Fredrik Hübinette (Hubbe)  }
63c6751998-04-09Fredrik Hübinette (Hubbe)  }
591c0c1997-01-19Fredrik Hübinette (Hubbe)  } UNSETJMP(tmp);
cd86322000-07-06Fredrik Hübinette (Hubbe)  ret=mkconstantsvaluenode(Pike_sp-1);
591c0c1997-01-19Fredrik Hübinette (Hubbe)  pop_stack(); return ret; }
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
5267b71995-08-09Fredrik Hübinette (Hubbe) int node_is_eq(node *a,node *b) {
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(a,0); check_tree(b,0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(a == b) return 1; if(!a || !b) return 0; if(a->token != b->token) return 0;
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(a->token) { case F_LOCAL:
7d7d7e1999-01-31Fredrik Hübinette (Hubbe)  return a->u.integer.a == b->u.integer.a && a->u.integer.b == b->u.integer.b;
4218011999-01-31Fredrik Hübinette (Hubbe) 
afa3651996-02-10Fredrik Hübinette (Hubbe)  case F_IDENTIFIER:
4218011999-01-31Fredrik Hübinette (Hubbe)  case F_TRAMPOLINE: /* FIXME, the context has to be the same! */
046afe1999-11-11Henrik Grubbström (Grubba)  return a->u.id.number == b->u.id.number;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CAST:
84191b1999-11-23Henrik Grubbström (Grubba)  case F_SOFT_CAST:
5267b71995-08-09Fredrik Hübinette (Hubbe)  return a->type == b->type && node_is_eq(CAR(a), CAR(b)); case F_CONSTANT: return is_equal(&(a->u.sval), &(b->u.sval)); default: if( a->type != b->type ) return 0; if(car_is_node(a) && !node_is_eq(CAR(a), CAR(b))) return 0; if(cdr_is_node(a) && !node_is_eq(CDR(a), CDR(b))) return 0; return 1; } }
0592971999-12-15Henrik Grubbström (Grubba) node *debug_mktypenode(struct pike_string *t) { node *res = mkemptynode(); res->token = F_CONSTANT; copy_shared_string(res->u.sval.u.string, t); res->u.sval.type = T_TYPE; copy_shared_string(res->type, type_type_string); return freeze_node(res); }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkconstantsvaluenode(struct svalue *s)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node *res = mkemptynode(); res->token = F_CONSTANT; assign_svalue_no_free(& res->u.sval, s);
046afe1999-11-11Henrik Grubbström (Grubba)  if(s->type == T_OBJECT || (s->type==T_FUNCTION && s->subtype!=FUNCTION_BUILTIN))
e82b301997-01-29Fredrik Hübinette (Hubbe)  {
993ba72000-02-15Fredrik Hübinette (Hubbe)  res->node_info|=OPT_EXTERNAL_DEPEND;
e82b301997-01-29Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  res->type = get_type_of_svalue(s);
046afe1999-11-11Henrik Grubbström (Grubba)  return freeze_node(res);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkliteralsvaluenode(struct svalue *s)
5683de1995-11-06Fredrik Hübinette (Hubbe) { node *res = mkconstantsvaluenode(s);
046afe1999-11-11Henrik Grubbström (Grubba)  /* FIXME: The following affects other instances of this node, * but probably not too much. */
5683de1995-11-06Fredrik Hübinette (Hubbe)  if(s->type!=T_STRING && s->type!=T_INT && s->type!=T_FLOAT) res->node_info|=OPT_EXTERNAL_DEPEND; return res; }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mksvaluenode(struct svalue *s)
5267b71995-08-09Fredrik Hübinette (Hubbe) { switch(s->type) { case T_ARRAY: return make_node_from_array(s->u.array);
06983f1996-09-22Fredrik Hübinette (Hubbe)  case T_MULTISET: return make_node_from_multiset(s->u.multiset);
5267b71995-08-09Fredrik Hübinette (Hubbe)  case T_MAPPING: return make_node_from_mapping(s->u.mapping); case T_OBJECT:
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(s->u.object == Pike_compiler->fake_object)
5267b71995-08-09Fredrik Hübinette (Hubbe)  { return mkefuncallnode("this_object", 0);
6d22541998-01-28Fredrik Hübinette (Hubbe)  } if(s->u.object->next == s->u.object) { int x=0; struct object *o; node *n=mkefuncallnode("this_object", 0);
bad5162000-06-23Fredrik Hübinette (Hubbe)  for(o=Pike_compiler->fake_object;o!=s->u.object;o=o->parent)
6d22541998-01-28Fredrik Hübinette (Hubbe)  { n=mkefuncallnode("function_object", mkefuncallnode("object_program",n)); } return n;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } break; case T_FUNCTION: {
bdb5091996-09-25Fredrik Hübinette (Hubbe)  if(s->subtype != FUNCTION_BUILTIN)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(s->u.object == Pike_compiler->fake_object)
5267b71995-08-09Fredrik Hübinette (Hubbe)  return mkidentifiernode(s->subtype);
6d22541998-01-28Fredrik Hübinette (Hubbe)  if(s->u.object->next == s->u.object) {
ff88db2000-07-12Henrik Grubbström (Grubba)  return mkexternalnode(s->u.object->prog, s->subtype);
6d22541998-01-28Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) /* yyerror("Non-constant function pointer! (should not happen!)"); */ } } } return mkconstantsvaluenode(s); } /* these routines operates on parsetrees and are mostly used by the * optimizer */
a566ca1999-12-14Fredrik Hübinette (Hubbe) #if 1 /* DEAD_CODE - I need this /Hubbe */
046afe1999-11-11Henrik Grubbström (Grubba) 
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. * In the SHARED_NODES case there's no need of course. */
5267b71995-08-09Fredrik Hübinette (Hubbe) node *copy_node(node *n) { node *b;
a566ca1999-12-14Fredrik Hübinette (Hubbe)  debug_malloc_touch(n); debug_malloc_touch(n->type); debug_malloc_touch(n->u.node.a); debug_malloc_touch(n->u.node.b);
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(n,0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!n) return n; switch(n->token) { case F_LOCAL:
06983f1996-09-22Fredrik Hübinette (Hubbe)  case F_IDENTIFIER:
4218011999-01-31Fredrik Hübinette (Hubbe)  case F_TRAMPOLINE:
046afe1999-11-11Henrik Grubbström (Grubba)  b=mknewintnode(0);
a566ca1999-12-14Fredrik Hübinette (Hubbe)  if(b->type) free_string(b->type);
5267b71995-08-09Fredrik Hübinette (Hubbe)  *b=*n; copy_shared_string(b->type, n->type); return b;
046afe1999-11-11Henrik Grubbström (Grubba)  default: #ifdef SHARED_NODES n->refs++; return n; #else /* !SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch((car_is_node(n) << 1) | cdr_is_node(n)) { default: fatal("fooo?\n"); case 3: b=mknode(n->token, copy_node(CAR(n)), copy_node(CDR(n))); break; case 2: b=mknode(n->token, copy_node(CAR(n)), CDR(n)); break; case 1: b=mknode(n->token, CAR(n), copy_node(CDR(n))); break; case 0: b=mknode(n->token, CAR(n), CDR(n)); } if(n->type) copy_shared_string(b->type, n->type); else b->type=0;
a566ca1999-12-14Fredrik Hübinette (Hubbe)  break; case F_CAST: b=mkcastnode(n->type,copy_node(CAR(n))); break; case F_SOFT_CAST: b=mksoftcastnode(n->type,copy_node(CAR(n))); break; case F_CONSTANT: b=mksvaluenode(&(n->u.sval)); break;
046afe1999-11-11Henrik Grubbström (Grubba) #endif /* SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
43fc171999-09-19Fredrik Hübinette (Hubbe)  if(n->name) { if(b->name) free_string(b->name); add_ref(b->name=n->name); }
48bd9c1999-09-22Henrik Grubbström (Grubba)  /* FIXME: Should b->name be kept if n->name is NULL? * /grubba 1999-09-22 */
5267b71995-08-09Fredrik Hübinette (Hubbe)  b->line_number = n->line_number; b->node_info = n->node_info; b->tree_info = n->tree_info; return b; }
046afe1999-11-11Henrik Grubbström (Grubba) #endif /* DEAD_CODE */
5267b71995-08-09Fredrik Hübinette (Hubbe)  int is_const(node *n) {
05533f1997-02-06Fredrik Hübinette (Hubbe)  if(!n) return 1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  return !(n->tree_info & (OPT_SIDE_EFFECT | OPT_NOT_CONST | OPT_ASSIGNMENT | OPT_CASE | OPT_CONTINUE | OPT_BREAK | OPT_RETURN )); } int node_is_tossable(node *n) { return !(n->tree_info & (OPT_SIDE_EFFECT | OPT_ASSIGNMENT | OPT_CASE | OPT_CONTINUE | OPT_BREAK | OPT_RETURN )); } /* this one supposes that the value is optimized */ int node_is_true(node *n) { if(!n) return 0; switch(n->token) { case F_CONSTANT: return !IS_ZERO(& n->u.sval); default: return 0; } } /* this one supposes that the value is optimized */ int node_is_false(node *n) { if(!n) return 0; switch(n->token) { case F_CONSTANT: return IS_ZERO(& n->u.sval); default: return 0; } }
cc5e511998-06-05Fredrik Hübinette (Hubbe) int node_may_overload(node *n, int lfun) { if(!n) return 0; if(!n->type) return 1; return type_may_overload(n->type->str, lfun); }
09667e2000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
6930181996-02-25Fredrik Hübinette (Hubbe) node **last_cmd(node **a)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node **n; if(!a || !*a) return (node **)NULL;
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
2a8cd81999-11-18Henrik Grubbström (Grubba)  if(((*a)->token == F_CAST) ||
84191b1999-11-23Henrik Grubbström (Grubba)  ((*a)->token == F_SOFT_CAST) ||
2a8cd81999-11-18Henrik Grubbström (Grubba)  ((*a)->token == F_POP_VALUE)) return last_cmd(&_CAR(*a));
920d201999-11-06Henrik Grubbström (Grubba)  if(((*a)->token != F_ARG_LIST) && ((*a)->token != F_COMMA_EXPR)) return a;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(CDR(*a)) {
2a8cd81999-11-18Henrik Grubbström (Grubba)  if(CDR(*a)->token != F_CAST &&
84191b1999-11-23Henrik Grubbström (Grubba)  CDR(*a)->token != F_SOFT_CAST &&
2a8cd81999-11-18Henrik Grubbström (Grubba)  CDR(*a)->token != F_POP_VALUE &&
4b2e0c2000-09-12Henrik Grubbström (Grubba)  CDR(*a)->token != F_ARG_LIST && CDR(*a)->token != F_COMMA_EXPR)
046afe1999-11-11Henrik Grubbström (Grubba)  return &_CDR(*a); if((n=last_cmd(&_CDR(*a))))
5267b71995-08-09Fredrik Hübinette (Hubbe)  return n; } if(CAR(*a)) {
2a8cd81999-11-18Henrik Grubbström (Grubba)  if(CAR(*a)->token != F_CAST &&
84191b1999-11-23Henrik Grubbström (Grubba)  CAR(*a)->token != F_SOFT_CAST &&
2a8cd81999-11-18Henrik Grubbström (Grubba)  CAR(*a)->token != F_POP_VALUE && CAR(*a)->token != F_ARG_LIST &&
920d201999-11-06Henrik Grubbström (Grubba)  CAR(*a)->token != F_COMMA_EXPR)
046afe1999-11-11Henrik Grubbström (Grubba)  return &_CAR(*a); if((n=last_cmd(&_CAR(*a))))
5267b71995-08-09Fredrik Hübinette (Hubbe)  return n; } return 0; }
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
5267b71995-08-09Fredrik Hübinette (Hubbe) static node **low_get_arg(node **a,int *nr) { node **n;
8db95f2000-03-13Henrik Grubbström (Grubba)  if (!a[0]) return NULL;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(a[0]->token != F_ARG_LIST) { if(!(*nr)--) return a; else return NULL; }
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(CAR(*a))
046afe1999-11-11Henrik Grubbström (Grubba)  if((n=low_get_arg(&_CAR(*a),nr)))
5267b71995-08-09Fredrik Hübinette (Hubbe)  return n; if(CDR(*a))
046afe1999-11-11Henrik Grubbström (Grubba)  if((n=low_get_arg(&_CDR(*a),nr)))
5267b71995-08-09Fredrik Hübinette (Hubbe)  return n; return 0; }
6930181996-02-25Fredrik Hübinette (Hubbe) node **my_get_arg(node **a,int n) { return low_get_arg(a,&n); }
cc5e511998-06-05Fredrik Hübinette (Hubbe)  node **is_call_to(node *n, c_fun f) { switch(n->token) { case F_APPLY: if(CAR(n) && CAR(n)->token == F_CONSTANT && CAR(n)->u.sval.type == T_FUNCTION && CAR(n)->u.sval.subtype == FUNCTION_BUILTIN && CAR(n)->u.sval.u.efun->function == f)
046afe1999-11-11Henrik Grubbström (Grubba)  return &_CDR(n);
cc5e511998-06-05Fredrik Hübinette (Hubbe)  } return 0; }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void low_print_tree(node *foo,int needlval) { if(!foo) return;
32e2af1998-11-17Fredrik Hübinette (Hubbe)  if(l_flag>9)
5219721998-11-06Fredrik Hübinette (Hubbe)  {
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "/*%x*/",foo->tree_info);
5219721998-11-06Fredrik Hübinette (Hubbe)  }
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
2e91222000-03-30Fredrik Hübinette (Hubbe)  switch(l_flag > 99 ? -1 : foo->token)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
046afe1999-11-11Henrik Grubbström (Grubba)  case USHRT_MAX: fprintf(stderr, "FREED_NODE"); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_LOCAL:
046afe1999-11-11Henrik Grubbström (Grubba)  if(needlval) fputc('&', stderr);
4218011999-01-31Fredrik Hübinette (Hubbe)  if(foo->u.integer.b) {
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "$<%ld>%ld",(long)foo->u.integer.b,(long)foo->u.integer.a);
4218011999-01-31Fredrik Hübinette (Hubbe)  }else{
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "$%ld",(long)foo->u.integer.a);
4218011999-01-31Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case '?':
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "("); low_print_tree(_CAR(foo),0); fprintf(stderr, ")?(");
a836c01999-11-12Henrik Grubbström (Grubba)  if (_CDR(foo)) { low_print_tree(_CADR(foo),0); fprintf(stderr, "):("); low_print_tree(_CDDR(foo),0); } else { fprintf(stderr, "0:0"); }
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, ")");
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case F_IDENTIFIER:
046afe1999-11-11Henrik Grubbström (Grubba)  if(needlval) fputc('&', stderr);
bad5162000-06-23Fredrik Hübinette (Hubbe)  if (Pike_compiler->new_program) { fprintf(stderr, "%s",ID_FROM_INT(Pike_compiler->new_program, foo->u.id.number)->name->str);
046afe1999-11-11Henrik Grubbström (Grubba)  } else { fprintf(stderr, "unknown identifier"); }
5267b71995-08-09Fredrik Hübinette (Hubbe)  break;
d1ae4f2000-08-27Henrik Grubbström (Grubba)  case F_EXTERNAL: if(needlval) fputc('&', stderr); { struct program_state *state = Pike_compiler; char *name = "external"; int program_id = foo->u.integer.a; while(state && (state->new_program->id != program_id)) { state = state->previous; } if (state) { int id_no = foo->u.integer.b; struct identifier *id = ID_FROM_INT(state->new_program, id_no); if (id && id->name) { name = id->name->str; } } fprintf(stderr, "%s", name); } break;
4218011999-01-31Fredrik Hübinette (Hubbe)  case F_TRAMPOLINE:
bad5162000-06-23Fredrik Hübinette (Hubbe)  if (Pike_compiler->new_program) {
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "trampoline<%s>",
bad5162000-06-23Fredrik Hübinette (Hubbe)  ID_FROM_INT(Pike_compiler->new_program, foo->u.id.number)->name->str);
046afe1999-11-11Henrik Grubbström (Grubba)  } else { fprintf(stderr, "trampoline<unknown identifier>"); }
4218011999-01-31Fredrik Hübinette (Hubbe)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_ASSIGN:
046afe1999-11-11Henrik Grubbström (Grubba)  low_print_tree(_CDR(foo),1); fprintf(stderr, "="); low_print_tree(_CAR(foo),0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  break;
2a8cd81999-11-18Henrik Grubbström (Grubba)  case F_POP_VALUE: fprintf(stderr, "{"); low_print_tree(_CAR(foo), 0); fprintf(stderr, "}"); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CAST: { char *s; init_buf(); low_describe_type(foo->type->str); s=simple_free_buf();
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "(%s){",s);
5267b71995-08-09Fredrik Hübinette (Hubbe)  free(s);
046afe1999-11-11Henrik Grubbström (Grubba)  low_print_tree(_CAR(foo),0); fprintf(stderr, "}");
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; }
84191b1999-11-23Henrik Grubbström (Grubba)  case F_SOFT_CAST: { char *s; init_buf(); low_describe_type(foo->type->str); s=simple_free_buf(); fprintf(stderr, "[%s]{",s); free(s); low_print_tree(_CAR(foo),0); fprintf(stderr, "}"); break; }
920d201999-11-06Henrik Grubbström (Grubba)  case F_COMMA_EXPR:
a2196f1999-11-21Henrik Grubbström (Grubba)  low_print_tree(_CAR(foo),0); if(_CAR(foo) && _CDR(foo)) { if(_CAR(foo)->type == void_type_string && _CDR(foo)->type == void_type_string) fprintf(stderr, ";\n"); else fprintf(stderr, ",\n"); } low_print_tree(_CDR(foo),needlval); return;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_ARG_LIST:
046afe1999-11-11Henrik Grubbström (Grubba)  low_print_tree(_CAR(foo),0); if(_CAR(foo) && _CDR(foo))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
046afe1999-11-11Henrik Grubbström (Grubba)  if(_CAR(foo)->type == void_type_string && _CDR(foo)->type == void_type_string) fprintf(stderr, ";\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  else
046afe1999-11-11Henrik Grubbström (Grubba)  fputc(',', stderr);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
046afe1999-11-11Henrik Grubbström (Grubba)  low_print_tree(_CDR(foo),needlval);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return;
2a32691998-01-31Fredrik Hübinette (Hubbe)  case F_ARRAY_LVALUE:
046afe1999-11-11Henrik Grubbström (Grubba)  fputc('[', stderr); low_print_tree(_CAR(foo),1); fputc(']', stderr);
2a32691998-01-31Fredrik Hübinette (Hubbe)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_LVALUE_LIST:
046afe1999-11-11Henrik Grubbström (Grubba)  low_print_tree(_CAR(foo),1); if(_CAR(foo) && _CDR(foo)) fputc(',', stderr); low_print_tree(_CDR(foo),1);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; case F_CONSTANT: { char *s; init_buf(); describe_svalue(& foo->u.sval, 0, 0); s=simple_free_buf();
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "%s",s);
5267b71995-08-09Fredrik Hübinette (Hubbe)  free(s); break; } case F_VAL_LVAL:
046afe1999-11-11Henrik Grubbström (Grubba)  low_print_tree(_CAR(foo),0); fprintf(stderr, ",&"); low_print_tree(_CDR(foo),0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; case F_APPLY:
046afe1999-11-11Henrik Grubbström (Grubba)  low_print_tree(_CAR(foo),0); fprintf(stderr, "("); low_print_tree(_CDR(foo),0); fprintf(stderr, ")");
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; default: if(!car_is_node(foo) && !cdr_is_node(foo)) {
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "%s",get_token_name(foo->token));
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; } if(foo->token<256) {
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "%c(",foo->token);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "%s(",get_token_name(foo->token));
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
046afe1999-11-11Henrik Grubbström (Grubba)  if(car_is_node(foo)) low_print_tree(_CAR(foo),0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(car_is_node(foo) && cdr_is_node(foo))
046afe1999-11-11Henrik Grubbström (Grubba)  fputc(',', stderr); if(cdr_is_node(foo)) low_print_tree(_CDR(foo),0); fprintf(stderr, ")");
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; } } void print_tree(node *n) {
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(n,0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  low_print_tree(n,0);
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  fflush(stdout); }
2ee5cb2000-08-27Henrik Grubbström (Grubba) /* The following routines need much better commenting. */ /* They also needed to support lexical scoping and external variables.
e674e72000-08-27Henrik Grubbström (Grubba)  * /grubba 2000-08-27 */
30ff0e2000-08-28Henrik Grubbström (Grubba) /* * Known bugs: * * Aliasing is not handled. * * Called functions are assumed not to use lexical scoping. */
e674e72000-08-27Henrik Grubbström (Grubba) #if MAX_LOCAL > MAX_GLOBAL #define MAX_VAR MAX_LOCAL #else /* MAX_LOCAL <= MAX_GLOBAL */ #define MAX_VAR MAX_GLOBAL #endif /* MAX_LOCAL > MAX_GLOBAL */
2ee5cb2000-08-27Henrik Grubbström (Grubba) /* FIXME: Should perhaps use BLOCK_ALLOC for struct scope_info? */
e674e72000-08-27Henrik Grubbström (Grubba) struct scope_info { struct scope_info *next; int scope_id; char vars[MAX_VAR]; };
5267b71995-08-09Fredrik Hübinette (Hubbe) struct used_vars {
e82b301997-01-29Fredrik Hübinette (Hubbe)  int err;
e674e72000-08-27Henrik Grubbström (Grubba)  int ext_flags;
2ee5cb2000-08-27Henrik Grubbström (Grubba)  /* Note that the locals and externals linked lists are sorted on scope_id. */ struct scope_info *locals; /* Lexical scopes. scope_id == depth */ struct scope_info *externals; /* External scopes. scope_id == program_id */
5267b71995-08-09Fredrik Hübinette (Hubbe) }; #define VAR_BLOCKED 0 #define VAR_UNUSED 1 #define VAR_USED 3
2ee5cb2000-08-27Henrik Grubbström (Grubba) /* FIXME: Shouldn't the following two functions be named "*_or_vars"? */ /* Perform a merge into a. * Note that b is freed. */
e674e72000-08-27Henrik Grubbström (Grubba) static void low_and_vars(struct scope_info **a, struct scope_info *b) { while (*a && b) { if ((*a)->scope_id < b->scope_id) { a = &((*a)->next); } else if ((*a)->scope_id > b->scope_id) { struct scope_info *tmp = *a; *a = b; b = b->next; (*a)->next = tmp; } else { struct scope_info *tmp = b; int e; for (e = 0; e < MAX_VAR; e++) { (*a)->vars[e] |= b->vars[e]; } a = &((*a)->next); b = b->next; free(tmp); } } if (!*a) { *a = b; } } /* NOTE: The second argument will be freed. */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void do_and_vars(struct used_vars *a,struct used_vars *b) {
e674e72000-08-27Henrik Grubbström (Grubba)  low_and_vars(&(a->locals), b->locals); low_and_vars(&(a->externals), b->externals); a->err |= b->err; a->ext_flags |= b->ext_flags; free(b);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
2ee5cb2000-08-27Henrik Grubbström (Grubba) /* Makes a copy of a. * Note: Can throw errors on out of memory. */
5267b71995-08-09Fredrik Hübinette (Hubbe) static struct used_vars *copy_vars(struct used_vars *a) { struct used_vars *ret;
e674e72000-08-27Henrik Grubbström (Grubba)  struct scope_info *src; struct scope_info **dst;
5267b71995-08-09Fredrik Hübinette (Hubbe)  ret=(struct used_vars *)xalloc(sizeof(struct used_vars));
e674e72000-08-27Henrik Grubbström (Grubba)  src = a->locals; dst = &(ret->locals); *dst = NULL; while (src) { *dst = malloc(sizeof(struct scope_info)); if (!*dst) { src = ret->locals; while(src) { struct scope_info *tmp = src->next; free(src); src = tmp; } free(ret); error("Out of memory in copy_vars.\n"); return NULL; /* Make sure that the optimizer knows we exit here. */ } MEMCPY(*dst, src, sizeof(struct scope_info));
e3131f2000-08-27Henrik Grubbström (Grubba)  src = src->next;
e674e72000-08-27Henrik Grubbström (Grubba)  dst = &((*dst)->next); *dst = NULL; } src = a->externals; dst = &(ret->externals); *dst = NULL; while (src) { *dst = malloc(sizeof(struct scope_info)); if (!*dst) { src = ret->locals; while(src) { struct scope_info *tmp = src->next; free(src); src = tmp; } src = ret->externals; while(src) { struct scope_info *tmp = src->next; free(src); src = tmp; } free(ret); error("Out of memory in copy_vars.\n"); return NULL; /* Make sure that the optimizer knows we exit here. */ } MEMCPY(*dst, src, sizeof(struct scope_info));
e3131f2000-08-27Henrik Grubbström (Grubba)  src = src->next;
e674e72000-08-27Henrik Grubbström (Grubba)  dst = &((*dst)->next); *dst = NULL; } ret->err = a->err; ret->ext_flags = a->ext_flags;
5267b71995-08-09Fredrik Hübinette (Hubbe)  return ret; }
2ee5cb2000-08-27Henrik Grubbström (Grubba) /* Find the insertion point for the variable a:scope_id:num. * Allocates a new scope if needed. * Can throw errors on out of memory. */
e674e72000-08-27Henrik Grubbström (Grubba) char *find_q(struct scope_info **a, int num, int scope_id) { struct scope_info *new; #ifdef PIKE_DEBUG if (l_flag > 3) { fprintf(stderr, "find_q %d:%d\n", scope_id, num); } #endif /* PIKE_DEBUG */ while (*a && ((*a)->scope_id < scope_id)) { a = &((*a)->next); } if ((*a) && ((*a)->scope_id == scope_id)) { #ifdef PIKE_DEBUG if (l_flag > 4) { fprintf(stderr, "scope found.\n"); } #endif /* PIKE_DEBUG */ return (*a)->vars + num; } #ifdef PIKE_DEBUG if (l_flag > 4) { fprintf(stderr, "Creating new scope.\n"); } #endif /* PIKE_DEBUG */ new = (struct scope_info *)xalloc(sizeof(struct scope_info)); MEMSET(new, VAR_UNUSED, sizeof(struct scope_info)); new->next = *a; new->scope_id = scope_id; *a = new; return new->vars + num; }
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
2ee5cb2000-08-27Henrik Grubbström (Grubba) /* Find the variables that are used in the tree n. */
5267b71995-08-09Fredrik Hübinette (Hubbe) static int find_used_variables(node *n, struct used_vars *p, int noblock, int overwrite) { struct used_vars *a; char *q; if(!n) return 0;
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(n->token) { case F_LOCAL:
e674e72000-08-27Henrik Grubbström (Grubba)  q = find_q(&(p->locals), n->u.integer.a, n->u.integer.b); #ifdef PIKE_DEBUG if (l_flag > 2) { fprintf(stderr, "local %d:%d is ", n->u.integer.b, n->u.integer.a); } #endif /* PIKE_DEBUG */ goto set_pointer; case F_EXTERNAL: q = find_q(&(p->externals), n->u.integer.b, n->u.integer.a); #ifdef PIKE_DEBUG if (l_flag > 2) { fprintf(stderr, "external %d:%d is ", n->u.integer.a, n->u.integer.b); } #endif /* PIKE_DEBUG */
5267b71995-08-09Fredrik Hübinette (Hubbe)  goto set_pointer; case F_IDENTIFIER:
e674e72000-08-27Henrik Grubbström (Grubba)  q = find_q(&(p->externals), n->u.id.number, Pike_compiler->new_program->id);
046afe1999-11-11Henrik Grubbström (Grubba)  if(n->u.id.number > MAX_GLOBAL)
e82b301997-01-29Fredrik Hübinette (Hubbe)  { p->err=1; return 0; }
e674e72000-08-27Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if (l_flag > 2) { fprintf(stderr, "external %d:%d is ", Pike_compiler->new_program->id, n->u.id.number); } #endif /* PIKE_DEBUG */
5267b71995-08-09Fredrik Hübinette (Hubbe)  set_pointer: if(overwrite) {
e674e72000-08-27Henrik Grubbström (Grubba)  if(*q == VAR_UNUSED && !noblock) { *q = VAR_BLOCKED; #ifdef PIKE_DEBUG if (l_flag > 2) { fprintf(stderr, "blocked\n"); } } else { if (l_flag > 2) { fprintf(stderr, "overwritten\n"); } #endif /* PIKE_DEBUG */ }
5267b71995-08-09Fredrik Hübinette (Hubbe)  } else {
e674e72000-08-27Henrik Grubbström (Grubba)  if(*q == VAR_UNUSED) { *q = VAR_USED; #ifdef PIKE_DEBUG if (l_flag > 2) { fprintf(stderr, "used\n"); } } else { if (l_flag > 2) { fprintf(stderr, "kept\n"); } #endif /* PIKE_DEBUG */ }
5267b71995-08-09Fredrik Hübinette (Hubbe)  } break; case F_ASSIGN: find_used_variables(CAR(n),p,noblock,0); find_used_variables(CDR(n),p,noblock,1); break; case '?': find_used_variables(CAR(n),p,noblock,0); a=copy_vars(p); find_used_variables(CADR(n),a,noblock,0); find_used_variables(CDDR(n),p,noblock,0);
e674e72000-08-27Henrik Grubbström (Grubba)  do_and_vars(p, a);
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case F_INC_NEQ_LOOP: case F_DEC_NEQ_LOOP: case F_INC_LOOP: case F_DEC_LOOP: case F_FOREACH: case F_FOR: find_used_variables(CAR(n),p,noblock,0); a=copy_vars(p); find_used_variables(CDR(n),a,noblock,0);
e674e72000-08-27Henrik Grubbström (Grubba)  do_and_vars(p, a);
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case F_SWITCH: find_used_variables(CAR(n),p,noblock,0); a=copy_vars(p); find_used_variables(CDR(n),a,1,0);
e674e72000-08-27Henrik Grubbström (Grubba)  do_and_vars(p, a);
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case F_DO: a=copy_vars(p); find_used_variables(CAR(n),a,noblock,0);
e674e72000-08-27Henrik Grubbström (Grubba)  do_and_vars(p, a);
5267b71995-08-09Fredrik Hübinette (Hubbe)  find_used_variables(CDR(n),p,noblock,0); break; default: if(car_is_node(n)) find_used_variables(CAR(n),p,noblock,0); if(cdr_is_node(n)) find_used_variables(CDR(n),p,noblock,0); } return 0; }
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
5267b71995-08-09Fredrik Hübinette (Hubbe) /* no subtility needed */ static void find_written_vars(node *n, struct used_vars *p, int lvalue) { if(!n) return;
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(n->token) { case F_LOCAL:
e674e72000-08-27Henrik Grubbström (Grubba)  if(lvalue) { #ifdef PIKE_DEBUG if (l_flag > 2) { fprintf(stderr, "local %d:%d is written\n", n->u.integer.b, n->u.integer.a); } #endif /* PIKE_DEBUG */ *find_q(&(p->locals), n->u.integer.a, n->u.integer.b) = VAR_USED; } break; case F_EXTERNAL: if(lvalue) { #ifdef PIKE_DEBUG if (l_flag > 2) { fprintf(stderr, "external %d:%d is written\n", n->u.integer.a, n->u.integer.b); } #endif /* PIKE_DEBUG */ *find_q(&(p->externals), n->u.integer.b, n->u.integer.a) = VAR_USED; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  break;
587a7c1998-08-05Fredrik Hübinette (Hubbe)  case F_IDENTIFIER:
e674e72000-08-27Henrik Grubbström (Grubba)  if(lvalue) { if(n->u.id.number >= MAX_VAR) { p->err=1; return; } #ifdef PIKE_DEBUG if (l_flag > 2) { fprintf(stderr, "external %d:%d is written\n", Pike_compiler->new_program->id, n->u.id.number); } #endif /* PIKE_DEBUG */ *find_q(&(p->externals), n->u.id.number, Pike_compiler->new_program->id) = VAR_USED; }
e82b301997-01-29Fredrik Hübinette (Hubbe)  break; case F_APPLY:
e674e72000-08-27Henrik Grubbström (Grubba)  if(n->tree_info & OPT_SIDE_EFFECT) { p->ext_flags = VAR_USED; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case F_INDEX:
dffa011997-01-15Fredrik Hübinette (Hubbe)  case F_ARROW:
5267b71995-08-09Fredrik Hübinette (Hubbe)  find_written_vars(CAR(n), p, lvalue); find_written_vars(CDR(n), p, 0); break; case F_INC: case F_DEC: case F_POST_INC: case F_POST_DEC: find_written_vars(CAR(n), p, 1); break; case F_ASSIGN: find_written_vars(CAR(n), p, 0); find_written_vars(CDR(n), p, 1); break;
5219721998-11-06Fredrik Hübinette (Hubbe)  case F_AND_EQ: case F_OR_EQ: case F_XOR_EQ: case F_LSH_EQ: case F_RSH_EQ: case F_ADD_EQ: case F_SUB_EQ: case F_MULT_EQ: case F_MOD_EQ: case F_DIV_EQ: find_written_vars(CAR(n), p, 1); find_written_vars(CDR(n), p, 0); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_SSCANF: find_written_vars(CAR(n), p, 0); find_written_vars(CDR(n), p, 1); break;
2a32691998-01-31Fredrik Hübinette (Hubbe)  case F_ARRAY_LVALUE: find_written_vars(CAR(n), p, 1); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_LVALUE_LIST: find_written_vars(CAR(n), p, 1); find_written_vars(CDR(n), p, 1); break; case F_VAL_LVAL: find_written_vars(CAR(n), p, 0); find_written_vars(CDR(n), p, 1); break; default: if(car_is_node(n)) find_written_vars(CAR(n), p, 0); if(cdr_is_node(n)) find_written_vars(CDR(n), p, 0); } }
e674e72000-08-27Henrik Grubbström (Grubba) void free_vars(struct used_vars *a) { struct scope_info *tmp; tmp = a->locals; while(tmp) { struct scope_info *next = tmp->next; free(tmp); tmp = next; } tmp = a->externals; while(tmp) { struct scope_info *next = tmp->next; free(tmp); tmp = next; } }
5267b71995-08-09Fredrik Hübinette (Hubbe) /* return 1 if A depends on B */
e674e72000-08-27Henrik Grubbström (Grubba) static int depend_p2(node *a, node *b)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
e674e72000-08-27Henrik Grubbström (Grubba)  struct used_vars aa, bb;
5267b71995-08-09Fredrik Hübinette (Hubbe)  int e;
e674e72000-08-27Henrik Grubbström (Grubba)  ONERROR free_aa; ONERROR free_bb;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!a || !b || is_const(a)) return 0;
e674e72000-08-27Henrik Grubbström (Grubba)  aa.err = 0; bb.err = 0; aa.ext_flags = 0; bb.ext_flags = 0; aa.locals = NULL; bb.locals = NULL; aa.externals = NULL; bb.externals = NULL; SET_ONERROR(free_aa, free_vars, &aa); SET_ONERROR(free_bb, free_vars, &bb); find_used_variables(a, &aa, 0, 0); find_written_vars(b, &bb, 0); UNSET_ONERROR(free_bb); UNSET_ONERROR(free_aa); if(aa.err || bb.err) { free_vars(&aa); free_vars(&bb); return 1; }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
e674e72000-08-27Henrik Grubbström (Grubba)  { struct scope_info *aaa = aa.locals; struct scope_info *bbb = bb.locals;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
e674e72000-08-27Henrik Grubbström (Grubba)  while (aaa) { while (bbb && (bbb->scope_id < aaa->scope_id)) { bbb = bbb->next; } if (!bbb) break; if (bbb->scope_id == aaa->scope_id) { for (e = 0; e < MAX_VAR; e++) { if ((aaa->vars[e] == VAR_USED) && (bbb->vars[e] != VAR_UNUSED)) { free_vars(&aa); free_vars(&bb); return 1; } } } aaa = aaa->next; } } if (bb.ext_flags == VAR_USED) { /* No need to look closer at b */ struct scope_info *aaa = aa.externals;
e82b301997-01-29Fredrik Hübinette (Hubbe) 
e674e72000-08-27Henrik Grubbström (Grubba)  /* FIXME: Probably only needed to check if aaa is NULL or not. */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
e674e72000-08-27Henrik Grubbström (Grubba)  while (aaa) { for (e = 0; e < MAX_VAR; e++) { if (aaa->vars[e] == VAR_USED) { free_vars(&aa); free_vars(&bb); return 1; } } aaa = aaa->next; } } else { struct scope_info *aaa = aa.externals; struct scope_info *bbb = bb.externals; while (aaa) { while (bbb && (bbb->scope_id < aaa->scope_id)) { bbb = bbb->next; } if (!bbb) break; if (bbb->scope_id == aaa->scope_id) { for (e = 0; e < MAX_VAR; e++) { if ((aaa->vars[e] == VAR_USED) && (bbb->vars[e] != VAR_UNUSED)) { free_vars(&aa); free_vars(&bb); return 1; } } } aaa = aaa->next; } } free_vars(&aa); free_vars(&bb);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return 0; }
5219721998-11-06Fredrik Hübinette (Hubbe) static int depend_p3(node *a,node *b)
5267b71995-08-09Fredrik Hübinette (Hubbe) { if(!b) return 0;
e82b301997-01-29Fredrik Hübinette (Hubbe) #if 0
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!(b->tree_info & OPT_SIDE_EFFECT) && (b->tree_info & OPT_EXTERNAL_DEPEND)) return 1;
e82b301997-01-29Fredrik Hübinette (Hubbe) #endif if((a->tree_info & OPT_EXTERNAL_DEPEND)) return 1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  return depend_p2(a,b); }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5219721998-11-06Fredrik Hübinette (Hubbe) static int depend_p(node *a,node *b) { int ret; if(l_flag > 3) { fprintf(stderr,"Checking if: "); print_tree(a); fprintf(stderr,"Depends on: "); print_tree(b); if(depend_p3(a,b)) { fprintf(stderr,"The answer is (durumroll) : yes\n"); return 1; }else{ fprintf(stderr,"The answer is (durumroll) : no\n"); return 0; } } return depend_p3(a,b); } #else #define depend_p depend_p3 #endif
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
5267b71995-08-09Fredrik Hübinette (Hubbe) static int cntargs(node *n) { if(!n) return 0; switch(n->token) { case F_CAST:
84191b1999-11-23Henrik Grubbström (Grubba)  case F_SOFT_CAST:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_APPLY: return n->type != void_type_string;
2a8cd81999-11-18Henrik Grubbström (Grubba)  case F_POP_VALUE:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_FOREACH: case F_INC_NEQ_LOOP: case F_DEC_NEQ_LOOP: case F_INC_LOOP: case F_DEC_LOOP: return 0;
920d201999-11-06Henrik Grubbström (Grubba)  case F_COMMA_EXPR:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_VAL_LVAL: case F_LVALUE_LIST: case F_ARG_LIST:
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return cntargs(CAR(n))+cntargs(CDR(n)); /* this might not be true, but it doesn't matter very much */ default: return 1; } }
086acc1999-09-11Fredrik Hübinette (Hubbe) static int function_type_max=0;
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void low_build_function_type(node *n) { if(!n) return;
086acc1999-09-11Fredrik Hübinette (Hubbe)  if(function_type_max++ > 999) { reset_type_stack();
327c051999-11-24Fredrik Hübinette (Hubbe)  push_type(T_MIXED); push_type(T_VOID); push_type(T_OR); /* return type is void or mixed */
086acc1999-09-11Fredrik Hübinette (Hubbe)  push_type(T_MIXED);
327c051999-11-24Fredrik Hübinette (Hubbe)  push_type(T_VOID); push_type(T_OR); /* varargs */
086acc1999-09-11Fredrik Hübinette (Hubbe)  push_type(T_MANY); return; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(n->token) {
920d201999-11-06Henrik Grubbström (Grubba)  case F_COMMA_EXPR:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_ARG_LIST:
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
5267b71995-08-09Fredrik Hübinette (Hubbe)  low_build_function_type(CDR(n)); low_build_function_type(CAR(n)); break; case F_PUSH_ARRAY: /* We let this ruin type-checking for now.. */ reset_type_stack();
327c051999-11-24Fredrik Hübinette (Hubbe) 
0d202a1995-10-20Fredrik Hübinette (Hubbe)  push_type(T_MIXED);
327c051999-11-24Fredrik Hübinette (Hubbe)  push_type(T_VOID); push_type(T_OR); /* return type is void or mixed */ push_type(T_MIXED); push_type(T_VOID); push_type(T_OR); /* varargs */
5267b71995-08-09Fredrik Hübinette (Hubbe)  push_type(T_MANY); return; default: if(n->type) { if(n->type == void_type_string) return; push_finished_type(n->type); }else{ push_type(T_MIXED); } } }
668c5b1999-12-26Henrik Grubbström (Grubba) void yytype_error(char *msg, struct pike_string *expected_t, struct pike_string *got_t, unsigned int flags)
edcd891999-12-23Henrik Grubbström (Grubba) {
03318e2000-03-16Fredrik Hübinette (Hubbe)  if (msg) { if (flags & YYTE_IS_WARNING)
edcd891999-12-23Henrik Grubbström (Grubba)  yywarning("%s", msg);
03318e2000-03-16Fredrik Hübinette (Hubbe)  else
edcd891999-12-23Henrik Grubbström (Grubba)  my_yyerror("%s", msg); }
03318e2000-03-16Fredrik Hübinette (Hubbe)  yyexplain_nonmatching_types(expected_t, got_t, flags);
edcd891999-12-23Henrik Grubbström (Grubba) }
5267b71995-08-09Fredrik Hübinette (Hubbe)  void fix_type_field(node *n) {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct pike_string *type_a,*type_b;
f68afd1999-11-20Henrik Grubbström (Grubba)  struct pike_string *old_type; if (n->type && !(n->node_info & OPT_TYPE_NOT_FIXED)) return; /* assume it is correct */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
f68afd1999-11-20Henrik Grubbström (Grubba)  old_type = n->type; n->type = 0; n->node_info &= ~OPT_TYPE_NOT_FIXED;
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(n->token) {
1d480f1999-11-23Henrik Grubbström (Grubba)  case F_SOFT_CAST: if (CAR(n) && CAR(n)->type) {
5986041999-12-21Henrik Grubbström (Grubba)  if (!check_soft_cast(old_type, CAR(n)->type)) {
1d480f1999-11-23Henrik Grubbström (Grubba)  struct pike_string *t1 = describe_type(old_type); struct pike_string *t2 = describe_type(CAR(n)->type); yywarning("Soft cast to %s isn't a restriction of %s.", t1->str, t2->str); free_string(t2); free_string(t1); }
5986041999-12-21Henrik Grubbström (Grubba)  /* FIXME: check_soft_cast() is weaker than pike_types_le() * The resulting type should probably be the and between the old * and the new type. */
1d480f1999-11-23Henrik Grubbström (Grubba)  } /* FALL_THROUGH */
f68afd1999-11-20Henrik Grubbström (Grubba)  case F_CAST: /* Type-field is correct by definition. */ copy_shared_string(n->type, old_type); break;
cb22561995-10-11Fredrik Hübinette (Hubbe)  case F_LAND: case F_LOR:
60ca281999-12-03Martin Stjernholm  if (!CAR(n) || CAR(n)->type == void_type_string) { yyerror("Conditional uses void expression.");
e9b1771999-11-18Henrik Grubbström (Grubba)  copy_shared_string(n->type, mixed_type_string);
8521291999-11-20Henrik Grubbström (Grubba)  break;
e9b1771999-11-18Henrik Grubbström (Grubba)  }
cb22561995-10-11Fredrik Hübinette (Hubbe)  if(!match_types(CAR(n)->type,mixed_type_string))
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Bad conditional expression.");
cb22561995-10-11Fredrik Hübinette (Hubbe) 
60ca281999-12-03Martin Stjernholm  if (!CDR(n) || CDR(n)->type == void_type_string) copy_shared_string(n->type,void_type_string);
8886701999-12-05Martin Stjernholm  else if(n->token == F_LAND || CAR(n)->type == CDR(n)->type)
cb22561995-10-11Fredrik Hübinette (Hubbe)  {
8886701999-12-05Martin Stjernholm  copy_shared_string(n->type,CDR(n)->type);
cb22561995-10-11Fredrik Hübinette (Hubbe)  }else{
4d7b181999-12-07Fredrik Hübinette (Hubbe)  n->type = or_pike_types(CAR(n)->type, CDR(n)->type, 0);
cb22561995-10-11Fredrik Hübinette (Hubbe)  } break;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
da55f91996-05-03Fredrik Hübinette (Hubbe)  case F_ASSIGN:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->type == void_type_string)) { my_yyerror("Assigning a void expression."); copy_shared_string(n->type, void_type_string); break;
f68afd1999-11-20Henrik Grubbström (Grubba)  } else if(CAR(n) && CDR(n)) {
84191b1999-11-23Henrik Grubbström (Grubba)  /* Ensure that the type-fields are up to date. */
f68afd1999-11-20Henrik Grubbström (Grubba)  fix_type_field(CAR(n)); fix_type_field(CDR(n));
84191b1999-11-23Henrik Grubbström (Grubba)  if (!pike_types_le(CAR(n)->type, CDR(n)->type)) { /* a["b"]=c and a->b=c can be valid when a is an array */ if (CDR(n)->token != F_INDEX && CDR(n)->token != F_ARROW && !match_types(CDR(n)->type,CAR(n)->type)) {
edcd891999-12-23Henrik Grubbström (Grubba)  yytype_error("Bad type in assignment.", CDR(n)->type, CAR(n)->type, 0);
84191b1999-11-23Henrik Grubbström (Grubba)  } else if (lex.pragmas & ID_STRICT_TYPES) { struct pike_string *t1 = describe_type(CAR(n)->type); struct pike_string *t2 = describe_type(CDR(n)->type);
49a0961999-11-24Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if (l_flag > 0) { fprintf(stderr, "Warning: Invalid assignment: "); print_tree(n); } #endif /* PIKE_DEBUG */
84191b1999-11-23Henrik Grubbström (Grubba)  yywarning("An expression type %s cannot be assigned to " "a variable of type %s.", t1->str, t2->str); free_string(t2); free_string(t1); }
f68afd1999-11-20Henrik Grubbström (Grubba)  }
e9b1771999-11-18Henrik Grubbström (Grubba)  }
f77d7e1999-11-21Henrik Grubbström (Grubba)  n->type = and_pike_types(CAR(n)->type, CDR(n)->type);
da55f91996-05-03Fredrik Hübinette (Hubbe)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_INDEX:
dffa011997-01-15Fredrik Hübinette (Hubbe)  case F_ARROW:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->type == void_type_string)) { my_yyerror("Indexing a void expression."); /* The optimizer converts this to an expression returning 0. */
84191b1999-11-23Henrik Grubbström (Grubba)  copy_shared_string(n->type, zero_type_string);
e9b1771999-11-18Henrik Grubbström (Grubba)  } else { type_a=CAR(n)->type; type_b=CDR(n)->type; if(!check_indexing(type_a, type_b, n))
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(!Pike_compiler->catch_level)
e9b1771999-11-18Henrik Grubbström (Grubba)  my_yyerror("Indexing on illegal type.");
4d7b181999-12-07Fredrik Hübinette (Hubbe)  n->type=index_type(type_a, type_b,n);
e9b1771999-11-18Henrik Grubbström (Grubba)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case F_APPLY:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->type == void_type_string)) { my_yyerror("Calling a void expression."); } else {
f68afd1999-11-20Henrik Grubbström (Grubba)  struct pike_string *s; struct pike_string *f;
b8cda21997-01-21Fredrik Hübinette (Hubbe)  char *name;
f68afd1999-11-20Henrik Grubbström (Grubba)  INT32 max_args,args;
327c051999-11-24Fredrik Hübinette (Hubbe)  push_type(T_MIXED); /* match any return type */ push_type(T_VOID); /* even void */ push_type(T_OR);
f68afd1999-11-20Henrik Grubbström (Grubba)  push_type(T_VOID); /* not varargs */ push_type(T_MANY); function_type_max=0; low_build_function_type(CDR(n)); push_type(T_FUNCTION);
acb9de1999-11-20Henrik Grubbström (Grubba)  s = pop_type(); f = CAR(n)->type?CAR(n)->type:mixed_type_string;
13eb3e1999-12-29Henrik Grubbström (Grubba)  n->type = check_call(s, f, (lex.pragmas & ID_STRICT_TYPES) && !(n->node_info & OPT_WEAK_TYPE));
acb9de1999-11-20Henrik Grubbström (Grubba)  args = count_arguments(s); max_args = count_arguments(f); if(max_args<0) max_args = 0x7fffffff;
7704531999-11-20Henrik Grubbström (Grubba) 
acb9de1999-11-20Henrik Grubbström (Grubba)  if (n->type) { /* Type/argument-check OK. */
93b07d1999-11-24Fredrik Hübinette (Hubbe)  free_string(s);
acb9de1999-11-20Henrik Grubbström (Grubba)  break; }
f68afd1999-11-20Henrik Grubbström (Grubba) 
3856c31996-11-25Fredrik Hübinette (Hubbe)  switch(CAR(n)->token) {
4218011999-01-31Fredrik Hübinette (Hubbe) #if 0 /* FIXME */
f68afd1999-11-20Henrik Grubbström (Grubba)  case F_TRAMPOLINE:
4218011999-01-31Fredrik Hübinette (Hubbe) #endif
3856c31996-11-25Fredrik Hübinette (Hubbe)  case F_IDENTIFIER:
bad5162000-06-23Fredrik Hübinette (Hubbe)  name=ID_FROM_INT(Pike_compiler->new_program, CAR(n)->u.id.number)->name->str;
3856c31996-11-25Fredrik Hübinette (Hubbe)  break;
a566ca1999-12-14Fredrik Hübinette (Hubbe)  case F_ARROW: case F_INDEX: if(CDAR(n)->token == F_CONSTANT && CDAR(n)->u.sval.type == T_STRING) { name=CDAR(n)->u.sval.u.string->str; }else{ name="dynamically resolved function"; } break;
3856c31996-11-25Fredrik Hübinette (Hubbe)  case F_CONSTANT:
0d3ea51998-01-19Fredrik Hübinette (Hubbe)  switch(CAR(n)->u.sval.type) {
f68afd1999-11-20Henrik Grubbström (Grubba)  case T_FUNCTION: if(CAR(n)->u.sval.subtype == FUNCTION_BUILTIN) { name=CAR(n)->u.sval.u.efun->name->str; }else{ name=ID_FROM_INT(CAR(n)->u.sval.u.object->prog, CAR(n)->u.sval.subtype)->name->str; } break;
0d3ea51998-01-19Fredrik Hübinette (Hubbe) 
f68afd1999-11-20Henrik Grubbström (Grubba)  case T_ARRAY: name="array call"; break;
0d3ea51998-01-19Fredrik Hübinette (Hubbe) 
f68afd1999-11-20Henrik Grubbström (Grubba)  case T_PROGRAM: name="clone call"; break;
0d3ea51998-01-19Fredrik Hübinette (Hubbe) 
f68afd1999-11-20Henrik Grubbström (Grubba)  default: name="`() (function call)"; break;
0d3ea51998-01-19Fredrik Hübinette (Hubbe)  }
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  break;
cbe8f32000-07-10Henrik Grubbström (Grubba)  case F_EXTERNAL: {
ff88db2000-07-12Henrik Grubbström (Grubba)  int program_id = CAR(n)->u.integer.a;
cbe8f32000-07-10Henrik Grubbström (Grubba)  int id_no = CAR(n)->u.integer.b;
342fef2000-08-23Fredrik Hübinette (Hubbe)  struct program_state *state = Pike_compiler;
ff88db2000-07-12Henrik Grubbström (Grubba) 
cbe8f32000-07-10Henrik Grubbström (Grubba)  name="external symbol";
ff88db2000-07-12Henrik Grubbström (Grubba)  while (state && (state->new_program->id != program_id)) { state = state->previous; } if (state) { struct identifier *id = ID_FROM_INT(state->new_program, id_no);
cbe8f32000-07-10Henrik Grubbström (Grubba)  if (id && id->name) { name = id->name->str;
01d4902000-07-11Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
cfe1fe2000-09-09Fredrik Hübinette (Hubbe)  /* FIXME: This test crashes on valid code because the type of the * identifier can change in pass 2 -Hubbe */
01d4902000-07-11Fredrik Hübinette (Hubbe)  if(id->type != f) { printf("Type of external node is not matching it's identifier.\nid->type: "); simple_describe_type(id->type); printf("\nf : "); simple_describe_type(f); printf("\n"); fatal("Type of external node is not matching it's identifier.\n"); } #endif
cbe8f32000-07-10Henrik Grubbström (Grubba)  } } } break;
f68afd1999-11-20Henrik Grubbström (Grubba) 
3856c31996-11-25Fredrik Hübinette (Hubbe)  default:
0d3ea51998-01-19Fredrik Hübinette (Hubbe)  name="unknown function";
b8cda21997-01-21Fredrik Hübinette (Hubbe)  }
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  if(max_args < args) {
9a78b21999-11-18Henrik Grubbström (Grubba)  my_yyerror("Too many arguments to %s.",name);
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  } else if(max_correct_args == args)
b8cda21997-01-21Fredrik Hübinette (Hubbe)  {
9a78b21999-11-18Henrik Grubbström (Grubba)  my_yyerror("Too few arguments to %s.",name);
b8cda21997-01-21Fredrik Hübinette (Hubbe)  }else{ my_yyerror("Bad argument %d to %s.", max_correct_args+1, name);
3856c31996-11-25Fredrik Hübinette (Hubbe)  }
93b07d1999-11-24Fredrik Hübinette (Hubbe) 
edcd891999-12-23Henrik Grubbström (Grubba)  yytype_error(NULL, f, s, 0);
cbe8f32000-07-10Henrik Grubbström (Grubba)  /* print_tree(n); */
93b07d1999-11-24Fredrik Hübinette (Hubbe)  free_string(s);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
f68afd1999-11-20Henrik Grubbström (Grubba)  copy_shared_string(n->type, mixed_type_string);
cb22561995-10-11Fredrik Hübinette (Hubbe)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case '?':
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->type == void_type_string)) {
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Conditional expression is void.");
e9b1771999-11-18Henrik Grubbström (Grubba)  } else if(!match_types(CAR(n)->type,mixed_type_string))
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Bad conditional expression.");
cb22561995-10-11Fredrik Hübinette (Hubbe) 
60ca281999-12-03Martin Stjernholm  if(!CDR(n) || !CADR(n) || !CDDR(n) || CADR(n)->type == void_type_string || CDDR(n)->type == void_type_string)
5267b71995-08-09Fredrik Hübinette (Hubbe)  { copy_shared_string(n->type,void_type_string);
f68afd1999-11-20Henrik Grubbström (Grubba)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } if(CADR(n)->type == CDDR(n)->type) { copy_shared_string(n->type,CADR(n)->type);
f68afd1999-11-20Henrik Grubbström (Grubba)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
4d7b181999-12-07Fredrik Hübinette (Hubbe)  n->type = or_pike_types(CADR(n)->type, CDDR(n)->type, 0);
cb22561995-10-11Fredrik Hübinette (Hubbe)  break;
42379f1999-11-21Henrik Grubbström (Grubba)  case F_AND_EQ: case F_OR_EQ: case F_XOR_EQ: case F_LSH_EQ: case F_RSH_EQ: case F_ADD_EQ: case F_SUB_EQ: case F_MULT_EQ: case F_MOD_EQ: case F_DIV_EQ: /* FIXME: Go via var = OP(var, expr); to restrict the type further? * type = typeof(OP(var, expr)) AND typeof(var); */
d00b001999-11-21Henrik Grubbström (Grubba)  case F_RANGE: case F_INC: case F_DEC: case F_POST_INC: case F_POST_DEC: if (CAR(n)) { /* The expression gets the type from the variable. */ /* FIXME: Ought to strip non-applicable subtypes from the type. */ copy_shared_string(n->type, CAR(n)->type); } else { copy_shared_string(n->type, mixed_type_string); } break;
cb22561995-10-11Fredrik Hübinette (Hubbe)  case F_RETURN:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->type == void_type_string)) {
a2196f1999-11-21Henrik Grubbström (Grubba)  yywarning("Returning a void expression."); if (!CAR(n)) { #ifdef SHARED_NODES sub_node(n); #endif /* SHARED_NODES */ _CAR(n) = mkintnode(0); copy_shared_string(n->type, CAR(n)->type); #ifdef SHARED_NODES n->hash = hash_node(n); n->node_info |= OPT_DEFROSTED; add_node(n); #endif /* SHARED_NODES */ break; }
bad5162000-06-23Fredrik Hübinette (Hubbe)  } else if(Pike_compiler->compiler_frame && Pike_compiler->compiler_frame->current_return_type) { if (!pike_types_le(CAR(n)->type, Pike_compiler->compiler_frame->current_return_type) &&
84191b1999-11-23Henrik Grubbström (Grubba)  !(
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->compiler_frame->current_return_type==void_type_string &&
84191b1999-11-23Henrik Grubbström (Grubba)  CAR(n)->token == F_CONSTANT && IS_ZERO(& CAR(n)->u.sval)
e9b1771999-11-18Henrik Grubbström (Grubba)  )
84191b1999-11-23Henrik Grubbström (Grubba)  ) {
bad5162000-06-23Fredrik Hübinette (Hubbe)  if (!match_types(Pike_compiler->compiler_frame->current_return_type,CAR(n)->type))
84191b1999-11-23Henrik Grubbström (Grubba)  { yyerror("Wrong return type.");
bad5162000-06-23Fredrik Hübinette (Hubbe)  yyexplain_nonmatching_types(Pike_compiler->compiler_frame->current_return_type,
03318e2000-03-16Fredrik Hübinette (Hubbe)  CAR(n)->type,0);
84191b1999-11-23Henrik Grubbström (Grubba)  } else if (lex.pragmas & ID_STRICT_TYPES) {
edcd891999-12-23Henrik Grubbström (Grubba)  yytype_error("Return type mismatch.",
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->compiler_frame->current_return_type,
edcd891999-12-23Henrik Grubbström (Grubba)  CAR(n)->type, YYTE_IS_WARNING);
84191b1999-11-23Henrik Grubbström (Grubba)  } }
cb22561995-10-11Fredrik Hübinette (Hubbe)  }
c9cfae2000-01-04Henrik Grubbström (Grubba)  copy_shared_string(n->type,void_type_string); break;
cb22561995-10-11Fredrik Hübinette (Hubbe) 
c9cfae2000-01-04Henrik Grubbström (Grubba)  case F_CASE: if (CDR(n) && CAR(n)) { /* case 1 .. 2: */ if (!match_types(CAR(n)->type, CDR(n)->type)) {
5ba7062000-01-04Henrik Grubbström (Grubba)  if (!match_types(CAR(n)->type, int_type_string) || !match_types(CDR(n)->type, int_type_string)) { yytype_error("Type mismatch in case range.", CAR(n)->type, CDR(n)->type, 0); }
c9cfae2000-01-04Henrik Grubbström (Grubba)  } else if ((lex.pragmas & ID_STRICT_TYPES) && (CAR(n)->type != CDR(n)->type)) { /* The type should be the same for both CAR & CDR. */ if (!pike_types_le(CDR(n)->type, CAR(n)->type)) {
cbe8f32000-07-10Henrik Grubbström (Grubba)  /* Note that zero should be handled as int(0..0) here. */ if (!(CAR(n)->type == zero_type_string) || !(pike_types_le(CDR(n)->type, int_type_string))) { yytype_error("Type mismatch in case range.", CAR(n)->type, CDR(n)->type, YYTE_IS_WARNING); }
c9cfae2000-01-04Henrik Grubbström (Grubba)  } else if (!pike_types_le(CAR(n)->type, CDR(n)->type)) {
cbe8f32000-07-10Henrik Grubbström (Grubba)  if (!(CDR(n)->type == zero_type_string) || !(pike_types_le(CAR(n)->type, int_type_string))) { yytype_error("Type mismatch in case range.", CDR(n)->type, CAR(n)->type, YYTE_IS_WARNING); }
c9cfae2000-01-04Henrik Grubbström (Grubba)  } } } /* FALL_THROUGH */
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_INC_LOOP: case F_DEC_LOOP: case F_DEC_NEQ_LOOP: case F_INC_NEQ_LOOP: case F_CONTINUE: case F_BREAK:
e9b1771999-11-18Henrik Grubbström (Grubba)  case F_DEFAULT:
f68afd1999-11-20Henrik Grubbström (Grubba)  case F_POP_VALUE:
5267b71995-08-09Fredrik Hübinette (Hubbe)  copy_shared_string(n->type,void_type_string);
cb22561995-10-11Fredrik Hübinette (Hubbe)  break; case F_DO:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CDR(n) || (CDR(n)->type == void_type_string)) {
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("do - while(): Conditional expression is void.");
e9b1771999-11-18Henrik Grubbström (Grubba)  } else if(!match_types(CDR(n)->type,mixed_type_string))
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Bad conditional expression do - while().");
cb22561995-10-11Fredrik Hübinette (Hubbe)  copy_shared_string(n->type,void_type_string); break; case F_FOR:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->type == void_type_string)) {
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("for(): Conditional expression is void.");
e9b1771999-11-18Henrik Grubbström (Grubba)  } else if(!match_types(CAR(n)->type,mixed_type_string))
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Bad conditional expression for().");
cb22561995-10-11Fredrik Hübinette (Hubbe)  copy_shared_string(n->type,void_type_string); break; case F_SWITCH:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->type == void_type_string)) {
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("switch(): Conditional expression is void.");
e9b1771999-11-18Henrik Grubbström (Grubba)  } else if(!match_types(CAR(n)->type,mixed_type_string))
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Bad switch expression.");
cb22561995-10-11Fredrik Hübinette (Hubbe)  copy_shared_string(n->type,void_type_string); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CONSTANT: n->type = get_type_of_svalue(& n->u.sval);
cb22561995-10-11Fredrik Hübinette (Hubbe)  break;
22a6d91999-12-19Henrik Grubbström (Grubba)  case F_FOREACH: if (!CAR(n) || (CAR(n)->token != F_VAL_LVAL)) { yyerror("foreach(): No expression to loop over."); } else { if (!CAAR(n) || pike_types_le(CAAR(n)->type, void_type_string)) { yyerror("foreach(): Looping over a void expression."); } else { struct pike_string *array_zero; MAKE_CONSTANT_SHARED_STRING(array_zero, tArr(tZero)); if (!pike_types_le(array_zero, CAAR(n)->type)) { yyerror("Bad argument 1 to foreach()."); } else { if ((lex.pragmas & ID_STRICT_TYPES) && !pike_types_le(CAAR(n)->type, array_type_string)) { struct pike_string *t = describe_type(CAAR(n)->type); yywarning("Argument 1 to foreach() is not always an array."); yywarning("Got: %s", t->str); free_string(t); } if (!CDAR(n) || pike_types_le(CDAR(n)->type, void_type_string)) { yyerror("Bad argument 2 to foreach()."); } else { struct pike_string *value_type = array_value_type(CAAR(n)->type); if (!pike_types_le(value_type, CDAR(n)->type)) { if (!match_types(value_type, CDAR(n)->type)) {
edcd891999-12-23Henrik Grubbström (Grubba)  yytype_error("Variable type mismatch in foreach().", value_type, CDAR(n)->type, 0);
22a6d91999-12-19Henrik Grubbström (Grubba)  } else if (lex.pragmas & ID_STRICT_TYPES) {
edcd891999-12-23Henrik Grubbström (Grubba)  yytype_error("Variable type mismatch in foreach().",
064f101999-12-23Henrik Grubbström (Grubba)  value_type, CDAR(n)->type, YYTE_IS_WARNING);
22a6d91999-12-19Henrik Grubbström (Grubba)  } } free_string(value_type); } } free_string(array_zero); } } copy_shared_string(n->type, void_type_string); break;
30c3b71999-11-22Henrik Grubbström (Grubba)  case F_SSCANF:
16addb1999-12-10Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->token != F_ARG_LIST) || !CAAR(n) || !CDAR(n)) { yyerror("Too few arguments to sscanf()."); } else { if (!pike_types_le(CAAR(n)->type, string_type_string)) { if (!match_types(CAAR(n)->type, string_type_string)) {
edcd891999-12-23Henrik Grubbström (Grubba)  yytype_error("Bad argument 1 to sscanf().", string_type_string, CAAR(n)->type, 0);
16addb1999-12-10Henrik Grubbström (Grubba)  } else if (lex.pragmas & ID_STRICT_TYPES) {
edcd891999-12-23Henrik Grubbström (Grubba)  yytype_error("Argument 1 to sscanf() has bad type.", string_type_string, CAAR(n)->type, YYTE_IS_WARNING);
16addb1999-12-10Henrik Grubbström (Grubba)  } } if (!pike_types_le(CDAR(n)->type, string_type_string)) { if (!match_types(CDAR(n)->type, string_type_string)) {
edcd891999-12-23Henrik Grubbström (Grubba)  yytype_error("Bad argument 2 to sscanf().", string_type_string, CDAR(n)->type, 0);
16addb1999-12-10Henrik Grubbström (Grubba)  } else if (lex.pragmas & ID_STRICT_TYPES) {
edcd891999-12-23Henrik Grubbström (Grubba)  yytype_error("Argument 2 to sscanf() has bad type.", string_type_string, CDAR(n)->type, YYTE_IS_WARNING);
16addb1999-12-10Henrik Grubbström (Grubba)  } } }
30c3b71999-11-22Henrik Grubbström (Grubba)  MAKE_CONSTANT_SHARED_STRING(n->type, tIntPos); break; case F_UNDEFINED:
84191b1999-11-23Henrik Grubbström (Grubba)  MAKE_CONSTANT_SHARED_STRING(n->type, tZero);
30c3b71999-11-22Henrik Grubbström (Grubba)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_ARG_LIST:
f68afd1999-11-20Henrik Grubbström (Grubba)  if (n->parent) { /* Propagate the changed type all the way up to the apply node. */ n->parent->node_info |= OPT_TYPE_NOT_FIXED; } /* FALL_THROUGH */ case F_COMMA_EXPR:
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!CAR(n) || CAR(n)->type==void_type_string) { if(CDR(n)) copy_shared_string(n->type,CDR(n)->type); else copy_shared_string(n->type,void_type_string);
f68afd1999-11-20Henrik Grubbström (Grubba)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } if(!CDR(n) || CDR(n)->type==void_type_string) { if(CAR(n)) copy_shared_string(n->type,CAR(n)->type); else copy_shared_string(n->type,void_type_string);
f68afd1999-11-20Henrik Grubbström (Grubba)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
16addb1999-12-10Henrik Grubbström (Grubba)  if (n->token == F_ARG_LIST) { n->type = or_pike_types(CAR(n)->type, CDR(n)->type, 0); } else { copy_shared_string(n->type, CDR(n)->type); } break;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
d00b001999-11-21Henrik Grubbström (Grubba)  case F_MAGIC_INDEX:
e948371999-12-29Henrik Grubbström (Grubba)  /* FIXME: Could have a stricter type for ::`->(). */ MAKE_CONSTANT_SHARED_STRING(n->type, tFunc(tMix,tMix)); break;
d00b001999-11-21Henrik Grubbström (Grubba)  case F_MAGIC_SET_INDEX:
e948371999-12-29Henrik Grubbström (Grubba)  /* FIXME: Could have a stricter type for ::`->=(). */ MAKE_CONSTANT_SHARED_STRING(n->type, tFunc(tMix tSetvar(0,tMix), tVar(0))); break;
d00b001999-11-21Henrik Grubbström (Grubba)  case F_CATCH:
e948371999-12-29Henrik Grubbström (Grubba)  /* FALL_THROUGH */
5267b71995-08-09Fredrik Hübinette (Hubbe)  default: copy_shared_string(n->type,mixed_type_string); }
f68afd1999-11-20Henrik Grubbström (Grubba)  if (n->type != old_type) { if (n->parent) { n->parent->node_info |= OPT_TYPE_NOT_FIXED; } } if (old_type) { free_string(old_type); }
ba0ca21999-11-22Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG check_type_string(n->type); #endif /* PIKE_DEBUG */
5267b71995-08-09Fredrik Hübinette (Hubbe) }
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void zapp_try_optimize(node *n) {
86bea91997-01-31Fredrik Hübinette (Hubbe)  if(!n) return;
5267b71995-08-09Fredrik Hübinette (Hubbe)  n->node_info &=~ OPT_TRY_OPTIMIZE; n->tree_info &=~ OPT_TRY_OPTIMIZE;
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(car_is_node(n)) zapp_try_optimize(CAR(n)); if(cdr_is_node(n)) zapp_try_optimize(CDR(n)); }
969a291999-11-17Henrik Grubbström (Grubba) #if defined(SHARED_NODES) && !defined(IN_TPIKE)
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
36dd451999-11-17Henrik Grubbström (Grubba) static void find_usage(node *n, unsigned char *usage,
969a291999-11-17Henrik Grubbström (Grubba)  unsigned char *switch_u, const unsigned char *cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  const unsigned char *break_u, const unsigned char *catch_u)
969a291999-11-17Henrik Grubbström (Grubba) { if (!n) return;
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
969a291999-11-17Henrik Grubbström (Grubba)  switch(n->token) { case F_ASSIGN: if ((CDR(n)->token == F_LOCAL) && (!CDR(n)->u.integer.b)) { usage[CDR(n)->u.integer.a] = 0;
55a20a1999-11-17Henrik Grubbström (Grubba)  } else if (CDR(n)->token == F_ARRAY_LVALUE) {
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  }
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return;
36dd451999-11-17Henrik Grubbström (Grubba)  case F_SSCANF: { int i; /* catch_usage is restored if sscanf throws an error. */ for (i=0; i < MAX_LOCAL; i++) { usage[i] |= catch_u[i]; } /* Only the first two arguments are evaluated. */ if (CAR(n)) { find_usage(CDAR(n), usage, switch_u, cont_u, break_u, catch_u); find_usage(CAAR(n), usage, switch_u, cont_u, break_u, catch_u); } return; } case F_CATCH: { unsigned char catch_usage[MAX_LOCAL]; int i; MEMCPY(catch_usage, usage, MAX_LOCAL); find_usage(CAR(n), usage, switch_u, cont_u, catch_usage, catch_usage); for(i=0; i < MAX_LOCAL; i++) { usage[i] |= catch_usage[i]; } return; } case F_APPLY: { int i; /* catch_usage is restored if the function throws an error. */ for (i=0; i < MAX_LOCAL; i++) { usage[i] |= catch_u[i]; } find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u); find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u); return; }
55a20a1999-11-17Henrik Grubbström (Grubba)  case F_LVALUE_LIST:
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
55a20a1999-11-17Henrik Grubbström (Grubba)  if (CAR(n)) { if ((CAR(n)->token == F_LOCAL) && (!CAR(n)->u.integer.b)) { usage[CAR(n)->u.integer.a] = 0; } } return; case F_ARRAY_LVALUE:
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
55a20a1999-11-17Henrik Grubbström (Grubba)  return;
969a291999-11-17Henrik Grubbström (Grubba)  case F_CONTINUE: MEMCPY(usage, cont_u, MAX_LOCAL); return; case F_BREAK: MEMCPY(usage, break_u, MAX_LOCAL); return; case F_DEFAULT: case F_CASE: { int i;
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u); find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for(i = 0; i < MAX_LOCAL; i++) { switch_u[i] |= usage[i]; } return; } case F_SWITCH: { unsigned char break_usage[MAX_LOCAL]; unsigned char switch_usage[MAX_LOCAL]; int i; MEMSET(switch_usage, 0, MAX_LOCAL); MEMCPY(break_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), usage, switch_usage, cont_u, break_usage, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for(i = 0; i < MAX_LOCAL; i++) { usage[i] |= switch_usage[i]; }
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return; } case F_RETURN: MEMSET(usage, 0, MAX_LOCAL); /* FIXME: The function arguments should be marked "used", since * they are seen in backtraces. */ return; case F_LOR: case F_LAND: { unsigned char trail_usage[MAX_LOCAL]; int i; MEMCPY(trail_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for(i=0; i < MAX_LOCAL; i++) { usage[i] |= trail_usage[i]; }
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return; } case '?': { unsigned char cadr_usage[MAX_LOCAL]; unsigned char cddr_usage[MAX_LOCAL]; int i; MEMCPY(cadr_usage, usage, MAX_LOCAL); MEMCPY(cddr_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CADR(n), cadr_usage, switch_u, cont_u, break_u, catch_u); find_usage(CDDR(n), cddr_usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for (i=0; i < MAX_LOCAL; i++) { usage[i] = cadr_usage[i] | cddr_usage[i]; }
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return; } case F_DO: { unsigned char break_usage[MAX_LOCAL]; unsigned char continue_usage[MAX_LOCAL]; MEMCPY(break_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), usage, switch_u, cont_u, break_usage, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(continue_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, break_usage, continue_usage, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return; } case F_FOR: {
36dd451999-11-17Henrik Grubbström (Grubba)  unsigned char loop_usage[MAX_LOCAL];
969a291999-11-17Henrik Grubbström (Grubba)  unsigned char break_usage[MAX_LOCAL]; unsigned char continue_usage[MAX_LOCAL]; node *car1, cadr, cddr;
55a20a1999-11-17Henrik Grubbström (Grubba)  int i;
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(break_usage, usage, MAX_LOCAL); /* for(;a;b) c; is handled like: * * if (a) { do { c; b; } while(a); } */
36dd451999-11-17Henrik Grubbström (Grubba)  MEMSET(loop_usage, 0, MAX_LOCAL); find_usage(CAR(n), loop_usage, switch_u, cont_u, break_u, catch_u); if (CDR(n)) { find_usage(CDDR(n), loop_usage, switch_u, cont_u, break_usage, catch_u);
969a291999-11-17Henrik Grubbström (Grubba) 
36dd451999-11-17Henrik Grubbström (Grubba)  MEMCPY(continue_usage, loop_usage, MAX_LOCAL); find_usage(CADR(n), loop_usage, switch_u, continue_usage, break_usage, catch_u); }
969a291999-11-17Henrik Grubbström (Grubba) 
55a20a1999-11-17Henrik Grubbström (Grubba)  for (i = 0; i < MAX_LOCAL; i++) {
36dd451999-11-17Henrik Grubbström (Grubba)  usage[i] |= loop_usage[i];
55a20a1999-11-17Henrik Grubbström (Grubba)  }
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return; } case F_FOREACH: {
36dd451999-11-17Henrik Grubbström (Grubba)  unsigned char loop_usage[MAX_LOCAL];
969a291999-11-17Henrik Grubbström (Grubba)  unsigned char break_usage[MAX_LOCAL]; unsigned char continue_usage[MAX_LOCAL];
36dd451999-11-17Henrik Grubbström (Grubba)  int i;
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(break_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  /* Find the usage from the loop */ MEMSET(loop_usage, 0, MAX_LOCAL);
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(continue_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), loop_usage, switch_u, continue_usage, break_usage, catch_u); if (CDAR(n)->token == F_LOCAL) { if (!(CDAR(n)->u.integer.b)) { loop_usage[CDAR(n)->u.integer.a] = 0; } } else if (CDAR(n)->token == F_LVALUE_LIST) { find_usage(CDAR(n), loop_usage, switch_u, cont_u, break_u, catch_u); } for(i=0; i < MAX_LOCAL; i++) { usage[i] |= loop_usage[i]; } find_usage(CAAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return; } case F_LOCAL: /* Use of local variable. */ if (!n->u.integer.b) { /* Recently used, and used at all */ usage[n->u.integer.a] = 3; } return; default: if (cdr_is_node(n)) {
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  } if (car_is_node(n)) {
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  } return; } } /* Note: Always builds a new tree. */ static node *low_localopt(node *n, unsigned char *usage, unsigned char *switch_u, const unsigned char *cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  const unsigned char *break_u, const unsigned char *catch_u)
969a291999-11-17Henrik Grubbström (Grubba) { node *car, *cdr; if (!n) return NULL; switch(n->token) { case F_ASSIGN: if ((CDR(n)->token == F_LOCAL) && (!CDR(n)->u.integer.b)) { /* Assignment of local variable */ if (!(usage[CDR(n)->u.integer.a] & 1)) { /* Value isn't used. */
1aac411999-11-19Henrik Grubbström (Grubba)  struct pike_string *ref_type; MAKE_CONSTANT_SHARED_STRING(ref_type, tOr(tComplex, tString)); if (!match_types(CDR(n)->type, ref_type)) { /* The variable doesn't hold a refcounted value. */ free_string(ref_type); return low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u); } free_string(ref_type);
969a291999-11-17Henrik Grubbström (Grubba)  } usage[CDR(n)->u.integer.a] = 0;
55a20a1999-11-17Henrik Grubbström (Grubba)  cdr = CDR(n); ADD_NODE_REF(cdr); } else if (CDR(n)->token == F_ARRAY_LVALUE) {
36dd451999-11-17Henrik Grubbström (Grubba)  cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
55a20a1999-11-17Henrik Grubbström (Grubba)  } else { cdr = CDR(n); ADD_NODE_REF(cdr);
969a291999-11-17Henrik Grubbström (Grubba)  } return mknode(F_ASSIGN, low_localopt(CAR(n), usage, switch_u, cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  break_u, catch_u), cdr); case F_SSCANF: { int i; /* catch_usage is restored if sscanf throws an error. */ for (i=0; i < MAX_LOCAL; i++) { usage[i] |= catch_u[i]; } /* Only the first two arguments are evaluated. */ if (CAR(n)) { cdr = low_localopt(CDAR(n), usage, switch_u, cont_u, break_u, catch_u); car = low_localopt(CAAR(n), usage, switch_u, cont_u, break_u, catch_u); if (CDR(n)) { ADD_NODE_REF(CDR(n)); } return mknode(F_SSCANF, mknode(F_ARG_LIST, car, cdr), CDR(n)); } ADD_NODE_REF(n); return n; } case F_CATCH: { unsigned char catch_usage[MAX_LOCAL]; int i; MEMCPY(catch_usage, usage, MAX_LOCAL); car = low_localopt(CAR(n), usage, switch_u, cont_u, catch_usage, catch_usage); for(i=0; i < MAX_LOCAL; i++) { usage[i] |= catch_usage[i]; } return mknode(F_CATCH, car, 0); } break; case F_APPLY: { int i; /* catch_usage is restored if the function throws an error. */ for (i=0; i < MAX_LOCAL; i++) { usage[i] |= catch_u[i]; } cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u); car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u); return mknode(F_APPLY, car, cdr); }
55a20a1999-11-17Henrik Grubbström (Grubba)  case F_LVALUE_LIST:
36dd451999-11-17Henrik Grubbström (Grubba)  cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
55a20a1999-11-17Henrik Grubbström (Grubba)  if (CAR(n)) { if ((CAR(n)->token == F_LOCAL) && (!CAR(n)->u.integer.b)) { /* Array assignment of local variable. */ if (!(usage[CDR(n)->u.integer.a] & 1)) { /* Variable isn't used. */ /* FIXME: Warn? */ } usage[CAR(n)->u.integer.a] = 0; } ADD_NODE_REF(CAR(n)); } return mknode(F_LVALUE_LIST, CAR(n), cdr); case F_ARRAY_LVALUE: return mknode(F_ARRAY_LVALUE, low_localopt(CAR(n), usage, switch_u, cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  break_u, catch_u), 0);
55a20a1999-11-17Henrik Grubbström (Grubba) 
969a291999-11-17Henrik Grubbström (Grubba)  case F_CAST: return mkcastnode(n->type, low_localopt(CAR(n), usage, switch_u, cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  break_u, catch_u));
969a291999-11-17Henrik Grubbström (Grubba) 
84191b1999-11-23Henrik Grubbström (Grubba)  case F_SOFT_CAST: return mksoftcastnode(n->type, low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u));
969a291999-11-17Henrik Grubbström (Grubba)  case F_CONTINUE: MEMCPY(usage, cont_u, MAX_LOCAL); ADD_NODE_REF(n); return n; case F_BREAK: MEMCPY(usage, break_u, MAX_LOCAL); ADD_NODE_REF(n); return n; case F_DEFAULT: case F_CASE: { int i;
36dd451999-11-17Henrik Grubbström (Grubba)  cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u); car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for(i = 0; i < MAX_LOCAL; i++) { switch_u[i] |= usage[i]; } return mknode(n->token, car, cdr); } case F_SWITCH: { unsigned char break_usage[MAX_LOCAL]; unsigned char switch_usage[MAX_LOCAL]; int i; MEMSET(switch_usage, 0, MAX_LOCAL); MEMCPY(break_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  cdr = low_localopt(CDR(n), usage, switch_usage, cont_u, break_usage, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for(i = 0; i < MAX_LOCAL; i++) { usage[i] |= switch_usage[i]; }
36dd451999-11-17Henrik Grubbström (Grubba)  car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return mknode(F_SWITCH, car, cdr); } case F_RETURN: MEMSET(usage, 0, MAX_LOCAL); /* FIXME: The function arguments should be marked "used", since * they are seen in backtraces. */ return mknode(F_RETURN, low_localopt(CAR(n), usage, switch_u, cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  break_u, catch_u), 0);
969a291999-11-17Henrik Grubbström (Grubba)  case F_LOR: case F_LAND: { unsigned char trail_usage[MAX_LOCAL]; int i; MEMCPY(trail_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for(i=0; i < MAX_LOCAL; i++) { usage[i] |= trail_usage[i]; }
36dd451999-11-17Henrik Grubbström (Grubba)  car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return mknode(n->token, car, cdr); } case '?': { unsigned char cadr_usage[MAX_LOCAL]; unsigned char cddr_usage[MAX_LOCAL]; int i; MEMCPY(cadr_usage, usage, MAX_LOCAL); MEMCPY(cddr_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  car = low_localopt(CADR(n), cadr_usage, switch_u, cont_u, break_u, catch_u); cdr = low_localopt(CDDR(n), cddr_usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for (i=0; i < MAX_LOCAL; i++) { usage[i] = cadr_usage[i] | cddr_usage[i]; } cdr = mknode(':', car, cdr);
36dd451999-11-17Henrik Grubbström (Grubba)  car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return mknode('?', car, cdr); } case F_DO: { unsigned char break_usage[MAX_LOCAL]; unsigned char continue_usage[MAX_LOCAL];
36dd451999-11-17Henrik Grubbström (Grubba)  int i;
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(break_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  /* Find the usage from the loop */ find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u); MEMCPY(continue_usage, usage, MAX_LOCAL); find_usage(CAR(n), usage, switch_u, continue_usage, break_usage, catch_u); for (i = 0; i < MAX_LOCAL; i++) { usage[i] |= break_usage[i]; } cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_usage, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(continue_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  car = low_localopt(CAR(n), usage, switch_u, continue_usage, break_usage, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return mknode(F_DO, car, cdr); } case F_FOR: {
36dd451999-11-17Henrik Grubbström (Grubba)  unsigned char loop_usage[MAX_LOCAL];
969a291999-11-17Henrik Grubbström (Grubba)  unsigned char break_usage[MAX_LOCAL]; unsigned char continue_usage[MAX_LOCAL];
55a20a1999-11-17Henrik Grubbström (Grubba)  int i;
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(break_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  /* * if (a A|B) { * B * do { * B * c; * continue: * D * b; * C * } while (a A|B); * A * } * break: * A
969a291999-11-17Henrik Grubbström (Grubba)  */
36dd451999-11-17Henrik Grubbström (Grubba)  /* Find the usage from the loop. */ MEMSET(loop_usage, 0, MAX_LOCAL); find_usage(CAR(n), loop_usage, switch_u, cont_u, break_u, catch_u); if (CDR(n)) { find_usage(CDDR(n), loop_usage, switch_u, cont_u, break_usage, catch_u); MEMCPY(continue_usage, loop_usage, MAX_LOCAL); find_usage(CADR(n), loop_usage, switch_u, continue_usage, break_usage, catch_u); } for (i = 0; i < MAX_LOCAL; i++) { usage[i] |= loop_usage[i]; } /* The last thing to be evaluated is the conditional */ car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u); if (CDR(n)) { node *cadr, *cddr;
969a291999-11-17Henrik Grubbström (Grubba) 
36dd451999-11-17Henrik Grubbström (Grubba)  /* The incrementor */ cddr = low_localopt(CDDR(n), usage, switch_u, cont_u, break_usage, catch_u); MEMCPY(continue_usage, usage, MAX_LOCAL); /* The body */ cadr = low_localopt(CADR(n), usage, switch_u, continue_usage, break_usage, catch_u); cdr = mknode(':', cadr, cddr); } else { cdr = 0; }
969a291999-11-17Henrik Grubbström (Grubba) 
55a20a1999-11-17Henrik Grubbström (Grubba)  for (i = 0; i < MAX_LOCAL; i++) { usage[i] |= break_usage[i]; }
36dd451999-11-17Henrik Grubbström (Grubba)  /* The conditional is also the first thing to be evaluated. */ find_usage(car, usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return mknode(F_FOR, car, cdr); } case F_FOREACH: {
36dd451999-11-17Henrik Grubbström (Grubba)  unsigned char loop_usage[MAX_LOCAL];
969a291999-11-17Henrik Grubbström (Grubba)  unsigned char break_usage[MAX_LOCAL]; unsigned char continue_usage[MAX_LOCAL];
36dd451999-11-17Henrik Grubbström (Grubba)  int i;
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(break_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  /* * D * arr = copy_value(arr); * int i = 0; * A|B * while (i < sizeof(arr)) { * B * loopvar = arr[i]; * C * body; * continue: * A|B * } * break: * A */ /* Find the usage from the loop */ MEMSET(loop_usage, 0, MAX_LOCAL);
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(continue_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), loop_usage, switch_u, continue_usage, break_usage, catch_u); if (CDAR(n)->token == F_LOCAL) { if (!(CDAR(n)->u.integer.b)) { loop_usage[CDAR(n)->u.integer.a] = 0; } } else if (CDAR(n)->token == F_LVALUE_LIST) { find_usage(CDAR(n), loop_usage, switch_u, cont_u, break_u, catch_u); } for (i = 0; i < MAX_LOCAL; i++) { usage[i] |= loop_usage[i]; } MEMCPY(continue_usage, usage, MAX_LOCAL); cdr = low_localopt(CDR(n), usage, switch_u, continue_usage, break_usage, catch_u); if (CDAR(n)->token == F_LOCAL) { if (!(CDAR(n)->u.integer.b)) { usage[CDAR(n)->u.integer.a] = 0; } } else if (CDAR(n)->token == F_LVALUE_LIST) { find_usage(CDAR(n), usage, switch_u, cont_u, break_u, catch_u); } for (i = 0; i < MAX_LOCAL; i++) { usage[i] |= break_usage[i]; } car = low_localopt(CAAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  ADD_NODE_REF(CDAR(n)); return mknode(F_FOREACH, mknode(F_VAL_LVAL, car, CDAR(n)), cdr); } case F_LOCAL: /* Use of local variable. */ if (!n->u.integer.b) { /* Recently used, and used at all */ usage[n->u.integer.a] = 3; } ADD_NODE_REF(n); return n; default: if (cdr_is_node(n)) {
36dd451999-11-17Henrik Grubbström (Grubba)  cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return mknode(n->token, low_localopt(CAR(n), usage, switch_u, cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  break_u, catch_u),
969a291999-11-17Henrik Grubbström (Grubba)  cdr); } if (car_is_node(n)) { ADD_NODE_REF(CDR(n)); return mknode(n->token, low_localopt(CAR(n), usage, switch_u, cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  break_u, catch_u),
969a291999-11-17Henrik Grubbström (Grubba)  CDR(n)); } ADD_NODE_REF(n); return n; } } static node *localopt(node *n) { unsigned char usage[MAX_LOCAL]; unsigned char b_usage[MAX_LOCAL]; unsigned char c_usage[MAX_LOCAL]; unsigned char s_usage[MAX_LOCAL];
36dd451999-11-17Henrik Grubbström (Grubba)  unsigned char catch_usage[MAX_LOCAL];
969a291999-11-17Henrik Grubbström (Grubba)  node *n2; MEMSET(usage, 0, MAX_LOCAL); MEMSET(b_usage, 0, MAX_LOCAL); MEMSET(c_usage, 0, MAX_LOCAL); MEMSET(s_usage, 0, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  MEMSET(catch_usage, 0, MAX_LOCAL);
969a291999-11-17Henrik Grubbström (Grubba) 
36dd451999-11-17Henrik Grubbström (Grubba)  n2 = low_localopt(n, usage, s_usage, c_usage, b_usage, catch_usage);
969a291999-11-17Henrik Grubbström (Grubba) 
36dd451999-11-17Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if (l_flag > 0) { if ((n2 != n) || (l_flag > 4)) { fprintf(stderr, "\nBefore localopt: "); print_tree(n);
969a291999-11-17Henrik Grubbström (Grubba) 
36dd451999-11-17Henrik Grubbström (Grubba)  fprintf(stderr, "After localopt: "); print_tree(n2); } } #endif /* PIKE_DEBUG */
969a291999-11-17Henrik Grubbström (Grubba) 
36dd451999-11-17Henrik Grubbström (Grubba)  free_node(n);
969a291999-11-17Henrik Grubbström (Grubba)  return n2; } #endif /* SHARED_NODES && !IN_TPIKE */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void optimize(node *n) { node *tmp1, *tmp2, *tmp3;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  INT32 save_line = lex.current_line;
178e2d1999-12-27Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG struct pike_string *save_file = lex.current_file; #endif /* PIKE_DEBUG */
5267b71995-08-09Fredrik Hübinette (Hubbe)  do {
bf4f7d1999-11-12Henrik Grubbström (Grubba)  if(car_is_node(n) && ((CAR(n)->node_info & (OPT_OPTIMIZED|OPT_DEFROSTED)) != OPT_OPTIMIZED))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
bf4f7d1999-11-12Henrik Grubbström (Grubba)  CAR(n)->parent = n; n = CAR(n);
5267b71995-08-09Fredrik Hübinette (Hubbe)  continue; }
bf4f7d1999-11-12Henrik Grubbström (Grubba)  if(cdr_is_node(n) && ((CDR(n)->node_info & (OPT_OPTIMIZED|OPT_DEFROSTED)) != OPT_OPTIMIZED))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
bf4f7d1999-11-12Henrik Grubbström (Grubba)  CDR(n)->parent = n; n = CDR(n);
5267b71995-08-09Fredrik Hübinette (Hubbe)  continue; }
bf4f7d1999-11-12Henrik Grubbström (Grubba)  #if defined(SHARED_NODES) if ((n->node_info & OPT_DEFROSTED) && (n->parent)) { #ifndef IN_TPIKE /* Add ref since both freeze_node() and use_tmp1 will free it. */ ADD_NODE_REF(n); /* We don't want freeze_node() to find this node in the hash-table. */ tmp1 = freeze_node(n); if (tmp1 != n) { /* n was a duplicate node. Use the original. */ goto use_tmp1; } /* Remove the extra ref from n */ free_node(n);
969a291999-11-17Henrik Grubbström (Grubba) #else /* IN_TPIKE */
bf4f7d1999-11-12Henrik Grubbström (Grubba)  n->node_info &= ~OPT_DEFROSTED;
969a291999-11-17Henrik Grubbström (Grubba) #endif /* !IN_TPIKE */
bf4f7d1999-11-12Henrik Grubbström (Grubba)  if (n->node_info & OPT_OPTIMIZED) { /* No need to check this node any more. */ n = n->parent; continue; } } #endif /* SHARED_NODES && !IN_TPIKE */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  lex.current_line = n->line_number;
178e2d1999-12-27Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG lex.current_file = n->current_file; #endif /* PIKE_DEBUG */
66d51c1997-03-04Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  n->tree_info = n->node_info; if(car_is_node(n)) n->tree_info |= CAR(n)->tree_info; if(cdr_is_node(n)) n->tree_info |= CDR(n)->tree_info;
66d51c1997-03-04Fredrik Hübinette (Hubbe)  if(!n->parent) break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(n->tree_info & (OPT_NOT_CONST| OPT_SIDE_EFFECT| OPT_EXTERNAL_DEPEND|
65757d2000-08-31Henrik Grubbström (Grubba)  OPT_ASSIGNMENT| OPT_RETURN))
5267b71995-08-09Fredrik Hübinette (Hubbe)  { if(car_is_node(n) && !(CAR(n)->tree_info & (OPT_NOT_CONST| OPT_SIDE_EFFECT| OPT_EXTERNAL_DEPEND|
65757d2000-08-31Henrik Grubbström (Grubba)  OPT_ASSIGNMENT| OPT_RETURN)) &&
5267b71995-08-09Fredrik Hübinette (Hubbe)  (CAR(n)->tree_info & OPT_TRY_OPTIMIZE) && CAR(n)->token != ':') {
046afe1999-11-11Henrik Grubbström (Grubba) #ifdef SHARED_NODES sub_node(n); #endif /* SHARED_NODES */ _CAR(n) = eval(CAR(n)); #ifdef SHARED_NODES n->hash = hash_node(n);
bf4f7d1999-11-12Henrik Grubbström (Grubba)  n->node_info |= OPT_DEFROSTED;
046afe1999-11-11Henrik Grubbström (Grubba)  add_node(n); #endif /* SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(CAR(n)) CAR(n)->parent = n; zapp_try_optimize(CAR(n)); /* avoid infinite loops */ continue; } if(cdr_is_node(n) && !(CDR(n)->tree_info & (OPT_NOT_CONST| OPT_SIDE_EFFECT| OPT_EXTERNAL_DEPEND|
65757d2000-08-31Henrik Grubbström (Grubba)  OPT_ASSIGNMENT| OPT_RETURN)) &&
5267b71995-08-09Fredrik Hübinette (Hubbe)  (CDR(n)->tree_info & OPT_TRY_OPTIMIZE) && CDR(n)->token != ':') {
046afe1999-11-11Henrik Grubbström (Grubba) #ifdef SHARED_NODES sub_node(n); #endif /* SHARED_NODES */ _CDR(n) = eval(CDR(n)); #ifdef SHARED_NODES n->hash = hash_node(n);
bf4f7d1999-11-12Henrik Grubbström (Grubba)  n->node_info |= OPT_DEFROSTED;
046afe1999-11-11Henrik Grubbström (Grubba)  add_node(n); #endif /* SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(CDR(n)) CDR(n)->parent = n; zapp_try_optimize(CDR(n)); /* avoid infinite loops */ continue; } }
f68afd1999-11-20Henrik Grubbström (Grubba)  if (!n->type || (n->node_info & OPT_TYPE_NOT_FIXED)) { fix_type_field(n); }
3c0c281998-01-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(n->type);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
66d51c1997-03-04Fredrik Hübinette (Hubbe)  if(l_flag > 3 && n)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
b464611999-11-14Henrik Grubbström (Grubba)  fprintf(stderr,"Optimizing (tree info=%04x):",n->tree_info);
5267b71995-08-09Fredrik Hübinette (Hubbe)  print_tree(n); } #endif
7018811999-11-08Henrik Grubbström (Grubba) #ifndef IN_TPIKE
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(n->token) {
7018811999-11-08Henrik Grubbström (Grubba) #include "treeopt.h"
5267b71995-08-09Fredrik Hübinette (Hubbe)  use_car:
71e11e1999-11-12Henrik Grubbström (Grubba)  ADD_NODE_REF2(CAR(n), tmp1 = CAR(n));
5267b71995-08-09Fredrik Hübinette (Hubbe)  goto use_tmp1; use_cdr:
71e11e1999-11-12Henrik Grubbström (Grubba)  ADD_NODE_REF2(CDR(n), tmp1 = CDR(n));
5267b71995-08-09Fredrik Hübinette (Hubbe)  goto use_tmp1;
5392401999-11-06Henrik Grubbström (Grubba)  zap_node: tmp1 = 0; goto use_tmp1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  use_tmp1:
bf4f7d1999-11-12Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if (l_flag > 4) { fprintf(stderr, "Optimized: "); print_tree(n); fprintf(stderr, "Result: "); print_tree(tmp1); } #endif /* PIKE_DEBUG */
046afe1999-11-11Henrik Grubbström (Grubba) #ifdef SHARED_NODES sub_node(n->parent); #endif /* SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(CAR(n->parent) == n)
a836c01999-11-12Henrik Grubbström (Grubba)  _CAR(n->parent) = tmp1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  else
a836c01999-11-12Henrik Grubbström (Grubba)  _CDR(n->parent) = tmp1;
046afe1999-11-11Henrik Grubbström (Grubba) 
f68afd1999-11-20Henrik Grubbström (Grubba)  if (!tmp1 || (tmp1->type != n->type)) { n->parent->node_info |= OPT_TYPE_NOT_FIXED; }
046afe1999-11-11Henrik Grubbström (Grubba) #ifdef SHARED_NODES n->parent->hash = hash_node(n->parent); add_node(n->parent);
bf4f7d1999-11-12Henrik Grubbström (Grubba)  n->parent->node_info |= OPT_DEFROSTED;
046afe1999-11-11Henrik Grubbström (Grubba) #endif /* SHARED_NODES */
5392401999-11-06Henrik Grubbström (Grubba)  if(tmp1) tmp1->parent = n->parent; else tmp1 = n->parent;
046afe1999-11-11Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  free_node(n);
046afe1999-11-11Henrik Grubbström (Grubba)  n = tmp1;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(l_flag > 3) {
bf4f7d1999-11-12Henrik Grubbström (Grubba)  fprintf(stderr,"Result: ");
5267b71995-08-09Fredrik Hübinette (Hubbe)  print_tree(n); } #endif continue; }
7018811999-11-08Henrik Grubbström (Grubba) #endif /* !IN_TPIKE */
5267b71995-08-09Fredrik Hübinette (Hubbe)  n->node_info |= OPT_OPTIMIZED; n=n->parent; }while(n);
178e2d1999-12-27Henrik Grubbström (Grubba) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  lex.current_line = save_line;
178e2d1999-12-27Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG lex.current_file = save_file; #endif /* PIKE_DEBUG */
5267b71995-08-09Fredrik Hübinette (Hubbe) }
a29e021996-10-15Fredrik Hübinette (Hubbe) struct timer_oflo { INT32 counter; int yes; };
d085c71996-11-18Fredrik Hübinette (Hubbe) static void check_evaluation_time(struct callback *cb,void *tmp,void *ignored)
a29e021996-10-15Fredrik Hübinette (Hubbe) { struct timer_oflo *foo=(struct timer_oflo *)tmp; if(foo->counter-- < 0) { foo->yes=1;
dc7cc91998-01-14Fredrik Hübinette (Hubbe)  pike_throw();
a29e021996-10-15Fredrik Hübinette (Hubbe)  } }
93b7202000-08-14Henrik Grubbström (Grubba) ptrdiff_t eval_low(node *n)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
5c8e891995-10-29Fredrik Hübinette (Hubbe)  unsigned INT16 num_strings, num_constants; INT32 jump;
cd86322000-07-06Fredrik Hübinette (Hubbe)  struct svalue *save_sp = Pike_sp;
93b7202000-08-14Henrik Grubbström (Grubba)  ptrdiff_t ret;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
66d51c1997-03-04Fredrik Hübinette (Hubbe)  if(l_flag > 3 && n) { fprintf(stderr,"Evaluating (tree info=%x):",n->tree_info); print_tree(n); } #endif
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->num_parse_error) return -1;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  num_strings=Pike_compiler->new_program->num_strings; num_constants=Pike_compiler->new_program->num_constants;
393a592000-08-16Henrik Grubbström (Grubba)  jump = DO_NOT_WARN((INT32)PC);
5267b71995-08-09Fredrik Hübinette (Hubbe)  store_linenumbers=0;
a836c01999-11-12Henrik Grubbström (Grubba)  docode(dmalloc_touch(node *, n));
5267b71995-08-09Fredrik Hübinette (Hubbe)  ins_f_byte(F_DUMB_RETURN); store_linenumbers=1; ret=-1;
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(!Pike_compiler->num_parse_error)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
a29e021996-10-15Fredrik Hübinette (Hubbe)  struct callback *tmp_callback; struct timer_oflo foo; /* This is how long we try to optimize before giving up... */ foo.counter=10000; foo.yes=0; tmp_callback=add_to_callback(&evaluator_callbacks, check_evaluation_time, (void *)&foo,0);
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(apply_low_safe_and_stupid(Pike_compiler->fake_object, jump))
5267b71995-08-09Fredrik Hübinette (Hubbe)  { /* Generate error message */
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(!Pike_compiler->catch_level)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
9649491998-02-27Fredrik Hübinette (Hubbe)  if(throw_value.type == T_ARRAY && throw_value.u.array->size) { union anything *a; a=low_array_get_item_ptr(throw_value.u.array, 0, T_STRING); if(a) { yyerror(a->string->str); }else{ yyerror("Nonstandard error format."); }
1994251999-09-06Fredrik Hübinette (Hubbe)  } else if(throw_value.type == T_OBJECT) { ref_push_object(throw_value.u.object); push_int(0); f_index(2);
cd86322000-07-06Fredrik Hübinette (Hubbe)  if(Pike_sp[-1].type != T_STRING)
1994251999-09-06Fredrik Hübinette (Hubbe)  yyerror("Nonstandard error format."); else
cd86322000-07-06Fredrik Hübinette (Hubbe)  yyerror(Pike_sp[-1].u.string->str);
1994251999-09-06Fredrik Hübinette (Hubbe)  pop_stack(); } else {
5267b71995-08-09Fredrik Hübinette (Hubbe)  yyerror("Nonstandard error format."); } } }else{
a29e021996-10-15Fredrik Hübinette (Hubbe)  if(foo.yes)
cd86322000-07-06Fredrik Hübinette (Hubbe)  pop_n_elems(Pike_sp-save_sp);
a29e021996-10-15Fredrik Hübinette (Hubbe)  else
cd86322000-07-06Fredrik Hübinette (Hubbe)  ret=Pike_sp-save_sp;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
a29e021996-10-15Fredrik Hübinette (Hubbe)  remove_callback(tmp_callback);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
bad5162000-06-23Fredrik Hübinette (Hubbe)  while(Pike_compiler->new_program->num_strings > num_strings)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->new_program->num_strings--; free_string(Pike_compiler->new_program->strings[Pike_compiler->new_program->num_strings]);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
bad5162000-06-23Fredrik Hübinette (Hubbe)  while(Pike_compiler->new_program->num_constants > num_constants)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
8132f31999-09-19Henrik Grubbström (Grubba)  struct program_constant *p_const;
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->new_program->num_constants--;
8132f31999-09-19Henrik Grubbström (Grubba) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  p_const = Pike_compiler->new_program->constants + Pike_compiler->new_program->num_constants;
8132f31999-09-19Henrik Grubbström (Grubba)  free_svalue(&p_const->sval); if (p_const->name) { free_string(p_const->name); p_const->name = NULL; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->new_program->num_program=jump;
5267b71995-08-09Fredrik Hübinette (Hubbe)  return ret; } static node *eval(node *n) {
3facd41999-12-30Martin Stjernholm  node *new;
93b7202000-08-14Henrik Grubbström (Grubba)  ptrdiff_t args;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!is_const(n) || n->token==':') return n;
84191b1999-11-23Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  args=eval_low(n); switch(args) { case -1: return n; break; case 0:
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->catch_level) return n;
5267b71995-08-09Fredrik Hübinette (Hubbe)  free_node(n); n=0; break; case 1:
cd86322000-07-06Fredrik Hübinette (Hubbe)  if(Pike_compiler->catch_level && IS_ZERO(Pike_sp-1))
9649491998-02-27Fredrik Hübinette (Hubbe)  { pop_stack(); return n; }
46ab571999-12-30Henrik Grubbström (Grubba)  if (n->token == F_SOFT_CAST) {
cd86322000-07-06Fredrik Hübinette (Hubbe)  new = mksoftcastnode(n->type, mksvaluenode(Pike_sp-1));
46ab571999-12-30Henrik Grubbström (Grubba)  } else {
cd86322000-07-06Fredrik Hübinette (Hubbe)  new = mksvaluenode(Pike_sp-1);
46ab571999-12-30Henrik Grubbström (Grubba)  if (n->type && (!new->type || ((n->type != new->type) && pike_types_le(n->type,new->type)))) { if (new->type) free_string(new->type); copy_shared_string(new->type,n->type); }
84191b1999-11-23Henrik Grubbström (Grubba)  }
3facd41999-12-30Martin Stjernholm  free_node(n); n = new;
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_stack(); break; default:
84191b1999-11-23Henrik Grubbström (Grubba)  if (n->token != F_SOFT_CAST) { free_node(n); n=NULL; while(args--) {
cd86322000-07-06Fredrik Hübinette (Hubbe)  n=mknode(F_ARG_LIST,mksvaluenode(Pike_sp-1),n);
84191b1999-11-23Henrik Grubbström (Grubba)  pop_stack(); } } else { node *nn = n; n = NULL; while(args--) {
cd86322000-07-06Fredrik Hübinette (Hubbe)  n=mknode(F_ARG_LIST,mksvaluenode(Pike_sp-1),n);
84191b1999-11-23Henrik Grubbström (Grubba)  pop_stack(); } n = mksoftcastnode(nn->type, n); free_node(nn);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
a836c01999-11-12Henrik Grubbström (Grubba)  return dmalloc_touch(node *, n);
5267b71995-08-09Fredrik Hübinette (Hubbe) } INT32 last_function_opt_info;
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
329cc01997-02-17Fredrik Hübinette (Hubbe) static int stupid_args(node *n, int expected,int vargs)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
329cc01997-02-17Fredrik Hübinette (Hubbe)  if(!n) return expected;
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
329cc01997-02-17Fredrik Hübinette (Hubbe)  switch(n->token) { case F_PUSH_ARRAY: if(!vargs) return -1; if(stupid_args(CAR(n), expected,vargs) == expected+1) return 65535; return -1; case F_ARG_LIST: expected=stupid_args(CAR(n), expected,vargs); if(expected==-1) return -1; return stupid_args(CDR(n), expected,vargs); case F_LOCAL:
4218011999-01-31Fredrik Hübinette (Hubbe)  return (!n->u.integer.b && n->u.integer.a==expected) ? expected + 1 : -1;
329cc01997-02-17Fredrik Hübinette (Hubbe)  default: return -1; } }
889d232000-09-12Henrik Grubbström (Grubba) /* FIXME: Ought to use parent pointer to avoid recursion. */
9c6f7d1997-04-15Fredrik Hübinette (Hubbe) static int is_null_branch(node *n)
329cc01997-02-17Fredrik Hübinette (Hubbe) { if(!n) return 1;
aee2d32000-09-12Henrik Grubbström (Grubba)  fatal_check_c_stack(16384);
2a8cd81999-11-18Henrik Grubbström (Grubba)  if((n->token==F_CAST && n->type==void_type_string) || n->token == F_POP_VALUE)
329cc01997-02-17Fredrik Hübinette (Hubbe)  return is_null_branch(CAR(n)); if(n->token==F_ARG_LIST) return is_null_branch(CAR(n)) && is_null_branch(CDR(n)); return 0; } static struct svalue *is_stupid_func(node *n, int args,
3aa7831999-06-02Fredrik Hübinette (Hubbe)  int vargs, struct pike_string *type)
329cc01997-02-17Fredrik Hübinette (Hubbe) { node *a,*b; int tmp; while(1) { if(!n) return 0; if(n->token == F_ARG_LIST) { if(is_null_branch(CAR(n))) n=CDR(n); else n=CAR(n); continue; }
2a8cd81999-11-18Henrik Grubbström (Grubba)  if((n->token == F_CAST && n->type==void_type_string) || n->token == F_POP_VALUE)
329cc01997-02-17Fredrik Hübinette (Hubbe)  { n=CAR(n); continue; } break; }
9669e81997-02-27Fredrik Hübinette (Hubbe)  if(!n || n->token != F_RETURN) return 0;
329cc01997-02-17Fredrik Hübinette (Hubbe)  n=CAR(n);
9669e81997-02-27Fredrik Hübinette (Hubbe)  if(!n || n->token != F_APPLY) return 0;
329cc01997-02-17Fredrik Hübinette (Hubbe)  tmp=stupid_args(CDR(n),0,vargs); if(!(vargs?tmp==65535:tmp==args)) return 0; n=CAR(n);
9669e81997-02-27Fredrik Hübinette (Hubbe)  if(!n || n->token != F_CONSTANT) return 0;
a609b51998-01-28Fredrik Hübinette (Hubbe) 
3aa7831999-06-02Fredrik Hübinette (Hubbe)  if((count_arguments(n->type) < 0) == !vargs) return 0; if(minimum_arguments(type) < minimum_arguments(n->type)) return 0;
a609b51998-01-28Fredrik Hübinette (Hubbe) 
3aa7831999-06-02Fredrik Hübinette (Hubbe)  return &n->u.sval;
329cc01997-02-17Fredrik Hübinette (Hubbe) } int dooptcode(struct pike_string *name, node *n, struct pike_string *type, int modifiers) { union idptr tmp; int args, vargs, ret; struct svalue *foo;
046afe1999-11-11Henrik Grubbström (Grubba)  check_tree(check_node_hash(n),0);
3c0c281998-01-26Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(a_flag > 1)
393a592000-08-16Henrik Grubbström (Grubba)  fprintf(stderr, "Doing function '%s' at %lx\n", name->str, DO_NOT_WARN((unsigned long)PC));
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
329cc01997-02-17Fredrik Hübinette (Hubbe)  args=count_arguments(type); if(args < 0) { args=~args; vargs=IDENTIFIER_VARARGS; }else{ vargs=0; }
8322b62000-05-08Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->compiler_frame->lexical_scope & SCOPE_SCOPED)
97f6282000-03-07Fredrik Hübinette (Hubbe)  vargs|=IDENTIFIER_SCOPED;
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->compiler_frame->lexical_scope & SCOPE_SCOPE_USED)
8322b62000-05-08Fredrik Hübinette (Hubbe)  vargs|=IDENTIFIER_SCOPE_USED;
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->compiler_pass==1)
329cc01997-02-17Fredrik Hübinette (Hubbe)  {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  tmp.offset=-1;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
1b5eb41998-11-17Fredrik Hübinette (Hubbe)  if(a_flag > 4) { fprintf(stderr,"Making prototype (pass 1) for: "); print_tree(n); } #endif
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }else{
a56a1f2000-04-01Henrik Grubbström (Grubba) #if defined(SHARED_NODES) && !defined(IN_TPIKE) && 0
969a291999-11-17Henrik Grubbström (Grubba)  /* Try the local variable usage analyser. */ n = localopt(check_node_hash(n)); /* Try optimizing some more. */ optimize(n); #endif /* SHARED_NODES && !IN_TPIKE */ n = mknode(F_ARG_LIST,check_node_hash(n),0);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
046afe1999-11-11Henrik Grubbström (Grubba)  if((foo=is_stupid_func(check_node_hash(n), args, vargs, type)))
329cc01997-02-17Fredrik Hübinette (Hubbe)  {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(foo->type == T_FUNCTION && foo->subtype==FUNCTION_BUILTIN) { tmp.c_fun=foo->u.efun->function;
4879c12000-04-06Fredrik Hübinette (Hubbe)  if(tmp.c_fun != f_destruct && tmp.c_fun != f_this_object && tmp.c_fun != f_backtrace) {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
4879c12000-04-06Fredrik Hübinette (Hubbe)  if(a_flag > 1) fprintf(stderr,"%s:%d: IDENTIFIER OPTIMIZATION %s == %s\n", lex.current_file->str, lex.current_line, name->str, foo->u.efun->name->str);
1be5391998-01-29Fredrik Hübinette (Hubbe) #endif
03d1cd2000-08-27Henrik Grubbström (Grubba)  ret=define_function(name, type, modifiers, IDENTIFIER_C_FUNCTION | vargs,
1ef5572000-08-30Henrik Grubbström (Grubba)  &tmp, foo->u.efun->flags);
03d1cd2000-08-27Henrik Grubbström (Grubba)  free_node(n);
4879c12000-04-06Fredrik Hübinette (Hubbe)  return ret; }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
329cc01997-02-17Fredrik Hübinette (Hubbe)  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  tmp.offset=PC;
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->compiler_frame->num_args=args;
329cc01997-02-17Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(a_flag > 2) { fprintf(stderr,"Coding: ");
046afe1999-11-11Henrik Grubbström (Grubba)  print_tree(check_node_hash(n));
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(!Pike_compiler->num_parse_error)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  {
a7538d1998-05-12Fredrik Hübinette (Hubbe)  extern int remove_clear_locals; remove_clear_locals=args; if(vargs) remove_clear_locals++;
046afe1999-11-11Henrik Grubbström (Grubba)  do_code_block(check_node_hash(n));
a7538d1998-05-12Fredrik Hübinette (Hubbe)  remove_clear_locals=0x7fffffff;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
329cc01997-02-17Fredrik Hübinette (Hubbe)  ret=define_function(name, type, modifiers, IDENTIFIER_PIKE_FUNCTION | vargs,
1ef5572000-08-30Henrik Grubbström (Grubba)  &tmp, Pike_compiler->compiler_frame->opt_flags);
329cc01997-02-17Fredrik Hübinette (Hubbe) 
1be5391998-01-29Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
1be5391998-01-29Fredrik Hübinette (Hubbe)  if(a_flag > 1) fprintf(stderr,"Identifer = %d\n",ret); #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  free_node(n);
329cc01997-02-17Fredrik Hübinette (Hubbe)  return ret;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
66d51c1997-03-04Fredrik Hübinette (Hubbe)