code.c 10.1 KB
Newer Older
1
2
#include <stdio.h>
#include <stdlib.h>
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
3
#include <stdbool.h>
4

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
5
#include "debug.h"
6
#include "code.h"
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
7
#include "mem.h"
8
9
#include "desc.h"

10
struct Thunk* create_thunk(Code* expr, int frame_ptr, int root_frame_ptr)
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
11
{
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
12
    assert(expr != NULL);
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    
    switch (expr->type) {
    case CT_APP:
    {
        // TODO: check over application
        // TODO: enforce strictness in ADT/Record

        VarEntry* var = &((AppEntry*) expr)->var;

        if (var->base.local_type == VAR_LOCAL) 
        {
            Thunk* basethunk = eval(local(frame_ptr, var->index));

            Desc* slice =
                    get_slice(basethunk->desc->type == FT_SLICE ?
                              ((SliceEntry*) basethunk->desc)->forward_ptr : basethunk->desc, basethunk->desc->arity + expr->nr_args);

30
            Thunk* thunk = updateF(NULL, slice);
31
32
33
34
35
36
37
38

            assert(thunk->desc->arity == basethunk->desc->arity + expr->nr_args);            

            for (int i = 0; i < basethunk->desc->arity; i++) {
                thunk->_args[i] = basethunk->_args[i];
            }

            for (int i = 0; i < expr->nr_args; i++) {
39
40
                thunk->_args[basethunk->desc->arity + i] 
                        = create_thunk(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
41
42
43
            }

            destroy_stack_frame(root_frame_ptr);
44
            return thunk;
45
46
47
        }
        else
        {
48
            Thunk* thunk = updateF(NULL, get_slice(var->f, expr->nr_args));
49
50
51
52

            assert(thunk->desc->arity == expr->nr_args);

            for (int i = 0; i < expr->nr_args; i++) {
53
                thunk->_args[i] = create_thunk(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
54
55
56
            }

            destroy_stack_frame(root_frame_ptr);
57
            return thunk;                    
58
        }
59
60
61
62
63
64
65
66
67
68
69
70
71
    }        
    case CT_VAR:
        if (expr->local_type == VAR_LOCAL) {
            Thunk* thunk = forward_to(NULL, local(frame_ptr, ((VarEntry*) expr)->index));
            destroy_stack_frame(root_frame_ptr);                        
            return thunk;
        }else{
            destroy_stack_frame(root_frame_ptr);
            return updateF(NULL, get_slice(((VarEntry*) expr)->f, 0));
        }
    case CT_LIT:
        destroy_stack_frame(root_frame_ptr);
        return updateT(NULL, &((LitEntry*) expr)->thunk);        
72
73
    }
}
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
74

75
76
void exec(Code* expr, int frame_ptr, int root_frame_ptr)
{
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
77
78
    while(1)
    {
79
        assert(expr != NULL);
80
81
        assert(stack_top_a < STACK_SIZE_A);
        
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
82
83
        switch (expr->type) {
        case CT_APP:
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
84
        {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
85
86
            // TODO: check over application
            // TODO: enforce strictness in ADT/Record
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
87

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
88
            VarEntry* var = &((AppEntry*) expr)->var;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
89

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
90
91
            if (var->base.local_type == VAR_LOCAL) 
            {
92
93
                // TODO: force
                
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
94
                Thunk* basethunk = eval(local(frame_ptr, var->index));
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
95

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
96
97
98
                Desc* slice =
                        get_slice(basethunk->desc->type == FT_SLICE ?
                                  ((SliceEntry*) basethunk->desc)->forward_ptr : basethunk->desc, basethunk->desc->arity + expr->nr_args);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
99

100
                Thunk* thunk = updateF(get_dst(root_frame_ptr), slice);
101

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
102
                assert(thunk->desc->arity == basethunk->desc->arity + expr->nr_args);            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
103

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
104
105
106
                for (int i = 0; i < basethunk->desc->arity; i++) {
                    thunk->_args[i] = basethunk->_args[i];
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
107
108

                for (int i = 0; i < expr->nr_args; i++) {
109
110
                    thunk->_args[basethunk->desc->arity + i] 
                            = create_thunk(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
111
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
112

113
114
                set_return(root_frame_ptr, thunk);
                destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
115
                return;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
116
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
117
118
119
            else
            {
                Desc* slice = get_slice(var->f, expr->nr_args);
120
                
121
                if (slice->type == FT_PRIM) {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
122
123
124
                    Thunk args[expr->nr_args];

                    for (int i = 0; i < expr->nr_args; i++) {
125
                        push_a(&args[i]);                        
126
                        exec(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
127
128
                    }

129
                    ((PrimEntry*) slice)->exec(root_frame_ptr);
130
                    destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
131
132
                    return;
                }
133
                else if (slice->type == FT_FUN) {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
134

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
135
                    int new_frame_ptr = stack_top_a;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
136

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
137
                    for (int i = 0; i < expr->nr_args; i++) {
138
                        
139
140
                        if(is_strict_fun_arg((FunEntry*) slice, i))
                        {
141
                            push_a(NULL);
142
143
144
145
                            exec(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
                        }
                        else
                        {
146
                            push_a(create_thunk(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a));  
147
                        }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
148
                    }
149
                    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
150
151
152
153
154
                    expr = ((FunEntry*) slice)->body;
                    frame_ptr = new_frame_ptr;
                    continue;
                }
                else {
155
                    Thunk* thunk = updateF(get_dst(root_frame_ptr), slice);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
156
157
158
159

                    assert(thunk->desc->arity == expr->nr_args);

                    for (int i = 0; i < expr->nr_args; i++) {
160
161
                        thunk->_args[i] 
                                = create_thunk(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
162
163
                    }
                    
164
165
                    set_return(root_frame_ptr, thunk);
                    destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
166
                    return;                    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
167
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
168
169
            }
            break;
170
171
172
        }            
        case CT_VAR:
            if (expr->local_type == VAR_LOCAL) {
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
                Thunk* thunk = local(frame_ptr, ((VarEntry*) expr)->index);
                                
                while (thunk->desc == (Desc*) __FORWARD_PTR__) {
                    thunk = thunk->_forward_ptr;
                }

                forward_to(get_dst(root_frame_ptr), thunk);
                set_return(root_frame_ptr, thunk);
                
                if (thunk->desc->type == FT_FUN) {
                    
                    // Destroy stack frame before eval, it is not needed any more
                    // Greatly reduces stack usage
                    destroy_stack_frame(root_frame_ptr);                    
                    frame_ptr = stack_top_a;
                    // Here frame_ptr == root_frame_ptr
                    
                    for (int i = 0; i < thunk->desc->arity; i++) {
                        // TODO: handle strictness
                        push_a(thunk->_args[i]);
                    }
                    
                    expr = ((FunEntry*) thunk->desc)->body;
                    continue;
                }
                else if(thunk->desc->type == FT_PRIM) {

                    for (int i = 0; i < thunk->desc->arity; i++) {
                        // TODO: handle strictness
                        push_a(thunk->_args[i]);
                    }

                    ((PrimEntry*) thunk->desc)->exec(root_frame_ptr);
                }                
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
                
                destroy_stack_frame(root_frame_ptr);
                return;
            }else{
                // Safe to destroy, the next call has no arguments
                destroy_stack_frame(root_frame_ptr);
                
                Desc* slice = get_slice(((VarEntry*) expr)->f, 0);
                
                if(slice->type == FT_FUN)
                {
                    expr = ((FunEntry*)slice)->body;
                    continue;
                }
                else
                {                    
                    set_return(root_frame_ptr, updateF(get_dst(root_frame_ptr), slice));
                    return;
                }
            }
        case CT_LIT:
            set_return(root_frame_ptr, updateT(get_dst(root_frame_ptr), &((LitEntry*) expr)->thunk));
            destroy_stack_frame(root_frame_ptr);
            return;               
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
231
232
        case CT_SELECT:
        {
233
            push_a(NULL);
234
            exec(((SelectEntry*) expr)->expr, frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
235
            Thunk* pattern = eval(pop_a());
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
236

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
237
238
239
240
241
            bool handled = false;
            
            for (int i = 0; i < expr->nr_cases; i++) {
                SelectCaseEntry* caseEntry = &((SelectEntry*) expr)->cases[i];

242
243
                assert(pattern->desc->type == FT_ADT);
                
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
244
245
246
247
248
249
250
                if (caseEntry->type == SC_CONS) {
                    // Pattern match
                    if ((Desc*) caseEntry->cons != pattern->desc) continue;

                    // Put the constructor arguments to the stack if matches
                    for (int i = 0; i < pattern->desc->arity; i++) {
                        push_a(pattern->_args[i]);
251
                    }                  
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
252
253
254
255
256
257
258
259
260
261
                }
                else if (caseEntry->type == SC_LIT) {
                    printf("Exec: Unhandled entry type in CT_SELECT (SC_LIT)");
                    exit(-1);
                }
                
                // must be SC_DEFAULT now
                handled = true;
                expr = caseEntry->body;
                break;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
262
263
            }

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
264
265
266
267
268
269
270
271
272
273
            if(handled) continue;
            
            printf("Exec: no select cases matches");
            print(pattern, false);
            exit(-1);
        }
        case CT_IF:
        {        
            Thunk tmp;
            tmp.desc = (Desc*) __BOOL__;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
274

275
            push_a(&tmp);
276
            exec(((IfEntry*) expr)->cond, frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
277
            Thunk* cond = eval(pop_a());
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
278

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
279
280
281
282
283
284
285
286
            if (readB(cond)) {
                expr = ((IfEntry*) expr)->texpr;
                continue;                
            }
            else {
                expr = ((IfEntry*) expr)->fexpr;
                continue;     
            }
287
        }     
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
288
289
290
        default:
            printf("Exec: Unhandled CODE type");
            exit(-1);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
291
        }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
292
    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
293
    }
294
}