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

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

11
12
13
14
15
16
// For compressing the source code a bit

#define follow_thunk(thunk) if (thunk->desc == (Desc*) __FORWARD_PTR__) thunk = thunk->_forward_ptr;

#define forward_thunk(thunk, frame_ptr) \
        Thunk* dst = get_dst(frame_ptr); \
17
18
        dst->desc = (Desc*) __FORWARD_PTR__; \
        dst->_forward_ptr = thunk; 
19

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
20
21
#define arg_from_thunk(descarg, arg) \
        if(((FunEntry*) (descarg))->strictness & argmask && !arg->desc->hnf) \
22
23
24
25
26
27
28
29
30
        { \
            push_a(eval(arg)); \
        } \
        else \
        { \
            push_a(arg); \
        } \
        argmask <<= 1;

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
31
32
#define arg_from_code(descarg, arg) \
        if(((FunEntry*) (descarg))->strictness & argmask) \
33
        { \
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
34
35
36
            Thunk* phl = alloc_b(); \
            phl->desc = (Desc*) __STACK_PLACEHOLDER__; \
            push_a(phl); \
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
37
            exec(arg, frame_ptr, stack_top_a); \
38
39
40
        } \
        else \
        { \
41
            push_a(arg->create_thunk(arg, frame_ptr)); \
42
43
44
        } \
        argmask <<= 1;

45
struct Thunk* create_thunk_app_static(Code* expr, int frame_ptr)
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
46
{
47
    Thunk* thunk = createF(((AppEntry*) expr)->f);
48

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

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

55
56
    return thunk;                        
}
57

58
59
60
61
struct Thunk* create_thunk_app_dyn(Code* expr, int frame_ptr)
{
    Thunk* basethunk = local(frame_ptr, ((AppEntry*)expr)->var.index);
    if(!basethunk->desc->hnf) basethunk = eval(basethunk);
62

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

67
    Thunk* thunk = createF(slice);
68

69
70
71
72
73
74
    assert(thunk->desc->arity == basethunk->desc->arity + expr->nr_args);            

    memcpy(&thunk->_args, &basethunk->_args, sizeof(Thunk*) * basethunk->desc->arity);

    for (int i = 0; i < expr->nr_args; i++) {
        thunk->_args[basethunk->desc->arity + i] 
75
                = ((AppEntry*) expr)->args[i]->create_thunk(((AppEntry*) expr)->args[i], frame_ptr);
76
    }
77
78
79
80
81
82
83
84
85
86
87
88
89

    return thunk;    
}

struct Thunk* create_thunk_var(Code* expr, int frame_ptr)
{
    return local(frame_ptr, ((VarEntry*) expr)->index);    
}

struct Thunk* create_thunk_var_strict(Code* expr, int frame_ptr)
{
    Thunk* arg = local(frame_ptr, ((VarEntry*) expr)->index);

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
90
    // TODO: check how often happens
91
    if(arg->desc->unboxable)
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
92
    {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
93
94
95
        Thunk* target = (Thunk*) alloc_heap(sizeof (Thunk));
        memcpy(target, arg, sizeof(Thunk));
        return target;
96
97
98
99
    }
    else
    {
        return arg;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
100
    }
101
102
103
104
105
106
107
}

struct Thunk* create_thunk_thunk(Code* expr, int frame_ptr)
{
    return &((ThunkEntry*) expr)->thunk;
}

