Lichen

Annotated templates/native.c

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