code.c 31.8 KB
Newer Older
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
1
2
3
4
5
6
7
/*
 * Some properties: 
 * - get_dst(root_frame_ptr) can be NULL, but never a FORWARD_PTR (at least I hope so)
 *   
 *
 */

8
9
#include <stdio.h>
#include <stdlib.h>
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
10
#include <stdbool.h>
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
11
#include <strings.h>
12

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
13
#include "debug.h"
14
#include "code.h"
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
15
#include "mem.h"
16
#include "desc.h"
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
17
#include "gc.h"
18

19
20
// For compressing the source code a bit

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
21
22
#define instackb(addr) ((char*)addr >= (char*) &stack_b[0] && (char*)addr < (char*) &stack_b[STACK_SIZE_B])

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
23
#define follow_thunk(thunk) while (thunk->desc == (Desc*) __FORWARD_PTR__) thunk = thunk->_forward_ptr;
24
25
26

#define forward_thunk(thunk, frame_ptr) \
        Thunk* dst = get_dst(frame_ptr); \
27
        if(dst != NULL){ \
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
28
29
            dst->desc = (Desc*) __FORWARD_PTR__; \
            dst->_forward_ptr = thunk; \
30
        }
31

Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
32
#define placeholder() \
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
33
        push_a(alloc_b());
34

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
35
#define arg_from_code(descarg, arg) \
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
36
        if(((FunEntry*) (descarg))->boxing & argmask) \
37
        { \
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
38
            placeholder(); \
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
39
            exec(arg, frame_ptr, stack_top_a); \
40
        } \
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
41
42
43
44
45
        else if(((FunEntry*) (descarg))->strictness & argmask) \
        { \
            push_a(NULL); \
            exec(arg, frame_ptr, stack_top_a); \
        } \
46
47
        else \
        { \
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
48
            arg->create_thunk(arg, &stack_a[stack_top_a++], frame_ptr); \
49
50
51
        } \
        argmask <<= 1;

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
52
void create_thunk_app_static(Code* expr, Thunk** target, int frame_ptr)
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
53
{
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
54
    Thunk* thunk = (Thunk*) alloc_heap(((AppEntry*) expr)->f->thunk_size);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
55
    *target = thunk;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
56
    thunk->desc = ((AppEntry*) expr)->f;
57

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

60
    for (int i = 0; i < expr->nr_args; i++) {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
61
62
         ((AppEntry*) expr)->args[i]->create_thunk(((AppEntry*) expr)->args[i], &thunk->_args[i], frame_ptr);
    }                     
63
}
64

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
65
void create_thunk_app_dyn(Code* expr, Thunk** target, int frame_ptr)
66
{
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
67
    push_a(local(frame_ptr, ((AppEntry*)expr)->var.index));
68

Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
69
70
71
72
73
74
75
    int tmp = gc_enabled;
    gc_enabled = 0;
    peek_a()->desc->eval();
    gc_enabled = tmp;
    
    Thunk* basethunk = pop_a();
    
76
77
78
    Desc* slice =
            get_slice(basethunk->desc->type == FT_SLICE ?
                      ((SliceEntry*) basethunk->desc)->forward_ptr : basethunk->desc, basethunk->desc->arity + expr->nr_args);
79

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
80
81
    Thunk* thunk = (Thunk*) alloc_heap(slice->thunk_size);
    thunk->desc = slice;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
82
83
    *target = thunk;
    
84
85
86
87
88
    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++) {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
89
90
        ((AppEntry*) expr)->args[i]->create_thunk(((AppEntry*) expr)->args[i], &thunk->_args[basethunk->desc->arity + i], frame_ptr);
    } 
91
92
}

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
93
void create_thunk_var(Code* expr, Thunk** target, int frame_ptr)
94
{
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
95
    *target = local(frame_ptr, ((VarEntry*) expr)->index);    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
96
    assert(!instackb(*target));
97
98
}

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
99
void create_thunk_var_unboxed(Code* expr, Thunk** target, int frame_ptr)
100
101
102
{
    Thunk* arg = local(frame_ptr, ((VarEntry*) expr)->index);

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
103
104
105
    if(instackb(arg))
    {
        // The likely case
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
106
107
108
        Thunk* newthunk = (Thunk*) alloc_heap(sizeof (Thunk));
        memcpy(newthunk, arg, sizeof(Thunk));
        *target = newthunk;        
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
109
110
111
    }
    else
    {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
112
        *target = arg;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
113
    }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
114
115
    
    assert(!instackb(*target));
116
117
}

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
118
void create_thunk_thunk(Code* expr, Thunk** target, int frame_ptr)
119
{
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
120
    *target = &((ThunkEntry*) expr)->thunk;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
121
    assert(!instackb(*target));
122
123
}

