This repository was archived by the owner on Dec 8, 2022. It is now read-only.
Repository navigation
Expand file tree
/
Copy pathpycompile.hpp
More file actions
134 lines (108 loc) · 3.59 KB
/
Copy pathpycompile.hpp
File metadata and controls
134 lines (108 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//
// Created by imper on 7/31/22.
//
#ifndef METAPYTHON_PYCOMPILE_HPP
#define METAPYTHON_PYCOMPILE_HPP
#include <string>
#include <list>
#include "pyexec.hpp"
namespace py
{
class pycompile
{
public:
inline pycompile(const std::string& input_filename, const std::string& output_filename, std::ostream& log_stream)
: input_filename(input_filename), output_filename(output_filename), log_stream(log_stream) { }
/// Compiles all metacode in input_filename file and writes the output to output_filename
DECL_FUNCTION(inline void, compile, (PyCompilerFlags * flags = nullptr, int optimize = 2))
{
if (!check_files_extensions())
log_stream << get_current_time() << FN_SIGNATURE(compile)
<< " WARNING: File \"" << input_filename << "\" and/or \"" << output_filename
<< "\" has/have wierd extension(s)\n";
FILE* ifile = ::fopen(input_filename.c_str(), "rb");
if (!ifile)
{
log_stream << get_current_time() << FN_SIGNATURE(compile)
<< " ERROR: Can't open file \"" << input_filename << "\" for reading\n";
return;
}
FILE* ofile = ::fopen(output_filename.c_str(), "wb");
if (!ofile)
{
log_stream << get_current_time() << FN_SIGNATURE(compile)
<< " ERROR: Can't open file \"" << output_filename << "\" for writing\n";
return;
}
if (verbose_flag)
log_stream << get_current_time() << FN_SIGNATURE(compile)
<< " INFO: Parsing the file \"" << input_filename << "\"...\n";
std::list<char> quot_queue;
size_t zaminach_count = 0;
bool zaminach_area = false;
std::string metacode;
char c;
while (!::feof(ifile) && ::fread(&c, sizeof c, 1, ifile))
{
if (zaminach_area) metacode += c;
else ::fwrite(&c, sizeof c, 1, ofile);
if (c == '\'' || c == '"') // toggle string literals
{
if (quot_queue.empty())
quot_queue.push_back(c);
else if (quot_queue.back() == c)
quot_queue.pop_back();
}
if (c == '@' && quot_queue.empty()) // check for @@@ not in the string literal
++zaminach_count;
else zaminach_count = 0;
if (zaminach_count == 3)
{
if (!(zaminach_area = !zaminach_area)) // trigger once on ending zaminach
{
py::pyexec exec(log_stream);
metacode.pop_back();
metacode.pop_back();
metacode.pop_back();
std::string res = exec.execute(metacode.c_str(), flags, optimize);
if (verbose_flag)
log_stream << get_current_time() << FN_SIGNATURE(compile)
<< " INFO: Writing execution result into \"" << output_filename << "\"...\n";
::fwrite(res.c_str(), sizeof(char), res.size(), ofile);
}
else
{
::fflush(ofile);
struct stat st;
::stat(output_filename.c_str(), &st);
::ftruncate(ofile->_fileno, st.st_size - 3);
::fseek(ofile, -3, SEEK_CUR);
}
}
if (!zaminach_area) metacode.clear(); // clear string if not in zaminach area
}
::fclose(ifile);
::fclose(ofile);
}
inline ~pycompile() { }
inline bool check_files_extensions()
{
return extension_of(input_filename) == ".mpy" && // metapython extension
extension_of(output_filename) == ".py";
}
private:
std::string input_filename;
std::string output_filename;
std::ostream& log_stream;
#ifdef TEST
public:
#endif
inline static std::string extension_of(const std::string& filename)
{
size_t pos = filename.find_last_of('.');
if (pos == std::string::npos) return "";
else return filename.substr(pos);
}
};
}
#endif //METAPYTHON_PYCOMPILE_HPP