Lichen

Annotated templates/native.c

198:e0a514cecae1
2016-11-20 Paul Boddie Added tentative implementations of several native functions.
paul@167 1
#include <stdlib.h> /* calloc, exit */
paul@173 2
#include <unistd.h> /* read, write */
paul@198 3
#include <math.h>   /* ceil, log10, pow */
paul@198 4
#include <string.h> /* strcmp, strlen */
paul@198 5
#include <stdio.h>  /* snprintf */
paul@161 6
#include "types.h"
paul@161 7
#include "exceptions.h"
paul@161 8
#include "ops.h"
paul@161 9
#include "progconsts.h"
paul@161 10
#include "progops.h"
paul@161 11
#include "progtypes.h"
paul@161 12
#include "main.h"
paul@161 13
paul@198 14
/* Utility functions. */
paul@198 15
paul@198 16
inline __attr __new_int(int i)
paul@198 17
{
paul@198 18
    /* Create a new integer and mutate the __data__ attribute. */
paul@198 19
    __attr attr = __new(&__InstanceTable___builtins___int_int, &__builtins___int_int, sizeof(__obj___builtins___int_int));
paul@198 20
    attr.value->attrs[__pos___data__].intvalue = i;
paul@198 21
    return attr;
paul@198 22
}
paul@198 23
paul@198 24
inline __attr __new_str(char *s)
paul@198 25
{
paul@198 26
    /* Create a new string and mutate the __data__ attribute. */
paul@198 27
    __attr attr = __new(&__InstanceTable___builtins___str_string, &__builtins___str_string, sizeof(__obj___builtins___str_string));
paul@198 28
    attr.value->attrs[__pos___data__].strvalue = s;
paul@198 29
    return attr;
paul@198 30
}
paul@198 31
paul@167 32
/* Native functions. */
paul@167 33
paul@167 34
__attr __fn_native__exit(__attr __args[])
paul@167 35
{
paul@167 36
    #define status (__args[1])
paul@167 37
paul@167 38
    exit(__load_via_object(status.value, __pos___data__).intvalue);
paul@167 39
    return __builtins___none_None;
paul@167 40
    #undef status
paul@167 41
}
paul@167 42
paul@182 43
__attr __fn_native__get_argv(__attr __args[])
paul@182 44
{
paul@182 45
    #define status (__args[1])
paul@182 46
paul@182 47
    /* NOTE: To be written. */
paul@182 48
    return __builtins___none_None;
paul@182 49
    #undef status
paul@182 50
}
paul@182 51
paul@182 52
__attr __fn_native__get_path(__attr __args[])
paul@182 53
{
paul@182 54
    #define status (__args[1])
paul@182 55
paul@182 56
    /* NOTE: To be written. */
paul@182 57
    return __builtins___none_None;
paul@182 58
    #undef status
paul@182 59
}
paul@182 60
paul@161 61
__attr __fn_native__is(__attr __args[])
paul@161 62
{
paul@161 63
    #define x (__args[1])
paul@161 64
    #define y (__args[2])
paul@161 65
paul@161 66
    return x.value == y.value ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 67
    #undef x
paul@161 68
    #undef y
paul@161 69
}
paul@161 70
paul@161 71
__attr __fn_native__is_not(__attr __args[])
paul@161 72
{
paul@161 73
    #define x (__args[1])
paul@161 74
    #define y (__args[2])
paul@161 75
paul@161 76
    return x.value != y.value ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 77
    #undef x
paul@161 78
    #undef y
paul@161 79
}
paul@161 80
paul@161 81
__attr __fn_native__int_add(__attr __args[])
paul@161 82
{
paul@161 83
    #define self (__args[1])
paul@161 84
    #define other (__args[2])
paul@198 85
    /* self.__data__ and other.__data__ interpreted as int */
paul@198 86
    int i = __load_via_object(self.value, __pos___data__).intvalue;
paul@198 87
    int j = __load_via_object(other.value, __pos___data__).intvalue;
paul@161 88
paul@198 89
    /* Return the new integer. */
paul@198 90
    /* NOTE: No overflow test applied. */
paul@198 91
    return __new_int(i + j);
paul@161 92
    #undef self
paul@161 93
    #undef other
paul@161 94
}
paul@161 95
paul@161 96
__attr __fn_native__int_sub(__attr __args[])
paul@161 97
{
paul@161 98
    #define self (__args[1])
paul@161 99
    #define other (__args[2])
paul@198 100
    /* self.__data__ and other.__data__ interpreted as int */
paul@198 101
    int i = __load_via_object(self.value, __pos___data__).intvalue;
paul@198 102
    int j = __load_via_object(other.value, __pos___data__).intvalue;
paul@161 103
paul@198 104
    /* Return the new integer. */
paul@198 105
    /* NOTE: No overflow test applied. */
paul@198 106
    return __new_int(i - j);
paul@161 107
    #undef self
paul@161 108
    #undef other
paul@161 109
}
paul@161 110
paul@161 111
__attr __fn_native__int_mul(__attr __args[])
paul@161 112
{
paul@161 113
    #define self (__args[1])
paul@161 114
    #define other (__args[2])
paul@198 115
    /* self.__data__ and other.__data__ interpreted as int */
paul@198 116
    int i = __load_via_object(self.value, __pos___data__).intvalue;
paul@198 117
    int j = __load_via_object(other.value, __pos___data__).intvalue;
paul@161 118
paul@198 119
    /* Return the new integer. */
paul@198 120
    /* NOTE: No overflow test applied. */
paul@198 121
    return __new_int(i * j);
paul@161 122
    #undef self
paul@161 123
    #undef other
paul@161 124
}
paul@161 125
paul@161 126
__attr __fn_native__int_div(__attr __args[])
paul@161 127
{
paul@161 128
    #define self (__args[1])
paul@161 129
    #define other (__args[2])
paul@198 130
    /* self.__data__ and other.__data__ interpreted as int */
paul@198 131
    int i = __load_via_object(self.value, __pos___data__).intvalue;
paul@198 132
    int j = __load_via_object(other.value, __pos___data__).intvalue;
paul@161 133
paul@198 134
    /* Return the new integer. */
paul@198 135
    /* NOTE: No overflow test applied. */
paul@198 136
    return __new_int(i / j);
paul@161 137
    #undef self
paul@161 138
    #undef other
paul@161 139
}
paul@161 140
paul@161 141
__attr __fn_native__int_mod(__attr __args[])
paul@161 142
{
paul@161 143
    #define self (__args[1])
paul@161 144
    #define other (__args[2])
paul@198 145
    /* self.__data__ and other.__data__ interpreted as int */
paul@198 146
    int i = __load_via_object(self.value, __pos___data__).intvalue;
paul@198 147
    int j = __load_via_object(other.value, __pos___data__).intvalue;
paul@161 148
paul@198 149
    /* Return the new integer. */
paul@198 150
    /* NOTE: No overflow test applied. */
paul@198 151
    return __new_int(i % j);
paul@161 152
    #undef self
paul@161 153
    #undef other
paul@161 154
}
paul@161 155
paul@161 156
__attr __fn_native__int_pow(__attr __args[])
paul@161 157
{
paul@161 158
    #define self (__args[1])
paul@161 159
    #define other (__args[2])
paul@198 160
    /* self.__data__ and other.__data__ interpreted as int */
paul@198 161
    int i = __load_via_object(self.value, __pos___data__).intvalue;
paul@198 162
    int j = __load_via_object(other.value, __pos___data__).intvalue;
paul@161 163
paul@198 164
    /* Return the new integer. */
paul@198 165
    /* NOTE: No overflow test applied. */
paul@198 166
    return __new_int((int) pow(i, j));
paul@161 167
    #undef self
paul@161 168
    #undef other
paul@161 169
}
paul@161 170
paul@161 171
__attr __fn_native__int_and(__attr __args[])
paul@161 172
{
paul@161 173
    #define self (__args[1])
paul@161 174
    #define other (__args[2])
paul@198 175
    /* self.__data__ and other.__data__ interpreted as int */
paul@198 176
    int i = __load_via_object(self.value, __pos___data__).intvalue;
paul@198 177
    int j = __load_via_object(other.value, __pos___data__).intvalue;
paul@161 178
paul@198 179
    /* Return the new integer. */
paul@198 180
    /* NOTE: No overflow test applied. */
paul@198 181
    return __new_int(i & j);
paul@161 182
    #undef self
paul@161 183
    #undef other
paul@161 184
}
paul@161 185
paul@161 186
__attr __fn_native__int_or(__attr __args[])
paul@161 187
{
paul@161 188
    #define self (__args[1])
paul@161 189
    #define other (__args[2])
paul@198 190
    /* self.__data__ and other.__data__ interpreted as int */
paul@198 191
    int i = __load_via_object(self.value, __pos___data__).intvalue;
paul@198 192
    int j = __load_via_object(other.value, __pos___data__).intvalue;
paul@161 193
paul@198 194
    /* Return the new integer. */
paul@198 195
    /* NOTE: No overflow test applied. */
paul@198 196
    return __new_int(i | j);
paul@161 197
    #undef self
paul@161 198
    #undef other
paul@161 199
}
paul@161 200
paul@161 201
__attr __fn_native__int_xor(__attr __args[])
paul@161 202
{
paul@161 203
    #define self (__args[1])
paul@161 204
    #define other (__args[2])
paul@198 205
    /* self.__data__ and other.__data__ interpreted as int */
paul@198 206
    int i = __load_via_object(self.value, __pos___data__).intvalue;
paul@198 207
    int j = __load_via_object(other.value, __pos___data__).intvalue;
paul@161 208
paul@198 209
    /* Return the new integer. */
paul@198 210
    /* NOTE: No overflow test applied. */
paul@198 211
    return __new_int(i ^ j);
paul@161 212
    #undef self
paul@161 213
    #undef other
paul@161 214
}
paul@161 215
paul@161 216
__attr __fn_native__int_lt(__attr __args[])
paul@161 217
{
paul@161 218
    #define self (__args[1])
paul@161 219
    #define other (__args[2])
paul@198 220
    /* self.__data__ and other.__data__ interpreted as int */
paul@198 221
    int i = __load_via_object(self.value, __pos___data__).intvalue;
paul@198 222
    int j = __load_via_object(other.value, __pos___data__).intvalue;
paul@161 223
paul@198 224
    /* Return a boolean result. */
paul@198 225
    return i < j ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 226
    #undef self
paul@161 227
    #undef other
paul@161 228
}
paul@161 229
paul@161 230
__attr __fn_native__int_gt(__attr __args[])
paul@161 231
{
paul@161 232
    #define self (__args[1])
paul@161 233
    #define other (__args[2])
paul@198 234
    /* self.__data__ and other.__data__ interpreted as int */
paul@198 235
    int i = __load_via_object(self.value, __pos___data__).intvalue;
paul@198 236
    int j = __load_via_object(other.value, __pos___data__).intvalue;
paul@161 237
paul@198 238
    /* Return a boolean result. */
paul@198 239
    return i > j ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 240
    #undef self
paul@161 241
    #undef other
paul@161 242
}
paul@161 243
paul@161 244
__attr __fn_native__int_eq(__attr __args[])
paul@161 245
{
paul@161 246
    #define self (__args[1])
paul@161 247
    #define other (__args[2])
paul@198 248
    /* self.__data__ and other.__data__ interpreted as int */
paul@198 249
    int i = __load_via_object(self.value, __pos___data__).intvalue;
paul@198 250
    int j = __load_via_object(other.value, __pos___data__).intvalue;
paul@161 251
paul@198 252
    /* Return a boolean result. */
paul@198 253
    return i == j ? __builtins___boolean_True : __builtins___boolean_False;
paul@198 254
    #undef self
paul@198 255
    #undef other
paul@198 256
}
paul@198 257
paul@198 258
__attr __fn_native__int_ne(__attr __args[])
paul@198 259
{
paul@198 260
    #define self (__args[1])
paul@198 261
    #define other (__args[2])
paul@198 262
    /* self.__data__ and other.__data__ interpreted as int */
paul@198 263
    int i = __load_via_object(self.value, __pos___data__).intvalue;
paul@198 264
    int j = __load_via_object(other.value, __pos___data__).intvalue;
paul@198 265
paul@198 266
    /* Return a boolean result. */
paul@198 267
    return i != j ? __builtins___boolean_True : __builtins___boolean_False;
paul@198 268
    #undef self
paul@198 269
    #undef other
paul@198 270
}
paul@198 271
paul@198 272
__attr __fn_native__int_str(__attr __args[])
paul@198 273
{
paul@198 274
    #define self (__args[1])
paul@198 275
    /* self.__data__ interpreted as int */
paul@198 276
    int i = __load_via_object(self.value, __pos___data__).intvalue;
paul@198 277
    int n = i != 0 ? (int) ceil(log10(i+1)) + 1 : 2;
paul@198 278
    char *s = calloc(n, sizeof(char));
paul@198 279
paul@198 280
    if (i < 0) n++;
paul@198 281
    snprintf(s, n, "%d", i);
paul@198 282
paul@198 283
    /* Return a new string. */
paul@198 284
    return __new_str(s);
paul@161 285
    #undef self
paul@161 286
    #undef other
paul@161 287
}
paul@161 288
paul@161 289
__attr __fn_native__str_add(__attr __args[])
paul@161 290
{
paul@161 291
    #define self (__args[1])
paul@161 292
    #define other (__args[2])
paul@198 293
    /* self.__data__, other.__data__ interpreted as string */
paul@198 294
    char *s = __load_via_object(self.value, __pos___data__).strvalue;
paul@198 295
    char *o = __load_via_object(other.value, __pos___data__).strvalue;
paul@198 296
    int n = strlen(s) + strlen(o) + 1;
paul@198 297
    char *r = calloc(n, sizeof(char));
paul@161 298
paul@198 299
    strncpy(r, s, n);
paul@198 300
    strncpy(r + strlen(s), o, n - strlen(s));
paul@198 301
paul@198 302
    /* Return a new string. */
paul@198 303
    return __new_str(r);
paul@161 304
    #undef self
paul@161 305
    #undef other
paul@161 306
}
paul@161 307
paul@161 308
__attr __fn_native__str_lt(__attr __args[])
paul@161 309
{
paul@161 310
    #define self (__args[1])
paul@161 311
    #define other (__args[2])
paul@198 312
    /* self.__data__, other.__data__ interpreted as string */
paul@198 313
    char *s = __load_via_object(self.value, __pos___data__).strvalue;
paul@198 314
    char *o = __load_via_object(other.value, __pos___data__).strvalue;
paul@161 315
paul@198 316
    /* NOTE: Using simple byte-level string operations. */
paul@198 317
    return strcmp(s, o) < 0 ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 318
    #undef self
paul@161 319
    #undef other
paul@161 320
}
paul@161 321
paul@161 322
__attr __fn_native__str_gt(__attr __args[])
paul@161 323
{
paul@161 324
    #define self (__args[1])
paul@161 325
    #define other (__args[2])
paul@198 326
    /* self.__data__, other.__data__ interpreted as string */
paul@198 327
    char *s = __load_via_object(self.value, __pos___data__).strvalue;
paul@198 328
    char *o = __load_via_object(other.value, __pos___data__).strvalue;
paul@161 329
paul@198 330
    /* NOTE: Using simple byte-level string operations. */
paul@198 331
    return strcmp(s, o) > 0 ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 332
    #undef self
paul@161 333
    #undef other
paul@161 334
}
paul@161 335
paul@161 336
__attr __fn_native__str_eq(__attr __args[])
paul@161 337
{
paul@161 338
    #define self (__args[1])
paul@161 339
    #define other (__args[2])
paul@198 340
    /* self.__data__, other.__data__ interpreted as string */
paul@198 341
    char *s = __load_via_object(self.value, __pos___data__).strvalue;
paul@198 342
    char *o = __load_via_object(other.value, __pos___data__).strvalue;
paul@161 343
paul@198 344
    /* NOTE: Using simple byte-level string operations. */
paul@198 345
    return strcmp(s, o) == 0 ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 346
    #undef self
paul@161 347
    #undef other
paul@161 348
}
paul@161 349
paul@161 350
__attr __fn_native__str_len(__attr __args[])
paul@161 351
{
paul@161 352
    #define self (__args[1])
paul@198 353
    /* self.__data__ interpreted as string */
paul@198 354
    char *s = __load_via_object(self.value, __pos___data__).strvalue;
paul@161 355
paul@198 356
    /* Return the new integer. */
paul@198 357
    return __new_int(strlen(s));
paul@161 358
    #undef self
paul@161 359
}
paul@161 360
paul@161 361
__attr __fn_native__str_nonempty(__attr __args[])
paul@161 362
{
paul@161 363
    #define self (__args[1])
paul@198 364
    /* self.__data__ interpreted as string */
paul@198 365
    char *s = __load_via_object(self.value, __pos___data__).strvalue;
paul@161 366
paul@198 367
    return strlen(s) ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 368
    #undef self
paul@161 369
}
paul@161 370
paul@161 371
__attr __fn_native__list_init(__attr __args[])
paul@161 372
{
paul@161 373
    #define size (__args[1])
paul@198 374
    /* size.__data__ interpreted as fragment */
paul@161 375
    __fragment *data = calloc(__load_via_object(size.value, __pos___data__).intvalue, sizeof(__attr));
paul@161 376
    __attr attr = {0, .data=data};
paul@161 377
paul@161 378
    return attr;
paul@161 379
    #undef size
paul@161 380
}
paul@161 381
paul@161 382
__attr __fn_native__list_len(__attr __args[])
paul@161 383
{
paul@161 384
    #define self (__args[1])
paul@182 385
    /* self.__data__ interpreted as fragment */
paul@182 386
    unsigned int size = __load_via_object(self.value, __pos___data__).data->size;
paul@161 387
paul@182 388
    /* Return the new integer. */
paul@198 389
    return __new_int(size);
paul@161 390
    #undef self
paul@161 391
}
paul@161 392
paul@161 393
__attr __fn_native__list_nonempty(__attr __args[])
paul@161 394
{
paul@161 395
    #define self (__args[1])
paul@161 396
paul@164 397
    return __load_via_object(self.value, __pos___data__).data->size ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 398
    #undef self
paul@161 399
}
paul@161 400
paul@161 401
__attr __fn_native__list_element(__attr __args[])
paul@161 402
{
paul@161 403
    #define self (__args[1])
paul@161 404
    #define index (__args[2])
paul@198 405
    /* self.__data__ interpreted as fragment */
paul@198 406
    __attr *elements = __load_via_object(self.value, __pos___data__).data->attrs;
paul@198 407
    /* index.__data__ interpreted as int */
paul@198 408
    int i = __load_via_object(index.value, __pos___data__).intvalue;
paul@161 409
paul@198 410
    return elements[i];
paul@161 411
    #undef self
paul@161 412
    #undef index
paul@161 413
}
paul@161 414
paul@161 415
__attr __fn_native__list_to_tuple(__attr __args[])
paul@161 416
{
paul@161 417
    #define l (__args[1])
paul@161 418
paul@161 419
    /* NOTE: To be written. */
paul@161 420
    return __builtins___none_None;
paul@161 421
    #undef l
paul@161 422
}
paul@161 423
paul@161 424
__attr __fn_native__tuple_init(__attr __args[])
paul@161 425
{
paul@161 426
    #define size (__args[1])
paul@198 427
    /* size.__data__ interpreted as fragment */
paul@161 428
    __fragment *data = calloc(__load_via_object(size.value, __pos___data__).intvalue, sizeof(__attr));
paul@161 429
    __attr attr = {0, .data=data};
paul@161 430
paul@161 431
    return attr;
paul@161 432
    #undef size
paul@161 433
}
paul@161 434
paul@161 435
__attr __fn_native__tuple_len(__attr __args[])
paul@161 436
{
paul@161 437
    #define self (__args[1])
paul@198 438
    /* self.__data__ interpreted as fragment */
paul@198 439
    unsigned int size = __load_via_object(self.value, __pos___data__).data->size;
paul@161 440
paul@198 441
    /* Return the new integer. */
paul@198 442
    return __new_int(size);
paul@161 443
    #undef self
paul@161 444
}
paul@161 445
paul@161 446
__attr __fn_native__tuple_element(__attr __args[])
paul@161 447
{
paul@161 448
    #define self (__args[1])
paul@161 449
    #define index (__args[2])
paul@198 450
    /* self.__data__ interpreted as fragment */
paul@198 451
    __attr *elements = __load_via_object(self.value, __pos___data__).data->attrs;
paul@198 452
    /* index.__data__ interpreted as int */
paul@198 453
    int i = __load_via_object(index.value, __pos___data__).intvalue;
paul@161 454
paul@198 455
    return elements[i];
paul@161 456
    #undef self
paul@161 457
    #undef index
paul@161 458
}
paul@161 459
paul@161 460
__attr __fn_native__isinstance(__attr __args[])
paul@161 461
{
paul@161 462
    #define obj (__args[1])
paul@161 463
    #define cls (__args[2])
paul@161 464
paul@182 465
    if (__is_instance(obj.value) && __HASATTR(__get_class(obj.value), __TYPEPOS(cls.value), __TYPECODE(cls.value)))
paul@198 466
        return __builtins___boolean_True;
paul@161 467
    else
paul@198 468
        return __builtins___boolean_False;
paul@161 469
    #undef obj
paul@161 470
    #undef cls
paul@161 471
}
paul@161 472
paul@173 473
__attr __fn_native__read(__attr __args[])
paul@173 474
{
paul@173 475
    #define fd (__args[1])
paul@173 476
    #define n (__args[2])
paul@173 477
paul@173 478
    /* NOTE: To be written. */
paul@173 479
    return __builtins___none_None;
paul@173 480
    #undef fd
paul@173 481
    #undef n
paul@173 482
}
paul@173 483
paul@173 484
__attr __fn_native__write(__attr __args[])
paul@173 485
{
paul@173 486
    #define fd (__args[1])
paul@173 487
    #define str (__args[2])
paul@198 488
    /* fd.__data__ interpreted as int */
paul@198 489
    int i = __load_via_object(fd.value, __pos___data__).intvalue;
paul@198 490
    /* str.__data__ interpreted as string */
paul@198 491
    char *s = __load_via_object(str.value, __pos___data__).strvalue;
paul@173 492
paul@198 493
    write(i, s, sizeof(char) * strlen(s));
paul@173 494
    return __builtins___none_None;
paul@173 495
    #undef fd
paul@173 496
    #undef str
paul@173 497
}
paul@173 498
paul@173 499
/* Module initialisation. */
paul@173 500
paul@161 501
void __main_native()
paul@161 502
{
paul@161 503
}