1 #include <stdlib.h> /* calloc, exit, realloc */ 2 #include <unistd.h> /* read, write */ 3 #include <math.h> /* ceil, log10, pow */ 4 #include <string.h> /* strcmp, 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 inline __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 inline __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 /* Native functions. */ 33 34 __attr __fn_native__exit(__attr __args[]) 35 { 36 #define status (__args[1]) 37 38 exit(__load_via_object(status.value, __pos___data__).intvalue); 39 return __builtins___none_None; 40 #undef status 41 } 42 43 __attr __fn_native__get_argv(__attr __args[]) 44 { 45 #define status (__args[1]) 46 47 /* NOTE: To be written. */ 48 return __builtins___none_None; 49 #undef status 50 } 51 52 __attr __fn_native__get_path(__attr __args[]) 53 { 54 #define status (__args[1]) 55 56 /* NOTE: To be written. */ 57 return __builtins___none_None; 58 #undef status 59 } 60 61 __attr __fn_native__is(__attr __args[]) 62 { 63 #define x (__args[1]) 64 #define y (__args[2]) 65 66 return x.value == y.value ? __builtins___boolean_True : __builtins___boolean_False; 67 #undef x 68 #undef y 69 } 70 71 __attr __fn_native__is_not(__attr __args[]) 72 { 73 #define x (__args[1]) 74 #define y (__args[2]) 75 76 return x.value != y.value ? __builtins___boolean_True : __builtins___boolean_False; 77 #undef x 78 #undef y 79 } 80 81 __attr __fn_native__int_add(__attr __args[]) 82 { 83 #define self (__args[1]) 84 #define other (__args[2]) 85 /* self.__data__ and other.__data__ interpreted as int */ 86 int i = __load_via_object(self.value, __pos___data__).intvalue; 87 int j = __load_via_object(other.value, __pos___data__).intvalue; 88 89 /* Return the new integer. */ 90 /* NOTE: No overflow test applied. */ 91 return __new_int(i + j); 92 #undef self 93 #undef other 94 } 95 96 __attr __fn_native__int_sub(__attr __args[]) 97 { 98 #define self (__args[1]) 99 #define other (__args[2]) 100 /* self.__data__ and other.__data__ interpreted as int */ 101 int i = __load_via_object(self.value, __pos___data__).intvalue; 102 int j = __load_via_object(other.value, __pos___data__).intvalue; 103 104 /* Return the new integer. */ 105 /* NOTE: No overflow test applied. */ 106 return __new_int(i - j); 107 #undef self 108 #undef other 109 } 110 111 __attr __fn_native__int_mul(__attr __args[]) 112 { 113 #define self (__args[1]) 114 #define other (__args[2]) 115 /* self.__data__ and other.__data__ interpreted as int */ 116 int i = __load_via_object(self.value, __pos___data__).intvalue; 117 int j = __load_via_object(other.value, __pos___data__).intvalue; 118 119 /* Return the new integer. */ 120 /* NOTE: No overflow test applied. */ 121 return __new_int(i * j); 122 #undef self 123 #undef other 124 } 125 126 __attr __fn_native__int_div(__attr __args[]) 127 { 128 #define self (__args[1]) 129 #define other (__args[2]) 130 /* self.__data__ and other.__data__ interpreted as int */ 131 int i = __load_via_object(self.value, __pos___data__).intvalue; 132 int j = __load_via_object(other.value, __pos___data__).intvalue; 133 134 /* Return the new integer. */ 135 /* NOTE: No overflow test applied. */ 136 return __new_int(i / j); 137 #undef self 138 #undef other 139 } 140 141 __attr __fn_native__int_mod(__attr __args[]) 142 { 143 #define self (__args[1]) 144 #define other (__args[2]) 145 /* self.__data__ and other.__data__ interpreted as int */ 146 int i = __load_via_object(self.value, __pos___data__).intvalue; 147 int j = __load_via_object(other.value, __pos___data__).intvalue; 148 149 /* Return the new integer. */ 150 /* NOTE: No overflow test applied. */ 151 return __new_int(i % j); 152 #undef self 153 #undef other 154 } 155 156 __attr __fn_native__int_neg(__attr __args[]) 157 { 158 #define self (__args[1]) 159 /* self.__data__ interpreted as int */ 160 int i = __load_via_object(self.value, __pos___data__).intvalue; 161 162 /* Return the new integer. */ 163 return __new_int(-i); 164 #undef self 165 } 166 167 __attr __fn_native__int_pow(__attr __args[]) 168 { 169 #define self (__args[1]) 170 #define other (__args[2]) 171 /* self.__data__ and other.__data__ interpreted as int */ 172 int i = __load_via_object(self.value, __pos___data__).intvalue; 173 int j = __load_via_object(other.value, __pos___data__).intvalue; 174 175 /* Return the new integer. */ 176 /* NOTE: No overflow test applied. */ 177 return __new_int((int) pow(i, j)); 178 #undef self 179 #undef other 180 } 181 182 __attr __fn_native__int_and(__attr __args[]) 183 { 184 #define self (__args[1]) 185 #define other (__args[2]) 186 /* self.__data__ and other.__data__ interpreted as int */ 187 int i = __load_via_object(self.value, __pos___data__).intvalue; 188 int j = __load_via_object(other.value, __pos___data__).intvalue; 189 190 /* Return the new integer. */ 191 /* NOTE: No overflow test applied. */ 192 return __new_int(i & j); 193 #undef self 194 #undef other 195 } 196 197 __attr __fn_native__int_or(__attr __args[]) 198 { 199 #define self (__args[1]) 200 #define other (__args[2]) 201 /* self.__data__ and other.__data__ interpreted as int */ 202 int i = __load_via_object(self.value, __pos___data__).intvalue; 203 int j = __load_via_object(other.value, __pos___data__).intvalue; 204 205 /* Return the new integer. */ 206 /* NOTE: No overflow test applied. */ 207 return __new_int(i | j); 208 #undef self 209 #undef other 210 } 211 212 __attr __fn_native__int_xor(__attr __args[]) 213 { 214 #define self (__args[1]) 215 #define other (__args[2]) 216 /* self.__data__ and other.__data__ interpreted as int */ 217 int i = __load_via_object(self.value, __pos___data__).intvalue; 218 int j = __load_via_object(other.value, __pos___data__).intvalue; 219 220 /* Return the new integer. */ 221 /* NOTE: No overflow test applied. */ 222 return __new_int(i ^ j); 223 #undef self 224 #undef other 225 } 226 227 __attr __fn_native__int_lt(__attr __args[]) 228 { 229 #define self (__args[1]) 230 #define other (__args[2]) 231 /* self.__data__ and other.__data__ interpreted as int */ 232 int i = __load_via_object(self.value, __pos___data__).intvalue; 233 int j = __load_via_object(other.value, __pos___data__).intvalue; 234 235 /* Return a boolean result. */ 236 return i < j ? __builtins___boolean_True : __builtins___boolean_False; 237 #undef self 238 #undef other 239 } 240 241 __attr __fn_native__int_gt(__attr __args[]) 242 { 243 #define self (__args[1]) 244 #define other (__args[2]) 245 /* self.__data__ and other.__data__ interpreted as int */ 246 int i = __load_via_object(self.value, __pos___data__).intvalue; 247 int j = __load_via_object(other.value, __pos___data__).intvalue; 248 249 /* Return a boolean result. */ 250 return i > j ? __builtins___boolean_True : __builtins___boolean_False; 251 #undef self 252 #undef other 253 } 254 255 __attr __fn_native__int_eq(__attr __args[]) 256 { 257 #define self (__args[1]) 258 #define 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 #undef self 266 #undef other 267 } 268 269 __attr __fn_native__int_ne(__attr __args[]) 270 { 271 #define self (__args[1]) 272 #define other (__args[2]) 273 /* self.__data__ and other.__data__ interpreted as int */ 274 int i = __load_via_object(self.value, __pos___data__).intvalue; 275 int j = __load_via_object(other.value, __pos___data__).intvalue; 276 277 /* Return a boolean result. */ 278 return i != j ? __builtins___boolean_True : __builtins___boolean_False; 279 #undef self 280 #undef other 281 } 282 283 __attr __fn_native__int_str(__attr __args[]) 284 { 285 #define self (__args[1]) 286 /* self.__data__ interpreted as int */ 287 int i = __load_via_object(self.value, __pos___data__).intvalue; 288 int n = i != 0 ? (int) ceil(log10(i+1)) + 1 : 2; 289 char *s = calloc(n, sizeof(char)); 290 291 if (i < 0) n++; 292 snprintf(s, n, "%d", i); 293 294 /* Return a new string. */ 295 return __new_str(s); 296 #undef self 297 #undef other 298 } 299 300 __attr __fn_native__str_add(__attr __args[]) 301 { 302 #define self (__args[1]) 303 #define other (__args[2]) 304 /* self.__data__, other.__data__ interpreted as string */ 305 char *s = __load_via_object(self.value, __pos___data__).strvalue; 306 char *o = __load_via_object(other.value, __pos___data__).strvalue; 307 int n = strlen(s) + strlen(o) + 1; 308 char *r = calloc(n, sizeof(char)); 309 310 strncpy(r, s, n); 311 strncpy(r + strlen(s), o, n - strlen(s)); 312 313 /* Return a new string. */ 314 return __new_str(r); 315 #undef self 316 #undef other 317 } 318 319 __attr __fn_native__str_lt(__attr __args[]) 320 { 321 #define self (__args[1]) 322 #define other (__args[2]) 323 /* self.__data__, other.__data__ interpreted as string */ 324 char *s = __load_via_object(self.value, __pos___data__).strvalue; 325 char *o = __load_via_object(other.value, __pos___data__).strvalue; 326 327 /* NOTE: Using simple byte-level string operations. */ 328 return strcmp(s, o) < 0 ? __builtins___boolean_True : __builtins___boolean_False; 329 #undef self 330 #undef other 331 } 332 333 __attr __fn_native__str_gt(__attr __args[]) 334 { 335 #define self (__args[1]) 336 #define other (__args[2]) 337 /* self.__data__, other.__data__ interpreted as string */ 338 char *s = __load_via_object(self.value, __pos___data__).strvalue; 339 char *o = __load_via_object(other.value, __pos___data__).strvalue; 340 341 /* NOTE: Using simple byte-level string operations. */ 342 return strcmp(s, o) > 0 ? __builtins___boolean_True : __builtins___boolean_False; 343 #undef self 344 #undef other 345 } 346 347 __attr __fn_native__str_eq(__attr __args[]) 348 { 349 #define self (__args[1]) 350 #define other (__args[2]) 351 /* self.__data__, other.__data__ interpreted as string */ 352 char *s = __load_via_object(self.value, __pos___data__).strvalue; 353 char *o = __load_via_object(other.value, __pos___data__).strvalue; 354 355 /* NOTE: Using simple byte-level string operations. */ 356 return strcmp(s, o) == 0 ? __builtins___boolean_True : __builtins___boolean_False; 357 #undef self 358 #undef other 359 } 360 361 __attr __fn_native__str_len(__attr __args[]) 362 { 363 #define self (__args[1]) 364 /* self.__data__ interpreted as string */ 365 char *s = __load_via_object(self.value, __pos___data__).strvalue; 366 367 /* Return the new integer. */ 368 return __new_int(strlen(s)); 369 #undef self 370 } 371 372 __attr __fn_native__str_nonempty(__attr __args[]) 373 { 374 #define self (__args[1]) 375 /* self.__data__ interpreted as string */ 376 char *s = __load_via_object(self.value, __pos___data__).strvalue; 377 378 return strlen(s) ? __builtins___boolean_True : __builtins___boolean_False; 379 #undef self 380 } 381 382 __attr __fn_native__list_init(__attr __args[]) 383 { 384 #define __size (__args[1]) 385 /* __size.__data__ interpreted as int */ 386 unsigned int n = __load_via_object(__size.value, __pos___data__).intvalue; 387 388 /* Allocate space for the list. */ 389 __fragment *data = calloc(1, __FRAGMENT_SIZE(n)); 390 __attr attr = {0, .data=data}; 391 392 /* The initial capacity is the same as the given size. */ 393 data->size = 0; 394 data->capacity = n; 395 return attr; 396 #undef __size 397 } 398 399 __attr __fn_native__list_append(__attr __args[]) 400 { 401 #define self (__args[1]) 402 #define __value (__args[2]) 403 /* self.__data__ interpreted as list */ 404 __fragment *data = __load_via_object(self.value, __pos___data__).data; 405 unsigned int size = data->size, capacity = data->capacity; 406 unsigned int n; 407 408 /* Re-allocate the fragment if the capacity has been reached. */ 409 if (size >= capacity) 410 { 411 /* NOTE: Consider various restrictions on capacity increases. */ 412 n = data->capacity * 2; 413 data = realloc(data, __FRAGMENT_SIZE(n)); 414 data->capacity = n; 415 } 416 417 /* Insert the new element and increment the list size. */ 418 data->attrs[size] = __value; 419 data->size = size + 1; 420 return __builtins___none_None; 421 #undef self 422 #undef __value 423 } 424 425 __attr __fn_native__list_concat(__attr __args[]) 426 { 427 #define self (__args[1]) 428 #define __other (__args[2]) 429 /* self.__data__, __other.__data__ interpreted as list */ 430 __fragment *data = __load_via_object(self.value, __pos___data__).data; 431 __fragment *other_data = __load_via_object(__other.value, __pos___data__).data; 432 unsigned int size = data->size, capacity = data->capacity; 433 unsigned int other_size = other_data->size; 434 unsigned int i, j, n; 435 436 /* Re-allocate the fragment if the capacity has been reached. */ 437 if (size + other_size >= capacity) 438 { 439 n = size + other_size; 440 data = realloc(data, __FRAGMENT_SIZE(n)); 441 data->capacity = n; 442 } 443 444 /* Copy the elements from the other list and increment the list size. */ 445 for (i = size, j = 0; j < other_size; i++, j++) 446 data->attrs[i] = other_data->attrs[j]; 447 data->size = n; 448 return __builtins___none_None; 449 #undef self 450 #undef __other 451 } 452 453 __attr __fn_native__list_len(__attr __args[]) 454 { 455 #define self (__args[1]) 456 /* self.__data__ interpreted as fragment */ 457 unsigned int size = __load_via_object(self.value, __pos___data__).data->size; 458 459 /* Return the new integer. */ 460 return __new_int(size); 461 #undef self 462 } 463 464 __attr __fn_native__list_nonempty(__attr __args[]) 465 { 466 #define self (__args[1]) 467 468 return __load_via_object(self.value, __pos___data__).data->size ? __builtins___boolean_True : __builtins___boolean_False; 469 #undef self 470 } 471 472 __attr __fn_native__list_element(__attr __args[]) 473 { 474 #define self (__args[1]) 475 #define index (__args[2]) 476 /* self.__data__ interpreted as fragment */ 477 __attr *elements = __load_via_object(self.value, __pos___data__).data->attrs; 478 /* index.__data__ interpreted as int */ 479 int i = __load_via_object(index.value, __pos___data__).intvalue; 480 481 return elements[i]; 482 #undef self 483 #undef index 484 } 485 486 __attr __fn_native__list_to_tuple(__attr __args[]) 487 { 488 #define l (__args[1]) 489 490 /* NOTE: To be written. */ 491 return __builtins___none_None; 492 #undef l 493 } 494 495 __attr __fn_native__buffer_str(__attr __args[]) 496 { 497 #define self (__args[1]) 498 /* self.__data__ interpreted as buffer */ 499 __fragment *data = __load_via_object(self.value, __pos___data__).data; 500 unsigned int size = 0, i, j; 501 char *s; 502 503 /* Calculate the size of the string. */ 504 for (i = 0; i < data->size; i++) 505 size += strlen(data->attrs[i].strvalue); 506 507 /* Reserve space for a new string. */ 508 s = calloc(size + 1, sizeof(char)); 509 510 /* Build a single string from the buffer contents. */ 511 for (i = 0, j = 0; i < data->size; j += strlen(data->attrs[i].strvalue), i++) 512 strcpy(s + j, data->attrs[i].strvalue); 513 514 /* Return a new string. */ 515 return __new_str(s); 516 #undef self 517 } 518 519 __attr __fn_native__tuple_init(__attr __args[]) 520 { 521 #define size (__args[1]) 522 /* size.__data__ interpreted as fragment */ 523 __fragment *data = calloc(__load_via_object(size.value, __pos___data__).intvalue, sizeof(__attr)); 524 __attr attr = {0, .data=data}; 525 526 return attr; 527 #undef size 528 } 529 530 __attr __fn_native__tuple_len(__attr __args[]) 531 { 532 #define self (__args[1]) 533 /* self.__data__ interpreted as fragment */ 534 unsigned int size = __load_via_object(self.value, __pos___data__).data->size; 535 536 /* Return the new integer. */ 537 return __new_int(size); 538 #undef self 539 } 540 541 __attr __fn_native__tuple_element(__attr __args[]) 542 { 543 #define self (__args[1]) 544 #define index (__args[2]) 545 /* self.__data__ interpreted as fragment */ 546 __attr *elements = __load_via_object(self.value, __pos___data__).data->attrs; 547 /* index.__data__ interpreted as int */ 548 int i = __load_via_object(index.value, __pos___data__).intvalue; 549 550 return elements[i]; 551 #undef self 552 #undef index 553 } 554 555 __attr __fn_native__isinstance(__attr __args[]) 556 { 557 #define obj (__args[1]) 558 #define cls (__args[2]) 559 560 if (__is_instance(obj.value) && __HASATTR(__get_class(obj.value), __TYPEPOS(cls.value), __TYPECODE(cls.value))) 561 return __builtins___boolean_True; 562 else 563 return __builtins___boolean_False; 564 #undef obj 565 #undef cls 566 } 567 568 __attr __fn_native__read(__attr __args[]) 569 { 570 #define fd (__args[1]) 571 #define n (__args[2]) 572 573 /* NOTE: To be written. */ 574 return __builtins___none_None; 575 #undef fd 576 #undef n 577 } 578 579 __attr __fn_native__write(__attr __args[]) 580 { 581 #define fd (__args[1]) 582 #define str (__args[2]) 583 /* fd.__data__ interpreted as int */ 584 int i = __load_via_object(fd.value, __pos___data__).intvalue; 585 /* str.__data__ interpreted as string */ 586 char *s = __load_via_object(str.value, __pos___data__).strvalue; 587 588 write(i, s, sizeof(char) * strlen(s)); 589 return __builtins___none_None; 590 #undef fd 591 #undef str 592 } 593 594 /* Module initialisation. */ 595 596 void __main_native() 597 { 598 }