code.c 9.35 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
void 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
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
    
    switch (expr->type) {
    case CT_LIT:
        set_return(root_frame_ptr, updateT(get_dst(root_frame_ptr), &((LitEntry*) expr)->thunk));
        destroy_stack_frame(root_frame_ptr);
        return;
    case CT_VAR:
        if (expr->local_type == VAR_LOCAL) {
            Thunk* thunk = forward_to(get_dst(root_frame_ptr), local(frame_ptr, ((VarEntry*) expr)->index));
            destroy_stack_frame(root_frame_ptr);                        
            set_return(root_frame_ptr, thunk);
            return;
        }else{
            destroy_stack_frame(root_frame_ptr);
            set_return(root_frame_ptr, updateF(get_dst(root_frame_ptr), get_slice(((VarEntry*) expr)->f, 0)));
            return;
        }
    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) 
        {
            // TODO: force

            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);

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

            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++) {
                push_a(NULL);
                create_thunk(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
                thunk->_args[basethunk->desc->arity + i] = pop_a();
            }

            set_return(root_frame_ptr, thunk);
            destroy_stack_frame(root_frame_ptr);
            return;
        }
        else
        {
            Thunk* thunk = updateF(get_dst(root_frame_ptr), get_slice(var->f, expr->nr_args));

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

            for (int i = 0; i < expr->nr_args; i++) {
                push_a(NULL);
                create_thunk(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
                thunk->_args[i] = pop_a();
            }

            set_return(root_frame_ptr, thunk);
            destroy_stack_frame(root_frame_ptr);
            return;                    
        }
        break;
    }
    }
}
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
85

86
87
void exec(Code* expr, int frame_ptr, int root_frame_ptr)
{
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
88
89
    while(1)
    {
90
        assert(expr != NULL);
91
92
        assert(stack_top_a < STACK_SIZE_A);
        
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
93
94
        switch (expr->type) {
        case CT_LIT:
95
            set_return(root_frame_ptr, updateT(get_dst(root_frame_ptr), &((LitEntry*) expr)->thunk));
96
            destroy_stack_frame(root_frame_ptr);
97
            return;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
98
99
        case CT_VAR:
            if (expr->local_type == VAR_LOCAL) {
100
                Thunk* thunk = forward_to(get_dst(root_frame_ptr), local(frame_ptr, ((VarEntry*) expr)->index));
101
102
103
                
                // Destroy stack frame before eval, it is not needed any more
                // Greatly reduces stack usage
104
105
                destroy_stack_frame(root_frame_ptr);
                set_return(root_frame_ptr, eval(thunk));
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
106
107
                return;
            }else{
108
109
110
                // Safe to destroy, the next call has no arguments
                destroy_stack_frame(root_frame_ptr);
                
111
112
                Desc* slice = get_slice(((VarEntry*) expr)->f, 0);
                
113
                if(slice->type == FT_FUN)
114
115
116
117
118
                {
                    expr = ((FunEntry*)slice)->body;
                    continue;
                }
                else
119
                {                    
120
                    set_return(root_frame_ptr, updateF(get_dst(root_frame_ptr), slice));
121
122
                    return;
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
123
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
124
        case CT_APP:
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
125
        {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
126
127
            // TODO: check over application
            // TODO: enforce strictness in ADT/Record
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
128

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

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
131
132
            if (var->base.local_type == VAR_LOCAL) 
            {
133
134
                // TODO: force
                
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
135
                Thunk* basethunk = eval(local(frame_ptr, var->index));
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
136

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
137
138
139
                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
140

141
                Thunk* thunk = updateF(get_dst(root_frame_ptr), slice);
142

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

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
145
146
147
                for (int i = 0; i < basethunk->desc->arity; i++) {
                    thunk->_args[i] = basethunk->_args[i];
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
148
149

                for (int i = 0; i < expr->nr_args; i++) {
150
                    push_a(NULL);
151
                    create_thunk(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
152
                    thunk->_args[basethunk->desc->arity + i] = pop_a();
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
153
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
154

155
156
                set_return(root_frame_ptr, thunk);
                destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
157
                return;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
158
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
159
160
161
            else
            {
                Desc* slice = get_slice(var->f, expr->nr_args);
162
                
163
                if (slice->type == FT_PRIM) {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
164
165
166
                    Thunk args[expr->nr_args];

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

171
                    ((PrimEntry*) slice)->exec(root_frame_ptr);
172
                    destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
173
174
                    return;
                }
175
                else if (slice->type == FT_FUN) {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
176

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
177
                    int new_frame_ptr = stack_top_a;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
178

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
179
                    for (int i = 0; i < expr->nr_args; i++) {
180
                        push_a(NULL);
181
182
183
184
185
186
187
188
                        if(is_strict_fun_arg((FunEntry*) slice, i))
                        {
                            exec(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
                        }
                        else
                        {
                          create_thunk(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);  
                        }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
189
                    }
190
                    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
191
192
193
194
195
                    expr = ((FunEntry*) slice)->body;
                    frame_ptr = new_frame_ptr;
                    continue;
                }
                else {
196
                    Thunk* thunk = updateF(get_dst(root_frame_ptr), slice);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
197
198
199
200

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

                    for (int i = 0; i < expr->nr_args; i++) {
201
                        push_a(NULL);
202
                        create_thunk(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
203
204
205
                        thunk->_args[i] = pop_a();
                    }
                    
206
207
                    set_return(root_frame_ptr, thunk);
                    destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
208
                    return;                    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
209
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
210
211
            }
            break;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
212
        }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
213
214
        case CT_SELECT:
        {
215
            push_a(NULL);
216
            exec(((SelectEntry*) expr)->expr, frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
217
            Thunk* pattern = eval(pop_a());
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
218

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
219
220
221
222
223
            bool handled = false;
            
            for (int i = 0; i < expr->nr_cases; i++) {
                SelectCaseEntry* caseEntry = &((SelectEntry*) expr)->cases[i];

224
225
                assert(pattern->desc->type == FT_ADT);
                
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
226
227
228
229
230
231
232
                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]);
233
                    }                  
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
234
235
236
237
238
239
240
241
242
243
                }
                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
244
245
            }

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
246
247
248
249
250
251
252
253
254
255
            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
256

257
            push_a(&tmp);
258
            exec(((IfEntry*) expr)->cond, frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
259
            Thunk* cond = eval(pop_a());
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
260

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
261
262
263
264
265
266
267
268
            if (readB(cond)) {
                expr = ((IfEntry*) expr)->texpr;
                continue;                
            }
            else {
                expr = ((IfEntry*) expr)->fexpr;
                continue;     
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
269
        }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
270
271
272
        default:
            printf("Exec: Unhandled CODE type");
            exit(-1);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
273
        }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
274
    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
275
    }
276
}