Example #1
0
        public static string BuildEnumHeader(EnumDecl decl, Dictionary <string, string> includePath)
        {
            var writer = new CodeWriter();

            var settings = GeneratorSettingsProvider.Get(decl.Module.ModuleName);

            writer.AppendLines(settings.Copyright);
            writer.AppendNewLineWithoutIndent();

            writer.AppendLine("#pragma once");
            writer.AppendNewLineWithoutIndent();

            // includes
            writer.AppendLine("#include <dot/system/enum.hpp>");
            // pure data

            writer.AppendNewLineWithoutIndent();

            writer.AppendLine($"namespace {settings.Namespace}");
            writer.AppendLine("{");
            writer.PushIndent();
            BuildEnumDeclaration(decl, writer);
            writer.PopIndent();
            writer.AppendLine("}");

            return(writer.ToString());
        }
        public static IEnumerable <string> ForKeyHeader(TypeDecl decl, Dictionary <string, string> declSet)
        {
            var settings = GeneratorSettingsProvider.Get(decl.Module.ModuleName);
            var includes = new List <string>
            {
                $"#include <{settings.Namespace}/declare.hpp>",
                "#include <dot/system/ptr.hpp>",
                "#include <dc/types/record/record.hpp>",
                $"#include <{declSet[decl.Name]}/{decl.Name.Underscore()}_data.hpp>"
            };

            // Include from field types
            includes.AddRange(decl.Elements.Where(t => t.Data != null)
                              .Select(t => t.Data.Name).Distinct()
                              .Select(t => $"#include <{declSet[t]}/{t.Underscore()}_data.hpp>"));
            includes.AddRange(decl.Elements.Where(t => t.Key != null)
                              .Select(t => t.Key.Name).Distinct()
                              .Select(t => $"#include <{declSet[t]}/{t.Underscore()}_key.hpp>"));

            var knownModules = GeneratorSettingsProvider.KnownModules();

            includes.AddRange(decl.Elements.Where(t => t.Enum != null)
                              // Skip external enum
                              .Where(t => knownModules.Contains(t.Enum.Module.ModuleName))
                              .Select(t => t.Enum.Name).Distinct()
                              .Select(t => $"#include <{declSet[t]}/{t.Underscore()}.hpp>"));

            return(includes);
        }
        public static string BuildDataSource(TypeDecl decl, Dictionary <string, string> declSet)
        {
            var writer = new CodeWriter();

            var settings = GeneratorSettingsProvider.Get(decl.Module.ModuleName);

            writer.AppendLines(settings.Copyright);
            writer.AppendNewLineWithoutIndent();

            writer.AppendLine($"#include <{settings.Namespace}/precompiled.hpp>");
            writer.AppendLine($"#include <{settings.Namespace}/implement.hpp>");
            writer.AppendLine($"#include <{declSet[decl.Name]}/{decl.Name.Underscore()}_data.hpp>");
            writer.AppendLine($"#include <dc/platform/context/context_base.hpp>");

            writer.AppendNewLineWithoutIndent();

            writer.AppendLine($"namespace {settings.Namespace}");
            writer.AppendLine("{");
            writer.PushIndent();
            BuildClassImplementation(decl, writer);
            writer.PopIndent();
            writer.AppendLine("}");

            return(writer.ToString());
        }
        public static string BuildDataHeader(TypeDecl decl, Dictionary <string, string> declSet)
        {
            var writer = new CodeWriter();

            var settings = GeneratorSettingsProvider.Get(decl.Module.ModuleName);

            writer.AppendLines(settings.Copyright);
            writer.AppendNewLineWithoutIndent();

            writer.AppendLine("#pragma once");
            writer.AppendNewLineWithoutIndent();

            // includes
            var includes = IncludesProvider.ForDataHeader(decl, declSet);

            foreach (string include in includes)
            {
                writer.AppendLine(include);
            }
            writer.AppendNewLineWithoutIndent();

            writer.AppendLine($"namespace {settings.Namespace}");
            writer.AppendLine("{");
            writer.PushIndent();
            BuildClassDeclaration(decl, writer);
            writer.PopIndent();
            writer.AppendLine("}");

            return(writer.ToString());
        }
        private static List <FileInfo> ConvertEnum(EnumDecl decl, Dictionary <string, string> includePath)
        {
            var    result     = new List <FileInfo>();
            var    settings   = GeneratorSettingsProvider.Get(decl.Module.ModuleName);
            string folderName = $"{settings.Namespace}.{decl.Category}".Underscore().Replace('.', '/');

            var enumHeader = new FileInfo
            {
                Content    = CppEnumBuilder.BuildEnumHeader(decl, includePath),
                FileName   = $"{decl.Name.Underscore()}.hpp",
                FolderName = folderName
            };

            result.Add(enumHeader);

            var enumSource = new FileInfo
            {
                Content    = CppEnumBuilder.BuildEnumSource(decl, includePath),
                FileName   = $"{decl.Name.Underscore()}.cpp",
                FolderName = folderName
            };

            result.Add(enumSource);

            return(result);
        }
