Lichen

Annotated templates/native.c

336:8c75cdf1a764
2016-12-06 Paul Boddie Introduced stream classes employing C-level FILE pointers, changing the sys stdin, stdout and stderr objects to be instances of these stream classes. Added fread and fwrite support to the native functions. Added support for raising EOFError.
paul@293 1
#include <stdlib.h> /* abs, exit */
paul@173 2
#include <unistd.h> /* read, write */
paul@306 3
#include <limits.h> /* INT_MAX, INT_MIN */
paul@198 4
#include <math.h>   /* ceil, log10, pow */
paul@209 5
#include <string.h> /* strcmp, strncpy, strlen */
paul@328 6
#include <stdio.h>  /* fdopen, snprintf */
paul@306 7
#include <errno.h>  /* errno */
paul@161 8
#include "types.h"
paul@161 9
#include "exceptions.h"
paul@161 10
#include "ops.h"
paul@161 11
#include "progconsts.h"
paul@161 12
#include "progops.h"
paul@161 13
#include "progtypes.h"
paul@161 14
#include "main.h"
paul@161 15
paul@198 16
/* Utility functions. */
paul@198 17
paul@231 18
static __attr __new_int(int i)
paul@198 19
{
paul@198 20
    /* Create a new integer and mutate the __data__ attribute. */
paul@198 21
    __attr attr = __new(&__InstanceTable___builtins___int_int, &__builtins___int_int, sizeof(__obj___builtins___int_int));
paul@198 22
    attr.value->attrs[__pos___data__].intvalue = i;
paul@198 23
    return attr;
paul@198 24
}
paul@198 25
paul@231 26
static __attr __new_str(char *s)
paul@198 27
{
paul@198 28
    /* Create a new string and mutate the __data__ attribute. */
paul@198 29
    __attr attr = __new(&__InstanceTable___builtins___str_string, &__builtins___str_string, sizeof(__obj___builtins___str_string));
paul@198 30
    attr.value->attrs[__pos___data__].strvalue = s;
paul@198 31
    return attr;
paul@198 32
}
paul@198 33
paul@283 34
static __attr __new_list(__fragment *f)
paul@283 35
{
paul@283 36
    /* Create a new list and mutate the __data__ attribute. */
paul@283 37
    __attr attr = __new(&__InstanceTable___builtins___list_list, &__builtins___list_list, sizeof(__obj___builtins___list_list));
paul@283 38
    attr.value->attrs[__pos___data__].seqvalue = f;
paul@283 39
    return attr;
paul@283 40
}
paul@283 41
paul@283 42
static __fragment *__fragment_append(__fragment *data, __attr * const value)
paul@283 43
{
paul@283 44
    __fragment *newdata = data;
paul@283 45
    unsigned int size = data->size, capacity = data->capacity;
paul@283 46
    unsigned int n;
paul@283 47
paul@283 48
    /* Re-allocate the fragment if the capacity has been reached. */
paul@283 49
    if (size >= capacity)
paul@283 50
    {
paul@283 51
        /* NOTE: Consider various restrictions on capacity increases. */
paul@283 52
        n = capacity ? capacity * 2 : 1;
paul@283 53
        newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n));
paul@283 54
        newdata->capacity = n;
paul@283 55
    }
paul@283 56
paul@283 57
    /* Insert the new element and increment the list size. */
paul@283 58
    newdata->attrs[size] = *value;
paul@283 59
    newdata->size = size + 1;
paul@283 60
paul@283 61
    return newdata;
