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