Phasor 3.3.0
Stack VM based Programming Language
Loading...
Searching...
No Matches
CppCodeGenerator.cpp
Go to the documentation of this file.
4#include <fstream>
5#include <iomanip>
6#include <sstream>
7
8namespace Phasor
9{
10
11bool CppCodeGenerator::generate(const Bytecode &bc, const std::filesystem::path &outputPath, const std::string &modName)
12{
13 try
14 {
15 bytecode = &bc;
16 output.str("");
17 output.clear();
18
19 // Determine module name
20 if (modName.empty())
21 {
22 moduleName = sanitizeModuleName(outputPath.stem().string());
23 }
24 else
25 {
27 }
28
29 // Serialize bytecode to binary format
30 BytecodeSerializer serializer;
31 serializedBytecode = serializer.serialize(bc);
32
33 // Generate header file with module name, bytecode, and size
37
38 // Write to file
39 std::ofstream file(outputPath);
40 if (!file.is_open())
41 {
42 return false;
43 }
44
45 file << output.str();
46 file.close();
47
48 return true;
49 }
50 catch (const std::exception &)
51 {
52 return false;
53 }
54}
55
57{
58 std::vector<unsigned char> bytecodeData = parseEmbeddedBytecode(input);
59 BytecodeDeserializer deserializer;
60 return deserializer.deserialize(bytecodeData);
61}
62
64{
65 output << "// Phasor VM Program\n";
66 output << "// Module: " << moduleName << "\n";
67 output << "#pragma once\n";
68 output << "#include <cstddef>\n";
69 output << "#include <string>\n\n";
70}
71
73{
74 output << "std::string moduleName = \"" << moduleName << "\";\n\n";
75}
76
78{
79#if defined(_WIN32)
80 const std::string sectionPrefixPragma = "#pragma section(\".phsb\", read)\n";
81 const std::string sectionAttr = "__declspec(allocate(\".phsb\")) ";
82#elif defined(__APPLE__)
83 const std::string sectionPrefixPragma = "";
84 const std::string sectionAttr = "__attribute__((section(\"__DATA,__phsb\"))) ";
85#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
86 const std::string sectionPrefixPragma = "";
87 const std::string sectionAttr = "__attribute__((section(\".phsb\"))) ";
88#else
89 const std::string sectionPrefixPragma = "";
90 const std::string sectionAttr = "";
91#endif
92
93 if (!sectionPrefixPragma.empty())
94 {
95 output << sectionPrefixPragma;
96 }
97
98 output << sectionAttr << "volatile const size_t embeddedBytecodeSize = " << serializedBytecode.size() << ";\n";
99
100 output << sectionAttr << "constexpr unsigned char embeddedBytecode[] = {\n";
101
102 for (size_t i = 0; i < serializedBytecode.size(); i++)
103 {
104 if (i % 16 == 0)
105 {
106 output << "\t";
107 }
108
109 output << "0x" << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(serializedBytecode[i]);
110
111 if (i < serializedBytecode.size() - 1)
112 {
113 output << ",";
114 }
115
116 if (i % 16 == 15)
117 {
118 output << "\n";
119 }
120 else if (i < serializedBytecode.size() - 1)
121 {
122 output << " ";
123 }
124 }
125
126 output << std::dec << "\n};\n";
127}
128
129std::vector<unsigned char> CppCodeGenerator::parseEmbeddedBytecode(const std::string &input)
130{
131 std::vector<unsigned char> result;
132 std::istringstream stream(input);
133 std::string token;
134
135 while (stream >> token)
136 {
137 // Only process tokens starting with "0x"
138 if (token.size() >= 3 && token[0] == '0' && (token[1] == 'x' || token[1] == 'X'))
139 {
140 unsigned int byte;
141 std::istringstream hexStream(token);
142 hexStream >> std::hex >> byte;
143 result.push_back(static_cast<unsigned char>(byte));
144 }
145 }
146
147 return result;
148}
149
150std::string CppCodeGenerator::escapeString(const std::string &str)
151{
152 std::ostringstream escaped;
153 for (char c : str)
154 {
155 switch (c)
156 {
157 case '\\':
158 escaped << "\\\\";
159 break;
160 case '\"':
161 escaped << "\\\"";
162 break;
163 case '\n':
164 escaped << "\\n";
165 break;
166 case '\r':
167 escaped << "\\r";
168 break;
169 case '\t':
170 escaped << "\\t";
171 break;
172 default:
173 if (c >= 32 && c <= 126)
174 {
175 escaped << c;
176 }
177 else
178 {
179 escaped << "\\x" << std::hex << std::setw(2) << std::setfill('0')
180 << static_cast<int>(static_cast<unsigned char>(c));
181 }
182 break;
183 }
184 }
185 return escaped.str();
186}
187
189{
190 switch (type)
191 {
192 case ValueType::Null:
193 return "Null";
194 case ValueType::Bool:
195 return "Bool";
196 case ValueType::Int:
197 return "Int";
198 case ValueType::Float:
199 return "Float";
201 return "String";
202 default:
203 return "Unknown";
204 }
205}
206
207std::string CppCodeGenerator::sanitizeModuleName(const std::string &name)
208{
209 std::string result;
210 for (char c : name)
211 {
212 if ((std::isalnum(c) != 0) || c == '_')
213 {
214 result += c;
215 }
216 else
217 {
218 result += '_';
219 }
220 }
221
222 // Ensure it starts with a letter or underscore
223 if (!result.empty() && (std::isdigit(result[0]) != 0))
224 {
225 result = "_" + result;
226 }
227
228 return result.empty() ? "PhasorModule" : result;
229}
230
231} // namespace Phasor
Bytecode binary format deserializer.
Bytecode deserialize(const std::vector< uint8_t > &data)
Deserialize bytecode from binary buffer.
Bytecode binary format serializer.
std::vector< uint8_t > serialize(const Bytecode &bytecode)
Serialize bytecode to binary buffer.
std::vector< uint8_t > serializedBytecode
Serialized bytecode in .phsb format.
static std::string getValueTypeString(ValueType type)
bool generate(const Bytecode &bytecode, const std::filesystem::path &outputPath, const std::string &moduleName="")
Generate C++ header file from bytecode.
static std::string escapeString(const std::string &str)
static std::vector< unsigned char > parseEmbeddedBytecode(const std::string &input)
std::ostringstream output
Output stream for generated code.
static std::string sanitizeModuleName(const std::string &name)
Bytecode generateBytecodeFromEmbedded(const std::string &input)
Generate Bytecode object from embedded bytecode string.
The Phasor Programming Language and Runtime.
Definition AST.hpp:12
ValueType
Runtime value types for the VM.
Definition Value.hpp:42
Complete bytecode structure.
Definition CodeGen.hpp:50