paul@283 62
}
paul@283 63
paul@167 64
/* Native functions. */
paul@167 65
paul@167 66
__attr __fn_native__exit(__attr __args[])
paul@167 67
{
paul@208 68
    __attr * const status = &__args[1];
paul@167 69
paul@208 70
    exit(__load_via_object(status->value, __pos___data__).intvalue);
paul@167 71
    return __builtins___none_None;
paul@167 72
}
paul@167 73
paul@182 74
__attr __fn_native__get_argv(__attr __args[])
paul@182 75
{
paul@208 76
    __attr * const status = &__args[1];
paul@182 77
paul@182 78
    /* NOTE: To be written. */
paul@182 79
    return __builtins___none_None;
paul@182 80
}
paul@182 81
paul@182 82
__attr __fn_native__get_path(__attr __args[])
paul@182 83
{
paul@208 84
    __attr * const status = &__args[1];
paul@182 85
paul@182 86
    /* NOTE: To be written. */
paul@182 87
    return __builtins___none_None;
paul@182 88
}
paul@182 89
paul@161 90
__attr __fn_native__is(__attr __args[])
paul@161 91
{
paul@208 92
    __attr * const x = &__args[1];
paul@208 93
    __attr * const y = &__args[2];
paul@161 94
paul@208 95
    return x->value == y->value ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 96
}
paul@161 97
paul@161 98
__attr __fn_native__is_not(__attr __args[])
paul@161 99
{
paul@208 100
    __attr * const x = &__args[1];
paul@208 101
    __attr * const y = &__args[2];
paul@161 102
paul@208 103
    return x->value != y->value ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 104
}
paul@161 105
paul@309 106
__attr __fn_native__get_maxint(__attr __args[])
paul@309 107
{
paul@309 108
    __attr * const status = &__args[1];
paul@309 109
paul@309 110
    return __new_int(INT_MAX);
paul@309 111
}
paul@309 112
paul@309 113
__attr __fn_native__get_minint(__attr __args[])
paul@309 114
{
paul@309 115
    __attr * const status = &__args[1];
paul@309 116
paul@309 117
    return __new_int(INT_MIN);
paul@309 118
}
paul@309 119
paul@161 120
__attr __fn_native__int_add(__attr __args[])
paul@161 121
{
paul@303 122
    __attr * const _data = &__args[1];
paul@208 123
    __attr * const other = &__args[2];
paul@303 124
    /* _data and other interpreted as int */
paul@303 125
    int i = _data->intvalue;
paul@303 126
    int j = other->intvalue;
paul@161 127
paul@306 128
    /* Test for overflow. */
paul@306 129
    if (((i > 0) && (j > 0) && (i > INT_MAX - j)) ||
paul@306 130
        ((i < 0) && (j < 0) && (i < INT_MIN - j)))
paul@306 131
paul@306 132
        __raise_overflow_error();
paul@306 133
paul@198 134
    /* Return the new integer. */
paul@198 135
    return __new_int(i + j);
paul@161 136
}
paul@161 137
paul@161 138
__attr __fn_native__int_sub(__attr __args[])
paul@161 139
{
paul@303 140
    __attr * const _data = &__args[1];
paul@208 141
    __attr * const other = &__args[2];
paul@303 142
    /* _data and other interpreted as int */
paul@303 143
    int i = _data->intvalue;
paul@303 144
    int j = other->intvalue;
paul@161 145
paul@306 146
    /* Test for overflow. */
paul@306 147
    if (((i < 0) && (j > 0) && (i < INT_MIN + j)) ||
paul@306 148
        ((i > 0) && (j < 0) && (i > INT_MAX + j)))
paul@306 149
paul@306 150
        __raise_overflow_error();
paul@306 151
paul@198 152
    /* Return the new integer. */
paul@198 153
    return __new_int(i - j);
paul@161 154
}
paul@161 155
paul@161 156
__attr __fn_native__int_mul(__attr __args[])
paul@161 157
{
paul@303 158
    __attr * const _data = &__args[1];
paul@208 159
    __attr * const other = &__args[2];
paul@303 160
    /* _data and other interpreted as int */
paul@303 161
    int i = _data->intvalue;
paul@303 162
    int j = other->intvalue;
paul@161 163
paul@306 164
    /* Test for overflow. */
paul@306 165
    if (((i > 0) && (j > 0) && (i > INT_MAX / j)) ||
paul@306 166
        ((i < 0) && (j < 0) && (i > INT_MAX / j)) ||
paul@306 167
        ((i < 0) && (j > 0) && (i < INT_MIN / j)) ||
paul@306 168
        ((i > 0) && (j < 0) && (j < INT_MIN / i)))
paul@306 169
paul@306 170
        __raise_overflow_error();
paul@306 171
paul@198 172
    /* Return the new integer. */
paul@198 173
    return __new_int(i * j);
paul@161 174
}
paul@161 175
paul@161 176
__attr __fn_native__int_div(__attr __args[])
paul@161 177
{
paul@303 178
    __attr * const _data = &__args[1];
paul@208 179
    __attr * const other = &__args[2];
paul@303 180
    /* _data and other interpreted as int */
paul@303 181
    int i = _data->intvalue;
paul@303 182
    int j = other->intvalue;
paul@161 183
paul@306 184
    /* Test for division by zero or overflow. */
paul@306 185
    if (j == 0)
paul@306 186
        __raise_zero_division_error();
paul@306 187
    else if ((j == -1) && (i == INT_MIN))
paul@306 188
        __raise_overflow_error();
paul@306 189
paul@198 190
    /* Return the new integer. */
paul@198 191
    return __new_int(i / j);
paul@161 192
}
paul@161 193
paul@161 194
__attr __fn_native__int_mod(__attr __args[])
paul@161 195
{
paul@303 196
    __attr * const _data = &__args[1];
paul@208 197
    __attr * const other = &__args[2];
paul@303 198
    /* _data and other interpreted as int */
paul@303 199
    int i = _data->intvalue;
paul@303 200
    int j = other->intvalue;
paul@161 201
paul@306 202
    /* Test for division by zero or overflow. */
paul@306 203
    if (j == 0)
paul@306 204
        __raise_zero_division_error();
paul@306 205
    else if ((j == -1) && (i == INT_MIN))
paul@306 206
        __raise_overflow_error();
paul@306 207
paul@198 208
    /* Return the new integer. */
paul@198 209
    return __new_int(i % j);
paul@161 210
}
paul@161 211
paul@207 212
__attr __fn_native__int_neg(__attr __args[])
paul@207 213
{
paul@303 214
    __attr * const _data = &__args[1];
paul@303 215
    /* _data interpreted as int */
paul@303 216
    int i = _data->intvalue;
paul@207 217
paul@306 218
    /* Test for overflow. */
paul@306 219
    if (i == INT_MIN)
paul@306 220
        __raise_overflow_error();
paul@306 221
paul@207 222
    /* Return the new integer. */
paul@207 223
    return __new_int(-i);
paul@207 224
}
paul@207 225
paul@161 226
__attr __fn_native__int_pow(__attr __args[])
paul@161 227
{
paul@303 228
    __attr * const _data = &__args[1];
paul@208 229
    __attr * const other = &__args[2];
paul@303 230
    /* _data and other interpreted as int */
paul@303 231
    int i = _data->intvalue;
paul@303 232
    int j = other->intvalue;
paul@306 233
    int k;
paul@306 234
paul@306 235
    errno = 0;
paul@306 236
    k = (int) pow(i, j);
paul@306 237
paul@306 238
    /* Test for overflow. */
paul@306 239
paul@306 240
    if (errno == ERANGE)
paul@306 241
        __raise_overflow_error();
paul@161 242
paul@198 243
    /* Return the new integer. */
paul@306 244
    return __new_int(k);
paul@161 245
}
paul@161 246
paul@161 247
__attr __fn_native__int_and(__attr __args[])
paul@161 248
{
paul@303 249
    __attr * const _data = &__args[1];
paul@208 250
    __attr * const other = &__args[2];
paul@303 251
    /* _data and other interpreted as int */
paul@303 252
    int i = _data->intvalue;
paul@303 253
    int j = other->intvalue;
paul@161 254
paul@198 255
    /* Return the new integer. */
paul@198 256
    /* NOTE: No overflow test applied. */
paul@198 257
    return __new_int(i & j);
paul@161 258
}
paul@161 259
paul@307 260
__attr __fn_native__int_not(__attr __args[])
paul@307 261
{
paul@307 262
    __attr * const _data = &__args[1];
paul@307 263
    /* _data interpreted as int */
paul@307 264
    int i = _data->intvalue;
paul@307 265
paul@307 266
    /* Return the new integer. */
paul@307 267
    return __new_int(~i);
paul@307 268
}
paul@307 269
paul@161 270
__attr __fn_native__int_or(__attr __args[])
paul@161 271
{
paul@303 272
    __attr * const _data = &__args[1];
paul@208 273
    __attr * const other = &__args[2];
paul@303 274
    /* _data and other interpreted as int */
paul@303 275
    int i = _data->intvalue;
paul@303 276
    int j = other->intvalue;
paul@161 277
paul@198 278
    /* Return the new integer. */
paul@198 279
    /* NOTE: No overflow test applied. */
paul@198 280
    return __new_int(i | j);
paul@161 281
}
paul@161 282
paul@161 283
__attr __fn_native__int_xor(__attr __args[])
paul@161 284
{
paul@303 285
    __attr * const _data = &__args[1];
paul@208 286
    __attr * const other = &__args[2];
paul@303 287
    /* _data and other interpreted as int */
paul@303 288
    int i = _data->intvalue;
paul@303 289
    int j = other->intvalue;
paul@161 290
paul@198 291
    /* Return the new integer. */
paul@198 292
    /* NOTE: No overflow test applied. */
paul@198 293
    return __new_int(i ^ j);
paul@161 294
}
paul@161 295
paul@161 296
__attr __fn_native__int_lt(__attr __args[])
paul@161 297
{
paul@303 298
    __attr * const _data = &__args[1];
paul@208 299
    __attr * const other = &__args[2];
paul@303 300
    /* _data and other interpreted as int */
paul@303 301
    int i = _data->intvalue;
paul@303 302
    int j = other->intvalue;
paul@161 303
paul@198 304
    /* Return a boolean result. */
paul@198 305
    return i < j ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 306
}
paul@161 307
paul@161 308
__attr __fn_native__int_gt(__attr __args[])
paul@161 309
{
paul@303 310
    __attr * const _data = &__args[1];
paul@208 311
    __attr * const other = &__args[2];
paul@303 312
    /* _data and other interpreted as int */
paul@303 313
    int i = _data->intvalue;
paul@303 314
    int j = other->intvalue;
paul@161 315
paul@198 316
    /* Return a boolean result. */
paul@198 317
    return i > j ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 318
}
paul@161 319
paul@161 320
__attr __fn_native__int_eq(__attr __args[])
paul@161 321
{
paul@303 322
    __attr * const _data = &__args[1];
paul@208 323
    __attr * const other = &__args[2];
paul@303 324
    /* _data and other interpreted as int */
paul@303 325
    int i = _data->intvalue;
paul@303 326
    int j = other->intvalue;
paul@161 327
paul@198 328
    /* Return a boolean result. */
paul@198 329
    return i == j ? __builtins___boolean_True : __builtins___boolean_False;
paul@198 330
}
paul@198 331
paul@198 332
__attr __fn_native__int_ne(__attr __args[])
paul@198 333
{
paul@303 334
    __attr * const _data = &__args[1];
paul@208 335
    __attr * const other = &__args[2];
paul@303 336
    /* _data and other interpreted as int */
paul@303 337
    int i = _data->intvalue;
paul@303 338
    int j = other->intvalue;
paul@198 339
paul@198 340
    /* Return a boolean result. */
paul@198 341
    return i != j ? __builtins___boolean_True : __builtins___boolean_False;
paul@198 342
}
paul@198 343
paul@198 344
__attr __fn_native__int_str(__attr __args[])
paul@198 345
{
paul@303 346
    __attr * const _data = &__args[1];
paul@303 347
    /* _data interpreted as int */
paul@303 348
    int i = _data->intvalue;
paul@309 349
    /* Employ a buffer big enough to fit the largest integer plus an extra
paul@309 350
       character, a minus sign, and the null terminator. */
paul@309 351
    unsigned int n = (int) log10(INT_MAX) + 3;
paul@260 352
    char *s = (char *) __ALLOCATE(n, sizeof(char));
paul@198 353
paul@198 354
    snprintf(s, n, "%d", i);
paul@198 355
paul@198 356
    /* Return a new string. */
paul@198 357
    return __new_str(s);
paul@161 358
}
paul@161 359
paul@161 360
__attr __fn_native__str_add(__attr __args[])
paul@161 361
{
paul@303 362
    __attr * const _data = &__args[1];
paul@208 363
    __attr * const other = &__args[2];
paul@303 364
    /* _data, other interpreted as string */
paul@303 365
    char *s = _data->strvalue;
paul@303 366
    char *o = other->strvalue;
paul@198 367
    int n = strlen(s) + strlen(o) + 1;
paul@260 368
    char *r = (char *) __ALLOCATE(n, sizeof(char));
paul@161 369
paul@198 370
    strncpy(r, s, n);
paul@292 371
    strncpy(r + strlen(s), o, n - strlen(s)); /* should null terminate */
paul@198 372
paul@198 373
    /* Return a new string. */
paul@198 374
    return __new_str(r);
paul@161 375
}
paul@161 376
paul@161 377
__attr __fn_native__str_lt(__attr __args[])
paul@161 378
{
paul@303 379
    __attr * const _data = &__args[1];
paul@208 380
    __attr * const other = &__args[2];
paul@303 381
    /* _data, other interpreted as string */
paul@303 382
    char *s = _data->strvalue;
paul@303 383
    char *o = other->strvalue;
paul@161 384
paul@198 385
    /* NOTE: Using simple byte-level string operations. */
paul@198 386
    return strcmp(s, o) < 0 ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 387
}
paul@161 388
paul@161 389
__attr __fn_native__str_gt(__attr __args[])
paul@161 390
{
paul@303 391
    __attr * const _data = &__args[1];
paul@208 392
    __attr * const other = &__args[2];
paul@303 393
    /* _data, other interpreted as string */
paul@303 394
    char *s = _data->strvalue;
paul@303 395
    char *o = other->strvalue;
paul@161 396
paul@198 397
    /* NOTE: Using simple byte-level string operations. */
paul@198 398
    return strcmp(s, o) > 0 ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 399
}
paul@161 400
paul@161 401
__attr __fn_native__str_eq(__attr __args[])
paul@161 402
{
paul@303 403
    __attr * const _data = &__args[1];
paul@208 404
    __attr * const other = &__args[2];
paul@303 405
    /* _data, other interpreted as string */
paul@303 406
    char *s = _data->strvalue;
paul@303 407
    char *o = other->strvalue;
paul@161 408
paul@198 409
    /* NOTE: Using simple byte-level string operations. */
paul@198 410
    return strcmp(s, o) == 0 ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 411
}
paul@161 412
paul@161 413
__attr __fn_native__str_len(__attr __args[])
paul@161 414
{
paul@303 415
    __attr * const _data = &__args[1];
paul@303 416
    /* _data interpreted as string */
paul@303 417
    char *s = _data->strvalue;
paul@161 418
paul@198 419
    /* Return the new integer. */
paul@198 420
    return __new_int(strlen(s));
paul@161 421
}
paul@161 422
paul@161 423
__attr __fn_native__str_nonempty(__attr __args[])
paul@161 424
{
paul@303 425
    __attr * const _data = &__args[1];
paul@303 426
    /* _data interpreted as string */
paul@303 427
    char *s = _data->strvalue;
paul@161 428
paul@198 429
    return strlen(s) ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 430
}
paul@161 431
paul@296 432
__attr __fn_native__str_ord(__attr __args[])
paul@296 433
{
paul@303 434
    __attr * const _data = &__args[1];
paul@303 435
    /* _data interpreted as string */
paul@303 436
    char *s = _data->strvalue;
paul@296 437
paul@296 438
    return __new_int((unsigned int) s[0]);
paul@296 439
}
paul@296 440
paul@292 441
__attr __fn_native__str_substr(__attr __args[])
paul@292 442
{
paul@303 443
    __attr * const _data = &__args[1];
paul@292 444
    __attr * const start = &__args[2];
paul@292 445
    __attr * const size = &__args[3];
paul@303 446
    /* _data interpreted as string */
paul@303 447
    char *s = _data->strvalue, *sub;
paul@292 448
    /* start.__data__ interpreted as int */
paul@292 449
    int i = __load_via_object(start->value, __pos___data__).intvalue;
paul@292 450
    /* size.__data__ interpreted as int */
paul@292 451
    int l = __load_via_object(size->value, __pos___data__).intvalue;
paul@292 452
paul@292 453
    /* Reserve space for a new string. */
paul@292 454
    sub = (char *) __ALLOCATE(l + 1, sizeof(char));
paul@292 455
    strncpy(sub, s + i, l); /* does not null terminate but final byte should be zero */
paul@292 456
    return __new_str(sub);
paul@292 457
}
paul@292 458
paul@161 459
__attr __fn_native__list_init(__attr __args[])
paul@161 460
{
paul@208 461
    __attr * const size = &__args[1];
paul@208 462
    /* size.__data__ interpreted as int */
paul@208 463
    unsigned int n = __load_via_object(size->value, __pos___data__).intvalue;
paul@283 464
    __attr attr = {0, .seqvalue=__new_fragment(n)};
paul@206 465
paul@283 466
    /* Return the __data__ attribute. */
paul@161 467
    return attr;
paul@206 468
}
paul@206 469
paul@227 470
__attr __fn_native__list_setsize(__attr __args[])
paul@227 471
{
paul@303 472
    __attr * const _data = &__args[1];
paul@227 473
    __attr * const size = &__args[2];
paul@303 474
    /* _data interpreted as list */
paul@303 475
    __fragment *data = _data->seqvalue;
paul@227 476
    /* size.__data__ interpreted as int */
paul@227 477
    unsigned int n = __load_via_object(size->value, __pos___data__).intvalue;
paul@227 478
paul@227 479
    data->size = n;
paul@227 480
    return __builtins___none_None;
paul@227 481
}
paul@227 482
paul@206 483
__attr __fn_native__list_append(__attr __args[])
paul@206 484
{
paul@208 485
    __attr * const self = &__args[1];
paul@208 486
    __attr * const value = &__args[2];
paul@206 487
    /* self.__data__ interpreted as list */
paul@280 488
    __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue;
paul@283 489
    __fragment *newdata = __fragment_append(data, value);
paul@215 490
paul@215 491
    /* Replace the __data__ attribute if appropriate. */
paul@215 492
    if (newdata != data)
paul@280 493
        __store_via_object(self->value, __pos___data__, ((__attr) {0, .seqvalue=newdata}));
paul@206 494
    return __builtins___none_None;
paul@206 495
}
paul@206 496
paul@206 497
__attr __fn_native__list_concat(__attr __args[])
paul@206 498
{
paul@208 499
    __attr * const self = &__args[1];
paul@215 500
    __attr * const other = &__args[2];
paul@303 501
    /* self.__data__, other interpreted as list */
paul@280 502
    __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue;
paul@303 503
    __fragment *other_data = other->seqvalue;
paul@215 504
    __fragment *newdata = data;
paul@206 505
    unsigned int size = data->size, capacity = data->capacity;
paul@206 506
    unsigned int other_size = other_data->size;
paul@206 507
    unsigned int i, j, n;
paul@206 508
paul@206 509
    /* Re-allocate the fragment if the capacity has been reached. */
paul@206 510
    if (size + other_size >= capacity)
paul@206 511
    {
paul@206 512
        n = size + other_size;
paul@260 513
        newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n));
