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

Complete basic implementation

parent 1a278c2e
No related branches found
No related tags found
1 merge request!1Task1 odevzdání
Pipeline #257955 failed
...@@ -157,31 +157,147 @@ void state_destroy ( ASTInterpreterState * state ) { ...@@ -157,31 +157,147 @@ void state_destroy ( ASTInterpreterState * state ) {
} }
} }
   
Value function_call ( ASTInterpreterState * state, Value function, bool is_function, Ast ** arguments, size_t argc ) { Value try_operator ( Value object, Value * arguments, size_t argc, Str * name ) {
switch ( object . kind ) {
case VALUE_INTEGER:
if ( argc != 1 || arguments [ 0 ] . kind != VALUE_INTEGER ) {
fprintf ( stderr, "Invalid argument for integer operation %.*s.\n", (int) name -> len, name -> str );
exit ( 10 );
}
if ( str_eq ( *name, STR ("+") ) )
return (Value) { .kind = VALUE_INTEGER, .integer = object . integer + arguments [ 0 ] . integer };
if ( str_eq ( *name, STR ("-") ) )
return (Value) { .kind = VALUE_INTEGER, .integer = object . integer - arguments [ 0 ] . integer };
if ( str_eq ( *name, STR ("*") ) )
return (Value) { .kind = VALUE_INTEGER, .integer = object . integer * arguments [ 0 ] . integer };
if ( str_eq ( *name, STR ("/") ) )
return (Value) { .kind = VALUE_INTEGER, .integer = object . integer / arguments [ 0 ] . integer };
if ( str_eq ( *name, STR ("%%") ) )
return (Value) { .kind = VALUE_INTEGER, .integer = object . integer % arguments [ 0 ] . integer };
if ( str_eq ( *name, STR ("<=") ) )
return (Value) { .kind = VALUE_BOOLEAN, .boolean = object . integer <= arguments [ 0 ] . integer };
if ( str_eq ( *name, STR (">=") ) )
return (Value) { .kind = VALUE_BOOLEAN, .boolean = object . integer >= arguments [ 0 ] . integer };
if ( str_eq ( *name, STR ("<") ) )
return (Value) { .kind = VALUE_BOOLEAN, .boolean = object . integer < arguments [ 0 ] . integer };
if ( str_eq ( *name, STR (">") ) )
return (Value) { .kind = VALUE_BOOLEAN, .boolean = object . integer > arguments [ 0 ] . integer };
if ( str_eq ( *name, STR ("==") ) )
return (Value) { .kind = VALUE_BOOLEAN, .boolean = object . integer == arguments [ 0 ] . integer };
if ( str_eq ( *name, STR ("!=") ) )
return (Value) { .kind = VALUE_BOOLEAN, .boolean = object . integer != arguments [ 0 ] . integer };
break;
case VALUE_BOOLEAN:
if ( argc != 1 || arguments [ 0 ] . kind != VALUE_BOOLEAN ) {
fprintf ( stderr, "Invalid argument for bool operation %.*s.\n", (int) name -> len, name -> str );
exit ( 10 );
}
if ( str_eq ( *name, STR ("&") ) )
return (Value) { .kind = VALUE_BOOLEAN, .boolean = object . boolean & arguments [ 0 ] . boolean };
if ( str_eq ( *name, STR ("|") ) )
return (Value) { .kind = VALUE_BOOLEAN, .boolean = object . boolean | arguments [ 0 ] . boolean };
if ( str_eq ( *name, STR ("==") ) )
return (Value) { .kind = VALUE_BOOLEAN, .boolean = object . boolean == arguments [ 0 ] . boolean };
if ( str_eq ( *name, STR ("!=") ) )
return (Value) { .kind = VALUE_BOOLEAN, .boolean = object . boolean != arguments [ 0 ] . boolean };
break;
case VALUE_NULL:
if ( argc != 1 ) {
fprintf ( stderr, "Invalid amount of arguments for null operation %.*s.\n", (int) name -> len, name -> str );
exit ( 10 );
}
if ( str_eq ( *name, STR ("==") ) )
return (Value) { .kind = VALUE_BOOLEAN, .boolean = arguments [ 0 ] . kind == VALUE_NULL };
if ( str_eq ( *name, STR ("!=") ) )
return (Value) { .kind = VALUE_BOOLEAN, .boolean = arguments [ 0 ] . kind != VALUE_NULL };
break;
case VALUE_ARRAY:
if ( str_eq ( *name, STR ("get") ) ) {
if ( argc != 1 || arguments [ 0 ] . kind != VALUE_INTEGER ) {
fprintf ( stderr, "Invalid argument for array get.\n" );
exit ( 11 );
}
Value * data = (Value*) object . address;
i32 index = arguments [ 0 ] . integer;
if ( index < 0 || index >= data [ 0 ] . integer ) {
fprintf ( stderr, "Index is out of bounds.\n" );
exit ( 11 );
}
return data [ index + 1 ];
}
if ( str_eq ( *name, STR ("set") ) ) {
if ( argc != 2 || arguments [ 0 ] . kind != VALUE_INTEGER ) {
fprintf ( stderr, "Invalid arguments for array set.\n" );
exit ( 12 );
}
Value * data = (Value*) object . address;
i32 index = arguments [ 0 ] . integer;
if ( index < 0 || index >= data [ 0 ] . integer ) {
fprintf ( stderr, "Index is out of bounds.\n" );
exit ( 12 );
}
data [ index + 1 ] = arguments [ 1 ];
return data [ index + 1 ];
}
break;
default:
break;
}
fprintf ( stderr, "Method %.*s does not exist.\n", (int) name -> len, name -> str );
exit ( 13 );
return (Value) { .kind = VALUE_NULL };
}
Value function_call ( ASTInterpreterState * state, Value callee, bool is_function, Ast ** arguments, size_t argc, Str * name ) {
Value * values = (Value *) malloc ( argc * sizeof (Value) ); Value * values = (Value *) malloc ( argc * sizeof (Value) );
for ( size_t i = 0; i < argc; ++i ) for ( size_t i = 0; i < argc; ++i )
values [ i ] = evaluate ( state, arguments [ i ] ); values [ i ] = evaluate ( state, arguments [ i ] );
Value ret = (Value) { .kind = VALUE_NULL }; Value ret = (Value) { .kind = VALUE_NULL };
if ( is_function ) { Value function = callee;
if ( function . kind != VALUE_FUNCTION ) { if ( ! is_function ) {
fprintf ( stderr, "Invalid calee.\n" ); function = (Value) { .kind = VALUE_NULL };
exit ( 4 ); Value * next = &callee;
Value * curr;
Object * tmp;
while ( next -> kind == VALUE_OBJECT ) {
curr = next;
tmp = (Object*) curr -> address;
for ( size_t i = 0; i < tmp -> member_cnt; ++i )
if ( str_eq ( tmp -> members [ i ] . name, *name ) ) {
function = tmp -> members [ i ] . value;
callee = *curr;
break;
}
next = & tmp -> extends;
}
if ( function . kind == VALUE_NULL ) {
ret = try_operator ( callee, values, argc, name );
free ( values );
return ret;
} }
Environment * tmp = state -> current_env; } if ( function . kind != VALUE_FUNCTION ) {
fprintf ( stderr, "Invalid callee.\n" );
exit ( 4 );
}
Environment * tmp;
if ( is_function ) {
tmp = state -> current_env;
state -> current_env = NULL; state -> current_env = NULL;
env_push ( state );
env_def ( state, STR ("this"), (Value) { .kind = VALUE_NULL} );
for ( size_t i = 0; i < argc; ++i )
env_def ( state, function . function -> parameters [ i ], values [ i ] );
ret = evaluate ( state, function . function -> body );
env_pop ( state );
state -> current_env = tmp;
} }
env_push ( state );
env_def ( state, STR ("this"), is_function ? (Value) { .kind = VALUE_NULL } : callee );
for ( size_t i = 0; i < argc; ++i )
env_def ( state, function . function -> parameters [ i ], values [ i ] );
ret = evaluate ( state, function . function -> body );
env_pop ( state );
if ( is_function )
state -> current_env = tmp;
free ( values ); free ( values );
return ret; return ret;
} }
   
