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