1 #include <stdlib.h> /* calloc, exit, realloc */ 2 #include <unistd.h> /* read, write */ 3 #include <math.h> /* ceil, log10, pow */ 4 #include <string.h> /* strcmp, strncpy, strlen */ 5 #include <stdio.h> /* snprintf */ 6 #include "types.h" 7 #include "exceptions.h" 8 #include "ops.h" 9 #include "progconsts.h" 10 #include "progops.h" 11 #include "progtypes.h" 12 #include "main.h" 13 14 /* Utility functions. */ 15 16 inline __attr __new_int(int i) 17 { 18 /* Create a new integer and mutate the __data__ attribute. */ 19 __attr attr = __new(&__InstanceTable___builtins___int_int, &__builtins___int_int, sizeof(__obj___builtins___int_int)); 20 attr.value->attrs[__pos___data__].intvalue = i; 21 return attr; 22 } 23 24 inline __attr __new_str(char *s) 25 { 26 /* Create a new string and mutate the __data__ attribute. */ 27 __attr attr = __new(&__InstanceTable___builtins___str_string, &__builtins___str_string, sizeof(__obj___builtins___str_string)); 28 attr.value->attrs[__pos___data__].strvalue = s; 29 return attr; 30 } 31 32 /* Native functions. */ 33 34 __attr __fn_native__exit(__attr __args[]) 35 { 36 __attr * const status = &__args[1]; 37 38 exit(__load_via_object(status->value, __pos___data__).intvalue); 39 return __builtins___none_None; 40 } 41 42 __attr __fn_native__get_argv(__attr __args[]) 43 { 44 __attr * const status = &__args[1]; 45 46 /* NOTE: To be written. */ 47 return __builtins___none_None; 48 } 49 50 __attr __fn_native__get_path(__attr __args[]) 51 { 52 __attr * const status = &__args[1]; 53 54 /* NOTE: To be written. */ 55 return __builtins___none_None; 56 } 57 58 __attr __fn_native__is(__attr __args[]) 59 { 60 __attr * const x = &__args[1]; 61 __attr * const y = &__args[2]; 62 63 return x->value == y->value ? __builtins___boolean_True : __builtins___boolean_False; 64 } 65 66 __attr __fn_native__is_not(__attr __args[]) 67 { 68 __attr * const x = &__args[1]; 69 __attr * const y = &__args[2]; 70 71 return x->value != y->value ? __builtins___boolean_True : __builtins___boolean_False; 72 } 73 74 __attr __fn_native__int_add(__attr __args[]) 75 { 76 __attr * const self = &__args[1]; 77 __attr * const other = &__args[2]; 78 /* self.__data__ and other.__data__ interpreted as int */ 79 int i = __load_via_object(self->value, __pos___data__).intvalue; 80 int j = __load_via_object(other->value, __pos___data__).intvalue; 81 82 /* Return the new integer. */ 83 /* NOTE: No overflow test applied. */ 84 return __new_int(i + j); 85 } 86 87 __attr __fn_native__int_sub(__attr __args[]) 88 { 89 __attr * const self = &__args[1]; 90 __attr * const other = &__args[2]; 91 /* self.__data__ and other.__data__ interpreted as int */ 92 int i = __load_via_object(self->value, __pos___data__).intvalue; 93 int j = __load_via_object(other->value, __pos___data__).intvalue; 94 95 /* Return the new integer. */ 96 /* NOTE: No overflow test applied. */ 97 return __new_int(i - j); 98 } 99 100 __attr __fn_native__int_mul(__attr __args[]) 101 { 102 __attr * const self = &__args[1]; 103 __attr * const other = &__args[2]; 104 /* self.__data__ and other.__data__ interpreted as int */ 105 int i = __load_via_object(self->value, __pos___data__).intvalue; 106 int j = __load_via_object(other->value, __pos___data__).intvalue; 107 108 /* Return the new integer. */ 109 /* NOTE: No overflow test applied. */ 110 return __new_int(i * j); 111 } 112 113 __attr __fn_native__int_div(__attr __args[]) 114 { 115 __attr * const self = &__args[1]; 116 __attr * const other = &__args[2]; 117 /* self.__data__ and other.__data__ interpreted as int */ 118 int i = __load_via_object(self->value, __pos___data__).intvalue; 119 int j = __load_via_object(other->value, __pos___data__).intvalue; 120 121 /* Return the new integer. */ 122 /* NOTE: No overflow test applied. */ 123 return __new_int(i / j); 124 } 125 126 __attr __fn_native__int_mod(__attr __args[]) 127 { 128 __attr * const self = &__args[1]; 129 __attr * const other = &__args[2]; 130 /* self.__data__ and other.__data__ interpreted as int */ 131 int i = __load_via_object(self->value, __pos___data__).intvalue; 132 int j = __load_via_object(other->value, __pos___data__).intvalue; 133 134 /* Return the new integer. */ 135 /* NOTE: No overflow test applied. */ 136 return __new_int(i % j); 137 } 138 139 __attr __fn_native__int_neg(__attr __args[]) 140 { 141 __attr * const self = &__args[1]; 142 /* self.__data__ interpreted as int */ 143 int i = __load_via_object(self->value, __pos___data__).intvalue; 144 145 /* Return the new integer. */ 146 return __new_int(-i); 147 } 148 149 __attr __fn_native__int_pow(__attr __args[]) 150 { 151 __attr * const self = &__args[1]; 152 __attr * const other = &__args[2]; 153 /* self.__data__ and other.__data__ interpreted as int */ 154 int i = __load_via_object(self->value, __pos___data__).intvalue; 155 int j = __load_via_object(other->value, __pos___data__).intvalue; 156 157 /* Return the new integer. */ 158 /* NOTE: No overflow test applied. */ 159 return __new_int((int) pow(i, j)); 160 } 161 162 __attr __fn_native__int_and(__attr __args[]) 163 { 164 __attr * const self = &__args[1]; 165 __attr * const other = &__args[2]; 166 /* self.__data__ and other.__data__ interpreted as int */ 167 int i = __load_via_object(self->value, __pos___data__).intvalue; 168 int j = __load_via_object(other->value, __pos___data__).intvalue; 169 170 /* Return the new integer. */ 171 /* NOTE: No overflow test applied. */ 172 return __new_int(i & j); 173 } 174 175 __attr __fn_native__int_or(__attr __args[]) 176 { 177 __attr * const self = &__args[1]; 178 __attr * const other = &__args[2]; 179 /* self.__data__ and other.__data__ interpreted as int */ 180 int i = __load_via_object(self->value, __pos___data__).intvalue; 181 int j = __load_via_object(other->value, __pos___data__).intvalue; 182 183 /* Return the new integer. */ 184 /* NOTE: No overflow test applied. */ 185 return __new_int(i | j); 186 } 187 188 __attr __fn_native__int_xor(__attr __args[]) 189 { 190 __attr * const self = &__args[1]; 191 __attr * const other = &__args[2]; 192 /* self.__data__ and other.__data__ interpreted as int */ 193 int i = __load_via_object(self->value, __pos___data__).intvalue; 194 int j = __load_via_object(other->value, __pos___data__).intvalue; 195 196 /* Return the new integer. */ 197 /* NOTE: No overflow test applied. */ 198 return __new_int(i ^ j); 199 } 200 201 __attr __fn_native__int_lt(__attr __args[]) 202 { 203 __attr * const self = &__args[1]; 204 __attr * const other = &__args[2]; 205 /* self.__data__ and other.__data__ interpreted as int */ 206 int i = __load_via_object(self->value, __pos___data__).intvalue; 207 int j = __load_via_object(other->value, __pos___data__).intvalue; 208 209 /* Return a boolean result. */ 210 return i < j ? __builtins___boolean_True : __builtins___boolean_False; 211 } 212 213 __attr __fn_native__int_gt(__attr __args[]) 214 { 215 __attr * const self = &__args[1]; 216 __attr * const other = &__args[2]; 217 /* self.__data__ and other.__data__ interpreted as int */ 218 int i = __load_via_object(self->value, __pos___data__).intvalue; 219 int j = __load_via_object(other->value, __pos___data__).intvalue; 220 221 /* Return a boolean result. */ 222 return i > j ? __builtins___boolean_True : __builtins___boolean_False; 223 } 224 225 __attr __fn_native__int_eq(__attr __args[]) 226 { 227 __attr * const self = &__args[1]; 228 __attr * const other = &__args[2]; 229 /* self.__data__ and other.__data__ interpreted as int */ 230 int i = __load_via_object(self->value, __pos___data__).intvalue; 231 int j = __load_via_object(other->value, __pos___data__).intvalue; 232 233 /* Return a boolean result. */ 234 return i == j ? __builtins___boolean_True : __builtins___boolean_False; 235 } 236 237 __attr __fn_native__int_ne(__attr __args[]) 238 { 239 __attr * const self = &__args[1]; 240 __attr * const other = &__args[2]; 241 /* self.__data__ and other.__data__ interpreted as int */ 242 int i = __load_via_object(self->value, __pos___data__).intvalue; 243 int j = __load_via_object(other->value, __pos___data__).intvalue; 244 245 /* Return a boolean result. */ 246 return i != j ? __builtins___boolean_True : __builtins___boolean_False; 247 } 248 249 __attr __fn_native__int_str(__attr __args[]) 250 { 251 __attr * const self = &__args[1]; 252 /* self.__data__ interpreted as int */ 253 int i = __load_via_object(self->value, __pos___data__).intvalue; 254 int n = i != 0 ? (int) ceil(log10(i+1)) + 1 : 2; 255 char *s = calloc(n, sizeof(char)); 256 257 if (i < 0) n++; 258 snprintf(s, n, "%d", i); 259 260 /* Return a new string. */ 261 return __new_str(s); 262 } 263 264 __attr __fn_native__str_add(__attr __args[]) 265 { 266 __attr * const self = &__args[1]; 267 __attr * const other = &__args[2]; 268 /* self.__data__, other.__data__ interpreted as string */ 269 char *s = __load_via_object(self->value, __pos___data__).strvalue; 270 char *o = __load_via_object(other->value, __pos___data__).strvalue; 271 int n = strlen(s) + strlen(o) + 1; 272 char *r = calloc(n, sizeof(char)); 273 274 strncpy(r, s, n); 275 strncpy(r + strlen(s), o, n - strlen(s)); 276 277 /* Return a new string. */ 278 return __new_str(r); 279 } 280 281 __attr __fn_native__str_lt(__attr __args[]) 282 { 283 __attr * const self = &__args[1]; 284 __attr * const other = &__args[2]; 285 /* self.__data__, other.__data__ interpreted as string */ 286 char *s = __load_via_object(self->value, __pos___data__).strvalue; 287 char *o = __load_via_object(other->value, __pos___data__).strvalue; 288 289 /* NOTE: Using simple byte-level string operations. */ 290 return strcmp(s, o) < 0 ? __builtins___boolean_True : __builtins___boolean_False; 291 } 292 293 __attr __fn_native__str_gt(__attr __args[]) 294 { 295 __attr * const self = &__args[1]; 296 __attr * const other = &__args[2]; 297 /* self.__data__, other.__data__ interpreted as string */ 298 char *s = __load_via_object(self->value, __pos___data__).strvalue; 299 char *o = __load_via_object(other->value, __pos___data__).strvalue; 300 301 /* NOTE: Using simple byte-level string operations. */ 302 return strcmp(s, o) > 0 ? __builtins___boolean_True : __builtins___boolean_False; 303 } 304 305 __attr __fn_native__str_eq(__attr __args[]) 306 { 307 __attr * const self = &__args[1]; 308 __attr * const other = &__args[2]; 309 /* self.__data__, other.__data__ interpreted as string */ 310 char *s = __load_via_object(self->value, __pos___data__).strvalue; 311 char *o = __load_via_object(other->value, __pos___data__).strvalue; 312 313 /* NOTE: Using simple byte-level string operations. */ 314 return strcmp(s, o) == 0 ? __builtins___boolean_True : __builtins___boolean_False; 315 } 316 317 __attr __fn_native__str_len(__attr __args[]) 318 { 319 __attr * const self = &__args[1]; 320 /* self.__data__ interpreted as string */ 321 char *s = __load_via_object(self->value, __pos___data__).strvalue; 322 323 /* Return the new integer. */ 324 return __new_int(strlen(s)); 325 } 326 327 __attr __fn_native__str_nonempty(__attr __args[]) 328 { 329 __attr * const self = &__args[1]; 330 /* self.__data__ interpreted as string */ 331 char *s = __load_via_object(self->value, __pos___data__).strvalue; 332 333 return strlen(s) ? __builtins___boolean_True : __builtins___boolean_False; 334 } 335 336 __attr __fn_native__list_init(__attr __args[]) 337 { 338 __attr * const size = &__args[1]; 339 /* size.__data__ interpreted as int */ 340 unsigned int n = __load_via_object(size->value, __pos___data__).intvalue; 341 342 /* Allocate space for the list. */ 343 __fragment *data = calloc(1, __FRAGMENT_SIZE(n)); 344 __attr attr = {0, .data=data}; 345 346 /* The initial capacity is the same as the given size. */ 347 data->size = 0; 348 data->capacity = n; 349 return attr; 350 } 351 352 __attr __fn_native__list_setsize(__attr __args[]) 353 { 354 __attr * const self = &__args[1]; 355 __attr * const size = &__args[2]; 356 /* self.__data__ interpreted as list */ 357 __fragment *data = __load_via_object(self->value, __pos___data__).data; 358 /* size.__data__ interpreted as int */ 359 unsigned int n = __load_via_object(size->value, __pos___data__).intvalue; 360 361 data->size = n; 362 return __builtins___none_None; 363 } 364 365 __attr __fn_native__list_append(__attr __args[]) 366 { 367 __attr * const self = &__args[1]; 368 __attr * const value = &__args[2]; 369 /* self.__data__ interpreted as list */ 370 __fragment *data = __load_via_object(self->value, __pos___data__).data; 371 __fragment *newdata = data; 372 unsigned int size = data->size, capacity = data->capacity; 373 unsigned int n; 374 375 /* Re-allocate the fragment if the capacity has been reached. */ 376 if (size >= capacity) 377 { 378 /* NOTE: Consider various restrictions on capacity increases. */ 379 n = capacity ? capacity * 2 : 1; 380 newdata = realloc(data, __FRAGMENT_SIZE(n)); 381 newdata->capacity = n; 382 } 383 384 /* Insert the new element and increment the list size. */ 385 newdata->attrs[size] = *value; 386 newdata->size = size + 1; 387 388 /* Replace the __data__ attribute if appropriate. */ 389 if (newdata != data) 390 __store_via_object(self->value, __pos___data__, ((__attr) {0, .data=newdata})); 391 return __builtins___none_None; 392 } 393 394 __attr __fn_native__list_concat(__attr __args[]) 395 { 396 __attr * const self = &__args[1]; 397 __attr * const other = &__args[2]; 398 /* self.__data__, other.__data__ interpreted as list */ 399 __fragment *data = __load_via_object(self->value, __pos___data__).data; 400 __fragment *other_data = __load_via_object(other->value, __pos___data__).data; 401 __fragment *newdata = data; 402 unsigned int size = data->size, capacity = data->capacity; 403 unsigned int other_size = other_data->size; 404 unsigned int i, j, n; 405 406 /* Re-allocate the fragment if the capacity has been reached. */ 407 if (size + other_size >= capacity) 408 { 409 n = size + other_size; 410 newdata = realloc(data, __FRAGMENT_SIZE(n)); 411 newdata->capacity = n; 412 } 413 414 /* Copy the elements from the other list and increment the list size. */ 415 for (i = size, j = 0; j < other_size; i++, j++) 416 newdata->attrs[i] = other_data->attrs[j]; 417 newdata->size = n; 418 419 /* Replace the __data__ attribute if appropriate. */ 420 if (newdata != data) 421 __store_via_object(self->value, __pos___data__, ((__attr) {0, .data=newdata})); 422 return __builtins___none_None; 423 } 424 425 __attr __fn_native__list_len(__attr __args[]) 426 { 427 __attr * const self = &__args[1]; 428 /* self.__data__ interpreted as fragment */ 429 unsigned int size = __load_via_object(self->value, __pos___data__).data->size; 430 431 /* Return the new integer. */ 432 return __new_int(size); 433 } 434 435 __attr __fn_native__list_nonempty(__attr __args[]) 436 { 437 __attr * const self = &__args[1]; 438 439 return __load_via_object(self->value, __pos___data__).data->size ? __builtins___boolean_True : __builtins___boolean_False; 440 } 441 442 __attr __fn_native__list_element(__attr __args[]) 443 { 444 __attr * const self = &__args[1]; 445 __attr * const index = &__args[2]; 446 /* self.__data__ interpreted as fragment */ 447 __attr *elements = __load_via_object(self->value, __pos___data__).data->attrs; 448 /* index.__data__ interpreted as int */ 449 int i = __load_via_object(index->value, __pos___data__).intvalue; 450 451 return elements[i]; 452 } 453 454 __attr __fn_native__list_setelement(__attr __args[]) 455 { 456 __attr * const self = &__args[1]; 457 __attr * const index = &__args[2]; 458 __attr * const value = &__args[3]; 459 /* self.__data__ interpreted as fragment */ 460 __attr *elements = __load_via_object(self->value, __pos___data__).data->attrs; 461 /* index.__data__ interpreted as int */ 462 int i = __load_via_object(index->value, __pos___data__).intvalue; 463 464 /* Set the element. */ 465 elements[i] = *value; 466 return __builtins___none_None; 467 } 468 469 __attr __fn_native__buffer_str(__attr __args[]) 470 { 471 __attr * const self = &__args[1]; 472 /* self.__data__ interpreted as buffer */ 473 __fragment *data = __load_via_object(self->value, __pos___data__).data; 474 unsigned int size = 0, i, j, n; 475 char *s, *o; 476 477 /* Calculate the size of the string. */ 478 for (i = 0; i < data->size; i++) 479 size += strlen(data->attrs[i].strvalue); 480 481 /* Reserve space for a new string. */ 482 s = calloc(size + 1, sizeof(char)); 483 484 /* Build a single string from the buffer contents. */ 485 for (i = 0, j = 0; i < data->size; i++) 486 { 487 o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue; 488 n = strlen(o); 489 strncpy(s + j, o, n); 490 j += n; 491 } 492 493 /* Return a new string. */ 494 return __new_str(s); 495 } 496 497 __attr __fn_native__object_getattr(__attr __args[]) 498 { 499 __attr * const obj = &__args[1]; 500 __attr * const name = &__args[2]; 501 __attr * const _default = &__args[3]; 502 503 /* NOTE: To be written. */ 504 return __builtins___none_None; 505 } 506 507 __attr __fn_native__isinstance(__attr __args[]) 508 { 509 __attr * const obj = &__args[1]; 510 __attr * const cls = &__args[2]; 511 512 if (__is_instance(obj->value) && __HASATTR(__get_class(obj->value), __TYPEPOS(cls->value), __TYPECODE(cls->value))) 513 return __builtins___boolean_True; 514 else 515 return __builtins___boolean_False; 516 } 517 518 __attr __fn_native__read(__attr __args[]) 519 { 520 __attr * const fd = &__args[1]; 521 __attr * const n = &__args[2]; 522 523 /* NOTE: To be written. */ 524 return __builtins___none_None; 525 } 526 527 __attr __fn_native__write(__attr __args[]) 528 { 529 __attr * const fd = &__args[1]; 530 __attr * const str = &__args[2]; 531 /* fd.__data__ interpreted as int */ 532 int i = __load_via_object(fd->value, __pos___data__).intvalue; 533 /* str.__data__ interpreted as string */ 534 char *s = __load_via_object(str->value, __pos___data__).strvalue; 535 536 write(i, s, sizeof(char) * strlen(s)); 537 return __builtins___none_None; 538 } 539 540 /* Module initialisation. */ 541 542 void __main_native() 543 { 544 }