124
void set_create_thunk_fun(Code* code)
125
{
126
127
    switch(code->type)
    {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
128
        case CT_APP_PRIM_FAST:
129
        case CT_APP_PRIM:            
130
        case CT_APP_FUN:
131
        case CT_APP_FUN_TR:
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
132
133
        case CT_APP_FUN1:
        case CT_APP_FUN2:
134
135
136
137
138
139
140
        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:
141
        case CT_VAR_STRICT:            
142
143
            code->create_thunk = create_thunk_var;
            break;
144
145
        case CT_VAR_UNBOXED:
            code->create_thunk = create_thunk_var_unboxed;
146
147
148
149
            break;
        case CT_THUNK:
            code->create_thunk = create_thunk_thunk;
            break;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
150
151
        case CT_SELECT_ADT:
        case CT_SELECT_LIT:    
152
        case CT_SELECT_STR:
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
153
        case CT_SELECT_REC:
154
        case CT_IF:
155
        case CT_LET:
156
157
158
            code->create_thunk = NULL;
            break;            
    }
159
160
}

161
162
163
164
165
166
167
// eval: frame_ptr, frame_ptr
// start: stack_top_a, stack_top_a
// otherwise: frame_ptr, stack_top_a

// frame_ptr: first arguments
// root_frame_ptr: place of the result

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
168
void exec(Code* expr, int frame_ptr, int root_frame_ptr)
169
{
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
170
171
    if(heap_curr > gc_trigger) gc();
    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
172
    int root_frame_ptr_b = stack_top_b;    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
173
    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
174
    while(1)
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
175
    {  
176
        assert(expr != NULL);
177
        assert(stack_top_a < STACK_SIZE_A);
178
        assert(stack_top_b < STACK_SIZE_B);
179
180
181

        // TODO: check over application
        // TODO: enforce strictness in ADT/Record
182
        
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
183
        switch (expr->type) {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
184
        case CT_APP_PRIM_FAST:
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
185
        {                         
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
186
187
            // careful, "exec" may trigger garbage collection
            // read local variables only after the last exec            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
188
189
            switch(expr->arg_pattern)
            {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
190
191
192
193
194
195
            case 0:
                placeholder();                       
                exec(((AppEntry*) expr)->args[0], frame_ptr, stack_top_a);
                placeholder();                        
                exec(((AppEntry*) expr)->args[1], frame_ptr, stack_top_a);
                break;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
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
            case 1:
                push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[0])->index));  
                push_a(&((ThunkEntry*) ((AppEntry*) expr)->args[1])->thunk);
                break;
            case 2:
                push_a(&((ThunkEntry*) ((AppEntry*) expr)->args[0])->thunk);            
                push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[1])->index));                        
                break;
            case 3:
                push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[0])->index));
                push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[1])->index));
                break;                    
            case 4:
                push_a(&((ThunkEntry*) ((AppEntry*) expr)->args[0])->thunk);            
                placeholder();                       
                exec(((AppEntry*) expr)->args[1], frame_ptr, stack_top_a);                    
                break;                    
            case 5:
                placeholder();                     
                exec(((AppEntry*) expr)->args[0], frame_ptr, stack_top_a);
                push_a(&((ThunkEntry*) ((AppEntry*) expr)->args[1])->thunk);                                
                break;                    
            case 6:
                push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[0])->index));
                placeholder();                       
                exec(((AppEntry*) expr)->args[1], frame_ptr, stack_top_a);
                break;                    
            case 7:
                placeholder();                        
                exec(((AppEntry*) expr)->args[0], frame_ptr, stack_top_a);
                push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[1])->index));
                break;                    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
