static void eval_root(void) { oast_t *ast; oword_t offset; orecord_t *record; ofunction_t *function; assert(current_record == root_record); assert(current_function == root_record->function); oeval_ast(root_record->function->ast->c.ast); odata(root_record->function->ast->c.ast); for (offset = type_vector->offset - 1; offset > t_root; --offset) { record = type_vector->v.ptr[offset]; if (otype(record) == t_prototype && likely(record->function && ofunction_p(record->function))) { function = record->function; current_record = record; current_function = function; /* Error later if function is actually called but never defined */ if ((ast = function->ast)) { oeval_ast(ast->l.ast); eval_ast_declexpr(ast->r.ast->r.ast); oeval_ast(ast->c.ast); odata(function->ast->c.ast); } } } current_function = root_record->function; current_record = root_record; }
otag_t * otag_object(oobject_t object) { otag_t *tag; otype_t type; orecord_t *record; oobject_t *pointer; if (object == null) return (null); switch (type = otype(object)) { case t_basic: record = object; if ((tag = (otag_t *)oget_hash(tag_table, record)) == null) { gc_ref(pointer); onew(pointer, tag); tag = *pointer; tag->name = record; tag->type = tag_basic; tag->size = record->length; oput_hash(tag_table, (oentry_t *)tag); gc_dec(); } break; case t_record: case t_namespace: record = object; if ((tag = (otag_t *)oget_hash(tag_table, record)) == null) { gc_ref(pointer); onew(pointer, tag); tag = *pointer; tag->name = record; tag->type = type == t_record ? tag_class : tag_namespace; tag->size = sizeof(oobject_t); oput_hash(tag_table, (oentry_t *)tag); gc_dec(); } break; case t_tag: tag = object; break; case t_void ... t_mpc: tag = types[type].tag; break; default: if (type & t_vector) { type &= ~t_vector; if (type >= t_void && type < t_mpc) tag = types[type].vtag; else tag = vector_tag; } else tag = auto_tag; break; } return (tag); }
void ocopy(oobject_t *pointer, oobject_t value) { switch (otype(value)) { case t_word: oget_word(pointer); pointer = *pointer; *(oword_t *)pointer = *(oword_t *)value; break; case t_float: oget_float(pointer); pointer = *pointer; *(ofloat_t *)pointer = *(ofloat_t *)value; break; case t_rat: oget_rat(pointer); pointer = *pointer; *(orat_t)pointer = *(orat_t)value; break; case t_mpz: oget_mpz(pointer); pointer = *pointer; mpz_set((ompz_t)pointer, (ompz_t)value); break; case t_mpq: oget_mpq(pointer); pointer = *pointer; mpq_set((ompq_t)pointer, (ompq_t)value); break; case t_mpr: oget_mpr(pointer); pointer = *pointer; mpfr_set((ompr_t)pointer, (ompr_t)value, thr_rnd); break; case t_cdd: oget_cdd(pointer); pointer = *pointer; *(ocdd_t *)pointer = *(ocdd_t *)value; break; case t_cqq: oget_cqq(pointer); pointer = *pointer; cqq_set((ocqq_t)pointer, (ocqq_t)value); break; default: assert(otype(value) == t_mpc); oget_mpc(pointer); pointer = *pointer; mpc_set((ompc_t)pointer, (ompc_t)value, thr_rndc); break; } }
static void native_unlock(oobject_t list, oint32_t size) { nat_mutex_t *alist; alist = (nat_mutex_t *)list; if (alist->mutex == null || otype(alist->mutex) != t_mutex) othrow(except_invalid_argument); omutex_unlock(alist->mutex); }
obool_t ofalse_p(oobject_t object) { if (object == null) return (true); switch (otype(object)) { case t_word: return (*(oword_t *)object == 0); case t_float: return (*(ofloat_t *)object == 0.0); case t_mpr: return (mpfr_zero_p((ompr_t)object) != 0); default: return (false); } }
otag_t * otag_ast(otag_t *tag, oast_t **list) { oast_t *ast; oword_t length; if ((ast = *list) == null) return (tag); for (;;) { switch (ast->token) { case tok_vector: /* This is the best place to "patch" the token value, * so that other code will not confuse a vector * declaration with a vector access. */ ast->token = tok_vecdcl; case tok_vecdcl: if (ast->r.ast) { /* Handle constant expression */ if (ast->r.ast->token != tok_number) oeval_ast(ast->r.ast); if (ast->r.ast->token != tok_number || otype(ast->r.ast->l.value) != t_word) oparse_error(ast->r.ast, "vector length not an integer"); if ((length = *(oword_t *)ast->r.ast->l.value) <= 0) oparse_error(ast->r.ast, "invalid vector length"); tag = tag_vector_check(tag, length, ast->r.ast); } else tag = otag_vector(tag, 0); if ((ast = ast->l.value) == null) { *list = null; return (tag); } break; case tok_call: case tok_symbol: *list = ast; return (tag); case tok_ellipsis: return (varargs_tag); default: oparse_error(ast, "expecting expression"); } } }
static void eval_ast_renew(oast_t *ast) { otag_t *tag; oeval_ast(ast->l.ast); tag = oeval_ast_tag(ast->l.ast); if (tag == null || tag->type != tag_vector) oparse_error(ast->l.ast, "expecting vector %A", ast->l.ast); oeval_ast(ast->r.ast); if (ast->r.ast->token == tok_number) { if (ast->r.ast->l.value == null || otype(ast->r.ast->l.value) != t_word) oparse_error(ast->r.ast, "expecting integer %A", ast->r.ast); if (*(oword_t *)ast->r.ast->l.value < 0) oparse_error(ast->r.ast, "not a positive integer"); } }
static void load_exception(jit_int32_t regval, oword_t offset) { if (otype(current_record) == t_namespace) { if (GPR[GLOBAL] != JIT_NOREG) jit_addi(regval, GPR[GLOBAL], offset); else jit_movi(regval, (oword_t)gd + offset); } else { if (GPR[FRAME] != JIT_NOREG) jit_addi(regval, GPR[FRAME], offset); else { jit_ldxi(regval, JIT_V0, offsetof(othread_t, fp)); jit_addi(regval, regval, offset); } } }
static void native_join(oobject_t list, oint32_t ac) { GET_THREAD_SELF() nat_join_t *alist; alist = (nat_join_t *)list; if (alist->thread == null || otype(alist->thread) != t_thread) othrow(except_invalid_argument); if (pthread_equal(thread_self->pthread, alist->thread->pthread)) othrow(except_invalid_argument); /* Do not fail if attempting to join a thread no longer running. * The thread return value, if any is gc protected by the fact * there is at least one reference to it. */ pthread_join(alist->thread->pthread, null); ovm_move(&thread_self->r0, &alist->thread->r0); }
static void eval_setup(oregister_t *r, oobject_t v) { if (v == null) { r->t = t_void; r->v.o = null; } else { switch (r->t = otype(v)) { case t_word: r->v.w = *(oword_t *)v; break; case t_float: r->v.d = *(ofloat_t *)v; break; case t_rat: r->v.r = *(orat_t)v; break; case t_mpz: mpz_set(ozr(r), (ompz_t)v); break; case t_mpq: mpq_set(oqr(r), (ompq_t)v); break; case t_mpr: mpfr_set(orr(r), (ompr_t)v, thr_rnd); break; case t_cdd: r->v.dd = *(ocdd_t *)v; break; case t_cqq: cqq_set(oqq(r), (ocqq_t)v); break; default: assert(r->t == t_mpc); mpc_set(occ(r), (ompc_t)v, thr_rndc); break; } } }
static otag_t * tag_ast_data_vector(otag_t *tag, oast_t *ast) { oast_t *rast; otag_t *btag; otag_t *rtag; oword_t length; oword_t offset; btag = tag->base; for (offset = length = 0; ast; ast = ast->next, offset++) { if (ast->token == tok_init) { rast = ast->l.ast; if (rast->token != tok_number || otype(rast->l.value) != t_word) oparse_error(rast, "not an integer"); offset = *(oword_t *)rast->l.value; if (offset < 0) oparse_error(rast, "negative offset"); if (tag->size && tag->size <= offset) oparse_error(rast, "offset out of bounds"); rtag = otag_ast_data(tag->base, ast->r.value); } else { rtag = otag_ast_data(tag->base, ast); if (tag->size && tag->size <= offset) oparse_error(ast, "too many initializers"); } if (rtag->type == btag->type && rtag->size > btag->size) btag = rtag; if (length <= offset) length = offset + 1; } if (!tag->size) tag = tag_vector_check(btag, length, ast); return (tag); }
void getobject( /* read the next object */ char *name, FILE *fp ) { #define OALIAS -2 OBJECT obj; char sbuf[MAXSTR]; int rval; OBJREC *objp; if ((obj = newobject()) == OVOID) error(SYSTEM, "out of object space"); objp = objptr(obj); /* get modifier */ strcpy(sbuf, "EOF"); fgetword(sbuf, MAXSTR, fp); if (strchr(sbuf, '\t')) { sprintf(errmsg, "(%s): illegal tab in modifier \"%s\"", name, sbuf); error(USER, errmsg); } if (!strcmp(sbuf, VOIDID)) objp->omod = OVOID; else if (!strcmp(sbuf, ALIASMOD)) objp->omod = OALIAS; else if ((objp->omod = modifier(sbuf)) == OVOID) { sprintf(errmsg, "(%s): undefined modifier \"%s\"", name, sbuf); error(USER, errmsg); } /* get type */ strcpy(sbuf, "EOF"); fgetword(sbuf, MAXSTR, fp); if ((objp->otype = otype(sbuf)) < 0) { sprintf(errmsg, "(%s): unknown type \"%s\"", name, sbuf); error(USER, errmsg); } /* get identifier */ sbuf[0] = '\0'; fgetword(sbuf, MAXSTR, fp); if (strchr(sbuf, '\t')) { sprintf(errmsg, "(%s): illegal tab in identifier \"%s\"", name, sbuf); error(USER, errmsg); } objp->oname = savqstr(sbuf); /* get arguments */ if (objp->otype == MOD_ALIAS) { OBJECT alias; strcpy(sbuf, "EOF"); fgetword(sbuf, MAXSTR, fp); if ((alias = modifier(sbuf)) == OVOID) { sprintf(errmsg, "(%s): bad reference \"%s\"", name, sbuf); objerror(objp, USER, errmsg); } if (objp->omod == OALIAS || objp->omod == objptr(alias)->omod) { objp->omod = alias; } else { objp->oargs.sarg = (char **)malloc(sizeof(char *)); if (objp->oargs.sarg == NULL) error(SYSTEM, "out of memory in getobject"); objp->oargs.nsargs = 1; objp->oargs.sarg[0] = savestr(sbuf); } } else if ((rval = readfargs(&objp->oargs, fp)) == 0) { sprintf(errmsg, "(%s): bad arguments", name); objerror(objp, USER, errmsg); } else if (rval < 0) { sprintf(errmsg, "(%s): error reading scene", name); error(SYSTEM, errmsg); } if (objp->omod == OALIAS) { sprintf(errmsg, "(%s): inappropriate use of '%s' modifier", name, ALIASMOD); objerror(objp, USER, errmsg); } /* initialize */ objp->os = NULL; insertobject(obj); /* add to global structure */ #undef OALIAS }
void ocoerce(oobject_t *pointer, otype_t type, oobject_t value) { union { oint64_t i; ofloat32_t f; ofloat_t d; } data; switch (type) { case t_int8: case t_uint8: case t_int16: case t_uint16: case t_int32: case t_uint32: case t_int64: case t_uint64: switch (otype(value)) { case t_word: data.i = *(oword_t *)value; break; case t_float: data.i = *(ofloat_t *)value; break; case t_mpz: data.i = ompz_get_sl((ompz_t)value); break; case t_mpq: data.i = ompq_get_sl((ompq_t)value); break; case t_mpr: data.i = ompr_get_sl((ompr_t)value); break; case t_cdd: data.i = real(*(ocdd_t *)value); break; case t_cqq: data.i = ompq_get_sl(cqq_realref((ocqq_t)value)); break; default: assert(otype(value) == t_mpc); data.i = ompr_get_sl(mpc_realref((ompc_t)value)); break; } break; case t_float32: case t_float64: switch (otype(value)) { case t_word: data.d = *(oword_t *)value; break; case t_float: data.d = *(ofloat_t *)value; break; case t_mpz: data.d = mpz_get_d((ompz_t)value); break; case t_mpq: data.d = mpq_get_d((ompq_t)value); break; case t_mpr: data.d = mpfr_get_d((ompr_t)value, thr_rnd); break; case t_cdd: data.d = real(*(ocdd_t *)value); break; case t_cqq: data.d = mpq_get_d(cqq_realref((ocqq_t)value)); break; default: assert(otype(value) == t_mpc); data.i = mpfr_get_d(mpc_realref((ompc_t)value), thr_rnd); break; } break; default: data.i = 0; break; } switch (type) { case t_int8: oget_word(pointer); pointer = *pointer; *(oword_t *)pointer = (oint8_t)data.i; break; case t_uint8: oget_word(pointer); pointer = *pointer; *(oword_t *)pointer = (ouint8_t)data.i; break; case t_int16: oget_word(pointer); pointer = *pointer; *(oword_t *)pointer = (oint16_t)data.i; break; case t_uint16: oget_word(pointer); pointer = *pointer; *(oword_t *)pointer = (ouint16_t)data.i; break; case t_int32: oget_word(pointer); pointer = *pointer; *(oword_t *)pointer = (oint32_t)data.i; break; case t_uint32: #if __WORDSIZE == 32 if ((ouword_t)data.i != data.i) { oget_mpz(pointer); pointer = *pointer; mpz_set_ui((ompz_t)pointer, (ouword_t)data.i); } else #endif { oget_word(pointer); pointer = *pointer; *(oword_t *)pointer = (ouint32_t)data.i; } break; case t_int64: #if __WORDSIZE == 32 if ((oword_t)data.i != data.i) { oget_mpz(pointer); pointer = *pointer; ompz_set_sl((ompz_t)pointer, data.i); } else #endif { oget_word(pointer); pointer = *pointer; *(oword_t *)pointer = (oword_t)data.i; } break; case t_uint64: if ((ouword_t)data.i != data.i) { oget_mpz(pointer); pointer = *pointer; mpz_set_ui((ompz_t)pointer, (ouword_t)data.i); } else { oget_word(pointer); pointer = *pointer; *(oword_t *)pointer = (ouword_t)data.i; } break; case t_float32: data.f = data.d; data.d = data.f; case t_float: oget_float(pointer); pointer = *pointer; *(ofloat_t *)pointer = data.d; break; default: ocopy(pointer, value); break; } }
int main ( int, char ** ) try { // Prepare the interpreter.a const py::Library library; // Build input stream class for 'wsgi.input' object. py::TypeBuilder itype("istream"); itype.init(py::ctor<&exports::init>()); itype.add(py::Method("read", py::vararg<&exports::read>())); itype.add(py::Method("readline", py::noargs<&exports::readline>())); itype.add(py::Method("readlines", py::vararg<&exports::readlines>())); itype.iterable(py::noargs<&exports::iter>(), py::noargs<&exports::next>()); itype.finish(); // Have 'wsgi.input' object read from standard input stream. py::Object istream = itype(); py::TypeBuilder::set_baton (istream, static_cast<std::istream*>(&std::cin)); // Build output stream class for 'wsgi.errors' object. py::TypeBuilder otype("ostream"); otype.init(py::ctor<&exports::init>()); otype.add(py::Method("flush", py::noargs<&exports::flush>())); otype.add(py::Method("write", py::vararg<&exports::write>())); otype.add(py::Method("writelines", py::vararg<&exports::writelines>())); otype.finish(); // Have 'wsgi.errors' object write to standard output stream. py::Object ostream = otype(); py::TypeBuilder::set_baton (ostream, static_cast<std::ostream*>(&std::cout)); // WSGI bootstrap code. wsgi::Runner execute("wsgi-bootstrap.py"); // WSGI application handler. wsgi::Application application("sample", "wsgi-application.py"); // Prepare application execution context. py::Map environment; // Required CGI-style variables. environment.put("REQUEST_METHOD", "GET"); // "GET", "POST", ... #if 0 environment.put("SCRIPT_NAME", ""); // Path to application script. environment.put("PATH_INFO", ""); // URL delegated to application. environment.put("QUERY_STRING", ""); // URL query string. environment.put("SERVER_NAME", ""); // environment.put("SERVER_PORT", ""); // environment.put("SERVER_PROTOCOL", ""); // "HTTP/1.x" // Optional CGI-style variables. environment.put("CONTENT_TYPE", ""); environment.put("CONTENT_LENGTH", ""); #endif #if 0 // HTTP headers. environment.put("HTTP_HOST", ""); //environment.put(...); #endif // WSGI variables. py::Tuple version(2); version[0] = py::Int(1); version[1] = py::Int(0); environment.put("wsgi.version", version); environment.put("wsgi.url_scheme", "http"); environment.put("wsgi.input", istream); environment.put("wsgi.errors", ostream); environment.put("wsgi.multithread", py::False()); environment.put("wsgi.multiprocess", py::False()); environment.put("wsgi.run_once", py::True()); // Execute application and print HTTP response to "cout". wsgi::http_response(execute(application, environment), wsgi::ostream_handler(std::cout)); } catch ( const py::SystemError& error ) { std::cerr << "Error: '" << error.message() << "'." << std::endl; return (EXIT_FAILURE); } catch ( const py::Error& ) { std::cerr << "Error: 'some python error'." << std::endl; return (EXIT_FAILURE); } catch ( const std::exception& error ) { std::cerr << "Error: '" << error.what() << "'." << std::endl; return (EXIT_FAILURE); }
void oeval_ast(oast_t *ast) { oast_t *temp; orecord_t *record; osymbol_t *symbol; switch (ast->token) { case tok_set: case tok_andset: case tok_orset: case tok_xorset: case tok_mul2set: case tok_div2set: case tok_shlset: case tok_shrset: case tok_addset: case tok_subset: case tok_mulset: case tok_divset: case tok_trunc2set: case tok_remset: oeval_ast(ast->l.ast); oeval_ast(ast->r.ast); break; case tok_vector: oeval_ast(ast->l.ast); if (ast->r.ast == null) oparse_error(ast, "expecting offset"); oeval_ast(ast->r.ast); /* validate element reference */ oeval_ast_tag(ast); break; case tok_dot: oeval_ast(ast->l.ast); /* validate field reference */ oeval_ast_tag(ast); break; case tok_explicit: oeval_ast_tag(ast); break; case tok_andand: case tok_oror: case tok_ne: case tok_lt: case tok_le: case tok_eq: case tok_ge: case tok_gt: case tok_and: case tok_or: case tok_xor: case tok_mul2: case tok_div2: case tok_shl: case tok_shr: case tok_add: case tok_sub: case tok_mul: case tok_div: case tok_trunc2: case tok_rem: case tok_complex: oeval_ast(ast->l.ast); oeval_ast(ast->r.ast); ofold(ast); break; case tok_inc: case tok_dec: case tok_postinc: case tok_postdec: case tok_new: case tok_thread: oeval_ast(ast->l.ast); break; case tok_init: case tok_vecnew: oeval_ast(ast->r.ast); break; case tok_com: case tok_plus: case tok_neg: case tok_not: case tok_integer_p: case tok_rational_p: case tok_float_p: case tok_real_p: case tok_complex_p: case tok_number_p: case tok_finite_p: case tok_inf_p: case tok_nan_p: case tok_num: case tok_den: case tok_real: case tok_imag: case tok_signbit: case tok_abs: case tok_signum: case tok_rational: case tok_arg: case tok_conj: case tok_floor: case tok_trunc: case tok_round: case tok_ceil: case tok_sqrt: case tok_cbrt: case tok_sin: case tok_cos: case tok_tan: case tok_asin: case tok_acos: case tok_atan: case tok_sinh: case tok_cosh: case tok_tanh: case tok_asinh: case tok_acosh: case tok_atanh: case tok_proj: case tok_exp: case tok_log: case tok_log2: case tok_log10: oeval_ast(ast->l.ast); ofold(ast); break; case tok_atan2: case tok_pow: case tok_hypot: oeval_ast(ast->l.ast); oeval_ast(ast->r.ast); ofold(ast); break; case tok_subtypeof: oeval_ast(ast->l.ast); oeval_ast(ast->r.ast); break; case tok_sizeof: eval_ast_sizeof(ast); break; case tok_typeof: eval_ast_typeof(ast); break; case tok_renew: eval_ast_renew(ast); break; case tok_question: oeval_ast(ast->t.ast); oeval_ast(ast->l.ast); oeval_ast(ast->r.ast); break; case tok_if: eval_ast_stat(ast->t.ast); eval_ast_stat(ast->l.ast); eval_ast_stat(ast->r.ast); break; case tok_return: check_exception(ast); case tok_throw: if (ast->l.ast) oeval_ast(ast->l.ast); break; case tok_switch: eval_ast_stat(ast->t.ast); eval_ast_stat(ast->c.ast); break; case tok_for: eval_ast_stat(ast->l.ast); eval_ast_stat(ast->t.ast); eval_ast_stat(ast->r.ast); eval_ast_stat(ast->c.ast); break; case tok_do: case tok_while: eval_ast_stat(ast->c.ast); eval_ast_stat(ast->t.ast); break; case tok_list: temp = ast->l.ast; eval_ast_stat(temp); /* Check inner fields for the sake of clean debug output. */ if (temp->next == null && temp->r.value == null && temp->t.value == null && temp->c.value == null) omove_ast_up_full(ast, temp); break; case tok_call: if (ast->l.ast->token != tok_symbol) oeval_ast(ast->l.ast); else update_symbol(ast->l.ast, true); eval_ast_stat(ast->r.ast); break; case tok_stat: case tok_code: case tok_data: case tok_finally: eval_ast_stat(ast->l.ast); break; case tok_decl: oeval_ast(ast->l.ast); eval_ast_decl(ast->r.ast); break; case tok_symbol: update_symbol(ast, false); break; case tok_goto: eval_ast_goto(ast); break; case tok_try: eval_ast_stat(ast->r.ast); break; case tok_catch: eval_ast_decl(ast->l.ast->r.ast); eval_ast_stat(ast->r.ast); break; case tok_break: case tok_continue: check_exception(ast); case tok_type: case tok_number: case tok_string: case tok_class: case tok_label: case tok_case: case tok_default: case tok_function: case tok_ellipsis: case tok_this: case tok_enum: break; case tok_namespace: record = current_record; assert(ast->l.ast->token == tok_symbol); symbol = ast->l.ast->l.value; current_record = symbol->value; assert(otype(current_record) == t_namespace); eval_ast_stat(ast->c.ast); current_record = record; break; default: #if DEBUG oparse_warn(ast, "code: not handling %s", otoken_to_charp(ast->token)); #endif break; } }
otag_t * oeval_ast_tag(oast_t *ast) { otag_t *tag; oast_t *rast; orecord_t *record; osymbol_t *symbol; ovector_t *vector; switch (ast->token) { case tok_symbol: update_symbol(ast, false); symbol = ast->l.value; return (symbol->tag); case tok_vector: tag = oeval_ast_tag(ast->l.ast); switch (tag->type) { case tag_vector: case tag_varargs: break; case tag_hash: /* Patch token to simplify later parsing */ ast->token = tok_hash; break; default: if (ast->l.ast->token == tok_symbol) { symbol = ast->l.ast->l.value; oparse_error(ast, "'%p' is not a vector %A", symbol->name, ast); } oparse_error(ast, "not a vector reference %A", ast); break; } return (tag->base); case tok_dot: if (ast->l.ast->token == tok_this) { for (record = current_record; record; record = record->parent) if (otype(record) == t_record) break; if (record == null) oparse_error(ast, "'this' now allowed outside 'class' method"); tag = record->name->tag; } else tag = oeval_ast_tag(ast->l.ast); rast = ast->r.ast; assert(rast->token == tok_symbol); if (tag->type == tag_class && ast->l.ast->token == tok_this) { omove_ast_up_full(ast, rast); rast = ast; } else { while (tag->type == tag_function) { vector = tag->name; tag = vector->v.ptr[0]; } if (tag->type != tag_class) { if (ast->l.ast->token == tok_symbol) { symbol = ast->l.ast->l.value; oparse_error(ast, "'%p' is not a class or namespace %A", symbol->name, ast); } oparse_error(ast, "not a class or namespace %A", ast); } } record = tag->name; symbol = rast->l.value; vector = symbol->name; if ((symbol = oget_symbol(record, vector)) == null) oparse_error(ast, "'%p' has no %s named '%p'", record->name, tag->type == tag_class ? "field" : "symbol", vector); rast->l.value = symbol; return (symbol->tag); case tok_explicit: tag = ast->l.ast->l.value; if (tag->type != tag_class) oparse_error(ast, "not a class reference"); record = tag->name; rast = ast->r.ast; assert(rast->token == tok_symbol); symbol = rast->l.value; vector = symbol->name; if ((symbol = oget_symbol(record, vector)) == null) oparse_error(ast, "'%p' has no field named '%p'", record->name, vector); rast->l.value = symbol; return (symbol->tag); case tok_string: return (string_tag); case tok_ellipsis: return (varargs_tag); case tok_call: return (oeval_ast_tag(ast->l.ast)); default: oparse_error(ast, "not a type or symbol reference %A", ast); } }
static void eval_ast_typeof(oast_t *ast) { otype_t type; osymbol_t *symbol; ofunction_t *function; oeval_ast(ast->l.ast); switch (ast->l.ast->token) { case tok_number: type = otype(ast->l.ast->l.value); break; case tok_string: type = t_string; break; case tok_symbol: symbol = ast->l.ast->l.value; type = otag_to_type(symbol->tag); break; case tok_call: symbol = ast_call_symbol(ast->l.ast); function = symbol->value; type = otag_to_type(function->tag) & ~t_function; break; case tok_type: type = otag_to_type(ast->l.ast->l.value); break; default: return; } /* Return "normalized" type, not variable type, because * otherwise there would be inconsistencies with actual * runtime type information for "unsigned word" if it * does not fit in a "signed word", as well as being * simply tagged as "word" if moved to a vm register */ switch ((oword_t)type) { case t_undef: if (ast->l.ast->token != tok_type) return; type = t_void; break; case t_void: break; case t_int8: case t_uint8: case t_int16: case t_uint16: case t_int32: #if __WORDSIZE == 64 case t_uint32: case t_int64: #endif type = t_word; break; #if __WORDSIZE == 32 case t_uint32: case t_int64: #endif case t_uint64: if (ast->l.ast->token != tok_type) return; type = t_word; break; case t_float32: case t_float64: break; case t_vector|t_int8: case t_vector|t_uint8: case t_vector|t_int16: case t_vector|t_uint16: case t_vector|t_int32: case t_vector|t_uint32: case t_vector|t_int64: case t_vector|t_uint64: case t_vector|t_float32: case t_vector|t_float64: break; case t_vector|t_undef: type = t_vector; break; default: if (type > rtti_vector->offset) return; break; } odel_object(&ast->l.value); ast->token = tok_number; onew_word(&ast->l.value, type); }