code.c 8.96 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
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
        }            
        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 before eval, it is not needed any more
                // Greatly reduces stack usage
                destroy_stack_frame(root_frame_ptr);
                set_return(root_frame_ptr, eval(thunk));
                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
201
202
        case CT_SELECT:
        {
203
            push_a(NULL);
204
            exec(((SelectEntry*) expr)->expr, frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
205
            Thunk* pattern = eval(pop_a());
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
206

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
207
208
209
210
211
            bool handled = false;
            
            for (int i = 0; i < expr->nr_cases; i++) {
                SelectCaseEntry* caseEntry = &((SelectEntry*) expr)->cases[i];

212
213
                assert(pattern->desc->type == FT_ADT);
                
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
214
215
216
217
218
219
220
                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]);
221
                    }                  
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
222
223
224
225
226
227
228
229
230
231
                }
                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
232
233
            }

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
234
235
236
237
238
239
240
241
242
243
            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
244

245
            push_a(&tmp);
246
            exec(((IfEntry*) expr)->cond, frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
247
            Thunk* cond = eval(pop_a());
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
248

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
249
250
251
252
253
254
255
256
            if (readB(cond)) {
                expr = ((IfEntry*) expr)->texpr;
                continue;                
            }
            else {
                expr = ((IfEntry*) expr)->fexpr;
                continue;     
            }
257
        }     
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
258
259
260
        default:
            printf("Exec: Unhandled CODE type");
            exit(-1);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
261
        }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
262
    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
263
    }
264
}