Project 1 — Struct Types#1
Open
chances190 wants to merge 6 commits into
Open
Conversation
- Rename "tagged types" -> "aggregate types", kind -> specifier, tag -> identifier, for semantic clarity - Move types hashmap to evironment for reuse in type-checker and interpreter
There was a problem hiding this comment.
Pull request overview
This PR extends the MiniC AST, parser, type-checker, and interpreter to support aggregate types (struct/union/enum), including top-level aggregate declarations and base.member member access/assignment, and adds tests + documentation to cover the new language features.
Changes:
- Added AST + parser support for aggregate type declarations and member access (
Expr::Member) and unified type parsing viatypes::type_definition. - Extended type checking and runtime evaluation/execution to represent and handle struct/union/enum values, including member access and member assignment.
- Added integration tests (parser/type-checker/interpreter/CLI) and a new introductory guide + Copilot instructions.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/type_checker.rs | Adds type-checker tests for aggregate declarations, member access, and related errors. |
| tests/program.rs | Updates program parsing tests and adds a fixture-based test for top-level aggregate declarations. |
| tests/parser.rs | Adds parser tests for aggregate type syntax and member-access expressions/assignment targets. |
| tests/interpreter.rs | Adds runtime tests for struct/union/enum behavior, including union active-field errors. |
| tests/fixtures/aggregate_types.minic | New fixture program exercising aggregates in a full program run. |
| tests/cli/run.test | Extends CLI shelltest coverage to run the new aggregate fixture. |
| src/semantic/type_checker.rs | Adds aggregate-aware typing: type-decl uniqueness, member typing, and aggregate-aware declarations/assignments. |
| src/parser/types.rs | New shared type grammar module including aggregate type declarations and type parsing. |
| src/parser/statements.rs | Switches declarations to type_definition and extends lvalue parsing to include .member. |
| src/parser/program.rs | Extends top-level program grammar to parse both aggregate type decls and functions. |
| src/parser/mod.rs | Exposes the new types module and re-exports aggregate_type_decl. |
| src/parser/identifiers.rs | Expands reserved words and adds identifier_decl for typed identifiers (params/fields). |
| src/parser/functions.rs | Updates function parsing to reuse type_definition and identifier_decl for params. |
| src/parser/expressions.rs | Extends primary expressions to support chained member access via .member. |
| src/ir/ast.rs | Adds aggregate type representations, member-access expression variant, typed identifier decls, and program-level type declarations. |
| src/interpreter/value.rs | Introduces runtime Value variants for struct/union/enum and display formatting. |
| src/interpreter/mod.rs | Builds and injects aggregate type declarations into the runtime environment. |
| src/interpreter/exec_stmt.rs | Implements aggregate variable initialization and member assignment execution. |
| src/interpreter/eval_expr.rs | Implements runtime member access for struct/union/enum (including enum enumerator resolution). |
| src/environment/mod.rs | Re-exports aggregate type-decl map helpers/types from the environment module. |
| src/environment/env.rs | Extends the environment to carry shared aggregate type declarations with lookup helpers. |
| docs/00-guide.md | Adds an introductory Rust/Nom/MiniC guide and project conventions/testing guidance. |
| .github/copilot-instructions.md | Adds repo-specific Copilot coding guidelines focused on educational clarity. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+147
to
+163
| fn parse_to_number(input: &str) -> Result<i32, std::num::ParseIntError> { | ||
| input.parse::<i32>() | ||
| } | ||
|
|
||
| // chamando e lidando com o resultado explicitamente | ||
| fn try_parse_number() { | ||
| match parse_number("42") { | ||
| Ok(n) => println!("numero: {}", n), | ||
| Err(e) => eprintln!("erro ao parsear: {}", e), | ||
| } | ||
| } | ||
|
|
||
| // propagando erros com `?` | ||
| fn try_double(s: &str) -> Result<i64, String> { | ||
| let n = parse_number(s)?; | ||
| Ok(n * 2) | ||
| } |
Comment on lines
+343
to
+351
| ### 5) [Funções e Tipos](../src/parser/functions.rs) | ||
|
|
||
| Declaração de função e tipos. | ||
|
|
||
| Parser de tipo inclui formas escalares e de array. Porque `alt` é ordenado, prefixos mais longos (como formas de array 2D) são listados listados antes dos mais curtos (formas 1D). | ||
|
|
||
| ### 6) [Parser de Programa](../src/parser/program.rs) | ||
|
|
||
| Parser de declarações top-level. Usa repetição sobre declarações de função. |
Comment on lines
+159
to
161
| for param in &f.params { | ||
| env.declare(param.name.clone(), param.ty.clone()); | ||
| } |
Comment on lines
+181
to
+192
| if let Type::Aggregate { | ||
| specifier, | ||
| identifier, | ||
| } = ty | ||
| { | ||
| if !env.has_aggregate_type(specifier, identifier) { | ||
| return Err(TypeError::new(format!( | ||
| "unknown aggregate type: {:?} {}", | ||
| specifier, identifier | ||
| ))); | ||
| } | ||
| } |
Comment on lines
+201
to
+203
| if init_checked.ty != Type::Int { | ||
| return Err(TypeError::new( | ||
| "aggregate-typed variable declarations currently require integer placeholder initializer", |
Comment on lines
+267
to
+305
| fn assign_member( | ||
| base: &CheckedExpr, | ||
| member: &str, | ||
| val: Value, | ||
| env: &mut Environment<Value>, | ||
| ) -> Result<(), RuntimeError> { | ||
| match &base.exp { | ||
| Expr::Ident(name) => { | ||
| let current = env | ||
| .get(name) | ||
| .cloned() | ||
| .ok_or_else(|| RuntimeError::new(format!("undefined variable '{}'", name)))?; | ||
| let updated = match current { | ||
| Value::Struct { | ||
| identifier, | ||
| mut fields, | ||
| } => { | ||
| fields.insert(member.to_string(), val); | ||
| Value::Struct { identifier, fields } | ||
| } | ||
| Value::Union { identifier, .. } => Value::Union { | ||
| identifier, | ||
| active_field: member.to_string(), | ||
| value: Box::new(val), | ||
| }, | ||
| other => { | ||
| return Err(RuntimeError::new(format!( | ||
| "cannot assign member on non-aggregate value: {}", | ||
| other | ||
| ))) | ||
| } | ||
| }; | ||
| env.set(name, updated); | ||
| Ok(()) | ||
| } | ||
| _ => Err(RuntimeError::new( | ||
| "member assignment currently requires a simple variable base".to_string(), | ||
| )), | ||
| } |
Comment on lines
+346
to
+350
| let coerced = coerce_value_to_type(init_val, &first_field.ty)?; | ||
| Ok(Value::Union { | ||
| identifier: identifier.to_string(), | ||
| active_field: first_field.name.clone(), | ||
| value: Box::new(coerced), |
Comment on lines
+32
to
34
| //! matters. Declaration is tried first because it starts with type_definition keyword | ||
| //! (`int`, `float`, …), which is unambiguous. If declaration fails, the | ||
| //! parser backtracks and tries assignment. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Grupo 7
Acabei implementando Structs, Unions e Enums, já que são todos "aggregate types" bem parecidos.
Segue abaixo descrição do PR pelo Copilot:
This pull request introduces full runtime support for aggregate types (struct, union, enum) in the MiniC interpreter. The changes add new value representations, extend the environment to track aggregate type declarations, and implement member access and assignment for aggregates. Additionally, the interpreter now correctly initializes and handles aggregate variables and enum values, with improved error handling and code clarity.
Aggregate type support and environment enhancements:
AgtTypeSpecifierand extended theTypeenum to represent aggregate types (struct,union,enum) insrc/ir/ast.rs. [1] [2]Environmentstruct to track aggregate type declarations, including helper functions to build and look up type declarations. [1] [2]Interpreter and runtime value changes:
Valuevariants forStruct,Union, andEnum, with correspondingDisplayimplementations for debugging. [1] [2]Additional improvements:
eval_expr.Documentation and guidelines:
docs/00-guides.mdfile with a brief introduction to Rust syntax, the Nom parser library and MiniC project conventions..github/copilot-instructions.mdfile outlining coding standards and best practices for educational clarity and code consistency.These changes collectively enable correct runtime handling of structs, unions, and enums in MiniC, making the interpreter more robust and aligned with the language specification.