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 void WriteElements(TypeDecl decl, CodeWriter writer) { foreach (var declare in decl.Declare.Handlers) { var @return = "void"; var @params = string.Join(", ", declare.Params.Select(param => $"{GetType(param)} {param.Name.Underscore()}")); var function = $"{@return} {declare.Name.Underscore()}({@params})"; var comment = CommentHelper.FormatComment(declare.Comment); writer.AppendLines(comment); var implement = decl.Implement?.Handlers.FirstOrDefault(i => i.Name == declare.Name); // Abstract if (implement == null) { writer.AppendLine($"virtual {function} = 0;"); } // Override else if (implement.Override == YesNo.Y) { writer.AppendLine($"virtual {function} override;"); } // No modifiers. else { writer.AppendLine($"{function};"); } writer.AppendNewLineWithoutIndent(); } }
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 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("}"); }
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 void WriteElements(List <ElementDecl> elements, CodeWriter writer) { foreach (var element in elements) { var comment = CommentHelper.FormatComment(element.Comment); writer.AppendLines(comment); var type = GetType(element); writer.AppendLine($"{type} {element.Name.Underscore()};"); writer.AppendNewLineWithoutIndent(); } }
private static void WriteMethods(TypeDecl decl, CodeWriter writer) { bool HasImplement(HandlerDeclareItem declare) { return(decl.Implement?.Handlers.FirstOrDefault(t => t.Name == declare.Name) == null); } var declarations = decl.Declare.Handlers; foreach (var declare in declarations) { bool isAbstract = !HasImplement(declare); if (isAbstract) { writer.AppendLine("@abstractmethod"); } var parameters = ""; foreach (var parameter in declare.Params) { parameters += ($", {parameter.Name.Underscore()}: {GetTypeHint(decl, parameter)}"); } writer.AppendLine($"def {declare.Name.Underscore()}(self{parameters}):"); writer.PushIndent(); writer.AppendLines(CommentHelper.PyComment(declare.Comment)); writer.AppendLine(isAbstract ? "pass" : "raise NotImplemented"); if (declarations.IndexOf(declare) != declarations.Count - 1) { writer.AppendNewLineWithoutIndent(); } writer.PopIndent(); } }
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 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("};"); }
/// <summary> /// Generate python classes from declaration. /// </summary> public static string Build(TypeDecl decl, List <IDecl> declarations) { var writer = new CodeWriter(); string name = decl.Name; // Determine if we are inside datacentric package // based on module name. This affects the imports // and namespace use. bool insideDc = PyExtensions.GetPackage(decl) == "datacentric"; // If not generating for DataCentric package, use dc. namespace // in front of datacentric types, otherwise use no prefix string dcNamespacePrefix = insideDc ? "" : "dc."; PythonImportsBuilder.WriteImports(decl, declarations, writer); writer.AppendNewLineWithoutIndent(); writer.AppendNewLineWithoutIndent(); // Get base classes for current declaration List <string> bases = new List <string>(); if (decl.Keys.Any()) { bases.Add(dcNamespacePrefix + "Record"); } else if (decl.Inherit != null) { // Full package name and short namespace of the parent class, // or null if there is no parent bool parentClassInDifferentModule = !PyExtensions.IsPackageEquals(decl, decl.Inherit); string parentPackage = PyExtensions.GetPackage(decl.Inherit); string parentClassNamespacePrefix = parentClassInDifferentModule ? PyExtensions.GetAlias(parentPackage) + "." : ""; bases.Add(parentClassNamespacePrefix + decl.Inherit.Name); } else { bases.Add(dcNamespacePrefix + "Data"); } if (decl.Kind == TypeKind.Abstract) { bases.Add("ABC"); } // Python 3.8: // if (decl.Kind == TypeKind.Final) // writer.AppendLine("@final"); writer.AppendLine("@attr.s(slots=True, auto_attribs=True)"); writer.AppendLine($"class {name}({string.Join(", ", bases)}):"); writer.PushIndent(); writer.AppendLines(CommentHelper.PyComment(decl.Comment)); writer.AppendNewLineWithoutIndent(); if (!decl.Elements.Any()) { writer.AppendLine("pass"); } foreach (var element in decl.Elements) { // TODO: Should be replaced with callable with specific format instead of skipping string skipRepresentation = element.Vector == YesNo.Y ? ", repr=False" : ""; writer.AppendLine($"{element.Name.Underscore()}: {GetTypeHint(decl, element)} = attr.ib(default=None, kw_only=True{skipRepresentation}{GetMetaData(element)})"); writer.AppendLines(CommentHelper.PyComment(element.Comment)); if (element != decl.Elements.Last()) { writer.AppendNewLineWithoutIndent(); } } // Add to_key and create_key() methods if (decl.Keys.Any()) { var keyElements = decl.Elements.Where(e => decl.Keys.Contains(e.Name)).ToList(); writer.AppendNewLineWithoutIndent(); writer.AppendLine("def to_key(self) -> str:"); writer.PushIndent(); writer.AppendLine(CommentHelper.PyComment($"Get {decl.Name} key.")); writer.AppendLines($"return '{decl.Name}='{GetToKeyArgs(decl.Name, keyElements, true)}"); writer.PopIndent(); writer.AppendNewLineWithoutIndent(); var namedParams = keyElements.Select(e => $"{e.Name.Underscore()}: {GetTypeHint(decl, e)}").ToList(); var joinedNamedParams = string.Join(", ", namedParams); string start = "def create_key("; // Check if tokens should be separated by new line if (4 + start.Length + joinedNamedParams.Length > 120) { var indent = new string(' ', start.Length); joinedNamedParams = string.Join("," + Environment.NewLine + indent, namedParams); } writer.AppendLine("@classmethod"); writer.AppendLines($"def create_key(cls, *, {joinedNamedParams}) -> str:"); writer.PushIndent(); writer.AppendLine(CommentHelper.PyComment($"Create {decl.Name} key.")); writer.AppendLines($"return '{decl.Name}='{GetToKeyArgs(decl.Name, keyElements, false)}"); writer.PopIndent(); } if (decl.Declare != null) { writer.AppendNewLineWithoutIndent(); WriteMethods(decl, writer); } // Class end writer.PopIndent(); return(writer.ToString()); }
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; }}"); }
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("}"); }
/// <summary> /// Add import statements for given declaration. /// </summary> public static void WriteImports(TypeDecl decl, List <IDecl> declarations, CodeWriter writer) { // Always import attr module writer.AppendLine("import attr"); // Instant is generated as Union[dt.datetime, dc.Instant] thus dt import is required if (decl.Elements.Any(e => e.Value != null && (e.Value.Type == ValueParamType.Instant || e.Value.Type == ValueParamType.NullableInstant))) { writer.AppendLine("import datetime as dt"); } // If type is abstract - ABC import is needed if (decl.Kind == TypeKind.Abstract) { writer.AppendLine("from abc import ABC"); } // Check if ObjectId is used bool hasObjectId = decl.Elements.Any(e => e.Value != null && (e.Value.Type == ValueParamType.TemporalId || e.Value.Type == ValueParamType.NullableTemporalId)); if (hasObjectId) { writer.AppendLine("from bson import ObjectId"); } // Check imports from typing var typingImports = new List <string>(); // Python 3.8 // if (decl.Keys.Any() || decl.Kind == TypeKind.Final) // typingImports.Add("final"); if (decl.Elements.Any(e => e.Vector == YesNo.Y)) { typingImports.Add("List"); } if (typingImports.Any()) { var items = string.Join(", ", typingImports); writer.AppendLine($"from typing import {items}"); } bool insideDc = PyExtensions.GetPackage(decl) == "datacentric"; List <string> packagesToImport = new List <string>(); List <string> individualImports = new List <string>(); // Import parent class package as its namespace, or if inside the same package, // import individual class instead if (decl.Inherit != null) { if (PyExtensions.IsPackageEquals(decl, decl.Inherit)) { IDecl parentDecl = declarations.FindByKey(decl.Inherit); individualImports.Add($"from {parentDecl.Category} import {decl.Inherit.Name}"); } else { packagesToImport.Add(PyExtensions.GetPackage(decl.Inherit)); } } // Import datacentric package as dc, or if inside datacentric, // import individual classes instead else if (decl.IsRecord) { if (insideDc) { individualImports.Add("from datacentric.storage.record import Record"); } else { packagesToImport.Add("datacentric"); } } // First child class of Data else { if (insideDc) { individualImports.Add("from datacentric.storage.data import Data"); } else { packagesToImport.Add("datacentric"); } } foreach (var data in decl.Elements.Where(d => d.Data != null).Select(d => d.Data)) { if (PyExtensions.IsPackageEquals(decl, data)) { IDecl dataDecl = declarations.FindByKey(data); individualImports.Add($"from {dataDecl.Category} import {data.Name}"); } else { packagesToImport.Add(PyExtensions.GetPackage(data)); } } foreach (var enumElement in decl.Elements.Where(d => d.Enum != null).Select(d => d.Enum)) { if (PyExtensions.IsPackageEquals(decl, enumElement)) { IDecl enumDecl = declarations.FindByKey(enumElement); individualImports.Add($"from {enumDecl.Category} import {enumElement.Name}"); } else { packagesToImport.Add(PyExtensions.GetPackage(enumElement)); } } foreach (var package in packagesToImport.Distinct()) { writer.AppendLine($"import {package} as {PyExtensions.GetAlias(package)}"); } foreach (var import in individualImports.Distinct()) { writer.AppendLine(import); } }
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("}"); }