108
void set_create_thunk_fun(Code* code)
109
{
110
111
112
    switch(code->type)
    {
        case CT_APP_PRIM1:
113
        case CT_APP_PRIM_S:
114
        case CT_APP_PRIM2:
115
116
117
118
119
120
121
        case CT_APP_PRIM_ST:
        case CT_APP_PRIM_TS:
        case CT_APP_PRIM_SS:
        case CT_APP_PRIM_AT:
        case CT_APP_PRIM_TA:
        case CT_APP_PRIM_AS:
        case CT_APP_PRIM_SA:
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
        case CT_APP_FUN:
        case CT_APP_THUNK:
            code->create_thunk = create_thunk_app_static;
            break;
        case CT_APP_DYN:
            code->create_thunk = create_thunk_app_dyn;
            break;
        case CT_VAR:
            code->create_thunk = create_thunk_var;
            break;
        case CT_VAR_STRICT:
            code->create_thunk = create_thunk_var_strict;
            break;
        case CT_THUNK:
            code->create_thunk = create_thunk_thunk;
            break;
138
139
        case CT_SELECT:
        case CT_IF:
140
141
142
            code->create_thunk = NULL;
            break;            
    }
143
144
}

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
145
void exec(Code* expr, int frame_ptr, int root_frame_ptr)
146
{
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
147
148
    int root_frame_ptr_b = stack_top_b;    
    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
149
150
    while(1)
    {
151
        assert(expr != NULL);
152
        assert(stack_top_a < STACK_SIZE_A);
153
        assert(stack_top_b < STACK_SIZE_B);
154
155
156

        // TODO: check over application
        // TODO: enforce strictness in ADT/Record
157
        
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
158
        switch (expr->type) {
159
160
161
162
        case CT_APP_PRIM1:
        {
            push_a(alloc_b());                        
            exec(((AppEntry*) expr)->args[0], frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
163
            
164
165
166
167
168
169
            ((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);

            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);
            return;                        
        }
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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
        case CT_APP_PRIM_S:
        {
            push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[0])->index));                        
            ((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);

            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);
            return;                        
        }
        case CT_APP_PRIM_ST:
        {            
            push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[0])->index));                        
            push_a(&((ThunkEntry*) ((AppEntry*) expr)->args[1])->thunk);                        
            ((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);

            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);
            return;                                    
        }        
        case CT_APP_PRIM_TS:
        {            
            push_a(&((ThunkEntry*) ((AppEntry*) expr)->args[0])->thunk);            
            push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[1])->index));                        
            ((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);

            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);
            return;                                    
        }        
        case CT_APP_PRIM_SS:
        {            
            push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[0])->index));
            push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[1])->index));
            ((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);

            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);
            return;                                    
        }        
        case CT_APP_PRIM_TA:
        {            
            push_a(&((ThunkEntry*) ((AppEntry*) expr)->args[0])->thunk);            
            push_a(alloc_b());                        
            exec(((AppEntry*) expr)->args[1], frame_ptr, stack_top_a);
            ((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);

            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);
            return;                                    
        }        
        case CT_APP_PRIM_AT:
        {            
            push_a(alloc_b());                        
            exec(((AppEntry*) expr)->args[0], frame_ptr, stack_top_a);
            push_a(&((ThunkEntry*) ((AppEntry*) expr)->args[1])->thunk);            
            ((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);

            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);
            return;                                    
        }        
        case CT_APP_PRIM_AS:
        {            
            push_a(alloc_b());                        
            exec(((AppEntry*) expr)->args[0], frame_ptr, stack_top_a);
            push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[1])->index));
            ((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);

            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);
            return;                                    
        }        
        case CT_APP_PRIM_SA:
        {            
            push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[0])->index));
            push_a(alloc_b());                        
            exec(((AppEntry*) expr)->args[1], frame_ptr, stack_top_a);
            ((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);

            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);
            return;                                    
        }        
253
254
255
256
257
258
259
260
        case CT_APP_PRIM2:
        {            
            push_a(alloc_b());                        
            exec(((AppEntry*) expr)->args[0], frame_ptr, stack_top_a);
            push_a(alloc_b());                        
            exec(((AppEntry*) expr)->args[1], frame_ptr, stack_top_a);

            ((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);
261

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
262
263
264
265
266
            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);
            return;            
        }
        case CT_APP_FUN:
