Skip to content

compiler: initial support for enums#161

Merged
pointbazaar merged 2 commits intomasterfrom
implement-enum
Apr 13, 2025
Merged

compiler: initial support for enums#161
pointbazaar merged 2 commits intomasterfrom
implement-enum

Conversation

@pointbazaar
Copy link
Owner

@pointbazaar pointbazaar commented Apr 12, 2025

Simple way to create named values.

Enum member names and enum names have to be all uppercase.

This separates them from other type names like structs.

Summary by CodeRabbit

  • New Features

    • Introduced full support for enumerations, allowing users to define and use enum types with associated values.
    • Enhanced language syntax by recognizing the new "enum" keyword and properly processing enum values during compilation.
    • Added new examples showcasing the usage of enumerations, including both standard and hexadecimal value definitions.
  • Documentation

    • Updated grammar and language documentation to include enum declarations, usage rules, and examples that demonstrate the new enumeration features.

@coderabbitai
Copy link

coderabbitai bot commented Apr 12, 2025

Walkthrough

The changes add comprehensive support for enumerations throughout the project. New AST structures and fields are introduced to represent enum declarations and members, along with corresponding token kinds and union members. Memory management, visitor traversal, type checking, and TAC generation are updated to recognize and process enum values. Parser modules are extended to parse enum declarations and members, while grammar documentation and tests are revised accordingly. Additionally, a new enum table is implemented and integrated into the symbol table, and lexer token classification is enhanced by introducing a new keyword for enum.

Changes

File(s) Change Summary
ast/ast.h, ast/ast/ast_enum.h, ast/ast/ast_expr.h, ast/ast_declare.h Added enum support in the AST: new fields in Namespace (enums, count_enums, capacity_enums), new structures EnumDecl and EnumMember, and a new term kind (TERM_KIND_ENUM_VALUE with a corresponding union member).
ast/util/free_ast.c, ast/util/free_ast.h Introduced free_enum_decl() and updated free_namespace() and free_term() to free memory allocated for enum declarations and enum value strings.
ast/visitor/visitor.c, ast/visitor/visitor.h Added static visitor functions (visit_enum_decl, visit_enum_member, visit_enum_value) and new NODE_TYPE enumerators for enums; updated visit_namespace and visit_term to process enum nodes.
compiler/main/compiler.c, compiler/main/util/fill_tables.c, compiler/main/util/fill_tables.h Modified fill_tables() to return a boolean; enhanced error checking by verifying the result of enum_table_fill().
compiler/main/gen_tac/gen_tac_term.c, compiler/main/gen_tac/gen_tac_constvalue.c, compiler/main/gen_tac/gen_tac.c, compiler/main/gen_tac/gen_tac.h Removed int_value_from_const and added tac_term_enum_value(); updated tac_term() to handle TERM_KIND_ENUM_VALUE with assertions and error logging.
compiler/main/typechecker/tc_term.c, compiler/main/typeinference/typeinfer_term.c Added new case for TERM_KIND_ENUM_VALUE in type checking and inference routines.
compiler/test/gen_tac/test_gen_tac_assignstmt.c, compiler/test/gen_tac/test_gen_tac_structdecl.c, compiler/test/gen_tac/test_gen_tac_variable.c, compiler/test/typeinference/test-src/infer_type_call_with_struct_member_access.dg Updated tests to reflect structure renaming (e.g. A to Astruct, B to Bstruct) and incorporate enum-related changes.
docs/html/grammar.html Added new grammar productions for EnumDecl, EnumMember, and EnumValue; updated Namespace and Term productions to include enumerations.
examples/enum/simple_enum/simple_enum.dg, examples/enum/simple_enum/simple_enum.exitcode, examples/struct/nested/nested.dg, examples/struct/very_nested/very_nested.dg Introduced a simple enum example (VALUES) and exit code file; renamed structures in nested examples for consistency.
lexer/src/lexer.c Added handling for the "enum" keyword and updated identifier classification to distinguish enum value tokens based on casing.
parser/main/CMakeLists.txt, parser/main/astnodes/EnumDecl.c, parser/main/astnodes/EnumDecl.h, parser/main/astnodes/EnumMember.c, parser/main/astnodes/EnumMember.h, parser/main/astnodes/Namespace.c, parser/main/astnodes/expr/Term.c Introduced new parser sources and functions (makeEnumDecl, makeEnumMember) for enum declarations and members; updated namespace and term parsing to include enum support.
tables/CMakeLists.txt, tables/enum/enum_table.c, tables/enum/enum_table.h, tables/symtable/symtable.c, tables/symtable/symtable.h Implemented a new EnumTable with functions for construction, insertion, lookup, fill, and printing, and integrated it within the symbol table.
token/TokenKeys.h Adjusted macro values (e.g. EMPTY, LINE_NO, etc.) and added a new macro KEYWORD_ENUM.
examples/enum/enum_hex_value/enum_hex_value.dg, examples/enum/enum_hex_value/enum_hex_value.exitcode Introduced a new enum example with hexadecimal values and corresponding exit code file.

Sequence Diagram(s)

sequenceDiagram
    participant L as Lexer
    participant P as Parser
    participant ND as AST (Namespace)
    participant ET as EnumTable
    participant ST as Symbol Table

    L->>P: Provide tokens (including KEYWORD_ENUM and enum value tokens)
    P->>P: Call makeEnumDecl() / makeEnumMember() to parse enum declarations
    P->>ND: Add parsed EnumDecl to Namespace (update enums, count_enums, capacity_enums)
    ND->>P: Return updated Namespace
    P->>ST: Pass Namespace during symbol table build
    ST->>ET: Call enum_table_fill() with Namespace enums
    ET->>ST: Enum entries inserted (using enum_table_insert)
    ST->>P: Proceed with further compilation steps
Loading
sequenceDiagram
    participant TAC as TAC Generator
    participant T as Term Processor
    participant ET as EnumTable
    participant Buffer as TACBuffer

    TAC->>T: Process Term of kind TERM_KIND_ENUM_VALUE
    T->>T: Call tac_term_enum_value() with assertions
    T->>ET: Lookup enum value by name (enum_table_lookup)
    ET-->>T: Return enum's integer value (or error if not found)
    T->>Buffer: Append TAC constant with retrieved enum value
    Buffer->>T: Confirm constant appended
Loading

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@netlify
Copy link

netlify bot commented Apr 12, 2025

Deploy Preview for espl1000 ready!

Name Link
🔨 Latest commit ab4826f
🔍 Latest deploy log https://app.netlify.com/sites/espl1000/deploys/67fab1f01b7425000841e88a
😎 Deploy Preview https://deploy-preview-161--espl1000.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🔭 Outside diff range comments (2)
parser/main/astnodes/Namespace.c (2)

65-65: ⚠️ Potential issue

Fix implicit function declaration warnings

The pipeline reports implicit declarations of sprintf functions.

The function asprintf at line 68 is a GNU extension and not part of standard C. Either:

  1. Include the appropriate header that defines asprintf:
+#define _GNU_SOURCE
 #include <string.h>
 #include <stdio.h>
  1. Or replace it with standard functions:
-asprintf(&(res->name), "%s", name);
+res->name = malloc(strlen(name) + 1);
+if (!res->name) {
+    goto error_res_token_path;
+}
+strcpy(res->name, name);

Also applies to: 68-68


100-121: ⚠️ Potential issue

Error handling label order issue

There's an unlabeled goto target at line 110 (error_res_name) but there's no corresponding label in the code.

This could lead to unexpected behavior. Make sure all goto targets are properly defined:

error_res_token_path:
	free(res->token_path);
error_res_src_path:
	free(res->src_path);
-error_res_name:
+// error_res_name label is not used
	free(res->name);
error_res_enums:
	free(res->enums);
🧹 Nitpick comments (18)
ast/ast/ast_enum.h (1)

11-13: Consider adding capacity field for dynamic array management

The EnumDecl structure contains a members array but doesn't include a capacity field. If members are added dynamically, you might need a capacity field to manage memory allocation/reallocation, similar to how other dynamic arrays are managed in the codebase.

struct EnumDecl {
	struct ASTNode super;

	// must be all uppercase (underscores are ok)
	char* name;

	struct EnumMember** members;
	uint16_t count_members;
+	size_t capacity_members;
};
token/TokenKeys.h (1)

13-13: Missing documentation for TOKEN_ENUM_VALUE

The new TOKEN_ENUM_VALUE token is added without any descriptive comment. Consider adding a comment to explain its purpose, similar to other token definitions in this file.

+// Token for enum values
 #define TOKEN_ENUM_VALUE 4
compiler/main/gen_tac/gen_tac_term.c (1)

44-46: Unnecessary break statement after return.

The break statement after the return is redundant since the function will exit upon return.

 case TERM_KIND_ENUM_VALUE:
     return tac_term_enum_value(buffer, t, ctx);
-    break;
parser/main/astnodes/EnumMember.c (1)

53-59: Consider adding an error message for missing semicolon

While the code correctly checks for a semicolon, it doesn't provide an error message like in other error cases.

 	if (next->kind != SEMICOLON) {
+		fprintf(stderr, "expected ';'\n");
 		freeTokenListShallow(copy);
 		free(res);
 		return NULL;
 	}
tables/enum/enum_table.h (8)

23-29: Insufficient documentation for the return value of enum_table_insert

The function documentation describes the parameters well but doesn't explain what the boolean return value represents. A user might not know that it returns false if the name already exists or if memory allocation fails.

// @brief inserts a new entry into enum value table
// @param str   the name to enter
// @param value the value for that enum value name
+// @return true if insertion was successful, false if name is null, already exists, or if memory allocation fails
bool enum_table_insert(struct EnumTable* data, char* str, uint64_t value);

27-29: Incorrect documentation format in enum_table_lookup

