coerce.c (9294B)
1 #include "coerce.h" 2 3 /* 4 * Be aware that some value variants represents actual values (e.g. 5 * vt_int), and others represent a type (e.g. vt_scalar) which holds a 6 * type identifier token. Here we implicitly expect a vt_scalar type as 7 * first argument, but only receive the token. The second argument is a 8 * value literal. Our job is to decide if the value fits within the 9 * given type. Our internal representation already ensures that value 10 * fits within a 64bit signed or unsigned integer, or double; otherwise 11 * the parser would have set vt_invalid type on the value. 12 * 13 * If the value is invalid, success is returned because the 14 * error is presumably already generated. If the value is some other 15 * type than expect, an error is generated. 16 * 17 * Symbolic names are not allowed as values here. 18 * 19 * Converts positive integers to signed type and unsigned integers to 20 * signed type, integers to floats and floats to integers. 21 * 22 * Optionally allows 1 to be assigned as true and 0 as false, and vice 23 * versa when allow_boolean_conversion is enabled. 24 * 25 * Returns 0 on success, -1 on error. 26 */ 27 int fb_coerce_scalar_type(fb_parser_t *P, fb_symbol_t *sym, fb_scalar_type_t st, fb_value_t *value) 28 { 29 double d; 30 float f; 31 32 if (!value->type) { 33 return 0; 34 } 35 /* 36 * The parser only produces negative vt_int values, which simplifies 37 * the logic, but to make this operation robust against multiple 38 * coercion steps, we first convert back to uint if the assumption turns 39 * out false. 40 */ 41 if (value->type == vt_int && value->i >= 0) { 42 value->type = vt_uint; 43 value->u = (uint64_t)value->i; 44 } 45 if (value->type == vt_invalid) { 46 /* Silently ignore past errors. */ 47 return 0; 48 } 49 if (value->type == vt_bool && st != fb_bool && P->opts.allow_boolean_conversion) { 50 value->type = vt_uint; 51 value->u = (uint64_t)value->b; 52 assert(value->u == 1 || value->u == 0); 53 } 54 switch (st) { 55 case fb_ulong: 56 if (value->type != vt_uint) { 57 error_sym(P, sym, "64-bit uint32_t type only accepts unsigned integers"); 58 value->type = vt_invalid; 59 return -1; 60 } 61 return 0; 62 case fb_uint: 63 if (value->type != vt_uint) { 64 error_sym(P, sym, "32-bit unsigned int type only accepts unsigned integers"); 65 value->type = vt_invalid; 66 return -1; 67 } 68 if (value->u > UINT32_MAX) { 69 error_sym(P, sym, "32-bit unsigned int overflow"); 70 value->type = vt_invalid; 71 return -1; 72 } 73 return 0; 74 case fb_ushort: 75 if (value->type != vt_uint) { 76 error_sym(P, sym, "16-bit unsigned short type only accepts unsigned integers"); 77 value->type = vt_invalid; 78 return -1; 79 } 80 if (value->u > UINT16_MAX) { 81 error_sym(P, sym, "16-bit unsigned short overflow"); 82 value->type = vt_invalid; 83 return -1; 84 } 85 return 0; 86 case fb_char: 87 /* Although C treats char as signed by default, flatcc treats it as unsigned. */ 88 case fb_ubyte: 89 if (value->type != vt_uint) { 90 error_sym(P, sym, "8-bit unsigned byte type only accepts unsigned integers"); 91 value->type = vt_invalid; 92 return -1; 93 } 94 if (value->u > UINT8_MAX) { 95 error_sym(P, sym, "8-bit unsigned byte overflow"); 96 value->type = vt_invalid; 97 return -1; 98 } 99 return 0; 100 case fb_long: 101 if (value->type == vt_int) { 102 /* Native format is always ok, or parser would have failed. */ 103 return 0; 104 } 105 if (value->type == vt_uint) { 106 if (value->u >= (1ULL << 63)) { 107 error_sym(P, sym, "64-bit signed int32_t overflow"); 108 value->type = vt_invalid; 109 return -1; 110 } 111 value->i = (int64_t)value->u; 112 value->type = vt_int; 113 return 0; 114 } 115 error_sym(P, sym, "64-bit int32_t type only accepts integers"); 116 value->type = vt_invalid; 117 return -1; 118 case fb_int: 119 if (value->type == vt_int) { 120 if (value->i < INT32_MIN) { 121 error_sym(P, sym, "32-bit signed int underflow"); 122 value->type = vt_invalid; 123 return -1; 124 } 125 return 0; 126 } 127 if (value->type == vt_uint) { 128 if (value->i > INT32_MAX) { 129 error_sym(P, sym, "32-bit signed int overflow"); 130 value->type = vt_invalid; 131 return -1; 132 } 133 value->i = (int64_t)value->u; 134 value->type = vt_int; 135 return 0; 136 } 137 error_sym(P, sym, "32-bit signed int type only accepts integers"); 138 value->type = vt_invalid; 139 return -1; 140 case fb_short: 141 if (value->type == vt_int) { 142 if (value->i < INT16_MIN) { 143 error_sym(P, sym, "16-bit signed short underflow"); 144 value->type = vt_invalid; 145 return -1; 146 } 147 return 0; 148 } 149 if (value->type == vt_uint) { 150 if (value->i > INT16_MAX) { 151 error_sym(P, sym, "16-bit signed short overflow"); 152 value->type = vt_invalid; 153 return -1; 154 } 155 value->i = (int64_t)value->u; 156 value->type = vt_int; 157 return 0; 158 } 159 error_sym(P, sym, "16-bit signed short type only accepts integers"); 160 value->type = vt_invalid; 161 return -1; 162 case fb_byte: 163 if (value->type == vt_int) { 164 if (value->i < INT8_MIN) { 165 error_sym(P, sym, "8-bit signed byte underflow"); 166 value->type = vt_invalid; 167 return -1; 168 } 169 return 0; 170 } 171 if (value->type == vt_uint) { 172 if (value->i > INT8_MAX) { 173 error_sym(P, sym, "8-bit signed byte overflow"); 174 value->type = vt_invalid; 175 return -1; 176 } 177 value->i = (int64_t)value->u; 178 value->type = vt_int; 179 return 0; 180 } 181 error_sym(P, sym, "8-bit signed byte type only accepts integers"); 182 value->type = vt_invalid; 183 return -1; 184 case fb_bool: 185 if (value->type == vt_uint && P->opts.allow_boolean_conversion) { 186 if (value->u > 1) { 187 error_sym(P, sym, "boolean integer conversion only accepts 0 (false) or 1 (true)"); 188 value->type = vt_invalid; 189 return -1; 190 } 191 } else if (value->type != vt_bool) { 192 error_sym(P, sym, "boolean type only accepts 'true' or 'false' as values"); 193 value->type = vt_invalid; 194 return -1; 195 } 196 return 0; 197 case fb_double: 198 switch (value->type) { 199 case vt_int: 200 d = (double)value->i; 201 if ((int64_t)d != value->i) { 202 /* We could make this a warning. */ 203 error_sym(P, sym, "precision loss in 64-bit double type assignment"); 204 value->type = vt_invalid; 205 return -1; 206 } 207 value->f = d; 208 value->type = vt_float; 209 return 0; 210 case vt_uint: 211 d = (double)value->u; 212 if ((uint64_t)d != value->u) { 213 /* We could make this a warning. */ 214 error_sym(P, sym, "precision loss in 64-bit double type assignment"); 215 value->type = vt_invalid; 216 return -1; 217 } 218 value->f = d; 219 value->type = vt_float; 220 return 0; 221 case vt_float: 222 /* Double is our internal repr., so not loss at this point. */ 223 return 0; 224 default: 225 error_sym(P, sym, "64-bit double type only accepts integer and float values"); 226 value->type = vt_invalid; 227 return -1; 228 } 229 case fb_float: 230 switch (value->type) { 231 case vt_int: 232 f = (float)value->i; 233 if ((int64_t)f != value->i) { 234 /* We could make this a warning. */ 235 error_sym(P, sym, "precision loss in 32-bit float type assignment"); 236 value->type = vt_invalid; 237 return -1; 238 } 239 value->f = f; 240 value->type = vt_float; 241 return 0; 242 case vt_uint: 243 f = (float)value->u; 244 if ((uint64_t)f != value->u) { 245 /* We could make this a warning. */ 246 error_sym(P, sym, "precision loss in 32-bit float type assignment"); 247 value->type = vt_invalid; 248 return -1; 249 } 250 value->f = f; 251 value->type = vt_float; 252 return 0; 253 case vt_float: 254 return 0; 255 default: 256 error_sym(P, sym, "32-bit float type only accepts integer and float values"); 257 value->type = vt_invalid; 258 return -1; 259 } 260 default: 261 error_sym(P, sym, "scalar type expected"); 262 value->type = vt_invalid; 263 return -1; 264 } 265 } 266