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_or(__attr __args[]) 247 { 248 __attr * const _data = &__args[1]; 249 __attr * const other = &__args[2]; 250 /* _data and other interpreted as int */ 251 int i = _data->intvalue; 252 int j = other->intvalue; 253 254 /* Return the new integer. */ 255 /* NOTE: No overflow test applied. */ 256 return __new_int(i | j); 257 } 258 259 __attr __fn_native__int_xor(__attr __args[]) 260 { 261 __attr * const _data = &__args[1]; 262 __attr * const other = &__args[2]; 263 /* _data and other interpreted as int */ 264 int i = _data->intvalue; 265 int j = other->intvalue; 266 267 /* Return the new integer. */ 268 /* NOTE: No overflow test applied. */ 269 return __new_int(i ^ j); 270 } 271 272 __attr __fn_native__int_lt(__attr __args[]) 273 { 274 __attr * const _data = &__args[1]; 275 __attr * const other = &__args[2]; 276 /* _data and other interpreted as int */ 277 int i = _data->intvalue; 278 int j = other->intvalue; 279 280 /* Return a boolean result. */ 281 return i < j ? __builtins___boolean_True : __builtins___boolean_False; 282 } 283 284 __attr __fn_native__int_gt(__attr __args[]) 285 { 286 __attr * const _data = &__args[1]; 287 __attr * const other = &__args[2]; 288 /* _data and other interpreted as int */ 289 int i = _data->intvalue; 290 int j = other->intvalue; 291 292 /* Return a boolean result. */ 293 return i > j ? __builtins___boolean_True : __builtins___boolean_False; 294 } 295 296 __attr __fn_native__int_eq(__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_ne(__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_str(__attr __args[]) 321 { 322 __attr * const _data = &__args[1]; 323 /* _data interpreted as int */ 324 int i = _data->intvalue; 325 int n = i != 0 ? (int) ceil(log10(abs(i)+1)) + 1 : 2; 326 char *s = (char *) __ALLOCATE(n, sizeof(char)); 327 328 if (i < 0) n++; 329 snprintf(s, n, "%d", i); 330 331 /* Return a new string. */ 332 return __new_str(s); 333 } 334 335 __attr __fn_native__str_add(__attr __args[]) 336 { 337 __attr * const _data = &__args[1]; 338 __attr * const other = &__args[2]; 339 /* _data, other interpreted as string */ 340 char *s = _data->strvalue; 341 char *o = other->strvalue; 342 int n = strlen(s) + strlen(o) + 1; 343 char *r = (char *) __ALLOCATE(n, sizeof(char)); 344 345 strncpy(r, s, n); 346 strncpy(r + strlen(s), o, n - strlen(s)); /* should null terminate */ 347 348 /* Return a new string. */ 349 return __new_str(r); 350 } 351 352 __attr __fn_native__str_lt(__attr __args[]) 353 { 354 __attr * const _data = &__args[1]; 355 __attr * const other = &__args[2]; 356 /* _data, other interpreted as string */ 357 char *s = _data->strvalue; 358 char *o = other->strvalue; 359 360 /* NOTE: Using simple byte-level string operations. */ 361 return strcmp(s, o) < 0 ? __builtins___boolean_True : __builtins___boolean_False; 362 } 363 364 __attr __fn_native__str_gt(__attr __args[]) 365 { 366 __attr * const _data = &__args[1]; 367 __attr * const other = &__args[2]; 368 /* _data, other interpreted as string */ 369 char *s = _data->strvalue; 370 char *o = other->strvalue; 371 372 /* NOTE: Using simple byte-level string operations. */ 373 return strcmp(s, o) > 0 ? __builtins___boolean_True : __builtins___boolean_False; 374 } 375 376 __attr __fn_native__str_eq(__attr __args[]) 377 { 378 __attr * const _data = &__args[1]; 379 __attr * const other = &__args[2]; 380 /* _data, other interpreted as string */ 381 char *s = _data->strvalue; 382 char *o = other->strvalue; 383 384 /* NOTE: Using simple byte-level string operations. */ 385 return strcmp(s, o) == 0 ? __builtins___boolean_True : __builtins___boolean_False; 386 } 387 388 __attr __fn_native__str_len(__attr __args[]) 389 { 390 __attr * const _data = &__args[1]; 391 /* _data interpreted as string */ 392 char *s = _data->strvalue; 393 394 /* Return the new integer. */ 395 return __new_int(strlen(s)); 396 } 397 398 __attr __fn_native__str_nonempty(__attr __args[]) 399 { 400 __attr * const _data = &__args[1]; 401 /* _data interpreted as string */ 402 char *s = _data->strvalue; 403 404 return strlen(s) ? __builtins___boolean_True : __builtins___boolean_False; 405 } 406 407 __attr __fn_native__str_ord(__attr __args[]) 408 { 409 __attr * const _data = &__args[1]; 410 /* _data interpreted as string */ 411 char *s = _data->strvalue; 412 413 return __new_int((unsigned int) s[0]); 414 } 415 416 __attr __fn_native__str_substr(__attr __args[]) 417 { 418 __attr * const _data = &__args[1]; 419 __attr * const start = &__args[2]; 420 __attr * const size = &__args[3]; 421 /* _data interpreted as string */ 422 char *s = _data->strvalue, *sub; 423 /* start.__data__ interpreted as int */ 424 int i = __load_via_object(start->value, __pos___data__).intvalue; 425 /* size.__data__ interpreted as int */ 426 int l = __load_via_object(size->value, __pos___data__).intvalue; 427 428 /* Reserve space for a new string. */ 429 sub = (char *) __ALLOCATE(l + 1, sizeof(char)); 430 strncpy(sub, s + i, l); /* does not null terminate but final byte should be zero */ 431 return __new_str(sub); 432 } 433 434 __attr __fn_native__list_init(__attr __args[]) 435 { 436 __attr * const size = &__args[1]; 437 /* size.__data__ interpreted as int */ 438 unsigned int n = __load_via_object(size->value, __pos___data__).intvalue; 439 __attr attr = {0, .seqvalue=__new_fragment(n)}; 440 441 /* Return the __data__ attribute. */ 442 return attr; 443 } 444 445 __attr __fn_native__list_setsize(__attr __args[]) 446 { 447 __attr * const _data = &__args[1]; 448 __attr * const size = &__args[2]; 449 /* _data interpreted as list */ 450 __fragment *data = _data->seqvalue; 451 /* size.__data__ interpreted as int */ 452 unsigned int n = __load_via_object(size->value, __pos___data__).intvalue; 453 454 data->size = n; 455 return __builtins___none_None; 456 } 457 458 __attr __fn_native__list_append(__attr __args[]) 459 { 460 __attr * const self = &__args[1]; 461 __attr * const value = &__args[2]; 462 /* self.__data__ interpreted as list */ 463 __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue; 464 __fragment *newdata = __fragment_append(data, value); 465 466 /* Replace the __data__ attribute if appropriate. */ 467 if (newdata != data) 468 __store_via_object(self->value, __pos___data__, ((__attr) {0, .seqvalue=newdata})); 469 return __builtins___none_None; 470 } 471 472 __attr __fn_native__list_concat(__attr __args[]) 473 { 474 __attr * const self = &__args[1]; 475 __attr * const other = &__args[2]; 476 /* self.__data__, other interpreted as list */ 477 __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue; 478 __fragment *other_data = other->seqvalue; 479 __fragment *newdata = data; 480 unsigned int size = data->size, capacity = data->capacity; 481 unsigned int other_size = other_data->size; 482 unsigned int i, j, n; 483 484 /* Re-allocate the fragment if the capacity has been reached. */ 485 if (size + other_size >= capacity) 486 { 487 n = size + other_size; 488 newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n)); 489 newdata->capacity = n; 490 } 491 492 /* Copy the elements from the other list and increment the list size. */ 493 for (i = size, j = 0; j < other_size; i++, j++) 494 newdata->attrs[i] = other_data->attrs[j]; 495 newdata->size = n; 496 497 /* Replace the __data__ attribute if appropriate. */ 498 if (newdata != data) 499 __store_via_object(self->value, __pos___data__, ((__attr) {0, .seqvalue=newdata})); 500 return __builtins___none_None; 501 } 502 503 __attr __fn_native__list_len(__attr __args[]) 504 { 505 __attr * const _data = &__args[1]; 506 /* _data interpreted as fragment */ 507 unsigned int size = _data->seqvalue->size; 508 509 /* Return the new integer. */ 510 return __new_int(size); 511 } 512 513 __attr __fn_native__list_nonempty(__attr __args[]) 514 { 515 __attr * const _data = &__args[1]; 516 517 return _data->seqvalue->size ? __builtins___boolean_True : __builtins___boolean_False; 518 } 519 520 __attr __fn_native__list_element(__attr __args[]) 521 { 522 __attr * const _data = &__args[1]; 523 __attr * const index = &__args[2]; 524 /* _data interpreted as fragment */ 525 __attr *elements = _data->seqvalue->attrs; 526 /* index.__data__ interpreted as int */ 527 int i = __load_via_object(index->value, __pos___data__).intvalue; 528 529 return elements[i]; 530 } 531 532 __attr __fn_native__list_setelement(__attr __args[]) 533 { 534 __attr * const _data = &__args[1]; 535 __attr * const index = &__args[2]; 536 __attr * const value = &__args[3]; 537 /* _data interpreted as fragment */ 538 __attr *elements = _data->seqvalue->attrs; 539 /* index.__data__ interpreted as int */ 540 int i = __load_via_object(index->value, __pos___data__).intvalue; 541 542 /* Set the element. */ 543 elements[i] = *value; 544 return __builtins___none_None; 545 } 546 547 __attr __fn_native__buffer_str(__attr __args[]) 548 { 549 __attr * const _data = &__args[1]; 550 /* _data interpreted as buffer */ 551 __fragment *data = _data->seqvalue; 552 unsigned int size = 0, i, j, n; 553 char *s, *o; 554 555 /* Calculate the size of the string. */ 556 for (i = 0; i < data->size; i++) 557 size += strlen(__load_via_object(data->attrs[i].value, __pos___data__).strvalue); 558 559 /* Reserve space for a new string. */ 560 s = (char *) __ALLOCATE(size + 1, sizeof(char)); 561 562 /* Build a single string from the buffer contents. */ 563 for (i = 0, j = 0; i < data->size; i++) 564 { 565 o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue; 566 n = strlen(o); 567 strncpy(s + j, o, n); /* does not null terminate but final byte should be zero */ 568 j += n; 569 } 570 571 /* Return a new string. */ 572 return __new_str(s); 573 } 574 575 __attr __fn_native__get_using(__attr __args[]) 576 { 577 __attr * const callable = &__args[1]; 578 __attr * const instance = &__args[2]; 579 580 return __replace_context(instance->value, *callable); 581 } 582 583 __attr __fn_native__object_getattr(__attr __args[]) 584 { 585 __attr * const obj = &__args[1]; 586 __attr * const name = &__args[2]; 587 __attr * const _default = &__args[3]; 588 589 /* NOTE: To be written. */ 590 return __builtins___none_None; 591 } 592 593 static int __issubclass(__ref obj, __attr cls) 594 { 595 return (__HASATTR(obj, __TYPEPOS(cls.value), __TYPECODE(cls.value))); 596 } 597 598 __attr __fn_native__isinstance(__attr __args[]) 599 { 600 __attr * const obj = &__args[1]; 601 __attr * const cls = &__args[2]; 602 603 /* cls must be a class. */ 604 if (__is_instance(obj->value) && __issubclass(__get_class(obj->value), *cls)) 605 return __builtins___boolean_True; 606 else 607 return __builtins___boolean_False; 608 } 609 610 __attr __fn_native__issubclass(__attr __args[]) 611 { 612 __attr * const obj = &__args[1]; 613 __attr * const cls = &__args[2]; 614 615 /* obj and cls must be classes. */ 616 if (__issubclass(obj->value, *cls)) 617 return __builtins___boolean_True; 618 else 619 return __builtins___boolean_False; 620 } 621 622 __attr __fn_native__read(__attr __args[]) 623 { 624 __attr * const fd = &__args[1]; 625 __attr * const n = &__args[2]; 626 627 /* NOTE: To be written. */ 628 return __builtins___none_None; 629 } 630 631 __attr __fn_native__write(__attr __args[]) 632 { 633 __attr * const fd = &__args[1]; 634 __attr * const str = &__args[2]; 635 /* fd.__data__ interpreted as int */ 636 int i = __load_via_object(fd->value, __pos___data__).intvalue; 637 /* str.__data__ interpreted as string */ 638 char *s = __load_via_object(str->value, __pos___data__).strvalue; 639 640 write(i, s, sizeof(char) * strlen(s)); 641 return __builtins___none_None; 642 } 643 644 /* Module initialisation. */ 645 646 void __main_native() 647 { 648 }