diff --git a/README.md b/README.md index 17c9627..6d64e0a 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,13 @@ skibidi main { ./brainrot < hello.brainrot ``` +Check out the [examples](examples/README.md): + +- [Hello world](examples/hello_world.brainrot) +- [Fizz Buzz](examples/fizz_buzz.brainrot) +- [Bubble Sort](examples/bubble_sort.brainrot) +- [One-dimensional Heat Equation Solver](examples/heat_equation_1d.brainrot) + ## πŸ—ͺ Community Join our community on [Discord](https://discord.gg/FjHhvBHSGj). diff --git a/ast.c b/ast.c index 3f2bd3a..35ec0c8 100644 --- a/ast.c +++ b/ast.c @@ -8,7 +8,6 @@ #include #include - static JumpBuffer *jump_buffer = {0}; TypeModifiers current_modifiers = {false, false, false, false, false}; @@ -566,12 +565,24 @@ int get_expression_type(ASTNode *node) return VAR_INT; case NODE_ARRAY_ACCESS: { - // Look up the array's type in the symbol table + // First, get the array's base type from symbol table const char *array_name = node->data.array.name; for (int i = 0; i < var_count; i++) { if (strcmp(symbol_table[i].name, array_name) == 0) { + // Found the array, now handle the index expression + ASTNode *index_expr = node->data.array.index; + + // Recursively evaluate index expression type + int index_type = get_expression_type(index_expr); + if (index_type != VAR_INT && index_type != VAR_SHORT) + { + yyerror("Array index must be an integer type"); + return NONE; + } + + // Return the array's element type return symbol_table[i].var_type; } } @@ -631,6 +642,17 @@ void *handle_binary_operation(ASTNode *node, int result_type) int left_type = get_expression_type(node->data.op.left); int right_type = get_expression_type(node->data.op.right); + if (node->data.op.left->type == NODE_ARRAY_ACCESS) + { + // Get value using array_access evaluation + left_value = evaluate_array_access(node->data.op.left); + } + if (node->data.op.right->type == NODE_ARRAY_ACCESS) + { + // Get value using array_access evaluation + right_value = evaluate_array_access(node->data.op.right); + } + // Promote types if necessary (short -> int -> float -> double). int promoted_type = VAR_SHORT; if (left_type == VAR_DOUBLE || right_type == VAR_DOUBLE) @@ -681,7 +703,6 @@ void *handle_binary_operation(ASTNode *node, int result_type) *(short *)left_value = evaluate_expression_short(node->data.op.left); *(short *)right_value = evaluate_expression_short(node->data.op.right); break; - default: yyerror("Unsupported type promotion"); @@ -712,7 +733,7 @@ void *handle_binary_operation(ASTNode *node, int result_type) else if (promoted_type == VAR_FLOAT) *(float *)result = *(float *)left_value - *(float *)right_value; else if (promoted_type == VAR_DOUBLE) - *(double *) result= *(double *)left_value - *(double *)right_value; + *(double *)result = *(double *)left_value - *(double *)right_value; else if (promoted_type == VAR_SHORT) *(short *)result = *(short *)left_value - *(short *)right_value; @@ -1351,9 +1372,9 @@ short evaluate_expression_short(ASTNode *node) ? *(short *)result : (result_type == VAR_FLOAT) ? (short)(*(float *)result) - : (result_type == VAR_DOUBLE) - ? (short)(*(double *)result) - : (short)(*(int *)result); + : (result_type == VAR_DOUBLE) + ? (short)(*(double *)result) + : (short)(*(int *)result); free(result); return result_short; } @@ -2754,17 +2775,72 @@ void bruh() LONGJMP(); } -ASTNode* create_default_node(VarType var_type) { - switch (var_type) { - case VAR_INT: return create_int_node(0); - case VAR_FLOAT: return create_float_node(0.0f); - case VAR_DOUBLE: return create_double_node(0.0); - case VAR_SHORT: return create_short_node(0); - case VAR_CHAR: return create_char_node('\0'); - case VAR_BOOL: return create_boolean_node(0); - default: - yyerror("Unsupported type for default node"); - exit(1); +ASTNode *create_default_node(VarType var_type) +{ + switch (var_type) + { + case VAR_INT: + return create_int_node(0); + case VAR_FLOAT: + return create_float_node(0.0f); + case VAR_DOUBLE: + return create_double_node(0.0); + case VAR_SHORT: + return create_short_node(0); + case VAR_CHAR: + return create_char_node('\0'); + case VAR_BOOL: + return create_boolean_node(0); + default: + yyerror("Unsupported type for default node"); + exit(1); } } +void *evaluate_array_access(ASTNode *node) +{ + if (!node || node->type != NODE_ARRAY_ACCESS) + { + yyerror("Invalid array access node"); + return NULL; + } + + const char *array_name = node->data.array.name; + int idx = evaluate_expression_int(node->data.array.index); + + for (int i = 0; i < var_count; i++) + { + if (strcmp(symbol_table[i].name, array_name) == 0) + { + if (!symbol_table[i].is_array) + { + yyerror("Not an array!"); + return NULL; + } + if (idx < 0 || idx >= symbol_table[i].array_length) + { + yyerror("Array index out of bounds!"); + return NULL; + } + + // Allocate and return value based on type + void *result = malloc(sizeof(double)); // Use largest possible type + switch (symbol_table[i].var_type) + { + case VAR_DOUBLE: + *(double *)result = symbol_table[i].value.darray[idx]; + break; + case VAR_FLOAT: + *(double *)result = (double)symbol_table[i].value.farray[idx]; + break; + case VAR_INT: + *(double *)result = (double)symbol_table[i].value.iarray[idx]; + break; + // ... handle other types ... + } + return result; + } + } + yyerror("Undefined array variable"); + return NULL; +} diff --git a/ast.h b/ast.h index acb4fac..e7ab034 100644 --- a/ast.h +++ b/ast.h @@ -264,9 +264,10 @@ CaseNode *create_case_node(ASTNode *value, ASTNode *statements); CaseNode *create_default_case_node(ASTNode *statements); CaseNode *append_case_list(CaseNode *list, CaseNode *case_node); ASTNode *create_break_node(void); -ASTNode* create_default_node(VarType var_type); +ASTNode *create_default_node(VarType var_type); /* Evaluation and execution functions */ +void *evaluate_array_access(ASTNode *node); double evaluate_expression_double(ASTNode *node); float evaluate_expression_float(ASTNode *node); int evaluate_expression_int(ASTNode *node); @@ -294,7 +295,6 @@ void reset_modifiers(void); bool check_and_mark_identifier(ASTNode *node, const char *contextErrorMessage); void bruh(); - extern TypeModifiers current_modifiers; /* Macros for assigning specific fields to a node */ diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..528a605 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,200 @@ +# Examples + +This directory contains several example programs written in the Brainrot language variant demonstrated by the provided grammar. Each example highlights different language features. + +--- + +## 1. Hello, World! + +**File Name:** `hello_world.brainrot` + +```c +skibidi main { + yappin("Hello, World!\n"); + bussin 0; +} +``` + +### What It Does + +- Prints `"Hello, World!"` to the standard output. +- Demonstrates a minimal working program in Brainraot language. +- Uses the `yappin` function to output text. +- Ends with `bussin 0;`, which acts like a `return 0;` in C. + +--- + +## 2. FizzBuzz + +**File Name:** `fizz_buzz.brainrot` + +```c +skibidi main { + nut rizz i; + flex (i = 1; i <= 10; i = i + 1){ + edgy ( (i % 15) == 0 ) { + yapping("FizzBuzz"); + } amogus edgy ( (i % 3) == 0 ) { + yapping("Fizz"); + } amogus edgy ( (i % 5) == 0 ) { + yapping("Buzz"); + } amogus { + yapping("%d", i); + } + } + bussin 0; +} +``` + +### What It Does + +- Implements the classic FizzBuzz challenge for values of `i` from `1` to `15`. +- Prints: + - **FizzBuzz** if a number is divisible by 15, + - **Fizz** if divisible by 3, + - **Buzz** if divisible by 5, + - the number itself otherwise. +- Demonstrates: + - Declarations (`nut rizz i;`) which sets a variable as signed int (because `nut` = `signed`, `rizz` = `int`). + - `flex` loops (equivalent to `for` loops). + - `edgy` (equivalent to `if`) statements and `amogus` (equivalent to `else`). + - `yapping` for printing. + +--- + +## 3. Bubble Sort + +**File Name:** `bubble_sort.brainrot` + +```c +skibidi main { + rizz arr[10]; + rizz i; + rizz j; + rizz temp; + + 🚽 Initialize array with some unsorted numbers + arr[0] = 64; + arr[1] = 34; + arr[2] = 25; + arr[3] = 12; + arr[4] = 22; + arr[5] = 11; + arr[6] = 90; + arr[7] = 42; + arr[8] = 15; + arr[9] = 77; + + 🚽 Print original array + yapping("Original array: "); + flex (i = 0; i < 10; i = i + 1) { + yapping("%d ", arr[i]); + } + + 🚽 Bubble sort + flex (i = 0; i < 9; i = i + 1) { + flex (j = 0; j < 9 - i; j = j + 1) { + edgy (arr[j] > arr[j + 1]) { + temp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = temp; + } + } + } + + 🚽 Print sorted array + yapping("Sorted array: "); + flex (i = 0; i < 10; i = i + 1) { + yapping("%d ", arr[i]); + } + + bussin 0; +} +``` + +### What It Does + +- Declares an integer array `arr` with 10 elements (`rizz` = `int`). +- Initializes and prints the unsorted array. +- Implements the **Bubble Sort** algorithm to sort the array in ascending order. +- Prints the sorted array. +- Demonstrates: + - Array declarations and assignments (`arr[i] = some_value;`) + - Nested `flex` loops for the sorting routine. + - Conditionals with `edgy`/`amogus`. + - Use of `yapping` to print results. + +--- + +## 4. Simple 1D Heat Equation Simulation + +**File Name:** `heat_equation_1d.brainrot` + +```c +skibidi main { + rizz N = 50; + gigachad u[50]; + gigachad u_new[50]; + rizz i; + rizz t; + rizz timesteps = 100; + + 🚽 Initialize array + flex (i = 0; i < N; i = i + 1) { + edgy ((i > 16) && (i < 33)) { + u[i] = 100.0; + } amogus { + u[i] = 0.0; + } + } + + 🚽 Time evolution using just comparisons + flex (t = 0; t < timesteps; t = t + 1) { + edgy (t % 10 == 0) { + yappin("Timestep %d: ", t); + flex (i = 0; i < N; i = i + 1) { + yapping("%lf", u[i]); + } + yapping(""); + } + + 🚽 Update interior points using only assignments + flex (i = 1; i < N-1; i = i + 1) { + edgy (u[i+1] > u[i]) { + u_new[i] = u[i] + 1.0; 🚽 If right neighbor is higher, increase slightly + } amogus edgy (u[i-1] > u[i]) { + u_new[i] = u[i] + 1.0; 🚽 If left neighbor is higher, increase slightly + } amogus edgy ((u[i-1] < u[i]) && (u[i+1] < u[i])) { + u_new[i] = u[i] - 1.0; 🚽 If both neighbors are lower, decrease slightly + } amogus { + u_new[i] = u[i]; 🚽 Otherwise keep same value + } + } + + u_new[0] = 0.0; + u_new[N-1] = 0.0; + + flex (i = 0; i < N; i = i + 1) { + u[i] = u_new[i]; + } + } + + bussin 0; +} +``` + +### What It Does + +- Demonstrates a **very** simplified 1D Heat Equation simulation or diffusion-like process (in a purely artificial sense). +- Initializes a 1D array `u` of size 50; elements from 17 through 32 are set to 100.0, others are 0.0. +- Runs 100 time steps of updates: + - Every 10 steps, prints the state of the array. + - At each step, updates `u[i]` based on comparisons with neighbors. +- Showcases: + - Double-precision arrays with `gigachad` (mapped to `double`). + - Conditionals (`edgy`/`amogus`) to handle different numeric comparisons. + - Printing partial array states (`yappin`) and final newlines with `yapping`. + +--- + +Feel free to explore and modify each example to learn more about how this language’s syntax and features work! diff --git a/examples/bubble_sort.brainrot b/examples/bubble_sort.brainrot new file mode 100644 index 0000000..ecf9bda --- /dev/null +++ b/examples/bubble_sort.brainrot @@ -0,0 +1,43 @@ +skibidi main { + rizz arr[10]; + rizz i; + rizz j; + rizz temp; + + 🚽 Initialize array with some unsorted numbers + arr[0] = 64; + arr[1] = 34; + arr[2] = 25; + arr[3] = 12; + arr[4] = 22; + arr[5] = 11; + arr[6] = 90; + arr[7] = 42; + arr[8] = 15; + arr[9] = 77; + + 🚽 Print original array + yapping("Original array: "); + flex (i = 0; i < 10; i = i + 1) { + yapping("%d ", arr[i]); + } + + 🚽 Bubble sort + flex (i = 0; i < 9; i = i + 1) { + flex (j = 0; j < 9 - i; j = j + 1) { + edgy (arr[j] > arr[j + 1]) { + temp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = temp; + } + } + } + + 🚽 Print sorted array + yapping("Sorted array: "); + flex (i = 0; i < 10; i = i + 1) { + yapping("%d ", arr[i]); + } + + bussin 0; +} diff --git a/examples/fizz_buzz.brainrot b/examples/fizz_buzz.brainrot index 606739a..41450f2 100644 --- a/examples/fizz_buzz.brainrot +++ b/examples/fizz_buzz.brainrot @@ -1,6 +1,6 @@ skibidi main { nut rizz i; - flex (i = 1; i <= 10; i = i + 1){ + flex (i = 1; i <= 15; i = i + 1){ edgy ( (i % 15) == 0 ) { yapping("FizzBuzz"); } amogus edgy ( (i % 3) == 0 ) { diff --git a/examples/heat_equation_1d.brainrot b/examples/heat_equation_1d.brainrot new file mode 100644 index 0000000..46ef9c0 --- /dev/null +++ b/examples/heat_equation_1d.brainrot @@ -0,0 +1,50 @@ +skibidi main { + rizz N = 50; + gigachad u[50]; + gigachad u_new[50]; + rizz i; + rizz t; + rizz timesteps = 100; + + 🚽 Initialize array + flex (i = 0; i < N; i = i + 1) { + edgy ((i > 16) && (i < 33)) { + u[i] = 100.0; + } amogus { + u[i] = 0.0; + } + } + + 🚽 Time evolution using just comparisons + flex (t = 0; t < timesteps; t = t + 1) { + edgy (t % 10 == 0) { + yapping("Timestep %d: ", t); + flex (i = 0; i < N; i = i + 1) { + yapping("%lf", u[i]); + } + yapping(""); + } + + 🚽 Update interior points using only assignments + flex (i = 1; i < N-1; i = i + 1) { + edgy (u[i+1] > u[i]) { + u_new[i] = u[i] + 1.0; 🚽 If right neighbor is higher, increase slightly + } amogus edgy (u[i-1] > u[i]) { + u_new[i] = u[i] + 1.0; 🚽 If left neighbor is higher, increase slightly + } amogus edgy ((u[i-1] < u[i]) && (u[i+1] < u[i])) { + u_new[i] = u[i] - 1.0; 🚽 If both neighbors are lower, decrease slightly + } amogus { + u_new[i] = u[i]; 🚽 Otherwise keep same value + } + } + + u_new[0] = 0.0; + u_new[N-1] = 0.0; + + flex (i = 0; i < N; i = i + 1) { + u[i] = u_new[i]; + } + } + + bussin 0; +} \ No newline at end of file diff --git a/examples/bool_array.brainrot b/test_cases/bool_array.brainrot similarity index 100% rename from examples/bool_array.brainrot rename to test_cases/bool_array.brainrot diff --git a/examples/boolean.brainrot b/test_cases/boolean.brainrot similarity index 100% rename from examples/boolean.brainrot rename to test_cases/boolean.brainrot diff --git a/examples/char.brainrot b/test_cases/char.brainrot similarity index 100% rename from examples/char.brainrot rename to test_cases/char.brainrot diff --git a/examples/char_array.brainrot b/test_cases/char_array.brainrot similarity index 100% rename from examples/char_array.brainrot rename to test_cases/char_array.brainrot diff --git a/examples/chill.brainrot b/test_cases/chill.brainrot similarity index 100% rename from examples/chill.brainrot rename to test_cases/chill.brainrot diff --git a/examples/circle_area.brainrot b/test_cases/circle_area.brainrot similarity index 100% rename from examples/circle_area.brainrot rename to test_cases/circle_area.brainrot diff --git a/examples/circle_area_double.brainrot b/test_cases/circle_area_double.brainrot similarity index 100% rename from examples/circle_area_double.brainrot rename to test_cases/circle_area_double.brainrot diff --git a/examples/comparison_edge_case.brainrot b/test_cases/comparison_edge_case.brainrot similarity index 100% rename from examples/comparison_edge_case.brainrot rename to test_cases/comparison_edge_case.brainrot diff --git a/examples/const.brainrot b/test_cases/const.brainrot similarity index 100% rename from examples/const.brainrot rename to test_cases/const.brainrot diff --git a/examples/division_edge_cases.brainrot b/test_cases/division_edge_cases.brainrot similarity index 100% rename from examples/division_edge_cases.brainrot rename to test_cases/division_edge_cases.brainrot diff --git a/examples/do-while.brainrot b/test_cases/do-while.brainrot similarity index 100% rename from examples/do-while.brainrot rename to test_cases/do-while.brainrot diff --git a/examples/double_array.brainrot b/test_cases/double_array.brainrot similarity index 100% rename from examples/double_array.brainrot rename to test_cases/double_array.brainrot diff --git a/examples/double_vs_float.brainrot b/test_cases/double_vs_float.brainrot similarity index 100% rename from examples/double_vs_float.brainrot rename to test_cases/double_vs_float.brainrot diff --git a/test_cases/fizz_buzz.brainrot b/test_cases/fizz_buzz.brainrot new file mode 100644 index 0000000..606739a --- /dev/null +++ b/test_cases/fizz_buzz.brainrot @@ -0,0 +1,15 @@ +skibidi main { + nut rizz i; + flex (i = 1; i <= 10; i = i + 1){ + edgy ( (i % 15) == 0 ) { + yapping("FizzBuzz"); + } amogus edgy ( (i % 3) == 0 ) { + yapping("Fizz"); + } amogus edgy ( (i % 5) == 0 ) { + yapping("Buzz"); + } amogus { + yapping("%d", i); + } + } + bussin 0; +} diff --git a/examples/fizz_buzz_short.brainrot b/test_cases/fizz_buzz_short.brainrot similarity index 100% rename from examples/fizz_buzz_short.brainrot rename to test_cases/fizz_buzz_short.brainrot diff --git a/examples/float.brainrot b/test_cases/float.brainrot similarity index 100% rename from examples/float.brainrot rename to test_cases/float.brainrot diff --git a/examples/float_array.brainrot b/test_cases/float_array.brainrot similarity index 100% rename from examples/float_array.brainrot rename to test_cases/float_array.brainrot diff --git a/examples/float_precision.brainrot b/test_cases/float_precision.brainrot similarity index 100% rename from examples/float_precision.brainrot rename to test_cases/float_precision.brainrot diff --git a/examples/for_loop.brainrot b/test_cases/for_loop.brainrot similarity index 100% rename from examples/for_loop.brainrot rename to test_cases/for_loop.brainrot diff --git a/examples/for_loop_break.brainrot b/test_cases/for_loop_break.brainrot similarity index 100% rename from examples/for_loop_break.brainrot rename to test_cases/for_loop_break.brainrot diff --git a/test_cases/hello_world.brainrot b/test_cases/hello_world.brainrot new file mode 100644 index 0000000..b8ea393 --- /dev/null +++ b/test_cases/hello_world.brainrot @@ -0,0 +1,4 @@ +skibidi main { + yappin("Hello, World!\n"); + bussin 0; +} diff --git a/examples/inc-dec.brainrot b/test_cases/inc-dec.brainrot similarity index 100% rename from examples/inc-dec.brainrot rename to test_cases/inc-dec.brainrot diff --git a/examples/int.brainrot b/test_cases/int.brainrot similarity index 100% rename from examples/int.brainrot rename to test_cases/int.brainrot diff --git a/examples/int_array.brainrot b/test_cases/int_array.brainrot similarity index 100% rename from examples/int_array.brainrot rename to test_cases/int_array.brainrot diff --git a/examples/integer_overflow.brainrot b/test_cases/integer_overflow.brainrot similarity index 100% rename from examples/integer_overflow.brainrot rename to test_cases/integer_overflow.brainrot diff --git a/examples/mixed_types.brainrot b/test_cases/mixed_types.brainrot similarity index 100% rename from examples/mixed_types.brainrot rename to test_cases/mixed_types.brainrot diff --git a/examples/modulo.brainrot b/test_cases/modulo.brainrot similarity index 100% rename from examples/modulo.brainrot rename to test_cases/modulo.brainrot diff --git a/examples/modulo_edge_case.brainrot b/test_cases/modulo_edge_case.brainrot similarity index 100% rename from examples/modulo_edge_case.brainrot rename to test_cases/modulo_edge_case.brainrot diff --git a/examples/nest-loop.brainrot b/test_cases/nest-loop.brainrot similarity index 100% rename from examples/nest-loop.brainrot rename to test_cases/nest-loop.brainrot diff --git a/examples/next-prime.brainrot b/test_cases/next-prime.brainrot similarity index 100% rename from examples/next-prime.brainrot rename to test_cases/next-prime.brainrot diff --git a/examples/output_error.brainrot b/test_cases/output_error.brainrot similarity index 100% rename from examples/output_error.brainrot rename to test_cases/output_error.brainrot diff --git a/examples/rage_quit.brainrot b/test_cases/rage_quit.brainrot similarity index 100% rename from examples/rage_quit.brainrot rename to test_cases/rage_quit.brainrot diff --git a/examples/scientific_notation.brainrot b/test_cases/scientific_notation.brainrot similarity index 100% rename from examples/scientific_notation.brainrot rename to test_cases/scientific_notation.brainrot diff --git a/examples/short_array.brainrot b/test_cases/short_array.brainrot similarity index 100% rename from examples/short_array.brainrot rename to test_cases/short_array.brainrot diff --git a/examples/sizeof.brainrot b/test_cases/sizeof.brainrot similarity index 100% rename from examples/sizeof.brainrot rename to test_cases/sizeof.brainrot diff --git a/examples/switch_case.brainrot b/test_cases/switch_case.brainrot similarity index 100% rename from examples/switch_case.brainrot rename to test_cases/switch_case.brainrot diff --git a/examples/type_conversion.brainrot b/test_cases/type_conversion.brainrot similarity index 100% rename from examples/type_conversion.brainrot rename to test_cases/type_conversion.brainrot diff --git a/examples/uint.brainrot b/test_cases/uint.brainrot similarity index 100% rename from examples/uint.brainrot rename to test_cases/uint.brainrot diff --git a/examples/unsigned_integer_wrap.brainrot b/test_cases/unsigned_integer_wrap.brainrot similarity index 100% rename from examples/unsigned_integer_wrap.brainrot rename to test_cases/unsigned_integer_wrap.brainrot diff --git a/examples/while_loop.brainrot b/test_cases/while_loop.brainrot similarity index 100% rename from examples/while_loop.brainrot rename to test_cases/while_loop.brainrot diff --git a/examples/while_loop_break.brainrot b/test_cases/while_loop_break.brainrot similarity index 100% rename from examples/while_loop_break.brainrot rename to test_cases/while_loop_break.brainrot diff --git a/tests/test_brainrot.py b/tests/test_brainrot.py index 5040ec4..efb8a2d 100644 --- a/tests/test_brainrot.py +++ b/tests/test_brainrot.py @@ -16,7 +16,7 @@ @pytest.mark.parametrize("example,expected_output", expected_results.items()) def test_brainrot_examples(example, expected_output): brainrot_path = os.path.abspath(os.path.join(script_dir, "../brainrot")) - example_file_path = os.path.abspath(os.path.join(script_dir, f"../examples/{example}.brainrot")) + example_file_path = os.path.abspath(os.path.join(script_dir, f"../test_cases/{example}.brainrot")) command = f"{brainrot_path} < {example_file_path}" result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True)