summaryrefslogtreecommitdiffstats
path: root/src/codegen.hpp
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2015-04-16 22:07:29 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2015-04-17 17:20:25 +0200
commit6c8cd11dad10587e5dde9ab7706384927b961bb6 (patch)
tree83df2371191ee2dea8ba2154ef538b91d38089ed /src/codegen.hpp
parentbb018683c93673679bb54b63c8aff43f507948de (diff)
downloadsolar-6c8cd11dad10587e5dde9ab7706384927b961bb6.tar
solar-6c8cd11dad10587e5dde9ab7706384927b961bb6.zip
Completely refactor code generation
Diffstat (limited to 'src/codegen.hpp')
-rw-r--r--src/codegen.hpp219
1 files changed, 219 insertions, 0 deletions
diff --git a/src/codegen.hpp b/src/codegen.hpp
new file mode 100644
index 0000000..7dbfd77
--- /dev/null
+++ b/src/codegen.hpp
@@ -0,0 +1,219 @@
+/*
+ Copyright (c) 2013-2015, Matthias Schiffer <mschiffer@universe-factory.net>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#pragma once
+
+#include <cstdio>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace solar {
+
+class nocopy_t {
+private:
+ nocopy_t(const nocopy_t &o) = delete;
+ nocopy_t(nocopy_t &&o) = delete;
+ nocopy_t & operator=(const nocopy_t &o) = delete;
+ nocopy_t & operator=(nocopy_t &&o) = delete;
+
+protected:
+ nocopy_t() {}
+};
+
+class codegen_t : private nocopy_t {
+public:
+ struct variable_t {
+ std::string str;
+ std::string name;
+
+
+ variable_t(const std::pair<std::string, std::string> &value, bool func = false) : str(value.first), name(value.second) {
+ if (!func) {
+ char last = str[str.length()-1];
+ if (last != '*' && last != '&')
+ str += ' ';
+
+ str += name;
+ }
+ }
+ };
+
+ struct function_t {
+ variable_t type_name;
+ std::vector<variable_t> args;
+
+ void add_arg(const std::pair<std::string, std::string> &value, bool func = false) {
+ args.emplace_back(value, func);
+ }
+
+ void add_arg(const std::string &str, const std::string &name, bool func = false) {
+ add_arg(std::make_pair(str, name), func);
+ }
+
+ function_t(const std::string &type, const std::string &name) : type_name({type + ' ' + name, name}, true) {}
+ };
+
+private:
+ FILE *file;
+ unsigned level;
+
+
+ template<typename... Args> void open_block(Args ...args) {
+ write_line(args..., " {");
+ level++;
+ }
+
+ template<typename... Args> void close_block(Args ...args) {
+ level--;
+ write_line("}", args...);
+ }
+
+
+ static void handle_arg(std::ostringstream *s, bool is_call, const variable_t &var) {
+ if (is_call)
+ *s << var.name;
+ else
+ *s << var.str;
+ }
+
+ static void handle_arg(std::ostringstream *s, bool is_call, const std::vector<variable_t> &vars) {
+ bool first = true;
+ for (const variable_t &var : vars) {
+ if (!first)
+ *s << ", ";
+
+ handle_arg(s, is_call, var);
+ first = false;
+ }
+ }
+
+ static void handle_arg(std::ostringstream *s, bool is_call, const function_t &f) {
+ handle_arg(s, is_call, f.type_name);
+
+ *s << "(";
+
+ if (f.args.empty() && !is_call)
+ *s << "void";
+ else
+ handle_arg(s, is_call, f.args);
+
+ *s << ")";
+ }
+
+ template<typename T> static void handle_arg(std::ostringstream *s, __attribute__((unused)) bool is_call, T arg) {
+ *s << arg;
+ }
+
+ static void handle_args(__attribute__((unused)) std::ostringstream *s, __attribute__((unused)) bool is_call) {
+ }
+
+ template<typename T, typename... Args> static void handle_args(std::ostringstream *s, bool is_call, T arg, Args ...args) {
+ handle_arg(s, is_call, arg);
+ handle_args(s, is_call, args...);
+ }
+
+ template<typename... Args> void write_offset(int offset, Args ...args) {
+ for (int i = 0; i < int(level) + offset; i++)
+ std::fputc('\t', file);
+
+ std::fputs(combine(args...).c_str(), file);
+ }
+
+ void write_line_offset(__attribute__((unused)) int offset) {
+ std::fputs("\n", file);
+ }
+
+ template<typename... Args> void write_line_offset(int offset, Args ...args) {
+ write_offset(offset, args..., "\n");
+ }
+
+public:
+ class block_t : private nocopy_t {
+ private:
+ codegen_t *codegen;
+ std::string close_string;
+
+ public:
+ template<typename... Args> block_t(codegen_t *codegen0, Args ...args) : codegen(codegen0) {
+ codegen->open_block(args...);
+ }
+
+ template<typename... Args> void close(Args ...args) {
+ close_string = combine(args...);
+ }
+
+ template<typename... Args> void close_(Args ...args) {
+ close(args..., ";");
+ }
+
+ ~block_t() {
+ codegen->close_block(close_string);
+ }
+ };
+
+ codegen_t(const char *filename);
+ ~codegen_t();
+
+ template<typename... Args> static std::string combine(Args ...args) {
+ std::ostringstream s;
+ handle_args(&s, false, args...);
+ return s.str();
+ }
+
+ template<typename... Args> static std::string call(Args ...args) {
+ std::ostringstream s;
+ handle_args(&s, true, args...);
+ return s.str();
+ }
+
+ template<typename... Args> void write_line(Args ...args) {
+ write_line_offset(0, args...);
+ }
+
+ template<typename... Args> void write_line_(Args ...args) {
+ write_line(args..., ";");
+ }
+
+ template<typename... Args> void _write_line(Args ...args) {
+ write_line_offset(1, args...);
+ }
+
+ template<typename... Args> void _write_line_(Args ...args) {
+ write_line_offset(1, args..., ";");
+ }
+
+ template<typename... Args> void write_case(Args ...args) {
+ write_line_offset(-1, "case ", args..., ":");
+ }
+
+ template<typename... Args> void write_default() {
+ write_line_offset(-1, "default:");
+ }
+};
+
+}