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)); /* should null terminate */ 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__str_substr(__attr __args[]) 367 { 368 __attr * const self = &__args[1]; 369 __attr * const start = &__args[2]; 370 __attr * const size = &__args[3]; 371 /* self.__data__ interpreted as string */ 372 char *s = __load_via_object(self->value, __pos___data__).strvalue, *sub; 373 /* start.__data__ interpreted as int */ 374 int i = __load_via_object(start->value, __pos___data__).intvalue; 375 /* size.__data__ interpreted as int */ 376 int l = __load_via_object(size->value, __pos___data__).intvalue; 377 378 /* Reserve space for a new string. */ 379 sub = (char *) __ALLOCATE(l + 1, sizeof(char)); 380 strncpy(sub, s + i, l); /* does not null terminate but final byte should be zero */ 381 return __new_str(sub); 382 } 383 384 __attr __fn_native__list_init(__attr __args[]) 385 { 386 __attr * const size = &__args[1]; 387 /* size.__data__ interpreted as int */ 388 unsigned int n = __load_via_object(size->value, __pos___data__).intvalue; 389 __attr attr = {0, .seqvalue=__new_fragment(n)}; 390 391 /* Return the __data__ attribute. */ 392 return attr; 393 } 394 395 __attr __fn_native__list_setsize(__attr __args[]) 396 { 397 __attr * const self = &__args[1]; 398 __attr * const size = &__args[2]; 399 /* self.__data__ interpreted as list */ 400 __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue; 401 /* size.__data__ interpreted as int */ 402 unsigned int n = __load_via_object(size->value, __pos___data__).intvalue; 403 404 data->size = n; 405 return __builtins___none_None; 406 } 407 408 __attr __fn_native__list_append(__attr __args[]) 409 { 410 __attr * const self = &__args[1]; 411 __attr * const value = &__args[2]; 412 /* self.__data__ interpreted as list */ 413 __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue; 414 __fragment *newdata = __fragment_append(data, value); 415 416 /* Replace the __data__ attribute if appropriate. */ 417 if (newdata != data) 418 __store_via_object(self->value, __pos___data__, ((__attr) {0, .seqvalue=newdata})); 419 return __builtins___none_None; 420 } 421 422 __attr __fn_native__list_concat(__attr __args[]) 423 { 424 __attr * const self = &__args[1]; 425 __attr * const other = &__args[2]; 426 /* self.__data__, other.__data__ interpreted as list */ 427 __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue; 428 __fragment *other_data = __load_via_object(other->value, __pos___data__).seqvalue; 429 __fragment *newdata = data; 430 unsigned int size = data->size, capacity = data->capacity; 431 unsigned int other_size = other_data->size; 432 unsigned int i, j, n; 433 434 /* Re-allocate the fragment if the capacity has been reached. */ 435 if (size + other_size >= capacity) 436 { 437 n = size + other_size; 438 newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n)); 439 newdata->capacity = n; 440 } 441 442 /* Copy the elements from the other list and increment the list size. */ 443 for (i = size, j = 0; j < other_size; i++, j++) 444 newdata->attrs[i] = other_data->attrs[j]; 445 newdata->size = n; 446 447 /* Replace the __data__ attribute if appropriate. */ 448 if (newdata != data) 449 __store_via_object(self->value, __pos___data__, ((__attr) {0, .seqvalue=newdata})); 450 return __builtins___none_None; 451 } 452 453 __attr __fn_native__list_len(__attr __args[]) 454 { 455 __attr * const self = &__args[1]; 456 /* self.__data__ interpreted as fragment */ 457 unsigned int size = __load_via_object(self->value, __pos___data__).seqvalue->size; 458 459 /* Return the new integer. */ 460 return __new_int(size); 461 } 462 463 __attr __fn_native__list_nonempty(__attr __args[]) 464 { 465 __attr * const self = &__args[1]; 466 467 return __load_via_object(self->value, __pos___data__).seqvalue->size ? __builtins___boolean_True : __builtins___boolean_False; 468 } 469 470 __attr __fn_native__list_element(__attr __args[]) 471 { 472 __attr * const self = &__args[1]; 473 __attr * const index = &__args[2]; 474 /* self.__data__ interpreted as fragment */ 475 __attr *elements = __load_via_object(self->value, __pos___data__).seqvalue->attrs; 476 /* index.__data__ interpreted as int */ 477 int i = __load_via_object(index->value, __pos___data__).intvalue; 478 479 return elements[i]; 480 } 481 482 __attr __fn_native__list_setelement(__attr __args[]) 483 { 484 __attr * const self = &__args[1]; 485 __attr * const index = &__args[2]; 486 __attr * const value = &__args[3]; 487 /* self.__data__ interpreted as fragment */ 488 __attr *elements = __load_via_object(self->value, __pos___data__).seqvalue->attrs; 489 /* index.__data__ interpreted as int */ 490 int i = __load_via_object(index->value, __pos___data__).intvalue; 491 492 /* Set the element. */ 493 elements[i] = *value; 494 return __builtins___none_None; 495 } 496 497 __attr __fn_native__dict_init(__attr __args[]) 498 { 499 __attr * const size = &__args[1]; 500 /* size.__data__ interpreted as int */ 501 unsigned int n = __load_via_object(size->value, __pos___data__).intvalue; 502 __mapping *data = __new_mapping(n); 503 __attr attr = {0, .mapvalue=data}; 504 505 /* Return the __data__ attribute. */ 506 return attr; 507 } 508 509 __attr __fn_native__dict_bucketsize(__attr __args[]) 510 { 511 __attr * const self = &__args[1]; 512 __attr * const index = &__args[2]; 513 /* self.__data__ interpreted as dict */ 514 __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue; 515 /* index.__data__ interpreted as int */ 516 int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS; 517 518 /* Return size of bucket k. */ 519 return __new_int(data->keys[k]->size); 520 } 521 522 __attr __fn_native__dict_keys(__attr __args[]) 523 { 524 __attr * const self = &__args[1]; 525 /* self.__data__ interpreted as dict */ 526 __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue; 527 unsigned int k, i, j, size = 0; 528 __fragment *f; 529 530 /* Count the number of keys. */ 531 for (k = 0; k < __MAPPING_BUCKETS; k++) 532 size += data->keys[k]->size; 533 534 /* Create a fragment for the keys. */ 535 f = __new_fragment(size); 536 537 /* Populate the fragment with the keys. */ 538 for (j = 0, k = 0; k < __MAPPING_BUCKETS; k++) 539 for (i = 0; i < data->keys[k]->size; i++, j++) 540 f->attrs[j] = data->keys[k]->attrs[i]; 541 f->size = size; 542 543 /* Return a list. */ 544 return __new_list(f); 545 } 546 547 __attr __fn_native__dict_values(__attr __args[]) 548 { 549 __attr * const self = &__args[1]; 550 /* self.__data__ interpreted as dict */ 551 __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue; 552 unsigned int k, i, j, size = 0; 553 __fragment *f; 554 555 /* Count the number of values. */ 556 for (k = 0; k < __MAPPING_BUCKETS; k++) 557 size += data->values[k]->size; 558 559 /* Create a fragment for the values. */ 560 f = __new_fragment(size); 561 562 /* Populate the fragment with the values. */ 563 for (j = 0, k = 0; k < __MAPPING_BUCKETS; k++) 564 for (i = 0; i < data->values[k]->size; i++, j++) 565 f->attrs[j] = data->values[k]->attrs[i]; 566 f->size = size; 567 568 /* Return a list. */ 569 return __new_list(f); 570 } 571 572 __attr __fn_native__dict_key(__attr __args[]) 573 { 574 __attr * const self = &__args[1]; 575 __attr * const index = &__args[2]; 576 __attr * const element = &__args[3]; 577 /* self.__data__ interpreted as dict */ 578 __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue; 579 /* index.__data__ interpreted as int */ 580 int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS; 581 /* element.__data__ interpreted as int */ 582 int i = __load_via_object(element->value, __pos___data__).intvalue; 583 584 /* Return key from bucket k, element i. */ 585 return data->keys[k]->attrs[i]; 586 } 587 588 __attr __fn_native__dict_value(__attr __args[]) 589 { 590 __attr * const self = &__args[1]; 591 __attr * const index = &__args[2]; 592 __attr * const element = &__args[3]; 593 /* self.__data__ interpreted as dict */ 594 __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue; 595 /* index.__data__ interpreted as int */ 596 int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS; 597 /* element.__data__ interpreted as int */ 598 int i = __load_via_object(element->value, __pos___data__).intvalue; 599 600 /* Return value from bucket k, element i. */ 601 return data->values[k]->attrs[i]; 602 } 603 604 __attr __fn_native__dict_additem(__attr __args[]) 605 { 606 __attr * const self = &__args[1]; 607 __attr * const index = &__args[2]; 608 __attr * const key = &__args[3]; 609 __attr * const value = &__args[4]; 610 /* self.__data__ interpreted as dict */ 611 __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue; 612 /* index.__data__ interpreted as int */ 613 int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS; 614 __fragment *keys = data->keys[k], *newkeys; 615 __fragment *values = data->values[k], *newvalues; 616 617 /* Append the item. */ 618 newkeys = __fragment_append(keys, key); 619 newvalues = __fragment_append(values, value); 620 621 /* Replace the fragments if appropriate. */ 622 if (newkeys != keys) 623 data->keys[k] = newkeys; 624 if (newvalues != values) 625 data->values[k] = newvalues; 626 return __builtins___none_None; 627 } 628 629 __attr __fn_native__dict_setitem(__attr __args[]) 630 { 631 __attr * const self = &__args[1]; 632 __attr * const index = &__args[2]; 633 __attr * const element = &__args[3]; 634 __attr * const key = &__args[4]; 635 __attr * const value = &__args[5]; 636 /* self.__data__ interpreted as dict */ 637 __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue; 638 /* index.__data__ interpreted as int */ 639 int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS; 640 /* element.__data__ interpreted as int */ 641 int i = __load_via_object(element->value, __pos___data__).intvalue; 642 643 /* Replace the item. */ 644 data->keys[k]->attrs[i] = *key; 645 data->values[k]->attrs[i] = *value; 646 647 return __builtins___none_None; 648 } 649 650 __attr __fn_native__buffer_str(__attr __args[]) 651 { 652 __attr * const self = &__args[1]; 653 /* self.__data__ interpreted as buffer */ 654 __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue; 655 unsigned int size = 0, i, j, n; 656 char *s, *o; 657 658 /* Calculate the size of the string. */ 659 for (i = 0; i < data->size; i++) 660 size += strlen(__load_via_object(data->attrs[i].value, __pos___data__).strvalue); 661 662 /* Reserve space for a new string. */ 663 s = (char *) __ALLOCATE(size + 1, sizeof(char)); 664 665 /* Build a single string from the buffer contents. */ 666 for (i = 0, j = 0; i < data->size; i++) 667 { 668 o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue; 669 n = strlen(o); 670 strncpy(s + j, o, n); /* does not null terminate but final byte should be zero */ 671 j += n; 672 } 673 674 /* Return a new string. */ 675 return __new_str(s); 676 } 677 678 __attr __fn_native__get_using(__attr __args[]) 679 { 680 __attr * const callable = &__args[1]; 681 __attr * const instance = &__args[2]; 682 683 return __replace_context(instance->value, *callable); 684 } 685 686 __attr __fn_native__object_getattr(__attr __args[]) 687 { 688 __attr * const obj = &__args[1]; 689 __attr * const name = &__args[2]; 690 __attr * const _default = &__args[3]; 691 692 /* NOTE: To be written. */ 693 return __builtins___none_None; 694 } 695 696 static int __issubclass(__ref obj, __attr cls) 697 { 698 return (__HASATTR(obj, __TYPEPOS(cls.value), __TYPECODE(cls.value))); 699 } 700 701 __attr __fn_native__isinstance(__attr __args[]) 702 { 703 __attr * const obj = &__args[1]; 704 __attr * const cls = &__args[2]; 705 706 /* cls must be a class. */ 707 if (__is_instance(obj->value) && __issubclass(__get_class(obj->value), *cls)) 708 return __builtins___boolean_True; 709 else 710 return __builtins___boolean_False; 711 } 712 713 __attr __fn_native__issubclass(__attr __args[]) 714 { 715 __attr * const obj = &__args[1]; 716 __attr * const cls = &__args[2]; 717 718 /* obj and cls must be classes. */ 719 if (__issubclass(obj->value, *cls)) 720 return __builtins___boolean_True; 721 else 722 return __builtins___boolean_False; 723 } 724 725 __attr __fn_native__read(__attr __args[]) 726 { 727 __attr * const fd = &__args[1]; 728 __attr * const n = &__args[2]; 729 730 /* NOTE: To be written. */ 731 return __builtins___none_None; 732 } 733 734 __attr __fn_native__write(__attr __args[]) 735 { 736 __attr * const fd = &__args[1]; 737 __attr * const str = &__args[2]; 738 /* fd.__data__ interpreted as int */ 739 int i = __load_via_object(fd->value, __pos___data__).intvalue; 740 /* str.__data__ interpreted as string */ 741 char *s = __load_via_object(str->value, __pos___data__).strvalue; 742 743 write(i, s, sizeof(char) * strlen(s)); 744 return __builtins___none_None; 745 } 746 747 /* Module initialisation. */ 748 749 void __main_native() 750 { 751 }