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