267
        {            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
268
            Desc* slice = ((AppEntry*) expr)->f;
269

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
270
271
272
273
274
            int new_frame_ptr = stack_top_a;
            int argmask = 1;

            for (int i = 0; i < expr->nr_args; i++) {
                arg_from_code(slice, ((AppEntry*) expr)->args[i]);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
275
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
276

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
277
278
279
280
281
282
283
            expr = ((FunEntry*) slice)->body;
            frame_ptr = new_frame_ptr;
            continue;            
        }
        case CT_APP_THUNK:
        {
            Desc* slice = ((AppEntry*) expr)->f;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
284

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
285
            Thunk* thunk = updateF(get_dst(root_frame_ptr), slice);
286

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
287
288
289
290
            assert(thunk->desc->arity == expr->nr_args);

            for (int i = 0; i < expr->nr_args; i++) {
                thunk->_args[i]  
291
                        = ((AppEntry*) expr)->args[i]->create_thunk(((AppEntry*) expr)->args[i], frame_ptr);
292
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
293
294
295
296
297
298

            set_return(root_frame_ptr, thunk);
            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);
            return;                                
        }
299
        case CT_APP_DYN:
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
300
        {
301
            Thunk* basethunk = local(frame_ptr, ((AppEntry*)expr)->var.index);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
302
            if(!basethunk->desc->hnf) basethunk = eval(basethunk);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
303

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

            switch(slice->type) {
309
310
            case FT_PRIM1:
            case FT_PRIM2:
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
311
            {
312
                for (int i = 0; i < basethunk->desc->arity; i++) {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
313
314
315
316
317
318
319
320
                    if(basethunk->_args[i]->desc->hnf)
                    {
                        push_a(basethunk->_args[i]);
                    }
                    else
                    {
                        push_a(eval(basethunk->_args[i]));   
                    }
321
                }
322

323
                for (int i = 0; i < expr->nr_args; i++) {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
324
                    push_a(alloc_b());
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
325
                    exec(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
326
327
328
                } 

                ((PrimEntry*) slice)->exec(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
329
                destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
330
                destroy_stack_frame_b(root_frame_ptr_b);                
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
331
332
                return;                    
            }
333
334
335
336
337
338
339
340
341
342
343
344
            case FT_FUN:
            {
                int new_frame_ptr = stack_top_a;                    
                int argmask = 1;

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

                for (int i = 0; i < expr->nr_args; i++) {
                    arg_from_code(slice, ((AppEntry*) expr)->args[i]);    
                } 
345

346
347
348
349
350
351
352
353
354
355
356
357
                expr = ((FunEntry*) slice)->body;
                frame_ptr = new_frame_ptr;
                continue;                    
            }
            case FT_SLICE:
            case FT_ADT:
            case FT_RECORD:
            {
                Thunk* thunk = updateF(get_dst(root_frame_ptr), slice);

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

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
358
                memcpy(&thunk->_args, &basethunk->_args, sizeof(Thunk*) * basethunk->desc->arity);
359
360
361

                for (int i = 0; i < expr->nr_args; i++) {
                    thunk->_args[basethunk->desc->arity + i] 
362
                            = ((AppEntry*) expr)->args[i]->create_thunk(((AppEntry*) expr)->args[i], frame_ptr);
363
364
365
366
                }

                set_return(root_frame_ptr, thunk);
                destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
367
                destroy_stack_frame_b(root_frame_ptr_b);
368
                return;                    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
369
            }
370
371
372
373
374
375
376
377
378
            case FT_BOXED_LIT:
                abort("Literal unexpected here");                
            case FT_CAF:
            case FT_CAF_REDUCED:
                not_implemented("CAF");
            }
        }
        case CT_VAR_STRICT:
        {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
379
            Thunk* arg = local(frame_ptr, ((VarEntry*) expr)->index);
380
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
381
            assert(is_hnf(arg));
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
382

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
383
            // TODO: check how often happens
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
384
385
            if(arg->desc->unboxable)
            {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
386
                memcpy(get_dst(root_frame_ptr), arg, sizeof(Thunk));
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
387
388
389
390
391
392
393
            }
            else
            {
                forward_thunk(arg, root_frame_ptr);
            }
            
            set_return(root_frame_ptr, arg);
394
            destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
395
            destroy_stack_frame_b(root_frame_ptr_b);            
396
397
398
399
400
            return;                    
        }
        case CT_VAR:
        {
            Thunk* thunk = local(frame_ptr, ((VarEntry*) expr)->index);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
401

402
403
404
            follow_thunk(thunk);
            forward_thunk(thunk, root_frame_ptr);            
            set_return(root_frame_ptr, thunk);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
405

406
407
408
            switch(thunk->desc->type) {
            case FT_FUN:
            {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
409
410
                // Destroy stack frame before eval, it is not needed any more
                // Greatly reduces stack usage
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
411
412
                destroy_stack_frame(root_frame_ptr);
                destroy_stack_frame_b(root_frame_ptr_b);  
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
413
414
415
416
                frame_ptr = stack_top_a;
                // Here frame_ptr == root_frame_ptr

                int argmask = 1;
417

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
418
                for (int i = 0; i < thunk->desc->arity; i++) {
419
                    arg_from_thunk(thunk->desc, thunk->_args[i]);
420
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
421
422
423

                expr = ((FunEntry*) thunk->desc)->body;
                continue;
424
            }
425
426
            case FT_PRIM1:
            case FT_PRIM2:
427
            {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
428
429
430
431
432
433

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

                ((PrimEntry*) thunk->desc)->exec(root_frame_ptr);
434
435
                
                destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
436
                destroy_stack_frame_b(root_frame_ptr_b);
437
438
439
440
441
442
443
444
445
446
                return;
            }
            case FT_CAF:
            case FT_CAF_REDUCED:
                not_implemented("CAF");            
            case FT_SLICE:
            case FT_ADT:
            case FT_RECORD:
            case FT_BOXED_LIT:
                destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
447
                destroy_stack_frame_b(root_frame_ptr_b);
448
449
                return;
            }            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
450
451
452
        }
        case CT_THUNK:
        {
453
454
            Thunk* thunk = &((ThunkEntry*) expr)->thunk;            
            forward_thunk(thunk, root_frame_ptr);            
455
            set_return(root_frame_ptr, thunk);
456
            destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
457
            destroy_stack_frame_b(root_frame_ptr_b);
458
            return;               
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
459
        }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
460
461
        case CT_SELECT:
        {
462
463
464
            Thunk* pattern = alloc_b();
            pattern->desc = (Desc*) __STACK_PLACEHOLDER__;
            push_a(pattern);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
465
            exec(((SelectEntry*) expr)->expr, frame_ptr, stack_top_a);
466
            pattern = pop_a();
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
467

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
468
469
            assert(is_hnf(pattern));
            assert(pattern->desc->type == FT_ADT);            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
470

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
471
472
473
474
            bool handled = false;
            
            for (int i = 0; i < expr->nr_cases; i++) {
                SelectCaseEntry* caseEntry = &((SelectEntry*) expr)->cases[i];
475
                
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
476
477
478
479
480
481
482
                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]);
483
                    }                  
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
484
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
485
486
487
488
                else if(caseEntry->type == SC_DEFAULT)
                {
                    // accept it
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
489
490
491
492
493
494
495
496
497
                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
498
499
            }

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
500
501
502
503
504
505
506
507
            if(handled) continue;
            
            printf("Exec: no select cases matches");
            print(pattern, false);
            exit(-1);
        }
        case CT_IF:
        {        
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
508
            push_a(alloc_b());
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
509
            exec(((IfEntry*) expr)->cond, frame_ptr, stack_top_a);
510
            Thunk* cond = pop_a();
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
511
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
512
513
514
515
516
517
518
519
            if (readB(cond)) {
                expr = ((IfEntry*) expr)->texpr;
                continue;                
            }
            else {
                expr = ((IfEntry*) expr)->fexpr;
                continue;     
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
520
        }
521
522
523
524
525
526
        }
    }
}

