start implementing generate.cpp
authorJacob Lifshay <programmerjake@gmail.com>
Wed, 7 Jun 2017 09:33:02 +0000 (02:33 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Wed, 7 Jun 2017 09:33:02 +0000 (02:33 -0700)
src/generate_spirv_parser/CMakeLists.txt
src/generate_spirv_parser/generate.cpp [new file with mode: 0644]
src/generate_spirv_parser/generate.h [new file with mode: 0644]
src/generate_spirv_parser/generate_spirv_parser.cpp
src/spirv/CMakeLists.txt

index f55fd72d82e537df079cf669a5aac7185e44eb44..6ac1316a7e42fe64572ba4758dbe0f8c2a21cece 100644 (file)
@@ -20,6 +20,7 @@
 #
 cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
 set(sources ast.cpp
+            generate.cpp
             generate_spirv_parser.cpp
             parser.cpp) 
 add_executable(generate_spirv_parser ${sources})
diff --git a/src/generate_spirv_parser/generate.cpp b/src/generate_spirv_parser/generate.cpp
new file mode 100644 (file)
index 0000000..4b3f53d
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2017 Jacob Lifshay
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+#include "generate.h"
+
+namespace vulkan_cpu
+{
+namespace generate_spirv_parser
+{
+namespace generate
+{
+Generator::Generator_state::Generator_state(const Generator *generator,
+                                            Generator_args &generator_args)
+    : generator_args(generator_args),
+      indent_level(0),
+      full_output_file_name(generator_args.output_directory + "/"
+                            + generator->output_base_file_name),
+      os()
+{
+    os.exceptions(std::ios::badbit | std::ios::failbit);
+}
+
+void Generator::Generator_state::open_output_file()
+{
+    os.open(full_output_file_name);
+}
+
+constexpr Generator::Indent_t Generator::indent;
+
+void Generator::write_indent(Generator_state &state)
+{
+    static constexpr auto indent_string = "    ";
+    for(std::size_t i = state.indent_level; i > 0; i--)
+        state << indent_string;
+}
+
+void Generator::write_automatically_generated_file_warning(Generator_state &state)
+{
+    state << "/* This file is automatically generated by "
+             "generate_spirv_parser. DO NOT MODIFY. */\n";
+}
+
+void Generator::write_copyright_comment(Generator_state &state, const ast::Copyright &copyright)
+{
+    state << "/*\n";
+    for(auto &line : copyright.lines)
+    {
+        if(line.empty())
+        {
+            state << " *\n";
+            continue;
+        }
+        state << " * ";
+        bool was_last_star = false;
+        for(char ch : line)
+        {
+            if(was_last_star && ch == '/')
+                state << ' ';
+            was_last_star = (ch == '*');
+            state << ch;
+        }
+        state << "\n";
+    }
+    state << " */\n";
+}
+
+struct Spirv_header_generator final : public Generator
+{
+    Spirv_header_generator() : Generator("spirv.h")
+    {
+    }
+    virtual void run(Generator_args &generator_args, const ast::Top_level &top_level) const override
+    {
+        Generator_state state(this, generator_args);
+        state.open_output_file();
+        write_file_comments(state, top_level.copyright);
+#warning finish
+    }
+};
+
+std::unique_ptr<Generator> Generators::make_spirv_header_generator()
+{
+    return std::unique_ptr<Generator>(new Spirv_header_generator);
+}
+}
+}
+}
\ No newline at end of file
diff --git a/src/generate_spirv_parser/generate.h b/src/generate_spirv_parser/generate.h
new file mode 100644 (file)
index 0000000..1663bd2
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2017 Jacob Lifshay
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef GENERATE_SPIRV_PARSER_GENERATE_H_
+#define GENERATE_SPIRV_PARSER_GENERATE_H_
+
+#include "ast.h"
+#include <fstream>
+#include <memory>
+#include <string>
+#include <cassert>
+#include <type_traits>
+
+namespace vulkan_cpu
+{
+namespace generate_spirv_parser
+{
+namespace generate
+{
+class Generator
+{
+public:
+    struct Generator_args
+    {
+        std::string output_directory;
+        explicit Generator_args(std::string output_directory) noexcept
+            : output_directory(std::move(output_directory))
+        {
+        }
+        Generator_args(Generator_args &&) = default;
+        Generator_args &operator=(Generator_args &&) = default;
+        Generator_args(const Generator_args &) = delete;
+        Generator_args &operator=(const Generator_args &) = delete;
+    };
+
+protected:
+    struct Generator_state
+    {
+        Generator_args &generator_args;
+        std::size_t indent_level;
+        std::string full_output_file_name;
+        std::ofstream os;
+        explicit Generator_state(const Generator *generator, Generator_args &generator_args);
+        void open_output_file();
+        template <typename T, typename = decltype(os << std::declval<T>())>
+        Generator_state &operator<<(T &&v)
+        {
+            os << std::forward<T>(v);
+            return *this;
+        }
+    };
+    class Push_indent final
+    {
+        Push_indent(const Push_indent &) = delete;
+        Push_indent &operator=(const Push_indent &) = delete;
+
+    private:
+        Generator_state *state;
+
+    public:
+        explicit Push_indent(Generator_state &state) noexcept : state(&state)
+        {
+            state.indent_level++;
+        }
+        Push_indent(Push_indent &&rt) noexcept : state(rt.state)
+        {
+            rt.state = nullptr;
+        }
+        void finish() noexcept
+        {
+            assert(state);
+            state->indent_level--;
+            state = nullptr;
+        }
+        ~Push_indent()
+        {
+            if(state)
+                state->indent_level--;
+        }
+    };
+    struct Indent_t
+    {
+        explicit Indent_t() = default;
+        friend Generator_state &operator<<(Generator_state &state, Indent_t)
+        {
+            write_indent(state);
+            return state;
+        }
+    };
+    static constexpr Indent_t indent{};
+
+protected:
+    const char *const output_base_file_name;
+
+protected:
+    static void write_indent(Generator_state &state);
+    static void write_automatically_generated_file_warning(Generator_state &state);
+    static void write_copyright_comment(Generator_state &state, const ast::Copyright &copyright);
+    static void write_file_comments(Generator_state &state, const ast::Copyright &copyright)
+    {
+        write_automatically_generated_file_warning(state);
+        write_copyright_comment(state, copyright);
+    }
+
+public:
+    explicit Generator(const char *output_base_file_name) noexcept
+        : output_base_file_name(output_base_file_name)
+    {
+    }
+    virtual void run(Generator_args &generator_args, const ast::Top_level &top_level) const = 0;
+    void run(Generator_args &&generator_args, const ast::Top_level &top_level) const
+    {
+        run(generator_args, top_level);
+    }
+
+public:
+    virtual ~Generator() = default;
+};
+
+struct Spirv_header_generator;
+
+struct Generators
+{
+    static std::unique_ptr<Generator> make_spirv_header_generator();
+};
+}
+}
+}
+
+#endif /* GENERATE_SPIRV_PARSER_GENERATE_H_ */
\ No newline at end of file
index 01d014af9c5227562410c28ecb2ae33305a970a8..07d371e9d28fa4e7200863021809fdd7ba7237f2 100644 (file)
@@ -25,7 +25,7 @@
 #include "../json/parser.h"
 #include "parser.h"
 #include "../util/optional.h"
-#include <fstream>
+#include "generate.h"
 
 namespace vulkan_cpu
 {
@@ -34,11 +34,15 @@ namespace generate_spirv_parser
 int generate_spirv_parser_main(int argc, char **argv)
 {
     std::string file_name;
+    std::string output_directory;
     if(argc >= 2)
         file_name = argv[1];
-    if(argc != 2 || (file_name.size() > 1 && file_name[0] == '-'))
+    if(argc >= 3)
+        output_directory = argv[2];
+    if(argc != 3 || (file_name.size() > 1 && file_name[0] == '-')
+       || (output_directory.size() > 1 && output_directory[0] == '-'))
     {
-        std::cerr << "usage: " << argv[0] << " <input.json>" << std::endl;
+        std::cerr << "usage: " << argv[0] << " <input.json> <output-directory>" << std::endl;
         return 1;
     }
     try
@@ -49,18 +53,11 @@ int generate_spirv_parser_main(int argc, char **argv)
         {
             auto json_in = json::parse(&source);
             auto ast = parser::parse(json_in.duplicate());
-            std::ofstream os("out.json");
-            auto json_out = ast.to_json();
-            json::write(os, json_out, json::Write_options::pretty());
-            os.close();
-            auto difference = json::Difference::find_difference(json_in, json_out);
-            if(difference)
+            for(auto &generator : {
+                    generate::Generators::make_spirv_header_generator(),
+                })
             {
-                std::cerr << "differs at " << difference->append_to_string("root") << std::endl;
-            }
-            else
-            {
-                std::cerr << "no difference" << std::endl;
+                generator->run(generate::Generator::Generator_args(output_directory), ast);
             }
 #warning finish
             std::cerr << "generate_spirv_parser is not finished being implemented" << std::endl;
index 95efadecad691b89fd10c1bc2f3bddb5a862a699..4ea7ac20be18b469fd3d96938e374552fe20522f 100644 (file)
@@ -25,20 +25,21 @@ set(do_generate_spirv_parser YES)
 set(sources spirv.cpp)
 
 if(${do_generate_spirv_parser})
-    set(spirv_parser_generated_include_dir ${CMAKE_CURRENT_BINARY_DIR}/src)
+    set(spirv_parser_generated_include_dir ${CMAKE_CURRENT_BINARY_DIR}/generated)
     set(spirv_parser_generated_dir ${spirv_parser_generated_include_dir}/spirv)
-    set(spirv_parser_source ${spirv_parser_generated_dir}/parser.cpp)
-    set(spirv_parser_header ${spirv_parser_generated_dir}/parser.h)
+    set(spirv_parser_sources ${spirv_parser_generated_dir}/parser.cpp)
+    set(spirv_parser_headers ${spirv_parser_generated_dir}/parser.h ${spirv_parser_generated_dir}/spirv.h)
     set(spirv_core_grammar_json ${CMAKE_CURRENT_SOURCE_DIR}/../khronos-spirv/spirv.core.grammar.json)
+    message(STATUS "spirv_parser_generated_dir: " ${spirv_parser_generated_dir})
 
-    add_custom_command(OUTPUT ${spirv_parser_source} ${spirv_parser_header}
+    add_custom_command(OUTPUT ${spirv_parser_sources} ${spirv_parser_headers}
                        COMMAND ${CMAKE_COMMAND} -E make_directory ${spirv_parser_generated_dir}
-                       COMMAND ${CMAKE_COMMAND} -E chdir ${spirv_parser_generated_dir} $<TARGET_FILE:generate_spirv_parser> ${spirv_core_grammar_json}
+                       COMMAND ${CMAKE_COMMAND} -E chdir ${spirv_parser_generated_dir} $<TARGET_FILE:generate_spirv_parser> ${spirv_core_grammar_json} ${spirv_parser_generated_dir}
                        MAIN_DEPENDENCY ${spirv_core_grammar_json}
                        DEPENDS $<TARGET_FILE:generate_spirv_parser>
                        VERBATIM
                        COMMENT "Generating SPIR-V Parser")
-    set(sources ${sources} ${spirv_parser_source})
+    set(sources ${sources} ${spirv_parser_sources})
 endif()
 add_library(spirv STATIC ${sources})
 target_link_libraries(spirv util)