Example #6
0
        private static void BuildClassImplementation(TypeDecl decl, CodeWriter writer)
        {
            var settings = GeneratorSettingsProvider.Get(decl.Module.ModuleName);
            var type     = decl.Name.Underscore();

            writer.AppendLine($"dot::type_t {type}_key_impl::type() {{ return typeof(); }}");
            writer.AppendLine($"dot::type_t {type}_key_impl::typeof()");

            writer.AppendLine("{");
            writer.PushIndent();

            writer.AppendLine("static dot::type_t type_ =");
            writer.PushIndent();

            writer.AppendLine($"dot::make_type_builder<self>(\"{settings.Namespace}\", \"{type}\")");
            var keyElements = decl.Elements.Where(e => decl.Keys.Contains(e.Name)).ToList();

            foreach (var element in keyElements)
            {
                var name = element.Name.Underscore();
                writer.AppendLine($"->with_field(\"{name}\", &self::{name})");
            }

            writer.AppendLine($"->template with_base<key<{type}_key_impl, {type}_data_impl>>()");
            writer.AppendLine($"->with_constructor(&make_{type}_key, {{  }})");
            writer.AppendLine("->build();");

            writer.PopIndent();
            writer.AppendLine("return type_;");

            writer.PopIndent();
            writer.AppendLine("}");
        }
        private static string GetIncludePath(IDecl decl)
        {
            var settings = GeneratorSettingsProvider.Get(decl.Module.ModuleName);

            // Avoid adding trailing path separator
            return(!string.IsNullOrEmpty(decl.Category) && !decl.Category.Equals(".")
                       ? $"{settings.Namespace}.{decl.Category}".Underscore().Replace('.', '/')
                       : $"{settings.Namespace}".Underscore().Replace('.', '/'));
        }