static Value * get_object_field ( Value * object, Str name ) { Value * get_object_field ( Value * object, Str name ) {
Value * next = object; Value * next = object;
Object * curr; Object * curr;
do { do {
...@@ -191,8 +307,7 @@ static Value * get_object_field ( Value * object, Str name ) { ...@@ -191,8 +307,7 @@ static Value * get_object_field ( Value * object, Str name ) {
return & curr -> members [ i ] . value; return & curr -> members [ i ] . value;
next = & curr -> extends; next = & curr -> extends;
} while ( next -> kind == VALUE_OBJECT ); } while ( next -> kind == VALUE_OBJECT );
fprintf ( stderr, "Field %.*s was not found in specified object.\n", (int) name . len, name . str ); return NULL;
exit ( 8 );
} }
   
void print_value ( Value value ) { void print_value ( Value value ) {
...@@ -355,7 +470,16 @@ Value evaluate ( ASTInterpreterState * state, Ast * ast ) { ...@@ -355,7 +470,16 @@ Value evaluate ( ASTInterpreterState * state, Ast * ast ) {
case AST_FUNCTION_CALL: { case AST_FUNCTION_CALL: {
AstFunctionCall * callAst = (AstFunctionCall*) ast; AstFunctionCall * callAst = (AstFunctionCall*) ast;
Value function = evaluate ( state, callAst -> function ); Value function = evaluate ( state, callAst -> function );
return function_call ( state, function, true, callAst -> arguments, callAst -> argument_cnt ); return function_call ( state, function, true, callAst -> arguments, callAst -> argument_cnt, NULL );
}
case AST_METHOD_CALL: {
AstMethodCall * methodAst = (AstMethodCall*) ast;
Value object = evaluate ( state, methodAst -> object );
if ( object . kind == VALUE_FUNCTION ) {
fprintf ( stderr, "Calling method on function.\n" );
exit ( 4 );
}
return function_call ( state, object, false, methodAst -> arguments, methodAst -> argument_cnt, &methodAst -> name );
} }
case AST_ARRAY: { case AST_ARRAY: {
AstArray * arrAst = (AstArray*) ast; AstArray * arrAst = (AstArray*) ast;
...@@ -372,6 +496,21 @@ Value evaluate ( ASTInterpreterState * state, Ast * ast ) { ...@@ -372,6 +496,21 @@ Value evaluate ( ASTInterpreterState * state, Ast * ast ) {
} }
return (Value) { .kind = VALUE_ARRAY, .address = addr }; return (Value) { .kind = VALUE_ARRAY, .address = addr };
} }
case AST_INDEX_ACCESS: {
AstIndexAccess * iaccess = (AstIndexAccess*) ast;
Value object = evaluate ( state, iaccess -> object );
Str tmp = STR ("get");
return function_call ( state, object, false, &iaccess -> index, 1, &tmp );
}
case AST_INDEX_ASSIGNMENT: {
AstIndexAssignment * iassign = (AstIndexAssignment*) ast;
Value object = evaluate ( state, iassign -> object );
Ast * arguments [2];
arguments [ 0 ] = iassign -> index;
arguments [ 1 ] = iassign -> value;
Str tmp = STR ("set");
return function_call ( state, object, false, arguments, 2, &tmp );
}
case AST_OBJECT: { case AST_OBJECT: {
AstObject * objAst = (AstObject*) ast; AstObject * objAst = (AstObject*) ast;
Value extends = evaluate ( state, objAst -> extends ); Value extends = evaluate ( state, objAst -> extends );
...@@ -403,17 +542,10 @@ Value evaluate ( ASTInterpreterState * state, Ast * ast ) { ...@@ -403,17 +542,10 @@ Value evaluate ( ASTInterpreterState * state, Ast * ast ) {
exit ( 8 ); exit ( 8 );
} }
Value * result = get_object_field ( &object_value, accessAst -> field ); Value * result = get_object_field ( &object_value, accessAst -> field );
/*Value * next = &object_value; if ( ! result ) {
Object * curr; fprintf ( stderr, "Field %.*s was not found in specified object.\n", (int) accessAst -> field . len, accessAst -> field . str );
do { exit ( 8 );
curr = (Object*) next -> address; }
for ( size_t i = 0; i < curr -> member_cnt; ++i )
if ( str_eq ( curr -> members [ i ] . name, accessAst -> field ) )
return curr -> members [ i ] . value;
next = & curr -> extends;
} while ( next -> kind == VALUE_OBJECT );
fprintf ( stderr, "Field %.*s was not found in specified object.\n", (int) accessAst -> field . len, accessAst -> field . str );
exit ( 9 );*/
return *result; return *result;
} }
case AST_FIELD_ASSIGNMENT: { case AST_FIELD_ASSIGNMENT: {
...@@ -425,19 +557,10 @@ Value evaluate ( ASTInterpreterState * state, Ast * ast ) { ...@@ -425,19 +557,10 @@ Value evaluate ( ASTInterpreterState * state, Ast * ast ) {
} }
Value value = evaluate ( state, assignAst -> value ); Value value = evaluate ( state, assignAst -> value );
Value * result = get_object_field ( &object_value, assignAst -> field ); Value * result = get_object_field ( &object_value, assignAst -> field );
/*Value * next = &object_value; if ( ! result ) {
Object * curr; fprintf ( stderr, "Field %.*s was not found in specified object.\n", (int) assignAst -> field . len, assignAst -> field . str );
do { exit ( 8 );
curr = (Object*) next -> address; }
for ( size_t i = 0; i < curr -> member_cnt; ++i )
if ( str_eq ( curr -> members [ i ] . name, assignAst -> field ) ) {
curr -> members [ i ] . value = value;
return value;
}
next = & curr -> extends;
} while ( next -> kind == VALUE_OBJECT );
fprintf ( stderr, "Field %.*s was not found in specified object.\n", (int) assignAst -> field . len, assignAst -> field . str );
exit ( 9 );*/
*result = value; *result = value;
return value; return value;
} }
......
...@@ -66,8 +66,9 @@ void heap_destroy ( Heap * heap ); ...@@ -66,8 +66,9 @@ void heap_destroy ( Heap * heap );
void state_init ( ASTInterpreterState * state, Heap * heap ); void state_init ( ASTInterpreterState * state, Heap * heap );
void state_destroy ( ASTInterpreterState * state ); void state_destroy ( ASTInterpreterState * state );
   
static Value * get_object_field (Value * object, Str name ); Value * get_object_field (Value * object, Str name );
Value function_call ( ASTInterpreterState * state, Value function, bool is_function, Ast ** arguments, size_t argc ); Value try_operator ( Value object, Value * arguments, size_t argc, Str * name );
Value function_call ( ASTInterpreterState * state, Value callee, bool is_function, Ast ** arguments, size_t argc, Str * name );
void print_value ( Value value ); void print_value ( Value value );
void fml_print ( Str format, Value * args, size_t argc ); void fml_print ( Str format, Value * args, size_t argc );
Value evaluate ( ASTInterpreterState * state, Ast * ast ); Value evaluate ( ASTInterpreterState * state, Ast * ast );
\ No newline at end of file
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