228
229
230
231
232
233
234
            case 8:
                push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[0])->index));  
                break;
            case 9:
                push_a(&((ThunkEntry*) ((AppEntry*) expr)->args[0])->thunk);            
                break;
            default: // 10
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
235
                placeholder();                        
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
236
237
                exec(((AppEntry*) expr)->args[0], frame_ptr, stack_top_a);
                break;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
238
            }
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
239
            
240
241
242
243
244
            if(get_dst(root_frame_ptr) == NULL && (((AppEntry*) expr)->f)->unboxable_return)
            {
                Thunk* tmp = (Thunk*) alloc_heap(sizeof(Thunk));
                set_return(root_frame_ptr, tmp);
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
245

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

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
248
249
250
251
            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);
            return;            
        }
252
253
        case CT_APP_PRIM:
        {           
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
254
255
            PrimEntry* desc = (PrimEntry*) ((AppEntry*) expr)->f;
            int argmask = 1;            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
256

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
257
258
259
260
261
262
263
264
265
266
            for (int i = 0; i < desc->base.arity; i++) {

                if(desc->boxingMap & argmask)
                {
                    placeholder();
                }
                else
                {
                    push_a(NULL);
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
267
268
                
                exec(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
269
270
271
                argmask <<= 1;            
            }

272
273
274
275
276
            if(get_dst(root_frame_ptr) == NULL && (((AppEntry*) expr)->f)->unboxable_return)
            {
                Thunk* tmp = (Thunk*) alloc_heap(sizeof(Thunk));
                set_return(root_frame_ptr, tmp);
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
277

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
278
279
280
281
282
            desc->exec(root_frame_ptr);
            
            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);
            return;            
283
        }        
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
284
285
286
287
288
289
290
        case CT_APP_FUN1:
        {
            Desc* slice = ((AppEntry*) expr)->f;

            int argmask = 1;            
            arg_from_code(slice, ((AppEntry*) expr)->args[0]);
              
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
291
292
293
294
295
296
#ifdef DEBUG_EXEC            
            printf("FUN1: <");
            printDesc(slice);
            printf(">\n");
#endif            
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
297
298
299
300
301
302
303
            expr = ((FunEntry*) slice)->body;
            frame_ptr = stack_top_a - 1;
            continue;                        
        }        
        case CT_APP_FUN2:
        {
            Desc* slice = ((AppEntry*) expr)->f;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
304

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
305
306
307
308
            int argmask = 1;
            
            arg_from_code(slice, ((AppEntry*) expr)->args[0]);
            arg_from_code(slice, ((AppEntry*) expr)->args[1]);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
309
310
311
312
313
314
315

#ifdef DEBUG_EXEC
            printf("FUN2: <");
            printDesc(slice);
            printf(">\n");
#endif
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
316
317
318
319
            expr = ((FunEntry*) slice)->body;
            frame_ptr = stack_top_a - 2;
            continue;                        
        }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
320
        case CT_APP_FUN:
321
        {            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
322
            Desc* slice = ((AppEntry*) expr)->f;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
323

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
324
325
            int new_frame_ptr = stack_top_a;
            int argmask = 1;
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
326
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
327
328
            for (int i = 0; i < expr->nr_args; i++) {
                arg_from_code(slice, ((AppEntry*) expr)->args[i]);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
329
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
330

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
331
332
333
334
335
336
#ifdef DEBUG_EXEC
            printf("FUN: <");
            printDesc(slice);
            printf(">\n");
#endif
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
337
            expr = ((FunEntry*) slice)->body;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
338

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
339
340
341
            frame_ptr = new_frame_ptr;
            continue;            
        }
342
343
344
        case CT_APP_FUN_TR:
        {            
            Desc* slice = ((AppEntry*) expr)->f;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
345

346
347
348
349
350
351
352
353
354
355
            // TODO: B stack?
            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]);
            }

            memcpy(&stack_a[frame_ptr], &stack_a[new_frame_ptr], sizeof(void*) * expr->nr_args);
            stack_top_a = frame_ptr + expr->nr_args;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
356
357
358
359
360
361
 
#ifdef DEBUG_EXEC
            printf("FUN TR: <");
            printDesc(slice);
            printf(">\n");
#endif
362
363
364
365
            
            expr = ((FunEntry*) slice)->body;
            continue;            
        }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
