Phasor 3.1.1
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 output << sectionPrefixPragma;
95
96 output << sectionAttr << "volatile const size_t embeddedBytecodeSize = "
97 << serializedBytecode.size() << ";\n";
98
99 output << sectionAttr << "constexpr unsigned char embeddedBytecode[] = {\n";
100
101 for (size_t i = 0; i < serializedBytecode.size(); i++)
102 {
103 if (i % 16 == 0)
104 output << "\t";
105
106 output << "0x" << std::hex << std::setw(2) << std::setfill('0')
107 << static_cast<int>(serializedBytecode[i]);
108
109 if (i < serializedBytecode.size() - 1)
110 output << ",";
111
112 if (i % 16 == 15)
113 output << "\n";
114 else if (i < serializedBytecode.size() - 1)
115 output << " ";
116 }
117
118 output << std::dec << "\n};\n";
119}
120
121std::vector<unsigned char> CppCodeGenerator::parseEmbeddedBytecode(const std::string &input)
122{
123 std::vector<unsigned char> result;
124 std::istringstream stream(input);
125 std::string token;
126
127 while (stream >> token)
128 {
129 // Only process tokens starting with "0x"
130 if (token.size() >= 3 && token[0] == '0' && (token[1] == 'x' || token[1] == 'X'))
131 {
132 unsigned int byte;
133 std::istringstream hexStream(token);
134 hexStream >> std::hex >> byte;
135 result.push_back(static_cast<unsigned char>(byte));
136 }
137 }
138
139 return result;
140}
141
142std::string CppCodeGenerator::escapeString(const std::string &str)
143{
144 std::ostringstream escaped;
145 for (char c : str)
146 {
147 switch (c)
148 {
149 case '\\':
150 escaped << "\\\\";
151 break;
152 case '\"':
153 escaped << "\\\"";
154 break;
155 case '\n':
156 escaped << "\\n";
157 break;
158 case '\r':
159 escaped << "\\r";
160 break;
161 case '\t':
162 escaped << "\\t";
163 break;
164 default:
165 if (c >= 32 && c <= 126)
166 escaped << c;
167 else
168 escaped << "\\x" << std::hex << std::setw(2) << std::setfill('0')
169 << static_cast<int>(static_cast<unsigned char>(c));
170 break;
171 }
172 }
173 return escaped.str();
174}
175
177{
178 switch (type)
179 {
180 case ValueType::Null:
181 return "Null";
182 case ValueType::Bool:
183 return "Bool";
184 case ValueType::Int:
185 return "Int";
186 case ValueType::Float:
187 return "Float";
189 return "String";
190 default:
191 return "Unknown";
192 }
193}
194
195std::string CppCodeGenerator::sanitizeModuleName(const std::string &name)
196{
197 std::string result;
198 for (char c : name)
199 {
200 if (std::isalnum(c) || c == '_')
201 result += c;
202 else
203 result += '_';
204 }
205
206 // Ensure it starts with a letter or underscore
207 if (!result.empty() && std::isdigit(result[0]))
208 result = "_" + result;
209
210 return result.empty() ? "PhasorModule" : result;
211}
212
213} // 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.
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.
std::string escapeString(const std::string &str)
std::vector< unsigned char > parseEmbeddedBytecode(const std::string &input)
std::ostringstream output
Output stream for generated code.
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:11
ValueType
Runtime value types for the VM.
Definition Value.hpp:51
Complete bytecode structure.
Definition CodeGen.hpp:47