Skip to content
Snippets Groups Projects
Commit a4b99815 authored by Michal Štěpánek's avatar Michal Štěpánek
Browse files

Continue with implementation up to method calls (only arrays missing)

parent ccfbc813
No related branches found
No related tags found
1 merge request!3Task2 odevzdání
......@@ -46,60 +46,15 @@ void vm_init ( VM * vm, size_t heap_size ) {
void vm_destroy ( VM * vm ) {
heap_destroy ( & vm -> heap );
ostack_destroy ( & vm -> stack );
for ( size_t i = 0; i < vm -> program . constant_count; ++i ) {
Constant constant = vm -> program . constant_pool [ i ];
if ( constant . kind == CONSTANT_CLASS )
free ( constant . class . members );
}
free ( vm -> program . globals . members );
free ( vm -> program . constant_pool );
}
 
// void * heap_alloc_alligned ( Heap * heap, size_t len, size_t align ) {
// size_t pos = (size_t) heap -> next;
// size_t rem = pos % align;
// if ( rem )
// heap -> next = heap -> next + align - rem;
// if ( heap -> next + len >= heap -> end )
// return NULL;
// void * ret = heap -> next;
// heap -> next += len;
// return ret;
// }
//
// void * heap_alloc ( Heap * heap, size_t len ) {
// size_t pos = (size_t) heap -> next;
// size_t rem = pos % 8;
// if ( rem )
// heap -> next = heap -> next + 8 - rem;
// if ( heap -> next + len >= heap -> end )
// return NULL;
// void * ret = heap -> next;
// heap -> next += len;
// return ret;
// }
//
// void heap_init ( Heap * heap, size_t heap_size ) {
// heap -> begin = (u8*) malloc ( heap_size );
// heap -> next = heap -> begin;
// heap -> end = heap -> begin + heap_size;
// }
//
// void heap_destroy ( Heap * heap ) {
// free ( heap -> begin );
// }
//Value * make_null ( ASTInterpreterState * state ) {
// NullValue * value = heap_alloc ( state -> heap, sizeof (NullValue) );
// *value = (NullValue) { .kind = (Value) { .kind = VALUE_NULL } };
// return (Value*) value;
//}
//
//Value * make_int ( ASTInterpreterState * state, i32 val ) {
// IntValue * value = heap_alloc ( state -> heap, sizeof (IntValue) );
// *value = (IntValue) { .kind = (Value) { .kind = VALUE_INTEGER }, .integer = val };
// return (Value*) value;
//}
//
//Value * make_bool ( ASTInterpreterState * state, bool val ) {
// BoolValue * value = heap_alloc ( state -> heap, sizeof (BoolValue) );
// *value = (BoolValue) { .kind = (Value) { .kind = VALUE_BOOLEAN }, .boolean = val };
// return (Value*) value;
//}
Value * alloc_constant ( VM * vm, u16 index ) {
assert ( vm -> program . constant_count > index );
Constant constant = vm -> program . constant_pool [ index ];
......@@ -118,6 +73,17 @@ Value * alloc_constant ( VM * vm, u16 index ) {
return NULL;
}
 
ObjectValue * create_object ( VM * vm, Class * class ) {
ObjectValue * object = (ObjectValue*) make_object ( & vm -> heap, class -> member_count );
Constant * pool = vm -> program . constant_pool;
for ( size_t i = 0; i < class -> member_count; ++i ) {
Constant constant = pool [ class -> members [ i ] ];
assert ( constant . kind == CONSTANT_STRING );
object -> members [ i ] = (SimpleEntry) { .name = constant . string, .value = NULL };
}
return object;
}
void print_operand_value ( Value * value ) {
switch ( value -> kind ) {
case VALUE_INTEGER:
......@@ -135,7 +101,7 @@ void print_operand_value ( Value * value ) {
case VALUE_FUNCTION:
printf ( "function" );
break;
/*case VALUE_ARRAY:
case VALUE_ARRAY:
putchar ( '[' );
ArrayValue * arr = (ArrayValue*) value;
for ( i32 i = 0; i < arr -> length; ++i ) {
......@@ -163,7 +129,7 @@ void print_operand_value ( Value * value ) {
print_operand_value ( obj -> members [ i ] . value );
}
putchar ( ')' );
break;*/
break;
default:
assert ( false );
}
......@@ -213,6 +179,7 @@ void print_call ( VM * vm, u16 index, u8 arguments ) {
} else
putchar ( c );
}
free ( args );
assert ( arg == arguments );
}
 
......@@ -233,6 +200,16 @@ static inline i32 read_i32 ( const u8 * data, size_t * pos ) {
return bytes [ 3 ] << 24 | bytes [ 2 ] << 16 | bytes [ 1 ] << 8 | bytes [ 0 ];
}
 
static inline Class read_class ( const u8 * data, size_t * pos ) {
Class class;
u16 elements = read_u16 ( data, pos );
class . member_count = elements;
class . members = (u16*) malloc ( elements * sizeof (u16) );
for ( size_t i = 0; i < elements; ++i )
class . members [ i ] = read_u16 ( data, pos );
return class;
}
void read_header ( Str input, size_t * pos ) {
u8 bytes [4];
for ( size_t i = 0; i < 4; ++i )
......@@ -283,6 +260,9 @@ void read_constant_pool ( Program * program, Str input, size_t * pos ) {
constant_pool [ i ] = (Constant) { .kind = CONSTANT_BOOLEAN, .boolean = read_byte ( input . str, pos ) };
// printf ( "%s\n", constant_pool [ i ] . boolean == true ? "true" : "false" );
break;
case 0x05: {
constant_pool [ i ] = (Constant) { .kind = CONSTANT_CLASS, .class = read_class ( input . str, pos ) };
}
default:
// printf ( "unsupported type\n" );
break;
......@@ -291,10 +271,9 @@ void read_constant_pool ( Program * program, Str input, size_t * pos ) {
program -> constant_pool = constant_pool;
}
 
void read_globals ( Str input, size_t * pos ) {
u16 elements = read_u16 ( input . str, pos );
*pos += elements;
}
// void read_globals ( Program * program, Str input, size_t * pos ) {
// program -> globals = read_class ( input . str, pos );
// }
 
void parse_program ( Program * program, Str input ) {
// read + check header
......@@ -302,27 +281,48 @@ void parse_program ( Program * program, Str input ) {
read_header ( input, &pos );
// read constant pool
read_constant_pool ( program, input, &pos );
read_globals ( input, &pos );
// read globals
program -> globals = read_class ( input . str, &pos );
// read EP
program -> entry_point = read_u16 ( input . str, &pos );
//printf ("EP: %u\n", program -> entry_point );
}
 
void bc_function_call ( VM * vm, u8 arguments ) {
// assert ( index < vm -> program . constant_count );
// assert ( vm -> program . constant_pool [ index ] . kind == CONSTANT_FUNCTION );
void bc_function_call ( VM * vm, u8 arguments, bool is_function, Str * name ) {
Value * tmp [256];
for ( size_t i = 0; i < arguments; ++i )
tmp [ i ] = ostack_pop ( & vm -> stack );
Value * fvalue = ostack_pop ( & vm -> stack );
assert ( fvalue -> kind == VALUE_FUNCTION );
ConstantFunction function = ((CFunctionValue*) fvalue ) -> function;
arguments = is_function ? arguments : arguments - 1;
for ( size_t i = arguments; i > 0; ++i )
tmp [ i - 1 ] = ostack_pop ( & vm -> stack );
Value * callee = ostack_pop ( & vm -> stack );
ConstantFunction function;
if ( is_function ) {
assert ( callee -> kind == VALUE_FUNCTION );
function = ((CFunctionValue*) callee ) -> function;
} else {
Value * field = *get_object_field ( callee, *name );
while ( ! field ) {
callee = ((ObjectValue*) callee ) -> extends;
if ( callee -> kind != VALUE_OBJECT )
break;
field = *get_object_field ( callee, *name );
}
if ( ! field ) {
Value * result = try_operator ( & vm -> heap, callee, tmp, arguments, name );
assert ( result );
ostack_push ( & vm -> stack, result );
}
assert ( field -> kind == VALUE_FUNCTION );
function = ((CFunctionValue*) field) -> function;
}
size_t local_count = function . parameters + function . locals;
Frame * new_frame = (Frame *) malloc ( sizeof (Frame) + local_count * sizeof (Value*) );
new_frame -> prev = vm -> local_frame;
new_frame -> return_ip = ++(vm -> instruction_pointer);
new_frame -> return_ip = vm -> instruction_pointer;
vm -> local_frame = new_frame;
assert ( arguments + 1 == function . parameters );
new_frame -> locals [ 0 ] = make_null ( & vm -> heap );
if ( is_function )
new_frame -> locals [ 0 ] = make_null ( & vm -> heap );
else
new_frame -> locals [ 0 ] = callee;
for ( size_t i = 1; i <= arguments; ++i )
new_frame -> locals [ i ] = tmp [ i - 1 ];
for ( size_t i = arguments + 1; i < local_count; ++i )
......@@ -332,29 +332,82 @@ void bc_function_call ( VM * vm, u8 arguments ) {
opcode = read_byte ( function . start, & vm -> instruction_pointer );
switch ( opcode ) {
case 0x00:
//printf ("drop\n");
// printf ("drop\n");
ostack_pop ( & vm -> stack );
break;
case 0x01: {
u16 index = read_u16 ( function . start, & vm -> instruction_pointer );
//printf ("constant %u\n", index);
// printf ("constant %u\n", index);
ostack_push ( & vm -> stack, alloc_constant ( vm, index ) );
break;
}
case 0x02: {
//printf ("print\n");
// printf ("print\n");
u16 index = read_u16 ( function . start, & vm -> instruction_pointer );
u8 arguments = read_byte ( function . start, & vm -> instruction_pointer );
print_call ( vm, index, arguments );
ostack_push ( & vm -> stack, make_null ( & vm -> heap) );
break;
}
case 0x04: {
// printf ("object\n");
u16 index = read_u16 ( function . start, & vm -> instruction_pointer );
Constant constant = vm -> program . constant_pool [ index ];
assert ( constant . kind == CONSTANT_CLASS );
assert ( constant . class . member_count < vm -> stack . size );
ObjectValue * obj = create_object ( vm, & constant . class );
for ( size_t i = obj -> member_cnt; i > 0; --i )
obj -> members [ i - 1 ] . value = ostack_pop ( & vm -> stack );
obj -> extends = ostack_pop ( & vm -> stack );
ostack_push ( & vm -> stack, (Value*) obj );
break;
}
case 0x05: {
// printf ("get field\n");
u16 index = read_u16 ( function . start, & vm -> instruction_pointer );
assert ( index < vm -> program . constant_count );
Constant name = vm -> program . constant_pool [ index ];
assert ( name . kind == CONSTANT_STRING );
Value * object = ostack_pop ( & vm -> stack );
assert ( object -> kind == VALUE_OBJECT );
Value ** field = get_object_field ( object, name . string );
assert ( field );
ostack_push ( & vm -> stack, *field );
break;
}
case 0x06: {
// printf ("set field\n");
u16 index = read_u16 ( function . start, & vm -> instruction_pointer );
assert ( index < vm -> program . constant_count );
Constant name = vm -> program . constant_pool [ index ];
assert ( name . kind == CONSTANT_STRING );
Value * value = ostack_pop ( & vm -> stack );
Value * object = ostack_pop ( & vm -> stack );
assert ( object -> kind == VALUE_OBJECT );
Value ** field = get_object_field ( object, name . string );
assert ( field );
*field = value;
ostack_push ( & vm -> stack, value );
break;
}
case 0x07: {
// printf ("method call\n");
u16 index = read_u16 ( function . start, & vm -> instruction_pointer );
u8 arguments = read_byte ( function . start, & vm -> instruction_pointer );
assert ( index < vm -> program . constant_count );
Constant name = vm -> program . constant_pool [ index ];
assert ( name . kind == CONSTANT_STRING );
bc_function_call ( vm, arguments, false, & name . string );
break;
}
case 0x08: {
// printf ("function call\n");
u8 arguments = read_byte ( function . start, & vm -> instruction_pointer );
bc_function_call ( vm, arguments );
bc_function_call ( vm, arguments, true, NULL );
break;
}
case 0x09: {
// printf ("set local\n");
u16 index = read_u16 ( function . start, & vm -> instruction_pointer );
assert ( index < local_count );
assert ( vm -> stack . size );
......@@ -362,12 +415,36 @@ void bc_function_call ( VM * vm, u8 arguments ) {
break;
}
case 0x0A: {
// printf ("get local\n");
u16 index = read_u16 ( function . start, & vm -> instruction_pointer );
assert ( index < local_count );
ostack_push ( & vm -> stack, new_frame -> locals [ index ] );
break;
}
case 0x0B: {
// printf ("set global\n");
u16 index = read_u16 ( function . start, & vm -> instruction_pointer );
assert ( index < vm -> program . constant_count );
Constant name = vm -> program . constant_pool [ index ];
assert ( name . kind == CONSTANT_STRING );
Value ** field = get_object_field ( vm -> globals, name . string );
assert ( field );
*field = ostack_top ( & vm -> stack );
break;
}
case 0x0C: {
// printf ("get global\n");
u16 index = read_u16 ( function . start, & vm -> instruction_pointer );
assert ( index < vm -> program . constant_count );
Constant name = vm -> program . constant_pool [ index ];
assert ( name . kind == CONSTANT_STRING );
Value ** field = get_object_field ( vm -> globals, name . string );
assert ( field );
ostack_push ( & vm -> stack, *field );
break;
}
case 0x0D: {
// printf ("cond\n");
i16 offset = (i16) read_u16 ( function . start, & vm -> instruction_pointer );
assert ( (i32) vm -> instruction_pointer >= offset && vm -> instruction_pointer + offset < function . len );
Value * cond = ostack_top ( & vm -> stack );
......@@ -376,12 +453,14 @@ void bc_function_call ( VM * vm, u8 arguments ) {
break;
}
case 0x0E: {
// printf ("jump\n");
i16 offset = (i16) read_u16 ( function . start, & vm -> instruction_pointer );
assert ( (i32) vm -> instruction_pointer >= offset && vm -> instruction_pointer + offset < function . len );
vm -> instruction_pointer += offset;
break;
}
case 0x0F: {
// printf ("ret\n");
Frame * tmp = vm -> local_frame;
vm -> local_frame = tmp -> prev;
vm -> instruction_pointer = tmp -> return_ip;
......@@ -389,7 +468,7 @@ void bc_function_call ( VM * vm, u8 arguments ) {
return;
}
default:
//printf ( "%d\n", opcode );
// printf ( "%d\n", opcode );
assert ( false );
}
}
......@@ -398,7 +477,11 @@ void bc_function_call ( VM * vm, u8 arguments ) {
int vm_interpret ( VM * vm, Str input ) {
parse_program ( & vm -> program, input );
ostack_push ( & vm -> stack, alloc_constant ( vm, vm -> program . entry_point ) );
bc_function_call ( vm, 0 );
ObjectValue * obj = create_object ( vm, & vm -> program . globals );
for ( size_t i = 0; i < obj -> member_cnt; ++i )
obj -> members [ i ] . value = make_null ( & vm -> heap );
vm -> globals = (Value*) obj;
bc_function_call ( vm, 0, true, NULL );
//Constant start = vm -> program . constant_pool [ vm -> program . entry_point ];
//u8 opcode;
......
......@@ -13,11 +13,17 @@ typedef enum {
CONSTANT_NULL,
CONSTANT_STRING,
CONSTANT_FUNCTION,
CONSTANT_CLASS
// VALUE_ARRAY,
// VALUE_OBJECT,
// VALUE_INVALID
} ConstantType;
 
typedef struct Class {
u16 member_count;
u16 * members;
} Class;
typedef struct Constant {
ConstantType kind;
union {
......@@ -25,13 +31,14 @@ typedef struct Constant {
bool boolean;
Str string;
ConstantFunction function;
Class class;
};
} Constant;
 
typedef struct Program {
u16 constant_count;
Constant * constant_pool;
//uint32_t * globals;
Class globals;
//size_t entry_point;
u16 entry_point;
} Program;
......@@ -58,7 +65,7 @@ typedef struct VM {
Program program;
Heap heap;
OperandStack stack;
//FrameStack fstack;
Value * globals;
Frame * local_frame;
size_t instruction_pointer;
} VM;
......@@ -77,16 +84,17 @@ void vm_destroy ( VM * vm );
//inline u8 read_byte ( Str str, size_t * pos );
 
Value * alloc_constant ( VM * vm, u16 index );
ObjectValue * create_object ( VM * vm, Class * class );
 
void print_operand_value ( Value * value );
void print_call ( VM * vm, u16 index, u8 arguments );
 
void read_header ( Str input, size_t * pos );
void read_constant_pool ( Program * program, Str input, size_t * pos );
void read_globals ( Str input, size_t * pos );
//void read_globals ( Program * program, Str input, size_t * pos );
void parse_program ( Program * program, Str input );
 
void bc_function_call ( VM * vm, u8 arguments );
void bc_function_call ( VM * vm, u8 arguments, bool is_function, Str * name );
 
//void bc_intepret ( VM * vm, Str input, size_t & offset );
int vm_interpret ( VM * vm, Str input );
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment