diff options
Diffstat (limited to 'CompilerKit')
| -rw-r--r-- | CompilerKit/AsmKit/Arch/32k.hpp | 92 | ||||
| -rw-r--r-- | CompilerKit/AsmKit/Arch/64k.hpp | 102 | ||||
| -rw-r--r-- | CompilerKit/AsmKit/AsmKit.cc | 47 | ||||
| -rw-r--r-- | CompilerKit/AsmKit/AsmKit.hpp | 63 | ||||
| -rw-r--r-- | CompilerKit/Defines.hpp | 135 | ||||
| -rw-r--r-- | CompilerKit/ParserKit.hpp | 93 | ||||
| -rw-r--r-- | CompilerKit/StdKit/AE.hpp | 61 | ||||
| -rw-r--r-- | CompilerKit/StdKit/ErrorID.hpp | 22 | ||||
| -rw-r--r-- | CompilerKit/StdKit/ErrorOr.hpp | 58 | ||||
| -rw-r--r-- | CompilerKit/StdKit/PEF.hpp | 85 | ||||
| -rw-r--r-- | CompilerKit/StdKit/Ref.hpp | 89 | ||||
| -rw-r--r-- | CompilerKit/StdKit/String.cc | 230 | ||||
| -rw-r--r-- | CompilerKit/StdKit/String.hpp | 72 |
13 files changed, 1149 insertions, 0 deletions
diff --git a/CompilerKit/AsmKit/Arch/32k.hpp b/CompilerKit/AsmKit/Arch/32k.hpp new file mode 100644 index 0000000..460a905 --- /dev/null +++ b/CompilerKit/AsmKit/Arch/32k.hpp @@ -0,0 +1,92 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Defines.hpp> + +// @brief 32x0 support. +// @file Arch/64k.hpp + +#define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \ + { .fName = __NAME, .fOpcode = __OPCODE, .fFunct3 = __FUNCT3, .fFunct7 = __FUNCT7 }, + + + +// placeholder for funct7/funct7-rs2 +#define kAsmImmediate 0x00 +#define kAsmSyscall 0x02 +#define kAsmJump 0x03 + +#define kAsmByte 0 +#define kAsmHWord 1 +#define kAsmWord 2 + +struct CpuCode32x0 +{ + const char fName[16]; + char fOpcode; + char fSize; + char fFunct3; + char fFunct7; +}; + +#define kAsmWordStr ".w" +#define kAsmHWordStr ".h" +#define kAsmByteStr ".b" + +inline std::vector<CpuCode32x0> kOpcodes32x0 = { + kAsmOpcodeDecl("nop", 0b0100011, 0b0000000, kAsmImmediate) // nothing to do. + kAsmOpcodeDecl("jmp", 0b1110011, 0b0000011, kAsmJump) // jump to branch + kAsmOpcodeDecl("move", 0b0100011, 0b101, kAsmImmediate) + kAsmOpcodeDecl("push", 0b0111011, 0b0, kAsmImmediate) // push to sp + kAsmOpcodeDecl("pop", 0b0111011, 0b1, kAsmImmediate) // pop from sp. + kAsmOpcodeDecl("int", 0b0111111, 0b0, kAsmSyscall) // raise interrupt +}; + +// \brief NewCPU register prefix +// example: r32, r0 +// r32 -> sp +// r0 -> hw zero + +#define kAsmRegisterPrefix "r" +#define kAsmRegisterLimit 20 +#define kAsmPcRegister 17 +#define kAsmCrRegister 18 +#define kAsmSpRegister 5 + +/* return address register */ +#define kAsmRetRegister 19 + +///////////////////////////////////////////////////////////////////////////// + +// SYSTEM CALL ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | OFF | + +// IMMEDIATE ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | REG | +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG | OFF | + +// REG TO REG ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG2 | + +//////////////////////////////// + +// LOAD/CALL INTERRUPTS + +// SET A HANDLER IN ADDRESS: TODO: find one +// DISABLE INTERRUPTS +// PROCESS INTERRUPT +// ENABLE INTERRUPTS + +////////////////////////////////
\ No newline at end of file diff --git a/CompilerKit/AsmKit/Arch/64k.hpp b/CompilerKit/AsmKit/Arch/64k.hpp new file mode 100644 index 0000000..e5c5253 --- /dev/null +++ b/CompilerKit/AsmKit/Arch/64k.hpp @@ -0,0 +1,102 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Defines.hpp> + +// @brief 64x0 support. +// @file Arch/64k.hpp + +#define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \ + { .fName = __NAME, .fOpcode = __OPCODE, .fFunct3 = __FUNCT3, .fFunct7 = __FUNCT7 }, + + + +// placeholder for funct7/funct7-rs2 +#define kAsmImmediate 0x00 +#define kAsmRegToReg 0x01 +#define kAsmSyscall 0x02 +#define kAsmJump 0x03 + +struct CpuCode64x0 +{ + const char fName[16]; + char fOpcode; + char fFunct3; + char fFunct7; +}; + +inline std::vector<CpuCode64x0> kOpcodes64x0 = { + kAsmOpcodeDecl("np", 0b0100011, 0b0000000, kAsmImmediate) // mv r0, r0 + kAsmOpcodeDecl("jb", 0b1110011, 0b0000011, kAsmJump) // jump to branch + kAsmOpcodeDecl("jlr", 0b1110011, 0b0000111, kAsmJump) // jump and link return register + kAsmOpcodeDecl("jrl", 0b1110011, 0b0001111, kAsmJump) // jump to register link + kAsmOpcodeDecl("jr", 0b1110011, 0b0001011, kAsmJump) // jump to register + kAsmOpcodeDecl("jal", 0b1110011, 0b0000001, kAsmJump) + kAsmOpcodeDecl("mv", 0b0100011, 0b101, kAsmRegToReg) + kAsmOpcodeDecl("psh", 0b0111011, 0b0, kAsmImmediate) // push to sp + kAsmOpcodeDecl("pop", 0b0111011, 0b1, kAsmImmediate) // pop from sp. + kAsmOpcodeDecl("bg", 0b1100111, 0b111, kAsmRegToReg) + kAsmOpcodeDecl("bl", 0b1100111, 0b011, kAsmRegToReg) + kAsmOpcodeDecl("beq", 0b1100111, 0b000, kAsmRegToReg) + kAsmOpcodeDecl("bne", 0b1100111, 0b001, kAsmRegToReg) + kAsmOpcodeDecl("bge", 0b1100111, 0b101, kAsmRegToReg) + kAsmOpcodeDecl("ble", 0b1100111, 0b100, kAsmRegToReg) + kAsmOpcodeDecl("stw", 0b0001111, 0b100, kAsmImmediate) + kAsmOpcodeDecl("ldw", 0b0001111, 0b100, kAsmImmediate) + kAsmOpcodeDecl("lda", 0b0001111, 0b101, kAsmImmediate) + kAsmOpcodeDecl("sta", 0b0001111, 0b001, kAsmImmediate) + kAsmOpcodeDecl("add", 0b0101011, 0b100, kAsmImmediate) + kAsmOpcodeDecl("dec", 0b0101011, 0b101, kAsmImmediate) + kAsmOpcodeDecl("scall", 0b1110011, 0b00, kAsmSyscall) + kAsmOpcodeDecl("sbreak", 0b1110011, 0b01, kAsmSyscall) + kAsmOpcodeDecl("mh", 0b1110011, 0b1111111, kAsmJump) +}; + +// \brief NewCPU register prefix +// example: r32, r0 +// r32 -> sp +// r0 -> hw zero + +#define kAsmRegisterPrefix "r" +#define kAsmRegisterLimit 20 +#define kAsmPcRegister 17 +#define kAsmCrRegister 18 +#define kAsmSpRegister 5 + +/* return address register */ +#define kAsmRetRegister 19 + +///////////////////////////////////////////////////////////////////////////// + +// SYSTEM CALL ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | OFF | + +// IMMEDIATE ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | REG | +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG | OFF | + +// REG TO REG ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG2 | + +//////////////////////////////// + +// LOAD/CALL INTERRUPTS + +// SET A HANDLER IN ADDRESS: TODO: find one +// DISABLE INTERRUPTS +// PROCESS INTERRUPT +// ENABLE INTERRUPTS + +////////////////////////////////
\ No newline at end of file diff --git a/CompilerKit/AsmKit/AsmKit.cc b/CompilerKit/AsmKit/AsmKit.cc new file mode 100644 index 0000000..4ee031f --- /dev/null +++ b/CompilerKit/AsmKit/AsmKit.cc @@ -0,0 +1,47 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#include <AsmKit/AsmKit.hpp> +#include <StdKit/ErrorID.hpp> + +#include <iostream> + +//! @file AsmKit.cpp +//! @brief AssemblyKit + +namespace CompilerKit +{ + //! @brief Compile for specific format (ELF, PEF, ZBIN) + Int32 AssemblyFactory::Compile(StringView& sourceFile, + const Int32& arch) noexcept + { + if (sourceFile.Length() < 1 || + !fMounted) + return CXXKIT_UNIMPLEMENTED; + + return fMounted->CompileToFormat(sourceFile, arch); + } + + //! @brief mount assembly backend. + void AssemblyFactory::Mount(AssemblyMountpoint* mountPtr) noexcept + { + if (mountPtr) + fMounted = mountPtr; + } + + AssemblyMountpoint* AssemblyFactory::Unmount() noexcept + { + auto mount_prev = fMounted; + + if (mount_prev) + fMounted = nullptr; + + return mount_prev; + } +} diff --git a/CompilerKit/AsmKit/AsmKit.hpp b/CompilerKit/AsmKit/AsmKit.hpp new file mode 100644 index 0000000..f512507 --- /dev/null +++ b/CompilerKit/AsmKit/AsmKit.hpp @@ -0,0 +1,63 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Compiler.hpp> +#include <CompilerKit/Defines.hpp> +#include <CompilerKit/StdKit/String.hpp> + +namespace CompilerKit +{ + // + // @brief Frontend to Assembly mountpoint. + // + class AssemblyMountpoint + { + public: + explicit AssemblyMountpoint() = default; + virtual ~AssemblyMountpoint() = default; + + CXXKIT_COPY_DEFAULT(AssemblyMountpoint); + + //@ brief compile to object file. + // Example C++ -> MASM -> AE object. + virtual Int32 CompileToFormat(StringView& src, Int32 arch) = 0; + + }; + + /// @brief Simple assembly factory + class AssemblyFactory final + { + public: + explicit AssemblyFactory() = default; + ~AssemblyFactory() = default; + + CXXKIT_COPY_DEFAULT(AssemblyFactory); + + public: + enum + { + kArchAMD64, + kArch32x0, + kArch64x0, + kArchRISCV, + kArchUnknown, + }; + + Int32 Compile(StringView& sourceFile, const Int32& arch) noexcept; + + void Mount(AssemblyMountpoint* mountPtr) noexcept; + AssemblyMountpoint* Unmount() noexcept; + + private: + AssemblyMountpoint* fMounted{ nullptr }; + + }; +} diff --git a/CompilerKit/Defines.hpp b/CompilerKit/Defines.hpp new file mode 100644 index 0000000..00c75f6 --- /dev/null +++ b/CompilerKit/Defines.hpp @@ -0,0 +1,135 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#ifndef __CXXKIT_DEFINES_HPP__ +#define __CXXKIT_DEFINES_HPP__ + +#ifndef Yes +#define Yes true +#endif // ifndef Yes + +#ifndef No +#define No false +#endif // ifndef No + +#include <stdint.h> + +#define SizeType size_t + +#define VoidPtr void* +#define voidPtr VoidPtr + +#define UIntPtr uintptr_t + +#define Int64 int64_t +#define UInt64 uint64_t + +#define Int32 int32_t +#define UInt32 uint32_t + +#define Bool bool + +#define Int16 int16_t +#define UInt16 uint16_t + +#define Int8 int8_t +#define UInt8 uint8_t + +#define CharType char +#define Boolean bool + +#include <new> +#include <cstring> +#include <cassert> + +#define nullPtr std::nullptr_t + +#define MUST_PASS(E) assert(E) + +#ifndef __FORCE_STRLEN +# define __FORCE_STRLEN 1 + +# define string_length(len) strlen(len) +#endif + +#ifndef __FORCE_MEMCPY +# define __FORCE_MEMCPY 1 + +# define rt_copy_memory(dst, src, len) memcpy(dst, src, len) +#endif + +#define CXXKIT_COPY_DELETE(KLASS) \ + KLASS &operator=(const KLASS &) = delete; \ + KLASS(const KLASS &) = delete; + + +#define CXXKIT_COPY_DEFAULT(KLASS) \ + KLASS &operator=(const KLASS &) = default; \ + KLASS(const KLASS &) = default; + + +#define CXXKIT_MOVE_DELETE(KLASS) \ + KLASS &operator=(KLASS &&) = delete; \ + KLASS(KLASS &&) = delete; + + +#define CXXKIT_MOVE_DEFAULT(KLASS) \ + KLASS &operator=(KLASS &&) = default; \ + KLASS(KLASS &&) = default; + + + +#include <ctime> +#include <string> + +namespace CompilerKit +{ + inline constexpr int BASE_YEAR = 1900; + + inline std::string current_date() + { + auto time_data = time(nullptr); + auto time_struct = gmtime(&time_data); + + std::string fmt = std::to_string(BASE_YEAR + time_struct->tm_year); + fmt += "-"; + fmt += std::to_string(time_struct->tm_mon + 1); + fmt += "-"; + fmt += std::to_string(time_struct->tm_mday); + + return fmt; + } + + inline bool to_str(CharType *str, Int32 limit, Int32 base) + { + if (limit == 0) + return false; + + Int32 copy_limit = limit; + Int32 cnt = 0; + Int32 ret = base; + + while (limit != 1) { + ret = ret % 10; + str[cnt] = ret; + + ++cnt; + --limit; + --ret; + } + + str[copy_limit] = '\0'; + return true; + } +} + +#define kObjectFileExt ".o" +#define kAsmFileExt64x0 ".64x" + +#endif /* ifndef __CXXKIT_DEFINES_HPP__ */ diff --git a/CompilerKit/ParserKit.hpp b/CompilerKit/ParserKit.hpp new file mode 100644 index 0000000..ce207a1 --- /dev/null +++ b/CompilerKit/ParserKit.hpp @@ -0,0 +1,93 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/AsmKit/AsmKit.hpp> + +namespace ParserKit +{ + using namespace CompilerKit; + + class CompilerBackend + { + public: + explicit CompilerBackend() = default; + virtual ~CompilerBackend() = default; + + CXXKIT_COPY_DEFAULT(CompilerBackend); + + // NOTE: cast this to your user defined ast. + typedef void* AstType; + + //! @brief Compile a syntax tree ouf of the text. + //! Also takes the source file name for metadata. + + virtual bool Compile(const std::string& text, const char* file) = 0; + + //! @brief What language are we dealing with? + virtual const char* Language() { return "Generic Language"; } + + }; + + struct SyntaxLeafList; + struct SyntaxLeafList; + + struct SyntaxLeafList final + { + struct SyntaxLeaf final + { + Int32 fUserType; + std::string fUserData; + std::string fUserValue; + struct SyntaxLeaf* fNext; + }; + + std::vector<SyntaxLeaf> fLeafList; + SizeType fNumLeafs; + + size_t SizeOf() { return fNumLeafs; } + std::vector<SyntaxLeaf>& Get() { return fLeafList; } + SyntaxLeaf& At(size_t index) { return fLeafList[index]; } + + }; + + /// find the perfect matching word in a haystack. + /// \param haystack base string + /// \param needle the string we search for. + /// \return if we found it or not. + inline bool find_word(const std::string& haystack,const std::string& needle) noexcept + { + auto index = haystack.find(needle); + + // check for needle validity. + if (index == std::string::npos) + return false; + + // declare lambda + auto not_part_of_word = [&](int index){ + if (std::isspace(haystack[index]) || std::ispunct(haystack[index])) + return true; + + if (index < 0 || index >= haystack.size()) + return true; + + return false; + }; + + return not_part_of_word(index - 1) && + not_part_of_word(index + needle.size()); + } + + inline bool find_word_strict(const std::string& haystack, const std::string& needle) noexcept + { + return ParserKit::find_word(haystack, needle) && + isspace(haystack[haystack.find(needle) + needle.size() + 1]); + } +}
\ No newline at end of file diff --git a/CompilerKit/StdKit/AE.hpp b/CompilerKit/StdKit/AE.hpp new file mode 100644 index 0000000..3aafc20 --- /dev/null +++ b/CompilerKit/StdKit/AE.hpp @@ -0,0 +1,61 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Defines.hpp> + +#define kAEMag0 'A' +#define kAEMag1 'E' + +#define kAESymbolLen 64 +#define kAEPad 8 +#define kAEMagLen 2 +#define kAEInvalidOpcode 0x00 + +// Advanced Executable File Format for MetroLink. +// Reloctable by offset is the default strategy. +// You can also relocate at runtime but that's up to the operating system loader. + +namespace CompilerKit +{ + // @brief Advanced Executable Header + // One thing to keep in mind. + // This object format, is reloctable. + typedef struct AEHeader final + { + CharType fMagic[kAEMagLen]; + CharType fArch; + SizeType fCount; + CharType fSize; + SizeType fStartCode; + SizeType fCodeSize; + CharType fPad[kAEPad]; + } __attribute__((packed)) AEHeader, *AEHeaderPtr; + + // @brief Advanced Executable Record. + // Could be data, code or bss. + // fKind must be filled with PEF fields. + + typedef struct AERecordHeader final + { + CharType fName[kAESymbolLen]; + SizeType fKind; + SizeType fSize; + SizeType fFlags; + UIntPtr fOffset; + CharType fPad[kAEPad]; + } __attribute__((packed)) AERecordHeader, *AERecordHeaderPtr; + + enum + { + kKindRelocationByOffset = 0x23f, + kKindRelocationAtRuntime = 0x34f, + }; +} diff --git a/CompilerKit/StdKit/ErrorID.hpp b/CompilerKit/StdKit/ErrorID.hpp new file mode 100644 index 0000000..b4b204c --- /dev/null +++ b/CompilerKit/StdKit/ErrorID.hpp @@ -0,0 +1,22 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <StdKit/ErrorOr.hpp> +#include <Defines.hpp> + +#define CXXKIT_EXEC_ERROR -30 +#define CXXKIT_FILE_NOT_FOUND -31 +#define CXXKIT_DIR_NOT_FOUND -32 +#define CXXKIT_FILE_EXISTS -33 +#define CXXKIT_TOO_LONG -34 +#define CXXKIT_INVALID_DATA -35 +#define CXXKIT_UNIMPLEMENTED -36 +#define CXXKIT_FAT_ERROR -37 diff --git a/CompilerKit/StdKit/ErrorOr.hpp b/CompilerKit/StdKit/ErrorOr.hpp new file mode 100644 index 0000000..c2457df --- /dev/null +++ b/CompilerKit/StdKit/ErrorOr.hpp @@ -0,0 +1,58 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Defines.hpp> +#include <CompilerKit/StdKit/Ref.hpp> + +namespace CompilerKit +{ +using ErrorT = UInt32; + +template <typename T> +class ErrorOr final +{ + public: + ErrorOr() = default; + ~ErrorOr() = default; + + public: + explicit ErrorOr(Int32 err) + : mId(err) + {} + + explicit ErrorOr(nullPtr Null) + {} + + explicit ErrorOr(T Class) + : mRef(Class) + {} + + ErrorOr &operator=(const ErrorOr &) = default; + ErrorOr(const ErrorOr &) = default; + + Ref<T> Leak() + { + return mRef; + } + + operator bool() + { + return mRef; + } + + private: + Ref<T> mRef; + Int32 mId{0}; +}; + +using ErrorOrAny = ErrorOr<voidPtr>; + +} // namespace CompilerKit diff --git a/CompilerKit/StdKit/PEF.hpp b/CompilerKit/StdKit/PEF.hpp new file mode 100644 index 0000000..5ff77f8 --- /dev/null +++ b/CompilerKit/StdKit/PEF.hpp @@ -0,0 +1,85 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Defines.hpp> + +#define kPefMagic "PEF" +#define kPefMagicFat "FEP" + +#define kPefMagicLen 3 + +#define kPefVersion 1 +#define kPefNameLen 64 + +// Protable Executable Format, a format designed for any computer. + +namespace CompilerKit +{ + enum + { + kPefArchIntel86S = 100, + kPefArchAMD64, + kPefArchRISCV, + kPefArch64000, /* Advanced RISC architecture. */ + kPefArch32000, + kPefArchInvalid = 0xFF, + }; + + enum + { + kPefKindExec = 1, /* .o/.pef/<none> */ + kPefKindSharedObject = 2, /* .lib */ + kPefKindObject = 4, /* .obj */ + kPefKindDwarf = 5, /* .dsym */ + }; + + /* PEF container */ + typedef struct PEFContainer final + { + CharType Magic[kPefMagicLen]; + UInt32 Linker; + UInt32 Version; + UInt32 Kind; + UInt32 Abi; + UInt32 Cpu; + UInt32 SubCpu; /* Cpu specific information */ + UIntPtr Start; + SizeType HdrSz; /* Size of header */ + SizeType Count; /* container header count */ + } __attribute__((packed)) PEFContainer; + + /* First PEFCommandHeader starts after PEFContainer */ + /* Last container is __exec_end */ + + /* PEF executable section and commands. */ + + typedef struct PEFCommandHeader final + { + CharType Name[kPefNameLen]; /* container name */ + UInt32 Flags; /* container flags */ + UInt16 Kind; /* container kind */ + UIntPtr Offset; /* file offset */ + SizeType Size; /* file size */ + } __attribute__((packed)) PEFCommandHeader; + + enum + { + kPefCode = 0xC, + kPefData = 0xD, + kPefZero = 0xE, + kPefLinkerID = 0x1, + }; +} + +#define kPefExt ".o" +#define kPefDylibExt ".so" +#define kPefObjectExt ".o" +#define kPefDebugExt ".dbg"
\ No newline at end of file diff --git a/CompilerKit/StdKit/Ref.hpp b/CompilerKit/StdKit/Ref.hpp new file mode 100644 index 0000000..2ca540a --- /dev/null +++ b/CompilerKit/StdKit/Ref.hpp @@ -0,0 +1,89 @@ + +/* + * ======================================================== + * + * CompilerKit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Defines.hpp> + +namespace CompilerKit +{ + // @author Western Company + // @brief Reference class, refers to a pointer of data in static memory. + template <typename T> + class Ref final + { + public: + Ref() = default; + ~Ref() = default; + + public: + Ref(T cls, const bool &strong = false) : m_Class(cls), m_Strong(strong) {} + + Ref &operator=(T ref) + { + m_Class = ref; + return *this; + } + + public: + T operator->() const + { + return m_Class; + } + + T &Leak() + { + return m_Class; + } + + T operator*() + { + return m_Class; + } + + bool IsStrong() const + { + return m_Strong; + } + + operator bool() + { + return m_Class; + } + + private: + T m_Class; + bool m_Strong{ false }; + + }; + + template <typename T> + class NonNullRef final + { + public: + NonNullRef() = delete; + NonNullRef(nullPtr) = delete; + + NonNullRef(T *ref) : m_Ref(ref, true) {} + + Ref<T> &operator->() + { + MUST_PASS(m_Ref); + return m_Ref; + } + + NonNullRef &operator=(const NonNullRef<T> &ref) = delete; + NonNullRef(const NonNullRef<T> &ref) = default; + + private: + Ref<T> m_Ref{ nullptr }; + + }; +} // namespace CompilerKit diff --git a/CompilerKit/StdKit/String.cc b/CompilerKit/StdKit/String.cc new file mode 100644 index 0000000..6f11404 --- /dev/null +++ b/CompilerKit/StdKit/String.cc @@ -0,0 +1,230 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#include "String.hpp" +#include <utility> + +namespace CompilerKit +{ + CharType* StringView::Data() + { + return m_Data.data(); + } + + const CharType* StringView::CData() const + { + return m_Data.c_str(); + } + + SizeType StringView::Length() const + { + return m_Data.size(); + } + + bool StringView::operator==(const StringView &rhs) const + { + if (rhs.Length() != Length()) + return false; + + for (SizeType index = 0; index < Length(); ++index) + { + if (rhs.m_Data[index] != m_Data[index]) + return false; + } + + return true; + } + + bool StringView::operator==(const CharType *rhs) const + { + if (string_length(rhs) != Length()) + return false; + + for (SizeType index = 0; index < string_length(rhs); ++index) + { + if (rhs[index] != m_Data[index]) + return false; + } + + return true; + } + + bool StringView::operator!=(const StringView &rhs) const + { + if (rhs.Length() != Length()) + return false; + + for (SizeType index = 0; index < rhs.Length(); ++index) + { + if (rhs.m_Data[index] == m_Data[index]) + return false; + } + + return true; + } + + bool StringView::operator!=(const CharType *rhs) const + { + if (string_length(rhs) != Length()) + return false; + + for (SizeType index = 0; index < string_length(rhs); ++index) + { + if (rhs[index] == m_Data[index]) + return false; + } + + return true; + } + + StringView StringBuilder::Construct(const CharType *data) + { + if (!data || + *data == 0) + return StringView(0); + + StringView view(strlen(data)); + view += data; + + return view; + } + + const char* StringBuilder::FromInt(const char *fmt, int i) + { + if (!fmt) + return ("-1"); + + char *ret = new char[8 + string_length(fmt)]; + + if (!ret) + return ("-1"); + + CharType result[8]; + if (!to_str(result, sizeof(int), i)) + { + delete[] ret; + return ("-1"); + } + + const auto fmt_len = string_length(fmt); + const auto res_len = string_length(result); + + for (SizeType idx = 0; idx < fmt_len; ++idx) + { + if (fmt[idx] == '%') { + SizeType result_cnt = idx; + + for (auto y_idx = idx; y_idx < res_len; ++y_idx) { + ret[result_cnt] = result[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; /* Copy that ret into a buffer, Alloca allocates to the stack */ + } + + const char* StringBuilder::FromBool(const char *fmt, bool i) + { + if (!fmt) + return ("?"); + + const char *boolean_expr = i ? "true" : "false"; + char *ret = new char[i ? 4 : 5 + string_length(fmt)]; + + if (!ret) + return ("?"); + + const auto fmt_len = string_length(fmt); + const auto res_len = string_length(boolean_expr); + + for (SizeType idx = 0; idx < fmt_len; ++idx) + { + if (fmt[idx] == '%') { + SizeType result_cnt = idx; + + for (auto y_idx = idx; y_idx < res_len; ++y_idx) + { + ret[result_cnt] = boolean_expr[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; + } + + bool StringBuilder::Equals(const char *lhs, const char *rhs) + { + if (string_length(rhs) != string_length(lhs)) + return false; + + for (SizeType index = 0; index < string_length(rhs); ++index) + { + if (rhs[index] != lhs[index]) + return false; + } + + return true; + } + + const char *StringBuilder::Format(const char *fmt, const char *fmt2) + { + if (!fmt || !fmt2) + return ("?"); + + char *ret = new char[string_length(fmt2) + string_length(fmt2)]; + if (!ret) + return ("?"); + + for (SizeType idx = 0; idx < string_length(fmt); ++idx) + { + if (fmt[idx] == '%') { + SizeType result_cnt = idx; + for (SizeType y_idx = 0; y_idx < string_length(fmt2); ++y_idx) + { + ret[result_cnt] = fmt2[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; + } + + StringView &StringView::operator+=(const CharType *rhs) + { + this->m_Data += rhs; + this->m_Cur = this->m_Data.size(); + this->m_Sz = this->m_Data.size(); + + return *this; + } + + StringView &StringView::operator+=(const StringView &rhs) + { + this->m_Data += rhs.CData(); + this->m_Cur = this->m_Data.size(); + this->m_Sz = this->m_Data.size(); + + return *this; + } +} // namespace CompilerKit diff --git a/CompilerKit/StdKit/String.hpp b/CompilerKit/StdKit/String.hpp new file mode 100644 index 0000000..592c244 --- /dev/null +++ b/CompilerKit/StdKit/String.hpp @@ -0,0 +1,72 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Defines.hpp> +#include <CompilerKit/StdKit/ErrorOr.hpp> + +namespace CompilerKit +{ + class StringView final + { + public: + StringView() = delete; + + explicit StringView(SizeType Sz) : m_Sz(Sz) + { + + } + + ~StringView() = default; + + CXXKIT_COPY_DEFAULT(StringView); + + CharType *Data(); + const CharType *CData() const; + SizeType Length() const; + + bool operator==(const CharType *rhs) const; + bool operator!=(const CharType *rhs) const; + + bool operator==(const StringView &rhs) const; + bool operator!=(const StringView &rhs) const; + + StringView &operator+=(const CharType *rhs); + StringView &operator+=(const StringView &rhs); + + operator bool() + { + return m_Data.empty() == false; + } + + bool operator!() + { + return m_Data.empty() == true; + } + + private: + std::basic_string<char> m_Data{""}; + SizeType m_Sz{0}; + SizeType m_Cur{0}; + + friend class StringBuilder; + + }; + + struct StringBuilder final + { + static StringView Construct(const CharType *data); + static const char* FromInt(const char *fmt, int n); + static const char* FromBool(const char *fmt, bool n); + static const char* Format(const char *fmt, const char* from); + static bool Equals(const char *lhs, const char *rhs); + + }; +} // namespace CompilerKit |
