diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-18 08:09:06 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-18 08:09:06 +0000 |
| commit | 30fced09675acfd2b9ab6db6be8359a70d3f0402 (patch) | |
| tree | 88dc4587cb71d9dc9bdd9a57c4e2de8a98d7f06e /lib | |
| parent | 345e3d419eafb0e234aecb4a33f37efe2afbbf53 (diff) | |
feat(operators): allow member assignment operator overloads
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/CodeGen/ConstructorGen.cc | 14 | ||||
| -rw-r--r-- | lib/CodeGen/FunctionGen.cc | 6 | ||||
| -rw-r--r-- | lib/Parser/ParserFunction.cc | 18 |
3 files changed, 35 insertions, 3 deletions
diff --git a/lib/CodeGen/ConstructorGen.cc b/lib/CodeGen/ConstructorGen.cc index 4bf5568..9fc762c 100644 --- a/lib/CodeGen/ConstructorGen.cc +++ b/lib/CodeGen/ConstructorGen.cc @@ -142,6 +142,20 @@ void CodeGen::emitAssignment(const LValueInfo &Target, ExprAST *Expr, const Symb } return; } + if (Info && Info->IsClass) { + auto Resolution = resolveOperator(tok_assign, Info, getExprTypeInfo(Expr)); + if (Resolution.Ambiguous) { + reportError("Ambiguous assignment operator"); + return; + } + if (const FuncSig *Sig = Resolution.Signature) { + if (!checkOperatorAccess(*Sig)) return; + std::vector<Value *> Args = {Target.Addr}; + if (marshalCallArgs(*Sig, std::vector<ExprAST *>{Expr}, DiagnosticLine, Args)) + FuncGen->emitCall(*Sig, Args); + return; + } + } Value *Val = emitCoercedExpr(Expr, Info); if (Val) Builder->CreateStore(Val, Target.Addr); } diff --git a/lib/CodeGen/FunctionGen.cc b/lib/CodeGen/FunctionGen.cc index 37df8ff..1f7bc2b 100644 --- a/lib/CodeGen/FunctionGen.cc +++ b/lib/CodeGen/FunctionGen.cc @@ -132,6 +132,12 @@ Function *FunctionGen::emitPrototype(PrototypeAST *Proto) { return nullptr; } } + if (Proto->getOperator() == tok_assign && + (Proto->getOwnerClass().empty() || !Proto->isOverload() || + !sameIdentifier(Proto->getReturnType(), "VOID"))) { + reportError("Assignment operator must be an OVERLOAD member PROCEDURE"); + return nullptr; + } if (int Op = Proto->getOperator()) { size_t Count = Proto->getParams().size() + !Proto->getOwnerClass().empty(); bool ValidCount = Op == '-' ? Count == 1 || Count == 2 diff --git a/lib/Parser/ParserFunction.cc b/lib/Parser/ParserFunction.cc index 65e0b85..cf8ecf8 100644 --- a/lib/Parser/ParserFunction.cc +++ b/lib/Parser/ParserFunction.cc @@ -214,12 +214,23 @@ std::unique_ptr<FunctionDefAST> Parser::ParseFunction(const std::string &OwnerCl std::unique_ptr<FunctionDefAST> Parser::ParseProcedure(const std::string &OwnerClass, bool IsPublic, bool IsOverload) { int Line = Lex.getLine(); getNextToken(); - if (CurTok != tok_identifier && CurTok != tok_new && CurTok != tok_delete) { + if (CurTok != tok_identifier && CurTok != tok_new && CurTok != tok_delete && CurTok != tok_operator) { cps::sourceDiagnostic(Lex.getLine(), "error: Expected procedure name\n"); return nullptr; } - std::string Name = CurTok == tok_new ? "NEW" : CurTok == tok_delete ? "DELETE" : Lex.IdentifierStr; + int Operator = 0; + bool IsOperator = CurTok == tok_operator; + std::string OperatorName; + if (IsOperator) { + OperatorName = ParseOperatorName(Operator); + if (OperatorName.empty()) return nullptr; + if (Operator != tok_assign || OwnerClass.empty() || !IsOverload) { + sourceDiagnostic(Line, "error: Assignment operator must be an OVERLOAD member PROCEDURE at line %d\n", Line); + return nullptr; + } + } + std::string Name = IsOperator ? OperatorName : CurTok == tok_new ? "NEW" : CurTok == tok_delete ? "DELETE" : Lex.IdentifierStr; if (OwnerClass.empty() && sameIdentifier(Name, "DELETE")) { cps::sourceDiagnostic(Lex.getLine(), "error: destructor DELETE is only allowed in a CLASS at line %d\n", Line); return nullptr; @@ -228,7 +239,7 @@ std::unique_ptr<FunctionDefAST> Parser::ParseProcedure(const std::string &OwnerC cps::sourceDiagnostic(Lex.getLine(), "error: constructor NEW is only allowed in a CLASS at line %d\n", Line); return nullptr; } - getNextToken(); + if (!IsOperator) getNextToken(); auto Args = ParsePrototypeArgs(/*AllowByRef=*/true); if (!Args) return nullptr; @@ -237,6 +248,7 @@ std::unique_ptr<FunctionDefAST> Parser::ParseProcedure(const std::string &OwnerC return nullptr; } auto Proto = std::make_unique<PrototypeAST>(Name, std::move(*Args), "VOID", false, OwnerClass, IsPublic, IsOverload); + Proto->setOperator(Operator); std::vector<std::unique_ptr<StmtAST>> Body = ParseBlock({tok_endprocedure}); |