366
367
368
        case CT_APP_THUNK:
        {
            Desc* slice = ((AppEntry*) expr)->f;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
369
            Thunk* thunk = get_dst(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
370

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
371
372
373
374
375
376
#ifdef DEBUG_EXEC
            printf("APP THUNK: <");
            printDesc(slice);
            printf(">\n");
#endif
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
377
            // no need to check for array length, thunks in HNF are never overwritten
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
378
379
            int newsize = slice->thunk_size;
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
380
381
382
383
            if (thunk == NULL)
            {
                thunk = (Thunk*) alloc_heap(newsize);
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
384
385
            else if (thunk->desc->thunk_size < newsize) 
            {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
386
387
388
                Thunk* target = thunk;
                thunk = (Thunk*) alloc_heap(newsize);
                target->desc = (Desc*) __FORWARD_PTR__;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
389
                target->_forward_ptr = thunk;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
390
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
391

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
392
            set_return(root_frame_ptr, thunk);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
393
394
            thunk->desc = slice;
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
395
            assert(thunk->desc->arity == expr->nr_args);
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
396
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
397
398
            for (int i = 0; i < expr->nr_args; i++) {  
                ((AppEntry*) expr)->args[i]->create_thunk(((AppEntry*) expr)->args[i], &thunk->_args[i], frame_ptr);
399
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
400
401
402
403
404

            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);
            return;                                
        }
405
        case CT_APP_DYN:
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
406
        {
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
407
408
409
            push_a(local(frame_ptr, ((AppEntry*)expr)->var.index));

            Thunk** bt = &peek_a();
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
410
            (*bt)->desc->eval(); // eval follows FORWARD_PTRs
411
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
412
            // The original fun arity if it is a slice
413
414
415
            Desc* baseDesc = (*bt)->desc->type == FT_SLICE ?
                              ((SliceEntry*) (*bt)->desc)->forward_ptr : (*bt)->desc;
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
416
417
            int totalArity = (*bt)->desc->arity + expr->nr_args;            
            int usedNrArgs = 0;
418
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
419
420
421
            Desc* slice;
            
            while(totalArity > baseDesc->arity)
422
            {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
                // must be an FT_FUN
                                
                Desc* d = (*bt)->desc;
                
                int remainingNrArgs = totalArity - baseDesc->arity;        
                slice = get_slice(baseDesc, baseDesc->arity);
              
                int new_frame_ptr = stack_top_a;
                                                
                int argmask = 1;
                
                for (int i = 0; i < (*bt)->desc->arity; i++) {
                    push_a((*bt)->_args[i]);
                    if(((FunEntry*) (slice))->strictness & argmask) 
                    { 
                        (*bt)->_args[i]->desc->eval(); 
                    } 
                    argmask <<= 1;
                }

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

                // VERY important, otherwise we overwrite the original thunk with something else
                set_return(new_frame_ptr, NULL);
                exec(((FunEntry*) slice)->body, new_frame_ptr, new_frame_ptr);
                                
                totalArity = (*bt)->desc->arity + expr->nr_args - usedNrArgs;
453
                
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
454
455
                baseDesc = (*bt)->desc->type == FT_SLICE ?
                              ((SliceEntry*) (*bt)->desc)->forward_ptr : (*bt)->desc;                
456
457
            }
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
458
            slice = get_slice(baseDesc, totalArity);
459
            
460
            switch(slice->type) {
461
            case FT_PRIM:
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
462
            {
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
463
464
                for (int i = 0; i < (*bt)->desc->arity; i++) {
                    push_a((*bt)->_args[i]);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
465
                    (*bt)->_args[i]->desc->eval();
466
                }
467

Laszlo Domoszlai's avatar
fix bug    
Laszlo Domoszlai committed
468
                int argmask = 1 << (*bt)->desc->arity;  
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
469

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
470
                for (int i = usedNrArgs; i < expr->nr_args; i++) {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
471
472
473
474
475
476
477
478
479
480
                    
                    if(((PrimEntry*) slice)->boxingMap & argmask)
                    {
                        placeholder();
                    }
                    else
                    {
                        push_a(NULL);
                    }

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
481
                    exec(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
482
483
                    argmask <<= 1;            
                }
484

485
486
487
488
489
490
                if(get_dst(root_frame_ptr) == NULL && slice->unboxable_return)
                {
                    Thunk* tmp = (Thunk*) alloc_heap(sizeof(Thunk));
                    set_return(root_frame_ptr, tmp);
                }
                                
491
                ((PrimEntry*) slice)->exec(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
492
                destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
493
                destroy_stack_frame_b(root_frame_ptr_b);                
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
494
495
                return;                    
            }
496
497
498
499
500
            case FT_FUN:
            {
                int new_frame_ptr = stack_top_a;                    
                int argmask = 1;

Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
501
502
                for (int i = 0; i < (*bt)->desc->arity; i++) {                    
                    push_a((*bt)->_args[i]);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
503
                    if(((FunEntry*) (slice))->strictness & argmask) 
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
504
505
506
507
                    { 
                        (*bt)->_args[i]->desc->eval(); 
                    } 
                    argmask <<= 1;
508
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
509
510
                
                for (int i = usedNrArgs; i < expr->nr_args; i++) {
511
512
                    arg_from_code(slice, ((AppEntry*) expr)->args[i]);    
                } 
513

514
515
516
517
518
519
520
521
                expr = ((FunEntry*) slice)->body;
                frame_ptr = new_frame_ptr;
                continue;                    
            }
            case FT_SLICE:
            case FT_ADT:
            case FT_RECORD:
            {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
522
                Thunk* thunk = get_dst(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
523
                // no need to check for array length, thunks in HNF are never overwritten
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
524
525
                int newsize = slice->thunk_size;

Laszlo Domoszlai's avatar
fix bug    
Laszlo Domoszlai committed
526
527
528
529
                if (thunk == NULL)
                {
                    thunk = (Thunk*) alloc_heap(newsize);
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
530
531
                else if (thunk->desc->thunk_size < newsize) 
                {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
532
533
534
                    Thunk* target = thunk;
                    thunk = (Thunk*) alloc_heap(newsize);
                    target->desc = (Desc*) __FORWARD_PTR__;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
535
                    target->_forward_ptr = thunk;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
536
                }
Laszlo Domoszlai's avatar
fix bug    
Laszlo Domoszlai committed
537
                
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
538
                set_return(root_frame_ptr, thunk);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
539
540
                thunk->desc = slice;
                
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
541
                assert(thunk->desc->arity == (*bt)->desc->arity + expr->nr_args);            
542

Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
543
                memcpy(&thunk->_args, &(*bt)->_args, sizeof(Thunk*) * (*bt)->desc->arity);
544

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
545
                for (int i = usedNrArgs; i < expr->nr_args; i++) {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
546
                    ((AppEntry*) expr)->args[i]->create_thunk(((AppEntry*) expr)->args[i], &thunk->_args[(*bt)->desc->arity + i], frame_ptr);
547
548
549
                }

                destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
550
                destroy_stack_frame_b(root_frame_ptr_b);
551
                return;                    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
552
            }
553
554
555
556
557
558
559
            case FT_BOXED_LIT:
                abort("Literal unexpected here");                
            case FT_CAF:
            case FT_CAF_REDUCED:
                not_implemented("CAF");
            }
        }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
560
        case CT_VAR_UNBOXED:       
561
        {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
562
            Thunk* arg = local(frame_ptr, ((VarEntry*) expr)->index);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
563
564
            follow_thunk(arg);
                        
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
565
            assert(is_hnf(arg));
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
566

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
567
568
569
570
#ifdef DEBUG_EXEC
            printf("VAR@: %d\n", ((VarEntry*) expr)->index);
#endif
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
571
            // no need to check for array length, thunks in HNF are never overwritten
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
            if(get_dst(root_frame_ptr) != NULL)
            {
                memcpy(get_dst(root_frame_ptr), arg, sizeof(Thunk));
            }
            else
            {
                if(instackb(arg))
                {
                    Thunk* newthunk = (Thunk*) alloc_heap(sizeof (Thunk));
                    memcpy(newthunk, arg, sizeof(Thunk));
                    set_return(root_frame_ptr, newthunk);
                }
                else
                {
                    set_return(root_frame_ptr, arg);
                }
            }
            
            destroy_stack_frame(root_frame_ptr);
            destroy_stack_frame_b(root_frame_ptr_b);            
            return;                                
        }
        case CT_VAR_STRICT:     
        {
            Thunk* arg = local(frame_ptr, ((VarEntry*) expr)->index);
            follow_thunk(arg);
                        
            assert(is_hnf(arg));

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
601
602
603
604
#ifdef DEBUG_EXEC
            printf("VAR!: %d\n", ((VarEntry*) expr)->index);
#endif
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
605
606
607
            // no need to check for array length, thunks in HNF are never overwritten
            // arrays always referenced
            if(get_dst(root_frame_ptr) != NULL && arg->desc->thunk_size <= sizeof(Thunk) && arg->desc != (Desc*) __ARRAY__)
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
608
            {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
609
                memcpy(get_dst(root_frame_ptr), arg, sizeof(Thunk));
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
610
611
612
613
            }
            else
            {
                forward_thunk(arg, root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
614
                set_return(root_frame_ptr, arg);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
615
616
            }
            
617
            destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
618
            destroy_stack_frame_b(root_frame_ptr_b);            
619
620
621
622
623
            return;                    
        }
        case CT_VAR:
        {
            Thunk* thunk = local(frame_ptr, ((VarEntry*) expr)->index);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
624

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
625
626
627
628
#ifdef DEBUG_EXEC
            printf("VAR: %d\n", ((VarEntry*) expr)->index);
#endif
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
629
630
            assert(!instackb(thunk));
            
631
632
633
            follow_thunk(thunk);
            forward_thunk(thunk, root_frame_ptr);            
            set_return(root_frame_ptr, thunk);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
634

635
636
637
            switch(thunk->desc->type) {
            case FT_FUN:
            {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
638
639
                // Destroy stack frame before eval, it is not needed any more
                // Greatly reduces stack usage
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
640
641
                destroy_stack_frame(root_frame_ptr);
                destroy_stack_frame_b(root_frame_ptr_b);  
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
642
                                
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
643
644
645
646
                frame_ptr = stack_top_a;
                // Here frame_ptr == root_frame_ptr

                int argmask = 1;
647

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
648
                for (int i = 0; i < thunk->desc->arity; i++) {
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
649
                    push_a(thunk->_args[i]);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
650
                    if(((FunEntry*) (thunk->desc))->strictness & argmask) 
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
651
652
653
654
655
                    { 
                        thunk->_args[i]->desc->eval(); 
                        thunk = stack_a[root_frame_ptr-1];
                    }
                    argmask <<= 1;
656
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
657
658
659

                expr = ((FunEntry*) thunk->desc)->body;
                continue;
660
            }
661
            case FT_PRIM:
662
            {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
663
                for (int i = 0; i < thunk->desc->arity; i++) {
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
664
                    push_a(thunk->_args[i]);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
665
                    thunk->_args[i]->desc->eval();
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
666
                    thunk = stack_a[root_frame_ptr-1];
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
667
668
                }

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
669
670
                // get_dst(root_frame_ptr) cannot be NULL, no need to check
                
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
671
                ((PrimEntry*) thunk->desc)->exec(root_frame_ptr);
672
673
                
                destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
674
                destroy_stack_frame_b(root_frame_ptr_b);                
675
676
677
678
679
680
681
682
683
684
                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
685
                destroy_stack_frame_b(root_frame_ptr_b);
686
687
                return;
            }            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
688
689
690
        }
        case CT_THUNK:
        {
691
            Thunk* thunk = &((ThunkEntry*) expr)->thunk;            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
            Thunk* dst = get_dst(root_frame_ptr);

            if(dst != NULL)
            {
                memcpy(dst, thunk, sizeof(Thunk));
                
                if(!instackb(dst))
                {
                    set_return(root_frame_ptr, thunk);
                }                
            }
            else
            {
                set_return(root_frame_ptr, thunk);
            }

708
            destroy_stack_frame(root_frame_ptr);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
709
            destroy_stack_frame_b(root_frame_ptr_b);
710
            return;               
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
711
        }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
712
713
        case CT_SELECT_LIT:
        {
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
714
            placeholder();
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
715
            exec(((SelectEntry*) expr)->expr, frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
716
            Thunk* lit = pop_a();
717
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
718
719
720
721
            bool handled = false;
            
            for (int i = 0; i < expr->nr_cases; i++) {
                SelectLitCaseEntry* caseEntry = &((SelectEntry*) expr)->cases[i];
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
722

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
723
724
                // NULL means "default", we accept it anyway
                if(caseEntry->lit != NULL)
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
725
                {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
726
                    assert(caseEntry->lit->thunk.desc == (Desc*) __INT__ ||
727
                           caseEntry->lit->thunk.desc == (Desc*) __BOOL__ || 
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
728
729
                           caseEntry->lit->thunk.desc == (Desc*) __CHAR__ ||
                           caseEntry->lit->thunk.desc == (Desc*) __REAL__);
730

Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
731
732
733
734
735
736
737
738
                    if(caseEntry->lit->thunk.desc == (Desc*) __REAL__)
                    {
                        if(caseEntry->lit->thunk._real != lit->_real) continue;
                    }
                    else
                    {
                        if(caseEntry->lit->thunk._int != lit->_int) continue;
                    }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
739
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
740
                
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
                // must be SC_DEFAULT now
                handled = true;
                expr = caseEntry->body;
                break;
            }
            
            if(handled) continue;
            
            if(((SelectEntry*) expr)->fallback != NULL)
            {
                stack_top_a -= ((SelectEntry*) expr)->fallback_nrargs;
                expr = ((SelectEntry*) expr)->fallback;
                
                continue;
            }
            
            abort("no match");
        }
        case CT_SELECT_STR:
        {                        
            SelectEntry* select = (SelectEntry*) expr;
            
            push_a(NULL);
            exec(select->expr, frame_ptr, stack_top_a);
            Thunk* str = pop_a();
            
            int length;
            char* chars;

            if(str->desc == (Desc*) __STRING_PTR__)
            {
                chars = str->_string_ptr->chars;
                length = str->_string_ptr->length;
            }
            else
            {
                chars = str->_array._chars;
                length = str->_array.length;
            }
            
            bool handled = false;
            
            for (int i = 0; i < expr->nr_cases; i++) {
                SelectLitCaseEntry* caseEntry = &((SelectEntry*) expr)->cases[i];

                // NULL means "default", we accept it anyway
                if(caseEntry->lit != NULL)
                {
                    assert(caseEntry->lit->thunk.desc == (Desc*) __STRING_PTR__); 

                    int eq = length == caseEntry->lit->thunk._string_ptr->length;
                    int i = 0;
                    while(i<length && eq)
                    {
                        eq = chars[i] == caseEntry->lit->thunk._string_ptr->chars[i];
                        i++;
                    }
                    
                    if(!eq) continue;
                }
                
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
802
803
804
805
806
807
808
809
                // must be SC_DEFAULT now
                handled = true;
                expr = caseEntry->body;
                break;
            }
            
            if(handled) continue;
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
810
811
812
813
814
815
816
817
818
            if(((SelectEntry*) expr)->fallback != NULL)
            {
                stack_top_a -= ((SelectEntry*) expr)->fallback_nrargs;
                expr = ((SelectEntry*) expr)->fallback;
                
                continue;
            }
            
            abort("no match");
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
819
820
821
        }
        case CT_SELECT_ADT:
        {                        
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
822
823
            SelectEntry* select = (SelectEntry*) expr;
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
824
            push_a(NULL);
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
825
            exec(select->expr, frame_ptr, stack_top_a);
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
826
            Thunk* cons = pop_a();            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
827
                                    
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
828
            expr = select->bodies[((ADTEntry*)cons->desc)->idx];
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
829
830
831
            
            if(expr != NULL)
            {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
832
833
834
835
836
837
838
                // Skip the arguments in the case of a default 
                if(!(select->default_map & 1<<((ADTEntry*)cons->desc)->idx))
                {
                    for (int i = 0; i < cons->desc->arity; i++) {
                        push_a(cons->_args[i]);
                    }                                      
                }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
839
840
841
                
                continue;
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
842
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
843
844
845
846
847
848
849
850
851
            if(select->fallback != NULL)
            {
                stack_top_a -= select->fallback_nrargs;
                expr = select->fallback;
                
                continue;
            }
            
            abort("no match");
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
852
        }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
        case CT_SELECT_REC:
        {                        
            SelectEntry* select = (SelectEntry*) expr;
            
            push_a(NULL);
            exec(select->expr, frame_ptr, stack_top_a);
            Thunk* cons = pop_a();            
            
            expr = select->bodies[0];
            
            if(expr != NULL)
            {
                for (int i = 0; i < cons->desc->arity; i++) {
                    push_a(cons->_args[i]);
                }                  
                
                continue;
            }
            
            // This cannot happen in record field selection            
            abort("no match");
        }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
875
876
        case CT_IF:
        {        
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
877
            placeholder();
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
878
            exec(((IfEntry*) expr)->cond, frame_ptr, stack_top_a);
879
            Thunk* cond = pop_a();
880
            
881
            // safe to do it before read as nothing can overwrite it in between
882
883
            stack_top_b--;
            
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
884
885
886
887
888
889
890
891
            if (readB(cond)) {
                expr = ((IfEntry*) expr)->texpr;
                continue;                
            }
            else {
                expr = ((IfEntry*) expr)->fexpr;
                continue;     
            }
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
892
        }
893
894
895
896
897
898
899
900
901
        case CT_LET:
        {
            for(int i=0; i<expr->nr_bindings; i++)
            {
                LetBindingEntry* binding = ((LetEntry*) expr)->bindings[i];
                
                // Normal
                if(binding->type == 0)
                {
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
902
                    binding->body->create_thunk(binding->body, &stack_a[stack_top_a++], frame_ptr);
903
904
905
906
907
908
909
910
911
912
913
                }
                else // strict (including unboxed))
                {
                    push_a(NULL);
                    exec(binding->body, frame_ptr, stack_top_a);
                }
            }
            
            expr = ((LetEntry*) expr)->body;
            continue;
        }
914
915
916
917
        }
    }
}

Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
918
919
920
921
922
923
924
925
926
927
void eval_hnf()
{
    return;
}

void eval_fun()
{
    Thunk* thunk = peek_a();    
    int frame_ptr = stack_top_a;
    int argmask = 1;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
928
    
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
929
930
931
932
933
934
935
    for (int i = 0; i < thunk->desc->arity; i++) {
        push_a(thunk->_args[i]);

        if(((FunEntry*) (thunk->desc))->strictness & argmask)
        {
            thunk->_args[i]->desc->eval();
            thunk = stack_a[frame_ptr-1]; // refresh thunk ptr after eval 
936
937
        }
        
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
938
        argmask <<= 1;
939
940
    }

Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
941
942
    exec(((FunEntry*) thunk->desc)->body, frame_ptr, frame_ptr);
}
943

Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
944
945
946
947
948
949
950
951
952
void eval_prim()
{
    Thunk* thunk = peek_a();
    int frame_ptr = stack_top_a;

    for (int i = 0; i < thunk->desc->arity; i++) {
        push_a(thunk->_args[i]);        
        thunk->_args[i]->desc->eval();
        thunk = stack_a[frame_ptr-1]; // refresh thunk ptr after eval 
953
    }
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988

    ((PrimEntry*) thunk->desc)->exec(frame_ptr);        

    stack_top_a = frame_ptr;        
}

void eval_fwd_ptr()
{
    Thunk* thunk = pop_a();
    follow_thunk(thunk);
    push_a(thunk);
    thunk->desc->eval();
}   
   
void set_eval_fun(Desc* desc)
{
    if(desc == (Desc*) __FORWARD_PTR__)
    {
        desc->eval = eval_fwd_ptr;
        return;
    }
    
    switch(desc->type)
    {
        case FT_BOXED_LIT:
        case FT_RECORD:
        case FT_ADT:
        case FT_CAF:
        case FT_CAF_REDUCED:
        case FT_SLICE:
            desc->eval = eval_hnf;
            break;
        case FT_FUN:
            desc->eval = eval_fun;
            break;
989
        case FT_PRIM:
Laszlo Domoszlai's avatar
GC    
Laszlo Domoszlai committed
990
991
            desc->eval = eval_prim;
            break;
Laszlo Domoszlai's avatar
Laszlo Domoszlai committed
992
    }
993
}