Commit afb6dc66 authored by Laszlo Domoszlai's avatar Laszlo Domoszlai
Browse files

+ store literals internally as thunk and just memcpy it when requested

+ execute a single VAR_FN when forced
+ refactor basic struct Desc definition to avoid cyclic includes
parent 27fa3129
...@@ -4,10 +4,9 @@ ...@@ -4,10 +4,9 @@
#include "debug.h" #include "debug.h"
#include "code.h" #include "code.h"
#include "desc.h"
#include "thunk.h"
#include "mem.h" #include "mem.h"
#include "desc.h"
void exec(Code* expr, int frame_ptr, int root_frame_ptr, Thunk* target, bool force) void exec(Code* expr, int frame_ptr, int root_frame_ptr, Thunk* target, bool force)
{ {
assert(expr != NULL); assert(expr != NULL);
...@@ -17,30 +16,29 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr, Thunk* target, bool for ...@@ -17,30 +16,29 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr, Thunk* target, bool for
switch (expr->type) { switch (expr->type) {
case CT_LIT: case CT_LIT:
stack_top_a = root_frame_ptr; stack_top_a = root_frame_ptr;
push_a(updateT(target, &((LitEntry*) expr)->thunk));
switch (expr->local_type) { return;
case LIT_INT:
push_a(updateI(target, ((LitEntry*) expr)->_int));
return;
case LIT_BOOL:
push_a(updateB(target, ((LitEntry*) expr)->_bool));
return;
default:
printf("Exec: Unhandled LIT type");
exit(-1);
}
break;
case CT_VAR: case CT_VAR:
stack_top_a = root_frame_ptr; stack_top_a = root_frame_ptr;
if (expr->local_type == VAR_LOCAL) { if (expr->local_type == VAR_LOCAL) {
push_a(forward_to(target, local(frame_ptr, ((VarEntry*) expr)->index))); Thunk* thunk = forward_to(target, local(frame_ptr, ((VarEntry*) expr)->index));
if(force) push_a(eval(thunk)); else push_a(thunk);
return; return;
}else{ }else{
push_a(updateF(target, get_slice(((VarEntry*) expr)->f, 0))); Desc* slice = get_slice(((VarEntry*) expr)->f, 0);
return;
if(force && slice->type == FT_FUN)
{
expr = ((FunEntry*)slice)->body;
continue;
}
else
{
push_a(updateF(target, get_slice(((VarEntry*) expr)->f, 0)));
return;
}
} }
break;
case CT_APP: case CT_APP:
{ {
// TODO: check over application // TODO: check over application
......
#ifndef __CODE_H #ifndef __CODE_H
#define __CODE_H #define __CODE_H
#include "desc.h"
#include "thunk.h" #include "thunk.h"
#define CT_LIT 1 #define CT_LIT 1
...@@ -23,21 +22,9 @@ struct Code { ...@@ -23,21 +22,9 @@ struct Code {
#define LIT_BOOL 4 #define LIT_BOOL 4
#define LIT_STRING 5 #define LIT_STRING 5
struct CleanString {
int length;
char chars[];
};
struct LitEntry { struct LitEntry {
struct Code base; struct Code base;
struct Thunk thunk;
union {
int _int;
double _real;
char _char;
int _bool;
struct CleanString _string;
};
}; };
#define VAR_LOCAL 0 #define VAR_LOCAL 0
......
...@@ -61,6 +61,30 @@ void gen_slices(SliceEntry* dest, Desc* forward_ptr, int arity) { ...@@ -61,6 +61,30 @@ void gen_slices(SliceEntry* dest, Desc* forward_ptr, int arity) {
} }
} }
int printDesc(Desc* f) {
switch (f->type) {
case FT_SLICE:
printDesc(((SliceEntry*) f)->forward_ptr);
return f->arity;
case FT_PRIM:
printf("%s", ((PrimEntry*) f)->name);
return f->arity;
case FT_FUN:
case FT_BOXED_LIT:
printf("%s", ((FunEntry*) f)->name);
return f->arity;
case FT_ADT:
printf("%s", ((ADTEntry*) f)->name);
return f->arity;
case FT_RECORD:
printf("%s", ((RecordEntry*) f)->name);
return f->arity;
default:
printf("printDesc: unhandled DESC %d\n", f->type);
exit(-1);
}
}
void init_desc() { void init_desc() {
__INT__ = alloc_prim("INT"); __INT__ = alloc_prim("INT");
__BOOL__ = alloc_prim("BOOL"); __BOOL__ = alloc_prim("BOOL");
......
#ifndef __DESC_H #ifndef __DESC_H
#define __DESC_H #define __DESC_H
#include "desc_base.h"
#include "thunk.h" #include "thunk.h"
#include "code.h" #include "code.h"
#define FT_BOXED_LIT 0
#define FT_RECORD 1
#define FT_ADT 2
#define FT_CAF 3
#define FT_CAF_REDUCED 4
#define FT_FUN 5
#define FT_SLICE 6
#define FT_PRIM 7
// LIMITATION: maximum 32 arguments // LIMITATION: maximum 32 arguments
struct Desc {
unsigned int type : 3;
unsigned int arity : 8;
};
struct FunEntry { struct FunEntry {
struct Desc base; struct Desc base;
int strictness; int strictness;
...@@ -50,7 +37,7 @@ struct CAFEntry { ...@@ -50,7 +37,7 @@ struct CAFEntry {
union { union {
char* parseCont; char* parseCont;
Code* body; Code* body;
Thunk* value; struct Thunk* value;
}; };
char name[]; char name[];
}; };
...@@ -80,6 +67,8 @@ Desc* get_slice(Desc* f, int nrargs); ...@@ -80,6 +67,8 @@ Desc* get_slice(Desc* f, int nrargs);
bool is_strict_fun_arg(FunEntry* f, int nr_arg); bool is_strict_fun_arg(FunEntry* f, int nr_arg);
int printDesc(Desc* f);
extern struct FunEntry* __INT__; extern struct FunEntry* __INT__;
extern struct FunEntry* __BOOL__; extern struct FunEntry* __BOOL__;
extern struct FunEntry* __CHAR__; extern struct FunEntry* __CHAR__;
......
#ifndef __DESC_BASE_H
#define __DESC_BASE_H
#define FT_BOXED_LIT 0
#define FT_RECORD 1
#define FT_ADT 2
#define FT_CAF 3
#define FT_CAF_REDUCED 4
#define FT_FUN 5
#define FT_SLICE 6
#define FT_PRIM 7
struct Desc {
unsigned int type : 3;
unsigned int arity : 8;
};
#endif // __DESC_H
\ No newline at end of file
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <assert.h>
#include "debug.h"
#include "mem.h" #include "mem.h"
int desc_alloc; int desc_alloc;
......
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
#include "parse.h" #include "parse.h"
#include "mem.h" #include "mem.h"
#include "desc.h"
#include "code.h" #include "code.h"
#include "desc.h"
int parseInt(char** ptr, int* result) { int parseInt(char** ptr, int* result) {
char *end; char *end;
...@@ -224,26 +224,29 @@ LitEntry* parseLit(char **ptr) { ...@@ -224,26 +224,29 @@ LitEntry* parseLit(char **ptr) {
struct LitEntry* entry = (LitEntry*) alloc_code(sizeof (LitEntry) + strlen + 1); struct LitEntry* entry = (LitEntry*) alloc_code(sizeof (LitEntry) + strlen + 1);
entry->base.type = CT_LIT; entry->base.type = CT_LIT;
switch (type) { switch (type) {
case 'I': // Int case 'I': // Int
{ {
entry->base.local_type = LIT_INT; entry->base.local_type = LIT_INT;
if (!parseInt(ptr, &entry->_int)) return 0; entry->thunk.desc = (Desc*) __INT__;
if (!parseInt(ptr, &entry->thunk._int)) return 0;
break; break;
} }
case 'C': // Char case 'C': // Char
{ {
entry->base.local_type = LIT_CHAR; entry->base.local_type = LIT_CHAR;
entry->_char = *(*ptr)++; entry->thunk.desc = (Desc*) __CHAR__;
entry->thunk._char = *(*ptr)++;
break; break;
} }
case 'R': // Real case 'R': // Real
{ {
entry->base.local_type = LIT_REAL; entry->base.local_type = LIT_REAL;
if (!parseReal(ptr, &entry->_real)) return 0; entry->thunk.desc = (Desc*) __REAL__;
if (!parseReal(ptr, &entry->thunk._real)) return 0;
break; break;
} }
...@@ -251,15 +254,15 @@ LitEntry* parseLit(char **ptr) { ...@@ -251,15 +254,15 @@ LitEntry* parseLit(char **ptr) {
case '1': case '1':
{ {
entry->base.local_type = LIT_BOOL; entry->base.local_type = LIT_BOOL;
entry->_bool = type == '1'; entry->thunk.desc = (Desc*) __BOOL__;
entry->thunk._bool = type == '1';
break; break;
} }
case 'S': // String case 'S': // String
{ {
entry->base.local_type = LIT_STRING; // TODO
entry->_string.length = strlen; return 0;
copyStringAndForward(entry->_string.chars, ptr, strlen);
} }
} }
......
#include <string.h> #include <string.h>
#include "prim.h" #include "prim.h"
...@@ -9,52 +8,25 @@ ...@@ -9,52 +8,25 @@
#define arg(idx) stack_a[stack_top_a - idx] #define arg(idx) stack_a[stack_top_a - idx]
struct Thunk* __add(Thunk* target) { struct Thunk* __add(Thunk* target) {
Thunk* arg1 = arg(2); return updateI(target, readI(arg(2)) + readI(arg(1)));
Thunk* arg2 = arg(1);
arg1 = eval(arg1);
arg2 = eval(arg2);
return updateI(target, readI(arg1) + readI(arg2));
} }
struct Thunk* __sub(Thunk* target) { struct Thunk* __sub(Thunk* target) {
Thunk* arg1 = arg(2); return updateI(target, readI(arg(2)) - readI(arg(1)));
Thunk* arg2 = arg(1);
arg1 = eval(arg1);
arg2 = eval(arg2);
return updateI(target, readI(arg1) - readI(arg2));
} }
struct Thunk* __gt(Thunk* target) { struct Thunk* __gt(Thunk* target) {
Thunk* arg1 = arg(2); return updateB(target, readI(arg(2)) > readI(arg(1)));
Thunk* arg2 = arg(1);
arg1 = eval(arg1);
arg2 = eval(arg2);
return updateB(target, readI(arg1) > readI(arg2));
} }
struct Thunk* __lt(Thunk* target) { struct Thunk* __lt(Thunk* target) {
Thunk* arg1 = arg(2); return updateB(target, readI(arg(2)) < readI(arg(1)));
Thunk* arg2 = arg(1);
arg1 = eval(arg1);
arg2 = eval(arg2);
return updateB(target, readI(arg1) < readI(arg2));
} }
struct Thunk* __eqI(Thunk* target) { struct Thunk* __eqI(Thunk* target) {
Thunk* arg1 = arg(2); Thunk* arg1 = arg(2);
Thunk* arg2 = arg(1); Thunk* arg2 = arg(1);
arg1 = eval(arg1);
arg2 = eval(arg2);
return updateB(target, readI(arg1) == readI(arg2)); return updateB(target, readI(arg1) == readI(arg2));
} }
...@@ -62,17 +34,12 @@ struct Thunk* __eqB(Thunk* target) { ...@@ -62,17 +34,12 @@ struct Thunk* __eqB(Thunk* target) {
Thunk* arg1 = arg(2); Thunk* arg1 = arg(2);
Thunk* arg2 = arg(1); Thunk* arg2 = arg(1);
arg1 = eval(arg1);
arg2 = eval(arg2);
return updateB(target, readB(arg1) == readB(arg2)); return updateB(target, readB(arg1) == readB(arg2));
} }
struct Thunk* __not(Thunk* target) { struct Thunk* __not(Thunk* target) {
Thunk* arg1 = arg(1); Thunk* arg1 = arg(1);
arg1 = eval(arg1);
return updateB(target, !readB(arg1)); return updateB(target, !readB(arg1));
} }
......
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
#include "debug.h" #include "debug.h"
#include "thunk.h" #include "thunk.h"
#include "desc.h"
#include "code.h"
#include "mem.h" #include "mem.h"
#include "desc.h"
#define max(a,b) \ #define max(a,b) \
({ __typeof__ (a) _a = (a); \ ({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \ __typeof__ (b) _b = (b); \
_a > _b ? _a : _b; }) _a > _b ? _a : _b; })
int printDesc(Desc* f) {
switch (f->type) {
case FT_SLICE:
printDesc(((SliceEntry*) f)->forward_ptr);
return f->arity;
case FT_PRIM:
printf("%s", ((PrimEntry*) f)->name);
return f->arity;
case FT_FUN:
case FT_BOXED_LIT:
printf("%s", ((FunEntry*) f)->name);
return f->arity;
case FT_ADT:
printf("%s", ((ADTEntry*) f)->name);
return f->arity;
case FT_RECORD:
printf("%s", ((RecordEntry*) f)->name);
return f->arity;
default:
printf("printDesc: unhandled DESC %d\n", f->type);
exit(-1);
}
}
Thunk* forward_to(Thunk* target, Thunk* thunk) { Thunk* forward_to(Thunk* target, Thunk* thunk) {
assert(thunk != NULL); assert(thunk != NULL);
...@@ -75,13 +51,15 @@ struct Thunk* updateI(Thunk* target, int i) { ...@@ -75,13 +51,15 @@ struct Thunk* updateI(Thunk* target, int i) {
int readI(Thunk* thunk) { int readI(Thunk* thunk) {
assert(thunk != NULL); assert(thunk != NULL);
#ifdef DEBUG
if (thunk->desc != (Desc*) __INT__) { if (thunk->desc != (Desc*) __INT__) {
printf("readI: not an integer\n"); printf("readI: not an integer\n");
printDesc(thunk->desc); printDesc(thunk->desc);
exit(-1); exit(-1);
} }
#endif
return thunk->_int; return thunk->_int;
} }
...@@ -97,14 +75,23 @@ struct Thunk* updateB(Thunk* target, int b) { ...@@ -97,14 +75,23 @@ struct Thunk* updateB(Thunk* target, int b) {
int readB(Thunk* thunk) { int readB(Thunk* thunk) {
assert(thunk != NULL); assert(thunk != NULL);
#ifdef DEBUG
if (thunk->desc != (Desc*) __BOOL__) { if (thunk->desc != (Desc*) __BOOL__) {
printf("readB: not a boolean\n"); printf("readB: not a boolean\n");
exit(-1); exit(-1);
} }
#endif
return thunk->_bool; return thunk->_bool;
} }
struct Thunk* updateT(Thunk* target, Thunk* source) {
if (target == NULL) target = (Thunk*) alloc_heap(sizeof (Thunk));
memcpy(target, source, sizeof(Thunk));
return target;
}
struct Thunk* updateF(Thunk* target, Desc* f) { struct Thunk* updateF(Thunk* target, Desc* f) {
assert(f != NULL); assert(f != NULL);
...@@ -130,48 +117,33 @@ struct Thunk* updateF(Thunk* target, Desc* f) { ...@@ -130,48 +117,33 @@ struct Thunk* updateF(Thunk* target, Desc* f) {
struct Thunk* eval(Thunk* thunk) { struct Thunk* eval(Thunk* thunk) {
assert(thunk != NULL); assert(thunk != NULL);
while (true) { while (thunk->desc == NULL) {
thunk = thunk->_forward_ptr;
}
if (thunk->desc->type == FT_FUN) {
int frame_ptr = stack_top_a;
while (thunk->desc == NULL) { for (int i = 0; i < thunk->desc->arity; i++) {
thunk = thunk->_forward_ptr; // TODO: handle strictness
push_a(thunk->_args[i]);
} }
exec(((FunEntry*) thunk->desc)->body, frame_ptr, frame_ptr, thunk, true);
thunk = pop_a();
}
else if(thunk->desc->type == FT_PRIM) {
int frame_ptr = stack_top_a;
//print(thunk, false); for (int i = 0; i < thunk->desc->arity; i++) {
//printf("\n"); push_a(thunk->_args[i]);
switch (thunk->desc->type) {
case FT_BOXED_LIT:
case FT_SLICE:
case FT_ADT:
case FT_RECORD:
return thunk;
case FT_FUN:
int frame_ptr;
frame_ptr = stack_top_a;
for (int i = 0; i < thunk->desc->arity; i++) {
// TODO: handle strictness
push_a(thunk->_args[i]);
}
exec(((FunEntry*) thunk->desc)->body, frame_ptr, frame_ptr, thunk, true);
thunk = pop_a();
break;
case FT_PRIM:
frame_ptr = stack_top_a;
for (int i = 0; i < thunk->desc->arity; i++) {
push_a(thunk->_args[i]);
}
((PrimEntry*) thunk->desc)->exec(thunk);
stack_top_a = frame_ptr;