paul@215 514
        newdata->capacity = n;
paul@206 515
    }
paul@206 516
paul@206 517
    /* Copy the elements from the other list and increment the list size. */
paul@206 518
    for (i = size, j = 0; j < other_size; i++, j++)
paul@215 519
        newdata->attrs[i] = other_data->attrs[j];
paul@215 520
    newdata->size = n;
paul@215 521
paul@215 522
    /* Replace the __data__ attribute if appropriate. */
paul@215 523
    if (newdata != data)
paul@280 524
        __store_via_object(self->value, __pos___data__, ((__attr) {0, .seqvalue=newdata}));
paul@206 525
    return __builtins___none_None;
paul@161 526
}
paul@161 527
paul@161 528
__attr __fn_native__list_len(__attr __args[])
paul@161 529
{
paul@303 530
    __attr * const _data = &__args[1];
paul@303 531
    /* _data interpreted as fragment */
paul@303 532
    unsigned int size = _data->seqvalue->size;
paul@161 533
paul@182 534
    /* Return the new integer. */
paul@198 535
    return __new_int(size);
paul@161 536
}
paul@161 537
paul@161 538
__attr __fn_native__list_nonempty(__attr __args[])
paul@161 539
{
paul@303 540
    __attr * const _data = &__args[1];
paul@161 541
paul@303 542
    return _data->seqvalue->size ? __builtins___boolean_True : __builtins___boolean_False;
paul@161 543
}
paul@161 544
paul@161 545
__attr __fn_native__list_element(__attr __args[])
paul@161 546
{
paul@303 547
    __attr * const _data = &__args[1];
paul@208 548
    __attr * const index = &__args[2];
paul@303 549
    /* _data interpreted as fragment */
paul@303 550
    __attr *elements = _data->seqvalue->attrs;
paul@198 551
    /* index.__data__ interpreted as int */
paul@208 552
    int i = __load_via_object(index->value, __pos___data__).intvalue;
paul@161 553
paul@198 554
    return elements[i];
paul@161 555
}
paul@161 556
paul@227 557
__attr __fn_native__list_setelement(__attr __args[])
paul@161 558
{
paul@303 559
    __attr * const _data = &__args[1];
paul@227 560
    __attr * const index = &__args[2];
paul@227 561
    __attr * const value = &__args[3];
paul@303 562
    /* _data interpreted as fragment */
paul@303 563
    __attr *elements = _data->seqvalue->attrs;
paul@227 564
    /* index.__data__ interpreted as int */
paul@227 565
    int i = __load_via_object(index->value, __pos___data__).intvalue;
paul@161 566
paul@227 567
    /* Set the element. */
paul@227 568
    elements[i] = *value;
paul@161 569
    return __builtins___none_None;
paul@161 570
}
paul@161 571
paul@206 572
__attr __fn_native__buffer_str(__attr __args[])
paul@206 573
{
paul@303 574
    __attr * const _data = &__args[1];
paul@303 575
    /* _data interpreted as buffer */
paul@303 576
    __fragment *data = _data->seqvalue;
paul@209 577
    unsigned int size = 0, i, j, n;
paul@209 578
    char *s, *o;
paul@206 579
paul@206 580
    /* Calculate the size of the string. */
paul@206 581
    for (i = 0; i < data->size; i++)
paul@253 582
        size += strlen(__load_via_object(data->attrs[i].value, __pos___data__).strvalue);
paul@206 583
paul@206 584
    /* Reserve space for a new string. */
paul@260 585
    s = (char *) __ALLOCATE(size + 1, sizeof(char));
paul@206 586
paul@206 587
    /* Build a single string from the buffer contents. */
paul@209 588
    for (i = 0, j = 0; i < data->size; i++)
paul@209 589
    {
paul@209 590
        o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue;
paul@209 591
        n = strlen(o);
paul@292 592
        strncpy(s + j, o, n); /* does not null terminate but final byte should be zero */
paul@209 593
        j += n;
paul@209 594
    }
paul@206 595
paul@206 596
    /* Return a new string. */
paul@206 597
    return __new_str(s);
paul@206 598
}
paul@206 599
paul@230 600
__attr __fn_native__get_using(__attr __args[])
paul@230 601
{
paul@230 602
    __attr * const callable = &__args[1];
paul@230 603
    __attr * const instance = &__args[2];
paul@230 604
paul@230 605
    return __replace_context(instance->value, *callable);
paul@230 606
}
paul@230 607
paul@228 608
__attr __fn_native__object_getattr(__attr __args[])
paul@228 609
{
paul@228 610
    __attr * const obj = &__args[1];
paul@228 611
    __attr * const name = &__args[2];
paul@228 612
    __attr * const _default = &__args[3];
paul@228 613
paul@228 614
    /* NOTE: To be written. */
paul@228 615
    return __builtins___none_None;
paul@228 616
}
paul@228 617
paul@231 618
static int __issubclass(__ref obj, __attr cls)
paul@231 619
{
paul@231 620
    return (__HASATTR(obj, __TYPEPOS(cls.value), __TYPECODE(cls.value)));
paul@231 621
}
paul@231 622
paul@161 623
__attr __fn_native__isinstance(__attr __args[])
paul@161 624
{
paul@208 625
    __attr * const obj = &__args[1];
paul@208 626
    __attr * const cls = &__args[2];
paul@161 627
paul@231 628
    /* cls must be a class. */
paul@231 629
    if (__is_instance(obj->value) && __issubclass(__get_class(obj->value), *cls))
paul@231 630
        return __builtins___boolean_True;
paul@231 631
    else
paul@231 632
        return __builtins___boolean_False;
paul@231 633
}
paul@231 634
paul@231 635
__attr __fn_native__issubclass(__attr __args[])
paul@231 636
{
paul@231 637
    __attr * const obj = &__args[1];
paul@231 638
    __attr * const cls = &__args[2];
paul@231 639
paul@231 640
    /* obj and cls must be classes. */
paul@231 641
    if (__issubclass(obj->value, *cls))
paul@198 642
        return __builtins___boolean_True;
paul@161 643
    else
paul@198 644
        return __builtins___boolean_False;
paul@161 645
}
paul@161 646
paul@328 647
/* Input/output. */
paul@328 648
paul@328 649
__attr __fn_native__fdopen(__attr __args[])
paul@328 650
{
paul@328 651
    __attr * const fd = &__args[1];
paul@328 652
    __attr * const mode = &__args[2];
paul@328 653
    /* fd.__data__ interpreted as int */
paul@328 654
    int i = __load_via_object(fd->value, __pos___data__).intvalue;
paul@328 655
    /* str.__data__ interpreted as string */
paul@328 656
    char *s = __load_via_object(mode->value, __pos___data__).strvalue;
paul@328 657
    FILE *f;
paul@328 658
    __attr attr;
paul@328 659
paul@328 660
    errno = 0;
paul@328 661
    f = fdopen(i, s);
paul@328 662
paul@328 663
    /* Produce an exception if the operation failed. */
paul@328 664
paul@328 665
    if (f == NULL)
paul@331 666
        __raise_io_error(__new_int(errno));
paul@333 667
paul@333 668
    /* Return the __data__ attribute. */
paul@333 669
paul@328 670
    else
paul@328 671
    {
paul@328 672
        attr.context = 0;
paul@328 673
        attr.datavalue = (void *) f;
paul@328 674
        return attr;
paul@328 675
    }
paul@328 676
}
paul@328 677
paul@336 678
__attr __fn_native__fread(__attr __args[])
paul@336 679
{
paul@336 680
    __attr * const fp = &__args[1];
paul@336 681
    __attr * const size = &__args[2];
paul@336 682
    /* fp interpreted as FILE reference */
paul@336 683
    FILE *f = (FILE *) fp->datavalue;
paul@336 684
    /* size.__data__ interpreted as int */
paul@336 685
    int to_read = __load_via_object(size->value, __pos___data__).intvalue;
paul@336 686
    char buf[to_read];
paul@336 687
    size_t have_read;
paul@336 688
    int error;
paul@336 689
    char *s;
paul@336 690
paul@336 691
    have_read = fread(buf, sizeof(char), to_read, f);
paul@336 692
paul@336 693
    if (have_read != to_read)
paul@336 694
    {
paul@336 695
        if (feof(f))
paul@336 696
            __raise_eof_error();
paul@336 697
        else if (error = ferror(f))
paul@336 698
            __raise_io_error(__new_int(error));
paul@336 699
    }
paul@336 700
paul@336 701
    /* Reserve space for a new string. */
paul@336 702
paul@336 703
    s = __ALLOCATE(have_read + 1, sizeof(char));
paul@336 704
    strncpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */
paul@336 705
    return __new_str(s);
paul@336 706
}
paul@336 707
paul@336 708
__attr __fn_native__fwrite(__attr __args[])
paul@336 709
{
paul@336 710
    __attr * const fp = &__args[1];
paul@336 711
    __attr * const str = &__args[2];
paul@336 712
    /* fp interpreted as FILE reference */
paul@336 713
    FILE *f = (FILE *) fp->datavalue;
paul@336 714
    /* str.__data__ interpreted as string */
paul@336 715
    char *s = __load_via_object(str->value, __pos___data__).strvalue;
paul@336 716
    size_t to_write = strlen(s);
paul@336 717
    size_t have_written = fwrite(s, sizeof(char), to_write, f);
paul@336 718
    int error;
paul@336 719
paul@336 720
    if (have_written != to_write)
paul@336 721
    {
paul@336 722
        if (feof(f))
paul@336 723
            __raise_eof_error();
paul@336 724
        else if (error = ferror(f))
paul@336 725
            __raise_io_error(__new_int(error));
paul@336 726
    }
paul@336 727
paul@336 728
    return __builtins___none_None;
paul@336 729
}
paul@336 730
paul@173 731
__attr __fn_native__read(__attr __args[])
paul@173 732
{
paul@208 733
    __attr * const fd = &__args[1];
paul@208 734
    __attr * const n = &__args[2];
paul@328 735
    /* fd.__data__ interpreted as int */
paul@328 736
    int i = __load_via_object(fd->value, __pos___data__).intvalue;
paul@328 737
    /* n.__data__ interpreted as int */
paul@328 738
    int to_read = __load_via_object(n->value, __pos___data__).intvalue;
paul@335 739
    char buf[to_read];
paul@328 740
    ssize_t have_read;
paul@331 741
    char *s;
paul@173 742
paul@328 743
    errno = 0;
paul@335 744
    have_read = read(i, buf, to_read * sizeof(char));
paul@328 745
paul@328 746
    if (have_read == -1)
paul@331 747
        __raise_io_error(__new_int(errno));
paul@328 748
    else
paul@328 749
    {
paul@331 750
        /* Reserve space for a new string. */
paul@336 751
paul@331 752
        s = __ALLOCATE(have_read + 1, 1);
paul@331 753
        strncpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */
paul@331 754
        return __new_str(s);
paul@328 755
    }
paul@173 756
}
paul@173 757
paul@173 758
__attr __fn_native__write(__attr __args[])
paul@173 759
{
paul@208 760
    __attr * const fd = &__args[1];
paul@208 761
    __attr * const str = &__args[2];
paul@198 762
    /* fd.__data__ interpreted as int */
paul@208 763
    int i = __load_via_object(fd->value, __pos___data__).intvalue;
paul@198 764
    /* str.__data__ interpreted as string */
paul@208 765
    char *s = __load_via_object(str->value, __pos___data__).strvalue;
paul@173 766
paul@198 767
    write(i, s, sizeof(char) * strlen(s));
paul@173 768
    return __builtins___none_None;
paul@173 769
}
paul@173 770
paul@173 771
/* Module initialisation. */
paul@173 772
paul@161 773
void __main_native()
paul@161 774
{
paul@161 775
}