From 3425b95cb654f8e1adc98365a4b370aa1fff8b4d Mon Sep 17 00:00:00 2001 From: _ov4 Date: Sat, 17 Oct 2026 06:02:21 +0000 Subject: feat(classes): support ordinary member methods and this references Co-Authored-By: Claude Fable 5.1 --- include/cps/CodeGen.h | 4 ++++ include/cps/FunctionAST.h | 32 ++++++++++++++++++++++++++++++-- include/cps/FunctionGen.h | 2 +- include/cps/Parser.h | 9 ++++++--- include/cps/TypeAST.h | 10 +++++++--- 5 files changed, 48 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/cps/CodeGen.h b/include/cps/CodeGen.h index 94aacb7..1c80434 100644 --- a/include/cps/CodeGen.h +++ b/include/cps/CodeGen.h @@ -32,6 +32,10 @@ class CodeGen { std::unique_ptr> Builder; int DiagnosticLine = 0; IdentifierMap Symbols; + IdentifierMap> ClassMethods; + std::string CurrentClass; + const PrototypeAST *findMethod(const std::string &Class, const std::string &Name) const; + llvm::Value *emitMemberCall(MemberCallExprAST *Call); struct ConstantScope { unsigned ID; IdentifierMap> Saved; diff --git a/include/cps/FunctionAST.h b/include/cps/FunctionAST.h index 0c2d0b5..16057e5 100644 --- a/include/cps/FunctionAST.h +++ b/include/cps/FunctionAST.h @@ -28,18 +28,24 @@ class PrototypeAST { std::vector Params; std::string ReturnType; bool IsExternal; + std::string OwnerClass; + bool IsPublic; public: PrototypeAST(const std::string &Name, std::vector Params, const std::string &ReturnType, - bool IsExternal = false) - : Name(Name), Params(std::move(Params)), ReturnType(ReturnType), IsExternal(IsExternal) {} + bool IsExternal = false, std::string OwnerClass = {}, bool IsPublic = true) + : Name(Name), Params(std::move(Params)), ReturnType(ReturnType), IsExternal(IsExternal), + OwnerClass(std::move(OwnerClass)), IsPublic(IsPublic) {} const std::string &getName() const { return Name; } const std::vector &getParams() const { return Params; } const std::string &getReturnType() const { return ReturnType; } bool isExternal() const { return IsExternal; } + const std::string &getOwnerClass() const { return OwnerClass; } + bool isPublic() const { return IsPublic; } + std::string getLinkName() const { return OwnerClass.empty() ? Name : OwnerClass + "." + Name; } }; class FunctionDefAST : public StmtAST { @@ -80,6 +86,28 @@ public: }; +// A member call keeps the receiver separate from explicit arguments. +class MemberCallExprAST : public ExprAST { + std::unique_ptr Receiver; + std::string Method; + std::vector> Args; +public: + MemberCallExprAST(std::unique_ptr Receiver, std::string Method, + std::vector> Args, int Line) + : ExprAST(Line), Receiver(std::move(Receiver)), Method(std::move(Method)), Args(std::move(Args)) {} + ExprAST *getReceiver() const { return Receiver.get(); } + const std::string &getMethod() const { return Method; } + const std::vector> &getArgs() const { return Args; } +}; + +class MemberCallStmtAST : public StmtAST { + std::unique_ptr Call; +public: + explicit MemberCallStmtAST(std::unique_ptr Call) + : StmtAST(Call->getLine()), Call(std::move(Call)) {} + MemberCallExprAST *getCall() const { return Call.get(); } +}; + class ReturnStmtAST : public StmtAST { std::unique_ptr RetVal; diff --git a/include/cps/FunctionGen.h b/include/cps/FunctionGen.h index fd874d2..5ff746d 100644 --- a/include/cps/FunctionGen.h +++ b/include/cps/FunctionGen.h @@ -65,7 +65,7 @@ private: IdentifierMap Signatures; ArrayParamBinder BindArrayParam; - void createArgumentAllocas(llvm::Function *F, const std::vector &Params); + void createArgumentAllocas(llvm::Function *F, const std::vector &Params, bool IsMethod); public: FunctionGen(llvm::LLVMContext &C, diff --git a/include/cps/Parser.h b/include/cps/Parser.h index fdbb99a..4874d7a 100644 --- a/include/cps/Parser.h +++ b/include/cps/Parser.h @@ -43,6 +43,8 @@ class Parser { std::unique_ptr ParseNumberExpr(); std::unique_ptr ParseIdentifierExpr(); std::unique_ptr ParseParenExpr(); + std::unique_ptr ParseMemberCall( + const std::string &Name, std::vector Accesses, int Line); std::string ParseTypeName(bool AllowVoid = false); std::unique_ptr ParseStatement(); @@ -66,11 +68,12 @@ class Parser { std::unique_ptr ParseTypeDecl(); std::optional> ParseRecordBody( - const std::string &Name, int Line, int EndToken); + const std::string &Name, int Line, int EndToken, + std::vector> *Methods = nullptr); bool ParseRecordField(std::vector &Out, bool IsPublic); - std::unique_ptr ParseFunction(); - std::unique_ptr ParseProcedure(); + std::unique_ptr ParseFunction(const std::string &OwnerClass = {}, bool IsPublic = true); + std::unique_ptr ParseProcedure(const std::string &OwnerClass = {}, bool IsPublic = true); std::unique_ptr ParseCallStmt(); std::unique_ptr ParseReturnStmt(); std::optional> ParsePrototypeArgs(bool AllowByRef); diff --git a/include/cps/TypeAST.h b/include/cps/TypeAST.h index edf2ee5..de5d12c 100644 --- a/include/cps/TypeAST.h +++ b/include/cps/TypeAST.h @@ -1,5 +1,6 @@ #pragma once #include "cps/AST.h" +#include "cps/FunctionAST.h" #include #include #include @@ -81,12 +82,15 @@ public: const std::vector &getFields() const { return Fields; } }; -// CLASS with default-public or explicit PUBLIC/PRIVATE fields, ending in ENDCLASS. +// CLASS with default-public or explicit PUBLIC/PRIVATE members, ending in ENDCLASS. // Storage and value semantics are inherited from record declarations. class ClassTypeDeclAST : public RecordTypeDeclAST { + std::vector> Methods; public: - ClassTypeDeclAST(const std::string &Name, std::vector Fields) - : RecordTypeDeclAST(Name, std::move(Fields)) {} + ClassTypeDeclAST(const std::string &Name, std::vector Fields, + std::vector> Methods) + : RecordTypeDeclAST(Name, std::move(Fields)), Methods(std::move(Methods)) {} + const auto &getMethods() const { return Methods; } }; // ---- Designators: chained accesses usable as lvalue or rvalue (ยง4.2) ---- -- cgit v1.3.1-4-g156e