inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { switch (get_common_type(t_lhs)) { case Common_Types::t_int32: return oper_rhs<int32_t>(t_oper, t_lhs, t_rhs); case Common_Types::t_uint8: return oper_rhs<uint8_t>(t_oper, t_lhs, t_rhs); case Common_Types::t_int8: return oper_rhs<int8_t>(t_oper, t_lhs, t_rhs); case Common_Types::t_uint16: return oper_rhs<uint16_t>(t_oper, t_lhs, t_rhs); case Common_Types::t_int16: return oper_rhs<int16_t>(t_oper, t_lhs, t_rhs); case Common_Types::t_uint32: return oper_rhs<uint32_t>(t_oper, t_lhs, t_rhs); case Common_Types::t_uint64: return oper_rhs<uint64_t>(t_oper, t_lhs, t_rhs); case Common_Types::t_int64: return oper_rhs<int64_t>(t_oper, t_lhs, t_rhs); case Common_Types::t_double: return oper_rhs<double>(t_oper, t_lhs, t_rhs); case Common_Types::t_float: return oper_rhs<float>(t_oper, t_lhs, t_rhs); case Common_Types::t_long_double: return oper_rhs<long double>(t_oper, t_lhs, t_rhs); } throw chaiscript::detail::exception::bad_any_cast(); }
static int parse_complete(token_t *tok) { unsigned int t0; _cffi_opcode_t t1; int modifiers_length, modifiers_sign; qualifiers: switch (tok->kind) { case TOK_CONST: /* ignored for now */ next_token(tok); goto qualifiers; case TOK_VOLATILE: /* ignored for now */ next_token(tok); goto qualifiers; default: ; } modifiers_length = 0; modifiers_sign = 0; modifiers: switch (tok->kind) { case TOK_SHORT: if (modifiers_length != 0) return parse_error(tok, "'short' after another 'short' or 'long'"); modifiers_length--; next_token(tok); goto modifiers; case TOK_LONG: if (modifiers_length < 0) return parse_error(tok, "'long' after 'short'"); if (modifiers_length >= 2) return parse_error(tok, "'long long long' is too long"); modifiers_length++; next_token(tok); goto modifiers; case TOK_SIGNED: if (modifiers_sign) return parse_error(tok, "multiple 'signed' or 'unsigned'"); modifiers_sign++; next_token(tok); goto modifiers; case TOK_UNSIGNED: if (modifiers_sign) return parse_error(tok, "multiple 'signed' or 'unsigned'"); modifiers_sign--; next_token(tok); goto modifiers; default: break; } if (modifiers_length || modifiers_sign) { switch (tok->kind) { case TOK_VOID: case TOK__BOOL: case TOK_FLOAT: case TOK_STRUCT: case TOK_UNION: case TOK_ENUM: return parse_error(tok, "invalid combination of types"); case TOK_DOUBLE: if (modifiers_sign != 0 || modifiers_length != 1) return parse_error(tok, "invalid combination of types"); next_token(tok); t0 = _CFFI_PRIM_LONGDOUBLE; break; case TOK_CHAR: if (modifiers_length != 0) return parse_error(tok, "invalid combination of types"); modifiers_length = -2; /* fall-through */ case TOK_INT: next_token(tok); /* fall-through */ default: if (modifiers_sign >= 0) switch (modifiers_length) { case -2: t0 = _CFFI_PRIM_SCHAR; break; case -1: t0 = _CFFI_PRIM_SHORT; break; case 1: t0 = _CFFI_PRIM_LONG; break; case 2: t0 = _CFFI_PRIM_LONGLONG; break; default: t0 = _CFFI_PRIM_INT; break; } else switch (modifiers_length) { case -2: t0 = _CFFI_PRIM_UCHAR; break; case -1: t0 = _CFFI_PRIM_USHORT; break; case 1: t0 = _CFFI_PRIM_ULONG; break; case 2: t0 = _CFFI_PRIM_ULONGLONG; break; default: t0 = _CFFI_PRIM_UINT; break; } } t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, t0); } else { switch (tok->kind) { case TOK_INT: t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_INT); break; case TOK_CHAR: t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_CHAR); break; case TOK_VOID: t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_VOID); break; case TOK__BOOL: t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_BOOL); break; case TOK_FLOAT: t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_FLOAT); break; case TOK_DOUBLE: t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_DOUBLE); break; case TOK_IDENTIFIER: { const char *replacement; int n = search_in_typenames(tok->info->ctx, tok->p, tok->size); if (n >= 0) { t1 = _CFFI_OP(_CFFI_OP_TYPENAME, n); break; } n = search_standard_typename(tok->p, tok->size); if (n >= 0) { t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, n); break; } replacement = get_common_type(tok->p, tok->size); if (replacement != NULL) { n = parse_common_type_replacement(tok, replacement); if (n < 0) return parse_error(tok, "internal error, please report!"); t1 = _CFFI_OP(_CFFI_OP_NOOP, n); break; } return parse_error(tok, "undefined type name"); } case TOK_STRUCT: case TOK_UNION: { int n, kind = tok->kind; next_token(tok); if (tok->kind != TOK_IDENTIFIER) return parse_error(tok, "struct or union name expected"); n = search_in_struct_unions(tok->info->ctx, tok->p, tok->size); if (n < 0) { if (kind == TOK_STRUCT && tok->size == 8 && !memcmp(tok->p, "_IO_FILE", 8)) n = _CFFI__IO_FILE_STRUCT; else return parse_error(tok, "undefined struct/union name"); } else if (((tok->info->ctx->struct_unions[n].flags & _CFFI_F_UNION) != 0) ^ (kind == TOK_UNION)) return parse_error(tok, "wrong kind of tag: struct vs union"); t1 = _CFFI_OP(_CFFI_OP_STRUCT_UNION, n); break; } case TOK_ENUM: { int n; next_token(tok); if (tok->kind != TOK_IDENTIFIER) return parse_error(tok, "enum name expected"); n = search_in_enums(tok->info->ctx, tok->p, tok->size); if (n < 0) return parse_error(tok, "undefined enum name"); t1 = _CFFI_OP(_CFFI_OP_ENUM, n); break; } default: return parse_error(tok, "identifier expected"); } next_token(tok); } return parse_sequel(tok, write_ds(tok, t1)); }
static Common_Types get_common_type(const Boxed_Value &t_bv) { const Type_Info &inp_ = t_bv.get_type_info(); if (inp_ == typeid(int)) { return get_common_type(sizeof(int), true); } else if (inp_ == typeid(double)) { return Common_Types::t_double; } else if (inp_ == typeid(long double)) { return Common_Types::t_long_double; } else if (inp_ == typeid(float)) { return Common_Types::t_float; } else if (inp_ == typeid(char)) { return get_common_type(sizeof(char), std::is_signed<char>::value); } else if (inp_ == typeid(unsigned char)) { return get_common_type(sizeof(unsigned char), false); } else if (inp_ == typeid(unsigned int)) { return get_common_type(sizeof(unsigned int), false); } else if (inp_ == typeid(long)) { return get_common_type(sizeof(long), true); } else if (inp_ == typeid(long long)) { return get_common_type(sizeof(long long), true); } else if (inp_ == typeid(unsigned long)) { return get_common_type(sizeof(unsigned long), false); } else if (inp_ == typeid(unsigned long long)) { return get_common_type(sizeof(unsigned long long), false); } else if (inp_ == typeid(std::int8_t)) { return Common_Types::t_int8; } else if (inp_ == typeid(std::int16_t)) { return Common_Types::t_int16; } else if (inp_ == typeid(std::int32_t)) { return Common_Types::t_int32; } else if (inp_ == typeid(std::int64_t)) { return Common_Types::t_int64; } else if (inp_ == typeid(std::uint8_t)) { return Common_Types::t_uint8; } else if (inp_ == typeid(std::uint16_t)) { return Common_Types::t_uint16; } else if (inp_ == typeid(std::uint32_t)) { return Common_Types::t_uint32; } else if (inp_ == typeid(std::uint64_t)) { return Common_Types::t_uint64; } else if (inp_ == typeid(wchar_t)) { return get_common_type(sizeof(wchar_t), std::is_signed<wchar_t>::value); } else if (inp_ == typeid(char16_t)) { return get_common_type(sizeof(char16_t), std::is_signed<char16_t>::value); } else if (inp_ == typeid(char32_t)) { return get_common_type(sizeof(char32_t), std::is_signed<char32_t>::value); } else { throw chaiscript::detail::exception::bad_any_cast(); } }
/*-------------------------------------------------------------------------*/ static lpctype_t * internal_get_common_type(lpctype_t *t1, lpctype_t* t2, bool find_one) /* Determine the intersection of both types. * Returns NULL if there is no common type. * If one of both types is TYPE_UNKNOWN, then * the result will by TYPE_UNKNOWN, too. * * If <find_one> is true, then it may finish even if only a part * of the result type was found (used for has_common_type()). */ { /* Hopefully the most common case. */ if (t1 && t1 == t2) return ref_lpctype(t1); /* We can't return NULL, as this is an error condition. */ if (t1 == NULL && t2 == NULL) return lpctype_mixed; else if (t1 == NULL) return ref_lpctype(t2); else if (t2 == NULL) return ref_lpctype(t1); if (t2->t_class == TCLASS_UNION && t1->t_class != TCLASS_UNION) { /* Switch them, so t2 is not a union unless t1 is one, too. */ lpctype_t *temp; temp = t1; t1 = t2; t2 = temp; } /* Some shortcuts, before we're diving into t1.*/ if (t2->t_class == TCLASS_PRIMARY) { switch (t2->t_primary) { case TYPE_UNKNOWN: return ref_lpctype(t2); case TYPE_ANY: return ref_lpctype(t1); default: break; } } switch (t1->t_class) { case TCLASS_PRIMARY: switch (t1->t_primary) { case TYPE_UNKNOWN: return ref_lpctype(t1); case TYPE_ANY: return ref_lpctype(t2); default: /* Primary types besides the above exceptions should be identical (checked at the beginning of this function). */ return NULL; } case TCLASS_STRUCT: if (t2->t_class != TCLASS_STRUCT) return NULL; else if (t1->t_struct == NULL) return ref_lpctype(t2); else if (t2->t_struct == NULL) return ref_lpctype(t1); /* This is somewhat counterintuitive, but the derived struct is more specialized, so it is the result of the intersection. */ else if (struct_baseof(t1->t_struct, t2->t_struct)) return ref_lpctype(t2); else if (struct_baseof(t2->t_struct, t1->t_struct)) return ref_lpctype(t1); else return NULL; case TCLASS_ARRAY: if (t2->t_class != TCLASS_ARRAY) return NULL; else { lpctype_t *common_element = get_common_type(t1->t_array.element, t2->t_array.element); lpctype_t *result = get_array_type(common_element); free_lpctype(common_element); return result; } case TCLASS_UNION: { lpctype_t *result = NULL; while (true) { lpctype_t *base = t1->t_class == TCLASS_UNION ? t1->t_union.member : t1; lpctype_t *common_base = get_common_type(t2, base); lpctype_t *oldresult = result; if (find_one && common_base) return common_base; result = get_union_type(result, common_base); free_lpctype(common_base); free_lpctype(oldresult); if (t1->t_class == TCLASS_UNION) t1 = t1->t_union.head; else break; } return result; } default: fatal("Unknown type class %d!\n", t1->t_class); return NULL; } } /* internal_get_common_type() */