pike.git / src / las.c

version» Context lines:

pike.git/src/las.c:1:   /*\   ||| This file a part of Pike, and is copyright by Fredrik Hubinette   ||| Pike is distributed as GPL (General Public License)   ||| See the files COPYING and DISCLAIMER for more information.   \*/   #include "global.h" - RCSID("$Id: las.c,v 1.39 1997/10/05 03:39:25 grubba Exp $"); + RCSID("$Id: las.c,v 1.40 1998/01/13 22:56:44 hubbe Exp $");      #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"   #include "pike_types.h"
pike.git/src/las.c:27:   #include "pike_macros.h"   #include "peep.h"      #define LASDEBUG      int lasdebug=0;      static node *eval(node *);   static void optimize(node *n);    - dynamic_buffer areas[NUM_AREAS]; +    node *init_node = 0;   int num_parse_error;   int cumulative_parse_error=0;   extern char *get_type_name(int);      #define MAX_GLOBAL 2048      int car_is_node(node *n)   {    switch(n->token)    { -  +  case F_EXTERNAL:    case F_IDENTIFIER:    case F_CONSTANT:    case F_LOCAL:    return 0;       default:    return !!CAR(n);    }   }      int cdr_is_node(node *n)   {    switch(n->token)    { -  +  case F_EXTERNAL:    case F_IDENTIFIER:    case F_CONSTANT:    case F_LOCAL:    case F_CAST:    return 0;       default:    return !!CDR(n);    }   }
pike.git/src/las.c:128:      struct node_chunk   {    struct node_chunk *next;    node nodes[NODES];   };      static struct node_chunk *node_chunks=0;   static node *free_nodes=0;    - void free_all_nodes(void) + void free_all_nodes()   { -  if(!local_variables) +  if(!compiler_frame)    {    node *tmp;    struct node_chunk *tmp2;    int e=0;          if(cumulative_parse_error)    {       for(tmp2=node_chunks;tmp2;tmp2=tmp2->next) e+=NODES;
pike.git/src/las.c:233:    node_chunks=tmp;       for(e=0;e<NODES-1;e++)    CAR(tmp->nodes+e)=tmp->nodes+e+1;    CAR(tmp->nodes+e)=0;    free_nodes=tmp->nodes;    }    res=free_nodes;    free_nodes=CAR(res);    res->token=0; -  res->line_number=current_line; +  res->line_number=lex.current_line;    res->type=0;    res->node_info=0;    res->tree_info=0;    res->parent=0;    return res;   }      node *mknode(short token,node *a,node *b)   {    node *res;
pike.git/src/las.c:266:    if(a && a->token == F_CONSTANT &&    a->u.sval.type == T_FUNCTION &&    a->u.sval.subtype == FUNCTION_BUILTIN)    {    res->node_info |= a->u.sval.u.efun->flags;    }else{    res->node_info |= OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND; /* for now */    }    break;    +  case F_UNDEFINED: +  res->node_info |= OPT_EXTERNAL_DEPEND | OPT_SIDE_EFFECT; +  break; +     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;
pike.git/src/las.c:303:    }    res->token = token;    res->type = 0;       /* We try to optimize most things, but argument lists are hard... */    if(token != F_ARG_LIST && (a || b))    res->node_info |= OPT_TRY_OPTIMIZE;       if(a) a->parent = res;    if(b) b->parent = res; -  if(!num_parse_error) optimize(res); +     -  +  if(!num_parse_error && compiler_pass==2) +  optimize(res); +    #ifdef DEBUG    if(d_flag > 3)    verify_shared_strings_tables();   #endif       return res;   }      node *mkstrnode(struct pike_string *str)   {
pike.git/src/las.c:365:   node *mkapplynode(node *func,node *args)   {    return mknode(F_APPLY, func, args);   }      node *mkefuncallnode(char *function, node *args)   {    struct pike_string *name;    node *n;    name = findstring(function); -  if(!name || !find_module_identifier(name)) +  if(!name || !(n=find_module_identifier(name)))    {    my_yyerror("Internally used efun undefined: %s",function);    return mkintnode(0);    } -  n=mkapplynode(mksvaluenode(sp-1), args); -  pop_stack(); +  n=mkapplynode(n, args);    return n;   }      node *mkopernode(char *oper_id, node *arg1, node *arg2)   {    if(arg1 && arg2)    arg1=mknode(F_ARG_LIST,arg1,arg2);       return mkefuncallnode(oper_id, arg1);   }      node *mklocalnode(int var)   {    node *res = mkemptynode();    res->token = F_LOCAL; -  copy_shared_string(res->type, local_variables->variable[var].type); +  copy_shared_string(res->type, compiler_frame->variable[var].type);    res->node_info = OPT_NOT_CONST;    res->tree_info=res->node_info;   #ifdef __CHECKER__    CDR(res)=0;   #endif    res->u.number = var;    return res;   }      node *mkidentifiernode(int i)   {    node *res = mkemptynode();    res->token = F_IDENTIFIER; -  setup_fake_program(); -  copy_shared_string(res->type, ID_FROM_INT(&fake_program, i)->type); +  copy_shared_string(res->type, ID_FROM_INT(new_program, i)->type);       /* FIXME */ -  if(IDENTIFIER_IS_CONSTANT(ID_FROM_INT(&fake_program, i)->identifier_flags)) +  if(IDENTIFIER_IS_CONSTANT(ID_FROM_INT(new_program, i)->identifier_flags))    {    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.number = i;    return res;   }    -  + node *mkexternalnode(int level, +  int i, +  struct identifier *id) + { +  node *res = mkemptynode(); +  res->token = F_EXTERNAL; +  +  copy_shared_string(res->type, id->type); +  +  /* FIXME */ +  res->node_info = OPT_NOT_CONST; +  res->tree_info=res->node_info; +  + #ifdef __CHECKER__ +  CDR(res)=0; + #endif +  res->u.integer.a = level; +  res->u.integer.b = i; +  return res; + } +    node *mkcastnode(struct pike_string *type,node *n)   {    node *res;    if(!n) return 0;    if(type==n->type) return n;    res = mkemptynode();    res->token = F_CAST;    copy_shared_string(res->type,type);       if(match_types(object_type_string, type) ||
pike.git/src/las.c:444: Inside #if defined(__CHECKER__)
  #ifdef __CHECKER__    CDR(res)=0;   #endif    n->parent=res;    return res;   }      void resolv_constant(node *n)   {    struct identifier *i; +  struct program *p; +  INT32 numid; +     if(!n)    {    push_int(0);    }else{    switch(n->token)    {    case F_CONSTANT:    push_svalue(& n->u.sval); -  break; +  return;    -  case F_IDENTIFIER: -  setup_fake_program(); -  i=ID_FROM_INT(& fake_program, n->u.number); -  -  if(IDENTIFIER_IS_CONSTANT(i->identifier_flags)) +  case F_EXTERNAL: +  p=parent_compilation(n->u.integer.a); +  if(!p)    { -  push_svalue(PROG_FROM_INT(&fake_program, n->u.number)->constants + -  i->func.offset); -  }else{ -  yyerror("Identifier is not a constant"); +  yyerror("Failed to resolv external constant");    push_int(0); -  +  return;    } -  +  numid=n->u.integer.b;    break;    -  +  case F_IDENTIFIER: +  p=new_program; +  numid=n->u.number; +  break; +     case F_LOCAL:    yyerror("Expected constant, got local variable");    push_int(0); -  break; +  return;       case F_GLOBAL:    yyerror("Expected constant, got global variable");    push_int(0); -  break; +  return; +  +  default: +  yyerror("Expected constant, got something else"); +  push_int(0); +  return;    } -  +  +  i=ID_FROM_INT(p, numid); +  +  if(IDENTIFIER_IS_CONSTANT(i->identifier_flags)) +  { +  push_svalue(PROG_FROM_INT(new_program, numid)->constants + +  i->func.offset); +  }else{ +  yyerror("Identifier is not a constant"); +  push_int(0);    }    } -  + }      node *index_node(node *n, struct pike_string * id)   {    node *ret;    JMP_BUF tmp;    if(SETJMP(tmp))    {    ONERROR tmp;    SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!");    assign_svalue_no_free(sp++, & throw_value);
pike.git/src/las.c:791:    low_print_tree(CAR(foo),0);    printf(")?(");    low_print_tree(CADR(foo),0);    printf("):(");    low_print_tree(CDDR(foo),0);    printf(")");    break;       case F_IDENTIFIER:    if(needlval) putchar('&'); -  setup_fake_program(); -  printf("%s",ID_FROM_INT(&fake_program, foo->u.number)->name->str); +  printf("%s",ID_FROM_INT(new_program, foo->u.number)->name->str);    break;       case F_ASSIGN:    low_print_tree(CDR(foo),1);    printf("=");    low_print_tree(CAR(foo),0);    break;       case F_CAST:    {
pike.git/src/las.c:1228:    f=CAR(n)->type?CAR(n)->type:mixed_type_string;    n->type=check_call(s,f);       if(!n->type)    {    char *name;    int args;    switch(CAR(n)->token)    {    case F_IDENTIFIER: -  setup_fake_program(); -  name=ID_FROM_INT(&fake_program, CAR(n)->u.number)->name->str; +  name=ID_FROM_INT(new_program, CAR(n)->u.number)->name->str;    break;       case F_CONSTANT:    default:    name="`() (function call)";    }       if(max_correct_args == count_arguments(s))    {    my_yyerror("To few arguments to %s.\n",name);
pike.git/src/las.c:1274:    }       copy_shared_string(n->type,mixed_type_string);    break;       case F_RETURN:    if(CAR(n)->type == void_type_string)    {    yyerror("You cannot return a void expression");    } -  if(local_variables && -  local_variables->current_return_type && -  !match_types(local_variables->current_return_type,CAR(n)->type) && +  if(compiler_frame && +  compiler_frame->current_return_type && +  !match_types(compiler_frame->current_return_type,CAR(n)->type) &&    !( -  local_variables->current_return_type==void_type_string && +  compiler_frame->current_return_type==void_type_string &&    CAR(n)->token == F_CONSTANT &&    IS_ZERO(& CAR(n)->u.sval)    )    )    {    yyerror("Wrong return type.");    }       /* Fall through */   
pike.git/src/las.c:1357:    if(!n) return;    n->node_info &=~ OPT_TRY_OPTIMIZE;    n->tree_info &=~ OPT_TRY_OPTIMIZE;    if(car_is_node(n)) zapp_try_optimize(CAR(n));    if(cdr_is_node(n)) zapp_try_optimize(CDR(n));   }      static void optimize(node *n)   {    node *tmp1, *tmp2, *tmp3; -  INT32 save_line = current_line; +  INT32 save_line = lex.current_line;    do    {    if(car_is_node(n) && !(CAR(n)->node_info & OPT_OPTIMIZED))    {    n=CAR(n);    continue;    }    if(cdr_is_node(n) && !(CDR(n)->node_info & OPT_OPTIMIZED))    {    n=CDR(n);    continue;    } -  current_line = n->line_number; +  lex.current_line = n->line_number;          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;       if(!n->parent) break;       if(n->tree_info & (OPT_NOT_CONST|    OPT_SIDE_EFFECT|
pike.git/src/las.c:1800: Inside #if defined(DEBUG)
   fprintf(stderr,"Result: ");    print_tree(n);    }   #endif    continue;       }    n->node_info |= OPT_OPTIMIZED;    n=n->parent;    }while(n); -  current_line = save_line; +  lex.current_line = save_line;   }      struct timer_oflo   {    INT32 counter;    int yes;   };      static void check_evaluation_time(struct callback *cb,void *tmp,void *ignored)   {
pike.git/src/las.c:1835: Inside #if defined(DEBUG)
     #ifdef DEBUG    if(l_flag > 3 && n)    {    fprintf(stderr,"Evaluating (tree info=%x):",n->tree_info);    print_tree(n);    }   #endif       if(num_parse_error) return -1; -  setup_fake_program(); +     -  num_strings=fake_program.num_strings; -  num_constants=fake_program.num_constants; +  num_strings=new_program->num_strings; +  num_constants=new_program->num_constants;    jump=PC;       store_linenumbers=0;    docode(n);    ins_f_byte(F_DUMB_RETURN);    store_linenumbers=1;    -  setup_fake_program(); +     ret=-1;    if(!num_parse_error)    {    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;   
pike.git/src/las.c:1889:    }else{    if(foo.yes)    pop_n_elems(sp-save_sp);    else    ret=sp-save_sp;    }       remove_callback(tmp_callback);    }    -  while(fake_program.num_strings > num_strings) +  while(new_program->num_strings > num_strings)    { -  fake_program.num_strings--; -  free_string(fake_program.strings[fake_program.num_strings]); -  areas[A_STRINGS].s.len-=sizeof(struct pike_string *); +  new_program->num_strings--; +  free_string(new_program->strings[new_program->num_strings]);    }    -  while(fake_program.num_constants > num_constants) +  while(new_program->num_constants > num_constants)    { -  fake_program.num_constants--; -  free_svalue(fake_program.constants + fake_program.num_constants); -  areas[A_CONSTANTS].s.len-=sizeof(struct svalue); +  new_program->num_constants--; +  free_svalue(new_program->constants + new_program->num_constants);    }    -  areas[A_PROGRAM].s.len=jump; +  new_program->num_program=jump;       return ret;   }      static node *eval(node *n)   {    int args;    extern struct svalue *sp;    if(!is_const(n) || n->token==':')    return n;
pike.git/src/las.c:2030:   int dooptcode(struct pike_string *name,    node *n,    struct pike_string *type,    int modifiers)   {    union idptr tmp;    int args, vargs, ret;    struct svalue *foo;      #ifdef DEBUG -  if(recoveries && sp-evaluator_stack < recoveries->sp) -  fatal("Stack error before dooptcode (underflow)\n"); - #endif -  - #ifdef DEBUG +     if(a_flag > 1)    fprintf(stderr,"Doing function '%s' at %x\n",name->str,PC);   #endif -  last_function_opt_info=OPT_SIDE_EFFECT; +        args=count_arguments(type);    if(args < 0)    {    args=~args;    vargs=IDENTIFIER_VARARGS;    }else{    vargs=0;    } -  +  if(compiler_pass==1) +  { +  tmp.offset=-1; +  }else{    n=mknode(F_ARG_LIST,n,0);       if((foo=is_stupid_func(n, args, vargs)))    {    if(foo->type == T_FUNCTION && foo->subtype==FUNCTION_BUILTIN)    {    tmp.c_fun=foo->u.efun->function;    ret=define_function(name,    type,    modifiers,    IDENTIFIER_C_FUNCTION | vargs,    &tmp);    free_node(n);    return ret;    }    }       tmp.offset=PC; -  ins_byte(local_variables->max_number_of_locals, A_PROGRAM); -  ins_byte(args, A_PROGRAM); +  add_to_program(compiler_frame->max_number_of_locals); +  add_to_program(args);      #ifdef DEBUG    if(a_flag > 2)    {    fprintf(stderr,"Coding: ");    print_tree(n);    }   #endif    if(!num_parse_error)    {    do_code_block(n);    } -  +  }    - #ifdef DEBUG -  if(recoveries && sp-evaluator_stack < recoveries->sp) -  fatal("Stack error after do_code_block (underflow)\n"); - #endif -  +     ret=define_function(name,    type,    modifiers,    IDENTIFIER_PIKE_FUNCTION | vargs,    &tmp);       free_node(n);    return ret;   }    - INT32 get_opt_info(void) { return last_function_opt_info; } +     -  +