diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-13 13:40:57 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-13 13:40:57 +0000 |
| commit | f5a2541ed3faf9a942b867e2d54577352153afce (patch) | |
| tree | d5f737fdb8d77dc67d46cc12f8603c7df6a168c7 /lib | |
| parent | 5b08d59dba28b99cf991c02e837297fbfdb190c9 (diff) | |
Refactor record fields to preserve visibility and share parsing
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/CodeGen/Designator.cc | 5 | ||||
| -rw-r--r-- | lib/CodeGen/TypeSystem.cc | 8 | ||||
| -rw-r--r-- | lib/Parser/ParserType.cc | 61 |
3 files changed, 40 insertions, 34 deletions
diff --git a/lib/CodeGen/Designator.cc b/lib/CodeGen/Designator.cc index ad0cc49..640ca0b 100644 --- a/lib/CodeGen/Designator.cc +++ b/lib/CodeGen/Designator.cc @@ -58,10 +58,7 @@ void CodeGen::runTypePrePass(const std::vector<std::unique_ptr<StmtAST>> &Statem } else if (auto *P = dynamic_cast<PointerTypeDeclAST*>(S.get())) { Ok = Types->definePointer(P->getName(), P->getPointeeTypeName(), Err); } else if (auto *R = dynamic_cast<RecordTypeDeclAST*>(S.get())) { - std::vector<std::pair<std::string, std::string>> Fields; - for (const RecordFieldDecl &F : R->getFields()) - Fields.emplace_back(F.Name, F.TypeName); - Ok = Types->defineRecord(R->getName(), Fields, Err); + Ok = Types->defineRecord(R->getName(), R->getFields(), Err); } if (!Ok) reportError("%s", Err.c_str()); } diff --git a/lib/CodeGen/TypeSystem.cc b/lib/CodeGen/TypeSystem.cc index c170be8..f693ba1 100644 --- a/lib/CodeGen/TypeSystem.cc +++ b/lib/CodeGen/TypeSystem.cc @@ -1,4 +1,5 @@ #include "cps/TypeSystem.h" +#include "cps/TypeAST.h" #include "llvm/IR/Constants.h" #include <utility> @@ -185,7 +186,7 @@ bool TypeSystem::defineEnum(const std::string &Name, } bool TypeSystem::defineRecord(const std::string &Name, - const std::vector<std::pair<std::string, std::string>> &Fields, + const std::vector<RecordFieldDecl> &Fields, std::string &Err) { auto It = Types.find(Name); if (It == Types.end() || It->second.Kind != TypeKind::Record) { @@ -195,7 +196,9 @@ bool TypeSystem::defineRecord(const std::string &Name, std::vector<Type*> FieldTypes; RecordPayload Payload; - for (const auto &[FieldName, FieldTypeName] : Fields) { + for (const RecordFieldDecl &Field : Fields) { + const std::string &FieldName = Field.Name; + const std::string &FieldTypeName = Field.TypeName; if (Payload.findField(FieldName)) { Err = "Duplicate field '" + FieldName + "' in record " + Name; return false; @@ -222,6 +225,7 @@ bool TypeSystem::defineRecord(const std::string &Name, RecordFieldInfo FI; FI.TypeName = FieldInfo->Name; FI.Index = static_cast<unsigned>(FieldTypes.size()); + FI.IsPublic = Field.IsPublic; Payload.Fields.emplace_back(FieldName, FI); FieldTypes.push_back(FieldInfo->LLVMType); } diff --git a/lib/Parser/ParserType.cc b/lib/Parser/ParserType.cc index 8be7e46..ae671d5 100644 --- a/lib/Parser/ParserType.cc +++ b/lib/Parser/ParserType.cc @@ -66,30 +66,9 @@ std::unique_ptr<StmtAST> Parser::ParseTypeDecl() { return nullptr; } } else { - // Record body: DECLARE-only lines, so nothing here can leak into the - // statement chain. One bad field yields one diagnostic; parsing then - // resumes at the next field or ENDTYPE. - std::vector<RecordFieldDecl> Fields; - bool HadFieldError = false; - while (CurTok == tok_declare) { - if (!ParseRecordField(Fields)) { - HadFieldError = true; - while (CurTok != tok_declare && CurTok != tok_endtype && CurTok != tok_eof) - getNextToken(); - } - } - if (CurTok != tok_endtype) { - fprintf(stderr, "error: Expected DECLARE or ENDTYPE in TYPE %s at line %d\n", - Name.c_str(), Lex.getLine()); - return nullptr; // token left for the outer recovery - } - getNextToken(); // eat ENDTYPE - if (Fields.empty()) { - fprintf(stderr, "error: Record TYPE %s has no fields at line %d\n", Name.c_str(), Line); - return nullptr; - } - if (HadFieldError) return nullptr; - Decl = std::make_unique<RecordTypeDeclAST>(Name, std::move(Fields)); + auto Fields = ParseRecordBody(Name, Line, tok_endtype); + if (!Fields) return nullptr; + Decl = std::make_unique<RecordTypeDeclAST>(Name, std::move(*Fields)); } if (!AtTopLevel) { @@ -99,9 +78,35 @@ std::unique_ptr<StmtAST> Parser::ParseTypeDecl() { return Decl; } -// DECLARE <field> : <type> — one record field. Array fields are deferred. -bool Parser::ParseRecordField(std::vector<RecordFieldDecl> &Out) { - getNextToken(); // eat DECLARE +// Shared record body and field parsing. Fields are data, never statements. +std::optional<std::vector<RecordFieldDecl>> Parser::ParseRecordBody( + const std::string &Name, int Line, int EndToken) { + std::vector<RecordFieldDecl> Fields; + bool HadFieldError = false; + while (CurTok == tok_declare) { + if (!ParseRecordField(Fields, true)) { + HadFieldError = true; + while (CurTok != tok_declare && CurTok != EndToken && CurTok != tok_eof) + getNextToken(); + } + } + if (CurTok != EndToken) { + fprintf(stderr, "error: Expected DECLARE or ENDTYPE in TYPE %s at line %d\n", + Name.c_str(), Lex.getLine()); + return std::nullopt; + } + getNextToken(); // eat body terminator + if (Fields.empty()) { + fprintf(stderr, "error: Record TYPE %s has no fields at line %d\n", Name.c_str(), Line); + return std::nullopt; + } + if (HadFieldError) return std::nullopt; + return Fields; +} + +// <field introducer> <field> : <type>. Array fields are deferred. +bool Parser::ParseRecordField(std::vector<RecordFieldDecl> &Out, bool IsPublic) { + getNextToken(); // eat field introducer if (CurTok != tok_identifier) { fprintf(stderr, "error: Expected field name after DECLARE at line %d\n", Lex.getLine()); return false; @@ -125,6 +130,6 @@ bool Parser::ParseRecordField(std::vector<RecordFieldDecl> &Out) { std::string TypeName = ParseTypeName(false); if (TypeName.empty()) return false; - Out.push_back({FieldName, TypeName}); + Out.push_back({FieldName, TypeName, IsPublic}); return true; } |
