cb2256 | 1995-10-11 | Fredrik Hübinette (Hubbe) | | |
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | ||| This file a part of Pike, and is copyright by Fredrik Hubinette
||| Pike is distributed as GPL (General Public License)
|
cb2256 | 1995-10-11 | Fredrik Hübinette (Hubbe) | | ||| See the files COPYING and DISCLAIMER for more information.
\*/
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | #include "global.h"
|
a1d9c1 | 1997-02-27 | Fredrik Hübinette (Hubbe) | | RCSID("$Id: las.c,v 1.27 1997/02/27 11:23:22 hubbe Exp $");
|
419ede | 1996-11-13 | Fredrik Hübinette (Hubbe) | |
|
5267b7 | 1995-08-09 | Fredrik 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"
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | #include "pike_types.h"
#include "constants.h"
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | #include "mapping.h"
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | #include "multiset.h"
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | #include "error.h"
#include "docode.h"
#include "main.h"
|
2a5096 | 1995-08-23 | Fredrik Hübinette (Hubbe) | | #include "memory.h"
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | #include "operators.h"
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | | #include "callback.h"
|
a8ef6e | 1996-12-03 | Fredrik Hübinette (Hubbe) | | #include "macros.h"
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
#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;
|
c3c703 | 1996-12-04 | Fredrik Hübinette (Hubbe) | | int cumulative_parse_error=0;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | extern char *get_type_name(int);
|
e82b30 | 1997-01-29 | Fredrik Hübinette (Hubbe) | | #define MAX_GLOBAL 2048
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
int car_is_node(node *n)
{
switch(n->token)
{
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_IDENTIFIER:
case F_CONSTANT:
case F_LOCAL:
case F_CAST:
return 0;
default:
return !!CDR(n);
}
}
INT32 count_args(node *n)
{
|
7bd0ea | 1996-02-19 | Fredrik Hübinette (Hubbe) | | int a,b;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | if(!n) return 0;
switch(n->token)
{
case F_VAL_LVAL:
case F_ARG_LIST:
|
7bd0ea | 1996-02-19 | Fredrik 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;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
case F_CAST:
if(n->type == void_type_string)
return 0;
else
return count_args(CAR(n));
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;
|
e26068 | 1996-04-11 | Fredrik Hübinette (Hubbe) | | tmp1=count_args(CADR(n));
tmp2=count_args(CDDR(n));
|
7bd0ea | 1996-02-19 | Fredrik Hübinette (Hubbe) | | if(tmp1==-1 || tmp2==-2) return -1;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | if(tmp1 < tmp2) return tmp1;
return tmp2;
}
|
b95bef | 1996-03-29 | Fredrik Hübinette (Hubbe) | | case F_PUSH_ARRAY:
return -1;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | default:
if(n->type == void_type_string) return 0;
return 1;
}
}
|
a8ef6e | 1996-12-03 | Fredrik Hübinette (Hubbe) | |
#define NODES 256
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()
{
if(!local_variables)
{
node *tmp;
struct node_chunk *tmp2;
int e=0;
|
c3c703 | 1996-12-04 | Fredrik Hübinette (Hubbe) | |
if(cumulative_parse_error)
|
a8ef6e | 1996-12-03 | Fredrik Hübinette (Hubbe) | | {
|
c3c703 | 1996-12-04 | Fredrik Hübinette (Hubbe) | |
for(tmp2=node_chunks;tmp2;tmp2=tmp2->next) e+=NODES;
for(tmp=free_nodes;tmp;tmp=CAR(tmp)) e--;
if(e)
|
a8ef6e | 1996-12-03 | Fredrik Hübinette (Hubbe) | | {
|
c3c703 | 1996-12-04 | Fredrik Hübinette (Hubbe) | | int e2=e;
for(tmp2=node_chunks;tmp2;tmp2=tmp2->next)
|
a8ef6e | 1996-12-03 | Fredrik Hübinette (Hubbe) | | {
|
c3c703 | 1996-12-04 | Fredrik Hübinette (Hubbe) | | for(e=0;e<NODES;e++)
{
for(tmp=free_nodes;tmp;tmp=CAR(tmp))
if(tmp==tmp2->nodes+e)
break;
if(!tmp)
{
tmp=tmp2->nodes+e;
#ifdef DEBUG
if(!cumulative_parse_error)
{
fprintf(stderr,"Free node at %p.\n",tmp);
}
else
#endif
{
if(car_is_node(tmp)) CAR(tmp)=0;
if(cdr_is_node(tmp)) CDR(tmp)=0;
free_node(tmp);
}
}
}
|
a8ef6e | 1996-12-03 | Fredrik Hübinette (Hubbe) | | }
|
c3c703 | 1996-12-04 | Fredrik Hübinette (Hubbe) | | #ifdef DEBUG
if(!cumulative_parse_error)
fatal("Failed to free %d nodes when compiling!\n",e2);
#endif
|
a8ef6e | 1996-12-03 | Fredrik Hübinette (Hubbe) | | }
}
while(node_chunks)
{
tmp2=node_chunks;
node_chunks=tmp2->next;
free((char *)tmp2);
}
free_nodes=0;
|
c3c703 | 1996-12-04 | Fredrik Hübinette (Hubbe) | | cumulative_parse_error=0;
|
a8ef6e | 1996-12-03 | Fredrik Hübinette (Hubbe) | | }
}
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | void free_node(node *n)
{
if(!n) return;
switch(n->token)
{
|
a8ef6e | 1996-12-03 | Fredrik Hübinette (Hubbe) | | case USHRT_MAX:
fatal("Freeing node again!\n");
break;
|
5267b7 | 1995-08-09 | Fredrik 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));
}
|
a8ef6e | 1996-12-03 | Fredrik Hübinette (Hubbe) | | n->token=USHRT_MAX;
if(n->type) free_string(n->type);
CAR(n)=free_nodes;
free_nodes=n;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | }
static node *mkemptynode()
{
node *res;
|
a8ef6e | 1996-12-03 | Fredrik Hübinette (Hubbe) | | if(!free_nodes)
{
int e;
struct node_chunk *tmp=ALLOC_STRUCT(node_chunk);
tmp->next=node_chunks;
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;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | res->line_number=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;
res = mkemptynode();
CAR(res) = a;
CDR(res) = b;
res->node_info = 0;
res->tree_info = 0;
switch(token)
{
case F_CATCH:
res->node_info |= OPT_SIDE_EFFECT;
break;
case F_APPLY:
|
d33477 | 1996-04-13 | Fredrik Hübinette (Hubbe) | | if(a && a->token == F_CONSTANT &&
a->u.sval.type == T_FUNCTION &&
|
bdb509 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | a->u.sval.subtype == FUNCTION_BUILTIN)
|
e26068 | 1996-04-11 | Fredrik Hübinette (Hubbe) | | {
res->node_info |= a->u.sval.u.efun->flags;
}else{
res->node_info |= OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND;
}
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | 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;
break;
case F_DEFAULT:
case F_CASE:
res->node_info |= OPT_CASE;
break;
case F_SSCANF:
if(!b || count_args(b) == 0) break;
case F_ASSIGN:
case F_INC:
case F_DEC:
case F_POST_INC:
case F_POST_DEC:
res->node_info |= OPT_ASSIGNMENT;
}
res->token = token;
res->type = 0;
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);
return res;
}
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | node *mkstrnode(struct pike_string *str)
|
5267b7 | 1995-08-09 | Fredrik 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);
return res;
}
node *mkintnode(int nr)
{
node *res = mkemptynode();
res->token = F_CONSTANT;
if(nr)
copy_shared_string(res->type, int_type_string);
else
copy_shared_string(res->type, mixed_type_string);
res->node_info = 0;
res->u.sval.type = T_INT;
res->u.sval.subtype = NUMBER_NUMBER;
res->u.sval.u.integer = nr;
return res;
}
node *mkfloatnode(FLOAT_TYPE foo)
{
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;
return res;
}
node *mkapplynode(node *func,node *args)
{
return mknode(F_APPLY, func, args);
}
node *mkefuncallnode(char *function, node *args)
{
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *name;
|
45e8a8 | 1997-01-26 | Fredrik Hübinette (Hubbe) | | node *n;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | name = findstring(function);
|
45e8a8 | 1997-01-26 | Fredrik Hübinette (Hubbe) | | if(!name || !find_module_identifier(name))
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
my_yyerror("Internally used efun undefined: %s",function);
return mkintnode(0);
}
|
45e8a8 | 1997-01-26 | Fredrik Hübinette (Hubbe) | | n=mkapplynode(mksvaluenode(sp-1), args);
pop_stack();
return n;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | }
|
7bd0ea | 1996-02-19 | Fredrik Hübinette (Hubbe) | | node *mkopernode(char *oper_id, node *arg1, node *arg2)
{
if(arg1 && arg2)
arg1=mknode(F_ARG_LIST,arg1,arg2);
return mkefuncallnode(oper_id, arg1);
}
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | node *mklocalnode(int var)
{
node *res = mkemptynode();
res->token = F_LOCAL;
copy_shared_string(res->type, local_variables->variable[var].type);
res->node_info = OPT_NOT_CONST;
#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);
|
3856c3 | 1996-11-25 | Fredrik Hübinette (Hubbe) | | if(IDENTIFIER_IS_CONSTANT(ID_FROM_INT(&fake_program, i)->flags))
{
res->node_info = OPT_EXTERNAL_DEPEND;
}else{
res->node_info = OPT_NOT_CONST;
}
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
#ifdef __CHECKER__
CDR(res)=0;
#endif
res->u.number = i;
return res;
}
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | node *mkcastnode(struct pike_string *type,node *n)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
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) ||
match_types(object_type_string, type))
res->node_info |= OPT_SIDE_EFFECT;
CAR(res) = n;
#ifdef __CHECKER__
CDR(res)=0;
#endif
n->parent=res;
return res;
}
|
591c0c | 1997-01-19 | Fredrik Hübinette (Hubbe) | | void resolv_constant(node *n)
{
struct identifier *i;
if(!n)
{
push_int(0);
}else{
switch(n->token)
{
case F_CONSTANT:
push_svalue(& n->u.sval);
break;
case F_IDENTIFIER:
setup_fake_program();
i=ID_FROM_INT(& fake_program, n->u.number);
if(IDENTIFIER_IS_CONSTANT(i->flags))
{
push_svalue(PROG_FROM_INT(&fake_program, n->u.number)->constants +
i->func.offset);
}else{
yyerror("Identifier is not a constant");
push_int(0);
}
break;
case F_LOCAL:
yyerror("Expected constant, got local variable");
push_int(0);
|
05533f | 1997-02-06 | Fredrik Hübinette (Hubbe) | | break;
|
591c0c | 1997-01-19 | Fredrik Hübinette (Hubbe) | |
case F_GLOBAL:
yyerror("Expected constant, got global variable");
push_int(0);
|
05533f | 1997-02-06 | Fredrik Hübinette (Hubbe) | | break;
|
591c0c | 1997-01-19 | Fredrik Hübinette (Hubbe) | | }
}
}
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);
APPLY_MASTER("handle_error", 1);
pop_stack();
UNSET_ONERROR(tmp);
yyerror("Couldn't index module.");
|
05533f | 1997-02-06 | Fredrik Hübinette (Hubbe) | | push_int(0);
|
591c0c | 1997-01-19 | Fredrik Hübinette (Hubbe) | | }else{
resolv_constant(n);
|
1470d8 | 1997-02-27 | Fredrik Hübinette (Hubbe) | | switch(sp[-1].type)
|
d6aef2 | 1997-02-27 | Fredrik Hübinette (Hubbe) | | {
|
1470d8 | 1997-02-27 | Fredrik Hübinette (Hubbe) | | case T_INT:
|
d6aef2 | 1997-02-27 | Fredrik Hübinette (Hubbe) | | yyerror("Failed to index module (module doesn't exist?)");
|
1470d8 | 1997-02-27 | Fredrik Hübinette (Hubbe) | | break;
case T_PROGRAM:
case T_FLOAT:
case T_STRING:
case T_ARRAY:
yyerror("Failed to index module (Not a module?)");
break;
default:
|
d6aef2 | 1997-02-27 | Fredrik Hübinette (Hubbe) | | push_string(id);
reference_shared_string(id);
f_index(2);
|
748520 | 1997-02-27 | Fredrik Hübinette (Hubbe) | |
if(sp[-1].type == T_INT &&
|
a1d9c1 | 1997-02-27 | Fredrik Hübinette (Hubbe) | | !sp[-1].u.integer &&
|
57db8d | 1997-02-27 | Fredrik Hübinette (Hubbe) | | sp[-1].subtype==NUMBER_UNDEFINED)
|
748520 | 1997-02-27 | Fredrik Hübinette (Hubbe) | | {
|
57db8d | 1997-02-27 | Fredrik Hübinette (Hubbe) | | my_yyerror("Index '%s' not present in module.",id->str);
|
748520 | 1997-02-27 | Fredrik Hübinette (Hubbe) | | }
|
d6aef2 | 1997-02-27 | Fredrik Hübinette (Hubbe) | | }
|
591c0c | 1997-01-19 | Fredrik Hübinette (Hubbe) | | }
UNSETJMP(tmp);
ret=mkconstantsvaluenode(sp-1);
pop_stack();
return ret;
}
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | int node_is_eq(node *a,node *b)
{
if(a == b) return 1;
if(!a || !b) return 0;
if(a->token != b->token) return 0;
switch(a->token)
{
case F_LOCAL:
|
afa365 | 1996-02-10 | Fredrik Hübinette (Hubbe) | | case F_IDENTIFIER:
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | return a->u.number == b->u.number;
case F_CAST:
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;
}
}
node *mkconstantsvaluenode(struct svalue *s)
{
node *res = mkemptynode();
res->token = F_CONSTANT;
assign_svalue_no_free(& res->u.sval, s);
|
e82b30 | 1997-01-29 | Fredrik Hübinette (Hubbe) | | if(s->type == T_OBJECT || (s->type==T_FUNCTION && s->subtype!=FUNCTION_BUILTIN))
{
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | res->node_info|=OPT_EXTERNAL_DEPEND;
|
e82b30 | 1997-01-29 | Fredrik Hübinette (Hubbe) | | }
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | res->type = get_type_of_svalue(s);
return res;
}
|
5683de | 1995-11-06 | Fredrik Hübinette (Hubbe) | | node *mkliteralsvaluenode(struct svalue *s)
{
node *res = mkconstantsvaluenode(s);
if(s->type!=T_STRING && s->type!=T_INT && s->type!=T_FLOAT)
res->node_info|=OPT_EXTERNAL_DEPEND;
return res;
}
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | node *mksvaluenode(struct svalue *s)
{
switch(s->type)
{
case T_ARRAY:
return make_node_from_array(s->u.array);
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | case T_MULTISET:
return make_node_from_multiset(s->u.multiset);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
case T_MAPPING:
return make_node_from_mapping(s->u.mapping);
case T_OBJECT:
if(s->u.object == &fake_object)
{
return mkefuncallnode("this_object", 0);
}
break;
case T_FUNCTION:
{
|
bdb509 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | if(s->subtype != FUNCTION_BUILTIN)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
if(s->u.object == &fake_object)
return mkidentifiernode(s->subtype);
}
}
}
return mkconstantsvaluenode(s);
}
node *copy_node(node *n)
{
node *b;
if(!n) return n;
switch(n->token)
{
case F_LOCAL:
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | case F_IDENTIFIER:
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | b=mkintnode(0);
*b=*n;
copy_shared_string(b->type, n->type);
return b;
case F_CAST:
b=mkcastnode(n->type,copy_node(CAR(n)));
break;
case F_CONSTANT:
b=mksvaluenode(&(n->u.sval));
break;
default:
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;
}
b->line_number = n->line_number;
b->node_info = n->node_info;
b->tree_info = n->tree_info;
return b;
}
int is_const(node *n)
{
|
05533f | 1997-02-06 | Fredrik Hübinette (Hubbe) | | if(!n) return 1;
|
5267b7 | 1995-08-09 | Fredrik 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
));
}
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;
}
}
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;
}
}
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | node **last_cmd(node **a)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
node **n;
if(!a || !*a) return (node **)NULL;
if((*a)->token == F_CAST) return last_cmd(&CAR(*a));
if((*a)->token != F_ARG_LIST) return a;
if(CDR(*a))
{
if(CDR(*a)->token != F_CAST && CAR(*a)->token != F_ARG_LIST)
return &CDR(*a);
if((n=last_cmd(&CDR(*a))))
return n;
}
if(CAR(*a))
{
if(CAR(*a)->token != F_CAST && CAR(*a)->token != F_ARG_LIST)
return &CAR(*a);
if((n=last_cmd(&CAR(*a))))
return n;
}
return 0;
}
static node **low_get_arg(node **a,int *nr)
{
node **n;
if(a[0]->token != F_ARG_LIST)
{
if(!(*nr)--)
return a;
else
return NULL;
}
if(CAR(*a))
if((n=low_get_arg(&CAR(*a),nr)))
return n;
if(CDR(*a))
if((n=low_get_arg(&CDR(*a),nr)))
return n;
return 0;
}
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | node **my_get_arg(node **a,int n) { return low_get_arg(a,&n); }
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
static void low_print_tree(node *foo,int needlval)
{
if(!foo) return;
switch(foo->token)
{
case F_LOCAL:
if(needlval) putchar('&');
printf("$%ld",(long)foo->u.number);
break;
case '?':
printf("(");
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);
break;
case F_ASSIGN:
low_print_tree(CDR(foo),1);
printf("=");
low_print_tree(CAR(foo),0);
break;
case F_CAST:
{
char *s;
init_buf();
low_describe_type(foo->type->str);
s=simple_free_buf();
printf("(%s){",s);
free(s);
low_print_tree(CAR(foo),0);
printf("}");
break;
}
case F_ARG_LIST:
low_print_tree(CAR(foo),0);
if(CAR(foo) && CDR(foo))
{
if(CAR(foo)->type == void_type_string &&
CDR(foo)->type == void_type_string)
printf(";\n");
else
putchar(',');
}
low_print_tree(CDR(foo),needlval);
return;
case F_LVALUE_LIST:
low_print_tree(CAR(foo),1);
if(CAR(foo) && CDR(foo)) putchar(',');
low_print_tree(CDR(foo),1);
return;
case F_CONSTANT:
{
char *s;
init_buf();
describe_svalue(& foo->u.sval, 0, 0);
s=simple_free_buf();
printf("%s",s);
free(s);
break;
}
case F_VAL_LVAL:
low_print_tree(CAR(foo),0);
printf(",&");
low_print_tree(CDR(foo),0);
return;
case F_APPLY:
low_print_tree(CAR(foo),0);
printf("(");
low_print_tree(CDR(foo),0);
printf(")");
return;
default:
if(!car_is_node(foo) && !cdr_is_node(foo))
{
|
0d202a | 1995-10-20 | Fredrik Hübinette (Hubbe) | | printf("%s",get_token_name(foo->token));
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | return;
}
if(foo->token<256)
{
printf("%c(",foo->token);
}else{
|
0d202a | 1995-10-20 | Fredrik Hübinette (Hubbe) | | printf("%s(",get_token_name(foo->token));
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | }
if(car_is_node(foo)) low_print_tree(CAR(foo),0);
if(car_is_node(foo) && cdr_is_node(foo))
putchar(',');
if(cdr_is_node(foo)) low_print_tree(CDR(foo),0);
printf(")");
return;
}
}
void print_tree(node *n)
{
low_print_tree(n,0);
printf("\n");
fflush(stdout);
}
struct used_vars
{
|
e82b30 | 1997-01-29 | Fredrik Hübinette (Hubbe) | | int err;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | char locals[MAX_LOCAL];
char globals[MAX_GLOBAL];
};
#define VAR_BLOCKED 0
#define VAR_UNUSED 1
#define VAR_USED 3
static void do_and_vars(struct used_vars *a,struct used_vars *b)
{
int e;
for(e=0;e<MAX_LOCAL;e++) a->locals[e]|=b->locals[e];
for(e=0;e<MAX_GLOBAL;e++) a->globals[e]|=b->globals[e];
|
e82b30 | 1997-01-29 | Fredrik Hübinette (Hubbe) | | a->err|=b->err;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | free((char *)b);
}
static struct used_vars *copy_vars(struct used_vars *a)
{
struct used_vars *ret;
ret=(struct used_vars *)xalloc(sizeof(struct used_vars));
MEMCPY((char *)ret,(char *)a,sizeof(struct used_vars));
return ret;
}
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;
switch(n->token)
{
case F_LOCAL:
q=p->locals+n->u.number;
goto set_pointer;
case F_IDENTIFIER:
q=p->globals+n->u.number;
|
e82b30 | 1997-01-29 | Fredrik Hübinette (Hubbe) | | if(n->u.number > MAX_GLOBAL)
{
p->err=1;
return 0;
}
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
set_pointer:
if(overwrite)
{
if(*q == VAR_UNUSED && !noblock) *q = VAR_BLOCKED;
}
else
{
|
e82b30 | 1997-01-29 | Fredrik Hübinette (Hubbe) | | if(*q == VAR_UNUSED) *q = VAR_USED;
|
5267b7 | 1995-08-09 | Fredrik 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);
do_and_vars(p,a);
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);
do_and_vars(p,a);
break;
case F_SWITCH:
find_used_variables(CAR(n),p,noblock,0);
a=copy_vars(p);
find_used_variables(CDR(n),a,1,0);
do_and_vars(p,a);
break;
case F_DO:
a=copy_vars(p);
find_used_variables(CAR(n),a,noblock,0);
do_and_vars(p,a);
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;
}
static void find_written_vars(node *n,
struct used_vars *p,
int lvalue)
{
if(!n) return;
switch(n->token)
{
case F_LOCAL:
if(lvalue) p->locals[n->u.number]=VAR_USED;
break;
case F_GLOBAL:
|
e82b30 | 1997-01-29 | Fredrik Hübinette (Hubbe) | | if(lvalue)
{
if(n->u.number>=MAX_GLOBAL)
{
p->err=1;
return;
}
p->globals[n->u.number]=VAR_USED;
}
break;
case F_APPLY:
if(n->tree_info & OPT_SIDE_EFFECT)
|
49e54b | 1997-02-10 | Fredrik Hübinette (Hubbe) | | MEMSET(p->globals, VAR_USED, MAX_GLOBAL);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | break;
case F_INDEX:
|
dffa01 | 1997-01-15 | Fredrik Hübinette (Hubbe) | | case F_ARROW:
|
5267b7 | 1995-08-09 | Fredrik 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;
case F_SSCANF:
find_written_vars(CAR(n), p, 0);
find_written_vars(CDR(n), p, 1);
break;
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);
}
}
static int depend_p2(node *a,node *b)
{
struct used_vars aa,bb;
int e;
if(!a || !b || is_const(a)) return 0;
|
3b79fa | 1997-02-10 | Fredrik Hübinette (Hubbe) | | aa.err=0;
bb.err=0;
|
49e54b | 1997-02-10 | Fredrik Hübinette (Hubbe) | | MEMSET((char *)aa.locals, VAR_UNUSED, MAX_LOCAL);
MEMSET((char *)bb.locals, VAR_UNUSED, MAX_LOCAL);
MEMSET((char *)aa.globals, VAR_UNUSED, MAX_GLOBAL);
MEMSET((char *)bb.globals, VAR_UNUSED, MAX_GLOBAL);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
find_used_variables(a,&aa,0,0);
find_written_vars(b,&bb,0);
|
e82b30 | 1997-01-29 | Fredrik Hübinette (Hubbe) | | if(aa.err || bb.err) return 1;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | for(e=0;e<MAX_LOCAL;e++)
if(aa.locals[e]==VAR_USED && bb.locals[e]!=VAR_UNUSED)
return 1;
for(e=0;e<MAX_GLOBAL;e++)
if(aa.globals[e]==VAR_USED && bb.globals[e]!=VAR_UNUSED)
return 1;
return 0;
}
static int depend_p(node *a,node *b)
{
if(!b) return 0;
|
e82b30 | 1997-01-29 | Fredrik Hübinette (Hubbe) | | #if 0
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | if(!(b->tree_info & OPT_SIDE_EFFECT) &&
(b->tree_info & OPT_EXTERNAL_DEPEND))
return 1;
|
e82b30 | 1997-01-29 | Fredrik Hübinette (Hubbe) | | #endif
if((a->tree_info & OPT_EXTERNAL_DEPEND)) return 1;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
return depend_p2(a,b);
}
static int cntargs(node *n)
{
if(!n) return 0;
switch(n->token)
{
case F_CAST:
case F_APPLY:
return n->type != void_type_string;
case F_FOREACH:
case F_INC_NEQ_LOOP:
case F_DEC_NEQ_LOOP:
case F_INC_LOOP:
case F_DEC_LOOP: return 0;
case F_VAL_LVAL:
case F_LVALUE_LIST:
case F_ARG_LIST:
return cntargs(CAR(n))+cntargs(CDR(n));
default: return 1;
}
}
static void low_build_function_type(node *n)
{
if(!n) return;
switch(n->token)
{
case F_ARG_LIST:
low_build_function_type(CDR(n));
low_build_function_type(CAR(n));
break;
case F_PUSH_ARRAY:
reset_type_stack();
|
0d202a | 1995-10-20 | Fredrik Hübinette (Hubbe) | | push_type(T_MIXED);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | push_type(T_MIXED);
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);
}
}
}
void fix_type_field(node *n)
{
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *type_a,*type_b;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
if(n->type) return;
switch(n->token)
{
|
cb2256 | 1995-10-11 | Fredrik Hübinette (Hubbe) | | case F_LAND:
case F_LOR:
if(!match_types(CAR(n)->type,mixed_type_string))
yyerror("Bad conditional expression.\n");
if(!match_types(CDR(n)->type,mixed_type_string))
yyerror("Bad conditional expression.\n");
if(CAR(n)->type == CDR(n)->type)
{
copy_shared_string(n->type,CAR(n)->type);
}else{
copy_shared_string(n->type,mixed_type_string);
}
break;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
|
da55f9 | 1996-05-03 | Fredrik Hübinette (Hubbe) | | case F_ASSIGN:
if(CAR(n) && CDR(n) &&
!match_types(CDR(n)->type,CAR(n)->type))
|
3856c3 | 1996-11-25 | Fredrik Hübinette (Hubbe) | | my_yyerror("Bad type in assignment.");
|
d8632c | 1996-05-04 | Fredrik Hübinette (Hubbe) | | copy_shared_string(n->type, CDR(n)->type);
|
da55f9 | 1996-05-03 | Fredrik Hübinette (Hubbe) | | break;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | case F_INDEX:
|
b8cda2 | 1997-01-21 | Fredrik Hübinette (Hubbe) | | type_a=CAR(n)->type;
type_b=CDR(n)->type;
if(!check_indexing(type_a, type_b, n))
my_yyerror("Indexing on illegal type.");
n->type=index_type(type_a,n);
break;
|
dffa01 | 1997-01-15 | Fredrik Hübinette (Hubbe) | | case F_ARROW:
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | type_a=CAR(n)->type;
type_b=CDR(n)->type;
|
b8cda2 | 1997-01-21 | Fredrik Hübinette (Hubbe) | | if(!check_indexing(type_a, type_b, n))
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | my_yyerror("Indexing on illegal type.");
|
b8cda2 | 1997-01-21 | Fredrik Hübinette (Hubbe) | | n->type=index_type(type_a,n);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | break;
case F_APPLY:
{
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *s;
|
b8cda2 | 1997-01-21 | Fredrik Hübinette (Hubbe) | | struct pike_string *f;
|
0d202a | 1995-10-20 | Fredrik Hübinette (Hubbe) | | push_type(T_MIXED);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | push_type(T_VOID);
push_type(T_MANY);
low_build_function_type(CDR(n));
push_type(T_FUNCTION);
s=pop_type();
|
b8cda2 | 1997-01-21 | Fredrik Hübinette (Hubbe) | | f=CAR(n)->type?CAR(n)->type:mixed_type_string;
n->type=check_call(s,f);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
if(!n->type)
{
|
b8cda2 | 1997-01-21 | Fredrik Hübinette (Hubbe) | | char *name;
int args;
|
3856c3 | 1996-11-25 | Fredrik Hübinette (Hubbe) | | switch(CAR(n)->token)
{
case F_IDENTIFIER:
setup_fake_program();
|
b8cda2 | 1997-01-21 | Fredrik Hübinette (Hubbe) | | name=ID_FROM_INT(&fake_program, CAR(n)->u.number)->name->str;
|
3856c3 | 1996-11-25 | Fredrik Hübinette (Hubbe) | | break;
|
b8cda2 | 1997-01-21 | Fredrik Hübinette (Hubbe) | |
|
3856c3 | 1996-11-25 | Fredrik Hübinette (Hubbe) | | case F_CONSTANT:
default:
|
b8cda2 | 1997-01-21 | Fredrik Hübinette (Hubbe) | | name="function call";
}
if(max_correct_args == count_arguments(s))
{
my_yyerror("To few arguments to %s.\n",name);
}else{
my_yyerror("Bad argument %d to %s.",
max_correct_args+1, name);
|
3856c3 | 1996-11-25 | Fredrik Hübinette (Hubbe) | | }
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | copy_shared_string(n->type, mixed_type_string);
}
free_string(s);
|
cb2256 | 1995-10-11 | Fredrik Hübinette (Hubbe) | | break;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | }
case '?':
|
cb2256 | 1995-10-11 | Fredrik Hübinette (Hubbe) | | if(!match_types(CAR(n)->type,mixed_type_string))
yyerror("Bad conditional expression.\n");
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | if(!CADR(n) || !CDDR(n))
{
copy_shared_string(n->type,void_type_string);
return;
}
if(CADR(n)->type == CDDR(n)->type)
{
copy_shared_string(n->type,CADR(n)->type);
return;
}
copy_shared_string(n->type,mixed_type_string);
|
cb2256 | 1995-10-11 | Fredrik Hübinette (Hubbe) | | break;
case F_RETURN:
if(local_variables &&
local_variables->current_return_type &&
!match_types(local_variables->current_return_type,CAR(n)->type) &&
!(
local_variables->current_return_type==void_type_string &&
CAR(n)->token == F_CONSTANT &&
IS_ZERO(& CAR(n)->u.sval)
)
)
{
yyerror("Wrong return type.");
}
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
case F_INC_LOOP:
case F_DEC_LOOP:
case F_DEC_NEQ_LOOP:
case F_INC_NEQ_LOOP:
case F_CASE:
case F_CONTINUE:
case F_BREAK:
copy_shared_string(n->type,void_type_string);
|
cb2256 | 1995-10-11 | Fredrik Hübinette (Hubbe) | | break;
case F_DO:
if(!match_types(CDR(n)->type,mixed_type_string))
yyerror("Bad conditional expression do - while().\n");
copy_shared_string(n->type,void_type_string);
break;
case F_FOR:
if(!match_types(CAR(n)->type,mixed_type_string))
yyerror("Bad conditional expression for().\n");
copy_shared_string(n->type,void_type_string);
break;
case F_SWITCH:
if(!match_types(CAR(n)->type,mixed_type_string))
yyerror("Bad switch expression.\n");
copy_shared_string(n->type,void_type_string);
break;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
case F_CONSTANT:
n->type = get_type_of_svalue(& n->u.sval);
|
cb2256 | 1995-10-11 | Fredrik Hübinette (Hubbe) | | break;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | case F_ARG_LIST:
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);
return;
}
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);
return;
}
default:
copy_shared_string(n->type,mixed_type_string);
}
}
static void zapp_try_optimize(node *n)
{
|
86bea9 | 1997-01-31 | Fredrik Hübinette (Hubbe) | | if(!n) return;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | 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;
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;
if(!n->parent) break;
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->tree_info & (OPT_NOT_CONST|
OPT_SIDE_EFFECT|
OPT_EXTERNAL_DEPEND|
OPT_ASSIGNMENT))
{
if(car_is_node(n) &&
!(CAR(n)->tree_info & (OPT_NOT_CONST|
OPT_SIDE_EFFECT|
OPT_EXTERNAL_DEPEND|
OPT_ASSIGNMENT)) &&
(CAR(n)->tree_info & OPT_TRY_OPTIMIZE) &&
CAR(n)->token != ':')
{
CAR(n) = eval(CAR(n));
if(CAR(n)) CAR(n)->parent = n;
zapp_try_optimize(CAR(n));
continue;
}
if(cdr_is_node(n) &&
!(CDR(n)->tree_info & (OPT_NOT_CONST|
OPT_SIDE_EFFECT|
OPT_EXTERNAL_DEPEND|
OPT_ASSIGNMENT)) &&
(CDR(n)->tree_info & OPT_TRY_OPTIMIZE) &&
CDR(n)->token != ':')
{
CDR(n) = eval(CDR(n));
if(CDR(n)) CDR(n)->parent = n;
zapp_try_optimize(CDR(n));
continue;
}
}
fix_type_field(n);
#ifdef DEBUG
if(l_flag > 3)
{
fprintf(stderr,"Optimizing: ");
print_tree(n);
}
#endif
switch(n->token)
{
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | case F_APPLY:
if(CAR(n)->token == F_CONSTANT &&
CAR(n)->u.sval.type == T_FUNCTION &&
|
bdb509 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | CAR(n)->u.sval.subtype == FUNCTION_BUILTIN &&
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | CAR(n)->u.sval.u.efun->optimize)
{
if(tmp1=CAR(n)->u.sval.u.efun->optimize(n))
goto use_tmp1;
}
break;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | case F_ARG_LIST:
case F_LVALUE_LIST:
if(!CAR(n)) goto use_cdr;
if(!CDR(n)) goto use_car;
if((CAR(n)->token==F_RETURN ||
CAR(n)->token==F_BREAK ||
CAR(n)->token==F_CONTINUE ||
(CAR(n)->token==F_ARG_LIST &&
CDAR(n) &&
(CDAR(n)->token==F_RETURN ||
CDAR(n)->token==F_BREAK ||
CDAR(n)->token==F_CONTINUE))) &&
!(CDR(n)->tree_info & OPT_CASE))
goto use_car;
break;
case F_LOR:
if(CAR(n)->token==F_NOT && CDR(n)->token==F_NOT)
{
tmp1=mknode(F_NOT,mknode(F_LAND,CAAR(n),CADR(n)),0);
CAAR(n)=CADR(n)=0;
goto use_tmp1;
}
break;
case F_LAND:
if(CAR(n)->token==F_NOT && CDR(n)->token==F_NOT)
{
tmp1=mknode(F_NOT,mknode(F_LOR,CAAR(n),CADR(n)),0);
CAAR(n)=CADR(n)=0;
goto use_tmp1;
}
break;
case '?':
if(CAR(n)->token == F_NOT)
{
tmp1=mknode('?',CAAR(n),mknode(':',CDDR(n),CADR(n)));
CAAR(n)=CDDR(n)=CADR(n)=0;
goto use_tmp1;
}
break;
case F_ADD_EQ:
if(CDR(n)->type == int_type_string)
{
if(CDR(n)->token == F_CONSTANT && CDR(n)->u.sval.type == T_INT)
{
if(n->u.sval.u.integer == 0) goto use_car;
if(n->u.sval.u.integer == 1)
{
tmp1=mknode(F_INC,CDR(n),0);
CDR(n)=0;
goto use_tmp1;
}
if(n->u.sval.u.integer == -1)
{
tmp1=mknode(F_DEC, CDR(n), 0);
CDR(n)=0;
goto use_tmp1;
}
}
}
break;
case F_SUB_EQ:
if(CDR(n)->type == int_type_string)
{
if(CDR(n)->token == F_CONSTANT && CDR(n)->u.sval.type == T_INT)
{
if(n->u.sval.u.integer == 0) goto use_car;
if(n->u.sval.u.integer == -1)
{
tmp1=mknode(F_INC, CDR(n), 0);
CDR(n)=0;
goto use_tmp1;
}
if(n->u.sval.u.integer == 1)
{
tmp1=mknode(F_DEC, CDR(n), 0);
CDR(n)=0;
goto use_tmp1;
}
}
}
break;
case F_FOR:
{
node **last;
int inc;
int token;
if(node_is_false(CAR(n)))
{
tmp1=mkintnode(0);
goto use_tmp1;
}
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | |
if(node_is_true(CAR(n)) &&
(!CDR(n) || (CDR(n)->token==':' && !CADR(n) && !CDDR(n))))
{
tmp1=mknode(F_FOR, CAR(n), mknode(':',mkefuncallnode("sleep",mkintnode(255)),0));
CAR(n)=0;
goto use_tmp1;
}
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | |
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | * if X and Y are free from 'continue' or X is null,
* then the following optimizations can be done:
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | * for(;++e; X) Y; -> ++ne_loop(e, -1) { Y ; X }
* for(;e++; X) Y; -> ++ne_loop(e, 0) { Y; X }
* for(;--e; X) Y; -> --ne_loop(e, 1) { Y; X }
* for(;e--; X) Y; -> --ne_loop(e, 0) { Y; X }
*/
if(CAR(n) &&
(CAR(n)->token==F_INC ||
CAR(n)->token==F_POST_INC ||
CAR(n)->token==F_DEC ||
CAR(n)->token==F_POST_DEC ) &&
(!CDDR(n) || !(CDDR(n)->tree_info & OPT_CONTINUE)) &&
(!CADR(n) || !(CADR(n)->tree_info & OPT_CONTINUE)) )
{
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | |
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | switch(CAR(n)->token)
{
case F_POST_DEC: token=F_DEC_NEQ_LOOP; inc=-1; break;
case F_DEC: token=F_DEC_NEQ_LOOP; inc=0; break;
case F_POST_INC: token=F_INC_NEQ_LOOP; inc=1; break;
case F_INC: token=F_INC_NEQ_LOOP; inc=0; break;
default: fatal("Impossible error\n"); return;
}
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | |
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | tmp1=mknode(token,
mknode(F_VAL_LVAL,
mkintnode(inc),
CAAR(n)),
mknode(F_ARG_LIST,
mkcastnode(void_type_string, CADR(n)),
mkcastnode(void_type_string, CDDR(n))));
|
0d202a | 1995-10-20 | Fredrik Hübinette (Hubbe) | | CDDR(n)=CADR(n)=CAAR(n)=0;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | goto use_tmp1;
}
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | |
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | last=&(CDDR(n));
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | tmp1=*last;
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | |
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | while(tmp1 &&
tmp1->token == F_CAST &&
tmp1->type == void_type_string)
{
last=&CAR(tmp1);
tmp1=*last;
}
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | |
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | if(tmp1 && (tmp1->token==F_INC ||
tmp1->token==F_POST_INC ||
tmp1->token==F_DEC ||
tmp1->token==F_POST_DEC))
{
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | node *opnode, **arg1, **arg2;
int oper;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
if(tmp1->token==F_INC || tmp1->token==F_POST_INC)
inc=1;
else
inc=0;
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | |
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | opnode=CAR(n);
if(opnode->token == F_APPLY &&
CAR(opnode) &&
CAR(opnode)->token == F_CONSTANT &&
CAR(opnode)->u.sval.type == T_FUNCTION &&
|
bdb509 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | CAR(opnode)->u.sval.subtype == FUNCTION_BUILTIN)
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | {
if(CAR(opnode)->u.sval.u.efun->function == f_gt)
oper=F_GT;
else if(CAR(opnode)->u.sval.u.efun->function == f_ge)
oper=F_GE;
else if(CAR(opnode)->u.sval.u.efun->function == f_lt)
oper=F_LT;
else if(CAR(opnode)->u.sval.u.efun->function == f_le)
oper=F_LE;
else if(CAR(opnode)->u.sval.u.efun->function == f_ne)
oper=F_NE;
else
break;
}else{
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | break;
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | }
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | if(count_args(CDR(opnode)) != 2) break;
arg1=my_get_arg(&CDR(opnode), 0);
arg2=my_get_arg(&CDR(opnode), 1);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | |
if(!node_is_eq(*arg1,CAR(tmp1)) ||
depend_p(*arg2,*arg2) ||
depend_p(*arg2,*arg1) ||
depend_p(*arg2,CADR(n)))
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | if(!node_is_eq(*arg2,CAR(tmp1)) ||
depend_p(*arg1,*arg2) ||
depend_p(*arg1,*arg1) ||
depend_p(*arg1,CADR(n))
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | )
{
break;
}else{
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | node **tmparg;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | switch(oper)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | case F_LT: oper=F_GT; break;
case F_LE: oper=F_GE; break;
case F_GT: oper=F_LT; break;
case F_GE: oper=F_LE; break;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | }
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | |
tmparg=arg1;
arg1=arg2;
arg2=tmparg;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | }
}
if(inc)
{
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | if(oper==F_LE)
tmp3=mkopernode("`+",*arg2,mkintnode(1));
else if(oper==F_LT)
tmp3=*arg2;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | else
break;
}else{
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | if(oper==F_GE)
tmp3=mkopernode("`-",*arg2,mkintnode(1));
else if(oper==F_GT)
tmp3=*arg2;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | else
break;
}
*last=0;
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | if(oper==F_NE)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
if(inc)
token=F_INC_NEQ_LOOP;
else
token=F_DEC_NEQ_LOOP;
}else{
if(inc)
token=F_INC_LOOP;
else
token=F_DEC_LOOP;
}
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | | tmp2=mknode(token,mknode(F_VAL_LVAL,tmp3,*arg1),CADR(n));
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | *arg1 = *arg2 = CADR(n) =0;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
if(inc)
{
tmp1->token=F_DEC;
}else{
tmp1->token=F_INC;
}
|
689118 | 1996-08-06 | Fredrik Hübinette (Hubbe) | |
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | tmp1=mknode(F_ARG_LIST,mkcastnode(void_type_string,tmp1),tmp2);
goto use_tmp1;
}
break;
}
use_car:
tmp1=CAR(n);
CAR(n)=0;
goto use_tmp1;
use_cdr:
tmp1=CDR(n);
CDR(n)=0;
goto use_tmp1;
use_tmp1:
if(CAR(n->parent) == n)
CAR(n->parent) = tmp1;
else
CDR(n->parent) = tmp1;
if(tmp1) tmp1->parent = n->parent;
free_node(n);
n=tmp1;
#ifdef DEBUG
if(l_flag > 3)
{
fprintf(stderr,"Result: ");
print_tree(n);
}
#endif
continue;
}
n->node_info |= OPT_OPTIMIZED;
n=n->parent;
}while(n);
current_line = save_line;
}
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | | struct timer_oflo
{
INT32 counter;
int yes;
};
|
d085c7 | 1996-11-18 | Fredrik Hübinette (Hubbe) | | static void check_evaluation_time(struct callback *cb,void *tmp,void *ignored)
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | | {
struct timer_oflo *foo=(struct timer_oflo *)tmp;
if(foo->counter-- < 0)
{
foo->yes=1;
throw();
}
}
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | int eval_low(node *n)
{
|
5c8e89 | 1995-10-29 | Fredrik Hübinette (Hubbe) | | unsigned INT16 num_strings, num_constants;
INT32 jump;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | struct svalue *save_sp = sp;
int ret;
if(num_parse_error) return -1;
setup_fake_program();
num_strings=fake_program.num_strings;
num_constants=fake_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)
{
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | | struct callback *tmp_callback;
struct timer_oflo foo;
foo.counter=10000;
foo.yes=0;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | setup_fake_object();
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | |
tmp_callback=add_to_callback(&evaluator_callbacks,
check_evaluation_time,
(void *)&foo,0);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | if(apply_low_safe_and_stupid(&fake_object, jump))
{
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.");
}
}else{
yyerror("Nonstandard error format.");
}
}else{
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | | if(foo.yes)
pop_n_elems(sp-save_sp);
else
ret=sp-save_sp;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | }
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | |
remove_callback(tmp_callback);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | }
while(fake_program.num_strings > num_strings)
{
fake_program.num_strings--;
free_string(fake_program.strings[fake_program.num_strings]);
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | areas[A_STRINGS].s.len-=sizeof(struct pike_string *);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | }
while(fake_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);
}
areas[A_PROGRAM].s.len=jump;
return ret;
}
static node *eval(node *n)
{
int args;
extern struct svalue *sp;
if(!is_const(n) || n->token==':')
return n;
args=eval_low(n);
switch(args)
{
case -1:
return n;
break;
case 0:
free_node(n);
n=0;
break;
case 1:
free_node(n);
n=mksvaluenode(sp-1);
pop_stack();
break;
default:
free_node(n);
n=NULL;
while(args--)
{
n=mknode(F_ARG_LIST,mksvaluenode(sp-1),n);
pop_stack();
}
}
return n;
}
INT32 last_function_opt_info;
|
329cc0 | 1997-02-17 | Fredrik Hübinette (Hubbe) | | static int stupid_args(node *n, int expected,int vargs)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
|
329cc0 | 1997-02-17 | Fredrik Hübinette (Hubbe) | | if(!n) return expected;
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:
return n->u.number==expected ? expected + 1 : -1;
default:
return -1;
}
}
static is_null_branch(node *n)
{
if(!n) return 1;
if(n->token==F_CAST && n->type==void_type_string)
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,
int vargs)
{
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;
}
if(n->token == F_CAST && n->type==void_type_string)
{
n=CAR(n);
continue;
}
break;
}
|
9669e8 | 1997-02-27 | Fredrik Hübinette (Hubbe) | | if(!n || n->token != F_RETURN) return 0;
|
329cc0 | 1997-02-17 | Fredrik Hübinette (Hubbe) | | n=CAR(n);
|
9669e8 | 1997-02-27 | Fredrik Hübinette (Hubbe) | | if(!n || n->token != F_APPLY) return 0;
|
329cc0 | 1997-02-17 | Fredrik Hübinette (Hubbe) | |
tmp=stupid_args(CDR(n),0,vargs);
if(!(vargs?tmp==65535:tmp==args)) return 0;
n=CAR(n);
|
9669e8 | 1997-02-27 | Fredrik Hübinette (Hubbe) | | if(!n || n->token != F_CONSTANT) return 0;
|
329cc0 | 1997-02-17 | Fredrik Hübinette (Hubbe) | | return &n->u.sval;
}
int dooptcode(struct pike_string *name,
node *n,
struct pike_string *type,
int modifiers)
{
union idptr tmp;
int args, vargs, ret;
struct svalue *foo;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | #ifdef DEBUG
if(a_flag > 1)
|
d33477 | 1996-04-13 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"Doing function '%s' at %x\n",name->str,PC);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | #endif
last_function_opt_info=OPT_SIDE_EFFECT;
|
329cc0 | 1997-02-17 | Fredrik Hübinette (Hubbe) | |
args=count_arguments(type);
if(args < 0)
{
args=~args;
vargs=IDENTIFIER_VARARGS;
}else{
vargs=0;
}
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | n=mknode(F_ARG_LIST,n,0);
|
329cc0 | 1997-02-17 | Fredrik Hübinette (Hubbe) | |
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);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | #ifdef DEBUG
if(a_flag > 2)
{
fprintf(stderr,"Coding: ");
print_tree(n);
}
#endif
if(!num_parse_error)
{
do_code_block(n);
}
|
329cc0 | 1997-02-17 | Fredrik Hübinette (Hubbe) | |
ret=define_function(name,
type,
modifiers,
IDENTIFIER_PIKE_FUNCTION | vargs,
&tmp);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | free_node(n);
|
329cc0 | 1997-02-17 | Fredrik Hübinette (Hubbe) | | return ret;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | }
INT32 get_opt_info() { return last_function_opt_info; }
|