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 _data = &__args[1]; 107 __attr * const other = &__args[2]; 108 /* _data and other interpreted as int */ 109 int i = _data->intvalue; 110 int j = other->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 _data = &__args[1]; 120 __attr * const other = &__args[2]; 121 /* _data and other interpreted as int */ 122 int i = _data->intvalue; 123 int j = other->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 _data = &__args[1]; 133 __attr * const other = &__args[2]; 134 /* _data and other interpreted as int */ 135 int i = _data->intvalue; 136 int j = other->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 _data = &__args[1]; 146 __attr * const other = &__args[2]; 147 /* _data and other interpreted as int */ 148 int i = _data->intvalue; 149 int j = other->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 _data = &__args[1]; 159 __attr * const other = &__args[2]; 160 /* _data and other interpreted as int */ 161 int i = _data->intvalue; 162 int j = other->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 _data = &__args[1]; 172 /* _data interpreted as int */ 173 int i = _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 _data = &__args[1]; 182 __attr * const other = &__args[2]; 183 /* _data and other interpreted as int */ 184 int i = _data->intvalue; 185 int j = other->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 _data = &__args[1]; 195 __attr * const other = &__args[2]; 196 /* _data and other interpreted as int */ 197 int i = _data->intvalue; 198 int j = other->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 _data = &__args[1]; 208 __attr * const other = &__args[2]; 209 /* _data and other interpreted as int */ 210 int i = _data->intvalue; 211 int j = other->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 _data = &__args[1]; 221 __attr * const other = &__args[2]; 222 /* _data and other interpreted as int */ 223 int i = _data->intvalue; 224 int j = other->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 _data = &__args[1]; 234 __attr * const other = &__args[2]; 235 /* _data and other interpreted as int */ 236 int i = _data->intvalue; 237 int j = other->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 _data = &__args[1]; 246 __attr * const other = &__args[2]; 247 /* _data and other interpreted as int */ 248 int i = _data->intvalue; 249 int j = other->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 _data = &__args[1]; 258 __attr * const other = &__args[2]; 259 /* _data and other interpreted as int */ 260 int i = _data->intvalue; 261 int j = other->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 _data = &__args[1]; 270 __attr * const other = &__args[2]; 271 /* _data and other interpreted as int */ 272 int i = _data->intvalue; 273 int j = other->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 _data = &__args[1]; 282 /* _data interpreted as int */ 283 int i = _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 _data = &__args[1]; 297 __attr * const other = &__args[2]; 298 /* _data, other interpreted as string */ 299 char *s = _data->strvalue; 300 char *o = other->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 _data = &__args[1]; 314 __attr * const other = &__args[2]; 315 /* _data, other interpreted as string */ 316 char *s = _data->strvalue; 317 char *o = other->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 _data = &__args[1]; 326 __attr * const other = &__args[2]; 327 /* _data, other interpreted as string */ 328 char *s = _data->strvalue; 329 char *o = other->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 _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 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 _data = &__args[1]; 350 /* _data interpreted as string */ 351 char *s = _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 _data = &__args[1]; 360 /* _data interpreted as string */ 361 char *s = _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 _data = &__args[1]; 369 /* _data interpreted as string */ 370 char *s = _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 _data = &__args[1]; 378 __attr * const start = &__args[2]; 379 __attr * const size = &__args[3]; 380 /* _data interpreted as string */ 381 char *s = _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 _data = &__args[1]; 407 __attr * const size = &__args[2]; 408 /* _data interpreted as list */ 409 __fragment *data = _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 interpreted as list */ 436 __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue; 437 __fragment *other_data = other->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 _data = &__args[1]; 465 /* _data interpreted as fragment */ 466 unsigned int size = _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 _data = &__args[1]; 475 476 return _data->seqvalue->size ? __builtins___boolean_True : __builtins___boolean_False; 477 } 478 479 __attr __fn_native__list_element(__attr __args[]) 480 { 481 __attr * const _data = &__args[1]; 482 __attr * const index = &__args[2]; 483 /* _data interpreted as fragment */ 484 __attr *elements = _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 _data = &__args[1]; 494 __attr * const index = &__args[2]; 495 __attr * const value = &__args[3]; 496 /* _data interpreted as fragment */ 497 __attr *elements = _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__buffer_str(__attr __args[]) 507 { 508 __attr * const _data = &__args[1]; 509 /* _data interpreted as buffer */ 510 __fragment *data = _data->seqvalue; 511 unsigned int size = 0, i, j, n; 512 char *s, *o; 513 514 /* Calculate the size of the string. */ 515 for (i = 0; i < data->size; i++) 516 size += strlen(__load_via_object(data->attrs[i].value, __pos___data__).strvalue); 517 518 /* Reserve space for a new string. */ 519 s = (char *) __ALLOCATE(size + 1, sizeof(char)); 520 521 /* Build a single string from the buffer contents. */ 522 for (i = 0, j = 0; i < data->size; i++) 523 { 524 o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue; 525 n = strlen(o); 526 strncpy(s + j, o, n); /* does not null terminate but final byte should be zero */ 527 j += n; 528 } 529 530 /* Return a new string. */ 531 return __new_str(s); 532 } 533 534 __attr __fn_native__get_using(__attr __args[]) 535 { 536 __attr * const callable = &__args[1]; 537 __attr * const instance = &__args[2]; 538 539 return __replace_context(instance->value, *callable); 540 } 541 542 __attr __fn_native__object_getattr(__attr __args[]) 543 { 544 __attr * const obj = &__args[1]; 545 __attr * const name = &__args[2]; 546 __attr * const _default = &__args[3]; 547 548 /* NOTE: To be written. */ 549 return __builtins___none_None; 550 } 551 552 static int __issubclass(__ref obj, __attr cls) 553 { 554 return (__HASATTR(obj, __TYPEPOS(cls.value), __TYPECODE(cls.value))); 555 } 556 557 __attr __fn_native__isinstance(__attr __args[]) 558 { 559 __attr * const obj = &__args[1]; 560 __attr * const cls = &__args[2]; 561 562 /* cls must be a class. */ 563 if (__is_instance(obj->value) && __issubclass(__get_class(obj->value), *cls)) 564 return __builtins___boolean_True; 565 else 566 return __builtins___boolean_False; 567 } 568 569 __attr __fn_native__issubclass(__attr __args[]) 570 { 571 __attr * const obj = &__args[1]; 572 __attr * const cls = &__args[2]; 573 574 /* obj and cls must be classes. */ 575 if (__issubclass(obj->value, *cls)) 576 return __builtins___boolean_True; 577 else 578 return __builtins___boolean_False; 579 } 580 581 __attr __fn_native__read(__attr __args[]) 582 { 583 __attr * const fd = &__args[1]; 584 __attr * const n = &__args[2]; 585 586 /* NOTE: To be written. */ 587 return __builtins___none_None; 588 } 589 590 __attr __fn_native__write(__attr __args[]) 591 { 592 __attr * const fd = &__args[1]; 593 __attr * const str = &__args[2]; 594 /* fd.__data__ interpreted as int */ 595 int i = __load_via_object(fd->value, __pos___data__).intvalue; 596 /* str.__data__ interpreted as string */ 597 char *s = __load_via_object(str->value, __pos___data__).strvalue; 598 599 write(i, s, sizeof(char) * strlen(s)); 600 return __builtins___none_None; 601 } 602 603 /* Module initialisation. */ 604 605 void __main_native() 606 { 607 }