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_pow(__attr __args[]) 157 { 158 #define self (__args[1]) 159 #define 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((int) pow(i, j)); 167 #undef self 168 #undef other 169 } 170 171 __attr __fn_native__int_and(__attr __args[]) 172 { 173 #define self (__args[1]) 174 #define other (__args[2]) 175 /* self.__data__ and other.__data__ interpreted as int */ 176 int i = __load_via_object(self.value, __pos___data__).intvalue; 177 int j = __load_via_object(other.value, __pos___data__).intvalue; 178 179 /* Return the new integer. */ 180 /* NOTE: No overflow test applied. */ 181 return __new_int(i & j); 182 #undef self 183 #undef other 184 } 185 186 __attr __fn_native__int_or(__attr __args[]) 187 { 188 #define self (__args[1]) 189 #define other (__args[2]) 190 /* self.__data__ and other.__data__ interpreted as int */ 191 int i = __load_via_object(self.value, __pos___data__).intvalue; 192 int j = __load_via_object(other.value, __pos___data__).intvalue; 193 194 /* Return the new integer. */ 195 /* NOTE: No overflow test applied. */ 196 return __new_int(i | j); 197 #undef self 198 #undef other 199 } 200 201 __attr __fn_native__int_xor(__attr __args[]) 202 { 203 #define self (__args[1]) 204 #define other (__args[2]) 205 /* self.__data__ and other.__data__ interpreted as int */ 206 int i = __load_via_object(self.value, __pos___data__).intvalue; 207 int j = __load_via_object(other.value, __pos___data__).intvalue; 208 209 /* Return the new integer. */ 210 /* NOTE: No overflow test applied. */ 211 return __new_int(i ^ j); 212 #undef self 213 #undef other 214 } 215 216 __attr __fn_native__int_lt(__attr __args[]) 217 { 218 #define self (__args[1]) 219 #define other (__args[2]) 220 /* self.__data__ and other.__data__ interpreted as int */ 221 int i = __load_via_object(self.value, __pos___data__).intvalue; 222 int j = __load_via_object(other.value, __pos___data__).intvalue; 223 224 /* Return a boolean result. */ 225 return i < j ? __builtins___boolean_True : __builtins___boolean_False; 226 #undef self 227 #undef other 228 } 229 230 __attr __fn_native__int_gt(__attr __args[]) 231 { 232 #define self (__args[1]) 233 #define other (__args[2]) 234 /* self.__data__ and other.__data__ interpreted as int */ 235 int i = __load_via_object(self.value, __pos___data__).intvalue; 236 int j = __load_via_object(other.value, __pos___data__).intvalue; 237 238 /* Return a boolean result. */ 239 return i > j ? __builtins___boolean_True : __builtins___boolean_False; 240 #undef self 241 #undef other 242 } 243 244 __attr __fn_native__int_eq(__attr __args[]) 245 { 246 #define self (__args[1]) 247 #define other (__args[2]) 248 /* self.__data__ and other.__data__ interpreted as int */ 249 int i = __load_via_object(self.value, __pos___data__).intvalue; 250 int j = __load_via_object(other.value, __pos___data__).intvalue; 251 252 /* Return a boolean result. */ 253 return i == j ? __builtins___boolean_True : __builtins___boolean_False; 254 #undef self 255 #undef other 256 } 257 258 __attr __fn_native__int_ne(__attr __args[]) 259 { 260 #define self (__args[1]) 261 #define other (__args[2]) 262 /* self.__data__ and other.__data__ interpreted as int */ 263 int i = __load_via_object(self.value, __pos___data__).intvalue; 264 int j = __load_via_object(other.value, __pos___data__).intvalue; 265 266 /* Return a boolean result. */ 267 return i != j ? __builtins___boolean_True : __builtins___boolean_False; 268 #undef self 269 #undef other 270 } 271 272 __attr __fn_native__int_str(__attr __args[]) 273 { 274 #define self (__args[1]) 275 /* self.__data__ interpreted as int */ 276 int i = __load_via_object(self.value, __pos___data__).intvalue; 277 int n = i != 0 ? (int) ceil(log10(i+1)) + 1 : 2; 278 char *s = calloc(n, sizeof(char)); 279 280 if (i < 0) n++; 281 snprintf(s, n, "%d", i); 282 283 /* Return a new string. */ 284 return __new_str(s); 285 #undef self 286 #undef other 287 } 288 289 __attr __fn_native__str_add(__attr __args[]) 290 { 291 #define self (__args[1]) 292 #define other (__args[2]) 293 /* self.__data__, other.__data__ interpreted as string */ 294 char *s = __load_via_object(self.value, __pos___data__).strvalue; 295 char *o = __load_via_object(other.value, __pos___data__).strvalue; 296 int n = strlen(s) + strlen(o) + 1; 297 char *r = calloc(n, sizeof(char)); 298 299 strncpy(r, s, n); 300 strncpy(r + strlen(s), o, n - strlen(s)); 301 302 /* Return a new string. */ 303 return __new_str(r); 304 #undef self 305 #undef other 306 } 307 308 __attr __fn_native__str_lt(__attr __args[]) 309 { 310 #define self (__args[1]) 311 #define other (__args[2]) 312 /* self.__data__, other.__data__ interpreted as string */ 313 char *s = __load_via_object(self.value, __pos___data__).strvalue; 314 char *o = __load_via_object(other.value, __pos___data__).strvalue; 315 316 /* NOTE: Using simple byte-level string operations. */ 317 return strcmp(s, o) < 0 ? __builtins___boolean_True : __builtins___boolean_False; 318 #undef self 319 #undef other 320 } 321 322 __attr __fn_native__str_gt(__attr __args[]) 323 { 324 #define self (__args[1]) 325 #define other (__args[2]) 326 /* self.__data__, other.__data__ interpreted as string */ 327 char *s = __load_via_object(self.value, __pos___data__).strvalue; 328 char *o = __load_via_object(other.value, __pos___data__).strvalue; 329 330 /* NOTE: Using simple byte-level string operations. */ 331 return strcmp(s, o) > 0 ? __builtins___boolean_True : __builtins___boolean_False; 332 #undef self 333 #undef other 334 } 335 336 __attr __fn_native__str_eq(__attr __args[]) 337 { 338 #define self (__args[1]) 339 #define other (__args[2]) 340 /* self.__data__, other.__data__ interpreted as string */ 341 char *s = __load_via_object(self.value, __pos___data__).strvalue; 342 char *o = __load_via_object(other.value, __pos___data__).strvalue; 343 344 /* NOTE: Using simple byte-level string operations. */ 345 return strcmp(s, o) == 0 ? __builtins___boolean_True : __builtins___boolean_False; 346 #undef self 347 #undef other 348 } 349 350 __attr __fn_native__str_len(__attr __args[]) 351 { 352 #define self (__args[1]) 353 /* self.__data__ interpreted as string */ 354 char *s = __load_via_object(self.value, __pos___data__).strvalue; 355 356 /* Return the new integer. */ 357 return __new_int(strlen(s)); 358 #undef self 359 } 360 361 __attr __fn_native__str_nonempty(__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 strlen(s) ? __builtins___boolean_True : __builtins___boolean_False; 368 #undef self 369 } 370 371 __attr __fn_native__list_init(__attr __args[]) 372 { 373 #define __size (__args[1]) 374 /* __size.__data__ interpreted as int */ 375 unsigned int n = __load_via_object(__size.value, __pos___data__).intvalue; 376 377 /* Allocate space for the list. */ 378 __fragment *data = calloc(1, __FRAGMENT_SIZE(n)); 379 __attr attr = {0, .data=data}; 380 381 /* The initial capacity is the same as the given size. */ 382 data->size = 0; 383 data->capacity = n; 384 return attr; 385 #undef __size 386 } 387 388 __attr __fn_native__list_append(__attr __args[]) 389 { 390 #define self (__args[1]) 391 #define __value (__args[2]) 392 /* self.__data__ interpreted as list */ 393 __fragment *data = __load_via_object(self.value, __pos___data__).data; 394 unsigned int size = data->size, capacity = data->capacity; 395 unsigned int n; 396 397 /* Re-allocate the fragment if the capacity has been reached. */ 398 if (size >= capacity) 399 { 400 /* NOTE: Consider various restrictions on capacity increases. */ 401 n = data->capacity * 2; 402 data = realloc(data, __FRAGMENT_SIZE(n)); 403 data->capacity = n; 404 } 405 406 /* Insert the new element and increment the list size. */ 407 data->attrs[size] = __value; 408 data->size = size + 1; 409 return __builtins___none_None; 410 #undef self 411 #undef __value 412 } 413 414 __attr __fn_native__list_concat(__attr __args[]) 415 { 416 #define self (__args[1]) 417 #define __other (__args[2]) 418 /* self.__data__, __other.__data__ interpreted as list */ 419 __fragment *data = __load_via_object(self.value, __pos___data__).data; 420 __fragment *other_data = __load_via_object(__other.value, __pos___data__).data; 421 unsigned int size = data->size, capacity = data->capacity; 422 unsigned int other_size = other_data->size; 423 unsigned int i, j, n; 424 425 /* Re-allocate the fragment if the capacity has been reached. */ 426 if (size + other_size >= capacity) 427 { 428 n = size + other_size; 429 data = realloc(data, __FRAGMENT_SIZE(n)); 430 data->capacity = n; 431 } 432 433 /* Copy the elements from the other list and increment the list size. */ 434 for (i = size, j = 0; j < other_size; i++, j++) 435 data->attrs[i] = other_data->attrs[j]; 436 data->size = n; 437 return __builtins___none_None; 438 #undef self 439 #undef __other 440 } 441 442 __attr __fn_native__list_len(__attr __args[]) 443 { 444 #define self (__args[1]) 445 /* self.__data__ interpreted as fragment */ 446 unsigned int size = __load_via_object(self.value, __pos___data__).data->size; 447 448 /* Return the new integer. */ 449 return __new_int(size); 450 #undef self 451 } 452 453 __attr __fn_native__list_nonempty(__attr __args[]) 454 { 455 #define self (__args[1]) 456 457 return __load_via_object(self.value, __pos___data__).data->size ? __builtins___boolean_True : __builtins___boolean_False; 458 #undef self 459 } 460 461 __attr __fn_native__list_element(__attr __args[]) 462 { 463 #define self (__args[1]) 464 #define index (__args[2]) 465 /* self.__data__ interpreted as fragment */ 466 __attr *elements = __load_via_object(self.value, __pos___data__).data->attrs; 467 /* index.__data__ interpreted as int */ 468 int i = __load_via_object(index.value, __pos___data__).intvalue; 469 470 return elements[i]; 471 #undef self 472 #undef index 473 } 474 475 __attr __fn_native__list_to_tuple(__attr __args[]) 476 { 477 #define l (__args[1]) 478 479 /* NOTE: To be written. */ 480 return __builtins___none_None; 481 #undef l 482 } 483 484 __attr __fn_native__buffer_str(__attr __args[]) 485 { 486 #define self (__args[1]) 487 /* self.__data__ interpreted as buffer */ 488 __fragment *data = __load_via_object(self.value, __pos___data__).data; 489 unsigned int size = 0, i, j; 490 char *s; 491 492 /* Calculate the size of the string. */ 493 for (i = 0; i < data->size; i++) 494 size += strlen(data->attrs[i].strvalue); 495 496 /* Reserve space for a new string. */ 497 s = calloc(size + 1, sizeof(char)); 498 499 /* Build a single string from the buffer contents. */ 500 for (i = 0, j = 0; i < data->size; j += strlen(data->attrs[i].strvalue), i++) 501 strcpy(s + j, data->attrs[i].strvalue); 502 503 /* Return a new string. */ 504 return __new_str(s); 505 #undef self 506 } 507 508 __attr __fn_native__tuple_init(__attr __args[]) 509 { 510 #define size (__args[1]) 511 /* size.__data__ interpreted as fragment */ 512 __fragment *data = calloc(__load_via_object(size.value, __pos___data__).intvalue, sizeof(__attr)); 513 __attr attr = {0, .data=data}; 514 515 return attr; 516 #undef size 517 } 518 519 __attr __fn_native__tuple_len(__attr __args[]) 520 { 521 #define self (__args[1]) 522 /* self.__data__ interpreted as fragment */ 523 unsigned int size = __load_via_object(self.value, __pos___data__).data->size; 524 525 /* Return the new integer. */ 526 return __new_int(size); 527 #undef self 528 } 529 530 __attr __fn_native__tuple_element(__attr __args[]) 531 { 532 #define self (__args[1]) 533 #define index (__args[2]) 534 /* self.__data__ interpreted as fragment */ 535 __attr *elements = __load_via_object(self.value, __pos___data__).data->attrs; 536 /* index.__data__ interpreted as int */ 537 int i = __load_via_object(index.value, __pos___data__).intvalue; 538 539 return elements[i]; 540 #undef self 541 #undef index 542 } 543 544 __attr __fn_native__isinstance(__attr __args[]) 545 { 546 #define obj (__args[1]) 547 #define cls (__args[2]) 548 549 if (__is_instance(obj.value) && __HASATTR(__get_class(obj.value), __TYPEPOS(cls.value), __TYPECODE(cls.value))) 550 return __builtins___boolean_True; 551 else 552 return __builtins___boolean_False; 553 #undef obj 554 #undef cls 555 } 556 557 __attr __fn_native__read(__attr __args[]) 558 { 559 #define fd (__args[1]) 560 #define n (__args[2]) 561 562 /* NOTE: To be written. */ 563 return __builtins___none_None; 564 #undef fd 565 #undef n 566 } 567 568 __attr __fn_native__write(__attr __args[]) 569 { 570 #define fd (__args[1]) 571 #define str (__args[2]) 572 /* fd.__data__ interpreted as int */ 573 int i = __load_via_object(fd.value, __pos___data__).intvalue; 574 /* str.__data__ interpreted as string */ 575 char *s = __load_via_object(str.value, __pos___data__).strvalue; 576 577 write(i, s, sizeof(char) * strlen(s)); 578 return __builtins___none_None; 579 #undef fd 580 #undef str 581 } 582 583 /* Module initialisation. */ 584 585 void __main_native() 586 { 587 }