diff --git a/c/class_resolver.c b/c/class_resolver.c index e4ee467..e23b574 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -120,6 +120,10 @@ struct class_entry * class_resolver_lookup_class(int class_hash_table_length, const uint8_t * class_name, int class_name_length) { + printf("class_resolver_lookup_class: "); + for (int i = 0; i < class_name_length; i++) { fputc(class_name[i], stdout); } + fputc('\n', stdout); + struct hash_table_entry * e = hash_table_find(class_hash_table_length, class_hash_table, class_name, @@ -134,6 +138,10 @@ struct field_entry * class_resolver_lookup_field(struct class_entry * class_entr const uint8_t * field_name, int field_name_length) { + printf("class_resolver_lookup_field: "); + for (int i = 0; i < field_name_length; i++) { fputc(field_name[i], stdout); } + fputc('\n', stdout); + int fields_hash_table_length = class_entry->fields.length; struct hash_table_entry * fields_hash_table = class_entry->fields.entry; @@ -150,6 +158,10 @@ struct method_info * class_resolver_lookup_method(struct class_entry * class_ent const uint8_t * method_name, int method_name_length) { + printf("class_resolver_lookup_method: "); + for (int i = 0; i < method_name_length; i++) { fputc(method_name[i], stdout); } + fputc('\n', stdout); + int methods_hash_table_length = class_entry->methods.length; struct hash_table_entry * methods_hash_table = class_entry->methods.entry; diff --git a/c/execute.c b/c/execute.c index 41c2435..ae9df72 100644 --- a/c/execute.c +++ b/c/execute.c @@ -75,7 +75,6 @@ void op_astore(struct vm * vm, uint32_t index) void op_astore_0(struct vm * vm) { - printf("op_astore0 %d\n", vm->current_frame->operand_stack_ix); uint32_t value = operand_stack_pop_u32(vm->current_frame); vm->current_frame->local_variable[0] = value; } @@ -959,14 +958,28 @@ void op_ireturn(struct vm * vm) of the invoked method was boolean, then value is narrowed from int to boolean by taking the bitwise AND of value and 1. */ - uint32_t value = operand_stack_pop_u32(vm->current_frame); + // The current method must have return type boolean, byte, char, short, or int + + int32_t value = operand_stack_pop_u32(vm->current_frame); switch (vm->current_frame->return_type) { - case 'I': + case 'Z': // boolean + value = value & 1; + break; + case 'B': // byte + value = (int8_t)value; + break; + case 'C': // char + value = (uint16_t)value; + break; + case 'S': // short + value = (int16_t)value; + break; + case 'I': // int + value = (int32_t)value; break; default: - fprintf(stderr, "conversion not implemented: %c\n", vm->current_frame->return_type); + fprintf(stderr, "invalid conversion: %c\n", vm->current_frame->return_type); assert(false); - break; } operand_stack_push_u32(vm->current_frame, value); diff --git a/c/frame.c b/c/frame.c index 9a5c154..44afc16 100644 --- a/c/frame.c +++ b/c/frame.c @@ -73,12 +73,17 @@ static int descriptor_nargs(struct constant * descriptor_constant) assert(descriptor_constant->utf8.length >= 2); assert(descriptor_constant->utf8.bytes[0] == '('); + printf("method descriptor: "); + print_utf8_string(descriptor_constant); + printf("\n"); + int i = 1; int nargs = 0; while (i < descriptor_constant->utf8.length) { if (descriptor_constant->utf8.bytes[i] == ')') break; - nargs += 1; + if (descriptor_constant->utf8.bytes[i] != '[') + nargs += 1; i += 1; } assert(i + 2 == descriptor_constant->utf8.length); @@ -100,7 +105,6 @@ void vm_static_method_call(struct vm * vm, struct class_file * class_file, struc int code_name_index = find_code_name_index(class_file); assert(code_name_index > 0); - printf("code_name_index %d\n", code_name_index); struct Code_attribute * code = get_code_attribute(code_name_index, method_info->attributes_count, @@ -120,9 +124,10 @@ void vm_static_method_call(struct vm * vm, struct class_file * class_file, struc printf("nargs %d\n", nargs); for (int i = 0; i < nargs; i++) { uint32_t value = operand_stack_pop_u32(old_frame); + printf("local[%d] = %x\n", nargs - i - 1, value); vm->current_frame->local_variable[nargs - i - 1] = value; } - vm->current_frame->return_type = descriptor_constant->utf8.bytes[nargs + 2]; + vm->current_frame->return_type = descriptor_constant->utf8.bytes[descriptor_constant->utf8.length - 1]; vm->current_frame->pc = 0; vm->current_thread.current_class = class_file; @@ -140,9 +145,38 @@ void vm_method_return(struct vm * vm) assert(vm->current_frame != old_frame); vm->current_frame->pc = vm->current_frame->next_pc; + /* + boolean int 1 + byte int 1 + char int 1 + short int 1 + int int 1 + float float 1 + reference reference 1 + returnAddress returnAddress 1 + long long 2 + double double 2 + */ + /* + B byte + C char + D double + F float + I int + J long + L ClassName ; Named class or interface type + S short + Z boolean + [ ComponentType Array of given component type + */ + switch (old_frame->return_type) { - case 'F': [[fallthrough]]; - case 'I': + case 'Z': [[fallthrough]]; + case 'B': [[fallthrough]]; + case 'C': [[fallthrough]]; + case 'S': [[fallthrough]]; + case 'I': [[fallthrough]]; + case 'F': uint32_t value = operand_stack_pop_u32(old_frame); operand_stack_push_u32(vm->current_frame, value); break; diff --git a/p/AdventDay1.java b/p/AdventOfCodeDay1.java similarity index 98% rename from p/AdventDay1.java rename to p/AdventOfCodeDay1.java index 506a691..8c90951 100644 --- a/p/AdventDay1.java +++ b/p/AdventOfCodeDay1.java @@ -1,6 +1,6 @@ package p; -class AdventDay1 { +class AdventOfCodeDay1 { public static int part1() { int[] input = {3, 4, 4, 3, diff --git a/p/AdventDay1_String.java b/p/AdventOfCodeDay1_String.java similarity index 98% rename from p/AdventDay1_String.java rename to p/AdventOfCodeDay1_String.java index 76a4952..a9e1fc2 100644 --- a/p/AdventDay1_String.java +++ b/p/AdventOfCodeDay1_String.java @@ -1,6 +1,6 @@ package p; -class AdventOfCode2024Day1 { +class AdventOfCodeDay1_String { public static int part1() { char[] string_input = { '3', ' ', ' ', ' ', '4', '\n', diff --git a/p/AdventOfCodeDay2.java b/p/AdventOfCodeDay2.java new file mode 100644 index 0000000..20a8b10 --- /dev/null +++ b/p/AdventOfCodeDay2.java @@ -0,0 +1,100 @@ +package p; + +class AdventOfCodeDay2 { + static float parse_digit(char c) { + switch (c) { + case '0': return 0.0f; + case '1': return 1.0f; + case '2': return 2.0f; + case '3': return 3.0f; + case '4': return 4.0f; + case '5': return 5.0f; + case '6': return 6.0f; + case '7': return 7.0f; + case '8': return 8.0f; + case '9': return 9.0f; + default: return -1.0f; + } + } + + static float fabs(float f) + { + if (f < 0) + return -f; + else + return f; + } + + static float fsign(float f) + { + if (f < 0) + return -1; + else + return 1; + } + + static boolean report_safe(float[] line, int length) + { + float last = line[0]; + float last_sign = 0.0f; + for (int i = 1; i < length; i++) { + float cur = line[i]; + float rate = last - cur; + + if (fabs(rate) < 1 || fabs(rate) > 3) + return false; // unsafe + + float sign = fsign(rate); + if (last_sign != 0.0f && sign != last_sign) + return false; // unsafe + + last_sign = sign; + last = cur; + } + + return true; // safe + } + + static float solve(char[] input) { + float[] line = new float[100]; + int line_ix = 0; + int input_ix = 0; + float num = 0.0f; + float safe_count = 0.0f; + + while (input_ix < input.length) { + if (input[input_ix] == ' ' || input[input_ix] == '\n') { + line[line_ix] = num; + line_ix += 1; + num = 0.0f; + } + if (input[input_ix] == '\n') { + if (report_safe(line, line_ix)) { + safe_count += 1.0f; + } + line_ix = 0; + } + float digit = parse_digit(input[input_ix]); + if (!(digit < 0.0f)) { + num *= 10.0f; + num += digit; + } + input_ix += 1; + } + + return safe_count; + } + + public static void main() { + char[] input = { + '7', ' ', '6', ' ', '4', ' ', '2', ' ', '1', '\n', + '1', ' ', '2', ' ', '7', ' ', '8', ' ', '9', '\n', + '9', ' ', '7', ' ', '6', ' ', '2', ' ', '1', '\n', + '1', ' ', '3', ' ', '2', ' ', '4', ' ', '5', '\n', + '8', ' ', '6', ' ', '4', ' ', '4', ' ', '1', '\n', + '1', ' ', '3', ' ', '6', ' ', '7', ' ', '9', '\n', + }; + + solve(input); + } +}