diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-17 06:02:21 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-17 06:02:21 +0000 |
| commit | 3425b95cb654f8e1adc98365a4b370aa1fff8b4d (patch) | |
| tree | 4d81b91d0bd807cd6f7ced037533d6e60f5c307f /include | |
| parent | 4e22f464387725a5a282f3d72e11cfb694a31a5a (diff) | |
feat(classes): support ordinary member methods and this references
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'include')
| -rw-r--r-- | include/cps/CodeGen.h | 4 | ||||
| -rw-r--r-- | include/cps/FunctionAST.h | 32 | ||||
| -rw-r--r-- | include/cps/FunctionGen.h | 2 | ||||
| -rw-r--r-- | include/cps/Parser.h | 9 | ||||
| -rw-r--r-- | include/cps/TypeAST.h | 10 |
5 files changed, 48 insertions, 9 deletions
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<llvm::IRBuilder<>> Builder; int DiagnosticLine = 0; IdentifierMap<SymbolInfo> Symbols; + IdentifierMap<IdentifierMap<FunctionDefAST*>> 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<std::optional<SymbolInfo>> 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<ParamDecl> Params; std::string ReturnType; bool IsExternal; + std::string OwnerClass; + bool IsPublic; public: PrototypeAST(const std::string &Name, std::vector<ParamDecl> 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<ParamDecl> &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<ExprAST> Receiver; + std::string Method; + std::vector<std::unique_ptr<ExprAST>> Args; +public: + MemberCallExprAST(std::unique_ptr<ExprAST> Receiver, std::string Method, + std::vector<std::unique_ptr<ExprAST>> 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<std::unique_ptr<ExprAST>> &getArgs() const { return Args; } +}; + +class MemberCallStmtAST : public StmtAST { + std::unique_ptr<MemberCallExprAST> Call; +public: + explicit MemberCallStmtAST(std::unique_ptr<MemberCallExprAST> Call) + : StmtAST(Call->getLine()), Call(std::move(Call)) {} + MemberCallExprAST *getCall() const { return Call.get(); } +}; + class ReturnStmtAST : public StmtAST { std::unique_ptr<ExprAST> 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<FuncSig> Signatures; ArrayParamBinder BindArrayParam; - void createArgumentAllocas(llvm::Function *F, const std::vector<ParamDecl> &Params); + void createArgumentAllocas(llvm::Function *F, const std::vector<ParamDecl> &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<ExprAST> ParseNumberExpr(); std::unique_ptr<ExprAST> ParseIdentifierExpr(); std::unique_ptr<ExprAST> ParseParenExpr(); + std::unique_ptr<MemberCallExprAST> ParseMemberCall( + const std::string &Name, std::vector<DesignatorAccess> Accesses, int Line); std::string ParseTypeName(bool AllowVoid = false); std::unique_ptr<StmtAST> ParseStatement(); @@ -66,11 +68,12 @@ class Parser { std::unique_ptr<StmtAST> ParseTypeDecl(); std::optional<std::vector<RecordFieldDecl>> ParseRecordBody( - const std::string &Name, int Line, int EndToken); + const std::string &Name, int Line, int EndToken, + std::vector<std::unique_ptr<FunctionDefAST>> *Methods = nullptr); bool ParseRecordField(std::vector<RecordFieldDecl> &Out, bool IsPublic); - std::unique_ptr<StmtAST> ParseFunction(); - std::unique_ptr<StmtAST> ParseProcedure(); + std::unique_ptr<FunctionDefAST> ParseFunction(const std::string &OwnerClass = {}, bool IsPublic = true); + std::unique_ptr<FunctionDefAST> ParseProcedure(const std::string &OwnerClass = {}, bool IsPublic = true); std::unique_ptr<StmtAST> ParseCallStmt(); std::unique_ptr<StmtAST> ParseReturnStmt(); std::optional<std::vector<ParamDecl>> 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 <cstdint> #include <memory> #include <string> @@ -81,12 +82,15 @@ public: const std::vector<RecordFieldDecl> &getFields() const { return Fields; } }; -// CLASS <name> with default-public or explicit PUBLIC/PRIVATE fields, ending in ENDCLASS. +// CLASS <name> 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<std::unique_ptr<FunctionDefAST>> Methods; public: - ClassTypeDeclAST(const std::string &Name, std::vector<RecordFieldDecl> Fields) - : RecordTypeDeclAST(Name, std::move(Fields)) {} + ClassTypeDeclAST(const std::string &Name, std::vector<RecordFieldDecl> Fields, + std::vector<std::unique_ptr<FunctionDefAST>> 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) ---- |
