int poe_pushargv(poe_universe *U, poe_arr *a) { if (U->argv_stack_index+1>=U->argv_stack_size) if (!enlarge_stack(U, POE_ARGV_STACK, 1)) return 0; U->argv_stack_index ++; U->argv_stack_base[U->argv_stack_index] = a; return 1; }
int poe_pushargc(poe_universe *U, int i) { if (U->argc_stack_index+1>=U->argc_stack_size) if (!enlarge_stack(U, POE_ARGC_STACK, 1)) return 0; U->argc_stack_index ++; U->argc_stack_base[U->argc_stack_index] = i; return 1; }
int poe_pushobj(poe_universe *U, poe_obj o, char tag) { if (U->main_stack_index+1>=U->main_stack_size) if (!enlarge_stack(U, POE_MAIN_STACK, 1)) return 0; U->main_stack_index ++; U->main_stack_base[U->main_stack_index].data = o; U->main_stack_base[U->main_stack_index].tag = tag; return 1; }
static int handle_token_lbrace( Token * tk, Parser * parser, FILE * out ) { if( !tk || !parser || !out ) return 0; ++parser->last_brace_indent; if( parser->last_brace_indent >= parser->stack_size && !enlarge_stack( &(parser->brace_indent), &(parser->stack_size) ) ) { return 0; } parser->brace_indent[parser->last_brace_indent] = parser->indent; if( !parser->empty_line && parser->prev_tk.type != ASSIGN_OP ) { putc( '\n', out ); parser->empty_line = 1; } // insert a space after '=' in array initialization if( parser->prev_tk.type == ASSIGN_OP ) { putc( ' ', out ); } if( !push_indent( parser->indent, out ) ) return 0; if( !push_token( tk, out ) ) return 0; parser->empty_line = 0; parser->in_branch = 0; ++parser->indent; parser->un_op = 0; return 1; }
/* if a pfunc is called, we need to generate a new local symbol table and push it onto the local stack. (The supertable of that table will be the parent symbol table of the pfunc; when the interpreter needs to search for a symbol, if will traverse the supertables until it reaches the global table.) A RETURN statement will pop the argv, argc, and locals stacks, so if we hit a codeend, we'll need to RETURN ourselves. HOWEVER, a cfunc does not need to clear the argv/argc stacks, so this function needs to take care of them. */ int pexec_call(poe_universe *U) { tagged_poe_obj *stack = U->main_stack_base; int index = U->main_stack_index, result, status; tagged_poe_obj a = stack[index]; poe_table *new_local; poe_obj metamethod; poe_arr *retv; char methodtag, retvtag; poe_obj retv_obj; switch (a.tag) { case POE_PFUNC_TAG: new_local = poe_make_table(U); if (!new_local) return POE_FATAL_ERROR; new_local->super_tag = POE_TABLE_TAG; new_local->super = (poe_obj)a.data.poe_pfunc->parent; index = U->locals_stack_index; if (index+1>=U->locals_stack_size) if (!enlarge_stack(U, POE_LOCALS_STACK, 1)) return POE_FATAL_ERROR; if (U->info_stack_index+1>=U->info_stack_size) if (!enlarge_stack(U, POE_INFO_STACK, 1)) return POE_FATAL_ERROR; U->locals_stack_index++; U->locals_stack_base[index+1] = new_local; U->info_stack_index++; U->info_stack_base[U->info_stack_index] = 0; if (!poe_gc_control(U,(poe_obj)new_local,POE_TABLE_TAG)) return POE_FATAL_ERROR; U->main_stack_index--; // remove the function from the stack result = poe_exec_code(U, a.data.poe_pfunc->code,NULL); if (result==POE_RETURN) { /* we need to push the first returned value onto the stack */ retv_obj = poe_arr_get(U->retv, 0L, &retvtag); if (!poe_pushobj(U,retv_obj,retvtag)) return POE_FATAL_ERROR; pgc_countdown(U); return POE_CONTINUE; } else if (result==POE_CODEEND) { /* we need to execute our own return statement and return an empty retv */ pexec_return(U); retv = poe_make_arr(U); if (!retv) return POE_FATAL_ERROR; U->retv = retv; retv_obj.poe_arr = retv; if (!poe_gc_control(U,retv_obj,POE_ARR_TAG)) return POE_FATAL_ERROR; U->retc = 0L; retv_obj.poe_int = 0; if (!poe_pushobj(U,retv_obj,POE_UNDEF_TAG)) return POE_FATAL_ERROR; pgc_countdown(U); return POE_CONTINUE; } return POE_FATAL_ERROR; break; case POE_CFUNC_TAG: /* no new local table */ U->main_stack_index --; result = (a.data.poe_cfunc)(U); U->argv_stack_base[U->argv_stack_index--] = NULL; U->argc_stack_base[U->argc_stack_index--] = -1; retv_obj = poe_arr_get(U->retv, 0L, &retvtag); if (!poe_pushobj(U,retv_obj,retvtag)) return POE_FATAL_ERROR; pgc_countdown(U); return result; default: metamethod = get_metamethod(meta_call,a.data,a.tag,&methodtag); if (methodtag!=POE_UNDEF_TAG) { U->main_stack_index --; if (!poe_pushobj(U,metamethod,methodtag)) return POE_FATAL_ERROR; if (!(status = pexec_call(U))) return POE_FATAL_ERROR; if (status==POE_HALT) return POE_HALT; } else { U->argv_stack_base[U->argv_stack_index--] = NULL; U->argc_stack_base[U->argc_stack_index--] = -1; } pgc_countdown(U); return POE_CONTINUE; break; } }