The documentation states "@returns" twice with contradictory conditions. The second line states "returns integer value >= for the enum value name" which is incomplete and confusing.

-// @returns -1 if entry is not found
-// @returns integer value >= for the enum value name
+// @return -1 if entry is not found
+// @return non-negative integer value when the enum value name is found
int64_t enum_table_lookup(struct EnumTable* data, char* name);

31-31: Missing documentation for enum_table_fill function

The enum_table_fill function lacks any documentation explaining its purpose and parameters.

+// @brief populates the enum table with entries from a namespace
+// @param enum_table the table to populate
+// @param ns the namespace containing the enum declarations
+// @param debug whether to print debug information
+// @return true if all entries were inserted successfully, false otherwise
bool enum_table_fill(struct EnumTable* enum_table, struct Namespace* ns, bool debug);

33-33: Missing documentation for enum_table_print function

The enum_table_print function lacks documentation.

+// @brief prints the contents of the enum table to stdout
void enum_table_print(struct EnumTable* enum_table);

35-35: Missing documentation for int_value_from_const function

The int_value_from_const function lacks documentation explaining its purpose, parameter, and possible return values.

+// @brief converts a ConstValue to an integer
+// @param cv the ConstValue to convert
+// @return the integer value of the constant, or -1 if the kind is not recognized
int int_value_from_const(struct ConstValue* cv);

1-36: Function parameters should be marked as const when appropriate

Several function parameters that are not modified should be marked as const to improve code safety and readability.

-bool enum_table_insert(struct EnumTable* data, char* str, uint64_t value);
+bool enum_table_insert(struct EnumTable* data, const char* str, uint64_t value);

-int64_t enum_table_lookup(struct EnumTable* data, char* name);
+int64_t enum_table_lookup(struct EnumTable* data, const char* name);

-bool enum_table_fill(struct EnumTable* enum_table, struct Namespace* ns, bool debug);
+bool enum_table_fill(struct EnumTable* enum_table, const struct Namespace* ns, bool debug);

-int int_value_from_const(struct ConstValue* cv);
+int int_value_from_const(const struct ConstValue* cv);

9-9: Structure declaration should include typedef

Consider adding a typedef for EnumTable to simplify usage and maintain consistency with C conventions.

-struct EnumTable;
+typedef struct EnumTable EnumTable;
+struct EnumTable;

11-17: Structure declaration should include typedef

Consider adding a typedef for EnumTableEntry to simplify usage and maintain consistency with C conventions.

-struct EnumTableEntry {
+typedef struct EnumTableEntry {
 
 	// needs to be freed
 	char* name;
 
 	uint64_t value;
-};
+} EnumTableEntry;
tables/enum/enum_table.c (6)

44-49: Potential integer overflow in resize condition

The condition (data->count_entries + 1) >= data->capacity could lead to an integer overflow if count_entries is close to SIZE_MAX. Consider a safer comparison.

