1 #include <stdlib.h> /* abs, exit */ 2 #include <unistd.h> /* read, write */ 3 #include <limits.h> /* INT_MAX, INT_MIN */ 4 #include <math.h> /* ceil, log10, pow */ 5 #include <string.h> /* strcmp, strncpy, strlen */ 6 #include <stdio.h> /* snprintf */ 7 #include <errno.h> /* errno */ 8 #include "types.h" 9 #include "exceptions.h" 10 #include "ops.h" 11 #include "progconsts.h" 12 #include "progops.h" 13 #include "progtypes.h" 14 #include "main.h" 15 16 /* Utility functions. */ 17 18 static __attr __new_int(int i) 19 { 20 /* Create a new integer and mutate the __data__ attribute. */ 21 __attr attr = __new(&__InstanceTable___builtins___int_int, &__builtins___int_int, sizeof(__obj___builtins___int_int)); 22 attr.value->attrs[__pos___data__].intvalue = i; 23 return attr; 24 } 25 26 static __attr __new_str(char *s) 27 { 28 /* Create a new string and mutate the __data__ attribute. */ 29 __attr attr = __new(&__InstanceTable___builtins___str_string, &__builtins___str_string, sizeof(__obj___builtins___str_string)); 30 attr.value->attrs[__pos___data__].strvalue = s; 31 return attr; 32 } 33 34 static __attr __new_list(__fragment *f) 35 { 36 /* Create a new list and mutate the __data__ attribute. */ 37 __attr attr = __new(&__InstanceTable___builtins___list_list, &__builtins___list_list, sizeof(__obj___builtins___list_list)); 38 attr.value->attrs[__pos___data__].seqvalue = f; 39 return attr; 40 } 41 42 static __fragment *__fragment_append(__fragment *data, __attr * const value) 43 { 44 __fragment *newdata = data; 45 unsigned int size = data->size, capacity = data->capacity; 46 unsigned int n; 47 48 /* Re-allocate the fragment if the capacity has been reached. */ 49 if (size >= capacity) 50 { 51 /* NOTE: Consider various restrictions on capacity increases. */ 52 n = capacity ? capacity * 2 : 1; 53 newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n)); 54 newdata->capacity = n; 55 } 56 57 /* Insert the new element and increment the list size. */ 58 newdata->attrs[size] = *value; 59 newdata->size = size + 1; 60 61 return newdata; 62 } 63 64 /* Native functions. */ 65 66 __attr __fn_native__exit(__attr __args[]) 67 { 68 __attr * const status = &__args[1]; 69 70 exit(__load_via_object(status->value, __pos___data__).intvalue); 71 return __builtins___none_None; 72 } 73 74 __attr __fn_native__get_argv(__attr __args[]) 75 { 76 __attr * const status = &__args[1]; 77 78 /* NOTE: To be written. */ 79 return __builtins___none_None; 80 } 81 82 __attr __fn_native__get_path(__attr __args[]) 83 { 84 __attr * const status = &__args[1]; 85 86 /* NOTE: To be written. */ 87 return __builtins___none_None; 88 } 89 90 __attr __fn_native__is(__attr __args[]) 91 { 92 __attr * const x = &__args[1]; 93 __attr * const y = &__args[2]; 94 95 return x->value == y->value ? __builtins___boolean_True : __builtins___boolean_False; 96 } 97 98 __attr __fn_native__is_not(__attr __args[]) 99 { 100 __attr * const x = &__args[1]; 101 __attr * const y = &__args[2]; 102 103 return x->value != y->value ? __builtins___boolean_True : __builtins___boolean_False; 104 } 105 106 __attr __fn_native__get_maxint(__attr __args[]) 107 { 108 __attr * const status = &__args[1]; 109 110 return __new_int(INT_MAX); 111 } 112 113 __attr __fn_native__get_minint(__attr __args[]) 114 { 115 __attr * const status = &__args[1]; 116 117 return __new_int(INT_MIN); 118 } 119 120 __attr __fn_native__int_add(__attr __args[]) 121 { 122 __attr * const _data = &__args[1]; 123 __attr * const other = &__args[2]; 124 /* _data and other interpreted as int */ 125 int i = _data->intvalue; 126 int j = other->intvalue; 127 128 /* Test for overflow. */ 129 if (((i > 0) && (j > 0) && (i > INT_MAX - j)) || 130 ((i < 0) && (j < 0) && (i < INT_MIN - j))) 131 132 __raise_overflow_error(); 133 134 /* Return the new integer. */ 135 return __new_int(i + j); 136 } 137 138 __attr __fn_native__int_sub(__attr __args[]) 139 { 140 __attr * const _data = &__args[1]; 141 __attr * const other = &__args[2]; 142 /* _data and other interpreted as int */ 143 int i = _data->intvalue; 144 int j = other->intvalue; 145 146 /* Test for overflow. */ 147 if (((i < 0) && (j > 0) && (i < INT_MIN + j)) || 148 ((i > 0) && (j < 0) && (i > INT_MAX + j))) 149 150 __raise_overflow_error(); 151 152 /* Return the new integer. */ 153 return __new_int(i - j); 154 } 155 156 __attr __fn_native__int_mul(__attr __args[]) 157 { 158 __attr * const _data = &__args[1]; 159 __attr * const other = &__args[2]; 160 /* _data and other interpreted as int */ 161 int i = _data->intvalue; 162 int j = other->intvalue; 163 164 /* Test for overflow. */ 165 if (((i > 0) && (j > 0) && (i > INT_MAX / j)) || 166 ((i < 0) && (j < 0) && (i > INT_MAX / j)) || 167 ((i < 0) && (j > 0) && (i < INT_MIN / j)) || 168 ((i > 0) && (j < 0) && (j < INT_MIN / i))) 169 170 __raise_overflow_error(); 171 172 /* Return the new integer. */ 173 return __new_int(i * j); 174 } 175 176 __attr __fn_native__int_div(__attr __args[]) 177 { 178 __attr * const _data = &__args[1]; 179 __attr * const other = &__args[2]; 180 /* _data and other interpreted as int */ 181 int i = _data->intvalue; 182 int j = other->intvalue; 183 184 /* Test for division by zero or overflow. */ 185 if (j == 0) 186 __raise_zero_division_error(); 187 else if ((j == -1) && (i == INT_MIN)) 188 __raise_overflow_error(); 189 190 /* Return the new integer. */ 191 return __new_int(i / j); 192 } 193 194 __attr __fn_native__int_mod(__attr __args[]) 195 { 196 __attr * const _data = &__args[1]; 197 __attr * const other = &__args[2]; 198 /* _data and other interpreted as int */ 199 int i = _data->intvalue; 200 int j = other->intvalue; 201 202 /* Test for division by zero or overflow. */ 203 if (j == 0) 204 __raise_zero_division_error(); 205 else if ((j == -1) && (i == INT_MIN)) 206 __raise_overflow_error(); 207 208 /* Return the new integer. */ 209 return __new_int(i % j); 210 } 211 212 __attr __fn_native__int_neg(__attr __args[]) 213 { 214 __attr * const _data = &__args[1]; 215 /* _data interpreted as int */ 216 int i = _data->intvalue; 217 218 /* Test for overflow. */ 219 if (i == INT_MIN) 220 __raise_overflow_error(); 221 222 /* Return the new integer. */ 223 return __new_int(-i); 224 } 225 226 __attr __fn_native__int_pow(__attr __args[]) 227 { 228 __attr * const _data = &__args[1]; 229 __attr * const other = &__args[2]; 230 /* _data and other interpreted as int */ 231 int i = _data->intvalue; 232 int j = other->intvalue; 233 int k; 234 235 errno = 0; 236 k = (int) pow(i, j); 237 238 /* Test for overflow. */ 239 240 if (errno == ERANGE) 241 __raise_overflow_error(); 242 243 /* Return the new integer. */ 244 return __new_int(k); 245 } 246 247 __attr __fn_native__int_and(__attr __args[]) 248 { 249 __attr * const _data = &__args[1]; 250 __attr * const other = &__args[2]; 251 /* _data and other interpreted as int */ 252 int i = _data->intvalue; 253 int j = other->intvalue; 254 255 /* Return the new integer. */ 256 /* NOTE: No overflow test applied. */ 257 return __new_int(i & j); 258 } 259 260 __attr __fn_native__int_not(__attr __args[]) 261 { 262 __attr * const _data = &__args[1]; 263 /* _data interpreted as int */ 264 int i = _data->intvalue; 265 266 /* Return the new integer. */ 267 return __new_int(~i); 268 } 269 270 __attr __fn_native__int_or(__attr __args[]) 271 { 272 __attr * const _data = &__args[1]; 273 __attr * const other = &__args[2]; 274 /* _data and other interpreted as int */ 275 int i = _data->intvalue; 276 int j = other->intvalue; 277 278 /* Return the new integer. */ 279 /* NOTE: No overflow test applied. */ 280 return __new_int(i | j); 281 } 282 283 __attr __fn_native__int_xor(__attr __args[]) 284 { 285 __attr * const _data = &__args[1]; 286 __attr * const other = &__args[2]; 287 /* _data and other interpreted as int */ 288 int i = _data->intvalue; 289 int j = other->intvalue; 290 291 /* Return the new integer. */ 292 /* NOTE: No overflow test applied. */ 293 return __new_int(i ^ j); 294 } 295 296 __attr __fn_native__int_lt(__attr __args[]) 297 { 298 __attr * const _data = &__args[1]; 299 __attr * const other = &__args[2]; 300 /* _data and other interpreted as int */ 301 int i = _data->intvalue; 302 int j = other->intvalue; 303 304 /* Return a boolean result. */ 305 return i < j ? __builtins___boolean_True : __builtins___boolean_False; 306 } 307 308 __attr __fn_native__int_gt(__attr __args[]) 309 { 310 __attr * const _data = &__args[1]; 311 __attr * const other = &__args[2]; 312 /* _data and other interpreted as int */ 313 int i = _data->intvalue; 314 int j = other->intvalue; 315 316 /* Return a boolean result. */ 317 return i > j ? __builtins___boolean_True : __builtins___boolean_False; 318 } 319 320 __attr __fn_native__int_eq(__attr __args[]) 321 { 322 __attr * const _data = &__args[1]; 323 __attr * const other = &__args[2]; 324 /* _data and other interpreted as int */ 325 int i = _data->intvalue; 326 int j = other->intvalue; 327 328 /* Return a boolean result. */ 329 return i == j ? __builtins___boolean_True : __builtins___boolean_False; 330 } 331 332 __attr __fn_native__int_ne(__attr __args[]) 333 { 334 __attr * const _data = &__args[1]; 335 __attr * const other = &__args[2]; 336 /* _data and other interpreted as int */ 337 int i = _data->intvalue; 338 int j = other->intvalue; 339 340 /* Return a boolean result. */ 341 return i != j ? __builtins___boolean_True : __builtins___boolean_False; 342 } 343 344 __attr __fn_native__int_str(__attr __args[]) 345 { 346 __attr * const _data = &__args[1]; 347 /* _data interpreted as int */ 348 int i = _data->intvalue; 349 /* Employ a buffer big enough to fit the largest integer plus an extra 350 character, a minus sign, and the null terminator. */ 351 unsigned int n = (int) log10(INT_MAX) + 3; 352 char *s = (char *) __ALLOCATE(n, sizeof(char)); 353 354 snprintf(s, n, "%d", i); 355 356 /* Return a new string. */ 357 return __new_str(s); 358 } 359 360 __attr __fn_native__str_add(__attr __args[]) 361 { 362 __attr * const _data = &__args[1]; 363 __attr * const other = &__args[2]; 364 /* _data, other interpreted as string */ 365 char *s = _data->strvalue; 366 char *o = other->strvalue; 367 int n = strlen(s) + strlen(o) + 1; 368 char *r = (char *) __ALLOCATE(n, sizeof(char)); 369 370 strncpy(r, s, n); 371 strncpy(r + strlen(s), o, n - strlen(s)); /* should null terminate */ 372 373 /* Return a new string. */ 374 return __new_str(r); 375 } 376 377 __attr __fn_native__str_lt(__attr __args[]) 378 { 379 __attr * const _data = &__args[1]; 380 __attr * const other = &__args[2]; 381 /* _data, other interpreted as string */ 382 char *s = _data->strvalue; 383 char *o = other->strvalue; 384 385 /* NOTE: Using simple byte-level string operations. */ 386 return strcmp(s, o) < 0 ? __builtins___boolean_True : __builtins___boolean_False; 387 } 388 389 __attr __fn_native__str_gt(__attr __args[]) 390 { 391 __attr * const _data = &__args[1]; 392 __attr * const other = &__args[2]; 393 /* _data, other interpreted as string */ 394 char *s = _data->strvalue; 395 char *o = other->strvalue; 396 397 /* NOTE: Using simple byte-level string operations. */ 398 return strcmp(s, o) > 0 ? __builtins___boolean_True : __builtins___boolean_False; 399 } 400 401 __attr __fn_native__str_eq(__attr __args[]) 402 { 403 __attr * const _data = &__args[1]; 404 __attr * const other = &__args[2]; 405 /* _data, other interpreted as string */ 406 char *s = _data->strvalue; 407 char *o = other->strvalue; 408 409 /* NOTE: Using simple byte-level string operations. */ 410 return strcmp(s, o) == 0 ? __builtins___boolean_True : __builtins___boolean_False; 411 } 412 413 __attr __fn_native__str_len(__attr __args[]) 414 { 415 __attr * const _data = &__args[1]; 416 /* _data interpreted as string */ 417 char *s = _data->strvalue; 418 419 /* Return the new integer. */ 420 return __new_int(strlen(s)); 421 } 422 423 __attr __fn_native__str_nonempty(__attr __args[]) 424 { 425 __attr * const _data = &__args[1]; 426 /* _data interpreted as string */ 427 char *s = _data->strvalue; 428 429 return strlen(s) ? __builtins___boolean_True : __builtins___boolean_False; 430 } 431 432 __attr __fn_native__str_ord(__attr __args[]) 433 { 434 __attr * const _data = &__args[1]; 435 /* _data interpreted as string */ 436 char *s = _data->strvalue; 437 438 return __new_int((unsigned int) s[0]); 439 } 440 441 __attr __fn_native__str_substr(__attr __args[]) 442 { 443 __attr * const _data = &__args[1]; 444 __attr * const start = &__args[2]; 445 __attr * const size = &__args[3]; 446 /* _data interpreted as string */ 447 char *s = _data->strvalue, *sub; 448 /* start.__data__ interpreted as int */ 449 int i = __load_via_object(start->value, __pos___data__).intvalue; 450 /* size.__data__ interpreted as int */ 451 int l = __load_via_object(size->value, __pos___data__).intvalue; 452 453 /* Reserve space for a new string. */ 454 sub = (char *) __ALLOCATE(l + 1, sizeof(char)); 455 strncpy(sub, s + i, l); /* does not null terminate but final byte should be zero */ 456 return __new_str(sub); 457 } 458 459 __attr __fn_native__list_init(__attr __args[]) 460 { 461 __attr * const size = &__args[1]; 462 /* size.__data__ interpreted as int */ 463 unsigned int n = __load_via_object(size->value, __pos___data__).intvalue; 464 __attr attr = {0, .seqvalue=__new_fragment(n)}; 465 466 /* Return the __data__ attribute. */ 467 return attr; 468 } 469 470 __attr __fn_native__list_setsize(__attr __args[]) 471 { 472 __attr * const _data = &__args[1]; 473 __attr * const size = &__args[2]; 474 /* _data interpreted as list */ 475 __fragment *data = _data->seqvalue; 476 /* size.__data__ interpreted as int */ 477 unsigned int n = __load_via_object(size->value, __pos___data__).intvalue; 478 479 data->size = n; 480 return __builtins___none_None; 481 } 482 483 __attr __fn_native__list_append(__attr __args[]) 484 { 485 __attr * const self = &__args[1]; 486 __attr * const value = &__args[2]; 487 /* self.__data__ interpreted as list */ 488 __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue; 489 __fragment *newdata = __fragment_append(data, value); 490 491 /* Replace the __data__ attribute if appropriate. */ 492 if (newdata != data) 493 __store_via_object(self->value, __pos___data__, ((__attr) {0, .seqvalue=newdata})); 494 return __builtins___none_None; 495 } 496 497 __attr __fn_native__list_concat(__attr __args[]) 498 { 499 __attr * const self = &__args[1]; 500 __attr * const other = &__args[2]; 501 /* self.__data__, other interpreted as list */ 502 __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue; 503 __fragment *other_data = other->seqvalue; 504 __fragment *newdata = data; 505 unsigned int size = data->size, capacity = data->capacity; 506 unsigned int other_size = other_data->size; 507 unsigned int i, j, n; 508 509 /* Re-allocate the fragment if the capacity has been reached. */ 510 if (size + other_size >= capacity) 511 { 512 n = size + other_size; 513 newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n)); 514 newdata->capacity = n; 515 } 516 517 /* Copy the elements from the other list and increment the list size. */ 518 for (i = size, j = 0; j < other_size; i++, j++) 519 newdata->attrs[i] = other_data->attrs[j]; 520 newdata->size = n; 521 522 /* Replace the __data__ attribute if appropriate. */ 523 if (newdata != data) 524 __store_via_object(self->value, __pos___data__, ((__attr) {0, .seqvalue=newdata})); 525 return __builtins___none_None; 526 } 527 528 __attr __fn_native__list_len(__attr __args[]) 529 { 530 __attr * const _data = &__args[1]; 531 /* _data interpreted as fragment */ 532 unsigned int size = _data->seqvalue->size; 533 534 /* Return the new integer. */ 535 return __new_int(size); 536 } 537 538 __attr __fn_native__list_nonempty(__attr __args[]) 539 { 540 __attr * const _data = &__args[1]; 541 542 return _data->seqvalue->size ? __builtins___boolean_True : __builtins___boolean_False; 543 } 544 545 __attr __fn_native__list_element(__attr __args[]) 546 { 547 __attr * const _data = &__args[1]; 548 __attr * const index = &__args[2]; 549 /* _data interpreted as fragment */ 550 __attr *elements = _data->seqvalue->attrs; 551 /* index.__data__ interpreted as int */ 552 int i = __load_via_object(index->value, __pos___data__).intvalue; 553 554 return elements[i]; 555 } 556 557 __attr __fn_native__list_setelement(__attr __args[]) 558 { 559 __attr * const _data = &__args[1]; 560 __attr * const index = &__args[2]; 561 __attr * const value = &__args[3]; 562 /* _data interpreted as fragment */ 563 __attr *elements = _data->seqvalue->attrs; 564 /* index.__data__ interpreted as int */ 565 int i = __load_via_object(index->value, __pos___data__).intvalue; 566 567 /* Set the element. */ 568 elements[i] = *value; 569 return __builtins___none_None; 570 } 571 572 __attr __fn_native__buffer_str(__attr __args[]) 573 { 574 __attr * const _data = &__args[1]; 575 /* _data interpreted as buffer */ 576 __fragment *data = _data->seqvalue; 577 unsigned int size = 0, i, j, n; 578 char *s, *o; 579 580 /* Calculate the size of the string. */ 581 for (i = 0; i < data->size; i++) 582 size += strlen(__load_via_object(data->attrs[i].value, __pos___data__).strvalue); 583 584 /* Reserve space for a new string. */ 585 s = (char *) __ALLOCATE(size + 1, sizeof(char)); 586 587 /* Build a single string from the buffer contents. */ 588 for (i = 0, j = 0; i < data->size; i++) 589 { 590 o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue; 591 n = strlen(o); 592 strncpy(s + j, o, n); /* does not null terminate but final byte should be zero */ 593 j += n; 594 } 595 596 /* Return a new string. */ 597 return __new_str(s); 598 } 599 600 __attr __fn_native__get_using(__attr __args[]) 601 { 602 __attr * const callable = &__args[1]; 603 __attr * const instance = &__args[2]; 604 605 return __replace_context(instance->value, *callable); 606 } 607 608 __attr __fn_native__object_getattr(__attr __args[]) 609 { 610 __attr * const obj = &__args[1]; 611 __attr * const name = &__args[2]; 612 __attr * const _default = &__args[3]; 613 614 /* NOTE: To be written. */ 615 return __builtins___none_None; 616 } 617 618 static int __issubclass(__ref obj, __attr cls) 619 { 620 return (__HASATTR(obj, __TYPEPOS(cls.value), __TYPECODE(cls.value))); 621 } 622 623 __attr __fn_native__isinstance(__attr __args[]) 624 { 625 __attr * const obj = &__args[1]; 626 __attr * const cls = &__args[2]; 627 628 /* cls must be a class. */ 629 if (__is_instance(obj->value) && __issubclass(__get_class(obj->value), *cls)) 630 return __builtins___boolean_True; 631 else 632 return __builtins___boolean_False; 633 } 634 635 __attr __fn_native__issubclass(__attr __args[]) 636 { 637 __attr * const obj = &__args[1]; 638 __attr * const cls = &__args[2]; 639 640 /* obj and cls must be classes. */ 641 if (__issubclass(obj->value, *cls)) 642 return __builtins___boolean_True; 643 else 644 return __builtins___boolean_False; 645 } 646 647 __attr __fn_native__read(__attr __args[]) 648 { 649 __attr * const fd = &__args[1]; 650 __attr * const n = &__args[2]; 651 652 /* NOTE: To be written. */ 653 return __builtins___none_None; 654 } 655 656 __attr __fn_native__write(__attr __args[]) 657 { 658 __attr * const fd = &__args[1]; 659 __attr * const str = &__args[2]; 660 /* fd.__data__ interpreted as int */ 661 int i = __load_via_object(fd->value, __pos___data__).intvalue; 662 /* str.__data__ interpreted as string */ 663 char *s = __load_via_object(str->value, __pos___data__).strvalue; 664 665 write(i, s, sizeof(char) * strlen(s)); 666 return __builtins___none_None; 667 } 668 669 /* Module initialisation. */ 670 671 void __main_native() 672 { 673 }