From c69f5894394f1d93625631f1a316087a2ddc8cfa Mon Sep 17 00:00:00 2001 From: kotofyt Date: Fri, 16 Jan 2026 13:32:36 +0200 Subject: [PATCH] some improvements i think --- asmrigs/brb/brb.h | 27 +++++++++++++++++++ asmrigs/brb/lexer.cpp | 53 ++++++++++++++++++++++++++++++++++++++ asmrigs/brb/main.cpp | 19 ++++++++++++++ asmrigs/build.cpp | 45 ++++++++++++++++++++++++++++++++ asmrigs/spec/brb.txt | 26 +++++++++++++++++++ asmrigs/spec/o.txt | 42 ++++++++++++++++++++++++++++++ asmrigs/tests/001.b | 4 +++ asmrigs/tests/002.b | 4 +++ asmrigs/tests/003.b | 4 +++ asmrigs/tests/004.b | 7 +++++ asmrigs/tests/005.b | 9 +++++++ fpc/library/clang/c.cpp | 8 +++++- public/tier1/utlstring.h | 2 ++ public/tier3/lexer.h | 18 +++++++++++++ stdfilesystems/build.cpp | 35 +++++++++++++++++++++++++ tier2/fileformats/json.cpp | 40 +++++++++++++++++++++++++--- 16 files changed, 338 insertions(+), 5 deletions(-) create mode 100644 asmrigs/brb/brb.h create mode 100644 asmrigs/brb/lexer.cpp create mode 100644 asmrigs/brb/main.cpp create mode 100644 asmrigs/build.cpp create mode 100644 asmrigs/spec/brb.txt create mode 100644 asmrigs/spec/o.txt create mode 100644 asmrigs/tests/001.b create mode 100644 asmrigs/tests/002.b create mode 100644 asmrigs/tests/003.b create mode 100644 asmrigs/tests/004.b create mode 100644 asmrigs/tests/005.b create mode 100644 public/tier3/lexer.h diff --git a/asmrigs/brb/brb.h b/asmrigs/brb/brb.h new file mode 100644 index 0000000..63835ef --- /dev/null +++ b/asmrigs/brb/brb.h @@ -0,0 +1,27 @@ +#ifndef BRB_H +#define BRB_H + +#include "tier2/tokenizer.h" +#include "tier3/lexer.h" + +#define B_LEXEL_INTERFACE_NAME "BLexer001" + + +enum EBWordType +{ + BWORDTYPE_CONST_WORD, + + BWORDTYPE_FUNCTION, + BWORDTYPE_FUNCTION_ARGS, + BWORDTYPE_FUNCTION_ARG, + BWORDTYPE_FUNCTION_SCOPE, + + BWORDTYPE_RETURN, +}; + +abstract_class IBLexerWord: public ILexerWord +{ +public: +}; + +#endif diff --git a/asmrigs/brb/lexer.cpp b/asmrigs/brb/lexer.cpp new file mode 100644 index 0000000..d125233 --- /dev/null +++ b/asmrigs/brb/lexer.cpp @@ -0,0 +1,53 @@ +#include "brb.h" + +abstract_class CBLexerWord: public IBLexerWord +{ +public: + virtual int GetType() override; + + CUtlVector m_children; + EBWordType m_eType; +}; + +int CBLexerWord::GetType() +{ + return m_eType; +} + +uint32_t CBLexerWord::GetNumChildren() +{ + return m_children.GetSize(); +} + +ILexerWord **CBLexerWord::GetChildren() +{ + return m_children.GetData(); +} + + + +class CBLexer: public ILexer +{ +public: + virtual ILexerWord *ParseTokens( CUtlVector tokens ) override; + + CBLexerWord *ParseFunctionBody( Token_t *&pToken, const Token_t *pEnding ); + + bool GetExpectedToken(); + CUtlString GetStringLiteral(); +}; + +#define NEXT_TOKEN() \ +pToken++; \ +if (pToken == pEnding) \ + goto eof \ + +ILexerWord *CBLexer::ParseTokens( CUtlVector tokens ) +{ + Token_t *pCurrentToken = tokens.GetData(); + Token_t *pEndingToken = tokens.GetData() + tokens.GetSize(); + CBLexerWord *pGlobalWord = new CBLexerWord; + + + return pGlobalWord; +}; diff --git a/asmrigs/brb/main.cpp b/asmrigs/brb/main.cpp new file mode 100644 index 0000000..e82ec5d --- /dev/null +++ b/asmrigs/brb/main.cpp @@ -0,0 +1,19 @@ +#include "brb.h" +#include "tier0/commandline.h" +#include "tier2/ifilesystem.h" + + +int main( int argc, char **argv ) +{ + CommandLine()->CreateCommandLine(argc, argv); + + CreateInterfaceFn filesystemFactory = Sys_GetFactory("filesystem_std"); + filesystem = (IFileSystem*)filesystemFactory(FILESYSTEM_INTERFACE_VERSION, NULL); + + IFileHandle *pFile = filesystem->Open(argv[1], FILEMODE_READ); + const char *szFileContents = filesystem->ReadString(pFile); + filesystem->Close(pFile); + + + V_free((void*)szFileContents); +} diff --git a/asmrigs/build.cpp b/asmrigs/build.cpp new file mode 100644 index 0000000..b9d6e43 --- /dev/null +++ b/asmrigs/build.cpp @@ -0,0 +1,45 @@ +#include "c.h" +#include "ld.h" +#include "helper.h" + +ADD_DEPENDENCY_BUILD_FILE(tier0, "../tier0/build.cpp") +ADD_DEPENDENCY_BUILD_FILE(tier1, "../tier1/build.cpp") +ADD_DEPENDENCY_BUILD_FILE(tier2, "../tier2/build.cpp") +ADD_DEPENDENCY_BUILD_FILE(fs, "../stdfilesystems/build.cpp") + +DECLARE_BUILD_STAGE(brb) +{ + CProject_t stProject = {}; + LinkProject_t stLink = {}; + CUtlString szBuiltFile = {}; + + stProject.m_szName = "bc"; + stProject.files = { + "brb/lexer.cpp", + "brb/main.cpp", + }; + stProject.includeDirectories = { + "../public" + }; + + stLink = ccompiler->Compile(&stProject); + stLink.libraryObjects = { + GET_PROJECT_LIBRARY(tier0, "tier0"), + GET_PROJECT_LIBRARY(tier1, "tier1"), + GET_PROJECT_LIBRARY(tier2, "tier2"), + }; + szBuiltFile = linker->Link(&stLink); + ADD_OUTPUT_OBJECT("bc", szBuiltFile); + + return 0; +}; + +DECLARE_BUILD_STAGE(brb_install) +{ + CUtlString szBuildOutput = CUtlString("build/%s", Target_t::DefaultTarget().GetTriplet().GetString()); + filesystem2->MakeDirectory(szBuildOutput); + filesystem2->CopyFile(szBuildOutput, GET_PROJECT_OBJECT(brb, "bc")); + filesystem2->CopyFile(szBuildOutput, GET_PROJECT_LIBRARY(tier0, "tier0")); + filesystem2->CopyFile(szBuildOutput, GET_PROJECT_LIBRARY(filesystem_std, "fs")); + return 0; +} diff --git a/asmrigs/spec/brb.txt b/asmrigs/spec/brb.txt new file mode 100644 index 0000000..25c762c --- /dev/null +++ b/asmrigs/spec/brb.txt @@ -0,0 +1,26 @@ +Brick Rigs B is a programming language made to work in the game Brick Rigs + +1. The main issues of Brick Rigs + +There are multiple limitations that are present in Brick Rigs: + 1. Math Bricks are updated once per frame. It limits them to be one + time usage, which may cause some problems if you want to set the same + brick multiple times. + +To solve this issue we've developed multiple targets: + 1. Native Brick Rigs framed - allows to run code once per frame, + useful for missiles and custom built-logic. + 2. Native Brick Rigs stacked - splits the code into multiple + parts, which allows stack to occur at a cost of a single frame. + 3. Combat Advanced's virtual machine - it allows to run complex code by + using Combat Advanced's virtual machine + +There are multiple extensions for native Brick Rigs + 1. Combat Advanced's memory module + 2. Combat Advanced's trigonometry functions + +2. Syntaxis + +It can be seen in B user's guide + + diff --git a/asmrigs/spec/o.txt b/asmrigs/spec/o.txt new file mode 100644 index 0000000..d41cae7 --- /dev/null +++ b/asmrigs/spec/o.txt @@ -0,0 +1,42 @@ +Brick Rigs math vehicle object file specification v 1.0. + +1. Terminology +"byte" must be 1 byte long (uint8_t in C) +"word" must be 2 bytes long (uint16_t in C) +"int" must be 4 bytes long (uint16_t in C) + +2. Global header + +First comes global header which has following structure: + +struct +{ + byte magic[4]; + byte architecture[2]; + word symbols_number; +} + +Where: +magic must equal to 0x1 'B' 'M' 'O' +architecture is defined per implementation +symbols_number is the amount of symbols + +3. Symbols + +First comes the header: + +struct +{ + byte type; + int name_offset; + byte name_lenght; + int data_offset; + byte data_lenght; +} + +Where: +type is equal to 0x1 which defines function or 0x2 which defines variable +name_lenght is equal to the lenght of the name of the symbol + 1 +data_lenght is equal to the data lenght of the symbol + +After that comes the ASCII terminated by 0x0 set of lenght of name_lenght, which defined name of the symbol diff --git a/asmrigs/tests/001.b b/asmrigs/tests/001.b new file mode 100644 index 0000000..6dc375c --- /dev/null +++ b/asmrigs/tests/001.b @@ -0,0 +1,4 @@ +main() +{ + +} diff --git a/asmrigs/tests/002.b b/asmrigs/tests/002.b new file mode 100644 index 0000000..c3f9756 --- /dev/null +++ b/asmrigs/tests/002.b @@ -0,0 +1,4 @@ +main() +{ + return 0; +} diff --git a/asmrigs/tests/003.b b/asmrigs/tests/003.b new file mode 100644 index 0000000..37e8a38 --- /dev/null +++ b/asmrigs/tests/003.b @@ -0,0 +1,4 @@ +main() +{ + return 1 + 2 * 3 +} diff --git a/asmrigs/tests/004.b b/asmrigs/tests/004.b new file mode 100644 index 0000000..591b830 --- /dev/null +++ b/asmrigs/tests/004.b @@ -0,0 +1,7 @@ +main() +{ + auto a, b; + a = 10; + b = a + 5; + return b; +} diff --git a/asmrigs/tests/005.b b/asmrigs/tests/005.b new file mode 100644 index 0000000..d562b56 --- /dev/null +++ b/asmrigs/tests/005.b @@ -0,0 +1,9 @@ +add(a,b) +{ + return a + b; +} + +main() +{ + return add(2,3); +} diff --git a/fpc/library/clang/c.cpp b/fpc/library/clang/c.cpp index 5ff0d62..6dc1ae9 100644 --- a/fpc/library/clang/c.cpp +++ b/fpc/library/clang/c.cpp @@ -254,6 +254,8 @@ void CClangCompiler::GenerateLinterData() IJSONValue *pFileValue = JSONManager()->CreateValue(); IJSONArray *pArgumentFiles = JSONManager()->CreateArray(); IJSONValue *pArgumentsValue = JSONManager()->CreateValue(); + IJSONValue *pFileNameValue = JSONManager()->CreateValue(); + IJSONValue *pDirectoryValue = JSONManager()->CreateValue(); CUtlVector values; for (auto &arg: f.m_szArguments) @@ -264,7 +266,11 @@ void CClangCompiler::GenerateLinterData() } pArgumentFiles->SetArray(values.GetSize(), values.GetData()); pArgumentsValue->SetArrayValue(pArgumentFiles); + pFileNameValue->SetStringValue(f.m_szName.GetString()); + pDirectoryValue->SetStringValue(filesystem2->BuildDirectory()); pFileObject->SetValue("arguments", pArgumentsValue); + pFileObject->SetValue("file", pFileNameValue); + pFileObject->SetValue("directory", pDirectoryValue); pFileValue->SetObjectValue(pFileObject); jsonValues.AppendTail(pFileValue); }; @@ -273,6 +279,6 @@ void CClangCompiler::GenerateLinterData() IJSONValue *pRoot = JSONManager()->CreateValue(); pRoot->SetArrayValue(pArray); CUtlString szCommands = JSONManager()->WriteString(pRoot); - V_printf("JSON\n%s\n",szCommands.GetString()); + V_fprintf(f, szCommands.GetString()); V_fclose(f); }; diff --git a/public/tier1/utlstring.h b/public/tier1/utlstring.h index 66bba5e..fd07e94 100644 --- a/public/tier1/utlstring.h +++ b/public/tier1/utlstring.h @@ -122,6 +122,8 @@ inline void CUtlString::RemoveAt( size_t nPosition, size_t nCount ) inline CUtlString CUtlString::GetFileName() { CUtlString szFileName = GetString(); + if (GetLenght() == 0) + return ""; char *pLast = &m_data[GetLenght()-1]; while (pLast != m_data.GetData()) diff --git a/public/tier3/lexer.h b/public/tier3/lexer.h new file mode 100644 index 0000000..264cff1 --- /dev/null +++ b/public/tier3/lexer.h @@ -0,0 +1,18 @@ +#ifndef BRB_LEXER_H +#define BRB_LEXER_H + +#include "tier0/platform.h" + +abstract_class ILexerWord +{ +public: + virtual int GetType() = 0; +}; + +abstract_class ILexer +{ +public: + virtual ILexerWord *ParseTokens( CUtlVector tokens ) = 0; +}; + +#endif diff --git a/stdfilesystems/build.cpp b/stdfilesystems/build.cpp index e69de29..36f365d 100644 --- a/stdfilesystems/build.cpp +++ b/stdfilesystems/build.cpp @@ -0,0 +1,35 @@ +#include "helper.h" +#include "c.h" +#include "ld.h" +#include "tier1/utlstring.h" + +ADD_DEPENDENCY_BUILD_FILE(tier0, "../tier0/build.cpp") +ADD_DEPENDENCY_BUILD_FILE(tier1, "../tier1/build.cpp") + +CUtlVector fs_CompiledFiles = { + "filesystem_libc.cpp", +}; + +DECLARE_BUILD_STAGE(filesystem_std) +{ + CProject_t compileProject = {}; + LinkProject_t ldProject = {}; + CUtlString szOutputProject = ""; + + compileProject.m_szName = "filesystem_std"; + compileProject.files = fs_CompiledFiles; + compileProject.includeDirectories = {"../public"}; + compileProject.bFPIC = true; + ldProject = ccompiler->Compile(&compileProject); + + ldProject.linkType = ELINK_DYNAMIC_LIBRARY; + ldProject.libraryObjects = { + GET_PROJECT_LIBRARY(tier0, "tier0"), + GET_PROJECT_LIBRARY(tier1, "tier1"), + }; + szOutputProject = linker->Link(&ldProject); + + ADD_OUTPUT_OBJECT("fs", szOutputProject); + + return 0; +}; diff --git a/tier2/fileformats/json.cpp b/tier2/fileformats/json.cpp index 0502250..f183c4d 100644 --- a/tier2/fileformats/json.cpp +++ b/tier2/fileformats/json.cpp @@ -249,6 +249,7 @@ public: private: CUtlString RealWriteString( IJSONValue *pValue, uint32_t uOffest ); + CUtlString GetAsJsonString( CUtlString szString ); static bool ExpectedToken( Token_t &token, const char *szValue ); static CUtlString GetQuotedToken( Token_t &token ); @@ -308,7 +309,7 @@ CUtlString CJSONManager::GetQuotedToken( Token_t &token ) return NULL; } -IJSONObject *CJSONManager::ParseObject( Token_t *&pToken, const Token_t *pEnding ) +IJSONObject *CJSONManager::ParseObject( Token_t *&pToken, const Token_t *pEnding ) { IJSONObject *pObject; CUtlString szParamName; @@ -462,6 +463,37 @@ CUtlString CJSONManager::WriteString( IJSONValue *pValue ) { return RealWriteString(pValue, 0); } +CUtlString CJSONManager::GetAsJsonString( CUtlString szString ) +{ + CUtlString szOut = "\""; + for ( int i = 0; i < szString.GetLenght(); i++ ) + { + char c = szString[i]; + switch (c) + { + case '\"': + szOut.AppendTail("\\\""); + break; + case '\n': + szOut.AppendTail("\\n"); + break; + case '\r': + szOut.AppendTail("\\r"); + break; + case '\t': + szOut.AppendTail("\\t"); + break; + case '\\': + szOut.AppendTail("\\\\"); + break; + default: + szOut.AppendTail(c); + break; + } + }; + szOut.AppendTail("\""); + return szOut; +} CUtlString CJSONManager::RealWriteString( IJSONValue *pValue, uint32_t uOffset ) { @@ -478,9 +510,9 @@ CUtlString CJSONManager::RealWriteString( IJSONValue *pValue, uint32_t uOffset ) return "true"; return "false"; case JSON_PARAMETER_NUMBER: - return CUtlString("\"%f\"", pValue->GetNumberValue()); + return CUtlString("%f", pValue->GetNumberValue()); case JSON_PARAMETER_STRING: - return CUtlString("\"%s\"", pValue->GetStringValue()); + return GetAsJsonString(pValue->GetStringValue()); case JSON_PARAMETER_ARRAY: pArray = pValue->GetArray(); szString.AppendTail("[\n"); @@ -505,7 +537,7 @@ CUtlString CJSONManager::RealWriteString( IJSONValue *pValue, uint32_t uOffset ) for ( uint32_t j = 0; j <= uOffset; j++) szString.AppendTail("\t"); - szString.AppendTail(pObject->m_params[i].m_szName); + szString.AppendTail(GetAsJsonString(pObject->m_params[i].m_szName)); szString.AppendTail(": "); szString.AppendTail(RealWriteString( pObject->m_params[i].m_pValue, uOffset+1 ));