static void generate_app(struct vec *v,OBJ ast) { OBJ procedure; OBJ primitive; OBJ cell; OBJ formals; if(obj_app_type(ast) == 0) /* procedure */ { generate_begin(v,obj_app_params(ast)); procedure = obj_app_data(ast); formals = obj_procedure_formals(procedure); while(obj_pairp(formals)) { emit(v,PUSH); emitv(v,car(formals)); emit(v,SET_CDR); emit(v,POP); formals = cdr(formals); } if(!nullp(formals)) { emit(v,PUSH); emitv(v,formals); /* fixme: something should do to support other form formals */ } emit(v,PUSH); emitv(v,procedure); emit(v,obj_app_tail(ast)?TAIL_CALL:CALL); } else if(obj_app_type(ast) == 1) /* primitive */ { generate_begin(v,obj_app_params(ast)); primitive = obj_app_data(ast); switch(obj_primitive_type(primitive)) { case DATA: emit(v,obj_primitive_opcode(primitive)); emitv(v,obj_primitive_data(primitive)); break; case FUNCALL: emit(v,obj_primitive_opcode(primitive)); emitv(v,obj_primitive_proc(primitive)); break; default: emit(v,obj_primitive_opcode(primitive)); } } else if(obj_app_type(ast) == 2) /* uninitialized procedure */ { cell = obj_app_data(ast); generate_begin(v,obj_app_params(ast)); emit(v,PUSH); emitv(v,cell); emit(v,UNINIT_REF); emit(v,BIND); emit(v,obj_app_tail(ast)?TAIL_CALL:CALL); } }
static void generate_lambda(struct vec *v,OBJ ast) { struct vec vec; OBJ procedure; unsigned length; OBJ code; vec.begin = malloc(100); vec.end = vec.begin + 100; vec.cur = vec.begin; generate_r(&vec,obj_lambda_body(ast)); emit(&vec,RET); length = vec.cur - vec.begin; code = obj_make_string_2(length); memcpy(obj_string_data(code),vec.begin,length); free(vec.begin); procedure = obj_make_procedure(obj_lambda_env(ast),code,obj_lambda_formals(ast)); emit(v,PUSH); emitv(v,procedure); }
static char* declare_label(struct vec *v) { char *ret = v->cur; emitv(v,0); return ret; }
void genobj( void ) { short int *symbol, *target; short int *p, *q, *r; short int action; set_size *mp; a_sym *sym; a_pro *pro; an_item *item; a_state *x; a_shift_action *tx; a_reduce_action *rx; int i, j, savings; for( i = nterm; i < nsym; ++i ) symtab[i]->token = i - nterm; label = OPTENTRY( nstate - 1 ); emitins( JMP, TOKENTRY( startstate->sidx ) ); target = CALLOC( nsym, short int ); for( i = 0; i < nsym; ++i ) target[i] = DEFAULT; symbol = CALLOC( nsym, short int ); for( i = 0; i < nstate; ++i ) { x = statetab[i]; q = symbol; for( tx = x->trans; (sym = tx->sym) != NULL; ++tx ) { if( sym == eofsym ) { action = ACCEPT; } else if( sym->idx < nterm ) { action = TOKENTRY(tx->state->sidx); } else { action = OPTENTRY(tx->state->sidx); } *q++ = sym->idx; target[sym->idx] = action; } savings = 0; for( rx = x->redun; (pro = rx->pro) != NULL; ++rx ) { action = PROENTRY( pro->pidx ); mp = Members( rx->follow ); if( mp - setmembers > savings ) { savings = mp - setmembers; r = q; } while( --mp >= setmembers ) { *q++ = *mp; target[*mp] = action; } } action = DEFAULT; if( savings ) { action = target[*r]; p = r; while( --savings >= 0 ) { target[*p++] = DEFAULT; } } emitins( LBL, TOKENTRY( x->sidx ) ); emitins( SCAN, 0 ); emitins( LBL, OPTENTRY( x->sidx ) ); emitins( CALL, VBLENTRY( x->sidx ) ); q = symbol; for( j = nterm; j < nsym; ++j ) { if( target[j] != DEFAULT ) { *q++ = j; } } if( q != symbol ) { emitv( symbol, target, q - symbol ); for( p = symbol; p < q; ++p ) { target[*p] = DEFAULT; } } emitins( LBL, VBLENTRY( x->sidx ) ); q = symbol; for( j = 0; j < nterm; ++j ) { if( target[j] != DEFAULT ) { *q++ = j; } } emitt( symbol, target, q - symbol, action ); for( p = symbol; p < q; ++p ) { target[*p] = DEFAULT; } } FREE( target ); FREE( symbol ); for( i = 0; i < npro; ++i ) { pro = protab[i]; if( pro != startpro ) { for( item = pro->item; item->p.sym != NULL; ) { ++item; } emitins( LBL, PROENTRY( pro->pidx ) ); emitins( ACTION, PROPACK( item - pro->item, i ) ); emitins( REDUCE, PROPACK( item - pro->item, pro->sym->token ) ); } } writeobj( label + 1 ); }