struct Thunk* eval(Thunk* thunk) {
    assert(thunk != NULL);    
527
        
528
529
530
531
532
533
534
535
536
537
538
539
540
    follow_thunk(thunk);
    
    switch(thunk->desc->type) {
    case FT_FUN:
    {
        push_a(thunk);
        int frame_ptr = stack_top_a;
        int argmask = 1;
        
        for (int i = 0; i < thunk->desc->arity; i++) {
            arg_from_thunk(thunk->desc, thunk->_args[i]);
        }
        
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
541
        exec(((FunEntry*) thunk->desc)->body, frame_ptr, frame_ptr);
542
543
544
        thunk = pop_a();
        return thunk;
    }
545
546
    case FT_PRIM1:
    case FT_PRIM2:
547
548
549
550
551
    {
        push_a(thunk);
        int frame_ptr = stack_top_a;

        for (int i = 0; i < thunk->desc->arity; i++) {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
552
553
554
555
556
557
558
559
            if(thunk->_args[i]->desc->hnf)
            {
                push_a(thunk->_args[i]);
            }
            else
            {
                push_a(eval(thunk->_args[i]));
            }
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
        }

        ((PrimEntry*) thunk->desc)->exec(frame_ptr);        
        
        stack_top_a = frame_ptr;        
        thunk = pop_a();
        return thunk;
    }
    case FT_CAF:
    case FT_CAF_REDUCED:
        not_implemented("CAF");            
    case FT_SLICE:
    case FT_ADT:
    case FT_RECORD:
    case FT_BOXED_LIT:
        return thunk;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
576
    }
577
}