void function_trace_print(Process *process) { printf(" ----------------------------------------------------------------\n"); for(int i = process->function_trace_pos - 1; i >= 0; i--) { printf("%3d ", i); StackTraceCallSite call_site = process->function_trace[i]; Obj *o = call_site.caller; Obj *function = call_site.callee; if(o->meta) { //printf("%s\n", obj_to_string(o->meta)->s); char *func_name = ""; Obj *func_name_data = NULL; if(function && function->meta) { func_name_data = env_lookup(process, function->meta, obj_new_keyword("name")); } if(func_name_data) { func_name = obj_to_string_not_prn(process, func_name_data)->s; } else { func_name = "???"; // obj_to_string(function)->s; } int line = env_lookup(process, o->meta, obj_new_keyword("line"))->i; int pos = env_lookup(process, o->meta, obj_new_keyword("pos"))->i; char *file_path = env_lookup(process, o->meta, obj_new_keyword("file"))->s; char *file = file_path; int len = (int)strlen(file_path); for(int i = len - 1; i >= 0; i--) { if(file_path[i] == '/') { file = strdup(file_path + i + 1); break; } } printf("%-30s %s %d:%d", func_name, file, line, pos); } else { printf("No meta data."); //"%s", obj_to_string(function)->s); } printf("\n"); } printf(" ----------------------------------------------------------------\n"); }
void obj_print_not_prn(Obj *o) { Obj *s = obj_to_string_not_prn(o); printf("%s", s->s); }
void print_generic_array_or_struct(Obj *total, Obj *type_lookup, struct Obj *arg_to_str_obj) { assert(total); assert(total->tag == 'S'); assert(type_lookup); assert(arg_to_str_obj); shadow_stack_push(total); shadow_stack_push(type_lookup); shadow_stack_push(arg_to_str_obj); Obj *reffed_arg_type = obj_list(obj_new_keyword("ref"), type_lookup); // HACK: ref needed when sending arrays into str Obj *args_type = obj_list(reffed_arg_type); Obj *signature = obj_list(obj_new_keyword("fn"), args_type, type_string); Obj *quoted_sig = obj_list(lisp_quote, signature); //printf("quoted_sig: %s\n", obj_to_string(quoted_sig)->s); Obj *call_to_generic_name = obj_list(obj_new_symbol("generic-name"), obj_new_string("str"), quoted_sig); shadow_stack_push(call_to_generic_name); Obj *generic_name_result = eval(global_env, call_to_generic_name); shadow_stack_push(generic_name_result); if(eval_error) { printf("Error when calling generic-name:\n"); printf("%s\n", obj_to_string(eval_error)->s); return; } else { //printf("Generic name: %s\n", obj_to_string_not_prn(generic_name_result)->s); } // Also make sure this particular version of the str primop has been baked: Obj *call_to_bake_generic_primop_auto = obj_list(obj_new_symbol("bake-generic-primop-auto"), obj_new_string("str"), quoted_sig); shadow_stack_push(call_to_bake_generic_primop_auto); eval(global_env, call_to_bake_generic_primop_auto); if(eval_error) { printf("Error when calling bake-generic-primop-auto from print_generic_array_or_struct:\n"); printf("%s\n", obj_to_string(eval_error)->s); function_trace_print(); return; } else { //printf("%s should now exists\n", obj_to_string_not_prn(generic_name_result)->s); } char *generic_name = obj_to_string_not_prn(generic_name_result)->s; //printf("generic_name 1: %s\n", generic_name); Obj *call_to_str = obj_list(obj_new_symbol(generic_name), (struct Obj *)arg_to_str_obj); // OBS!!! // // Calling obj_to_string on the call_to_str form will result in an infinite loop: // printf("Call to str: %s\n", obj_to_string(call_to_str)->s); // // DON'T DO IT!!! shadow_stack_push(call_to_str); Obj *array_to_string_result = eval(global_env, call_to_str); shadow_stack_push(array_to_string_result); if(eval_error) { printf("Error when calling str function for void ptr of type '%s':\n", obj_to_string(type_lookup)->s); printf("%s\n", obj_to_string(eval_error)->s); assert(false); stack_pop(); obj_string_mut_append(total, "FAIL"); return; } obj_string_mut_append(total, obj_to_string_not_prn(array_to_string_result)->s); Obj *pop1 = shadow_stack_pop(); assert(pop1 == array_to_string_result); shadow_stack_pop(); shadow_stack_pop(); shadow_stack_pop(); shadow_stack_pop(); shadow_stack_pop(); shadow_stack_pop(); Obj *pop8 = shadow_stack_pop(); assert(pop8 == total); return; }
void obj_to_string_internal(Obj *total, const Obj *o, bool prn, int indent) { assert(o); int x = indent; if(o->tag == 'C') { obj_string_mut_append(total, "("); x++; int save_x = x; const Obj *p = o; while(p && p->car) { obj_to_string_internal(total, p->car, true, x); if(p->cdr && p->cdr->tag != 'C') { obj_string_mut_append(total, " . "); obj_to_string_internal(total, o->cdr, true, x); break; } else if(p->cdr && p->cdr->car) { if(/* p->car->tag == 'C' || */p->car->tag == 'E') { obj_string_mut_append(total, "\n"); x = save_x; add_indentation(total, x); } else { obj_string_mut_append(total, " "); x++; } } p = p->cdr; } obj_string_mut_append(total, ")"); x++; } else if(o->tag == 'A') { //printf("Will print Obj Array with count %d\n", o->count); shadow_stack_push((struct Obj *)o); x++; //int save_x = x; obj_string_mut_append(total, "["); for(int i = 0; i < o->count; i++) { obj_to_string_internal(total, o->array[i], true, x); if(i < o->count - 1) { /* if(o->array[i]->car->tag == 'Q' || o->array[i]->car->tag == 'E') { */ /* obj_string_mut_append(total, "\n"); */ /* x = save_x; */ /* add_indentation(total, x); */ /* } */ /* else { */ /* obj_string_mut_append(total, " "); */ /* x++; */ /* } */ obj_string_mut_append(total, " "); } } obj_string_mut_append(total, "]"); shadow_stack_pop(); x++; } else if(o->tag == 'E') { shadow_stack_push((struct Obj *)o); obj_string_mut_append(total, "{"); x++; Obj *p = o->bindings; while(p && p->car) { char *key_s = obj_to_string(p->car->car)->s; obj_string_mut_append(total, key_s); obj_string_mut_append(total, " "); obj_to_string_internal(total, p->car->cdr, true, x + (int)strlen(key_s) + 1); p = p->cdr; if(p && p->car && p->car->car) { obj_string_mut_append(total, ", \n"); add_indentation(total, x); } } obj_string_mut_append(total, "}"); if(o->parent) { obj_string_mut_append(total, " -> \n"); Obj *parent_printout = obj_to_string(o->parent); obj_string_mut_append(total, parent_printout->s); } shadow_stack_pop(); } else if(o->tag == 'I') { static char temp[64]; snprintf(temp, 64, "%d", o->i); obj_string_mut_append(total, temp); } else if(o->tag == 'V') { static char temp[64]; snprintf(temp, 64, "%f", o->f32); obj_string_mut_append(total, temp); obj_string_mut_append(total, "f"); } else if(o->tag == 'W') { static char temp[64]; snprintf(temp, 64, "%f", o->f64); obj_string_mut_append(total, temp); } else if(o->tag == 'S') { if(prn) { obj_string_mut_append(total, "\""); } obj_string_mut_append(total, o->s); if(prn) { obj_string_mut_append(total, "\""); } } else if(o->tag == 'Y') { obj_string_mut_append(total, o->s); } else if(o->tag == 'K') { obj_string_mut_append(total, ":"); obj_string_mut_append(total, o->s); } else if(o->tag == 'P') { obj_string_mut_append(total, "<primop:"); static char temp[256]; snprintf(temp, 256, "%p", o->primop); obj_string_mut_append(total, temp); if(o->meta) { Obj *name = env_lookup(o->meta, obj_new_keyword("name")); if(name) { obj_string_mut_append(total, ":"); obj_string_mut_append(total, obj_to_string_not_prn(name)->s); } } obj_string_mut_append(total, ">"); } else if(o->tag == 'D') { obj_string_mut_append(total, "<dylib:"); static char temp[256]; snprintf(temp, 256, "%p", o->primop); obj_string_mut_append(total, temp); obj_string_mut_append(total, ">"); } else if(o->tag == 'Q') { shadow_stack_push((struct Obj *)o); Obj *type_lookup; if(o->meta && (type_lookup = env_lookup(o->meta, obj_new_keyword("type")))) { if(type_lookup->tag == 'C' && type_lookup->cdr->car && obj_eq(type_lookup->car, obj_new_keyword("Array"))) { print_generic_array_or_struct(total, type_lookup, (struct Obj *)o); } else { print_generic_array_or_struct(total, type_lookup, (struct Obj *)o); /* obj_string_mut_append(total, "<ptr"); */ /* obj_string_mut_append(total, obj_to_string(type_lookup)->s); */ /* obj_string_mut_append(total, ">"); */ } } else { obj_string_mut_append(total, "<ptr:"); static char temp[256]; snprintf(temp, 256, "%p", o->primop); obj_string_mut_append(total, temp); obj_string_mut_append(total, " of unknown type"); obj_string_mut_append(total, ">"); } shadow_stack_pop(); } else if(o->tag == 'F') { obj_string_mut_append(total, "<ffi:"); static char temp[256]; snprintf(temp, 256, "%p", o->funptr); obj_string_mut_append(total, temp); if(o->meta) { Obj *name = env_lookup(o->meta, obj_new_keyword("name")); if(name) { obj_string_mut_append(total, ":"); obj_string_mut_append(total, obj_to_string_not_prn(name)->s); } } else { } obj_string_mut_append(total, ">"); } else if(o->tag == 'L') { if(setting_print_lambda_body) { obj_string_mut_append(total, "(fn"); obj_string_mut_append(total, " "); obj_string_mut_append(total, obj_to_string(o->params)->s); obj_string_mut_append(total, " "); obj_string_mut_append(total, obj_to_string(o->body)->s); obj_string_mut_append(total, ")"); } else { obj_string_mut_append(total, "<lambda>"); } } else if(o->tag == 'M') { if(setting_print_lambda_body) { obj_string_mut_append(total, "(macro"); obj_string_mut_append(total, " "); obj_string_mut_append(total, obj_to_string(o->params)->s); obj_string_mut_append(total, " "); obj_string_mut_append(total, obj_to_string(o->body)->s); obj_string_mut_append(total, ")"); } else { obj_string_mut_append(total, "<macro>"); } } else if(o->tag == 'T') { char s[2] = { o->character, '\0' }; if(prn) { obj_string_mut_append(total, "\\"); } obj_string_mut_append(total, s); } else if(o->tag == 'B') { if(o->boolean) { obj_string_mut_append(total, "true"); } else { obj_string_mut_append(total, "false"); } } else { printf("obj_to_string() can't handle type tag %c (%d).\n", o->tag, o->tag); assert(false); } }
void obj_print_not_prn(Process *process, Obj *o) { Obj *s = obj_to_string_not_prn(process, o); printf("%s", s->s); }
void print_generic_array_or_struct(Process *process, Obj *total, Obj *type_lookup, struct Obj *arg_to_str_obj) { assert(total); assert(total->tag == 'S'); assert(type_lookup); assert(arg_to_str_obj); shadow_stack_push(process, total); shadow_stack_push(process, type_lookup); shadow_stack_push(process, arg_to_str_obj); Obj *reffed_arg_type = obj_list(obj_new_keyword("ref"), type_lookup); // HACK: ref needed when sending arrays into str Obj *args_type = obj_list(reffed_arg_type); Obj *signature = obj_list(obj_new_keyword("fn"), args_type, type_string); Obj *quoted_sig = obj_list(lisp_quote, signature); //printf("quoted_sig: %s\n", obj_to_string(quoted_sig)->s); Obj *generic_name_result = generic_name(process, "prn", quoted_sig); if(eval_error) { return; } shadow_stack_push(process, generic_name_result); bake_generic_primop_auto(process, "prn", quoted_sig); if(eval_error) { return; } // TODO: why this conversion? char *generic_name = obj_to_string_not_prn(process, generic_name_result)->s; //printf("generic_name 1: %s\n", generic_name); Obj *call_to_str = obj_list(obj_new_symbol(generic_name), (struct Obj *)arg_to_str_obj); // OBS!!! // // Calling obj_to_string on the call_to_str form will result in an infinite loop: // printf("Call to str: %s\n", obj_to_string(call_to_str)->s); // // DON'T DO IT!!! shadow_stack_push(process, call_to_str); Obj *array_to_string_result = NULL; if(BYTECODE_EVAL) { array_to_string_result = bytecode_sub_eval_form(process, process->global_env, call_to_str); } else { array_to_string_result = eval(process, process->global_env, call_to_str); } shadow_stack_push(process, array_to_string_result); if(eval_error) { printf("Error when calling str function for void ptr of type '%s':\n", obj_to_string(process, type_lookup)->s); printf("%s\n", obj_to_string(process, eval_error)->s); assert(false); stack_pop(process); obj_string_mut_append(total, "FAIL"); return; } obj_string_mut_append(total, obj_to_string_not_prn(process, array_to_string_result)->s); Obj *pop1 = shadow_stack_pop(process); assert(pop1 == array_to_string_result); shadow_stack_pop(process); shadow_stack_pop(process); shadow_stack_pop(process); shadow_stack_pop(process); Obj *pop8 = shadow_stack_pop(process); assert(pop8 == total); return; }
void obj_to_string_internal(Process *process, Obj *total, const Obj *o, bool prn, int indent) { assert(o); int x = indent; if(o->tag == 'C') { obj_string_mut_append(total, "("); x++; int save_x = x; const Obj *p = o; while(p && p->car) { obj_to_string_internal(process, total, p->car, true, x); if(p->cdr && p->cdr->tag != 'C') { obj_string_mut_append(total, " . "); obj_to_string_internal(process, total, o->cdr, true, x); break; } else if(p->cdr && p->cdr->car) { if(/* p->car->tag == 'C' || */ p->car->tag == 'E') { obj_string_mut_append(total, "\n"); x = save_x; add_indentation(total, x); } else { obj_string_mut_append(total, " "); x++; } } p = p->cdr; } obj_string_mut_append(total, ")"); x++; } else if(o->tag == 'A') { //printf("Will print Obj Array with count %d\n", o->count); shadow_stack_push(process, (struct Obj *)o); x++; //int save_x = x; obj_string_mut_append(total, "["); for(int i = 0; i < o->count; i++) { obj_to_string_internal(process, total, o->array[i], true, x); if(i < o->count - 1) { /* if(o->array[i]->car->tag == 'Q' || o->array[i]->car->tag == 'E') { */ /* obj_string_mut_append(total, "\n"); */ /* x = save_x; */ /* add_indentation(total, x); */ /* } */ /* else { */ /* obj_string_mut_append(total, " "); */ /* x++; */ /* } */ obj_string_mut_append(total, " "); } } obj_string_mut_append(total, "]"); shadow_stack_pop(process); x++; } else if(o->tag == 'E') { shadow_stack_push(process, (struct Obj *)o); if(o == process->global_env) { obj_string_mut_append(total, "{ GLOBAL ENVIRONMENT }"); return; } obj_string_mut_append(total, "{"); x++; Obj *p = o->bindings; while(p && p->car) { char *key_s = obj_to_string(process, p->car->car)->s; obj_string_mut_append(total, key_s); obj_string_mut_append(total, " "); obj_to_string_internal(process, total, p->car->cdr, true, x + (int)strlen(key_s) + 1); p = p->cdr; if(p && p->car && p->car->car) { obj_string_mut_append(total, ", \n"); add_indentation(total, x); } } obj_string_mut_append(total, "}"); if(o->parent) { obj_string_mut_append(total, " -> \n"); Obj *parent_printout = obj_to_string(process, o->parent); obj_string_mut_append(total, parent_printout->s); } shadow_stack_pop(process); } else if(o->tag == 'I') { static char temp[64]; snprintf(temp, 64, "%d", o->i); obj_string_mut_append(total, temp); } else if(o->tag == 'V') { static char temp[64]; snprintf(temp, 64, "%f", o->f32); obj_string_mut_append(total, temp); obj_string_mut_append(total, "f"); } else if(o->tag == 'W') { static char temp[64]; snprintf(temp, 64, "%f", o->f64); obj_string_mut_append(total, temp); } else if(o->tag == 'S') { if(prn) { obj_string_mut_append(total, "\""); } obj_string_mut_append(total, o->s); if(prn) { obj_string_mut_append(total, "\""); } } else if(o->tag == 'Y') { obj_string_mut_append(total, o->s); } else if(o->tag == 'K') { obj_string_mut_append(total, ":"); obj_string_mut_append(total, o->s); } else if(o->tag == 'P') { obj_string_mut_append(total, "<primop:"); static char temp[256]; snprintf(temp, 256, "%p", o->primop); obj_string_mut_append(total, temp); if(o->meta) { Obj *name = env_lookup(process, o->meta, obj_new_keyword("name")); if(name) { obj_string_mut_append(total, ":"); obj_string_mut_append(total, obj_to_string_not_prn(process, name)->s); } } obj_string_mut_append(total, ">"); } else if(o->tag == 'D') { obj_string_mut_append(total, "<dylib:"); static char temp[256]; snprintf(temp, 256, "%p", o->primop); obj_string_mut_append(total, temp); obj_string_mut_append(total, ">"); } else if(o->tag == 'Q') { shadow_stack_push(process, (struct Obj *)o); Obj *type_lookup; if(o->meta && (type_lookup = env_lookup(process, o->meta, obj_new_keyword("type")))) { if(type_lookup->tag == 'C' && type_lookup->cdr->car && obj_eq(process, type_lookup->car, obj_new_keyword("Array"))) { print_generic_array_or_struct(process, total, type_lookup, (struct Obj *)o); } else { print_generic_array_or_struct(process, total, type_lookup, (struct Obj *)o); /* obj_string_mut_append(total, "<ptr"); */ /* obj_string_mut_append(total, obj_to_string(type_lookup)->s); */ /* obj_string_mut_append(total, ">"); */ } } else { obj_string_mut_append(total, "<ptr:"); static char temp[256]; snprintf(temp, 256, "%p", o->primop); obj_string_mut_append(total, temp); obj_string_mut_append(total, " of unknown type"); obj_string_mut_append(total, ">"); } shadow_stack_pop(process); } else if(o->tag == 'R') { shadow_stack_push(process, (struct Obj *)o); if(!o->void_ptr) { eval_error = obj_new_string("Pointer to global is NULL.\n"); return; } Obj *type_lookup; //printf("o %p %p\n", o, o->void_ptr); if(o->void_ptr == NULL) { obj_string_mut_append(total, "NULL"); } else if(o->meta && (type_lookup = env_lookup(process, o->meta, obj_new_keyword("type")))) { //printf("type %s\n", obj_to_string(type_lookup)->s); if(type_lookup->tag == 'C' && type_lookup->cdr->car && obj_eq(process, type_lookup->car, obj_new_keyword("Array"))) { void *dereffed = *(void **)o->void_ptr; assert(dereffed); Obj *x = primitive_to_obj(process, dereffed, type_lookup); shadow_stack_push(process, x); obj_string_mut_append(total, obj_to_string(process, x)->s); shadow_stack_pop(process); // x } else if(obj_eq(process, type_lookup, type_int)) { //int i = 123; void *dereffed = *(void **)o->void_ptr; assert(dereffed); Obj *x = primitive_to_obj(process, dereffed, type_int); obj_string_mut_append(total, obj_to_string(process, x)->s); } else if(obj_eq(process, type_lookup, type_float)) { //int i = 123; void *dereffed = *(void **)o->void_ptr; assert(dereffed); Obj *x = primitive_to_obj(process, dereffed, type_float); obj_string_mut_append(total, obj_to_string(process, x)->s); } else if(obj_eq(process, type_lookup, type_double)) { void *dereffed = *(void **)o->void_ptr; assert(dereffed); Obj *x = primitive_to_obj(process, dereffed, type_double); obj_string_mut_append(total, obj_to_string(process, x)->s); } else if(obj_eq(process, type_lookup, type_bool)) { void *dereffed = *(void **)o->void_ptr; // can't assert since false == NULL Obj *x = primitive_to_obj(process, dereffed, type_bool); obj_string_mut_append(total, obj_to_string(process, x)->s); } else if(obj_eq(process, type_lookup, type_string)) { void *dereffed = *(void **)o->void_ptr; assert(dereffed); Obj *x = primitive_to_obj(process, dereffed, type_string); obj_string_mut_append(total, x->s); } else if(obj_eq(process, type_lookup, type_char)) { void *dereffed = *(void **)o->void_ptr; assert(dereffed); Obj *x = primitive_to_obj(process, dereffed, type_char); obj_string_mut_append(total, obj_to_string(process, x)->s); } else { void *dereffed = *(void **)o->void_ptr; assert(dereffed); Obj *x = primitive_to_obj(process, dereffed, type_lookup); print_generic_array_or_struct(process, total, type_lookup, (struct Obj *)x); /* obj_string_mut_append(total, "<ptr"); */ /* obj_string_mut_append(total, obj_to_string(type_lookup)->s); */ /* obj_string_mut_append(total, ">"); */ } } obj_string_mut_append(total, " ; ptr-to-global"); shadow_stack_pop(process); } else if(o->tag == 'F') { obj_string_mut_append(total, "<ffi:"); static char temp[256]; snprintf(temp, 256, "%p", o->funptr); obj_string_mut_append(total, temp); if(o->meta) { Obj *name = env_lookup(process, o->meta, obj_new_keyword("name")); if(name) { obj_string_mut_append(total, ":"); obj_string_mut_append(total, obj_to_string_not_prn(process, name)->s); } } else { } obj_string_mut_append(total, ">"); } else if(o->tag == 'L') { if(setting_print_lambda_body) { obj_string_mut_append(total, "(fn"); obj_string_mut_append(total, " "); obj_string_mut_append(total, obj_to_string(process, o->params)->s); obj_string_mut_append(total, " "); obj_string_mut_append(total, obj_to_string(process, o->body)->s); obj_string_mut_append(total, ")"); } else { obj_string_mut_append(total, "<lambda>"); } } else if(o->tag == 'M') { if(setting_print_lambda_body) { obj_string_mut_append(total, "(macro"); obj_string_mut_append(total, " "); obj_string_mut_append(total, obj_to_string(process, o->params)->s); obj_string_mut_append(total, " "); obj_string_mut_append(total, obj_to_string(process, o->body)->s); obj_string_mut_append(total, ")"); } else { obj_string_mut_append(total, "<macro>"); } } else if(o->tag == 'T') { char s[2] = {o->character, '\0'}; if(prn) { obj_string_mut_append(total, "\\"); } obj_string_mut_append(total, s); } else if(o->tag == 'B') { if(o->boolean) { obj_string_mut_append(total, "true"); } else { obj_string_mut_append(total, "false"); } } else if(o->tag == 'X') { obj_string_mut_append(total, "(\n"); for(char *p = o->bytecode; *p != '\0';) { const int buffer_size = 128; char buffer[buffer_size]; snprintf(buffer, buffer_size, "%4d ", (int)(p - o->bytecode)); obj_string_mut_append(total, buffer); char c = *p; p++; if(c == 'l') { snprintf(buffer, buffer_size, "LOAD LIT %d", *((int*)p)); p += sizeof(int); } else if(c == 'a') { snprintf(buffer, buffer_size, "LOAD λ %d", *((int*)p)); p += sizeof(int); } else if(c == 'c') { snprintf(buffer, buffer_size, "CALL %d", *((int*)p)); p += sizeof(int); } else if(c == 'd') { snprintf(buffer, buffer_size, "DEFINE %d", *((int*)p)); p += sizeof(int); } else if(c == 'y') { snprintf(buffer, buffer_size, "LOOKUP %d", *((int*)p)); p += sizeof(int); } else if(c == 'i') { snprintf(buffer, buffer_size, "JUMP IF NOT %d", *((int*)p)); p += sizeof(int); } else if(c == 'j') { snprintf(buffer, buffer_size, "JUMP %d", *((int*)p)); p += sizeof(int); } else if(c == 'r') { snprintf(buffer, buffer_size, "RESET %d", *((int*)p)); p += sizeof(int); } else if(c == 't') { snprintf(buffer, buffer_size, "LET %d", *((int*)p)); p += sizeof(int); } else if(c == 'e') { snprintf(buffer, buffer_size, "DISCARD"); } else if(c == 'g') { snprintf(buffer, buffer_size, "CATCH"); } else if(c == 'n') { snprintf(buffer, buffer_size, "NOT"); } else if(c == 'p') { snprintf(buffer, buffer_size, "PUSH NIL"); } else if(c == 'v') { snprintf(buffer, buffer_size, "POP LET-SCOPE"); } else if(c == 'x') { snprintf(buffer, buffer_size, "DIRECT LOOKUP"); } else if(c == 'q') { snprintf(buffer, buffer_size, "END"); } else { snprintf(buffer, buffer_size, "UNHANDLED OP (%c)", *p); p++; } obj_string_mut_append(total, buffer); obj_string_mut_append(total, "\n"); } obj_string_mut_append(total, "Literals: "); obj_string_mut_append(total, obj_to_string(process, o->bytecode_literals)->s); obj_string_mut_append(total, "\n"); obj_string_mut_append(total, ")"); } else { printf("obj_to_string() can't handle type tag %c (%d).\n", o->tag, o->tag); assert(false); } }