Example #8
0
        private static void BuildEnumImplementation(EnumDecl decl, CodeWriter writer)
        {
            var settings = GeneratorSettingsProvider.Get(decl.Module.ModuleName);
            var type     = decl.Name.Underscore();

            writer.AppendLines($@"{type}::operator dot::object() {{ return new dot::struct_wrapper_impl<self>(*this); }}
{type}::operator int() const {{ return value_; }}
{type}& {type}::operator=(int rhs) {{ value_ = rhs; return *this; }}
{type}& {type}::operator=(const self& other) {{ value_ = other.value_; return *this; }}
dot::type_t {type}::type() {{ return typeof(); }}");

            writer.AppendNewLineWithoutIndent();

            writer.AppendLines($@"dot::type_t {type}::typeof()
{{
    static dot::type_t type_ =
        dot::make_type_builder<self>(""{settings.Namespace}"", ""{type}"")
        ->is_enum()
        ->with_constructor(&self::make_self, {{}})
        ->with_base<enum_base>()
        ->build();
    return type_;
}}");

            writer.AppendNewLineWithoutIndent();

            writer.AppendLines($@"dot::dictionary<dot::string, int> {type}::get_enum_map()
{{
    static dot::dictionary<dot::string, int> enum_map_ = []()
    {{
        auto map_ = dot::make_dictionary<dot::string, int>();");
            // catching indents from prev verbatim get_enum_map block
            writer.PushIndent();
            writer.PushIndent();

            foreach (EnumItem item in decl.Items)
            {
                writer.AppendLine($"map_[\"{item.Name.Underscore()}\"] = {item.Name.Underscore()};");
            }

            writer.AppendLine("return map_;");
            writer.PopIndent();
            writer.AppendLine("}();");
            writer.AppendLine("return enum_map_;");
            writer.PopIndent();
            writer.AppendLine("}");
        }
Example #9
0
        public static string BuildEnumSource(EnumDecl decl, Dictionary <string, string> includePath)
        {
            var writer   = new CodeWriter();
            var settings = GeneratorSettingsProvider.Get(decl.Module.ModuleName);

            writer.AppendLines(settings.Copyright);
            writer.AppendNewLineWithoutIndent();

            writer.AppendLine($"#include <{settings.Namespace}/precompiled.hpp>");
            writer.AppendLine($"#include <{settings.Namespace}/implement.hpp>");
            writer.AppendLine($"#include <{includePath[decl.Name]}/{decl.Name.Underscore()}.hpp>");
            writer.AppendNewLineWithoutIndent();

            writer.AppendLine($"namespace {settings.Namespace}");
            writer.AppendLine("{");
            writer.PushIndent();
            BuildEnumImplementation(decl, writer);
            writer.PopIndent();
            writer.AppendLine("}");

            return(writer.ToString());
        }
        private static void BuildClassImplementation(TypeDecl decl, CodeWriter writer)
        {
            var  settings  = GeneratorSettingsProvider.Get(decl.Module.ModuleName);
            var  type      = decl.Name.Underscore();
            bool isRecord  = decl.Keys.Any();
            bool isDerived = decl.Inherit != null;

            writer.AppendLine($"dot::type_t {type}_data_impl::type() {{ return typeof(); }}");
            writer.AppendLine($"dot::type_t {type}_data_impl::typeof()");

            writer.AppendLine("{");
            writer.PushIndent();

            writer.AppendLine("static dot::type_t type_ =");
            writer.PushIndent();

            writer.AppendLine($"dot::make_type_builder<self>(\"{settings.Namespace}\", \"{type}\")");
            foreach (var element in decl.Elements)
            {
                var name = element.Name.Underscore();
                writer.AppendLine($"->with_field(\"{name}\", &self::{name})");
            }

            var baseType = isRecord ? $"record<{type}_key_impl, {type}_data_impl>" :
                           isDerived ? $"{decl.Inherit.Name.Underscore()}_data" :
                           "data";

            writer.AppendLine($"->template with_base<{baseType}>()");
            writer.AppendLine($"->with_constructor(&make_{type}_data, {{  }})");
            writer.AppendLine("->build();");

            writer.PopIndent();
            writer.AppendLine("return type_;");

            writer.PopIndent();
            writer.AppendLine("}");
        }
Example #11
0
        private static void BuildEnumDeclaration(EnumDecl decl, CodeWriter writer)
        {
            var settings = GeneratorSettingsProvider.Get(decl.Module.ModuleName);
            var type     = decl.Name.Underscore();

            writer.AppendNewLineWithoutIndent();

            writer.AppendLines(CommentHelper.FormatComment(decl.Comment));

            writer.AppendLine($"class {settings.DeclSpec} {type} : public dot::enum_base");
            writer.AppendLine("{");

            writer.PushIndent();
            writer.AppendLine($"typedef {type} self;");
            writer.PopIndent();
            writer.AppendNewLineWithoutIndent();

            var elements = decl.Items;

            writer.AppendLine("public:");
            writer.AppendNewLineWithoutIndent();
            writer.PushIndent();

            writer.AppendLine("enum enum_type {");
            writer.PushIndent();
            foreach (EnumItem item in elements)
            {
                writer.AppendLines(CommentHelper.FormatComment(item.Comment));
                writer.AppendLine($"{item.Name.Underscore()},");
                // Do not add new line after last item
                if (elements.IndexOf(item) != elements.Count - 1)
                {
                    writer.AppendNewLineWithoutIndent();
                }
            }

            writer.PopIndent();
            writer.AppendLine("};");
            writer.AppendNewLineWithoutIndent();
            writer.PopIndent();

            writer.AppendLines(@"private:
    static dot::object make_self() { return self(); }

public:
    typedef self element_type;
    typedef dot::struct_wrapper_impl<self>* pointer_type;
    using dot::enum_base::enum_base;

    operator dot::object();
    operator int() const;
    self& operator=(int rhs);
    self& operator=(const self& other);
    virtual dot::type_t type();
    static dot::type_t typeof();

protected:
    virtual dot::dictionary<dot::string, int> get_enum_map() override;");

            writer.AppendLine("};");
        }
        private static void BuildClassDeclaration(TypeDecl decl, CodeWriter writer)
        {
            var  settings  = GeneratorSettingsProvider.Get(decl.Module.ModuleName);
            var  type      = decl.Name.Underscore();
            bool isRecord  = decl.Keys.Any();
            bool isDerived = decl.Inherit != null;

            // Self-forward
            writer.AppendLine($"class {type}_data_impl; using {type}_data = dot::ptr<{type}_data_impl>;");
            if (isRecord)
            {
                writer.AppendLine($"class {type}_key_impl; using {type}_key = dot::ptr<{type}_key_impl>;");
            }

            // Get unique keys and data from elements
            var dataForwards = decl.Elements.Where(e => e.Data != null)
                               .Where(e => e.Data.Module.ModuleName == decl.Module.ModuleName)
                               .Select(e => $"{e.Data.Name.Underscore()}_data").ToList();

            var keysForwards = decl.Elements.Where(e => e.Key != null)
                               .Where(e => e.Key.Module.ModuleName == decl.Module.ModuleName)
                               .Select(e => $"{e.Key.Name.Underscore()}_key").ToList();

            var forwards = keysForwards.Union(dataForwards).Distinct();

            // Appends forwards
            foreach (var f in forwards)
            {
                writer.AppendLine($"class {f}_impl; using {f} = dot::ptr<{f}_impl>;");
            }
            writer.AppendNewLineWithoutIndent();

            writer.AppendLine($"inline {type}_data make_{type}_data();");
            writer.AppendNewLineWithoutIndent();

            writer.AppendLines(CommentHelper.FormatComment(decl.Comment));

            var baseType = isRecord ? $"record_impl<{type}_key_impl, {type}_data_impl>" :
                           isDerived    ? $"{decl.Inherit.Name.Underscore()}_data_impl" :
                           "data_impl";

            writer.AppendLine($"class {settings.DeclSpec} {type}_data_impl : public {baseType}");
            writer.AppendLine("{");

            writer.PushIndent();
            writer.AppendLine($"typedef {type}_data_impl self;");
            writer.AppendLine($"friend {type}_data make_{type}_data();");
            writer.PopIndent();
            writer.AppendNewLineWithoutIndent();

            writer.AppendLine("public: // FIELDS");
            writer.AppendNewLineWithoutIndent();

            var elements = decl.Elements;

            if (elements.Any())
            {
                writer.PushIndent();
                CppElementBuilder.WriteElements(decl.Elements, writer);
                writer.PopIndent();
            }

            if (decl.Declare != null)
            {
                writer.AppendLine("public: // METHODS");
                writer.AppendNewLineWithoutIndent();
                writer.PushIndent();
                CppMethodBuilder.WriteElements(decl, writer);
                writer.PopIndent();
            }

            writer.AppendLine("public:");
            writer.PushIndent();
            writer.AppendLine("virtual dot::type_t type();");
            writer.AppendLine("static dot::type_t typeof();");
            writer.PopIndent();

            writer.AppendLine("};");
            writer.AppendNewLineWithoutIndent();

            writer.AppendLine("/// Create an empty instance.");
            writer.AppendLine($"inline {type}_data make_{type}_data() {{ return new {type}_data_impl; }}");
        }