@@ -175,6 +175,38 @@ static void scope_add_variable(Interpreter_Object* interp, int var_id) {
175175 scope -> variable_ids [scope -> count ++ ] = var_id ;
176176}
177177
178+ void resolve_escape_characters (char * str ) {
179+ char * src = str ;
180+ char * dst = str ;
181+
182+ while (* src ) {
183+ if (* src == '\\' ) {
184+ src ++ ;
185+ switch (* src ) {
186+ case 'n' : * dst ++ = '\n' ; break ;
187+ case 't' : * dst ++ = '\t' ; break ;
188+ case 'r' : * dst ++ = '\r' ; break ;
189+ case '0' : * dst ++ = '\0' ; break ;
190+ case '\\' : * dst ++ = '\\' ; break ;
191+ case '"' : * dst ++ = '"' ; break ;
192+ case '\'' : * dst ++ = '\'' ; break ;
193+ default :
194+ * dst ++ = '\\' ;
195+ * dst ++ = * src ;
196+ break ;
197+ }
198+
199+ if (* src ) {
200+ src ++ ;
201+ }
202+ } else {
203+ * dst ++ = * src ++ ;
204+ }
205+ }
206+
207+ * dst = '\0' ;
208+ }
209+
178210GaloObject interpret_node (Interpreter_Object * interp , Node * node ) {
179211 if (node -> type == NODE_STRUCT_DECLARATION || node -> type == NODE_FUNCTION_DECLARATION ) {
180212 return void_object_value (); // handled by validator
@@ -294,7 +326,8 @@ GaloObject interpret_node(Interpreter_Object* interp, Node* node) {
294326 * (float * )object .data = value ;
295327 return object ;
296328 } else if (token -> type == TOKEN_CONSTANT_STRING ) {
297- const char * value = token -> value ;
329+ char * value = (char * )token -> value ;
330+ resolve_escape_characters (value );
298331 object .type_id = STRING_TYPE ;
299332 object .size = strlen (value ) + 1 ;
300333 object .data = malloc (object .size );
@@ -550,14 +583,210 @@ GaloObject interpret_node(Interpreter_Object* interp, Node* node) {
550583 } else if (node -> type == NODE_CONTINUE_STATEMENT ) {
551584 interp -> did_continue = true;
552585 return void_object_value ();
586+ } else if (node -> type == NODE_RETURN_STATEMENT ) {
587+ interp -> did_return = true;
588+ ReturnStatement * return_stmt = (ReturnStatement * )node -> data ;
589+ if (return_stmt -> value .type != NODE_EMPTY ) {
590+ GaloObject value = interpret_node (interp , & return_stmt -> value );
591+ return value ;
592+ }
593+ return void_object_value ();
594+ } else if (node -> type == NODE_FUNCTION_CALL ) {
595+ FunctionCall * func_call = (FunctionCall * )node -> data ;
596+
597+ int argument_count = func_call -> argument_count ;
598+ GaloObject * arguments = calloc (argument_count , sizeof (GaloObject ));
599+
600+ for (int i = 0 ; i < argument_count ; i ++ ) {
601+ Node arg = func_call -> arguments [i ];
602+ arguments [i ] = interpret_node (interp , & arg );
603+ }
604+
605+ GaloObject return_value = void_object_value ();
606+
607+ if (func_call -> id < interp -> validator_object -> predefined_functions -> size ) {
608+ // predefined function call
609+ PredefinedFunction * predefined_function = (PredefinedFunction * )get_object (interp -> validator_object -> predefined_functions , func_call -> id );
610+ return_value = predefined_function_call (interp , predefined_function , argument_count , arguments );
611+ } else {
612+ // user defined function call
613+ FunctionDeclaration * func = (FunctionDeclaration * )get_object (interp -> validator_object -> functions , func_call -> id );
614+ return_value = function_call (interp , func , argument_count , arguments );
615+ }
616+
617+ for (int i = 0 ; i < argument_count ; i ++ ) {
618+ GaloObject arg = arguments [i ];
619+ free (arg .data );
620+ }
621+ free (arguments );
622+
623+ return return_value ;
553624 } else {
554- printf ("TODO nodetype: %s\n" , get_node_type_name (node -> type ));
625+ printf ("ERROR: Unknown nodetype: %s\n" , get_node_type_name (node -> type ));
555626 exit (1 );
556627 }
557628
558629 return void_object_value ();
559630}
560631
632+ GaloObject predefined_function_call (Interpreter_Object * interp , PredefinedFunction * predefined_function , int argument_count , GaloObject * arguments ) {
633+ int id = predefined_function -> id ;
634+ GaloObject (* function )(Interpreter_Object * interp , GaloObject * args , int arg_count ) = interp -> builtins [id ];
635+ return function (interp , arguments , argument_count );
636+ }
637+ GaloObject function_call (Interpreter_Object * interp , FunctionDeclaration * function , int argument_count , GaloObject * arguments ) {
638+ printf ("TODO: function_call\n" );
639+ exit (1 );
640+ }
641+ void add_builtin_function (Interpreter_Object * interp , char * name , GaloObject (* function )(Interpreter_Object * interp , GaloObject * args , int arg_count )) {
642+ PredefinedFunction * pf = NULL ;
643+ for (int i = 0 ; i < interp -> validator_object -> predefined_functions -> size ; i ++ ) {
644+ PredefinedFunction * index = (PredefinedFunction * )get_object (interp -> validator_object -> predefined_functions , i );
645+ if (strcmp (index -> name , name ) == 0 ) {
646+ pf = index ;
647+ break ;
648+ }
649+ }
650+
651+ if (pf == NULL ) {
652+ printf ("DEVELOPER ERROR: Function %s not found in predefined functions from the validator object\n" , name );
653+ exit (1 );
654+ }
655+
656+ interp -> builtins [pf -> id ] = function ;
657+ }
658+
659+ static void append_to_string (char * * buffer , size_t * capacity , size_t * length , const char * text ) {
660+ size_t add = strlen (text );
661+
662+ if (* length + add + 1 > * capacity ) {
663+ * capacity = (* capacity + add + 1 ) * 2 ;
664+ char * new_buf = realloc (* buffer , * capacity );
665+ if (!new_buf ) {
666+ printf ("Out of memory\n" );
667+ exit (1 );
668+ }
669+ * buffer = new_buf ;
670+ }
671+
672+ memcpy (* buffer + * length , text , add );
673+ * length += add ;
674+ (* buffer )[* length ] = '\0' ;
675+ }
676+
677+ GaloObject string_object_value (char * string ) {
678+ GaloObject object ;
679+ object .type_id = STRING_TYPE ;
680+ object .size = strlen (string ) + 1 ;
681+ object .data = string ;
682+ return object ;
683+ }
684+
685+ GaloObject builtin_to_string (Interpreter_Object * interp , GaloObject * args , int arg_count ) {
686+ if (arg_count != 1 ) {
687+ printf ("ERROR: to_string() takes 1 argument\n" );
688+ exit (1 );
689+ }
690+ GaloObject object = args [0 ];
691+ if (object .type_id == STRING_TYPE ) {
692+ char * string = strdup ((char * )object .data );
693+ GaloObject new_object = string_object_value (string );
694+ return new_object ;
695+ } else if (object .type_id == INT_TYPE ) {
696+ char * string = calloc (32 , sizeof (char ));
697+ sprintf (string , "%d" , * (int * )object .data );
698+ GaloObject new_object = string_object_value (string );
699+ return new_object ;
700+ } else if (object .type_id == FLOAT_TYPE ) {
701+ char * string = calloc (32 , sizeof (char ));
702+ sprintf (string , "%f" , * (float * )object .data );
703+ GaloObject new_object = string_object_value (string );
704+ return new_object ;
705+ } else if (object .type_id == BOOLEAN_TYPE ) {
706+ char * string = calloc (6 , sizeof (char ));
707+ if (* (bool * )object .data ) {
708+ sprintf (string , "true" );
709+ } else {
710+ sprintf (string , "false" );
711+ }
712+ GaloObject new_object = string_object_value (string );
713+ return new_object ;
714+ } else if (object .type_id == BYTE_TYPE ) {
715+ char * string = calloc (8 , sizeof (char ));
716+ sprintf (string , "%d" , * (unsigned char * )object .data );
717+ GaloObject new_object = string_object_value (string );
718+ return new_object ;
719+ } else if (object .type_id == LIST_TYPE ) {
720+ size_t cap = 64 ;
721+ size_t len = 0 ;
722+ char * string = malloc (cap );
723+ string [0 ] = '\0' ;
724+
725+ append_to_string (& string , & cap , & len , "[" );
726+
727+ ObjectList * list = (ObjectList * )object .data ;
728+
729+ for (int i = 0 ; i < list -> size ; i ++ ) {
730+ GaloObject * item = get_object (list , i );
731+ GaloObject item_str = builtin_to_string (interp , item , 1 );
732+
733+ append_to_string (& string , & cap , & len , (char * )item_str .data );
734+
735+ if (i != list -> size - 1 ) {
736+ append_to_string (& string , & cap , & len , ", " );
737+ }
738+
739+ free (item_str .data );
740+ }
741+
742+ append_to_string (& string , & cap , & len , "]" );
743+
744+ return string_object_value (string );
745+ } else {
746+ size_t cap = 64 ;
747+ size_t len = 0 ;
748+ char * string = malloc (cap );
749+ string [0 ] = '\0' ;
750+
751+ append_to_string (& string , & cap , & len , "{" );
752+
753+ StructDeclaration * decl = get_struct_from_id (object .type_id , interp -> validator_object );
754+
755+ for (int i = 0 ; i < decl -> field_count ; i ++ ) {
756+ GaloObject field = get_field_in_struct (interp , object , object .type_id , decl -> fields [i ].name .name );
757+
758+ GaloObject field_str = builtin_to_string (interp , & field , 1 );
759+
760+ append_to_string (& string , & cap , & len , decl -> fields [i ].name .name -> value );
761+ append_to_string (& string , & cap , & len , " = " );
762+ append_to_string (& string , & cap , & len , (char * )field_str .data );
763+
764+ if (i != decl -> field_count - 1 ) {
765+ append_to_string (& string , & cap , & len , ", " );
766+ }
767+
768+ free (field_str .data );
769+ }
770+
771+ append_to_string (& string , & cap , & len , "}" );
772+
773+ return string_object_value (string );
774+ }
775+ }
776+
777+ GaloObject builtin_print (Interpreter_Object * interp , GaloObject * args , int arg_count ) {
778+ for (int i = 0 ; i < arg_count ; i ++ ) {
779+ GaloObject arg = args [i ];
780+ GaloObject arg_to_string = builtin_to_string (interp , & arg , 1 );
781+ char * string = (char * )arg_to_string .data ;
782+ printf ("%s" , string );
783+ free (arg_to_string .data );
784+ }
785+
786+ return void_object_value ();
787+ }
788+
789+
561790Interpreter_Object * create_interpreter_object (NodeList * ast , Validator_Object * validator_object ) {
562791 Interpreter_Object * interp = calloc (1 , sizeof (Interpreter_Object ));
563792
@@ -573,6 +802,12 @@ Interpreter_Object* create_interpreter_object(NodeList* ast, Validator_Object* v
573802 interp -> call_capacity = 64 ;
574803 interp -> call_stack = calloc (interp -> call_capacity , sizeof (CallFrame ));
575804
805+ interp -> builtin_count = validator_object -> predefined_functions -> size ;
806+ interp -> builtins = calloc (interp -> builtin_count , sizeof (GaloObject (* )(Interpreter_Object * interp , GaloObject * args , int arg_count )));
807+
808+ add_builtin_function (interp , "to_string" , builtin_to_string );
809+ add_builtin_function (interp , "print" , builtin_print );
810+
576811 return interp ;
577812}
578813
0 commit comments