-	if ((data->count_entries + 1) >= data->capacity) {
+	if (data->count_entries >= data->capacity) {
 		data->capacity *= 2;
 		data->entries = realloc(data->entries, data->capacity * sizeof(struct EnumTableEntry*));
 
 		assert(data->entries);
 	}

102-112: Explicitly define the constant value kinds

The function int_value_from_const uses magic numbers for the different kinds of constants. Consider defining these as an enum to improve code readability and maintainability.

+// Define this in the appropriate header file (perhaps ast/ast.h)
+typedef enum {
+    CONST_BOOL = 1,
+    CONST_INT = 2,
+    CONST_CHAR = 3,
+    CONST_STRING = 4, // Assuming this exists based on the numbering
+    CONST_HEX = 5,
+    CONST_BIN = 6
+} ConstValueKind;

int int_value_from_const(struct ConstValue* cv) {

	switch (cv->kind) {
-		case 1: return (int)cv->ptr.m1_bool_const;
-		case 2: return (int)cv->ptr.m2_int_const;
-		case 3: return (int)cv->ptr.m3_char_const;
-		case 5: return (int)cv->ptr.m5_hex_const;
-		case 6: return (int)cv->ptr.m5_hex_const;
+		case CONST_BOOL: return (int)cv->ptr.m1_bool_const;
+		case CONST_INT: return (int)cv->ptr.m2_int_const;
+		case CONST_CHAR: return (int)cv->ptr.m3_char_const;
+		case CONST_HEX: return (int)cv->ptr.m5_hex_const;
+		case CONST_BIN: return (int)cv->ptr.m6_bin_const; // Assuming this is the correct field
	}
	return -1;
}

114-130: Add documentation for enum_table_fill_single function

The enum_table_fill_single function lacks documentation explaining its purpose and parameters.

+/**
+ * @brief Fills the enum table with entries from a single enum declaration
+ * @param enum_table the table to populate
+ * @param ed the enum declaration to process
+ * @return true if all entries were inserted successfully, false otherwise
+ */
static bool enum_table_fill_single(struct EnumTable* enum_table, struct EnumDecl* ed) {

165-165: Potential format specifier mismatch in printf

The printf statement uses %ld to print entry->value which is defined as uint64_t. This could lead to incorrect output or warnings on some platforms. Use the proper format specifier for uint64_t.

-		printf("%-20s = %10ld\n", entry->name, entry->value);
+		printf("%-20s = %10" PRIu64 "\n", entry->name, entry->value);

And add the necessary include:

+#include <inttypes.h>

84-100: Consider using strdup in enum_table_lookup

The function enum_table_lookup is comparing strings using strcmp. This is fine, but consider using a hash table for better performance as the number of enum entries grows.

The current implementation has O(n) lookup time. A hash table implementation would provide O(1) average lookup time, which could be beneficial for larger enum tables. Consider implementing a hash table-based lookup for better performance.


17-26: Initialize entries array to NULL in constructor

The enum_table_ctor function uses calloc for the entries array, which initializes all entries to NULL (zero). This is good practice, but it would be clearer to handle the error case of calloc failing.

struct EnumTable* enum_table_ctor() {

	struct EnumTable* res = calloc(1, sizeof(struct EnumTable));
+	if (res == NULL) {
+		return NULL;
+	}
+	
	res->count_entries = 0;
	res->capacity = 10;

	res->entries = calloc(res->capacity, sizeof(struct DataEntry*));
+	if (res->entries == NULL) {
+		free(res);
+		return NULL;
+	}

	return res;
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e1b03ea and e1f9a1b.

📒 Files selected for processing (40)
  • ast/ast.h (2 hunks)
  • ast/ast/ast_enum.h (1 hunks)
  • ast/ast/ast_expr.h (2 hunks)
  • ast/ast_declare.h (1 hunks)
  • ast/util/free_ast.c (3 hunks)
  • ast/util/free_ast.h (1 hunks)
  • ast/visitor/visitor.c (5 hunks)
  • ast/visitor/visitor.h (1 hunks)
  • compiler/main/compiler.c (1 hunks)
  • compiler/main/gen_tac/gen_tac.c (0 hunks)
  • compiler/main/gen_tac/gen_tac.h (0 hunks)
  • compiler/main/gen_tac/gen_tac_constvalue.c (1 hunks)
  • compiler/main/gen_tac/gen_tac_term.c (1 hunks)
  • compiler/main/typechecker/tc_term.c (1 hunks)
  • compiler/main/typeinference/typeinfer_term.c (1 hunks)
  • compiler/main/util/fill_tables.c (2 hunks)
  • compiler/main/util/fill_tables.h (1 hunks)
  • compiler/test/gen_tac/test_gen_tac_assignstmt.c (1 hunks)
  • compiler/test/gen_tac/test_gen_tac_structdecl.c (2 hunks)
  • compiler/test/gen_tac/test_gen_tac_variable.c (1 hunks)
  • compiler/test/typeinference/test-src/infer_type_call_with_struct_member_access.dg (1 hunks)
  • docs/html/grammar.html (2 hunks)
  • examples/enum/simple_enum/simple_enum.dg (1 hunks)
  • examples/enum/simple_enum/simple_enum.exitcode (1 hunks)
  • examples/struct/nested/nested.dg (1 hunks)
  • examples/struct/very_nested/very_nested.dg (2 hunks)
  • lexer/src/lexer.c (2 hunks)
  • parser/main/CMakeLists.txt (1 hunks)
  • parser/main/astnodes/EnumDecl.c (1 hunks)
  • parser/main/astnodes/EnumDecl.h (1 hunks)
  • parser/main/astnodes/EnumMember.c (1 hunks)
  • parser/main/astnodes/EnumMember.h (1 hunks)
  • parser/main/astnodes/Namespace.c (6 hunks)
  • parser/main/astnodes/expr/Term.c (1 hunks)
  • tables/CMakeLists.txt (1 hunks)
  • tables/enum/enum_table.c (1 hunks)
  • tables/enum/enum_table.h (1 hunks)
  • tables/symtable/symtable.c (3 hunks)
  • tables/symtable/symtable.h (2 hunks)
  • token/TokenKeys.h (2 hunks)
💤 Files with no reviewable changes (2)
  • compiler/main/gen_tac/gen_tac.h
  • compiler/main/gen_tac/gen_tac.c
🧰 Additional context used
🧬 Code Graph Analysis (10)
compiler/main/typeinference/typeinfer_term.c (2)
compiler/main/typeinference/util/type_str.h (1)
  • typeFromStrPrimitive (5-5)
compiler/main/typeinference/util/type_str.c (1)
  • typeFromStrPrimitive (75-83)
parser/main/astnodes/expr/Term.c (2)
token/list/TokenList.h (2)
  • list_head (30-30)
  • list_consume (16-16)
token/list/TokenList.c (2)
  • list_head (183-185)
  • list_consume (89-93)
compiler/main/gen_tac/gen_tac_term.c (2)
tables/enum/enum_table.h (2)
  • enum_table_lookup (29-29)
  • enum_table_print (33-33)
tables/enum/enum_table.c (2)
  • enum_table_lookup (84-100)
  • enum_table_print (158-169)
parser/main/astnodes/EnumMember.c (1)
parser/main/astnodes/EnumMember.h (1)
  • makeEnumMember (6-6)
compiler/main/compiler.c (2)
compiler/main/util/fill_tables.h (1)
  • fill_tables (8-8)
compiler/main/util/fill_tables.c (1)
  • fill_tables (14-42)
ast/util/free_ast.c (1)
ast/util/free_ast.h (1)
  • free_enum_decl (32-32)
parser/main/astnodes/EnumDecl.c (3)
parser/main/astnodes/EnumDecl.h (1)
  • makeEnumDecl (6-6)
parser/main/astnodes/EnumMember.h (1)
  • makeEnumMember (6-6)
parser/main/astnodes/EnumMember.c (1)
  • makeEnumMember (19-65)
tables/symtable/symtable.c (2)
tables/enum/enum_table.h (2)
  • enum_table_ctor (19-19)
  • enum_table_dtor (20-20)
tables/enum/enum_table.c (2)
  • enum_table_ctor (17-26)
  • enum_table_dtor (28-38)
parser/main/astnodes/Namespace.c (4)
token/list/TokenList.h (1)
  • list_head (30-30)
token/list/TokenList.c (1)
  • list_head (183-185)
parser/main/astnodes/EnumDecl.h (1)
  • makeEnumDecl (6-6)
parser/main/astnodes/EnumDecl.c (1)
  • makeEnumDecl (18-87)
tables/enum/enum_table.c (1)
tables/enum/enum_table.h (7)
  • enum_table_ctor (19-19)
  • enum_table_dtor (20-20)
  • enum_table_insert (25-25)
  • enum_table_lookup (29-29)
  • int_value_from_const (35-35)
  • enum_table_fill (31-31)
  • enum_table_print (33-33)
🪛 CircleCI: valgrind
parser/main/astnodes/EnumMember.c

[warning] 33-33: Implicit declaration of function 'sprintf'; did you mean 'vsprintf'?

parser/main/astnodes/Namespace.c

[warning] 52-52: Implicit declaration of function 'sprintf'; did you mean 'vsprintf'?


[warning] 68-68: Implicit declaration of function 'sprintf'; did you mean 'vsprintf'?

🔇 Additional comments (77)
examples/enum/simple_enum/simple_enum.exitcode (1)

1-2: Exit code looks appropriate for demonstration purposes.

This new file containing just the exit code 28 appears to be a simple test case for the enum functionality being added. It's part of the simple_enum example, likely corresponding to a value defined in the related .dg file.

parser/main/astnodes/EnumMember.h (1)

1-6: Header file structure looks good.

The header file follows good C programming practices with proper include guards, forward declarations, and a clean function signature for creating enum members.

parser/main/astnodes/EnumDecl.h (1)

1-6: Header file structure looks good.

The header file follows good C programming practices with proper include guards, forward declarations, and a clean function signature for creating enum declarations.

tables/CMakeLists.txt (1)

17-19: Appropriate integration in build system.

The new enum table source files are correctly added to the "sd-tables" static library. The placement and organization fit well with the existing codebase structure.

parser/main/CMakeLists.txt (1)

38-40: Integration of enum support files looks good.

The addition of EnumDecl.c and EnumMember.c to the build system is appropriately placed in the CMake configuration. These files will provide the necessary functionality for parsing enum declarations and members.

examples/enum/simple_enum/simple_enum.dg (2)

2-6: Enum declaration follows the specified conventions.

The enum name VALUES and its members (VALUE_1, VALUE_28, VALUE_29) are correctly written in uppercase, following the convention mentioned in the PR description. The explicit value assignments are also properly formatted with semicolon separators.


8-11: Example usage of enum value is correct.

The main function correctly demonstrates using an enum member (VALUE_28) as a value that can be returned from a function. This is a good basic example to validate the enum implementation.

ast/util/free_ast.h (1)

31-33: Memory management for enum declarations looks good.

The addition of the free_enum_decl function follows the established pattern for other AST nodes. Each type gets its own free function, ensuring proper memory management. The new section with the comment // enum helps organize the code by categorizing the enum-related functions.

compiler/main/typeinference/typeinfer_term.c (1)

37-37: Type inference for enum values looks good

Setting enum values to be inferred as uint64 is a reasonable choice. This is consistent with the common practice of using integer types for enum values underneath.

ast/ast_declare.h (1)

14-14: Forward declaration for EnumDecl correctly added

The forward declaration for struct EnumDecl is placed appropriately with other top-level declarations.

tables/symtable/symtable.h (2)

9-9: Include for enum table header looks good

The include statement for the enum table header is appropriately placed with other table include statements.


26-26: EnumTable field added to ST structure

The addition of the enum_table field to the ST structure allows the symbol table to track enum declarations, which is necessary for the implementation of enum support.

compiler/main/typechecker/tc_term.c (1)

37-37: Type checking for enum values looks correct

Returning true for enum values is consistent with how other constant values are handled in the type checker. Since enum values are essentially named constants, this approach makes sense.

parser/main/astnodes/expr/Term.c (1)

68-71: LGTM: Enum value handling added properly

The implementation for handling enum values in the makeTerm function is correctly structured and follows the pattern established for other token types. The code appropriately sets the Term kind to TERM_KIND_ENUM_VALUE, duplicates the string value using strdup(), and consumes the token from the list.

compiler/main/util/fill_tables.h (2)

3-4: LGTM: Adding stdbool.h header for bool type

Appropriate inclusion of the stdbool.h header to support the updated return type.


8-8: LGTM: Improved error handling with bool return type

Good improvement to change the return type from void to bool, allowing the function to indicate success or failure when filling tables. This is particularly valuable for handling enum table filling failures.

ast/ast/ast_expr.h (2)

81-81: LGTM: Added enum value to TERM_KIND enum

Appropriate addition of TERM_KIND_ENUM_VALUE to the enum list to support the new enum term type.


96-96: LGTM: Added enum_value_term to the union

The char* enum_value_term field is correctly added to the union to store enum value names. This complements the changes in Term.c for handling enum values.

compiler/test/typeinference/test-src/infer_type_call_with_struct_member_access.dg (2)

2-2: LGTM: Improved struct naming

Good change to rename the struct from 'A' to the more descriptive 'Astruct', improving code readability.


7-8: LGTM: Updated variable declaration to use renamed struct

Variable declaration correctly updated to use the renamed Astruct type.

compiler/main/compiler.c (1)

119-121: Good addition of error handling for fill_tables

The error handling has been improved by checking the return value of fill_tables and propagating the error. This ensures that subsequent compilation steps are only executed if the tables are properly filled.

lexer/src/lexer.c (2)

336-336: LGTM: Added enum keyword recognition

The addition of the "enum" keyword recognition is correctly implemented using the existing macro pattern.


354-366: Good implementation of the uppercase naming convention for enum values

This change implements the PR requirement that "enum member names must be written in uppercase letters" by checking if all characters in an identifier are uppercase. This helps distinguish enum values from other identifiers in the language.

ast/visitor/visitor.h (1)

27-30: LGTM: Added enum-related node types to the visitor pattern

The new node types for enum declarations, members, and values have been appropriately added to the NODE_TYPE enum. This enables the visitor pattern to properly traverse enum-related nodes in the AST.

examples/struct/nested/nested.dg (3)

2-5: Appropriate renaming of struct to distinguish from enums

The structure has been renamed from A to Astruct to avoid potential confusion with uppercase-only enum names. This aligns with the PR's naming convention where enum names must be in uppercase.


7-7: Consistent renaming of struct

The structure has been renamed from B to Bstruct, following the same pattern as the Astruct rename.


13-13: Updated variable type to match the renamed struct

The local variable's type has been correctly updated to use the renamed Astruct type.

ast/ast/ast_enum.h (1)

1-21: Clean implementation of enum structure definitions

The implementation correctly defines the required structures for enum support with proper inheritance from ASTNode. The comment about uppercase naming convention aligns with the PR objectives.

compiler/test/gen_tac/test_gen_tac_variable.c (1)

37-37: Appropriate structure renaming for clarity

Renaming the structure from (likely) "A" to "Astruct" helps distinguish it from enum names, which according to the PR will be uppercase. This change is consistent with the PR objectives.

compiler/test/gen_tac/test_gen_tac_assignstmt.c (1)

57-57: Appropriate structure renaming for clarity

Renaming the structure from (likely) "A" to "Astruct" helps distinguish it from enum names, which according to the PR will be uppercase. This change maintains consistency across test files.

compiler/test/gen_tac/test_gen_tac_structdecl.c (1)

15-15: Consistent structure renaming across test cases

Renaming the structure from "A" to "Astruct" in both test functions maintains consistency with the changes in other files and helps distinguish struct types from enum types (which will use uppercase names per PR objectives).

Also applies to: 38-38

token/TokenKeys.h (4)

8-8: Value adjustment for TPARAM

The value for TPARAM has been decreased from 3 to 2. Ensure all code that directly uses this numerical value is updated accordingly.


11-11: Value adjustment for ID

The value for ID has been decreased from 4 to 3. Ensure all code that directly uses this numerical value is updated accordingly.


100-101: LGTM - New enum keyword token

The addition of KEYWORD_ENUM supports the PR objective of adding enum support to the compiler. The token value is appropriately placed in the keywords section.


4-5:

Details

❓ Verification inconclusive

Token value adjustments may impact existing code

The values for EMPTY and LINE_NO have been decreased. This change could affect any code that relies on these specific numerical values.


🏁 Script executed:

#!/bin/bash
# Check where these token values are used directly in the codebase
echo "Checking for direct usage of EMPTY value:"
rg -n "== 1" --include="*.c" | grep -i token
echo "Checking for direct usage of LINE_NO value:"
rg -n "== 2" --include="*.c" | grep -i token

Length of output: 1167



Attention: Confirm Token Value Modifications

The update in token/TokenKeys.h (lines 4–5) reduces the numerical values for EMPTY (now 0) and LINE_NO (now 1). This reduction might affect parts of the code relying on the original values.

  • Action Required: Manually verify all code paths that reference these definitions.
  • Next Step: Use the revised script above (or an equivalent manual search) to check for direct comparisons or usage in C source files.
  • Note: The previous attempt using --include="*.c" resulted in an error. The updated script now uses -g "*.c" for filtering.

🏁 Script executed:

#!/bin/bash
# Re-run the check using the proper flag for filtering C source files
echo "Checking for direct usage of EMPTY token (value expected == 1):"
rg -n "== 1" -g "*.c" | grep -i "token"

echo "Checking for direct usage of LINE_NO token (value expected == 2):"
rg -n "== 2" -g "*.c" | grep -i "token"

Length of output: 725


Verify Token Macro Adjustments and Update Corresponding Test Expectations

The token value changes in token/TokenKeys.h now define:

#define EMPTY 0
#define LINE_NO 1

However, several tests still compare against the previous hardcoded values. For example:

  • In lexer/test/testcases/tests_mixed.c:
    • Line 271 asserts that tokens[0]->line_num == 1
    • Line 174 asserts that tokens[1]->line_num == 2
  • Other tests in token/test/testcases/tests_tokenlist.c and parser/test/astnodes/expr/ExprTest.c also expect numeric values such as 1 for list sizes.

Please carefully verify that these tests are updated to reflect the new token values or that the logic producing the token values is adjusted accordingly. Manual verification of all code paths relying on these macros is recommended.

ast/ast.h (2)

13-13: LGTM - Added include for enum AST definitions

The inclusion of "ast/ast_enum.h" is appropriate for supporting enum declarations in the AST structure.


43-47: LGTM - New fields for managing enum declarations

The addition of fields to store enum declarations in the Namespace structure follows the same pattern as other declaration types (structs, methods), which is good for consistency.

tables/symtable/symtable.c (3)

10-10: LGTM - Added include for enum table support

The inclusion of the enum table header is appropriate for integrating enum support into the symbol table.


37-37: LGTM - Enum table initialization

The initialization of the enum table in the symbol table constructor is properly implemented, following the pattern used for other table types.


48-48: LGTM - Enum table cleanup

The cleanup of the enum table in the symbol table destructor is properly implemented, ensuring no memory leaks.

examples/struct/very_nested/very_nested.dg (3)

2-2: Struct renaming for clarity

The renaming of structures from single-letter names (A, B, C) to more descriptive names (As, Bs, Cs) improves code readability and helps distinguish between enum types and struct types.

Also applies to: 7-8, 12-12


4-4: Updated struct reference

The field type has been correctly updated to match the renamed struct.


21-21: Updated local variable type

The local variable declaration has been correctly updated to use the renamed struct type.

compiler/main/gen_tac/gen_tac_term.c (3)

2-2: Appropriate includes added for the new enum functionality.

The addition of these header files is necessary for the enum value handling implementation, providing access to assertion capabilities, symbol tables, and the enum table.

Also applies to: 5-6


10-30: Well-implemented enum value handling function.

The new static function properly handles enum value terms with good error checking and debugging output. It:

  1. Retrieves and validates the symbol table
  2. Extracts and validates the enum name
  3. Looks up the enum value and handles errors
  4. Appends the appropriate TAC constant when successful

34-37: Good defensive programming with parameter validation.

Adding assertions for input parameters improves robustness by ensuring invalid inputs are caught early.

ast/visitor/visitor.c (7)

56-56: Good addition of visitor function prototype for enum values.

The function declaration follows the established pattern for visitor functions in this file.


64-66: Well-organized declaration of enum visitor functions.

The function prototypes are properly grouped under a descriptive comment and follow the established naming convention.


86-88: Proper integration of enum declarations in namespace visitor.

The new loop correctly processes enum declarations within a namespace, following the same pattern as other member types.


103-114: Well-implemented enum declaration visitor.

The function properly visits the enum declaration and all its members, maintaining the visitor pattern consistency and error handling approach used throughout the codebase.


116-120: Simple and effective enum member visitor implementation.

The visitor function for enum members follows the established pattern and correctly handles visitation of these nodes.


377-379: Appropriate handling of enum values in term visitor.

The added case statement properly processes enum value terms by calling the new visitor function.


399-402: Clean implementation of enum value visitor.

The visitor function for enum values is simple and follows the established pattern in the codebase.

parser/main/astnodes/EnumDecl.c (4)

1-17: Appropriate includes for the new implementation.

The file includes all necessary headers for the implementation of enum declaration parsing.


18-57: Well-structured function setup and initial token parsing.

The function properly:

  1. Validates input parameters
  2. Creates a working copy of the token list
  3. Initializes the EnumDecl structure
  4. Parses the enum keyword and name tokens
  5. Verifies the opening curly brace

The error handling is consistent with the project's style.


58-74: Effective enum member parsing loop.

The implementation correctly handles the iterative parsing of enum members with appropriate error handling and memory management.


76-87: Proper finalization of the parsing process.

The function correctly:

  1. Verifies the closing curly brace
  2. Updates the original token list
  3. Frees temporary resources
  4. Returns the constructed EnumDecl
ast/util/free_ast.c (4)

65-67: Proper cleanup of enum declarations in namespace.

The added loop ensures all enum declarations in a namespace are properly freed, preventing memory leaks.


108-115: Well-implemented enum declaration cleanup function.

The function correctly frees all resources associated with an enum declaration, including all its members and their names.


140-140: Appropriate handling of enum value terms in free_term.

The added case properly frees the memory associated with enum value terms.


142-142: Improved error message with case number.

The updated error message now includes the specific term kind value for unhandled cases, which will make debugging easier.

compiler/main/util/fill_tables.c (4)

7-7: Good addition of the enum table header

This include is necessary for the enum_table_fill function used later in the code.


14-14: Function signature improved to indicate success/failure

Changing the return type from void to bool properly reflects the function's ability to fail, which is important for error handling.

Also applies to: 41-41


16-18: Good refactoring of debug flag

Storing the debug flag in a local variable is a good practice that improves readability and avoids redundant function calls.


31-33: Proper error handling for enum table filling

The added check for enum_table_fill's return value with early return on failure improves the robustness of the code.

parser/main/astnodes/EnumMember.c (4)

1-12: Comprehensive includes for the new file

The file includes all necessary headers for AST operations, token handling, and memory management.


19-23: Good implementation of EnumMember creation

The initialization of the EnumMember structure follows the project's conventions for memory allocation and initialization.


45-51: Good error handling for failed constant value creation

The code properly checks if value creation failed and frees all allocated resources before returning NULL.


61-64: Proper token list management

The function correctly updates the original token list and frees the copy before returning.

docs/html/grammar.html (3)

38-38: Updated Namespace rule to include EnumDecl

The grammar has been properly updated to include enum declarations as part of namespaces.


42-51: Well-structured grammar for enumerations

The grammar for enum-related constructs is clear and follows the same formatting as other grammar sections. The rules properly define the expected structure of enums in the language.


160-160: Updated Term rule to include EnumValue

The Term production rule now correctly includes EnumValue as a possible term in expressions.

parser/main/astnodes/Namespace.c (5)

8-8: Added necessary include for enum declarations

The include for EnumDecl.h is required for the new enum-related functionality.


37-37: Proper initialization for enum tracking variables

The count_enums and capacity_enums are initialized consistently with other similar counters.

Also applies to: 42-42


52-55: Memory allocation for enums array

The memory allocation for enums follows the same pattern as for methods and structs, including proper error handling.

🧰 Tools
🪛 CircleCI: valgrind

[warning] 52-52: Implicit declaration of function 'sprintf'; did you mean 'vsprintf'?


76-85: Implemented enum parsing logic

The enum parsing logic is well-implemented, following the same pattern as struct and method parsing.


111-112: Added proper cleanup for enums array

The error handling section now includes freeing the enums array, which prevents memory leaks.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
parser/main/astnodes/EnumMember.c (1)

53-58: Missing error message for semicolon.

When checking for a semicolon, if it's not found, the function returns NULL without any error message, unlike other error checks in this function.

next = list_head(copy);
if (next->kind != SEMICOLON) {
+   fprintf(stderr, "expected ';' at the end of enum member\n");
    freeTokenListShallow(copy);
    free(res);
    return NULL;
}
parser/main/astnodes/Namespace.c (1)

209-209: Inconsistent array reallocation strategy.

For structs, the reallocation strategy directly allocates for (count_structs + 1) without using a capacity variable, while for enums (and methods), a capacity variable is used. This inconsistency could lead to confusion and potential bugs.

-res->structs = realloc(res->structs, sizeof(struct StructDecl*) * (res->count_structs + 1));
+if (res->count_structs >= res->capacity_structs) {
+    res->capacity_structs *= 2;
+    res->structs = realloc(res->structs, sizeof(struct StructDecl*) * res->capacity_structs);
+    if (!res->structs) {
+        // Handle error
+        return false;
+    }
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e1f9a1b and f0fce19.

📒 Files selected for processing (40)
  • ast/ast.h (2 hunks)
  • ast/ast/ast_enum.h (1 hunks)
  • ast/ast/ast_expr.h (2 hunks)
  • ast/ast_declare.h (1 hunks)
  • ast/util/free_ast.c (4 hunks)
  • ast/util/free_ast.h (1 hunks)
  • ast/visitor/visitor.c (5 hunks)
  • ast/visitor/visitor.h (1 hunks)
  • compiler/main/compiler.c (1 hunks)
  • compiler/main/gen_tac/gen_tac.c (0 hunks)
  • compiler/main/gen_tac/gen_tac.h (0 hunks)
  • compiler/main/gen_tac/gen_tac_constvalue.c (1 hunks)
  • compiler/main/gen_tac/gen_tac_term.c (1 hunks)
  • compiler/main/typechecker/tc_term.c (1 hunks)
  • compiler/main/typeinference/typeinfer_term.c (1 hunks)
  • compiler/main/util/fill_tables.c (2 hunks)
  • compiler/main/util/fill_tables.h (1 hunks)
  • compiler/test/gen_tac/test_gen_tac_assignstmt.c (1 hunks)
  • compiler/test/gen_tac/test_gen_tac_structdecl.c (2 hunks)
  • compiler/test/gen_tac/test_gen_tac_variable.c (1 hunks)
  • compiler/test/typeinference/test-src/infer_type_call_with_struct_member_access.dg (1 hunks)
  • docs/html/grammar.html (2 hunks)
  • examples/enum/simple_enum/simple_enum.dg (1 hunks)
  • examples/enum/simple_enum/simple_enum.exitcode (1 hunks)
  • examples/struct/nested/nested.dg (1 hunks)
  • examples/struct/very_nested/very_nested.dg (2 hunks)
  • lexer/src/lexer.c (2 hunks)
  • parser/main/CMakeLists.txt (1 hunks)
  • parser/main/astnodes/EnumDecl.c (1 hunks)
  • parser/main/astnodes/EnumDecl.h (1 hunks)
  • parser/main/astnodes/EnumMember.c (1 hunks)
  • parser/main/astnodes/EnumMember.h (1 hunks)
  • parser/main/astnodes/Namespace.c (6 hunks)
  • parser/main/astnodes/expr/Term.c (1 hunks)
  • tables/CMakeLists.txt (1 hunks)
  • tables/enum/enum_table.c (1 hunks)
  • tables/enum/enum_table.h (1 hunks)
  • tables/symtable/symtable.c (3 hunks)
  • tables/symtable/symtable.h (2 hunks)
  • token/TokenKeys.h (2 hunks)
💤 Files with no reviewable changes (2)
  • compiler/main/gen_tac/gen_tac.h
  • compiler/main/gen_tac/gen_tac.c
🚧 Files skipped from review as they are similar to previous changes (33)
  • examples/enum/simple_enum/simple_enum.exitcode
  • parser/main/astnodes/EnumDecl.h
  • examples/enum/simple_enum/simple_enum.dg
  • parser/main/astnodes/EnumMember.h
  • ast/util/free_ast.h
  • ast/ast_declare.h
  • tables/CMakeLists.txt
  • compiler/main/typechecker/tc_term.c
  • compiler/main/compiler.c
  • ast/ast/ast_expr.h
  • compiler/main/typeinference/typeinfer_term.c
  • tables/symtable/symtable.h
  • parser/main/CMakeLists.txt
  • compiler/main/gen_tac/gen_tac_constvalue.c
  • lexer/src/lexer.c
  • compiler/test/gen_tac/test_gen_tac_variable.c
  • compiler/test/typeinference/test-src/infer_type_call_with_struct_member_access.dg
  • compiler/test/gen_tac/test_gen_tac_assignstmt.c
  • ast/ast.h
  • token/TokenKeys.h
  • examples/struct/nested/nested.dg
  • compiler/test/gen_tac/test_gen_tac_structdecl.c
  • tables/symtable/symtable.c
  • compiler/main/gen_tac/gen_tac_term.c
  • ast/ast/ast_enum.h
  • examples/struct/very_nested/very_nested.dg
  • ast/util/free_ast.c
  • compiler/main/util/fill_tables.h
  • tables/enum/enum_table.h
  • tables/enum/enum_table.c
  • parser/main/astnodes/expr/Term.c
  • ast/visitor/visitor.h
  • docs/html/grammar.html
🧰 Additional context used
🧬 Code Graph Analysis (2)
parser/main/astnodes/EnumMember.c (1)
parser/main/astnodes/EnumMember.h (1)
  • makeEnumMember (6-6)
parser/main/astnodes/EnumDecl.c (3)
parser/main/astnodes/EnumDecl.h (1)
  • makeEnumDecl (6-6)
parser/main/astnodes/EnumMember.h (1)
  • makeEnumMember (6-6)
parser/main/astnodes/EnumMember.c (1)
  • makeEnumMember (19-65)
🔇 Additional comments (20)
compiler/main/util/fill_tables.c (5)

7-7: New include for enum table support.

The addition of the enum table header is necessary for integrating the new enum functionality into the compiler's symbol tables.


14-14: Method signature updated to return bool.

Good change - modifying the function to return a boolean value allows for error propagation when filling tables fails. This enhances error handling in the compiler.


16-18: Refactored debug flag retrieval.

Storing the debug flag in a local variable improves code readability and avoids multiple calls to flags_debug(). This is a good refactoring.


31-33: Added enum table filling with error handling.

The code now calls enum_table_fill() and properly handles its return value, returning false if enum table filling fails. This is consistent with the PR's objective of adding enum support.


41-41: Added success return value.

Adding an explicit return statement to indicate successful execution completes the boolean return type implementation.

ast/visitor/visitor.c (7)

56-56: Function declaration for handling enum values.

This declaration for visit_enum_value follows the visitor pattern established in the codebase, though it differs slightly by taking a char* parameter rather than a struct pointer like most other visitor functions.


64-66: Well-structured function declarations for handling enum AST nodes.

The declarations for visit_enum_decl and visit_enum_member follow the established pattern in the codebase, returning a boolean to indicate success or failure during traversal.


86-88: Proper integration of enum traversal in namespace visitor.

The new code correctly iterates over the enums in a namespace, following the same pattern used for structs and methods in the surrounding code.


103-114: Well-implemented enum declaration visitor.

The implementation of visit_enum_decl properly visits each enum member and follows the established pattern by:

  1. Calling the visitor on the enum declaration node
  2. Iterating through all enum members
  3. Handling errors appropriately
  4. Returning a boolean to indicate success/failure

116-120: Simple but correct enum member visitor implementation.

The implementation of visit_enum_member is straightforward since it doesn't need to traverse any child nodes beyond calling the visitor function for the enum member itself.


377-379: Added support for enum values in term visitor.

The new case for TERM_KIND_ENUM_VALUE in the switch statement properly calls the appropriate visitor function and follows the pattern established for other term kinds.


399-402: Correct implementation of enum value visitor.

The implementation of visit_enum_value is simple and correctly calls the visitor function with the appropriate node type.

parser/main/astnodes/EnumDecl.c (2)

29-30: Initial memory allocation for enum members.

The code properly allocates memory for the enum members array with an initial capacity of 1.


41-47: Enum name validation and storage.

The code correctly validates that enum names follow the uppercase convention and duplicates the name to store it in the EnumDecl struct.

parser/main/astnodes/EnumMember.c (2)

33-34: Using asprintf for name duplication.

Using asprintf is fine here since the project's build environment supports it (as confirmed in previous comments).


45-51: Proper error handling for makeConstValue failure.

The function correctly checks if makeConstValue returns NULL and handles the error by freeing all allocated resources.

parser/main/astnodes/Namespace.c (4)

37-37: Proper initialization of enum counts and capacities.

The code correctly initializes the count_enums to 0 and capacity_enums to the same INITIAL_CAPACITY constant used for other collections.

Also applies to: 42-42


52-55: Proper memory allocation and error handling for enums array.

The code correctly allocates memory for the enums array based on the capacity and includes appropriate error handling, similar to the handling for methods and structs.


78-85: Enum parsing implementation.

The code correctly iterates through tokens to find and parse enum declarations, storing them in the namespace and handling errors appropriately.


111-112: Proper resource cleanup for enums in error case.

The error handling code correctly frees the enums array in the error cleanup path.

Simple way to create named values.

Enum member names and enum names have to be all uppercase.

This separates them from other type names like structs.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🔭 Outside diff range comments (1)
parser/main/astnodes/Namespace.c (1)

100-113: ⚠️ Potential issue

Incomplete cleanup in error handling.

The error handling section only frees the enums array pointer (line 112) but doesn't free individual enum objects. If makeEnumDecl succeeds for some enums before failing, those successfully created enums would leak memory.

Apply this diff to properly clean up enum objects:

error_res_parse_structs:
    for (int i = 0; i < res->count_includes; i++) {
        free(res->includes[i]);
    }
    free(res->includes);
error_res_token_path:
    free(res->token_path);
error_res_src_path:
    free(res->src_path);
error_res_name:
    free(res->name);
error_res_enums:
+    for (int i = 0; i < res->count_enums; i++) {
+        free_enum_decl(res->enums[i]);
+    }
    free(res->enums);
🧹 Nitpick comments (8)
tables/enum/enum_table.c (5)

41-60: Check for potential overflow when doubling capacity

While the resizing logic is correct for moderate-sized tables, an extreme number of entries may lead to capacity overflow. Consider checking for (data->capacity > SIZE_MAX / 2) before doubling.

 if ((data->count_entries + 1) >= data->capacity) {
+    if (data->capacity > SIZE_MAX / 2) {
+        fprintf(stderr, "Error: Enum table capacity overflow\n");
+        return false;
+    }
     data->capacity *= 2;
     ...
 }

62-103: Validate uppercase enforcement and handle partial insertion errors

  • The uppercase validation (lines 75-80) correctly rejects any lowercase character. If you plan to allow digits or underscores, consider clarifying or extending the check.
  • The insertion logic cleanly checks for duplicates and handles memory failures. Logging additional info before returning false could aid debugging in large projects.

105-121: Potential performance bottleneck for large enums

enum_table_lookup iterates linearly over all entries. While acceptable for small enums, consider a hash-based lookup if enums grow significantly.


123-133: Use of the same pointer for hex and binary values

Both cases (5 and 6) map to cv->ptr.m5_hex_const, which is intentional per your design. Including a brief comment clarifying this shared field could prevent confusion for future maintainers.


179-190: Optional enhancement for printing format

enum_table_print provides clear output. If you need more advanced formatting or sorting, consider expansions here.

parser/main/astnodes/EnumDecl.c (1)

104-107: Improve memory cleanup with dedicated free function.

The error handling section directly frees member resources instead of using a dedicated free function for EnumMember (like free_enum_member). This approach might miss freeing other internal resources that EnumMember could contain.

Consider replacing the direct free calls with a proper free_enum_member function:

exit_error:
    for (size_t i = 0; i < res->count_members; i++) {
-        free(res->members[i]->name);
-        free(res->members[i]);
+        free_enum_member(res->members[i]);
    }
    free(res);
    freeTokenListShallow(copy);
    return NULL;
parser/main/astnodes/Namespace.c (2)

76-86: Extract enum parsing into a separate function.

For consistency with structs and methods (which have ns_parse_structs and ns_parse_methods), consider extracting the enum parsing logic into its own function.

Consider creating a function like ns_parse_enums and refactor the code as follows:

+ // @returns false on error
+ static bool ns_parse_enums(struct Namespace* res, struct TokenList* copy) {
+     if (list_size(copy) == 0) { return true; }
+ 
+     struct Token* next = list_head(copy);
+ 
+     while (next->kind == KEYWORD_ENUM) {
+         res->enums[res->count_enums] = makeEnumDecl(copy);
+         if (!res->enums[res->count_enums]) {
+             return false;
+         }
+         res->count_enums++;
+         
+         if (res->count_enums >= res->capacity_enums) {
+             res->capacity_enums *= 2;
+             struct EnumDecl** new_enums = realloc(res->enums, 
+                                sizeof(struct EnumDecl*) * res->capacity_enums);
+             if (!new_enums) {
+                 return false;
+             }
+             res->enums = new_enums;
+         }
+         
+         next = list_head(copy);
+     }
+     
+     return true;
+ }

Then update the makeNamespace function:

- struct Token* next = list_head(copy);
- 
- while (next->kind == KEYWORD_ENUM) {
-     res->enums[res->count_enums] = makeEnumDecl(copy);
-     if (!res->enums[res->count_enums]) {
-         goto error_res_parse_structs;
-     }
-     res->count_enums++;
-     next = list_head(copy);
- }
+ if (!ns_parse_enums(res, copy)) {
+     goto error_res_parse_structs;
+ }

109-109: Unused error label in error handling flow.

The error label error_res_name: is included in the error handling flow but is never referenced anywhere in the code (no goto statements jump to this label).

Consider removing the unused label or ensuring the error flow properly references it.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0fce19 and 8660359.

📒 Files selected for processing (42)
  • ast/ast.h (2 hunks)
  • ast/ast/ast_enum.h (1 hunks)
  • ast/ast/ast_expr.h (2 hunks)
  • ast/ast_declare.h (1 hunks)
  • ast/util/free_ast.c (4 hunks)
  • ast/util/free_ast.h (1 hunks)
  • ast/visitor/visitor.c (5 hunks)
  • ast/visitor/visitor.h (1 hunks)
  • compiler/main/compiler.c (1 hunks)
  • compiler/main/gen_tac/gen_tac.c (0 hunks)
  • compiler/main/gen_tac/gen_tac.h (0 hunks)
  • compiler/main/gen_tac/gen_tac_constvalue.c (1 hunks)
  • compiler/main/gen_tac/gen_tac_term.c (1 hunks)
  • compiler/main/typechecker/tc_term.c (1 hunks)
  • compiler/main/typeinference/typeinfer_term.c (1 hunks)
  • compiler/main/util/fill_tables.c (2 hunks)
  • compiler/main/util/fill_tables.h (1 hunks)
  • compiler/test/gen_tac/test_gen_tac_assignstmt.c (1 hunks)
  • compiler/test/gen_tac/test_gen_tac_structdecl.c (2 hunks)
  • compiler/test/gen_tac/test_gen_tac_variable.c (1 hunks)
  • compiler/test/typeinference/test-src/infer_type_call_with_struct_member_access.dg (1 hunks)
  • docs/html/grammar.html (2 hunks)
  • examples/enum/enum_hex_value/enum_hex_value.dg (1 hunks)
  • examples/enum/enum_hex_value/enum_hex_value.exitcode (1 hunks)
  • examples/enum/simple_enum/simple_enum.dg (1 hunks)
  • examples/enum/simple_enum/simple_enum.exitcode (1 hunks)
  • examples/struct/nested/nested.dg (1 hunks)
  • examples/struct/very_nested/very_nested.dg (2 hunks)
  • lexer/src/lexer.c (2 hunks)
  • parser/main/CMakeLists.txt (1 hunks)
  • parser/main/astnodes/EnumDecl.c (1 hunks)
  • parser/main/astnodes/EnumDecl.h (1 hunks)
  • parser/main/astnodes/EnumMember.c (1 hunks)
  • parser/main/astnodes/EnumMember.h (1 hunks)
  • parser/main/astnodes/Namespace.c (6 hunks)
  • parser/main/astnodes/expr/Term.c (1 hunks)
  • tables/CMakeLists.txt (1 hunks)
  • tables/enum/enum_table.c (1 hunks)
  • tables/enum/enum_table.h (1 hunks)
  • tables/symtable/symtable.c (3 hunks)
  • tables/symtable/symtable.h (2 hunks)
  • token/TokenKeys.h (2 hunks)
💤 Files with no reviewable changes (2)
  • compiler/main/gen_tac/gen_tac.h
  • compiler/main/gen_tac/gen_tac.c
✅ Files skipped from review due to trivial changes (1)
  • examples/enum/enum_hex_value/enum_hex_value.exitcode
🚧 Files skipped from review as they are similar to previous changes (34)
  • ast/util/free_ast.h
  • examples/enum/simple_enum/simple_enum.exitcode
  • compiler/main/gen_tac/gen_tac_constvalue.c
  • compiler/main/typechecker/tc_term.c
  • parser/main/CMakeLists.txt
  • parser/main/astnodes/expr/Term.c
  • parser/main/astnodes/EnumDecl.h
  • compiler/test/typeinference/test-src/infer_type_call_with_struct_member_access.dg
  • compiler/main/typeinference/typeinfer_term.c
  • ast/visitor/visitor.h
  • compiler/main/util/fill_tables.h
  • compiler/test/gen_tac/test_gen_tac_structdecl.c
  • ast/ast.h
  • compiler/main/compiler.c
  • ast/ast_declare.h
  • compiler/main/util/fill_tables.c
  • parser/main/astnodes/EnumMember.h
  • ast/ast/ast_enum.h
  • compiler/test/gen_tac/test_gen_tac_assignstmt.c
  • tables/symtable/symtable.h
  • examples/struct/nested/nested.dg
  • compiler/main/gen_tac/gen_tac_term.c
  • token/TokenKeys.h
  • examples/struct/very_nested/very_nested.dg
  • ast/util/free_ast.c
  • tables/symtable/symtable.c
  • tables/CMakeLists.txt
  • examples/enum/simple_enum/simple_enum.dg
  • docs/html/grammar.html
  • parser/main/astnodes/EnumMember.c
  • compiler/test/gen_tac/test_gen_tac_variable.c
  • lexer/src/lexer.c
  • ast/ast/ast_expr.h
  • tables/enum/enum_table.h
🧰 Additional context used
🧬 Code Graph Analysis (1)
tables/enum/enum_table.c (1)
tables/enum/enum_table.h (7)
  • enum_table_ctor (19-19)
  • enum_table_dtor (20-20)
  • enum_table_insert (25-25)
  • enum_table_lookup (29-29)
  • int_value_from_const (35-35)
  • enum_table_fill (31-31)
  • enum_table_print (33-33)
🔇 Additional comments (13)
tables/enum/enum_table.c (4)

1-7: Use of <ctype.h> is consistent with uppercase checks

The inclusion of <ctype.h> is appropriate for ensuring uppercase name validation in enum_table_insert.


29-39: Destructor logic looks solid

The destructor properly frees each entry and handles the array and table deallocation. This is straightforward and correct.


135-151: Enum table fill for a single declaration is concise

enum_table_fill_single cleanly loops over members and inserts each value. This is straightforward, and error conditions are handled properly.


153-177: Filling the table in debug mode is well-structured

enum_table_fill navigates the enums array and optionally prints debug info. This is well-structured, and the debug toggle is clear.

examples/enum/enum_hex_value/enum_hex_value.dg (2)

2-6: Enum definition adheres to uppercase naming convention

Using uppercase for both the enum name (VALUES) and the members (VALUE_1, VALUE_6, VALUE_9) meets the PR’s requirement. Good work!


8-11: Return statement from main is clear

Returning VALUE_9 demonstrates the correct usage of enum constants, verifying the integration of hex-based enum values.

ast/visitor/visitor.c (7)

56-56: New function declaration for visiting enum values

Declaring visit_enum_value is a clean approach to handle enum values distinctly.


64-67: Forward declarations for visit_enum_decl and visit_enum_member

These declarations keep the file organized by allowing usage before the functions are defined.


86-88: Visiting each enum in the namespace

This loop ensures that all enumerations are processed. It aligns well with the established visitor pattern.


103-114: visit_enum_decl effectively pipes declarations through the visitor

Iterating over members ensures each enumeration constant is handled, and propagating success/failure addresses potential issues.


116-120: visit_enum_member properly invokes the visitor

This function is minimal and consistent. It could be extended if additional logic is needed while visiting enum members.


377-379: New case for TERM_KIND_ENUM_VALUE in visit_term

Adding visit_enum_value here extends the visitor pattern to recognize enum values. This is aligned with your architecture.


399-402: visit_enum_value visits the enum name directly

The straightforward approach passes the enum value string to the visitor. This is a neat, consistent way to handle literals.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
parser/main/astnodes/EnumDecl.c (1)

53-57: Memory leak on early return when enum name is invalid.

This repeats a previously identified issue. If TOKEN_ENUM_VALUE is missing, the function returns without cleaning up resources created before this check.

To fix, direct all failures to the exit_error label:

if (list_head(copy)->kind != TOKEN_ENUM_VALUE) {
    fprintf(stderr, "parsing error, expected enum value (all uppercase) , but got: %s\n", list_code(copy));
-    return NULL;
+    goto exit_error;
}
🧹 Nitpick comments (4)
tables/enum/enum_table.c (4)

18-37: Constructor Handles Allocation Properly
The constructor correctly checks for calloc failures and returns NULL on error. You could optionally print an error message before returning, to improve observability in case of failures.

 if (!res) {
+    fprintf(stderr, "Error: Unable to allocate EnumTable\n");
     return NULL;
 }

51-70: Check for Potential Capacity Overflow
While the resizing logic is valid, consider adding a check for potential overflow when doubling data->capacity. This prevents scenarios where extremely large values might wrap around. Also, printing an error message before returning false could improve debugging.

 size_t new_capacity = data->capacity * 2;
+if (new_capacity < data->capacity) {
+    // Overflow occurred
+    fprintf(stderr, "Error: Enum table capacity overflow\n");
+    return false;
+}
 
 struct EnumTableEntry** new_entries = realloc(data->entries, new_capacity * sizeof(struct EnumTableEntry*));
 if (!new_entries) {
+    fprintf(stderr, "Error: Failed to resize enum table\n");
     return false;
 }
 
 data->capacity = new_capacity;
 data->entries = new_entries;

83-95: Strict Enforcement of Uppercase
Returning false on encountering any lowercase character enforces the uppercase-only rule. If you want a more user-friendly approach, you could automatically convert the name to uppercase or issue a specific error message.

for (size_t i = 0; i < len; i++) {
-    if (islower(name[i])) {
-        return false;
-    }
+    if (islower(name[i])) {
+        // Convert or fail with explicit error
+        name[i] = toupper(name[i]);
+        // or
+        fprintf(stderr, "Error: %s is not uppercase\n", name);
+        return false;
    }
}

133-143: Consolidate or Document Cases for Hex & Binary
Cases 5 and 6 return the same field (m5_hex_const). Although intentional, consider adding a comment clarifying they share the same union field to avoid confusion.

 case 5: return (int)cv->ptr.m5_hex_const;
 case 6:
+    // Intentional: both hex and binary use the same field
     return (int)cv->ptr.m5_hex_const;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8660359 and 3ddd334.

📒 Files selected for processing (3)
  • parser/main/astnodes/EnumDecl.c (1 hunks)
  • parser/main/astnodes/Namespace.c (7 hunks)
  • tables/enum/enum_table.c (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
parser/main/astnodes/Namespace.c (4)
token/list/TokenList.h (1)
  • list_head (30-30)
token/list/TokenList.c (1)
  • list_head (183-185)
parser/main/astnodes/EnumDecl.c (1)
  • makeEnumDecl (18-113)
parser/main/astnodes/EnumDecl.h (1)
  • makeEnumDecl (6-6)
parser/main/astnodes/EnumDecl.c (3)
parser/main/astnodes/EnumDecl.h (1)
  • makeEnumDecl (6-6)
parser/main/astnodes/EnumMember.c (1)
  • makeEnumMember (19-65)
parser/main/astnodes/EnumMember.h (1)
  • makeEnumMember (6-6)
tables/enum/enum_table.c (1)
tables/enum/enum_table.h (7)
  • enum_table_ctor (19-19)
  • enum_table_dtor (20-20)
  • enum_table_insert (25-25)
  • enum_table_lookup (29-29)
  • int_value_from_const (35-35)
  • enum_table_fill (31-31)
  • enum_table_print (33-33)
🔇 Additional comments (9)
tables/enum/enum_table.c (8)

1-8: Header Inclusions Look Good
No issues with these includes; they align well with the subsequent usage of ctype, stdlib, etc.


39-49: Destructor Frees Resources Appropriately
This destructor thoroughly frees each entry, its name, and the array itself. No issues found.


72-81: Duplicate Entry Check
Detecting duplicates before insertion and emitting a clear error message is a good approach. This helps maintain data integrity in the enum table.


96-113: Memory Allocation for Entries Is Handled Correctly
Allocating, checking for NULL, and then performing strdup ensures safety. Releasing resources upon failures (e.g., free(entry) when strdup fails) is also a good practice.


115-131: Lookup Function Is Straightforward
This function properly returns the associated value if found, or -1 if missing. No concerns with correctness or readability here.


145-161: Filling Single Enum Declaration
Nicely iterates enum members, converts values, and inserts them. If insertion fails, you cleanly return false. This is robust error propagation.


163-187: Filling Enum Table From Namespace
The debug logs and the iteration across all enums are well-structured. Properly returns false on any insertion failure, halting further processing.


189-201: Print Function Is Clear
This function is straightforward and does exactly what it should: printing enum names and values in a neat format.

parser/main/astnodes/Namespace.c (1)

124-150: Enums parsing logic looks good.

The ns_parse_enums function correctly resizes the enums array, handles error returns, and delegates declaration creation to makeEnumDecl. The approach is consistent with the existing pattern for methods and structs.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
tables/enum/enum_table.c (4)

39-49: Consider checking for null pointers in destructor.
Although the current usage ensures a valid data, adding defensive checks (like if (!data) return;) would guard against potential misuse. This is a minor improvement for extra safety.

 void enum_table_dtor(struct EnumTable* data) {
+    if (!data) {
+        return;
+    }
     for (size_t i = 0; i < data->count_entries; i++) {
         ...

51-70: Resize function is correct; consider overflow checks.
Doubling the capacity works fine, and the function returns false if reallocation fails. For completeness, you could add a check to ensure data->capacity * 2 does not overflow a size_t. This is generally a minor corner case, so it’s optional.


72-113: Insert function is logically sound; consider logging for lowercase rejection.

  1. Checking for duplicate names and uppercase naming is done correctly.
  2. You might want to log an error when a name contains lowercase letters to provide clearer feedback to the caller.
+fprintf(stderr, "Error: enum name %s is not all uppercase\n", name);
 return false;

115-131: Lookup implementation is straightforward.
Linear search is fine for smaller tables. If performance becomes an issue for large numbers of enum entries, consider a more efficient data structure.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3ddd334 and 8426edf.

📒 Files selected for processing (3)
  • parser/main/astnodes/EnumDecl.c (1 hunks)
  • parser/main/astnodes/Namespace.c (7 hunks)
  • tables/enum/enum_table.c (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
parser/main/astnodes/EnumDecl.c (3)
parser/main/astnodes/EnumDecl.h (1)
  • makeEnumDecl (6-6)
parser/main/astnodes/EnumMember.h (1)
  • makeEnumMember (6-6)
parser/main/astnodes/EnumMember.c (1)
  • makeEnumMember (19-65)
parser/main/astnodes/Namespace.c (4)
token/list/TokenList.h (1)
  • list_head (30-30)
token/list/TokenList.c (1)
  • list_head (183-185)
parser/main/astnodes/EnumDecl.c (1)
  • makeEnumDecl (18-112)
parser/main/astnodes/EnumDecl.h (1)
  • makeEnumDecl (6-6)
tables/enum/enum_table.c (1)
tables/enum/enum_table.h (7)
  • enum_table_ctor (19-19)
  • enum_table_dtor (20-20)
  • enum_table_insert (25-25)
  • enum_table_lookup (29-29)
  • int_value_from_const (35-35)
  • enum_table_fill (31-31)
  • enum_table_print (33-33)
🔇 Additional comments (7)
tables/enum/enum_table.c (7)

1-9: Headers look good.
The choice of including <assert.h>, <ctype.h>, and other necessary headers is appropriate and minimal.


11-16: Struct definition is clear and concise.
The EnumTable struct is straightforward, holding an array of pointers, a count, and a capacity. This is a clear layout for managing dynamically growing entries.


18-37: Robust constructor with allocation checks.
The constructor correctly checks for calloc failures and handles them gracefully by returning NULL. This ensures that the caller can detect and handle memory allocation issues properly.


133-143: Hex and binary share the same field—verified.
Using the same union field (m5_hex_const) for both hex and binary is intentional in this codebase. The function handles all recognized kind values gracefully.


145-161: Single enum fill routine is clear.
This function properly retrieves each member’s value and inserts it into the table. The short-circuit return false on insert failure is a good practice for error handling.


163-187: Enum table filling logic aligns with PR objectives.
Iterating through each enum declaration and inserting members enforces the uppercase rule (through enum_table_insert). The debug logs make troubleshooting easier.


189-200: Printing logic is clear and user-friendly.
Displaying each entry name and associated value in a formatted manner is straightforward and effective for debugging.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
parser/main/astnodes/Namespace.c (2)

101-104: ⚠️ Potential issue

Free the enum name before freeing the enum structure.

Lines 102-103 free res->enums[i] first, then access res->enums[i]->name. This is a use-after-free bug. Swap the order to avoid undefined behavior.

for (int i = 0; i < res->count_enums; i++) {
-    free(res->enums[i]->name);
-    free(res->enums[i]);
+    free(res->enums[i]->name);
+    free(res->enums[i]);
}

100-112: ⚠️ Potential issue

Prevent potential double-free of res->enums.

After freeing res->enums in the error_res_parse_enums: block, execution falls through to error_res_enums:, which frees res->enums again. This results in a double-free. To fix this, either remove the free call at lines 101–105 and rely solely on the error_res_enums: label for cleanup, or jump over the error_res_enums: label after manually freeing res->enums here. For example, you can unify the cleanup logic under error_res_enums::

error_res_parse_enums:
 for (int i = 0; i < res->count_enums; i++) {
     free(res->enums[i]->name);
     free(res->enums[i]);
 }
-free(res->enums);
-goto error_res_token_path;
+goto error_res_enums;

 error_res_token_path:
     free(res->token_path);
 ...
error_res_enums:
+ for (int i = 0; i < res->count_enums; i++) {
+     free(res->enums[i]->name);
+     free(res->enums[i]);
+ }
 free(res->enums);
 ...
🧹 Nitpick comments (5)
tables/enum/enum_table.c (5)

18-37: Consider optional logging for allocation failures
The constructor correctly checks for memory allocation failure and returns NULL. Optionally, a brief log statement before returning could help diagnose errors in production.


51-70: Avoid potential capacity overflow
If this table grows very large, doubling the capacity might cause an overflow. Consider adding a check before multiplying by 2.


72-113: Provide consistent error messages when insert fails
Currently, insertion fails silently on uppercase validation or malloc issues. Displaying an error message could improve debugging.


115-131: Consider more efficient lookups
Linear search is acceptable for small enum tables. For large projects with many enum members, consider a hash map or sorted data structure.


133-143: Use an enum for the cv->kind values
The switch statement for cv->kind uses numeric constants. An enumerated type would clarify usage and reduce confusion.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8426edf and e7cfa1e.

📒 Files selected for processing (3)
  • parser/main/astnodes/EnumDecl.c (1 hunks)
  • parser/main/astnodes/Namespace.c (7 hunks)
  • tables/enum/enum_table.c (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
parser/main/astnodes/EnumDecl.c (3)
parser/main/astnodes/EnumDecl.h (1)
  • makeEnumDecl (6-6)
parser/main/astnodes/EnumMember.c (1)
  • makeEnumMember (19-65)
parser/main/astnodes/EnumMember.h (1)
  • makeEnumMember (6-6)
tables/enum/enum_table.c (1)
tables/enum/enum_table.h (7)
  • enum_table_ctor (19-19)
  • enum_table_dtor (20-20)
  • enum_table_insert (25-25)
  • enum_table_lookup (29-29)
  • int_value_from_const (35-35)
  • enum_table_fill (31-31)
  • enum_table_print (33-33)
parser/main/astnodes/Namespace.c (4)
token/list/TokenList.h (1)
  • list_head (30-30)
token/list/TokenList.c (1)
  • list_head (183-185)
parser/main/astnodes/EnumDecl.c (1)
  • makeEnumDecl (18-113)
parser/main/astnodes/EnumDecl.h (1)
  • makeEnumDecl (6-6)
🔇 Additional comments (10)
tables/enum/enum_table.c (6)

1-8: Includes and header references look good
No issues found in the use of standard libraries and header files here.


11-16: Struct definition is concise
Using separate fields for count_entries and capacity is clear and maintainable.


39-49: Destructor implementation is correct
Memory for each entry is freed, followed by the array and the table itself.


145-161: Enum table filling is straightforward
The single-fill function cleanly loops over members, converts values, and inserts them into the enum table.


163-187: Filling multiple enums is well-handled
Debug logs and error propagation are implemented correctly, returning false on any insertion failure.


189-200: Printing function is clear
Enumerations are displayed in a readable format. Looks good.

parser/main/astnodes/EnumDecl.c (2)

1-17: Well-organized imports and header structure.

The file has a clean organization with proper separation between standard library headers, internal project headers, and token-related headers.


18-113: Well-implemented function with proper error handling and memory management.

The implementation of makeEnumDecl follows good practices:

  • Proper input validation before allocating resources
  • Well-structured error handling with goto labels for cleanup
  • Comprehensive token validation and parsing logic
  • Appropriate memory management with allocation checks
  • Clean dynamic resizing of the members array

The function correctly parses the enum declaration format while maintaining proper resource management throughout.

parser/main/astnodes/Namespace.c (2)

8-8: Good implementation of enum support infrastructure.

The changes properly integrate enum support into the Namespace structure with:

  • Appropriate header inclusion
  • Initialization of enum count and capacity variables
  • Memory allocation for the enum array with proper error handling

The implementation follows the established patterns in the codebase.

Also applies to: 21-21, 39-39, 44-44, 54-57


78-80: Well-implemented enum parsing function.

The ns_parse_enums function:

  • Correctly iterates through tokens to find enum declarations
  • Properly handles array resizing when needed
  • Includes appropriate error checking for memory allocation
  • Returns appropriate status values to trigger cleanup on failure

The function follows the same pattern as the existing functions for methods and structs, maintaining consistency in the codebase.

Also applies to: 123-149

Fixes for issues found in code review.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
parser/main/astnodes/Namespace.c (1)

129-138: Better memory reallocation pattern than existing code.

This reallocation pattern is more robust than the one used in ns_parse_structs (line 237) as it:

  1. Checks if capacity will be exceeded before reallocating
  2. Doubles the capacity rather than just adding one element
  3. Stores the realloc result in a temporary variable
  4. Checks if reallocation failed before assigning it back

Consider applying this improved pattern to the structs and methods parsing functions as well.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7cfa1e and ab4826f.

📒 Files selected for processing (3)
  • parser/main/astnodes/EnumDecl.c (1 hunks)
  • parser/main/astnodes/Namespace.c (7 hunks)
  • tables/enum/enum_table.c (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tables/enum/enum_table.c
🧰 Additional context used
🧬 Code Graph Analysis (2)
parser/main/astnodes/EnumDecl.c (3)
parser/main/astnodes/EnumDecl.h (1)
  • makeEnumDecl (6-6)
parser/main/astnodes/EnumMember.c (1)
  • makeEnumMember (19-65)
parser/main/astnodes/EnumMember.h (1)
  • makeEnumMember (6-6)
parser/main/astnodes/Namespace.c (4)
token/list/TokenList.h (1)
  • list_head (30-30)
token/list/TokenList.c (1)
  • list_head (183-185)
parser/main/astnodes/EnumDecl.c (1)
  • makeEnumDecl (18-114)
parser/main/astnodes/EnumDecl.h (1)
  • makeEnumDecl (6-6)
🔇 Additional comments (14)
parser/main/astnodes/EnumDecl.c (6)

24-27: Good use of early error handling and goto pattern.

The code correctly handles the case where memory allocation for the EnumDecl structure fails by using the goto pattern, which is an appropriate C idiom for resource cleanup in error paths.


41-45: Good memory allocation check and error handling.

The code properly checks if memory allocation for the members array fails and jumps to the appropriate cleanup label. This ensures no memory leaks occur in error conditions.


49-57: Consistent error handling for token validation.

The code properly validates that the current token is an enum value (all uppercase as per requirements) and handles the error case correctly by jumping to the appropriate cleanup label.


73-81: Good reallocation pattern with proper error handling.

The code uses a safe pattern for array reallocation:

  1. Storing the realloc result in a temporary variable
  2. Checking for allocation failure before assigning it back
  3. Using the appropriate error handling path if allocation fails

This prevents memory leaks or pointer corruption if reallocation fails.


83-88: Robust loop termination condition for enum members.

The break condition properly checks if the next token is not an enum value, allowing for graceful exit from the loop without requiring explicit counting or other complex conditions.


102-114: Well-structured cleanup hierarchy with proper resource management.

The cleanup code is well-organized with a hierarchical label structure that ensures resources are freed in the correct order. The code properly frees:

  1. Each enum member and its name
  2. The members array pointer
  3. The token list copy
  4. The main EnumDecl structure

This thorough cleanup approach prevents memory leaks in error scenarios.

parser/main/astnodes/Namespace.c (8)

8-8: Appropriate header inclusion for EnumDecl.

The code correctly includes the "EnumDecl.h" header file needed for enum declaration support.


20-21: Consistent function declaration style.

The new function declaration for ns_parse_enums follows the same style and documentation pattern as the existing ns_parse_methods and ns_parse_structs functions, maintaining code consistency.


39-44: Consistent initialization of enum-related fields.

The count and capacity fields for enums are initialized following the same pattern as methods and structs, maintaining consistency in the code structure.


54-57: Proper memory allocation with error handling for enums array.

The code allocates memory for the enums array and correctly handles allocation failure by jumping to an appropriate error label, consistent with the existing pattern for methods and structs.


78-80: Logical ordering of parsing functions.

The enum parsing is called before struct and method parsing, which makes sense from a language structure perspective. The error handling is consistent with the existing pattern.


100-105: Properly ordered memory cleanup for enums.

The cleanup code first frees the name and then the enum structure itself for each enum, ensuring proper resource cleanup in case of errors. This follows good C programming practices.


111-112: Consistent cleanup label for enums array.

The error_res_enums label frees the enums array, following the same pattern as the existing error labels for methods and structs.


123-149: Well-implemented enum parsing function with array resizing.

The ns_parse_enums function follows a similar pattern to the existing parsing functions but improves on them by implementing dynamic array resizing when the capacity is reached. Key strengths:

  1. Proper capacity checking and doubling strategy
  2. Safe reallocation with temporary variable
  3. Allocation failure handling
  4. Consistent return value semantics

This is actually an improvement over the struct parsing function (line 237) which doesn't check the reallocation result.

@pointbazaar pointbazaar merged commit 2f424f3 into master Apr 13, 2025
16 checks passed
@pointbazaar pointbazaar deleted the implement-enum branch April 13, 2025 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant