aboutsummaryrefslogtreecommitdiff
path: root/runtime/src/shed/namespaces/Std/Lists.c
blob: a803d0106acb21b6073f2ed68b918dc1005442dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "shed/arrays.h"
#include "shed/gc.h"
#include "shed/ints.h"
#include "./Lists.h"

struct ShedArrayBuilder {
    struct ShedGcObjectHeader object_header;
    // TODO: in principle, this should really be a PatioInt since the GC should
    // assumes everything is stored in a Patio int. In practice, pointers in
    // C are the same size as PatioInt, and indeed the GC assumes this is the
    // case (at the time of writing at least), so this should also work.
    struct ShedArray* array;
    PatioInt capacity;
    PatioInt size;
    bool is_owner;
};

// TODO: move other array code into `shed/arrays`?

static struct ShedArray* array_copy(struct ShedArray* source, PatioInt size, PatioInt capacity) {
    struct ShedArray* array = shed__runtime__gc_alloc(
        sizeof(struct ShedArray) + sizeof(ShedObject) * capacity,
        1
    );
    array->size = size;

    for (PatioInt element_index = 0; element_index < size; element_index++) {
        array->elements[element_index] = source->elements[element_index];
    }

    return array;
}

ShedObject shed__runtime__namespace__Std__Lists__arrayBuilder(ShedClosurePointer closurePointer, ShedObject capacityObject) {
    PatioInt capacity = shed__runtime__int_value(capacityObject);

    struct ShedArray* array = shed__runtime__gc_alloc(
        sizeof(struct ShedArray) + sizeof(ShedObject) * capacity,
        1
    );
    array->size = 0;

    struct ShedArrayBuilder* array_builder = shed__runtime__gc_alloc(sizeof(struct ShedArrayBuilder), 2);
    array_builder->array = array;
    array_builder->capacity = capacity;
    array_builder->size = 0;
    array_builder->is_owner = true;

    return (ShedObject) array_builder;
}

ShedObject shed__runtime__namespace__Std__Lists__method__Array__unsafeGet(ShedClosurePointer closurePointer, ShedObject arg0, ShedObject arg1) {
    struct ShedArray* array = (struct ShedArray*) arg0;
    PatioInt index = shed__runtime__int_value(arg1);
    return array->elements[index];
}

ShedObject shed__runtime__namespace__Std__Lists__method__Array__size(ShedClosurePointer closurePointer, ShedObject arg0) {
    struct ShedArray* array = (struct ShedArray*) arg0;
    return shed__runtime__int_create(array->size);
}

ShedObject shed__runtime__namespace__Std__Lists__method__ArrayBuilder__capacity(ShedClosurePointer closurePointer, ShedObject arg0) {
    struct ShedArrayBuilder* array_builder = (struct ShedArrayBuilder*) arg0;
    return shed__runtime__int_create(array_builder->capacity);
}

ShedObject shed__runtime__namespace__Std__Lists__method__ArrayBuilder__size(ShedClosurePointer closurePointer, ShedObject arg0) {
    struct ShedArrayBuilder* array_builder = (struct ShedArrayBuilder*) arg0;
    return shed__runtime__int_create(array_builder->size);
}

ShedObject shed__runtime__namespace__Std__Lists__method__ArrayBuilder__unsafeAdd(ShedClosurePointer closurePointer, ShedObject arg0, ShedObject arg1) {
    struct ShedArrayBuilder* array_builder = (struct ShedArrayBuilder*) arg0;

    struct ShedArray* array;
    if (array_builder->is_owner) {
        array_builder->is_owner = false;
        array = array_builder->array;
    } else {
        array = array_copy(
            array_builder->array,
            array_builder->size,
            array_builder->capacity
        );
    }

    array->elements[array_builder->size] = arg1;

    struct ShedArrayBuilder* new_array_builder = shed__runtime__gc_alloc(sizeof(struct ShedArrayBuilder), 2);
    new_array_builder->array = array;
    new_array_builder->capacity = array_builder->capacity;
    new_array_builder->size = array_builder->size + 1;
    new_array_builder->is_owner = true;

    return (ShedObject) new_array_builder;
}

ShedObject shed__runtime__namespace__Std__Lists__method__ArrayBuilder__unsafeEnlarge(ShedClosurePointer closurePointer, ShedObject arg0, ShedObject capacity) {
    // TODO: implement
    return arg0;
}

ShedObject shed__runtime__namespace__Std__Lists__method__ArrayBuilder__build(ShedClosurePointer closurePointer, ShedObject arg0) {
    struct ShedArrayBuilder* array_builder = (struct ShedArrayBuilder*) arg0;
    if (array_builder->is_owner) {
        array_builder->is_owner = false;
        array_builder->array->size = array_builder->size;
        return (ShedObject) array_builder->array;
    } else {
        struct ShedArray* array = array_copy(
            array_builder->array,
            array_builder->size,
            array_builder->size
        );

        return (ShedObject) array;
    }
}