├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── VERSION ├── doc.go ├── docs ├── 404.html ├── CNAME ├── _config.yml ├── _includes │ ├── disqus.html │ ├── download.html │ ├── download.js │ ├── ga.js.temp │ ├── shared-deps.html │ ├── shared-footer.html │ ├── shared-header.html │ ├── toc-section.html │ ├── toc-section.js │ └── toc.html ├── _layouts │ ├── blog-home.html │ ├── default.html │ ├── dl.html │ └── post.html ├── api-cn.md ├── api.md ├── assets │ ├── css │ │ └── style.scss │ └── js │ │ └── platform.js ├── blog.md ├── downloads.md ├── index-cn.md └── index.md ├── extensions ├── README.md └── midc │ ├── codec │ ├── ext.json │ └── templates │ │ └── go │ │ ├── after_import.go.temp │ │ ├── after_protocol.go.temp │ │ ├── after_struct.go.temp │ │ ├── before_import.go.temp │ │ ├── decode.go.temp │ │ ├── decode │ │ ├── decode_array.go.temp │ │ ├── decode_bool.go.temp │ │ ├── decode_byte.go.temp │ │ ├── decode_int.go.temp │ │ ├── decode_int16.go.temp │ │ ├── decode_int32.go.temp │ │ ├── decode_int64.go.temp │ │ ├── decode_int8.go.temp │ │ ├── decode_map.go.temp │ │ ├── decode_string.go.temp │ │ ├── decode_struct.go.temp │ │ ├── decode_type.go.temp │ │ ├── decode_uint.go.temp │ │ ├── decode_uint16.go.temp │ │ ├── decode_uint32.go.temp │ │ ├── decode_uint64.go.temp │ │ ├── decode_uint8.go.temp │ │ └── decode_vector.go.temp │ │ ├── encode.go.temp │ │ ├── encode │ │ ├── encode_array.go.temp │ │ ├── encode_bool.go.temp │ │ ├── encode_byte.go.temp │ │ ├── encode_int.go.temp │ │ ├── encode_int16.go.temp │ │ ├── encode_int32.go.temp │ │ ├── encode_int64.go.temp │ │ ├── encode_int8.go.temp │ │ ├── encode_map.go.temp │ │ ├── encode_string.go.temp │ │ ├── encode_struct.go.temp │ │ ├── encode_type.go.temp │ │ ├── encode_uint.go.temp │ │ ├── encode_uint16.go.temp │ │ ├── encode_uint32.go.temp │ │ ├── encode_uint64.go.temp │ │ ├── encode_uint8.go.temp │ │ └── encode_vector.go.temp │ │ └── for_var.go.temp │ └── meta │ ├── ext.json │ └── templates │ ├── cpp │ ├── after_protocol.cpp.temp │ ├── after_struct.cpp.temp │ ├── protocol_front.h.temp │ └── struct_front.h.temp │ └── go │ ├── after_protocol.go.temp │ └── after_struct.go.temp ├── go.mod ├── go.sum ├── hack └── genmeta.sh ├── install.sh ├── languages.txt ├── midconfig ├── release.sh ├── src ├── cmd │ ├── mid-gen-cpp │ │ ├── main.go │ │ └── types.go │ ├── mid-gen-csharp │ │ ├── main.go │ │ └── types.go │ ├── mid-gen-go │ │ ├── main.go │ │ └── types.go │ ├── mid-gen-js │ │ ├── main.go │ │ └── types.go │ ├── mid-gen-protobuf │ │ ├── main.go │ │ └── types.go │ ├── mid-gen-ts │ │ ├── main.go │ │ └── types.go │ └── midc │ │ ├── config.go │ │ └── main.go ├── genutil │ ├── context.go │ ├── format.go │ ├── generator.go │ ├── template.go │ ├── types.go │ └── values.go └── mid │ ├── ast │ ├── ast.go │ └── scope.go │ ├── build │ ├── builder.go │ ├── extension.go │ ├── id_allocator.go │ ├── plugin.go │ ├── types.go │ └── types_test.go │ ├── external │ └── go │ │ └── scanner │ │ └── scanner.go │ ├── lexer │ ├── position.go │ └── token.go │ ├── meta.go │ ├── parser │ ├── helper.go │ ├── parser.go │ └── parser_test.go │ ├── scanner │ ├── scanner.go │ └── scanner_test.go │ └── syntax │ └── syntax.mid ├── templates ├── _common │ └── go │ │ ├── const.go.temp │ │ ├── enum.go.temp │ │ ├── fn_table_key.temp │ │ ├── fn_xorm.temp │ │ ├── head.go.temp │ │ ├── import.go.temp │ │ ├── package.sql.temp │ │ ├── protocol.go.temp │ │ ├── service.go.temp │ │ ├── storage_init.go.temp │ │ └── struct.go.temp ├── beans │ ├── cpp │ │ ├── const.h.temp │ │ ├── enum.h.temp │ │ ├── protocol.cpp.temp │ │ ├── protocol.h.temp │ │ ├── service.cpp.temp │ │ ├── service.h.temp │ │ ├── struct.cpp.temp │ │ └── struct.h.temp │ └── go │ │ ├── const.go.temp │ │ ├── enum.go.temp │ │ ├── protocol.go.temp │ │ ├── service.go.temp │ │ └── struct.go.temp ├── default │ ├── cpp │ │ ├── package.cpp.temp │ │ └── package.h.temp │ ├── go │ │ └── package.go.temp │ └── js │ │ └── package.js.temp ├── storage │ └── go │ │ ├── const.go.temp │ │ ├── enum.go.temp │ │ ├── package.go.init.temp │ │ ├── package.sql.temp │ │ ├── protocol.go.temp │ │ ├── service.go.temp │ │ └── struct.go.temp └── storage_onefile │ └── go │ ├── package.go.temp │ └── package.sql.temp ├── testdata ├── demo.mid ├── demo.sh └── main.go └── x ├── cpp ├── include │ └── mid │ │ ├── core │ │ └── std.h │ │ └── proto │ │ ├── decoder.h │ │ ├── encoder.h │ │ └── proto.h ├── proto │ ├── decoder.cpp │ ├── encoder.cpp │ └── proto.cpp └── tests │ ├── cbuild.json │ └── main.cpp └── go └── codec ├── codec.go ├── decoder.go ├── encoder.go ├── zcode_bench_test.go └── zcode_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | *.DS_Store 4 | src/cmd/midc/midc 5 | src/cmd/mid-gen-go/mid-gen-go 6 | src/cmd/mid-gen-cpp/mid-gen-cpp 7 | src/cmd/mid-gen-js/mid-gen-js 8 | src/cmd/mid-gen-protobuf/mid-gen-protobuf 9 | testdata/generated/ 10 | targets/ 11 | x/go/storage/example/demo/ 12 | 13 | docs/_site/ 14 | docs/.sass-cache/ 15 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Change log 2 | ========== 3 | 4 | ## Head 5 | 6 | ## v0.1.3 (2018-08-25) 7 | 8 | * Fix docs 9 | * Fix APIs 10 | * Add `js` generator 11 | 12 | ## v0.1.2 (2016-12-12) 13 | 14 | * Add extension `meta` and `proto` 15 | * Add template `beans/cpp` 16 | * Add `deps` in Extension 17 | * Add embedded positions `*_front` and `*_back` 18 | * Fix template `default/cpp` 19 | * Add docs directory 20 | 21 | ## v0.1.1 (2016-12-03) 22 | 23 | * Fix templates `default` for go 24 | * Add supporting `extension` 25 | * Fix compiler `midc` 26 | * Add generator `gencpp` 27 | 28 | ## v0.1 (2016-11-22) 29 | 30 | * Add `Context` for templates which used for generator 31 | * Add builtin templates `default` and `beans` 32 | * Add compiler `midc` and generator `gengo` 33 | * Add midlang builder 34 | * Add midlang lexer,ast,parser 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2016 midlang 2 | 3 |   Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | software and associated documentation files (the "Software"), to deal in the Software 5 | without restriction, including without limitation the rights to use, copy, modify, 6 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so, subject to the following 8 | conditions: 9 |    10 |   The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 14 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 15 | PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 16 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 17 | OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 18 | OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | midlang 2 | ======= 3 | ``` 4 | ___ ___ ___ ___ ___ ___ ___ 5 | /\__\ /\ \ /\ \ /\__\ /\ \ /\__\ /\ \ 6 | /::L_L_ _\:\ \ /::\ \ /:/ / /::\ \ /:| _|_ /::\ \ 7 | /:/L:\__\ /\/::\__\ /:/\:\__\ /:/__/ /::\:\__\ /::|/\__\ /:/\:\__\ 8 | \/_/:/ / \::/\/__/ \:\/:/ / \:\ \ \/\::/ / \/|::/ / \:\:\/__/ 9 | /:/ / \:\__\ \::/ / \:\__\ /:/ / |:/ / \::/ / 10 | \/__/ \/__/ \/__/ \/__/ \/__/ \/__/ \/__/ 11 | ``` 12 | 13 | * [x] [English](https://midlang.org) 14 | * [x] [中文](https://midlang.org/cn) 15 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.1.11 2 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | package mid 2 | 3 | // The aim of the first stage is to implement a Domain-specific language,but have some differences. 4 | // 5 | // The code generated by midlang is highly customizable. Use templates to generate code, even documents. 6 | // midlang was committed to eradicating boring and tedious code which can be generated, not just as a data interchange format. 7 | // The compiler midc compile midlang source code to an AST, and then you can visit the AST in template file. 8 | // 9 | // https://midlang.org/#whats-midlang 10 | -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | notoc: true 4 | --- 5 | 6 | 27 | 28 |
29 |
404
30 | 31 | Page not found 32 |
33 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | midlang.org -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman 2 | permalink: /:categories/:title:output_ext 3 | 4 | google_analytics: 'UA-77412491-2' 5 | 6 | email: i@mkideal.com 7 | facebook_username: mkideal.io 8 | twitter_username: mkideal 9 | wechat_id: mkideal 10 | github_username: mkideal 11 | 12 | markdown: kramdown 13 | kramdown: 14 | syntax_highlighter_opts: 15 | span: 16 | line_numbers: false 17 | block: 18 | line_numbers: true 19 | 20 | mid_versions: 21 | - "0.1.3" 22 | - "0.1.2" 23 | - "0.1.1" 24 | - "0.1" 25 | 26 | plugins: 27 | - jemoji 28 | -------------------------------------------------------------------------------- /docs/_includes/disqus.html: -------------------------------------------------------------------------------- 1 | {% if site.disqus_username %} 2 |
3 |
4 | 19 | 21 | 22 |
23 | 24 | {% endif %} 25 | -------------------------------------------------------------------------------- /docs/_includes/download.html: -------------------------------------------------------------------------------- 1 |
2 | 11 | 19 | 32 | 36 |
37 | -------------------------------------------------------------------------------- /docs/_includes/download.js: -------------------------------------------------------------------------------- 1 | 2 | $('.ui.dropdown').dropdown(); 3 | 4 | function active_selection(menu, text) { 5 | $(menu + " .menu").children(".item").each(function() { 6 | var value = $(this).text(); 7 | if (text === value) { 8 | $(this).addClass("active selected"); 9 | $(menu + " .text").html($(this).html()); 10 | } else { 11 | $(this).removeClass("active selected"); 12 | } 13 | }); 14 | } 15 | var current_os = platform.os.family; 16 | if (current_os == "OS X") { 17 | active_selection("#os-selection", "macOS"); 18 | } else if (current_os == "Windows") { 19 | active_selection("#os-selection", "windows"); 20 | } 21 | var current_arch = platform.os.architecture; 22 | if (current_arch == 32) { 23 | active_selection("#arch-selection", "32 bit"); 24 | } 25 | 26 | $('#download-button').click(function() { 27 | var os = "linux"; 28 | var arch = "64 bit"; 29 | var version = ""; 30 | var suffix = ".tar.gz"; 31 | $("#os-selection .menu").children(".selected").each(function() { 32 | os = $(this).text(); 33 | }); 34 | $("#arch-selection .menu").children(".selected").each(function() { 35 | arch = $(this).text(); 36 | }); 37 | $("#version-selection .menu").children(".selected").each(function() { 38 | version = $(this).text(); 39 | }); 40 | if (os === "macOS") { 41 | os = "darwin"; 42 | } 43 | if (os === "windows") { 44 | suffix = ".zip"; 45 | } 46 | if (arch === "32 bit") { 47 | arch = "386"; 48 | } else if (arch === "64 bit") { 49 | arch = "amd64"; 50 | } 51 | version = version.replace(/^v/, ''); 52 | var addr = "https://github.com/midlang/mid/releases/download/"; 53 | addr += "v" + version + "/mid" + version + "." + os + "-" + arch + suffix; 54 | console.log("address: " + addr); 55 | window.location.href = addr; 56 | }); 57 | -------------------------------------------------------------------------------- /docs/_includes/ga.js.temp: -------------------------------------------------------------------------------- 1 | {% if site.google_analytics %} 2 | 21 | {% endif %} 22 | -------------------------------------------------------------------------------- /docs/_includes/shared-deps.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | {% if site.google_ad_client %} 11 | 12 | 18 | {% endif %} 19 | -------------------------------------------------------------------------------- /docs/_includes/shared-footer.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
 4 | {% if site.email %}E-mail:   {{ site.email }}{% endif %}
 5 | {% if site.facebook_username %}Facebook: {{ site.facebook_username }}{% endif %}
 6 | {% if site.twitter_username %}Twitter:  {{ site.twitter_username }}{% endif %}
 7 | {% if site.github_username %}Github:   {{ site.github_username }}{% endif %}
 8 | {% if site.wechat_id %}WeChat:   {{ site.wechat_id }}{% endif %}
9 |
10 |
11 | -------------------------------------------------------------------------------- /docs/_includes/shared-header.html: -------------------------------------------------------------------------------- 1 | Docs 2 | API 3 | Blog 4 | Download 5 | 6 |
7 |
8 | Star 9 | Fork 10 | -------------------------------------------------------------------------------- /docs/_includes/toc-section.html: -------------------------------------------------------------------------------- 1 | {% unless page.notoc %} 2 |
3 |
4 | 5 |
6 |

7 | Contents 8 | 9 | 10 | 11 |

12 |
13 |
14 | {% include toc.html html=content h_min=2 h_max=4 %} 15 |
16 |
17 |
18 | {% endunless %} 19 | -------------------------------------------------------------------------------- /docs/_includes/toc-section.js: -------------------------------------------------------------------------------- 1 | {% unless page.notoc %} 2 | 3 | function toccheckboxChanged(e) { 4 | //console.log("toccheckboxChanged"); 5 | if (e.is(':checked')) { 6 | $('.toccontent').hide(); 7 | } else { 8 | $('.toccontent').show(); 9 | } 10 | } 11 | 12 | function tocMarkupHelper(ul, deeps) { 13 | var count = 0; 14 | ul.children("li").each(function() { 15 | count++; 16 | var li = $(this); 17 | deeps.push(count); 18 | li.children("a").each(function() { 19 | var a = $(this); 20 | var prepended = '' + deeps.join(".") + ''; 21 | a.html(prepended + "  " + a.html()); 22 | }); 23 | li.children("ul").each(function() { 24 | tocMarkupHelper($(this), deeps.slice()); 25 | }); 26 | deeps.pop(); 27 | }); 28 | } 29 | 30 | $(".toccontent").children("ul").each(function() { 31 | $(this).css("padding-left", 0); 32 | tocMarkupHelper($(this), []); 33 | }); 34 | 35 | /* 36 | $('.overlay').visibility({ 37 | type: 'fixed', 38 | offset: 20, 39 | onTopVisible: function(calculations) { 40 | console.log("onTopVisible"); 41 | // 如果原来是隐藏状态则改为显示 42 | var e = $('#toctogglecheckbox'); 43 | if (e.is(':checked')) { 44 | e.prop("checked", false); 45 | toccheckboxChanged(e); 46 | } 47 | }, 48 | onTopVisibleReverse: function(calculations) { 49 | console.log("onTopVisibleReverse"); 50 | }, 51 | onTopPassedReverse: function(calculations) { 52 | console.log("onTopPassedReverse"); 53 | }, 54 | onTopPassed: function(calculations) { 55 | console.log("onTopPassed"); 56 | }, 57 | onBottomVisible: function(calculations) { 58 | console.log("onBottomVisible"); 59 | }, 60 | onBottomVisibleReverse: function(calculations) { 61 | console.log("onBottomVisibleReverse"); 62 | }, 63 | onBottomPassedReverse: function(calculations) { 64 | console.log("onBottomPassedReverse"); 65 | }, 66 | onBottomPassed: function(calculations) { 67 | console.log("onBottomPassed"); 68 | // 如果原来是显示状态则改为隐藏 69 | var e = $('#toctogglecheckbox'); 70 | if (!e.is(':checked')) { 71 | e.prop("checked", true); 72 | toccheckboxChanged(e); 73 | } 74 | }, 75 | onPassingReverse: function(calculations) { 76 | console.log("onPassingReverse"); 77 | }, 78 | onPassing: function(calculations) { 79 | console.log("onPassing"); 80 | // 如果原来是显示状态则改为隐藏 81 | var e = $('#toctogglecheckbox'); 82 | if (!e.is(':checked')) { 83 | e.prop("checked", true); 84 | toccheckboxChanged(e); 85 | } 86 | }, 87 | }); 88 | */ 89 | 90 | $('#toctogglecheckbox').change(function() { 91 | toccheckboxChanged($(this)); 92 | }); 93 | 94 | $('.main-content h2').each(function() { 95 | var e = $(this); 96 | e.html('§ ' + e.html()); 97 | }); 98 | $('.main-content h5').each(function() { 99 | var e = $(this); 100 | e.html(' ' + e.html()); 101 | }); 102 | 103 | {% endunless %} 104 | -------------------------------------------------------------------------------- /docs/_includes/toc.html: -------------------------------------------------------------------------------- 1 | {% capture tocWorkspace %} 2 | {% comment %} 3 | Version 1.0.5 4 | https://github.com/allejo/jekyll-toc 5 | 6 | "...like all things liquid - where there's a will, and ~36 hours to spare, there's usually a/some way" ~jaybe 7 | 8 | Usage: 9 | {% include toc.html html=content sanitize=true class="inline_toc" id="my_toc" h_min=2 h_max=3 %} 10 | 11 | Parameters: 12 | * html (string) - the HTML of compiled markdown generated by kramdown in Jekyll 13 | 14 | Optional Parameters: 15 | * sanitize (bool) : false - when set to true, the headers will be stripped of any HTML in the TOC 16 | * class (string) : '' - a CSS class assigned to the TOC 17 | * id (string) : '' - an ID to assigned to the TOC 18 | * h_min (int) : 1 - the minimum TOC header level to use; any header lower than this value will be ignored 19 | * h_max (int) : 6 - the maximum TOC header level to use; any header greater than this value will be ignored 20 | * ordered (bool) : false - when set to true, an ordered list will be outputted instead of an unordered list 21 | * item_class (string) : '' - add custom class for each list item; has support for '%level%' placeholder, which is the current heading level 22 | * baseurl (string) : '' - add a base url to the TOC links for when your TOC is on another page than the actual content 23 | 24 | Output: 25 | An ordered or unordered list representing the table of contents of a markdown block. This snippet will only generate the table of contents and will NOT output the markdown given to it 26 | {% endcomment %} 27 | 28 | {% capture my_toc %}{% endcapture %} 29 | {% assign orderedList = include.ordered | default: false %} 30 | {% assign minHeader = include.h_min | default: 1 %} 31 | {% assign maxHeader = include.h_max | default: 6 %} 32 | {% assign nodes = include.html | split: ' maxHeader %} 45 | {% continue %} 46 | {% endif %} 47 | 48 | {% if firstHeader %} 49 | {% assign firstHeader = false %} 50 | {% assign minHeader = headerLevel %} 51 | {% endif %} 52 | 53 | {% assign indentAmount = headerLevel | minus: minHeader | add: 1 %} 54 | {% assign _workspace = node | split: '' | first }}>{% endcapture %} 61 | {% assign header = _workspace[0] | replace: _hAttrToStrip, '' %} 62 | 63 | {% assign space = '' %} 64 | {% for i in (1..indentAmount) %} 65 | {% assign space = space | prepend: ' ' %} 66 | {% endfor %} 67 | 68 | {% unless include.item_class == blank %} 69 | {% capture listItemClass %}{:.{{ include.item_class | replace: '%level%', headerLevel }}}{% endcapture %} 70 | {% endunless %} 71 | 72 | {% capture my_toc %}{{ my_toc }} 73 | {{ space }}{{ listModifier }} {{ listItemClass }} [{% if include.sanitize %}{{ header | strip_html }}{% else %}{{ header }}{% endif %}]({% if include.baseurl %}{{ include.baseurl }}{% endif %}#{{ html_id }}){% endcapture %} 74 | {% endfor %} 75 | 76 | {% if include.class %} 77 | {% capture my_toc %}{:.{{ include.class }}} 78 | {{ my_toc | lstrip }}{% endcapture %} 79 | {% endif %} 80 | 81 | {% if include.id %} 82 | {% capture my_toc %}{: #{{ include.id }}} 83 | {{ my_toc | lstrip }}{% endcapture %} 84 | {% endif %} 85 | {% endcapture %}{% assign tocWorkspace = '' %}{{ my_toc | markdownify | strip }} -------------------------------------------------------------------------------- /docs/_layouts/blog-home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% seo %} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% include shared-deps.html %} 16 | 17 | 18 | 19 | 22 | 23 |
24 |

{{ page.title }}

25 | {{ content }} 26 | 27 | 30 |
31 | 32 | 39 | 40 | {% include ga.js.temp %} 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /docs/_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% seo %} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% include shared-deps.html %} 16 | 17 | 18 | 19 | 22 | 23 |
24 |

{{ page.title }}

25 | {% include toc-section.html %} 26 | 27 |
28 | {{ content }} 29 |
30 | 31 | 34 |
35 | 36 | 49 | 50 | {% include ga.js.temp %} 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /docs/_layouts/dl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% seo %} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% include shared-deps.html %} 16 | 17 | 18 | 19 | 22 | 23 |
24 |

{{ page.title }}

25 | 26 | {% include download.html %} 27 | 28 | {% include toc-section.html %} 29 | 30 |
31 | {{ content }} 32 |
33 | 34 | 37 |
38 | 39 | 52 | 53 | {% include ga.js.temp %} 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /docs/_layouts/post.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% seo %} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% include shared-deps.html %} 16 | 17 | 18 | 19 | 22 | 23 |
24 |

{{ page.title }}

25 |

26 | {{ page.date | date: "%Y/%m/%d %H:%M" }} 27 | {% if page.previous.url %} 28 | Prev 29 | {% endif %} 30 | {% if page.next.url %} 31 | Next 32 | {% endif %} 33 |

34 | 35 | {% include toc-section.html %} 36 | 37 |
38 | {{ content }} 39 |
40 | 41 | 51 | 52 | 55 |
56 | 57 | 68 | 69 | {% include ga.js.temp %} 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /docs/blog.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: blog-home 3 | date: 2018-08-19 14:52:50 +0800 4 | title: Blog 5 | permalink: /blog 6 | --- 7 | 8 | ## Blog 9 | -------------------------------------------------------------------------------- /docs/downloads.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: dl 3 | date: 2016-12-03T17:49:57+08:00 4 | title: Downloads 5 | permalink: /dl 6 | --- 7 | 8 | {% for version in site.mid_versions %} 9 | {% if version == site.mid_versions[0] %} 10 | ## Latest version: v{{ version }} 11 | {% else %} 12 | {% if version == site.mid_versions[1] %} 13 | ## Older versions 14 | 15 | {% endif %} 16 | ### v{{ version }} 17 | {% endif %} 18 | ##### Linux 19 | * [mid{{ version }}.linux-386.tar.gz](https://github.com/midlang/mid/releases/download/v{{ version }}/mid{{ version }}.linux-386.tar.gz) 20 | * [mid{{ version }}.linux-amd64.tar.gz](https://github.com/midlang/mid/releases/download/v{{ version }}/mid{{ version }}.linux-amd64.tar.gz) 21 | 22 | ##### Mac OS 23 | * [mid{{ version }}.darwin-386.tar.gz](https://github.com/midlang/mid/releases/download/v{{ version }}/mid{{ version }}.darwin-386.tar.gz) 24 | * [mid{{ version }}.darwin-amd64.tar.gz](https://github.com/midlang/mid/releases/download/v{{ version }}/mid{{ version }}.darwin-amd64.tar.gz) 25 | 26 | ##### Windows 27 | * [mid{{ version }}.windows-386.zip](https://github.com/midlang/mid/releases/download/v{{ version }}/mid{{ version }}.windows-386.zip) 28 | * [mid{{ version }}.windows-amd64.zip](https://github.com/midlang/mid/releases/download/v{{ version }}/mid{{ version }}.windows-amd64.zip) 29 | 30 | ##### Source code 31 | * [mid{{ version }}.source.zip](https://github.com/midlang/mid/archive/v0.1.1.zip) 32 | * [mid{{ version }}.source.tar.gz](https://github.com/midlang/mid/archive/v0.1.1.tar.gz) 33 | {% endfor %} 34 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | date: 2016-12-03 18:11:54 +0800 4 | title: Docs 5 | permalink: / 6 | --- 7 | 8 | 中文 9 | 10 | Go to [API documentation](/api) 。 11 | 12 | ## What's midlang? 13 | 14 | The aim of the first stage is to implement a [Domain-specific language][dsl],but have some differences. 15 | 16 | 1. The code generated by [midlang][midlang-github] is highly customizable. Use templates to generate code, even documents. 17 | 2. `midlang` was committed to eradicating boring and tedious code which can be generated, not just as a data interchange format. 18 | 19 | The compiler `midc` compile midlang source code to an AST, and then you can visit the AST in template file. 20 | 21 | Here is an example template file (`package.go.temp`\): 22 | 23 | {% raw %} 24 | ``` 25 | package {{.Name}} 26 | 27 | {{define "T_const"}} 28 | {{.Doc}}const ( 29 | {{range $field := .Consts}}{{$field.Name}} = {{$field.ValueString}} 30 | {{end}} 31 | ) 32 | {{end}} 33 | 34 | {{define "T_enum"}} 35 | {{$type := .Name}} 36 | type {{$type}} int 37 | 38 | {{.Doc}}const ( 39 | {{range $field := .Fields}}{{$type}}_{{$field.Name}} = {{$field.Value}}{{$field.Comment}} 40 | {{end}} 41 | ) 42 | {{end}} 43 | 44 | {{define "T_struct"}} 45 | {{$type := .Name}} 46 | {{.Doc}}type {{$type}} struct { 47 | {{range $field := .Fields}}{{$field.Name | title}} {{context.BuildType $field.Type}}{{$field.Comment}} 48 | {{end}} 49 | } 50 | {{end}} 51 | 52 | {{define "T_protocol"}} 53 | {{template "T_struct" .}} 54 | {{end}} 55 | 56 | {{define "T_service"}} 57 | {{$type := .Name}} 58 | {{.Doc}}type {{$type}} interface { 59 | {{range $field := .Fields}}{{$field.Name | title}} {{context.BuildType $field.Type}}{{$field.Comment}} 60 | {{end}} 61 | } 62 | {{end}} 63 | 64 | {{.GenerateDeclsBySubTemplates}} 65 | ``` 66 | {% endraw %} 67 | 68 | The following will be devoted to writing a document on how to use template in midlang. 69 | 70 | Mainly includes the following points: 71 | 72 | - template filename form: \\[.suffix\][.flags].temp 73 | - kind maybe `package`,`file`,`const` and other bean kinds like `struct`,`protocol`,`service` etc. 74 | - struct.go.temp -> (struct, go) 75 | - struct.h.temp -> (struct, h) 76 | - struct.cpp.temp -> (struct, cpp) 77 | - struct.cpp.1.temp -> (struct, cpp) 78 | - template kind `package`: each package as a data be applied to the template file 79 | - template kind `file`: each source file as a data be applied to the template file 80 | - template kind `const`: each constant group as a data be applied to the template file 81 | - template kind `enum`: each enum type as a data be applied to the template file 82 | - template kind `struct`: each struct as a data be applied to the template file 83 | - template kind `protocol`: each protocol as a data be applied to the template file 84 | - template kind `service`: each service as a data be applied to the template file 85 | - template can use some builtin functions, e.g. `context`,`include`,`include_template`,`osenv` and many utility string functions.(all these functions are defined in `mid/src/tools/generator/generator.go`\) 86 | - The `context` function returns a object `Context` which has fields `Pkg`, `Plugin`, `Config` and methods `BuildType`, `Env`, `FindBean` etc. 87 | 88 | See [builtin templates](https://github.com/midlang/mid/tree/master/templates) 89 | 90 | ## Install 91 | 92 | ### Install from source 93 | 94 | ```sh 95 | go get github.com/midlang/mid 96 | cd /path/to/mid # replace `/path/to/mid` with your actual directory 97 | ./install.sh 98 | ``` 99 | 100 | ### Install from binary package 101 | 102 | Download and install 103 | 104 |
105 | {% include download.html %} 106 |
107 | 108 | ```sh 109 | tar zcf .tar.gz 110 | cd 111 | 112 | # install to /usr/local/ 113 | sudo ./install.sh 114 | 115 | # or install to other directory, e.g. user directory 116 | # PREFIX=$HOME ./install.sh 117 | ``` 118 | 119 | ## Getting started 120 | 121 | ### Write a source file `demo.mid` 122 | 123 | ``` 124 | /** 125 | * package declaration must has a `;` 126 | */ 127 | package demo; 128 | 129 | // constants 130 | const ( 131 | A = 1; 132 | B = 2; 133 | ) 134 | 135 | // doc: status 136 | // Status 137 | enum Status { 138 | Ok = 0, // ok 139 | Bad = 1, // bad 140 | } 141 | 142 | struct User { 143 | int64 id; 144 | string name; 145 | vector otherNames; 146 | array code; 147 | } 148 | 149 | protocol UserList { 150 | map users; 151 | } 152 | 153 | service UserService { 154 | sayHello() 155 | getUsers() UserList 156 | findUser(int64 uid) User 157 | delUser(int64) Status 158 | } 159 | 160 | struct Info extends User { 161 | string desc; 162 | map>>> xxx; 163 | } 164 | ``` 165 | 166 | ### Compile and generate codes 167 | 168 | ```sh 169 | midc -I demo.mid -Ogo=generated/go 170 | # Or 171 | # midc -I demo.mid -Ogo=generated/go -K default 172 | ``` 173 | 174 | Try `midc -h` to get help information of compiler `midc` 175 | 176 | Try this: 177 | 178 | ```sh 179 | midc -I demo.mid -Ogo=generated/go -K beans 180 | ``` 181 | 182 | ## Language plugins 183 | 184 | Midlang language plugin used to generate code for the program language 185 | 186 | Here are all builtin plugins: 187 | 188 | - gengo - golang plugin 189 | - gencpp - c++ plugin 190 | 191 | You can write yourself plugin instead of using builtin plugin. 192 | 193 | ## Templates 194 | 195 | Templates used to generate codes. You can use option `-T=` to specify templates for specified language, also you can use option `-K ` to specify template kind(default template kind is default). 196 | 197 | Builtin template kinds: `default`, `beans` 198 | 199 | ## Plugin for editor 200 | 201 | - vim-mid - [https://github.com/midlang/vim-mid](https://github.com/midlang/vim-mid) 202 | - mid-sublime - [https://github.com/midlang/mid-sublime](https://github.com/midlang/mid-sublime) 203 | 204 | ## TODO 205 | 206 | - Other generators: [go][go],[java][java],[rust][rust],[swift][swift],[python][python],[javascript][javascript],... 207 | - More builtin extensions 208 | - Build documents 209 | 210 | [go]: https://golang.org/ "Go" 211 | [java]: https://www.java.com/ "Java" 212 | [rust]: https://www.rust-lang.org/ "Rust" 213 | [swift]: https://developer.apple.com/swift/ "Swift" 214 | [python]: https://www.python.org/ "Python" 215 | [javascript]: https://www.javascript.com/ "Javascript" 216 | [dsl]: https://en.wikipedia.org/wiki/Domain-specific_language "DSL" 217 | [midlang-github]: https://github.com/midlang/mid "mid" 218 | -------------------------------------------------------------------------------- /extensions/README.md: -------------------------------------------------------------------------------- 1 | Extension 2 | ========= 3 | -------------------------------------------------------------------------------- /extensions/midc/codec/ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "at": { 3 | "cpp": {}, 4 | "go": { 5 | "after_import": [ 6 | { 7 | "kinds": [ 8 | "package", 9 | "struct", 10 | "protocol", 11 | "service" 12 | ], 13 | "template": "go/after_import.go.temp" 14 | } 15 | ], 16 | "after_protocol": [ 17 | { 18 | "template": "go/after_protocol.go.temp" 19 | }, 20 | { 21 | "template": "go/encode.go.temp" 22 | }, 23 | { 24 | "template": "go/decode.go.temp" 25 | } 26 | ], 27 | "after_struct": [ 28 | { 29 | "template": "go/after_struct.go.temp" 30 | }, 31 | { 32 | "template": "go/encode.go.temp" 33 | }, 34 | { 35 | "template": "go/decode.go.temp" 36 | } 37 | ], 38 | "before_import": [ 39 | { 40 | "kinds": [ 41 | "package", 42 | "struct", 43 | "protocol", 44 | "service" 45 | ], 46 | "template": "go/before_import.go.temp" 47 | } 48 | ] 49 | } 50 | }, 51 | "author": "midc", 52 | "name": "codec", 53 | "version": "0.1" 54 | } 55 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/after_import.go.temp: -------------------------------------------------------------------------------- 1 | var _ = codec.Unused 2 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/after_protocol.go.temp: -------------------------------------------------------------------------------- 1 | 2 | func (x {{.Name}}) MessageName() string { 3 | return "{{.Name}}" 4 | } 5 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/after_struct.go.temp: -------------------------------------------------------------------------------- 1 | 2 | func (x {{.Name}}) MessageName() string { 3 | return "{{.Name}}" 4 | } 5 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/before_import.go.temp: -------------------------------------------------------------------------------- 1 | import "github.com/midlang/mid/x/go/codec" 2 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-05 23:29 3 | author: mkideal 4 | --- 5 | 6 | {{- $bean := .}} 7 | func (x *{{.Name}}) Decode(r codec.Reader) error { 8 | {{- $flag := newBool}} 9 | {{- range $field := .Fields}} 10 | {{$type := $field.Type}} 11 | {{- if OR ($type.IsMap) ($type.IsArray) ($type.IsVector)}} 12 | {{- if not $flag.Get}} 13 | var length int 14 | {{- $flag.Set true}} 15 | {{- end}} 16 | {{- end}} 17 | {{- end}} 18 | {{- range $field := .Extends}} 19 | {{- $varName := join "" "x." (context.BuildType $field)}} 20 | {{- $dep := newInt}} 21 | {{- include_template (joinPath (pwd) "decode/decode_type.go.temp") (slice $varName $field $dep)}} 22 | {{- end}} 23 | {{- range $field := .Fields}} 24 | {{- $varName := join "" "x." (title $field.Name)}} 25 | {{- $dep := newInt}} 26 | {{- include_template (joinPath (pwd) "decode/decode_type.go.temp") (slice $varName $field.Type $dep)}} 27 | {{- end}} 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_array.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 13:50 3 | author: mkideal 4 | category: array 5 | --- 6 | 7 | {{- $fieldVar := valueAt . 0}} 8 | {{- $type := valueAt . 1}} 9 | {{- $dep := valueAt . 2}} 10 | 11 | {{- $length := newString}} 12 | {{- $forVar := newString}} 13 | {{- include_template (joinPath (pwd) "../for_var.go.temp") (slice $dep $forVar)}} 14 | {{- $i := $forVar.Get}} 15 | {{- if eq $dep.Get 0}} 16 | {{- $length.Set "length"}} 17 | {{$length}} = len({{$fieldVar}}) 18 | {{- else}} 19 | {{- $length.Set (join "" "length" $dep.String)}} 20 | {{$length}} := len({{$fieldVar}}) 21 | {{- end}} 22 | {{- $newDep := newInt}} 23 | {{- $newDep.Set ($dep.Add 1)}} 24 | for {{$i}} := 0; {{$i}} < {{$length}}; {{$i}}++ { 25 | {{- $varName := join "" $fieldVar "[" $i "]"}} 26 | {{- include_template (joinPath (pwd) "decode_type.go.temp") (slice $varName $type.T $newDep)}} 27 | } 28 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_bool.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 13:30 3 | author: mkideal 4 | category: bool 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | if v, _, err := codec.Dec.DecodeBool(r); err != nil { 9 | return err 10 | } else { 11 | {{$fieldVar}} = v 12 | } 13 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_byte.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 13:33 3 | author: mkideal 4 | category: byte 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | if v, _, err := codec.Dec.DecodeUint8(r); err != nil { 9 | return err 10 | } else { 11 | {{$fieldVar}} = v 12 | } 13 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_int.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 13:35 3 | author: mkideal 4 | category: int 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- $fsuffix := newString}} 9 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 10 | {{$fsuffix.Set "f"}} 11 | {{- else}} 12 | {{$fsuffix.Set "v"}} 13 | {{- end}} 14 | if v, _, err := codec.Dec.DecodeInt64{{$fsuffix.Get}}(r); err != nil { 15 | return err 16 | } else { 17 | {{$fieldVar}} = int(v) 18 | } 19 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_int16.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 13:38 3 | author: mkideal 4 | category: int16 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- $fsuffix := newString}} 9 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 10 | {{$fsuffix.Set "f"}} 11 | {{- else}} 12 | {{$fsuffix.Set "v"}} 13 | {{- end}} 14 | if v, _, err := codec.Dec.DecodeInt16{{$fsuffix.Get}}(r); err != nil { 15 | return err 16 | } else { 17 | {{$fieldVar}} = v 18 | } 19 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_int32.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 13:40 3 | author: mkideal 4 | category: int32 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- $fsuffix := newString}} 9 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 10 | {{$fsuffix.Set "f"}} 11 | {{- else}} 12 | {{$fsuffix.Set "v"}} 13 | {{- end}} 14 | if v, _, err := codec.Dec.DecodeInt32{{$fsuffix.Get}}(r); err != nil { 15 | return err 16 | } else { 17 | {{$fieldVar}} = v 18 | } 19 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_int64.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 13:35 3 | author: mkideal 4 | category: int64 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- $fsuffix := newString}} 9 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 10 | {{$fsuffix.Set "f"}} 11 | {{- else}} 12 | {{$fsuffix.Set "v"}} 13 | {{- end}} 14 | if v, _, err := codec.Dec.DecodeInt64{{$fsuffix.Get}}(r); err != nil { 15 | return err 16 | } else { 17 | {{$fieldVar}} = v 18 | } 19 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_int8.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 13:35 3 | author: mkideal 4 | category: int 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | if v, _, err := codec.Dec.DecodeInt8(r); err != nil { 9 | return err 10 | } else { 11 | {{$fieldVar}} = v 12 | } 13 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_map.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 14:25 3 | author: mkideal 4 | category: map 5 | --- 6 | 7 | {{- $fieldVar := valueAt . 0}} 8 | {{- $type := valueAt . 1}} 9 | {{- $dep := valueAt . 2}} 10 | 11 | {{- $length := newString}} 12 | {{- $forVar := newString}} 13 | {{- include_template (joinPath (pwd) "../for_var.go.temp") (slice $dep $forVar)}} 14 | {{- $i := $forVar.Get}} 15 | {{- if eq $dep.Get 0}} 16 | {{- $length.Set "length"}} 17 | {{- else}} 18 | {{- $length.Set (join "" "length" $dep.String)}} 19 | var {{$length}} int 20 | {{- end}} 21 | 22 | {{- $fsuffix := newString}} 23 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 24 | {{$fsuffix.Set "f"}} 25 | {{- else}} 26 | {{$fsuffix.Set "v"}} 27 | {{- end}} 28 | 29 | if v, _, err := codec.Dec.DecodeUint32{{$fsuffix.Get}}(r); err != nil { 30 | return err 31 | } else { 32 | {{$length}} = int(v) 33 | } 34 | if {{$length}} < 0 { 35 | return codec.ErrNegativeLength 36 | } 37 | 38 | {{- $keyType := context.BuildType $type.K}} 39 | {{- $valueType := context.BuildType $type.V}} 40 | {{ $fieldVar }} = make(map[{{$keyType}}]{{$valueType}}) 41 | 42 | {{- $forVar := newString}} 43 | {{- include_template (joinPath (pwd) "../for_var.go.temp") (slice $dep $forVar)}} 44 | {{- $i := $forVar.Get}} 45 | {{- $key := newString}} 46 | {{- $value := newString}} 47 | {{- if eq ($dep.Get) 0}} 48 | {{$key.Set "key"}} 49 | {{$value.Set "value"}} 50 | {{- else}} 51 | {{- $key.Set (join "" "key" $dep.String)}} 52 | {{- $value.Set (join "" "value" $dep.String)}} 53 | {{- end}} 54 | {{- $newDep := newInt}} 55 | {{- $newDep.Set ($dep.Add 1)}} 56 | 57 | for {{$i}} := 0; {{$i}} < {{$length}}; {{$i}}++ { 58 | var {{$key.Get}} {{$keyType}} 59 | var {{$value.Get}} {{$valueType}} 60 | {{- include_template (joinPath (pwd) "decode_type.go.temp") (slice ($key.Get) $type.K $newDep)}} 61 | {{- include_template (joinPath (pwd) "decode_type.go.temp") (slice ($value.Get) $type.V $newDep)}} 62 | {{$fieldVar}}[{{$key.Get}}] = {{$value.Get}} 63 | } 64 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_string.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 14:23 3 | author: mkideal 4 | category: string 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | if v, _, err := codec.Dec.DecodeString(r); err != nil { 9 | return err 10 | } else { 11 | {{$fieldVar}} = v 12 | } 13 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_struct.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 14:43 3 | author: mkideal 4 | category: struct 5 | --- 6 | 7 | {{- $fieldVar := valueAt . 0 }} 8 | {{- $type := valueAt . 1}} 9 | if err := {{$fieldVar}}.Decode(r); err != nil { 10 | return err 11 | } 12 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_type.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 13:23 3 | author: mkideal 4 | --- 5 | {{- $fieldVar := valueAt . 0}} 6 | {{- $type := valueAt . 1}} 7 | {{- $dep := valueAt . 2}} 8 | {{- $fieldType := context.BuildType $type | lastOf "."}} 9 | {{- $tempDir := "."}} 10 | {{- if eq $fieldType "int"}}{{ include_template (joinPath (pwd) $tempDir "decode_int.go.temp") $fieldVar }} 11 | {{- else if eq $fieldType "int8"}}{{ include_template (joinPath (pwd) $tempDir "decode_int8.go.temp") $fieldVar }} 12 | {{- else if eq $fieldType "int16"}}{{ include_template (joinPath (pwd) $tempDir "decode_int16.go.temp") $fieldVar }} 13 | {{- else if eq $fieldType "int32"}}{{ include_template (joinPath (pwd) $tempDir "decode_int32.go.temp") $fieldVar }} 14 | {{- else if eq $fieldType "int64"}}{{ include_template (joinPath (pwd) $tempDir "decode_int64.go.temp") $fieldVar }} 15 | {{- else if eq $fieldType "uint"}}{{ include_template (joinPath (pwd) $tempDir "decode_uint.go.temp") $fieldVar }} 16 | {{- else if eq $fieldType "uint8"}}{{ include_template (joinPath (pwd) $tempDir "decode_uint8.go.temp") $fieldVar }} 17 | {{- else if eq $fieldType "uint16"}}{{ include_template (joinPath (pwd) $tempDir "decode_uint16.go.temp") $fieldVar }} 18 | {{- else if eq $fieldType "uint32"}}{{ include_template (joinPath (pwd) $tempDir "decode_uint32.go.temp") $fieldVar }} 19 | {{- else if eq $fieldType "uint64"}}{{ include_template (joinPath (pwd) $tempDir "decode_uint64.go.temp") $fieldVar }} 20 | {{- else if eq $fieldType "byte"}}{{ include_template (joinPath (pwd) $tempDir "decode_byte.go.temp") $fieldVar }} 21 | {{- else if eq $fieldType "bool"}}{{ include_template (joinPath (pwd) $tempDir "decode_bool.go.temp") $fieldVar }} 22 | {{- else if eq $fieldType "string"}}{{ include_template (joinPath (pwd) $tempDir "decode_string.go.temp") $fieldVar }} 23 | {{- else if $type.IsArray}}{{ include_template (joinPath (pwd) $tempDir "decode_array.go.temp") (slice $fieldVar $type $dep)}} 24 | {{- else if $type.IsVector}}{{ include_template (joinPath (pwd) $tempDir "decode_vector.go.temp") (slice $fieldVar $type $dep)}} 25 | {{- else if $type.IsMap}}{{ include_template (joinPath (pwd) $tempDir "decode_map.go.temp") (slice $fieldVar $type $dep)}} 26 | {{- else if $type.IsStruct}}{{ include_template (joinPath (pwd) $tempDir "decode_struct.go.temp") (slice $fieldVar $type)}} 27 | {{- end}} 28 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_uint.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 13:47 3 | author: mkideal 4 | category: uint 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- $fsuffix := newString}} 9 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 10 | {{$fsuffix.Set "f"}} 11 | {{- else}} 12 | {{$fsuffix.Set "v"}} 13 | {{- end}} 14 | if v, _, err := codec.Dec.DecodeUint64{{$fsuffix.Get}}(r); err != nil { 15 | return err 16 | } else { 17 | {{$fieldVar}} = uint(v) 18 | } 19 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_uint16.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 13:47 3 | author: mkideal 4 | category: uint16 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- $fsuffix := newString}} 9 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 10 | {{$fsuffix.Set "f"}} 11 | {{- else}} 12 | {{$fsuffix.Set "v"}} 13 | {{- end}} 14 | if v, _, err := codec.Dec.DecodeUint16{{$fsuffix.Get}}(r); err != nil { 15 | return err 16 | } else { 17 | {{$fieldVar}} = v 18 | } 19 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_uint32.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 13:48 3 | author: mkideal 4 | category: uint32 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- $fsuffix := newString}} 9 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 10 | {{$fsuffix.Set "f"}} 11 | {{- else}} 12 | {{$fsuffix.Set "v"}} 13 | {{- end}} 14 | if v, _, err := codec.Dec.DecodeUint32{{$fsuffix.Get}}(r); err != nil { 15 | return err 16 | } else { 17 | {{$fieldVar}} = v 18 | } 19 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_uint64.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 13:49 3 | author: mkideal 4 | category: uint64 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- $fsuffix := newString}} 9 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 10 | {{$fsuffix.Set "f"}} 11 | {{- else}} 12 | {{$fsuffix.Set "v"}} 13 | {{- end}} 14 | if v, _, err := codec.Dec.DecodeUint64{{$fsuffix.Get}}(r); err != nil { 15 | return err 16 | } else { 17 | {{$fieldVar}} = v 18 | } 19 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_uint8.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 13:49 3 | author: mkideal 4 | category: uint8 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | if v, _, err := codec.Dec.DecodeUint8(r); err != nil { 9 | return err 10 | } else { 11 | {{$fieldVar}} = v 12 | } 13 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/decode/decode_vector.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-11 14:21 3 | author: mkideal 4 | category: vector 5 | --- 6 | 7 | {{- $fieldVar := valueAt . 0}} 8 | {{- $type := valueAt . 1}} 9 | {{- $dep := valueAt . 2}} 10 | 11 | {{- $length := newString}} 12 | {{- $forVar := newString}} 13 | {{- include_template (joinPath (pwd) "../for_var.go.temp") (slice $dep $forVar)}} 14 | {{- $i := $forVar.Get}} 15 | {{- if eq $dep.Get 0}} 16 | {{- $length.Set "length"}} 17 | {{- else}} 18 | {{- $length.Set (join "" "length" $dep.String)}} 19 | var {{$length}} int 20 | {{- end}} 21 | 22 | {{- $fsuffix := newString}} 23 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 24 | {{$fsuffix.Set "f"}} 25 | {{- else}} 26 | {{$fsuffix.Set "v"}} 27 | {{- end}} 28 | if v, _, err := codec.Dec.DecodeUint32{{$fsuffix.Get}}(r); err != nil { 29 | return err 30 | } else { 31 | {{$length}} = int(v) 32 | } 33 | if {{$length}} < 0 { 34 | return codec.ErrNegativeLength 35 | } 36 | 37 | {{- $newDep := newInt}} 38 | {{- $newDep.Set ($dep.Add 1)}} 39 | if {{$length}} > 0 { 40 | {{$elemType := context.BuildType $type.T}} 41 | {{$fieldVar}} = make([]{{$elemType}}, {{$length}}) 42 | for {{$i}} := 0; {{$i}} < {{$length}}; {{$i}}++ { 43 | {{- $varName := join "" $fieldVar "[" $i "]"}} 44 | {{- include_template (joinPath (pwd) "decode_type.go.temp") (slice $varName $type.T $newDep)}} 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-05 23:29 3 | author: mkideal 4 | --- 5 | 6 | {{- $bean := .}} 7 | func (x {{.Name}}) Encode(w codec.Writer) error { 8 | {{- $flag := newBool}} 9 | {{- range $field := .Fields}} 10 | {{$type := $field.Type}} 11 | {{- if OR ($type.IsArray) ($type.IsVector)}} 12 | {{- if not $flag.Get}} 13 | var length int 14 | {{- $flag.Set true}} 15 | {{- end}} 16 | {{- end}} 17 | {{- end}} 18 | {{- range $field := .Extends}} 19 | {{- $varName := join "" "x." (context.BuildType $field)}} 20 | {{- $dep := newInt}} 21 | {{- include_template (joinPath (pwd) "encode/encode_type.go.temp") (slice $varName $field $dep)}} 22 | {{- end}} 23 | {{- range $field := .Fields}} 24 | {{- $varName := join "" "x." (title $field.Name)}} 25 | {{- $dep := newInt}} 26 | {{- include_template (joinPath (pwd) "encode/encode_type.go.temp") (slice $varName $field.Type $dep)}} 27 | {{- end}} 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_array.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-06 00:05 3 | author: mkideal 4 | category: array 5 | --- 6 | 7 | {{- $fieldVar := valueAt . 0}} 8 | {{- $type := valueAt . 1}} 9 | {{- $dep := valueAt . 2}} 10 | {{- $length := newString}} 11 | {{- $forVar := newString}} 12 | {{- include_template (joinPath (pwd) "../for_var.go.temp") (slice $dep $forVar)}} 13 | {{- $i := $forVar.Get}} 14 | {{- if eq $dep.Get 0}} 15 | {{- $length.Set "length"}} 16 | {{$length}} = len({{$fieldVar}}) 17 | {{- else}} 18 | {{- $length.Set (join "" "length" $dep.String)}} 19 | {{$length}} := len({{$fieldVar}}) 20 | {{- end}} 21 | {{- $newDep := newInt}} 22 | {{- $newDep.Set ($dep.Add 1)}} 23 | for {{$i}} := 0; {{$i}} < {{$length}}; {{$i}}++ { 24 | {{- $varName := join "" $fieldVar "[" $i "]"}} 25 | {{- include_template (joinPath (pwd) "encode_type.go.temp") (slice $varName $type.T $newDep)}} 26 | } 27 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_bool.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-05 23:52 3 | author: mkideal 4 | category: bool 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | if _, err := codec.Enc.EncodeBool(w, {{$fieldVar}}); err != nil { 9 | return err 10 | } 11 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_byte.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-05 23:54 3 | author: mkideal 4 | category: byte 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | if _, err := codec.Enc.EncodeUint8(w, uint8({{$fieldVar}})); err != nil { 9 | return err 10 | } 11 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_int.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-05 23:55 3 | author: mkideal 4 | category: int 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 9 | if _, err := codec.Enc.EncodeInt64f(w, int64({{$fieldVar}})); err != nil { 10 | return err 11 | } 12 | {{- else}} 13 | if _, err := codec.Enc.EncodeInt64v(w, int64({{$fieldVar}})); err != nil { 14 | return err 15 | } 16 | {{- end}} 17 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_int16.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-05 23:55 3 | author: mkideal 4 | category: int16 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 9 | if _, err := codec.Enc.EncodeInt16f(w, {{$fieldVar}}); err != nil { 10 | return err 11 | } 12 | {{- else}} 13 | if _, err := codec.Enc.EncodeInt16v(w, {{$fieldVar}}); err != nil { 14 | return err 15 | } 16 | {{- end}} 17 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_int32.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-05 23:56 3 | author: mkideal 4 | category: int32 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 9 | if _, err := codec.Enc.EncodeInt32f(w, {{$fieldVar}}); err != nil { 10 | return err 11 | } 12 | {{- else}} 13 | if _, err := codec.Enc.EncodeInt32v(w, {{$fieldVar}}); err != nil { 14 | return err 15 | } 16 | {{- end}} 17 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_int64.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-05 23:56 3 | author: mkideal 4 | category: int64 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 9 | if _, err := codec.Enc.EncodeInt64f(w, {{$fieldVar}}); err != nil { 10 | return err 11 | } 12 | {{- else}} 13 | if _, err := codec.Enc.EncodeInt64v(w, {{$fieldVar}}); err != nil { 14 | return err 15 | } 16 | {{- end}} 17 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_int8.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-05 23:56 3 | author: mkideal 4 | category: int8 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | if _, err := codec.Enc.EncodeInt8(w, {{$fieldVar}}); err != nil { 9 | return err 10 | } 11 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_map.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-07 23:35 3 | author: mkideal 4 | category: map 5 | --- 6 | 7 | {{- $fieldVar := valueAt . 0}} 8 | {{- $type := valueAt . 1}} 9 | {{- $dep := valueAt . 2}} 10 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 11 | if _, err := codec.Enc.EncodeUint32f(w, uint32(len({{$fieldVar}}))); err != nil { 12 | return err 13 | } 14 | {{- else}} 15 | if _, err := codec.Enc.EncodeUint32v(w, uint32(len({{$fieldVar}}))); err != nil { 16 | return err 17 | } 18 | {{- end}} 19 | {{- $key := newString}} 20 | {{- $value := newString}} 21 | {{- if eq ($dep.Get) 0}} 22 | {{$key.Set "key"}} 23 | {{$value.Set "value"}} 24 | {{- else}} 25 | {{- $key.Set (join "" "key" $dep.String)}} 26 | {{- $value.Set (join "" "value" $dep.String)}} 27 | {{- end}} 28 | {{- $newDep := newInt}} 29 | {{- $newDep.Set ($dep.Add 1)}} 30 | for {{$key}}, {{$value}} := range {{$fieldVar}} { 31 | {{- include_template (joinPath (pwd) "encode_type.go.temp") (slice ($key.Get) $type.K $newDep)}} 32 | {{- include_template (joinPath (pwd) "encode_type.go.temp") (slice ($value.Get) $type.V $newDep)}} 33 | } 34 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_string.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-07 22:53 3 | author: mkideal 4 | category: string 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | if _, err := codec.Enc.EncodeString(w, {{$fieldVar}}); err != nil { 9 | return err 10 | } 11 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_struct.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-07 23:37 3 | author: mkideal 4 | category: struct 5 | --- 6 | 7 | {{- $fieldVar := valueAt . 0}} 8 | {{- $type := valueAt . 1}} 9 | if err := {{$fieldVar}}.Encode(w); err != nil { 10 | return err 11 | } 12 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_type.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-07 00:06 3 | author: mkideal 4 | --- 5 | {{- $fieldVar := valueAt . 0}} 6 | {{- $type := valueAt . 1}} 7 | {{- $dep := valueAt . 2}} 8 | {{- $fieldType := context.BuildType $type | lastOf "."}} 9 | {{- $tempDir := "."}} 10 | {{- if eq $fieldType "int"}}{{ include_template (joinPath (pwd) $tempDir "encode_int.go.temp") $fieldVar }} 11 | {{- else if eq $fieldType "int8"}}{{ include_template (joinPath (pwd) $tempDir "encode_int8.go.temp") $fieldVar }} 12 | {{- else if eq $fieldType "int16"}}{{ include_template (joinPath (pwd) $tempDir "encode_int16.go.temp") $fieldVar }} 13 | {{- else if eq $fieldType "int32"}}{{ include_template (joinPath (pwd) $tempDir "encode_int32.go.temp") $fieldVar }} 14 | {{- else if eq $fieldType "int64"}}{{ include_template (joinPath (pwd) $tempDir "encode_int64.go.temp") $fieldVar }} 15 | {{- else if eq $fieldType "uint"}}{{ include_template (joinPath (pwd) $tempDir "encode_uint.go.temp") $fieldVar }} 16 | {{- else if eq $fieldType "uint8"}}{{ include_template (joinPath (pwd) $tempDir "encode_uint8.go.temp") $fieldVar }} 17 | {{- else if eq $fieldType "uint16"}}{{ include_template (joinPath (pwd) $tempDir "encode_uint16.go.temp") $fieldVar }} 18 | {{- else if eq $fieldType "uint32"}}{{ include_template (joinPath (pwd) $tempDir "encode_uint32.go.temp") $fieldVar }} 19 | {{- else if eq $fieldType "uint64"}}{{ include_template (joinPath (pwd) $tempDir "encode_uint64.go.temp") $fieldVar }} 20 | {{- else if eq $fieldType "byte"}}{{ include_template (joinPath (pwd) $tempDir "encode_byte.go.temp") $fieldVar }} 21 | {{- else if eq $fieldType "bool"}}{{ include_template (joinPath (pwd) $tempDir "encode_bool.go.temp") $fieldVar }} 22 | {{- else if eq $fieldType "string"}}{{ include_template (joinPath (pwd) $tempDir "encode_string.go.temp") $fieldVar }} 23 | {{- else if $type.IsArray}}{{ include_template (joinPath (pwd) $tempDir "encode_array.go.temp") (slice $fieldVar $type $dep)}} 24 | {{- else if $type.IsVector}}{{ include_template (joinPath (pwd) $tempDir "encode_vector.go.temp") (slice $fieldVar $type $dep)}} 25 | {{- else if $type.IsMap}}{{ include_template (joinPath (pwd) $tempDir "encode_map.go.temp") (slice $fieldVar $type $dep)}} 26 | {{- else if $type.IsStruct}}{{ include_template (joinPath (pwd) $tempDir "encode_struct.go.temp") (slice $fieldVar $type)}} 27 | {{- end}} 28 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_uint.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-06 00:01 3 | author: mkideal 4 | category: uint 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 9 | if _, err := codec.Enc.EncodeUint64f(w, uint64({{$fieldVar}})); err != nil { 10 | return err 11 | } 12 | {{- else}} 13 | if _, err := codec.Enc.EncodeUint64v(w, uint64({{$fieldVar}})); err != nil { 14 | return err 15 | } 16 | {{- end}} 17 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_uint16.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-06 00:02 3 | author: mkideal 4 | category: uint16 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 9 | if _, err := codec.Enc.EncodeUint16f(w, {{$fieldVar}}); err != nil { 10 | return err 11 | } 12 | {{- else}} 13 | if _, err := codec.Enc.EncodeUint16v(w, {{$fieldVar}}); err != nil { 14 | return err 15 | } 16 | {{- end}} 17 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_uint32.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-06 00:03 3 | author: mkideal 4 | category: uint32 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 9 | if _, err := codec.Enc.EncodeUint32f(w, {{$fieldVar}}); err != nil { 10 | return err 11 | } 12 | {{- else}} 13 | if _, err := codec.Enc.EncodeUint32v(w, {{$fieldVar}}); err != nil { 14 | return err 15 | } 16 | {{- end}} 17 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_uint64.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-06 00:02 3 | author: mkideal 4 | category: uint64 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 9 | if _, err := codec.Enc.EncodeUint64f(w, {{$fieldVar}}); err != nil { 10 | return err 11 | } 12 | {{- else}} 13 | if _, err := codec.Enc.EncodeUint64v(w, {{$fieldVar}}); err != nil { 14 | return err 15 | } 16 | {{- end}} 17 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_uint8.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-06 00:02 3 | author: mkideal 4 | category: uint8 5 | --- 6 | 7 | {{- $fieldVar := .}} 8 | if _, err := codec.Enc.EncodeUint8(w, {{$fieldVar}}); err != nil { 9 | return err 10 | } 11 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/encode/encode_vector.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-07 23:34 3 | author: mkideal 4 | category: vector 5 | --- 6 | 7 | {{- $fieldVar := valueAt . 0}} 8 | {{- $type := valueAt . 1}} 9 | {{- $dep := valueAt . 2}} 10 | 11 | {{- $length := newString}} 12 | {{- $forVar := newString}} 13 | {{- include_template (joinPath (pwd) "../for_var.go.temp") (slice $dep $forVar)}} 14 | {{- $i := $forVar.Get}} 15 | {{- if eq $dep.Get 0}} 16 | {{- $length.Set "length"}} 17 | {{$length}} = len({{$fieldVar}}) 18 | {{- else}} 19 | {{- $length.Set (join "" "length" $dep.String)}} 20 | {{$length}} := len({{$fieldVar}}) 21 | {{- end}} 22 | {{- if context.Config.BoolEnv "use_fixed_encode"}} 23 | if _, err := codec.Enc.EncodeUint32f(w, uint32({{$length}})); err != nil { 24 | return err 25 | } 26 | {{- else}} 27 | if _, err := codec.Enc.EncodeUint32v(w, uint32({{$length}})); err != nil { 28 | return err 29 | } 30 | {{- end}} 31 | {{- $newDep := newInt}} 32 | {{- $newDep.Set ($dep.Add 1)}} 33 | for {{$i}} := 0; {{$i}} < {{$length}}; {{$i}}++ { 34 | {{- $varName := join "" $fieldVar "[" $i "]"}} 35 | {{- include_template (joinPath (pwd) "encode_type.go.temp") (slice $varName $type.T $newDep)}} 36 | } 37 | -------------------------------------------------------------------------------- /extensions/midc/codec/templates/go/for_var.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-08 00:03 3 | author: mkideal 4 | desc: define local varible for for-loop 5 | --- 6 | 7 | {{- $dep := valueAt . 0}} 8 | {{- $res := valueAt . 1}} 9 | 10 | {{- if eq ($dep.Get) 0}} 11 | {{- $res.Set "i" }} 12 | {{- else if eq ($dep.Get) 1}} 13 | {{- $res.Set "j" }} 14 | {{- else if eq ($dep.Get) 2}} 15 | {{- $res.Set "k" }} 16 | {{- else}} 17 | {{- $res.Set (join "" "i" $dep.String)}} 18 | {{- end}} 19 | -------------------------------------------------------------------------------- /extensions/midc/meta/ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "at": { 3 | "cpp": { 4 | "after_protocol": [ 5 | { 6 | "suffix": "cpp", 7 | "template": "cpp/after_protocol.cpp.temp" 8 | } 9 | ], 10 | "after_struct": [ 11 | { 12 | "suffix": "cpp", 13 | "template": "cpp/after_struct.cpp.temp" 14 | } 15 | ], 16 | "protocol_front": [ 17 | { 18 | "suffix": "h", 19 | "template": "cpp/protocol_front.h.temp" 20 | } 21 | ], 22 | "struct_front": [ 23 | { 24 | "suffix": "h", 25 | "template": "cpp/struct_front.h.temp" 26 | } 27 | ] 28 | }, 29 | "go": { 30 | "after_protocol": [ 31 | { 32 | "template": "go/after_protocol.go.temp" 33 | } 34 | ], 35 | "after_struct": [ 36 | { 37 | "template": "go/after_struct.go.temp" 38 | } 39 | ] 40 | } 41 | }, 42 | "author": "midc", 43 | "name": "meta", 44 | "version": "0.1" 45 | } 46 | -------------------------------------------------------------------------------- /extensions/midc/meta/templates/cpp/after_protocol.cpp.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 19:09 3 | author: mkideal 4 | --- 5 | {{include_template (joinPath (pwd) "after_struct.cpp.temp") .}} 6 | -------------------------------------------------------------------------------- /extensions/midc/meta/templates/cpp/after_struct.cpp.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 19:05 3 | author: mkideal 4 | --- 5 | 6 | {{- $beanName := .Name}} 7 | {{- range $field := .Extends}} 8 | {{- $fieldType := context.BuildType $field}} 9 | {{- if true}}const std::string {{$beanName}}::Meta::F_{{$fieldType}} = "{{$fieldType}}";{{end}} 10 | {{end}} 11 | {{- range $field := .Fields}} 12 | {{- if true}}const std::string {{$beanName}}::Meta::F_{{$field.Name}} = "{{$field.Name}}";{{end}} 13 | {{ end}} 14 | 15 | std::string {{.Name}}::Meta::name() { 16 | return "{{.Name}}"; 17 | } 18 | 19 | int {{.Name}}::Meta::numField() { 20 | return {{len .Fields}} + {{len .Extends}}; 21 | } 22 | 23 | std::string {{.Name}}::Meta::field(int i) { 24 | {{- $idx := newInt}} 25 | switch (i) { 26 | {{range $field := .Extends}}case {{$idx.Get}}:{{$idx.Set ($idx.Add 1)}} 27 | {{- $fieldType := context.BuildType $field}} 28 | return "{{$fieldType}}"; 29 | {{end}} 30 | {{- range $field := .Fields}}case {{$idx.Get}}:{{$idx.Set ($idx.Add 1)}} 31 | return "{{$field.Name}}"; 32 | {{end}} 33 | } 34 | return ""; 35 | } 36 | -------------------------------------------------------------------------------- /extensions/midc/meta/templates/cpp/protocol_front.h.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 17:28 3 | author: mkideal 4 | --- 5 | {{include_template (joinPath (pwd) "struct_front.h.temp") .}} 6 | -------------------------------------------------------------------------------- /extensions/midc/meta/templates/cpp/struct_front.h.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 17:04 3 | author: mkideal 4 | --- 5 | 6 | struct Meta { 7 | {{range $field := .Extends}}const static std::string F_{{context.BuildType $field}}; 8 | {{end}} 9 | {{range $field := .Fields}}const static std::string F_{{$field.Name}}; 10 | {{end}} 11 | static std::string name(); 12 | static int numField(); 13 | static std::string field(int i); 14 | }; 15 | -------------------------------------------------------------------------------- /extensions/midc/meta/templates/go/after_protocol.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 13:14 3 | author: mkideal 4 | --- 5 | {{include_template (joinPath (pwd) "after_struct.go.temp") .}} 6 | -------------------------------------------------------------------------------- /extensions/midc/meta/templates/go/after_struct.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 12:45 3 | author: mkideal 4 | --- 5 | 6 | type {{.Name}}Meta struct { 7 | {{range $field := .Extends}} 8 | {{- $fieldType := context.BuildType $field | lastOf "."}}F_{{$fieldType}} string 9 | {{end}} 10 | {{range $field := .Fields}}F_{{$field.Name}} string 11 | {{end}} 12 | } 13 | 14 | func ({{.Name}}Meta) Name() string { 15 | return "{{.Name}}" 16 | } 17 | 18 | func ({{.Name}}Meta) NumField() int { 19 | return {{len .Fields}} 20 | } 21 | 22 | func ({{.Name}}Meta) Field(i int, v {{.Name}}) (string, interface{}) { 23 | {{- $idx := newInt}} 24 | switch i { 25 | {{range $field := .Extends}}case {{$idx.Get}}:{{$idx.Set ($idx.Add 1)}} 26 | {{- $fieldType := context.BuildType $field | lastOf "."}} 27 | return "{{$fieldType}}", v.{{$fieldType}} 28 | {{end}} 29 | {{range $field := .Fields}}case {{$idx.Get}}:{{$idx.Set ($idx.Add 1)}} 30 | return "{{$field.Name}}", v.{{$field.Name | title}} 31 | {{end}} 32 | } 33 | return "", nil 34 | } 35 | 36 | func ({{.Name}}Meta) FieldPtr(i int, v *{{.Name}}) (string, interface{}) { 37 | {{- $idx := newInt}} 38 | switch i { 39 | {{range $field := .Extends}}case {{$idx.Get}}:{{$idx.Set ($idx.Add 1)}} 40 | {{- $fieldType := context.BuildType $field | lastOf "."}} 41 | return "{{$fieldType}}", &v.{{$fieldType}} 42 | {{end}} 43 | {{range $field := .Fields}}case {{$idx.Get}}:{{$idx.Set ($idx.Add 1)}} 44 | return "{{$field.Name}}", &v.{{$field.Name | title}} 45 | {{end}} 46 | } 47 | return "", nil 48 | } 49 | 50 | var {{.Name}}MetaVar = {{.Name}}Meta{ 51 | {{range $field := .Extends}} 52 | {{- $fieldType := context.BuildType $field | lastOf "."}}F_{{$fieldType}}: "{{$fieldType}}", 53 | {{end}} 54 | {{range $field := .Fields}}F_{{$field.Name}}: "{{$field.Name}}", 55 | {{end}} 56 | } 57 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/midlang/mid 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/gopherd/log v0.1.14 7 | github.com/mkideal/cli v0.2.7 8 | github.com/mkideal/pkg v0.1.3 9 | github.com/stretchr/testify v1.5.1 10 | ) 11 | 12 | require ( 13 | github.com/davecgh/go-spew v1.1.0 // indirect 14 | github.com/labstack/gommon v0.3.0 // indirect 15 | github.com/mattn/go-colorable v0.1.7 // indirect 16 | github.com/mattn/go-isatty v0.0.12 // indirect 17 | github.com/mkideal/expr v0.1.0 // indirect 18 | github.com/pmezard/go-difflib v1.0.0 // indirect 19 | golang.org/x/crypto v0.1.0 // indirect 20 | golang.org/x/sys v0.1.0 // indirect 21 | golang.org/x/term v0.1.0 // indirect 22 | gopkg.in/yaml.v2 v2.2.2 // indirect 23 | ) 24 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/gopherd/log v0.1.14 h1:1+P7H5uRwuq53FGqiq8EvjRnrT2+dd43ufMtP9j1Wbk= 4 | github.com/gopherd/log v0.1.14/go.mod h1:gmYpBUEA6VpJUvyariz0aU4gT3Oqvu94nk45vx8W6uQ= 5 | github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0= 6 | github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= 7 | github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 8 | github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= 9 | github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 10 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 11 | github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= 12 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 13 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 14 | github.com/mkideal/cli v0.2.7 h1:mB/XrMzuddmTJ8f7KY1c+KzfYoM149tYGAnzmqRdvOU= 15 | github.com/mkideal/cli v0.2.7/go.mod h1:efaTeFI4jdPqzAe0bv3myLB2NW5yzMBLvWB70a6feco= 16 | github.com/mkideal/expr v0.1.0 h1:fzborV9TeSUmLm0aEQWTWcexDURFFo4v5gHSc818Kl8= 17 | github.com/mkideal/expr v0.1.0/go.mod h1:vL1DsSb87ZtU6IEjOtUfxw98z0FQbzS8xlGtnPkKdzg= 18 | github.com/mkideal/pkg v0.1.3 h1:4XlD59fshHEiO8z7jftNHYrK7qjp5+2xK7VDnvZw0Qo= 19 | github.com/mkideal/pkg v0.1.3/go.mod h1:u/enAxPeRcYSsxtu1NUifWSeOTU/31VsCaOPg54SMJ4= 20 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 21 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 22 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 23 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 24 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= 25 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 26 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 27 | github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= 28 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 29 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 30 | golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= 31 | golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= 32 | golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= 33 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 34 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 35 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 36 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 37 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 38 | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 39 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 40 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 41 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 42 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 43 | golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= 44 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 45 | golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 46 | golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= 47 | golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 48 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 49 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 50 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 51 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 52 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 53 | -------------------------------------------------------------------------------- /hack/genmeta.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | file=../src/mid/meta.go 6 | version=$1 7 | 8 | if [[ "$version" == "" ]]; then 9 | echo "var version missing as first argument" 10 | exit 1 11 | fi 12 | 13 | cat > $file < /dev/null 59 | } 60 | 61 | if [[ -d "$RELEASE_DIR/$VERSION" ]]; then 62 | rm -r $RELEASE_DIR/$VERSION 63 | fi 64 | mkdir -p $RELEASE_DIR/$VERSION 65 | 66 | release_mid_for windows 386 67 | release_mid_for windows amd64 68 | release_mid_for windows arm64 69 | release_mid_for linux 386 70 | release_mid_for linux amd64 71 | release_mid_for linux arm64 72 | release_mid_for darwin amd64 73 | release_mid_for darwin arm64 74 | -------------------------------------------------------------------------------- /src/cmd/mid-gen-cpp/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/gopherd/log" 7 | "github.com/mkideal/pkg/errors" 8 | 9 | "github.com/midlang/mid/src/genutil" 10 | "github.com/midlang/mid/src/mid/build" 11 | ) 12 | 13 | func main() { 14 | log.Start(log.WithSync(true), log.WithLevel(log.LevelWarn)) 15 | 16 | plugin, config, builder, err := build.ParseFlags() 17 | log.If(err != nil).Fatal(). 18 | Error("err", err). 19 | Print("ParseFlags error") 20 | log.Debug(). 21 | Any("plugin", plugin). 22 | Any("config", config). 23 | Any("builder", builder). 24 | Print("running plugin") 25 | 26 | err = generate(builder, plugin, config) 27 | log.If(err != nil).Error(). 28 | Error("err", err). 29 | Print("generate error") 30 | } 31 | 32 | func generate(builder *build.Builder, plugin build.Plugin, config build.PluginRuntimeConfig) (err error) { 33 | defer func() { 34 | if e := recover(); e != nil { 35 | switch x := e.(type) { 36 | case error: 37 | err = x 38 | case string: 39 | err = errors.Error(x) 40 | default: 41 | err = fmt.Errorf("%v", x) 42 | } 43 | } 44 | }() 45 | 46 | // initialize generator 47 | genutil.Init(buildType, plugin, config) 48 | 49 | pkgs := builder.Packages 50 | for _, pkg := range pkgs { 51 | if _, err := genutil.GeneratePackage(pkg); err != nil { 52 | return err 53 | } 54 | } 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /src/cmd/mid-gen-cpp/types.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "strings" 7 | 8 | "github.com/midlang/mid/src/mid/build" 9 | "github.com/midlang/mid/src/mid/lexer" 10 | ) 11 | 12 | const ( 13 | Env_unordered_map = "cpp:unordered_map" 14 | ) 15 | 16 | var ( 17 | config build.PluginRuntimeConfig 18 | ) 19 | 20 | func cppFieldDecl(f *build.Field) string { 21 | if len(f.Names) == 0 { 22 | return "" 23 | } 24 | return buildType(f.Type) + " " + strings.Join(f.Names, ", ") 25 | } 26 | 27 | func basicIntExprString(expr build.Expr) (string, bool) { 28 | switch e := expr.(type) { 29 | case *build.BasicLit: 30 | if e.Kind == lexer.INT { 31 | return e.Value, true 32 | } 33 | } 34 | return "", false 35 | } 36 | 37 | func buildType(typ build.Type) string { 38 | switch t := typ.(type) { 39 | case *build.BasicType: 40 | builtinType, ok := lexer.LookupType(t.Name) 41 | if !ok { 42 | panic("type `" + t.Name + "` not a builtin type") 43 | } 44 | switch builtinType { 45 | case lexer.Bool: 46 | return "bool" 47 | case lexer.Byte: 48 | return "unsigned char" 49 | case lexer.Bytes: 50 | return "unsigned char*" 51 | case lexer.String: 52 | return "std::string" 53 | case lexer.Int: 54 | return "int" 55 | case lexer.Int8: 56 | return "int8_t" 57 | case lexer.Int16: 58 | return "int16_t" 59 | case lexer.Int32: 60 | return "int32_t" 61 | case lexer.Int64: 62 | return "int64_t" 63 | case lexer.Uint: 64 | return "uint_t" 65 | case lexer.Uint8: 66 | return "uint8_t" 67 | case lexer.Uint16: 68 | return "uint16_t" 69 | case lexer.Uint32: 70 | return "uint32_t" 71 | case lexer.Uint64: 72 | return "uint64_t" 73 | case lexer.Float32: 74 | return "float" 75 | case lexer.Float64: 76 | return "double" 77 | default: 78 | panic("unknown builtin type `" + t.Name + "`") 79 | } 80 | case *build.ArrayType: 81 | size, ok := basicIntExprString(t.Size) 82 | if !ok { 83 | panic("array.Size not an integer") 84 | } 85 | return fmt.Sprintf("std::array<%s,%s> ", buildType(t.T), size) 86 | case *build.VectorType: 87 | return fmt.Sprintf("std::vector<%s> ", buildType(t.T)) 88 | case *build.MapType: 89 | if config.BoolEnv(Env_unordered_map) { 90 | return fmt.Sprintf("std::unordered_map<%s,%s> ", buildType(t.K), buildType(t.V)) 91 | } else { 92 | return fmt.Sprintf("std::map<%s,%s> ", buildType(t.K), buildType(t.V)) 93 | } 94 | case *build.StructType: 95 | if t.Package != "" { 96 | return t.Package + "::" + t.Name 97 | } 98 | return t.Name 99 | case build.TypeBase, *build.TypeBase: 100 | return "void" 101 | case *build.FuncType: 102 | var buf bytes.Buffer 103 | if t.Result != nil { 104 | buf.WriteString(buildType(t.Result)) 105 | } else { 106 | buf.WriteString("void") 107 | } 108 | buf.WriteByte('(') 109 | if len(t.Params) > 0 { 110 | for i, field := range t.Params { 111 | if i > 0 { 112 | buf.WriteByte(',') 113 | } 114 | buf.WriteString(cppFieldDecl(field)) 115 | } 116 | } 117 | buf.WriteByte(')') 118 | return buf.String() 119 | default: 120 | return "" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/cmd/mid-gen-csharp/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/gopherd/log" 7 | "github.com/mkideal/pkg/errors" 8 | 9 | "github.com/midlang/mid/src/genutil" 10 | "github.com/midlang/mid/src/mid/build" 11 | ) 12 | 13 | func main() { 14 | log.Start(log.WithSync(true), log.WithLevel(log.LevelWarn)) 15 | 16 | plugin, config, builder, err := build.ParseFlags() 17 | log.If(err != nil).Fatal(). 18 | Error("err", err). 19 | Print("ParseFlags error") 20 | log.Debug(). 21 | Any("plugin", plugin). 22 | Any("config", config). 23 | Any("builder", builder). 24 | Print("running plugin") 25 | 26 | err = generate(builder, plugin, config) 27 | log.If(err != nil).Error(). 28 | Error("err", err). 29 | Print("generate error") 30 | } 31 | 32 | func generate(builder *build.Builder, plugin build.Plugin, config build.PluginRuntimeConfig) (err error) { 33 | defer func() { 34 | if e := recover(); e != nil { 35 | switch x := e.(type) { 36 | case error: 37 | err = x 38 | case string: 39 | err = errors.Error(x) 40 | default: 41 | err = fmt.Errorf("%v", x) 42 | } 43 | } 44 | }() 45 | 46 | // initialize generator 47 | genutil.Init(buildType, plugin, config) 48 | 49 | pkgs := builder.Packages 50 | for _, pkg := range pkgs { 51 | if _, err := genutil.GeneratePackage(pkg); err != nil { 52 | return err 53 | } 54 | } 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /src/cmd/mid-gen-csharp/types.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "strings" 7 | 8 | "github.com/midlang/mid/src/mid/build" 9 | "github.com/midlang/mid/src/mid/lexer" 10 | ) 11 | 12 | func csFieldDecl(f *build.Field, emptyIfNoName bool) string { 13 | if len(f.Names) == 0 { 14 | if emptyIfNoName { 15 | return buildType(f.Type) 16 | } 17 | return "_ " + buildType(f.Type) 18 | } 19 | return strings.Join(f.Names, ", ") + " " + buildType(f.Type) 20 | } 21 | 22 | func buildType(typ build.Type) string { 23 | switch t := typ.(type) { 24 | case *build.BasicType: 25 | builtinType, ok := lexer.LookupType(t.Name) 26 | if !ok { 27 | panic("type `" + t.Name + "` not a builtin type") 28 | } 29 | switch builtinType { 30 | case lexer.Bool: 31 | return "bool" 32 | case lexer.Byte: 33 | return "byte" 34 | case lexer.Bytes: 35 | return "byte[]" 36 | case lexer.String: 37 | return "string" 38 | case lexer.Int: 39 | return "int" 40 | case lexer.Int8: 41 | return "int8" 42 | case lexer.Int16: 43 | return "int16" 44 | case lexer.Int32: 45 | return "int32" 46 | case lexer.Int64: 47 | return "int64" 48 | case lexer.Uint: 49 | return "uint" 50 | case lexer.Uint8: 51 | return "uint8" 52 | case lexer.Uint16: 53 | return "uint16" 54 | case lexer.Uint32: 55 | return "uint32" 56 | case lexer.Uint64: 57 | return "uint64" 58 | case lexer.Float32: 59 | return "float" 60 | case lexer.Float64: 61 | return "double" 62 | default: 63 | panic("unknown builtin type `" + t.Name + "`") 64 | } 65 | case *build.ArrayType: 66 | size, ok := build.IntFromExpr(t.Size) 67 | if !ok { 68 | panic("array.Size not an integer") 69 | } 70 | _ = size 71 | return fmt.Sprintf("%s[]", buildType(t.T)) 72 | case *build.VectorType: 73 | return fmt.Sprintf("%s[]", buildType(t.T)) 74 | case *build.MapType: 75 | return fmt.Sprintf("Dictionary<%s, %s>", buildType(t.K), buildType(t.V)) 76 | case *build.StructType: 77 | if t.Package != "" { 78 | return t.Package + "." + t.Name 79 | } 80 | return t.Name 81 | case *build.FuncType: 82 | var buf bytes.Buffer 83 | buf.WriteByte('(') 84 | if len(t.Params) > 0 { 85 | allNoName := true 86 | for _, field := range t.Params { 87 | if len(field.Names) > 0 { 88 | allNoName = false 89 | break 90 | } 91 | } 92 | for i, field := range t.Params { 93 | if i > 0 { 94 | buf.WriteByte(',') 95 | } 96 | buf.WriteString(csFieldDecl(field, allNoName)) 97 | } 98 | } 99 | buf.WriteByte(')') 100 | if t.Result != nil { 101 | buf.WriteString(buildType(t.Result)) 102 | } 103 | return buf.String() 104 | default: 105 | return "" 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/cmd/mid-gen-go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/gopherd/log" 7 | "github.com/mkideal/pkg/errors" 8 | 9 | "github.com/midlang/mid/src/genutil" 10 | "github.com/midlang/mid/src/mid/build" 11 | ) 12 | 13 | func main() { 14 | log.Start(log.WithSync(true), log.WithLevel(log.LevelWarn)) 15 | 16 | plugin, config, builder, err := build.ParseFlags() 17 | log.If(err != nil).Fatal(). 18 | Error("err", err). 19 | Print("ParseFlags error") 20 | log.Debug(). 21 | Any("plugin", plugin). 22 | Any("config", config). 23 | Any("builder", builder). 24 | Print("running plugin") 25 | 26 | err = generate(builder, plugin, config) 27 | log.If(err != nil).Error(). 28 | Error("err", err). 29 | Print("generate error") 30 | } 31 | 32 | func generate(builder *build.Builder, plugin build.Plugin, config build.PluginRuntimeConfig) (err error) { 33 | defer func() { 34 | if e := recover(); e != nil { 35 | switch x := e.(type) { 36 | case error: 37 | err = x 38 | case string: 39 | err = errors.Error(x) 40 | default: 41 | err = fmt.Errorf("%v", x) 42 | } 43 | } 44 | }() 45 | 46 | // initialize generator 47 | genutil.Init(buildType, plugin, config) 48 | 49 | pkgs := builder.Packages 50 | for _, pkg := range pkgs { 51 | if files, err := genutil.GeneratePackage(pkg); err != nil { 52 | return err 53 | } else { 54 | for file := range files { 55 | if err = genutil.GoFmt(file); err != nil { 56 | return errors.Throw("gofmt file `" + file + "` error: " + err.Error()) 57 | } 58 | } 59 | } 60 | } 61 | return nil 62 | } 63 | -------------------------------------------------------------------------------- /src/cmd/mid-gen-go/types.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "strings" 7 | 8 | "github.com/midlang/mid/src/mid/build" 9 | "github.com/midlang/mid/src/mid/lexer" 10 | ) 11 | 12 | func goFieldDecl(f *build.Field, emptyIfNoName bool) string { 13 | if len(f.Names) == 0 { 14 | if emptyIfNoName { 15 | return buildType(f.Type) 16 | } 17 | return "_ " + buildType(f.Type) 18 | } 19 | return strings.Join(f.Names, ", ") + " " + buildType(f.Type) 20 | } 21 | 22 | func buildType(typ build.Type) string { 23 | switch t := typ.(type) { 24 | case *build.BasicType: 25 | builtinType, ok := lexer.LookupType(t.Name) 26 | if !ok { 27 | panic("type `" + t.Name + "` not a builtin type") 28 | } 29 | switch builtinType { 30 | case lexer.Bool: 31 | return "bool" 32 | case lexer.Byte: 33 | return "byte" 34 | case lexer.Bytes: 35 | return "[]byte" 36 | case lexer.String: 37 | return "string" 38 | case lexer.Int: 39 | return "int" 40 | case lexer.Int8: 41 | return "int8" 42 | case lexer.Int16: 43 | return "int16" 44 | case lexer.Int32: 45 | return "int32" 46 | case lexer.Int64: 47 | return "int64" 48 | case lexer.Uint: 49 | return "uint" 50 | case lexer.Uint8: 51 | return "uint8" 52 | case lexer.Uint16: 53 | return "uint16" 54 | case lexer.Uint32: 55 | return "uint32" 56 | case lexer.Uint64: 57 | return "uint64" 58 | case lexer.Float32: 59 | return "float32" 60 | case lexer.Float64: 61 | return "float64" 62 | default: 63 | panic("unknown builtin type `" + t.Name + "`") 64 | } 65 | case *build.ArrayType: 66 | size, ok := build.IntFromExpr(t.Size) 67 | if !ok { 68 | panic("array.Size not an integer") 69 | } 70 | return fmt.Sprintf("[%s]%s", size, buildType(t.T)) 71 | case *build.VectorType: 72 | return fmt.Sprintf("[]%s", buildType(t.T)) 73 | case *build.MapType: 74 | return fmt.Sprintf("map[%s]%s", buildType(t.K), buildType(t.V)) 75 | case *build.StructType: 76 | if t.Package != "" { 77 | return t.Package + "." + t.Name 78 | } 79 | return t.Name 80 | case *build.FuncType: 81 | var buf bytes.Buffer 82 | buf.WriteByte('(') 83 | if len(t.Params) > 0 { 84 | allNoName := true 85 | for _, field := range t.Params { 86 | if len(field.Names) > 0 { 87 | allNoName = false 88 | break 89 | } 90 | } 91 | for i, field := range t.Params { 92 | if i > 0 { 93 | buf.WriteByte(',') 94 | } 95 | buf.WriteString(goFieldDecl(field, allNoName)) 96 | } 97 | } 98 | buf.WriteByte(')') 99 | if t.Result != nil { 100 | buf.WriteString(buildType(t.Result)) 101 | } 102 | return buf.String() 103 | default: 104 | return "" 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/cmd/mid-gen-js/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/gopherd/log" 7 | "github.com/mkideal/pkg/errors" 8 | 9 | "github.com/midlang/mid/src/genutil" 10 | "github.com/midlang/mid/src/mid/build" 11 | ) 12 | 13 | func main() { 14 | log.Start(log.WithSync(true), log.WithLevel(log.LevelWarn)) 15 | 16 | plugin, config, builder, err := build.ParseFlags() 17 | log.If(err != nil).Fatal(). 18 | Error("err", err). 19 | Print("ParseFlags error") 20 | log.Debug(). 21 | Any("plugin", plugin). 22 | Any("config", config). 23 | Any("builder", builder). 24 | Print("running plugin") 25 | 26 | err = generate(builder, plugin, config) 27 | log.If(err != nil).Error(). 28 | Error("err", err). 29 | Print("generate error") 30 | } 31 | 32 | func generate(builder *build.Builder, plugin build.Plugin, config build.PluginRuntimeConfig) (err error) { 33 | defer func() { 34 | if e := recover(); e != nil { 35 | switch x := e.(type) { 36 | case error: 37 | err = x 38 | case string: 39 | err = errors.Error(x) 40 | default: 41 | err = fmt.Errorf("%v", x) 42 | } 43 | } 44 | }() 45 | 46 | // initialize generator 47 | genutil.Init(buildType, plugin, config) 48 | 49 | pkgs := builder.Packages 50 | for _, pkg := range pkgs { 51 | if _, err := genutil.GeneratePackage(pkg); err != nil { 52 | return err 53 | } 54 | } 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /src/cmd/mid-gen-js/types.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "strings" 6 | 7 | "github.com/midlang/mid/src/mid/build" 8 | "github.com/midlang/mid/src/mid/lexer" 9 | ) 10 | 11 | func jsFieldDecl(f *build.Field, emptyIfNoName bool) string { 12 | if len(f.Names) == 0 { 13 | return buildType(f.Type) 14 | } 15 | return strings.Join(f.Names, ", ") 16 | } 17 | 18 | func basicIntExprString(expr build.Expr) (string, bool) { 19 | switch e := expr.(type) { 20 | case *build.BasicLit: 21 | if e.Kind == lexer.INT { 22 | return e.Value, true 23 | } 24 | } 25 | return "", false 26 | } 27 | 28 | func buildType(typ build.Type) string { 29 | switch t := typ.(type) { 30 | case *build.BasicType: 31 | builtinType, ok := lexer.LookupType(t.Name) 32 | if !ok { 33 | panic("type `" + t.Name + "` not a builtin type") 34 | } 35 | switch builtinType { 36 | case lexer.Bool: 37 | return "Boolean" 38 | case lexer.Byte: 39 | return "Number" 40 | case lexer.Bytes: 41 | return "Array" 42 | case lexer.String: 43 | return "String" 44 | case lexer.Int, 45 | lexer.Int8, 46 | lexer.Int16, 47 | lexer.Int32, 48 | lexer.Int64, 49 | lexer.Uint, 50 | lexer.Uint8, 51 | lexer.Uint16, 52 | lexer.Uint32, 53 | lexer.Uint64: 54 | return "Number" 55 | default: 56 | panic("unknown builtin type `" + t.Name + "`") 57 | } 58 | case *build.ArrayType: 59 | _, ok := basicIntExprString(t.Size) 60 | if !ok { 61 | panic("array.Size not a integer") 62 | } 63 | return "Array" 64 | case *build.VectorType: 65 | return "Array" 66 | case *build.MapType: 67 | return "Object" 68 | case *build.StructType: 69 | return t.Name 70 | case *build.FuncType: 71 | var buf bytes.Buffer 72 | buf.WriteByte('(') 73 | if len(t.Params) > 0 { 74 | allNoName := true 75 | for _, field := range t.Params { 76 | if len(field.Names) > 0 { 77 | allNoName = false 78 | break 79 | } 80 | } 81 | for i, field := range t.Params { 82 | if i > 0 { 83 | buf.WriteByte(',') 84 | } 85 | buf.WriteString(jsFieldDecl(field, allNoName)) 86 | } 87 | } 88 | buf.WriteByte(')') 89 | return buf.String() 90 | default: 91 | return "" 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/cmd/mid-gen-protobuf/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/gopherd/log" 7 | "github.com/mkideal/pkg/errors" 8 | 9 | "github.com/midlang/mid/src/genutil" 10 | "github.com/midlang/mid/src/mid/build" 11 | ) 12 | 13 | func main() { 14 | log.Start(log.WithSync(true), log.WithLevel(log.LevelWarn)) 15 | 16 | plugin, config, builder, err := build.ParseFlags() 17 | log.If(err != nil).Fatal(). 18 | Error("err", err). 19 | Print("ParseFlags error") 20 | log.Debug(). 21 | Any("plugin", plugin). 22 | Any("config", config). 23 | Any("builder", builder). 24 | Print("running plugin") 25 | 26 | err = generate(builder, plugin, config) 27 | log.If(err != nil).Error(). 28 | Error("err", err). 29 | Print("generate error") 30 | } 31 | 32 | func generate(builder *build.Builder, plugin build.Plugin, config build.PluginRuntimeConfig) (err error) { 33 | defer func() { 34 | if e := recover(); e != nil { 35 | switch x := e.(type) { 36 | case error: 37 | err = x 38 | case string: 39 | err = errors.Error(x) 40 | default: 41 | err = fmt.Errorf("%v", x) 42 | } 43 | } 44 | }() 45 | 46 | // initialize generator 47 | genutil.Init(buildType, plugin, config) 48 | 49 | pkgs := builder.Packages 50 | for _, pkg := range pkgs { 51 | if _, err := genutil.GeneratePackage(pkg); err != nil { 52 | return err 53 | } 54 | } 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /src/cmd/mid-gen-protobuf/types.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/midlang/mid/src/mid/build" 8 | "github.com/midlang/mid/src/mid/lexer" 9 | ) 10 | 11 | func goFieldDecl(f *build.Field, emptyIfNoName bool) string { 12 | if len(f.Names) == 0 { 13 | if emptyIfNoName { 14 | return buildType(f.Type) 15 | } 16 | return "_ " + buildType(f.Type) 17 | } 18 | return strings.Join(f.Names, ", ") + " " + buildType(f.Type) 19 | } 20 | 21 | func buildType(typ build.Type) string { 22 | switch t := typ.(type) { 23 | case *build.BasicType: 24 | builtinType, ok := lexer.LookupType(t.Name) 25 | if !ok { 26 | panic("type `" + t.Name + "` not a builtin type") 27 | } 28 | switch builtinType { 29 | case lexer.Bool: 30 | return "bool" 31 | case lexer.Byte: 32 | return "byte" 33 | case lexer.Bytes: 34 | return "bytes" 35 | case lexer.String: 36 | return "string" 37 | case lexer.Int: 38 | return "int64" 39 | case lexer.Int8: 40 | return "int32" 41 | case lexer.Int16: 42 | return "int32" 43 | case lexer.Int32: 44 | return "int32" 45 | case lexer.Int64: 46 | return "int64" 47 | case lexer.Uint: 48 | return "uint64" 49 | case lexer.Uint8: 50 | return "uint32" 51 | case lexer.Uint16: 52 | return "uint32" 53 | case lexer.Uint32: 54 | return "uint32" 55 | case lexer.Uint64: 56 | return "uint64" 57 | case lexer.Float32: 58 | return "float" 59 | case lexer.Float64: 60 | return "double" 61 | default: 62 | panic("unknown builtin type `" + t.Name + "`") 63 | } 64 | case *build.ArrayType: 65 | size, ok := build.IntFromExpr(t.Size) 66 | if !ok { 67 | panic("array.Size not an integer") 68 | } 69 | return fmt.Sprintf("repeated %s", size, buildType(t.T)) 70 | case *build.VectorType: 71 | return fmt.Sprintf("repeated %s", buildType(t.T)) 72 | case *build.MapType: 73 | return fmt.Sprintf("map<%s,%s>", buildType(t.K), buildType(t.V)) 74 | case *build.StructType: 75 | if t.Package != "" { 76 | return t.Package + "." + t.Name 77 | } 78 | return t.Name 79 | default: 80 | return "" 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/cmd/mid-gen-ts/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/gopherd/log" 7 | "github.com/mkideal/pkg/errors" 8 | 9 | "github.com/midlang/mid/src/genutil" 10 | "github.com/midlang/mid/src/mid/build" 11 | ) 12 | 13 | func main() { 14 | log.Start(log.WithSync(true), log.WithLevel(log.LevelWarn)) 15 | 16 | plugin, config, builder, err := build.ParseFlags() 17 | log.If(err != nil).Fatal(). 18 | Error("err", err). 19 | Print("ParseFlags error") 20 | log.Debug(). 21 | Any("plugin", plugin). 22 | Any("config", config). 23 | Any("builder", builder). 24 | Print("running plugin") 25 | 26 | err = generate(builder, plugin, config) 27 | log.If(err != nil).Error(). 28 | Error("err", err). 29 | Print("generate error") 30 | } 31 | 32 | func generate(builder *build.Builder, plugin build.Plugin, config build.PluginRuntimeConfig) (err error) { 33 | defer func() { 34 | if e := recover(); e != nil { 35 | switch x := e.(type) { 36 | case error: 37 | err = x 38 | case string: 39 | err = errors.Error(x) 40 | default: 41 | err = fmt.Errorf("%v", x) 42 | } 43 | } 44 | }() 45 | 46 | // initialize generator 47 | genutil.Init(buildType, plugin, config) 48 | 49 | pkgs := builder.Packages 50 | for _, pkg := range pkgs { 51 | if _, err := genutil.GeneratePackage(pkg); err != nil { 52 | return err 53 | } 54 | } 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /src/cmd/mid-gen-ts/types.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "strings" 7 | 8 | "github.com/midlang/mid/src/mid/build" 9 | "github.com/midlang/mid/src/mid/lexer" 10 | ) 11 | 12 | func tsFieldDecl(f *build.Field, emptyIfNoName bool) string { 13 | if len(f.Names) == 0 { 14 | return buildType(f.Type) 15 | } 16 | return strings.Join(f.Names, ", ") 17 | } 18 | 19 | func basicIntExprString(expr build.Expr) (string, bool) { 20 | switch e := expr.(type) { 21 | case *build.BasicLit: 22 | if e.Kind == lexer.INT { 23 | return e.Value, true 24 | } 25 | } 26 | return "", false 27 | } 28 | 29 | func buildType(typ build.Type) string { 30 | switch t := typ.(type) { 31 | case *build.BasicType: 32 | builtinType, ok := lexer.LookupType(t.Name) 33 | if !ok { 34 | panic("type `" + t.Name + "` not a builtin type") 35 | } 36 | switch builtinType { 37 | case lexer.Bool: 38 | return "boolean" 39 | case lexer.Byte: 40 | return "number" 41 | case lexer.Bytes: 42 | return "Unit8Array" 43 | case lexer.String: 44 | return "string" 45 | case lexer.Int, 46 | lexer.Int8, 47 | lexer.Int16, 48 | lexer.Int32, 49 | lexer.Int64, 50 | lexer.Uint, 51 | lexer.Uint8, 52 | lexer.Uint16, 53 | lexer.Uint32, 54 | lexer.Uint64: 55 | return "number" 56 | default: 57 | panic("unknown builtin type `" + t.Name + "`") 58 | } 59 | case *build.ArrayType: 60 | return fmt.Sprintf("%s[]", buildType(t.T)) 61 | case *build.VectorType: 62 | return fmt.Sprintf("%s[]", buildType(t.T)) 63 | case *build.MapType: 64 | return fmt.Sprintf("{[key: %s]: %s}", buildType(t.K), buildType(t.V)) 65 | case *build.StructType: 66 | return t.Name 67 | case *build.FuncType: 68 | var buf bytes.Buffer 69 | buf.WriteByte('(') 70 | if len(t.Params) > 0 { 71 | allNoName := true 72 | for _, field := range t.Params { 73 | if len(field.Names) > 0 { 74 | allNoName = false 75 | break 76 | } 77 | } 78 | for i, field := range t.Params { 79 | if i > 0 { 80 | buf.WriteByte(',') 81 | } 82 | buf.WriteString(tsFieldDecl(field, allNoName)) 83 | } 84 | } 85 | buf.WriteByte(')') 86 | return buf.String() 87 | default: 88 | return "" 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/cmd/midc/config.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "os" 6 | 7 | "github.com/gopherd/log" 8 | "github.com/midlang/mid/src/mid/build" 9 | ) 10 | 11 | type Config struct { 12 | Suffix string `json:"suffix" cli:"suffix" usage:"source file suffix" dft:".mid" name:"SUFFIX"` 13 | MidRoot string `json:"midroot" cli:"midroot" dft:"$MIDROOT" usage:"mid root directory"` 14 | 15 | Plugins *build.PluginSet `json:"-" cli:"-"` 16 | LoadedPlugins []build.Plugin `json:"plugins" cli:"-"` 17 | } 18 | 19 | func newConfig() *Config { 20 | cfg := new(Config) 21 | cfg.Plugins = build.NewPluginSet() 22 | return cfg 23 | } 24 | 25 | func (cfg *Config) Load(filename string) error { 26 | file, err := os.Open(filename) 27 | if err != nil { 28 | return err 29 | } 30 | defer file.Close() 31 | if err := json.NewDecoder(file).Decode(cfg); err != nil { 32 | return err 33 | } 34 | log.Debug().Printf("plugins.length: %d", cfg.Plugins.Len()) 35 | for _, p := range cfg.LoadedPlugins { 36 | log.Debug().Printf("register plugin %s", p.Lang) 37 | if err := cfg.Plugins.Register(p); err != nil { 38 | return err 39 | } 40 | } 41 | return nil 42 | } 43 | -------------------------------------------------------------------------------- /src/genutil/context.go: -------------------------------------------------------------------------------- 1 | package genutil 2 | 3 | import ( 4 | "bytes" 5 | "path/filepath" 6 | 7 | "github.com/midlang/mid/src/mid/build" 8 | ) 9 | 10 | // Context holds current context for generating codes of specified package 11 | type Context struct { 12 | // Pkg represents current package 13 | Pkg *build.Package 14 | // Root represents root template 15 | Root *Template 16 | // Plugin represents current plugin 17 | Plugin build.Plugin 18 | // Config represents current plugin runtime config 19 | Config build.PluginRuntimeConfig 20 | // Kind holds current template kind 21 | Kind string 22 | // Suffix holds current template suffix 23 | Suffix string 24 | // Pwd holds current template file directory 25 | Pwd string 26 | // Beans holds all beans in current package 27 | Beans map[string]*build.Bean 28 | 29 | // BuildType functions for current language 30 | buildType BuildTypeFunc 31 | 32 | Filename string 33 | } 34 | 35 | // NewContext creates a context by buildType,plugin,plugin_config 36 | func NewContext( 37 | buildType BuildTypeFunc, 38 | plugin build.Plugin, 39 | config build.PluginRuntimeConfig, 40 | ) *Context { 41 | ctx := &Context{ 42 | buildType: buildType, 43 | Plugin: plugin, 44 | Config: config, 45 | Beans: make(map[string]*build.Bean), 46 | } 47 | return ctx 48 | } 49 | 50 | func (ctx *Context) initWithPkg(pkg *build.Package) { 51 | ctx.Pkg = pkg 52 | ctx.Beans = make(map[string]*build.Bean) 53 | for _, file := range ctx.Pkg.Files { 54 | for _, bean := range file.Beans { 55 | ctx.Beans[bean.Name] = bean 56 | } 57 | } 58 | } 59 | 60 | // BuildType executes buildType function 61 | func (ctx *Context) BuildType(typ build.Type) string { 62 | return ctx.buildType(typ) 63 | } 64 | 65 | // Getenv gets custom envvar 66 | func (ctx *Context) Getenv(key string) string { 67 | if ctx.Config.Envvars == nil { 68 | return "" 69 | } 70 | return ctx.Config.Envvars[key] 71 | } 72 | 73 | // FindBean finds bean by name in current package 74 | func (ctx *Context) FindBean(name string) *build.Bean { 75 | return ctx.Beans[name] 76 | } 77 | 78 | // AutoGenDeclaration returns a declaration which would be written to each generated file header 79 | // e.g. 80 | // // AUTO-GENERATED by midc!! DON'T EDIT!! 81 | func (ctx *Context) AutoGenDeclaration() string { 82 | if value := ctx.Config.Getenv(ctx.Plugin.Lang + ":autogen_decl"); value != "" { 83 | return value 84 | } 85 | return ctx.Config.Getenv("autogen_decl") 86 | } 87 | 88 | // Extension inserts code for extensions at specific position 89 | func (ctx *Context) Extension(at string, data interface{}) (string, error) { 90 | var buf bytes.Buffer 91 | for _, ext := range ctx.Config.Extensions { 92 | extdir := filepath.Join(ctx.Config.ExtentionsDir, ext.Path, "templates") 93 | values := ext.Find(ctx.Plugin.Lang, ctx.Kind, at) 94 | for _, value := range values { 95 | if !value.IsValid() { 96 | continue 97 | } 98 | if value.Suffix != "" && value.Suffix != ctx.Suffix { 99 | continue 100 | } 101 | if buf.Len() > 0 { 102 | buf.WriteByte('\n') 103 | } 104 | if value.Text != "" { 105 | buf.WriteString(value.Text) 106 | continue 107 | } 108 | filename := value.Template 109 | if !filepath.IsAbs(filename) { 110 | filename = filepath.Join(extdir, filename) 111 | } 112 | // NOTE: meta header would be ignored 113 | _, temp, err := ParseTemplateFile(filename) 114 | if err != nil { 115 | return "", err 116 | } 117 | pwd := context.Pwd 118 | ctx.Pwd, _ = filepath.Split(filename) 119 | err = temp.Execute(&buf, data) 120 | context.Pwd = pwd 121 | if err != nil { 122 | return "", err 123 | } 124 | } 125 | } 126 | return buf.String(), nil 127 | } 128 | 129 | // JSInitValue returns init value of javascript by Type 130 | func (ctx *Context) JSInitValue(typ build.Type) string { 131 | switch { 132 | case typ.IsInt(): 133 | return "0" 134 | case typ.IsBool(): 135 | return "false" 136 | case typ.IsString(): 137 | return `""` 138 | case typ.IsArray(): 139 | t, ok := typ.(*build.ArrayType) 140 | if ok { 141 | size, ok := build.IntFromExpr(t.Size) 142 | if ok { 143 | return "new Array(" + size + ")" 144 | } 145 | } 146 | case typ.IsVector(): 147 | return "[]" 148 | case typ.IsMap(): 149 | return "{}" 150 | case typ.IsStruct(): 151 | t, ok := typ.(*build.StructType) 152 | if ok { 153 | if bean := ctx.Pkg.FindBean(t.Name); bean != nil && bean.Kind == "enum" { 154 | return "0" 155 | } else { 156 | return "new " + t.String(".") + "()" 157 | } 158 | } 159 | } 160 | return "null" 161 | } 162 | -------------------------------------------------------------------------------- /src/genutil/format.go: -------------------------------------------------------------------------------- 1 | package genutil 2 | 3 | import ( 4 | "os" 5 | "os/exec" 6 | "strings" 7 | ) 8 | 9 | // GoFmt formats go code file 10 | func GoFmt(filename string) error { 11 | if info, err := os.Stat(filename); err != nil || info == nil { 12 | // skip wrong file 13 | return nil 14 | } 15 | if !strings.HasSuffix(filename, ".go") { 16 | // ignore non-golang file 17 | return nil 18 | } 19 | const gofmt = "gofmt" 20 | if _, err := exec.LookPath(gofmt); err != nil { 21 | // do nothing if failed to lookup `gofmt` 22 | return nil 23 | } 24 | cmd := exec.Command(gofmt, "-w", filename) 25 | cmd.Stdout = os.Stdout 26 | cmd.Stderr = os.Stderr 27 | return cmd.Run() 28 | } 29 | 30 | // CppFormat formats cpp code file 31 | func CppFormat(filename string) error { 32 | //TODO 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /src/genutil/template.go: -------------------------------------------------------------------------------- 1 | package genutil 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "fmt" 7 | "io" 8 | "io/ioutil" 9 | "os" 10 | "path/filepath" 11 | "strings" 12 | "text/template" 13 | 14 | "github.com/gopherd/log" 15 | "github.com/mkideal/pkg/errors" 16 | ) 17 | 18 | const ( 19 | // IncludesDir contains template files for `include` and `include_template` functions 20 | IncludesDir = "includes" 21 | 22 | // TemplateFileSuffix is the template filename suffix could be recognized 23 | TemplateFileSuffix = ".temp" 24 | ) 25 | 26 | // Template wraps template.Template 27 | type Template struct { 28 | *template.Template 29 | } 30 | 31 | // NewTemplate creates a Template by template.Template 32 | func NewTemplate(temp *template.Template) *Template { 33 | t := &Template{temp} 34 | return t 35 | } 36 | 37 | // Lookup overrides template.Template.Lookup method 38 | func (temp *Template) Lookup(name string) *Template { 39 | sub := temp.Template.Lookup(name) 40 | if sub == nil { 41 | return nil 42 | } 43 | return NewTemplate(sub) 44 | } 45 | 46 | // OpenTemplatesDir opens a directory for getting all files and directories 47 | func OpenTemplatesDir(lang, dir string) ([]os.FileInfo, error) { 48 | // open templates directory 49 | fs, err := os.Open(dir) 50 | if err != nil { 51 | return nil, errors.Throw(fmt.Sprintf("open templates directory %s error: %v", dir, err)) 52 | } 53 | defer fs.Close() 54 | infos, err := fs.Readdir(-1) 55 | if err != nil { 56 | return nil, errors.Throw(err.Error()) 57 | } 58 | templates := make([]os.FileInfo, 0, len(infos)) 59 | for _, info := range infos { 60 | if info.IsDir() { 61 | continue 62 | } 63 | if !strings.HasSuffix(info.Name(), TemplateFileSuffix) { 64 | continue 65 | } 66 | templates = append(templates, info) 67 | } 68 | return templates, nil 69 | } 70 | 71 | // TemplateMeta represents meta information of a template file 72 | type TemplateMeta struct { 73 | File string 74 | nativeValues, Values map[string]string 75 | } 76 | 77 | // ParseTemplateFile parses template file 78 | func ParseTemplateFile(filename string) (*TemplateMeta, *Template, error) { 79 | meta := &TemplateMeta{ 80 | Values: make(map[string]string), 81 | nativeValues: make(map[string]string), 82 | } 83 | // parse template file meta header 84 | // e.g. 85 | // 86 | // --- 87 | // file: {{.Name}}.go 88 | // --- 89 | data, err := ioutil.ReadFile(filename) 90 | if err != nil { 91 | err = fmt.Errorf("ParseTemplateFile %s: %v", filename, err) 92 | return nil, nil, err 93 | } 94 | advance, token, _ := bufio.ScanLines(data, true) 95 | const metaHeaderFlag = "---" 96 | if string(token) == metaHeaderFlag { 97 | ended := false 98 | line := 1 99 | for advance < len(data) { 100 | tmp, tok, _ := bufio.ScanLines(data[advance:], true) 101 | advance += tmp 102 | if tmp == 0 { 103 | break 104 | } 105 | if string(tok) == metaHeaderFlag { 106 | ended = true 107 | break 108 | } 109 | line++ 110 | kv := strings.SplitN(string(tok), ":", 2) 111 | if len(kv) != 2 { 112 | err = fmt.Errorf("%s:%d: not a key value pair split by `:`", filename, line) 113 | return nil, nil, err 114 | } 115 | kv[0] = strings.TrimSpace(kv[0]) 116 | meta.nativeValues[kv[0]] = kv[1] 117 | } 118 | if !ended { 119 | err = fmt.Errorf("%s: unexpected meta header end", filename) 120 | return nil, nil, err 121 | } 122 | data = data[advance:] 123 | } 124 | temp := template.New(filename) 125 | temp = temp.Funcs(funcs) 126 | temp, err = temp.Parse(string(data)) 127 | if err != nil { 128 | err = fmt.Errorf("ParseTemplateFile %s: %v", filename, err) 129 | return nil, nil, err 130 | } 131 | return meta, NewTemplate(temp), err 132 | } 133 | 134 | // ApplyMeta creates a target file by the template meta 135 | func ApplyMeta(outdir string, meta *TemplateMeta, data interface{}, dftName string) (io.WriteCloser, error) { 136 | // execute template for meta 137 | values := make(map[string]string) 138 | for k, v := range meta.nativeValues { 139 | temp := template.New(k) 140 | temp = temp.Funcs(funcs) 141 | temp, err := temp.Parse(v) 142 | if err != nil { 143 | log.Error().Printf("apply meta error: %v", err) 144 | return nil, err 145 | } 146 | var buf bytes.Buffer 147 | if err = temp.Execute(&buf, data); err != nil { 148 | log.Error().Printf("apply meta error: %v", err) 149 | return nil, err 150 | } 151 | v = strings.TrimSpace(buf.String()) 152 | values[k] = v 153 | log.Debug().Printf("meta key value pair: <%s,%s>", k, v) 154 | } 155 | meta.Values = values 156 | 157 | // pick `file` value to meta.File 158 | if value, ok := meta.Values["file"]; ok { 159 | meta.File = value 160 | delete(meta.Values, "file") 161 | } 162 | if meta.File == "" { 163 | meta.File = dftName 164 | } 165 | 166 | if !filepath.IsAbs(meta.File) { 167 | meta.File = filepath.Join(outdir, meta.File) 168 | } 169 | 170 | _, err := os.Stat(meta.File) 171 | if meta.Values["cond"] != "false" && (err != nil || meta.Values["notexist"] != "true") { 172 | dir, _ := filepath.Split(meta.File) 173 | if dir != "" && dir != "." { 174 | if err := os.MkdirAll(dir, 0755); err != nil { 175 | log.Error().Printf("mkdir %s error: %v", dir, err) 176 | return nil, err 177 | } 178 | } 179 | flags := os.O_CREATE | os.O_WRONLY 180 | if meta.Values["append"] == "true" { 181 | flags |= os.O_APPEND 182 | } else { 183 | flags |= os.O_TRUNC 184 | } 185 | file, err := os.OpenFile(meta.File, flags, 0666) 186 | if err != nil { 187 | log.Error().Printf("open file %s error: %v", meta.File, err) 188 | return nil, err 189 | } 190 | return file, err 191 | } 192 | return discard, nil 193 | } 194 | 195 | type discardWriter struct{} 196 | 197 | var discard = discardWriter{} 198 | 199 | func (w discardWriter) Write(p []byte) (int, error) { return len(p), nil } 200 | func (w discardWriter) Close() error { return nil } 201 | 202 | // ParseTemplateFilename parses template filename: [.suffix[.flags]].temp 203 | // `kind` maybe `package`,`file`,`const` and other bean kinds like `struct`,`protocol`,`service` etc. 204 | // Examples: 205 | // 206 | // struct.go.temp -> (struct, go) 207 | // struct.h.temp -> (struct, h) 208 | // struct.cpp.temp -> (struct, cpp) 209 | // struct.cpp.1.temp -> (struct, cpp) 210 | func ParseTemplateFilename(filename string) (kind, suffix string) { 211 | filename = strings.TrimSuffix(filename, TemplateFileSuffix) 212 | strs := strings.Split(filename, ".") 213 | if len(strs) == 0 { 214 | return filename, "" 215 | } 216 | if len(strs) == 1 { 217 | return strs[0], "" 218 | } 219 | return strs[0], strs[1] 220 | } 221 | -------------------------------------------------------------------------------- /src/genutil/types.go: -------------------------------------------------------------------------------- 1 | package genutil 2 | 3 | import ( 4 | "bytes" 5 | 6 | "github.com/midlang/mid/src/mid/build" 7 | ) 8 | 9 | // Package wraps build.Package 10 | type Package struct { 11 | *build.Package 12 | } 13 | 14 | // Depcrated API, use `Gen' instead 15 | func (pkg Package) GenerateDeclsBySubTemplates() (string, error) { 16 | return pkg.Gen() 17 | } 18 | 19 | // Gen generates file by predefined sub-template `T_const`, `T_group`, `T_` 20 | func (pkg Package) Gen() (string, error) { 21 | buf := new(bytes.Buffer) 22 | 23 | if temp := context.Root.Lookup("T_const"); temp != nil { 24 | constDecls := make([]*GenDecl, 0) 25 | for _, f := range pkg.Files { 26 | for _, c := range f.Decls { 27 | if len(c.Consts) > 0 { 28 | constDecls = append(constDecls, NewGenDecl(f, c)) 29 | } 30 | } 31 | } 32 | if len(constDecls) > 0 { 33 | if err := temp.Execute(buf, constDecls); err != nil { 34 | return "", err 35 | } 36 | } 37 | } 38 | 39 | if temp := context.Root.Lookup("T_group"); temp != nil { 40 | for _, f := range pkg.Files { 41 | context.Filename = f.Filename 42 | for _, g := range f.Groups { 43 | if err := temp.Execute(buf, NewGroup(f, g)); err != nil { 44 | context.Filename = "" 45 | return "", err 46 | } 47 | } 48 | context.Filename = "" 49 | } 50 | } 51 | 52 | for _, f := range pkg.Files { 53 | context.Filename = f.Filename 54 | for _, b := range f.Beans { 55 | if temp := context.Root.Lookup("T_" + b.Kind); temp != nil { 56 | if err := temp.Execute(buf, NewBean(f, b)); err != nil { 57 | context.Filename = "" 58 | return "", err 59 | } 60 | } 61 | } 62 | context.Filename = "" 63 | } 64 | return buf.String(), nil 65 | } 66 | 67 | // File wraps build.File 68 | type File struct { 69 | *build.File 70 | groups map[string]*build.Group 71 | } 72 | 73 | func (f *File) FindGroup(name string) *build.Group { 74 | if f.groups == nil { 75 | f.groups = make(map[string]*build.Group) 76 | pendings := make(map[string]*build.Group) 77 | for _, g := range f.Groups { 78 | pendings[g.Name] = g 79 | } 80 | for len(pendings) > 0 { 81 | var first *build.Group 82 | for _, v := range pendings { 83 | first = v 84 | break 85 | } 86 | delete(pendings, first.Name) 87 | f.groups[first.Name] = first 88 | for _, g := range first.Groups { 89 | pendings[g.Name] = g 90 | } 91 | } 92 | } 93 | return f.groups[name] 94 | } 95 | 96 | // Depcrated API, use `Gen' instead 97 | func (f File) GenerateDeclsBySubTemplates() (string, error) { 98 | return f.Gen() 99 | } 100 | 101 | // Gen generates file by predefined sub-template `T_const`, `T_` 102 | func (f File) Gen() (string, error) { 103 | buf := new(bytes.Buffer) 104 | 105 | if temp := context.Root.Lookup("T_const"); temp != nil { 106 | for _, c := range f.Decls { 107 | if len(c.Consts) > 0 { 108 | if err := temp.Execute(buf, NewGenDecl(f.File, c)); err != nil { 109 | return "", err 110 | } 111 | } 112 | } 113 | } 114 | 115 | for _, b := range f.Beans { 116 | context.Filename = f.Filename 117 | if temp := context.Root.Lookup("T_" + b.Kind); temp != nil { 118 | if err := temp.Execute(buf, NewBean(f.File, b)); err != nil { 119 | context.Filename = "" 120 | return "", err 121 | } 122 | } 123 | context.Filename = "" 124 | } 125 | return buf.String(), nil 126 | } 127 | 128 | // GenDecl wraps build.GenDecl 129 | type GenDecl struct { 130 | *build.GenDecl 131 | File *File 132 | } 133 | 134 | func NewGenDecl(file *build.File, c *build.GenDecl) *GenDecl { 135 | return &GenDecl{ 136 | GenDecl: c, 137 | File: &File{File: file}, 138 | } 139 | } 140 | 141 | // Bean wraps build.Bean 142 | type Bean struct { 143 | *build.Bean 144 | File *File 145 | } 146 | 147 | func NewBean(file *build.File, b *build.Bean) *Bean { 148 | return &Bean{ 149 | Bean: b, 150 | File: &File{File: file}, 151 | } 152 | } 153 | 154 | // Extends gets extends of bean as a string slice 155 | func (bean *Bean) BuildExtends(ctx *Context) []string { 156 | extends := bean.Bean.Extends 157 | if len(extends) == 0 { 158 | return nil 159 | } 160 | var strs []string 161 | for _, ex := range extends { 162 | strs = append(strs, ctx.BuildType(ex)) 163 | } 164 | return strs 165 | } 166 | 167 | // AddTag is a chain function for adding tag 168 | func (bean *Bean) AddTag(key, value string, field *build.Field) *build.Field { 169 | return bean.addTag(key, value, field, true) 170 | } 171 | 172 | func (bean *Bean) AddTagNX(key, value string, field *build.Field) *build.Field { 173 | return bean.addTag(key, value, field, false) 174 | } 175 | 176 | func (bean *Bean) addTag(key, value string, field *build.Field, force bool) *build.Field { 177 | _, found := field.Tag.Lookup(key) 178 | if !found || force { 179 | field.Tag.Set(key, value) 180 | } 181 | return field 182 | } 183 | 184 | // Group wraps build.Group 185 | type Group struct { 186 | *build.Group 187 | File *File 188 | } 189 | 190 | func NewGroup(file *build.File, g *build.Group) *Group { 191 | return &Group{ 192 | Group: g, 193 | File: &File{File: file}, 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /src/genutil/values.go: -------------------------------------------------------------------------------- 1 | package genutil 2 | 3 | import ( 4 | "strconv" 5 | ) 6 | 7 | type Bool bool 8 | 9 | func (b Bool) Get() bool { return bool(b) } 10 | func (b *Bool) Set(v bool) string { *b = Bool(v); return "" } 11 | func (b Bool) String() string { return strconv.FormatBool(bool(b)) } 12 | 13 | type String string 14 | 15 | func (s String) Get() string { return string(s) } 16 | func (s *String) Set(v string) string { *s = String(v); return "" } 17 | func (s String) String() string { return string(s) } 18 | 19 | type Int int64 20 | 21 | func (i Int) Get() int64 { return int64(i) } 22 | func (i Int) Int() int { return int(i) } 23 | func (i *Int) Set(v int64) string { *i = Int(v); return "" } 24 | func (i *Int) Add(delta int64) int64 { return i.Get() + delta } 25 | func (i *Int) Sub(delta int64) int64 { return i.Get() - delta } 26 | func (i *Int) Incr(delta int64) int64 { i.Set(i.Get() + delta); return i.Get() } 27 | func (i Int) String() string { return strconv.FormatInt(int64(i), 10) } 28 | -------------------------------------------------------------------------------- /src/mid/ast/scope.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | 7 | "github.com/midlang/mid/src/mid/lexer" 8 | ) 9 | 10 | // A Scope maintains the set of named language entities declared 11 | // in the scope and a link to the immediately surrounding (outer) 12 | // scope. 13 | // 14 | type Scope struct { 15 | Outer *Scope 16 | Objects map[string]*Object 17 | } 18 | 19 | // NewScope creates a new scope nested in the outer scope. 20 | func NewScope(outer *Scope) *Scope { 21 | const n = 4 // initial scope capacity 22 | return &Scope{outer, make(map[string]*Object, n)} 23 | } 24 | 25 | // Lookup returns the object with the given name if it is 26 | // found in scope s, otherwise it returns nil. Outer scopes 27 | // are ignored. 28 | // 29 | func (s *Scope) Lookup(name string) *Object { 30 | return s.Objects[name] 31 | } 32 | 33 | // Insert attempts to insert a named object obj into the scope s. 34 | // If the scope already contains an object alt with the same name, 35 | // Insert leaves the scope unchanged and returns alt. Otherwise 36 | // it inserts obj and returns nil. 37 | // 38 | func (s *Scope) Insert(obj *Object) (alt *Object) { 39 | if alt = s.Objects[obj.Name]; alt == nil { 40 | s.Objects[obj.Name] = obj 41 | } 42 | return 43 | } 44 | 45 | // Debugging support 46 | func (s *Scope) String() string { 47 | var buf bytes.Buffer 48 | fmt.Fprintf(&buf, "scope %p {", s) 49 | if s != nil && len(s.Objects) > 0 { 50 | fmt.Fprintln(&buf) 51 | for _, obj := range s.Objects { 52 | fmt.Fprintf(&buf, "\t%s %s\n", obj.Kind, obj.Name) 53 | } 54 | } 55 | fmt.Fprintf(&buf, "}\n") 56 | return buf.String() 57 | } 58 | 59 | type Object struct { 60 | Kind ObjKind 61 | Name string 62 | Decl interface{} // Field,Spec,Decl or Scope 63 | Data interface{} 64 | } 65 | 66 | // NewObj creates a new object of a given kind and name. 67 | func NewObj(kind ObjKind, name string) *Object { 68 | return &Object{Kind: kind, Name: name} 69 | } 70 | 71 | func (obj *Object) Begin() lexer.Pos { 72 | name := obj.Name 73 | switch d := obj.Decl.(type) { 74 | case *Field: 75 | for _, n := range d.Names { 76 | if n.Name == name { 77 | return n.Begin() 78 | } 79 | } 80 | case *ImportSpec: 81 | if d.Name != nil && d.Name.Name == name { 82 | return d.Name.Begin() 83 | } 84 | return d.Package.Begin() 85 | case *ConstSpec: 86 | return d.Begin() 87 | case *GenDecl: 88 | return d.Begin() 89 | case *BeanDecl: 90 | return d.Begin() 91 | case *Scope: 92 | // nothing to do 93 | } 94 | return lexer.NoPos 95 | } 96 | 97 | type ObjKind int 98 | 99 | const ( 100 | Bad ObjKind = iota 101 | Pkg 102 | Const 103 | Var 104 | Bean 105 | Fun 106 | ) 107 | 108 | var objKindStrings = [...]string{ 109 | Bad: "bad", 110 | Pkg: "package", 111 | Const: "const", 112 | Var: "var", 113 | Bean: "bean", 114 | Fun: "func", 115 | } 116 | 117 | func (kind ObjKind) String() string { return objKindStrings[kind] } 118 | -------------------------------------------------------------------------------- /src/mid/build/builder.go: -------------------------------------------------------------------------------- 1 | package build 2 | 3 | import ( 4 | "bytes" 5 | "encoding/base64" 6 | "encoding/gob" 7 | "fmt" 8 | "log" 9 | "sort" 10 | "strings" 11 | 12 | "github.com/midlang/mid/src/mid/ast" 13 | ) 14 | 15 | func init() { 16 | gob.Register(&Builder{}) 17 | gob.Register(map[string]*Package{}) 18 | } 19 | 20 | type ObjectId string 21 | 22 | func (id ObjectId) IsValid() bool { return id != "" } 23 | 24 | func (id ObjectId) index(pre bool) int { 25 | i := strings.Index(string(id), ".") 26 | if i < 0 { 27 | if pre { 28 | i = 0 29 | } else { 30 | i = -1 31 | } 32 | } 33 | return i 34 | } 35 | 36 | func (id ObjectId) Package() string { 37 | return string(id[:id.index(true)]) 38 | } 39 | 40 | func (id ObjectId) Name() string { 41 | return string(id[id.index(false)+1:]) 42 | } 43 | 44 | func (id ObjectId) String() string { return string(id) } 45 | 46 | // Builder 47 | type Builder struct { 48 | Packages map[string]*Package 49 | SortedPackages []*Package 50 | encodedString string 51 | } 52 | 53 | func NewBuilder() *Builder { 54 | return &Builder{ 55 | Packages: map[string]*Package{}, 56 | } 57 | } 58 | 59 | func Build(pkgs map[string]*ast.Package) (*Builder, error) { 60 | builder := NewBuilder() 61 | for _, pkg := range pkgs { 62 | for _, file := range pkg.Files { 63 | for _, imp := range file.Imports { 64 | _, pkgId := imp.Package.IsString() 65 | importedPkg, ok := pkgs[pkgId] 66 | if !ok { 67 | return nil, fmt.Errorf("package `%s` not found", pkgId) 68 | } 69 | obj := ast.NewObj(ast.Pkg, importedPkg.Name) 70 | obj.Decl = importedPkg 71 | pkg.Imports[pkgId] = obj 72 | } 73 | } 74 | } 75 | for _, pkg := range pkgs { 76 | builtPkg := BuildPackage(pkg) 77 | builder.Packages[pkg.Name] = builtPkg 78 | builder.SortedPackages = append(builder.SortedPackages, builtPkg) 79 | } 80 | sort.Slice(builder.SortedPackages, func(i, j int) bool { 81 | return builder.SortedPackages[i].Name < builder.SortedPackages[j].Name 82 | }) 83 | return builder, nil 84 | } 85 | 86 | func (builder *Builder) Encode() string { 87 | if builder.encodedString != "" { 88 | return builder.encodedString 89 | } 90 | buf := new(bytes.Buffer) 91 | err := gob.NewEncoder(buf).Encode(builder) 92 | if err != nil { 93 | log.Fatalf("encode builder error: %v", err) 94 | } 95 | builder.encodedString = base64.StdEncoding.EncodeToString(buf.Bytes()) 96 | return builder.encodedString 97 | } 98 | 99 | func (builder *Builder) Decode(s string) error { 100 | data, err := base64.StdEncoding.DecodeString(s) 101 | if err != nil { 102 | return err 103 | } 104 | return gob.NewDecoder(bytes.NewBuffer(data)).Decode(builder) 105 | } 106 | -------------------------------------------------------------------------------- /src/mid/build/extension.go: -------------------------------------------------------------------------------- 1 | package build 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "fmt" 7 | "io/ioutil" 8 | "path/filepath" 9 | "strings" 10 | 11 | "github.com/midlang/mid/src/mid" 12 | ) 13 | 14 | var ( 15 | ErrExtensionName = errors.New("invalid extension name") 16 | ) 17 | 18 | const ( 19 | // positions 20 | FileHead = "file_head" 21 | BeforeImport = "before_import" 22 | InImport = "in_import" 23 | AfterImport = "after_import" 24 | BeforeConst = "before_const" 25 | AfterConst = "after_const" 26 | ConstFront = "const_front" 27 | ConstBack = "const_back" 28 | BeforeEnum = "before_enum" 29 | EnumFront = "enum_front" 30 | EnumBack = "enum_back" 31 | AfterEnum = "after_enum" 32 | BeforeStruct = "before_struct" 33 | StructFront = "struct_front" 34 | StructBack = "struct_back" 35 | AfterStruct = "after_struct" 36 | BeforeProtocol = "before_protocol" 37 | ProtocolFront = "protocol_front" 38 | ProtocolBack = "protocol_back" 39 | AfterProtocol = "after_protocol" 40 | BeforeService = "before_service" 41 | ServiceFront = "service_front" 42 | ServiceBack = "service_back" 43 | AfterService = "after_service" 44 | 45 | // Extension config filename 46 | ExtConfigFilename = "ext.json" 47 | ) 48 | 49 | func IsValidKind(kind string) bool { 50 | switch kind { 51 | case "package", "file", "const", "enum", "struct", "protocol", "service": 52 | return true 53 | default: 54 | return false 55 | } 56 | } 57 | 58 | type EmbeddedPosition string 59 | 60 | func (pos EmbeddedPosition) IsValid() bool { 61 | switch pos { 62 | case FileHead, 63 | BeforeImport, 64 | InImport, 65 | AfterImport, 66 | BeforeConst, 67 | ConstFront, 68 | ConstBack, 69 | AfterConst, 70 | BeforeEnum, 71 | EnumFront, 72 | EnumBack, 73 | AfterEnum, 74 | BeforeStruct, 75 | StructFront, 76 | StructBack, 77 | AfterStruct, 78 | BeforeProtocol, 79 | ProtocolFront, 80 | ProtocolBack, 81 | AfterProtocol, 82 | BeforeService, 83 | ServiceFront, 84 | ServiceBack, 85 | AfterService: 86 | default: 87 | return false 88 | } 89 | return true 90 | } 91 | 92 | func (pos EmbeddedPosition) Match(at string) bool { 93 | return string(pos) == at 94 | } 95 | 96 | type EmbeddedValue struct { 97 | Text string `join:"text"` 98 | Template string `json:"template"` 99 | Suffix string `json:"suffix"` 100 | Kinds []string `json:"kinds"` 101 | } 102 | 103 | func (v EmbeddedValue) IsValid() bool { 104 | valid := (v.Text != "" && v.Template == "") || (v.Text == "" && v.Template != "") 105 | if !valid { 106 | return false 107 | } 108 | for _, kind := range v.Kinds { 109 | if !IsValidKind(kind) { 110 | return false 111 | } 112 | } 113 | return true 114 | } 115 | 116 | func (v EmbeddedValue) MatchKind(kind string) bool { 117 | if len(v.Kinds) == 0 { 118 | return true 119 | } 120 | for _, k := range v.Kinds { 121 | if k == kind { 122 | return true 123 | } 124 | } 125 | return false 126 | } 127 | 128 | type Extension struct { 129 | Name string `json:"name"` 130 | Author string `json:"author"` 131 | URL string `json:"url"` 132 | Version string `json:"version"` 133 | Deps []string `json:"deps"` 134 | // language -> position -> embedded_values 135 | EmbeddedAt map[string]map[EmbeddedPosition][]EmbeddedValue `json:"at"` 136 | 137 | Path string `json:"path"` 138 | } 139 | 140 | func (e Extension) Find(lang, kind, at string) []EmbeddedValue { 141 | if e.EmbeddedAt == nil { 142 | return nil 143 | } 144 | m, ok := e.EmbeddedAt[lang] 145 | if !ok || m == nil { 146 | return nil 147 | } 148 | values := make([]EmbeddedValue, 0) 149 | for pos, vals := range m { 150 | if pos.Match(at) { 151 | for _, val := range vals { 152 | if val.MatchKind(kind) { 153 | values = append(values, val) 154 | } 155 | } 156 | } 157 | } 158 | return values 159 | } 160 | 161 | type ExtensionKey struct { 162 | Author string 163 | Name string 164 | } 165 | 166 | func GetExtensionKey(name string) (ExtensionKey, error) { 167 | key := ExtensionKey{} 168 | strs := strings.SplitN(name, "/", 2) 169 | if len(strs) == 0 { 170 | return key, ErrExtensionName 171 | } 172 | if len(strs) == 1 { 173 | key.Author = mid.Meta.String("officialAuthor") 174 | key.Name = name 175 | } else { 176 | key.Author = strs[0] 177 | key.Name = strs[1] 178 | } 179 | return key, nil 180 | } 181 | 182 | func (key ExtensionKey) Path(rootdir string) string { 183 | return filepath.Join(rootdir, key.Subdir()) 184 | } 185 | 186 | func (key ExtensionKey) Subdir() string { 187 | return filepath.Join(key.Author, key.Name) 188 | } 189 | 190 | func LoadExtensions(rootdir string, names []string) ([]Extension, error) { 191 | seen := map[ExtensionKey]bool{} 192 | exts := make([]Extension, 0, len(names)) 193 | for _, name := range names { 194 | key, err := GetExtensionKey(name) 195 | if err != nil { 196 | return nil, err 197 | } 198 | if seen[key] { 199 | continue 200 | } 201 | seen[key] = true 202 | data, err := ioutil.ReadFile(filepath.Join(key.Path(rootdir), ExtConfigFilename)) 203 | if err != nil { 204 | return nil, err 205 | } 206 | ext := Extension{} 207 | if err := json.Unmarshal(data, &ext); err != nil { 208 | return nil, err 209 | } 210 | if ext.Author == "" { 211 | ext.Author = key.Author 212 | } 213 | if ext.Name == "" { 214 | ext.Name = key.Name 215 | } 216 | ext.Path = key.Subdir() 217 | if ext.EmbeddedAt != nil { 218 | for lang, x := range ext.EmbeddedAt { 219 | if x != nil { 220 | for pos, values := range x { 221 | if !pos.IsValid() { 222 | return nil, fmt.Errorf("extension %s lang %s: invalid pos %s", name, lang, pos) 223 | } 224 | for i, value := range values { 225 | if !value.IsValid() { 226 | return nil, fmt.Errorf("extension %s lang %s: %dth: invalid value %s", name, lang, i+1, value) 227 | } 228 | } 229 | } 230 | } 231 | } 232 | } 233 | exts = append(exts, ext) 234 | } 235 | return exts, nil 236 | } 237 | -------------------------------------------------------------------------------- /src/mid/build/id_allocator.go: -------------------------------------------------------------------------------- 1 | package build 2 | 3 | import ( 4 | "bufio" 5 | "errors" 6 | "fmt" 7 | "io" 8 | "io/ioutil" 9 | "math/rand" 10 | "os" 11 | "sort" 12 | "strconv" 13 | "strings" 14 | "time" 15 | ) 16 | 17 | func init() { 18 | rand.Seed(time.Now().UnixNano()) 19 | } 20 | 21 | type BeanIdAllocator interface { 22 | // Allocate returns a integer as id of key 23 | Allocate(key string) int 24 | // Output outputs all key-id pairs to writer w or outputs to default writer of allocator if w is nil 25 | Output(w io.Writer) error 26 | } 27 | 28 | type IdPair struct { 29 | Key string 30 | Id int 31 | } 32 | 33 | func JoinBeanKey(pkgName, beanName string) string { 34 | return pkgName + "." + beanName 35 | } 36 | 37 | func SplitBeanKey(key string) (pkgName, beanName string) { 38 | index := strings.LastIndex(key, ".") 39 | if index >= 0 { 40 | return key[:index], key[index+1:] 41 | } 42 | return "", key 43 | } 44 | 45 | func NewBeanIdAllocator(name, opts string) (BeanIdAllocator, error) { 46 | switch name { 47 | case "file": 48 | return NewFileBeanIdAllocator(opts) 49 | default: 50 | return nil, errors.New("unsupported bean id allocator: " + name) 51 | } 52 | } 53 | 54 | // fileBeanIdAllocator implements BeanIdAllocator 55 | type fileBeanIdAllocator struct { 56 | filename string 57 | perm os.FileMode 58 | idMap map[string]int 59 | ids []IdPair 60 | maxId int 61 | } 62 | 63 | func NewFileBeanIdAllocator(filename string) (BeanIdAllocator, error) { 64 | allocator := &fileBeanIdAllocator{ 65 | filename: filename, 66 | idMap: make(map[string]int), 67 | } 68 | if err := allocator.readInit(); err != nil { 69 | return nil, err 70 | } 71 | return allocator, nil 72 | } 73 | 74 | // Allocate allocates id for key if key not found and returns allocated id 75 | // Found id returned if key found 76 | func (allocator *fileBeanIdAllocator) Allocate(key string) int { 77 | if id, found := allocator.idMap[key]; found { 78 | return id 79 | } 80 | allocator.maxId += 1 + rand.Intn(5) 81 | id := allocator.maxId 82 | allocator.idMap[key] = id 83 | allocator.ids = append(allocator.ids, IdPair{Key: key, Id: id}) 84 | return id 85 | } 86 | 87 | // Output outputs key-id pairs to writer w or outputs to file allocator.filename if w is nil 88 | func (allocator *fileBeanIdAllocator) Output(w io.Writer) error { 89 | if len(allocator.ids) == 0 { 90 | return nil 91 | } 92 | if w == nil { 93 | file, err := os.OpenFile(allocator.filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, allocator.perm) 94 | if err != nil { 95 | return err 96 | } 97 | defer file.Close() 98 | w = file 99 | } 100 | sort.Slice(allocator.ids, func(i, j int) bool { return allocator.ids[i].Id < allocator.ids[j].Id }) 101 | for _, pair := range allocator.ids { 102 | fmt.Fprintf(w, "%s=%d\n", pair.Key, pair.Id) 103 | } 104 | return nil 105 | } 106 | 107 | // readInit reads file to initialize allocator 108 | func (allocator *fileBeanIdAllocator) readInit() error { 109 | info, err := os.Stat(allocator.filename) 110 | if err != nil { 111 | if os.IsNotExist(err) { 112 | allocator.perm = 0666 113 | return nil 114 | } 115 | return err 116 | } 117 | if info.IsDir() { 118 | return errors.New(allocator.filename + " is not a regular file") 119 | } 120 | allocator.perm = info.Mode() 121 | file, err := os.Open(allocator.filename) 122 | if err != nil { 123 | return err 124 | } 125 | defer file.Close() 126 | idMap, err := ReadBeanIds(file, "=") 127 | if err != nil { 128 | return err 129 | } 130 | allocator.idMap = idMap 131 | for key, id := range idMap { 132 | if len(allocator.ids) == 0 || allocator.maxId < id { 133 | allocator.maxId = id 134 | } 135 | allocator.ids = append(allocator.ids, IdPair{Key: key, Id: id}) 136 | } 137 | return nil 138 | } 139 | 140 | // ReadBeanIds read key-id pairs from reader. 141 | // Each line contains one key-id pair seperated by `sep`. 142 | func ReadBeanIds(reader io.Reader, sep string) (map[string]int, error) { 143 | var ( 144 | idMap = make(map[string]int) 145 | advance int 146 | token []byte 147 | ) 148 | data, err := ioutil.ReadAll(reader) 149 | if err != nil { 150 | return nil, err 151 | } 152 | count := 0 153 | for advance < len(data) { 154 | count++ 155 | lineno := fmt.Sprintf("line %d: ", count) 156 | total := advance 157 | advance, token, _ = bufio.ScanLines(data[advance:], true) 158 | if advance == 0 { 159 | break 160 | } 161 | advance = total + advance 162 | tok := strings.TrimSpace(string(token)) 163 | if tok == "" { 164 | continue 165 | } 166 | kv := strings.SplitN(tok, sep, 2) 167 | if len(kv) != 2 { 168 | return nil, errors.New(lineno + string(token) + " is not a key value pair seperated by " + sep) 169 | } 170 | key, value := strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1]) 171 | id, err := strconv.Atoi(value) 172 | if err != nil { 173 | return nil, errors.New(lineno + value + " is not an integer") 174 | } 175 | idMap[key] = id 176 | } 177 | return idMap, nil 178 | } 179 | -------------------------------------------------------------------------------- /src/mid/build/plugin.go: -------------------------------------------------------------------------------- 1 | package build 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "fmt" 7 | "io" 8 | "io/ioutil" 9 | "os" 10 | "os/exec" 11 | "strconv" 12 | "strings" 13 | ) 14 | 15 | type PluginRuntimeConfig struct { 16 | Verbose string 17 | Outdir string 18 | ExtentionsDir string 19 | Extensions []Extension 20 | Envvars map[string]string 21 | } 22 | 23 | func (config PluginRuntimeConfig) Encode() string { 24 | data, _ := json.Marshal(config) 25 | return string(data) 26 | } 27 | 28 | func (config *PluginRuntimeConfig) Decode(s string) error { 29 | return json.Unmarshal([]byte(s), config) 30 | } 31 | 32 | func (config *PluginRuntimeConfig) Getenv(name string) string { 33 | if config.Envvars == nil { 34 | return "" 35 | } 36 | return config.Envvars[name] 37 | } 38 | 39 | func (config *PluginRuntimeConfig) BoolEnv(name string) bool { 40 | if config.Envvars != nil { 41 | v, found := config.Envvars[name] 42 | if found && v == "" { 43 | return true 44 | } 45 | } 46 | s := config.Getenv(name) 47 | b, _ := strconv.ParseBool(s) 48 | return b 49 | } 50 | 51 | func (config *PluginRuntimeConfig) IntEnv(name string) int64 { 52 | s := config.Getenv(name) 53 | i, _ := strconv.ParseInt(s, 0, 64) 54 | return i 55 | } 56 | 57 | func (config *PluginRuntimeConfig) UintEnv(name string) uint64 { 58 | s := config.Getenv(name) 59 | u, _ := strconv.ParseUint(s, 0, 64) 60 | return u 61 | } 62 | 63 | func (config *PluginRuntimeConfig) FloatEnv(name string) float64 { 64 | s := config.Getenv(name) 65 | f, _ := strconv.ParseFloat(s, 64) 66 | return f 67 | } 68 | 69 | type Plugin struct { 70 | Lang string `json:"lang"` 71 | Name string `json:"name"` 72 | Bin string `json:"bin"` 73 | TemplatesDir string `json:"templates,omitempty"` 74 | 75 | RuntimeConfig PluginRuntimeConfig `json:"-"` 76 | } 77 | 78 | func (plugin *Plugin) Init() error { 79 | bin, err := exec.LookPath(plugin.Bin) 80 | if err != nil { 81 | return err 82 | } 83 | plugin.Bin = bin 84 | return nil 85 | } 86 | 87 | func (plugin Plugin) Generate(builder *Builder, stdout, stderr io.Writer) error { 88 | source := builder.Encode() 89 | runtimeConfig := plugin.RuntimeConfig.Encode() 90 | encodedPlugin, err := json.Marshal(plugin) 91 | if err != nil { 92 | return err 93 | } 94 | cmd := exec.Command(plugin.Bin, 95 | "-p", string(encodedPlugin), 96 | "-c", runtimeConfig, 97 | ) 98 | cmd.Stdin = strings.NewReader(source) 99 | if stdout != nil { 100 | cmd.Stdout = stdout 101 | } 102 | if stderr != nil { 103 | cmd.Stderr = stderr 104 | } 105 | return cmd.Run() 106 | } 107 | 108 | type PluginSet struct { 109 | plugins []*Plugin 110 | } 111 | 112 | func NewPluginSet() *PluginSet { 113 | return &PluginSet{plugins: []*Plugin{}} 114 | } 115 | 116 | func (pset *PluginSet) Len() int { 117 | return len(pset.plugins) 118 | } 119 | 120 | func (pset *PluginSet) Register(plugin Plugin) error { 121 | if _, existed := pset.Lookup(plugin.Lang); existed { 122 | return fmt.Errorf("plugin %s existed", plugin.Lang) 123 | } 124 | pset.plugins = append(pset.plugins, &plugin) 125 | return nil 126 | } 127 | 128 | func (pset *PluginSet) Lookup(lang string) (*Plugin, bool) { 129 | for _, plugin := range pset.plugins { 130 | if plugin.Lang == lang { 131 | return plugin, true 132 | } 133 | } 134 | return nil, false 135 | } 136 | 137 | func ParseFlags() (plugin Plugin, config PluginRuntimeConfig, builder *Builder, err error) { 138 | flPlugin := flag.String("p", "", "plugin information which encoded with json") 139 | flConfig := flag.String("c", "", "plugin runtime config which encoded with json") 140 | flSource := flag.String("src", "", "AST source which encoded with job and base64") 141 | flag.Parse() 142 | 143 | if err = json.Unmarshal([]byte(*flPlugin), &plugin); err != nil { 144 | err = fmt.Errorf("decode plugin error: %v", err) 145 | return 146 | } 147 | if err = config.Decode(*flConfig); err != nil { 148 | err = fmt.Errorf("decode config error: %v", err) 149 | return 150 | } 151 | builder = new(Builder) 152 | var source string 153 | if *flSource != "" { 154 | source = *flSource 155 | } else { 156 | var content []byte 157 | content, err = ioutil.ReadAll(os.Stdin) 158 | if err != nil { 159 | err = fmt.Errorf("read source error: %v", err) 160 | return 161 | } 162 | source = string(content) 163 | } 164 | if err = builder.Decode(source); err != nil { 165 | err = fmt.Errorf("decode source error: %v", err) 166 | } 167 | return 168 | } 169 | -------------------------------------------------------------------------------- /src/mid/build/types_test.go: -------------------------------------------------------------------------------- 1 | package build 2 | 3 | import "testing" 4 | 5 | func TestParseTag(t *testing.T) { 6 | var tag = Tag(`key:"value"`) 7 | t.Logf("tag.key=%s", tag.Get("key")) 8 | } 9 | -------------------------------------------------------------------------------- /src/mid/lexer/token.go: -------------------------------------------------------------------------------- 1 | package lexer 2 | 3 | import ( 4 | "strconv" 5 | ) 6 | 7 | type Token int 8 | 9 | const ( 10 | ILLEGAL Token = iota 11 | EOF 12 | COMMENT 13 | 14 | literal_beg 15 | IDENT // main 16 | INT // 12345 17 | FLOAT // 123.45 18 | CHAR // 'a' 19 | STRING // "abc" 20 | literal_end 21 | 22 | operator_beg 23 | LPAREN // ( 24 | RPAREN // ) 25 | LBRACK // [ 26 | RBRACK // ] 27 | LBRACE // { 28 | RBRACE // } 29 | LESS // < 30 | GREATER // > 31 | COMMA // , 32 | PERIOD // . 33 | SEMICOLON // ; 34 | COLON // : 35 | ASSIGN // = 36 | AT // @ @function(args) 37 | DOLLAR // $ env variable 38 | SHARP // # 39 | operator_end 40 | 41 | keyword_beg 42 | PACKAGE // package 43 | IMPORT // import 44 | ENUM // enum 45 | CONST // const 46 | STRUCT // struct 47 | PROTOCOL // protocol 48 | SERVICE // service 49 | REQUIRED // required 50 | OPTIONAL // optional 51 | EXTENDS // extends 52 | keyword_end 53 | ) 54 | 55 | const Group = "group" 56 | 57 | var tokens = [...]string{ 58 | ILLEGAL: "ILLEGAL", 59 | 60 | EOF: "EOF", 61 | COMMENT: "COMMENT", 62 | 63 | IDENT: "IDENT", 64 | INT: "INT", 65 | FLOAT: "FLOAT", 66 | CHAR: "CHAR", 67 | STRING: "STRING", 68 | 69 | LPAREN: "(", 70 | RPAREN: ")", 71 | LBRACK: "[", 72 | RBRACK: "]", 73 | LBRACE: "{", 74 | RBRACE: "}", 75 | LESS: "<", 76 | GREATER: ">", 77 | COMMA: ",", 78 | PERIOD: ".", 79 | SEMICOLON: ";", 80 | COLON: ":", 81 | ASSIGN: "=", 82 | AT: "@", 83 | DOLLAR: "$", 84 | SHARP: "#", 85 | 86 | PACKAGE: "package", 87 | IMPORT: "import", 88 | ENUM: "enum", 89 | CONST: "const", 90 | STRUCT: "struct", 91 | PROTOCOL: "protocol", 92 | SERVICE: "service", 93 | REQUIRED: "required", 94 | OPTIONAL: "optional", 95 | EXTENDS: "extends", 96 | } 97 | 98 | func (tok Token) String() string { 99 | s := "" 100 | if 0 <= tok && tok < Token(len(tokens)) { 101 | s = tokens[tok] 102 | } 103 | if s == "" { 104 | s = "token(" + strconv.Itoa(int(tok)) + ")" 105 | } 106 | return s 107 | } 108 | 109 | var ( 110 | keywords map[string]Token 111 | operators map[string]Token 112 | ) 113 | 114 | func init() { 115 | keywords = make(map[string]Token) 116 | for i := keyword_beg + 1; i < keyword_end; i++ { 117 | keywords[tokens[i]] = i 118 | } 119 | operators = make(map[string]Token) 120 | for i := operator_beg + 1; i < operator_end; i++ { 121 | operators[tokens[i]] = i 122 | } 123 | } 124 | 125 | func Lookup(ident string) Token { 126 | if tok, is_keyword := keywords[ident]; is_keyword { 127 | return tok 128 | } 129 | return IDENT 130 | } 131 | 132 | func LookupOperator(lit string) (Token, bool) { 133 | if op, ok := operators[lit]; ok { 134 | return op, true 135 | } 136 | return ILLEGAL, false 137 | } 138 | 139 | func (tok Token) IsLiteral() bool { return literal_beg < tok && tok < literal_end } 140 | func (tok Token) IsOperator() bool { return operator_beg < tok && tok < operator_end } 141 | func (tok Token) IsKeyword() bool { return keyword_beg < tok && tok < keyword_end } 142 | 143 | type BuiltinType int 144 | 145 | const ( 146 | Any BuiltinType = iota // any 147 | Bool // bool 148 | Byte // byte 149 | Bytes // bytes 150 | String // string 151 | Int // int 152 | Int8 // int8 153 | Int16 // int16 154 | Int32 // int32 155 | Int64 // int64 156 | Uint // uint 157 | Uint8 // uint8 158 | Uint16 // uint16 159 | Uint32 // uint32 160 | Uint64 // uint64 161 | Float32 // float32 162 | Float64 // float64 163 | Map // map 164 | Vector // vector 165 | Array // array 166 | ) 167 | 168 | var builtinTypes = [...]string{ 169 | Any: "any", 170 | Bool: "bool", 171 | Byte: "byte", 172 | Bytes: "bytes", 173 | String: "string", 174 | Int: "int", 175 | Int8: "int8", 176 | Int16: "int16", 177 | Int32: "int32", 178 | Int64: "int64", 179 | Uint: "uint", 180 | Uint8: "uint8", 181 | Uint16: "uint16", 182 | Uint32: "uint32", 183 | Uint64: "uint64", 184 | Float32: "float32", 185 | Float64: "float64", 186 | Map: "map", 187 | Vector: "vector", 188 | Array: "array", 189 | } 190 | 191 | var revBuiltinTypes = make(map[string]BuiltinType) 192 | 193 | func init() { 194 | for t, s := range builtinTypes { 195 | revBuiltinTypes[s] = BuiltinType(t) 196 | } 197 | } 198 | 199 | func LookupType(ident string) (BuiltinType, bool) { 200 | t, ok := revBuiltinTypes[ident] 201 | return t, ok 202 | } 203 | 204 | func (bt BuiltinType) String() string { 205 | if int(bt) >= 0 && int(bt) < len(builtinTypes) { 206 | return builtinTypes[int(bt)] 207 | } 208 | return "" 209 | } 210 | 211 | func (bt BuiltinType) IsInt() bool { 212 | switch bt { 213 | case Byte, 214 | Int, 215 | Int8, 216 | Int16, 217 | Int32, 218 | Int64, 219 | Uint, 220 | Uint8, 221 | Uint16, 222 | Uint32, 223 | Uint64: 224 | return true 225 | } 226 | return false 227 | } 228 | 229 | func (bt BuiltinType) IsFloat() bool { return bt == Float32 || bt == Float64 } 230 | func (bt BuiltinType) IsNumber() bool { return bt.IsInt() || bt.IsFloat() } 231 | func (bt BuiltinType) IsContainer() bool { return bt == Array || bt == Map || bt == Vector } 232 | -------------------------------------------------------------------------------- /src/mid/meta.go: -------------------------------------------------------------------------------- 1 | package mid 2 | 3 | import "fmt" 4 | 5 | type Map map[string]interface{} 6 | 7 | func (m Map) String(key string) string { 8 | v, ok := m[key] 9 | if !ok || v == nil { 10 | return "" 11 | } 12 | switch x := v.(type) { 13 | case string: 14 | return x 15 | case []byte: 16 | return string(x) 17 | default: 18 | return fmt.Sprintf("%v", v) 19 | } 20 | } 21 | 22 | var Meta = Map{ 23 | "version": "0.1.11", 24 | "officialAuthor": "midc", 25 | } 26 | -------------------------------------------------------------------------------- /src/mid/parser/parser_test.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "log" 7 | "os" 8 | "testing" 9 | 10 | "github.com/midlang/mid/src/mid/ast" 11 | "github.com/midlang/mid/src/mid/lexer" 12 | ) 13 | 14 | type traceVisitor struct { 15 | w io.Writer 16 | prefix []byte 17 | indents []byte 18 | } 19 | 20 | func (v *traceVisitor) Fprintf(w io.Writer, format string, args ...interface{}) { 21 | log.Output(2, string(v.indents)+fmt.Sprintf(format, args...)) 22 | } 23 | 24 | func (v *traceVisitor) Visit(node ast.Node) ast.Visitor { 25 | switch n := node.(type) { 26 | case *ast.Field: 27 | if len(n.Names) > 0 { 28 | v.Fprintf(v.w, "%T: %s\n", n, n.Names[0].Name) 29 | } 30 | case *ast.FieldList: 31 | v.Fprintf(v.w, "%T: %d\n", n, len(n.List)) 32 | case *ast.Comment: 33 | case *ast.CommentGroup: 34 | if n != nil { 35 | v.Fprintf(v.w, "CommentGroup: %s\n", n.Text()) 36 | } 37 | case *ast.File: 38 | case *ast.Package: 39 | case *ast.Ident: 40 | if n != nil { 41 | v.Fprintf(v.w, "%T: %s\n", n, n.Name) 42 | } else { 43 | v.Fprintf(v.w, "%T(nil)\n", n) 44 | } 45 | case *ast.BasicLit: 46 | if n != nil { 47 | v.Fprintf(v.w, "%T: %s\n", n, n.Value) 48 | } else { 49 | v.Fprintf(v.w, "%T(nil)\n", n) 50 | } 51 | case *ast.BasicType: 52 | if n != nil && n.Name != nil { 53 | v.Fprintf(v.w, "%T: %s\n", n, n.Name.Name) 54 | } else { 55 | v.Fprintf(v.w, "%T(nil)\n", n) 56 | } 57 | case *ast.ArrayType: 58 | v.Fprintf(v.w, "%T\n", n) 59 | case *ast.MapType: 60 | v.Fprintf(v.w, "%T\n", n) 61 | case *ast.VectorType: 62 | v.Fprintf(v.w, "%T\n", n) 63 | case *ast.StructType: 64 | v.Fprintf(v.w, "%T\n", n) 65 | case *ast.GenDecl: 66 | v.Fprintf(v.w, "%T\n", n) 67 | case *ast.BeanDecl: 68 | if n != nil { 69 | v.Fprintf(v.w, "%T: %s\n", n, n.Kind) 70 | } else { 71 | v.Fprintf(v.w, "%T(nil)\n", n) 72 | } 73 | case *ast.ImportSpec: 74 | v.Fprintf(v.w, "%T\n", n) 75 | case *ast.ConstSpec: 76 | v.Fprintf(v.w, "%T\n", n) 77 | case *ast.BadDecl: 78 | v.Fprintf(v.w, "%T\n", n) 79 | case *ast.BadExpr: 80 | v.Fprintf(v.w, "%T\n", n) 81 | } 82 | //v.Fprintf(v.w, "%T\n", n) 83 | return v 84 | } 85 | 86 | func (v *traceVisitor) In() { 87 | v.indents = append(v.indents, v.prefix...) 88 | } 89 | 90 | func (v *traceVisitor) Out() { 91 | v.indents = v.indents[:len(v.indents)-len(v.prefix)] 92 | } 93 | 94 | func TestParser(t *testing.T) { 95 | w := os.Stdout 96 | src := []byte(`package demo; 97 | 98 | import "a/b/c"; 99 | import x "o/p/q"; 100 | 101 | struct User { 102 | int32 id; 103 | } 104 | 105 | protocol UserInfo { 106 | int16 a,b; 107 | bool x; 108 | string y; 109 | int32 z; 110 | vector list; 111 | array arr; 112 | } 113 | 114 | service HelloWorld { 115 | name() 116 | say(string s) 117 | abc(int32 a, bool b) 118 | } 119 | 120 | // doc 121 | enum Type { 122 | A = 1, 123 | B = 2, 124 | } 125 | `) 126 | 127 | fset := lexer.NewFileSet() 128 | file, err := ParseFile(fset, "demo.mid", src) 129 | if err != nil { 130 | t.Errorf("parse error: %v", err) 131 | return 132 | } 133 | ast.Walk(file, &traceVisitor{w: w, prefix: []byte(". . ")}) 134 | 135 | for _, unresolved := range file.Unresolved { 136 | log.Printf("unresolved ident: %s (pos: %v)", unresolved.Name, fset.Position(unresolved.Pos)) 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/mid/scanner/scanner.go: -------------------------------------------------------------------------------- 1 | package scanner 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/midlang/mid/src/mid/external/go/scanner" 7 | "github.com/midlang/mid/src/mid/lexer" 8 | ) 9 | 10 | const ( 11 | DefaultScanMode = scanner.GoTokens 12 | ) 13 | 14 | type Scanner struct { 15 | scanner.Scanner 16 | } 17 | 18 | func NewScanner(file *lexer.File, src io.Reader) *Scanner { 19 | s := new(Scanner) 20 | s.Scanner.Init(file, src) 21 | s.Scanner.Mode = scanner.ScanIdents | scanner.ScanFloats | scanner.ScanChars | scanner.ScanStrings | scanner.ScanRawStrings | scanner.ScanComments 22 | return s 23 | } 24 | 25 | func (s *Scanner) Scan() (pos lexer.Pos, tok lexer.Token, lit string) { 26 | r := s.Scanner.Scan() 27 | pos = lexer.Pos(s.Scanner.Pos().Offset) 28 | tok = lexer.EOF 29 | if r == scanner.EOF { 30 | return 31 | } 32 | lit = s.Scanner.TokenText() 33 | switch r { 34 | case scanner.Ident: 35 | tok = lexer.Lookup(lit) 36 | case scanner.Int: 37 | tok = lexer.INT 38 | case scanner.Float: 39 | tok = lexer.FLOAT 40 | case scanner.Char: 41 | tok = lexer.CHAR 42 | case scanner.String: 43 | tok = lexer.STRING 44 | case scanner.Comment: 45 | tok = lexer.COMMENT 46 | default: 47 | if op, ok := lexer.LookupOperator(lit); ok { 48 | tok = op 49 | } else { 50 | tok = lexer.ILLEGAL 51 | } 52 | } 53 | return 54 | } 55 | -------------------------------------------------------------------------------- /src/mid/scanner/scanner_test.go: -------------------------------------------------------------------------------- 1 | package scanner 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/midlang/mid/src/mid/external/go/scanner" 9 | "github.com/midlang/mid/src/mid/lexer" 10 | ) 11 | 12 | func TestScanner(t *testing.T) { 13 | text := fmt.Sprintf(`package scanner 14 | 15 | const x = 1 16 | const y = "2" 17 | 18 | const ( 19 | a = 1.1 20 | b = 'c' 21 | ) 22 | 23 | const rawstr = %s 24 | 25 | // comment 26 | 27 | /** 28 | * comments 29 | */ 30 | 31 | protocol Hello { 32 | string name; 33 | } 34 | `, "`abcdef`") 35 | 36 | src := strings.NewReader(text) 37 | 38 | fmt.Println(text) 39 | 40 | fset := lexer.NewFileSet() 41 | file := fset.AddFile("demo.mid", -1, len(text)) 42 | s := NewScanner(file, src) 43 | s.Mode = scanner.GoTokens & (^(scanner.SkipComments)) 44 | s.Filename = file.Name() 45 | fmt.Println("s.Mode&ScanRawStrings != 0:", s.Mode&scanner.ScanRawStrings != 0) 46 | for { 47 | pos, tok, lit := s.Scan() 48 | if tok == lexer.EOF { 49 | break 50 | } 51 | fmt.Printf("pos,tok,lit=(%v,%v,%v)\n", pos, tok, lit) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/mid/syntax/syntax.mid: -------------------------------------------------------------------------------- 1 | package syntax; 2 | 3 | enum Token { 4 | ILLEGAL = 0, `value:"ILLEGAL"` // invalid token 5 | EOF = 1, `value:"EOF"` // eof 6 | COMMENT = 2, `value:"COMMENT"` // comment 7 | IDENT = 3, `value:"IDENT"` // identifier, e.g. main,abc 8 | INT = 4, `value:"INT"` // integer, e.g. 12345 9 | FLOAT = 5, `value:"FLOAT"` // float number, e.g. 123.45 10 | CHAR = 6, `value:"CHAR"` // char, e.g. 'c' 11 | STRING = 7, `value:"STRING"` // string, e.g. "abc" 12 | 13 | // operators 14 | LPAREN = 11, `kind:"operator" value:"("` 15 | RPAREN = 12, `kind:"operator" value:")"` 16 | LBRACK = 13, `kind:"operator" value:"["` 17 | RBRACK = 14, `kind:"operator" value:"]"` 18 | LBRACE = 15, `kind:"operator" value:"{"` 19 | RBRACE = 16, `kind:"operator" value:"}"` 20 | LT = 17, `kind:"operator" value:"<"` 21 | GT = 18, `kind:"operator" value:">"` 22 | EQ = 19 `kind:"operator" value:"="` 23 | COMMA = 20, `kind:"operator" value:","` 24 | DOT = 21, `kind:"operator" value:"."` 25 | SEMICOLON = 22, `kind:"operator" value:";"` 26 | COLON = 23, `kind:"operator" value:":"` 27 | AT = 24, `kind:"operator" value:"@"` 28 | DOLLAR = 25, `kind:"operator" value:"$"` 29 | SHARP = 26, `kind:"operator" value:"#"` 30 | SLASH = 27, `kind:"operator" value:"/"` 31 | STAR = 28, `kind:"operator" value:"*"` 32 | 33 | // keywords 34 | PACKAGE = 40, `kind:"keyword" value:"package"` 35 | IMPORT = 41, `kind:"keyword" value:"import"` 36 | ENUM = 42, `kind:"keyword" value:"enum"` 37 | CONST = 43, `kind:"keyword" value:"const"` 38 | REQUIRED = 44, `kind:"keyword" value:"required"` 39 | OPTIONAL = 45, `kind:"keyword" value:"optional"` 40 | EXTENDS = 46, `kind:"keyword" value:"extends"` 41 | } 42 | 43 | // common nodes 44 | 45 | struct Field `kind:"node"` { 46 | CommentGroup doc; 47 | vector options; 48 | Type type; 49 | vector names; 50 | Expr default; 51 | BasicLit tag; 52 | CommentGroup comment; 53 | } 54 | 55 | // expr nodes 56 | 57 | struct BadExpr `kind:"expr"` { 58 | int from; `begin:"true"` 59 | int to; 60 | } 61 | 62 | struct Ident `kind:"expr"` { 63 | int pos; `value:"begin"` 64 | string name; 65 | } 66 | 67 | struct BasicLit `kind:"expr"` { 68 | int pos; `begin:"true" token:"INT,FLOAT,CHAR,STRING"` 69 | Token tok; `store:"token"` 70 | string lit; `stror:"lit"` 71 | } 72 | 73 | // type nodes 74 | 75 | struct BasicType `kind:"type"` { 76 | Ident name; `begin:"true"` 77 | } 78 | 79 | // array 80 | struct ArrayType `kind:"type"` { 81 | int pos; `begin:"true" token:"IDENT:array"` 82 | int lt; `token:"LT"` 83 | Type t; 84 | int commaPos; `token:"COMMA"` 85 | Expr size; 86 | int gt; `token:"GT"` 87 | } 88 | 89 | // vector 90 | struct VectorType `kind:"type"` { 91 | int pos; `begin:"true" token:"IDENT:vector"` 92 | int lt; `token:"LT"` 93 | Type t; 94 | int gt; `token:"GT"` 95 | } 96 | 97 | // map 98 | struct MapType `kind:"type"` { 99 | int pos; `begin:"true" token:"IDENT:array"` 100 | int lt; `token:"LT"` 101 | Type t; 102 | int commaPos; `token:"COMMA"` 103 | Expr size; 104 | int gt; `token:"GT"` 105 | } 106 | 107 | // struct/protocol/enum 108 | struct BeanType `kind:"type"` { 109 | Ident pkg; `token:"IDENT+DOT" optional:"true"` 110 | Ident name; 111 | } 112 | 113 | // func 114 | struct FuncType `kind:"type"` { 115 | int lParen; `begin:"true" token:"LPAREN"` 116 | vector params; 117 | int rParen; `token:"RPAREN"` 118 | Type result; `optional:"true"` 119 | } 120 | -------------------------------------------------------------------------------- /templates/_common/go/const.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-07 10:59 3 | desc: 常量声明的生成 4 | --- 5 | 6 | {{range $decl := .}} 7 | {{$decl.Doc}}const ( 8 | {{range $field := $decl.Consts}}{{$field.Name}} = {{$field.ValueString}}{{$field.Comment}} 9 | {{end}} 10 | ) 11 | {{end}} 12 | -------------------------------------------------------------------------------- /templates/_common/go/enum.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-07 10:59 3 | desc: 枚举声明的生成 4 | --- 5 | 6 | {{$type := .Name}} 7 | type {{$type}} int 8 | 9 | {{.Doc}}const ( 10 | {{range $field := .Fields}}{{$type}}_{{$field.Name}} {{$type}} = {{$field.Value}}{{$field.Comment}} 11 | {{end}} 12 | ) 13 | -------------------------------------------------------------------------------- /templates/_common/go/fn_table_key.temp: -------------------------------------------------------------------------------- 1 | --- 2 | desc: 获取 table 的关键字段和关键字段类型 3 | --- 4 | 5 | {{- $bean := valueAt . 0}} 6 | {{- $key := valueAt . 1}} 7 | {{- $keyType := valueAt . 2}} 8 | {{- range $index, $field := $bean.Fields}} 9 | {{- if (eq ($field.GetTag "key") "true") and (eq ($key.Get) "")}} 10 | {{- $key.Set (title $field.Name)}} 11 | {{- $keyType.Set (context.BuildType $field.Type)}} 12 | {{- end}} 13 | {{- end}} 14 | -------------------------------------------------------------------------------- /templates/_common/go/fn_xorm.temp: -------------------------------------------------------------------------------- 1 | --- 2 | desc: 计算一个字段的sql属性,包括类型,选项,默认值,注释 3 | --- 4 | {{- $field := valueAt . 0}} 5 | {{- $type := valueAt . 1}} 6 | {{- $option := valueAt . 2}} 7 | {{- $default := valueAt . 3}} 8 | {{- $comment := valueAt . 4}} 9 | 10 | {{- $bits := $field.GetTag "bits"}} 11 | {{- $fieldType := context.BuildType $field.Type}} 12 | 13 | {{- if eq $fieldType "string"}} 14 | {{- if eq $bits ""}}{{- $type.Set "TEXT"}} 15 | {{- else}}{{- $type.Set (join "" "VARCHAR(" $bits ")")}} 16 | {{- end}} 17 | {{- else if eq $fieldType "int"}}{{$type.Set "BIGINT(20)"}} 18 | {{- else if eq $fieldType "int8"}}{{$type.Set "INT(4)"}} 19 | {{- else if eq $fieldType "int16"}}{{$type.Set "INT(6)"}} 20 | {{- else if eq $fieldType "int32"}}{{$type.Set "INT(10)"}} 21 | {{- else if eq $fieldType "int64"}}{{$type.Set "BIGINT(20)"}} 22 | {{- else if eq $fieldType "uint"}}{{$type.Set "BIGINT(20)"}} 23 | {{- else if eq $fieldType "uint8"}}{{$type.Set "INT(4)"}} 24 | {{- else if eq $fieldType "uint16"}}{{$type.Set "INT(6)"}} 25 | {{- else if eq $fieldType "uint32"}}{{$type.Set "INT(10)"}} 26 | {{- else if eq $fieldType "uint64"}}{{$type.Set "BIGINT(20)"}} 27 | {{- else if eq $fieldType "bool"}}{{$type.Set "TINYINT(1)"}} 28 | {{- else if eq $fieldType "float32"}}{{$type.Set "DOUBLE"}} 29 | {{- else if eq $fieldType "float64"}}{{$type.Set "DOUBLE"}} 30 | {{- else if $field.Type.IsStruct}}{{$type.Set "TEXT"}} 31 | {{- else if $field.Type.IsVector}}{{$type.Set "TEXT"}} 32 | {{- else}}{{error "unsupported type: %s" $fieldType}} 33 | {{- end -}} 34 | 35 | {{- $option.Set ($field.GetTag "opt")}} 36 | 37 | {{- $dft := $field.GetTag "dft"}} 38 | {{- if $field.Type.IsString }} 39 | {{- if ne $dft ""}} 40 | {{- $default.Set (join "" "DEFAULT '" $dft "'")}} 41 | {{- else if $field.Tag.HasKey "dft"}} 42 | {{- $default.Set "DEFAULT ''"}} 43 | {{- end}} 44 | {{- else if ne $dft ""}} 45 | {{- $default.Set (join " " "DEFAULT" $dft)}} 46 | {{- end}} 47 | 48 | {{- $c := newString}} 49 | {{- $c.Set (trimPrefix "//" $field.Comment)}} 50 | {{- $c.Set (trimSpace $c.Get)}} 51 | {{- if ne ($c.Get) ""}} 52 | {{- $comment.Set (join "" "COMMENT '" ($c.Get) "'")}} 53 | {{- end -}} 54 | -------------------------------------------------------------------------------- /templates/_common/go/head.go.temp: -------------------------------------------------------------------------------- 1 | // NOTE: AUTO-GENERATED by midc, DON'T edit!! 2 | 3 | package {{context.Pkg.Name}} 4 | 5 | -------------------------------------------------------------------------------- /templates/_common/go/import.go.temp: -------------------------------------------------------------------------------- 1 | import ( 2 | "fmt" 3 | 4 | "github.com/mkideal/pkg/storage" 5 | "github.com/mkideal/pkg/typeconv" 6 | "gopkg.in/redis.v5" 7 | ) 8 | 9 | var ( 10 | _ = fmt.Printf 11 | _ = storage.Unused 12 | _ = typeconv.Unused 13 | _ = redis.Nil 14 | ) 15 | -------------------------------------------------------------------------------- /templates/_common/go/package.sql.temp: -------------------------------------------------------------------------------- 1 | /* NOTE: AUTO-GENERATED by midc, DON'T edit!! */ 2 | 3 | {{- range $file := .Files}} 4 | {{- range $bean := $file.Beans}} 5 | {{- if eq $bean.Kind "protocol"}} 6 | {{- $type := .Name}} 7 | {{- $key := newString}} 8 | {{- $keyType := newString}} 9 | {{- include_template (joinPath (pwd) "./fn_table_key.temp") (slice . $key $keyType)}} 10 | CREATE TABLE IF NOT EXISTS `{{underScore $type}}` ( 11 | {{range $field := .Fields}} 12 | {{- $type := newString}} 13 | {{- $option := newString}} 14 | {{- $default := newString}} 15 | {{- $comment := newString}} 16 | {{- include_template (joinPath (pwd) "./fn_xorm.temp") (slice $field $type $option $default $comment)}} 17 | {{- if $field.Type.IsBool}} 18 | {{- if OR (eq ($default.Get) "true") (eq ($default.Get) "1") }} 19 | {{- $default.Set "DEFAULT 1"}} 20 | {{- else}} 21 | {{- $default.Set "DEFAULT 0"}} 22 | {{- end}} 23 | {{- end}}`{{underScore $field.Name}}` {{$type.Get}} {{$option.Get}} {{$default.Get}} {{$comment.Get}}, 24 | {{end -}} 25 | PRIMARY KEY (`{{underScore $key.Get}}`) 26 | ) 27 | ENGINE = InnoDB 28 | DEFAULT CHARACTER SET = utf8mb4; 29 | {{- end}} 30 | {{- end}} 31 | {{- end}} 32 | -------------------------------------------------------------------------------- /templates/_common/go/service.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-07 11:00 3 | desc: 暂不支持 service 类型定义 4 | --- 5 | 6 | {{error "unsupport service"}} 7 | -------------------------------------------------------------------------------- /templates/_common/go/storage_init.go.temp: -------------------------------------------------------------------------------- 1 | 2 | func Init(eng storage.Engine) { 3 | {{- range $file := .Files}} 4 | {{- range $bean := $file.Beans}} 5 | {{- if eq "protocol" $bean.Kind}} 6 | {{- range $field := .Fields}} 7 | {{- $index := $field.GetTag "index"}} 8 | {{- if ne $index ""}} 9 | {{- $indexStructName := upperCamel $index}} 10 | eng.AddIndex({{$indexStructName}}Var) 11 | {{- end}} 12 | {{- end}} 13 | {{- end}} 14 | {{- end}} 15 | {{- end}} 16 | } 17 | -------------------------------------------------------------------------------- /templates/_common/go/struct.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-07 11:00 3 | --- 4 | 5 | {{.Doc}}type {{.Name}} struct { 6 | {{- range $field := .Fields}} 7 | {{title $field.Name}} {{context.BuildType $field.Type}}{{end}} 8 | } 9 | -------------------------------------------------------------------------------- /templates/beans/cpp/const.h.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 23:32 3 | author: mkideal 4 | --- 5 | {{context.AutoGenDeclaration}} 6 | 7 | {{- range $decl := .}} 8 | {{- context.Extension "file_head" .}} 9 | {{- end}} 10 | 11 | namespace {{context.Pkg.Name}} { 12 | {{range $decl := .}} 13 | {{- context.Extension "before_const" $decl}} 14 | {{- context.Extension "const_front" $decl}} 15 | {{$decl.Doc}}{{range $field := $decl.Consts}}const int {{$field.Name}} = {{$field.ValueString}};{{$field.Comment}} 16 | {{- context.Extension "const_back" $decl}} 17 | {{end}} 18 | {{- context.Extension "after_const" $decl}} 19 | 20 | {{- context.Extension "file_end" $decl}} 21 | {{end}} 22 | } 23 | -------------------------------------------------------------------------------- /templates/beans/cpp/enum.h.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 23:33 3 | author: mkideal 4 | --- 5 | {{context.AutoGenDeclaration}} 6 | 7 | {{- context.Extension "file_head" .}} 8 | 9 | namespace {{context.Pkg.Name}} { 10 | {{$type := .Name}} 11 | {{- context.Extension "before_enum" .}} 12 | {{.Doc}}enum {{$type}} { 13 | {{- context.Extension "enum_front" .}} 14 | {{range $field := .Fields}} 15 | {{- $field.Name}} = {{$field.Value}},{{$field.Comment}} 16 | {{end}} 17 | {{- context.Extension "enum_back" .}} 18 | }; 19 | {{- context.Extension "after_enum" .}} 20 | 21 | {{- context.Extension "file_end" .}} 22 | } 23 | -------------------------------------------------------------------------------- /templates/beans/cpp/protocol.cpp.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 23:33 3 | author: mkideal 4 | --- 5 | {{context.AutoGenDeclaration}} 6 | {{context.Extension "file_head" .}} 7 | {{context.Extension "before_import" .}} 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | {{context.Extension "after_import" .}} 14 | namespace {{context.Pkg.Name}} { 15 | {{context.Extension "before_protocol" .}} 16 | {{context.Extension "protocol_front" .}} 17 | {{context.Extension "protocol_back" .}} 18 | {{context.Extension "after_protocol" .}} 19 | {{context.Extension "file_end" .}} 20 | } 21 | -------------------------------------------------------------------------------- /templates/beans/cpp/protocol.h.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date; 2016-12-04 23:33 3 | author: mkideal 4 | --- 5 | {{context.AutoGenDeclaration}} 6 | 7 | {{- context.Extension "file_head" .}} 8 | 9 | {{- context.Extension "before_import" .}} 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | {{- context.Extension "after_import" .}} 16 | 17 | namespace {{context.Pkg.Name}} { 18 | {{- $type := .Name}} 19 | {{- context.Extension "before_protocol" .}} 20 | {{- $extends := .BuildExtends context}} 21 | {{.Doc}}struct {{$type}}{{if ne (len $extends) 0}}: public {{$extends | join " "}}{{end}} { 22 | {{- context.Extension "protocol_front" .}} 23 | {{range $field := .Fields}} 24 | {{- context.BuildType $field.Type}} {{$field.Name}};{{$field.Comment}} 25 | {{end}} 26 | {{- context.Extension "protocol_back" .}} 27 | }; 28 | {{- context.Extension "after_protocol" .}} 29 | 30 | {{- context.Extension "file_end" .}} 31 | } 32 | -------------------------------------------------------------------------------- /templates/beans/cpp/service.cpp.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 23:33 3 | author: mkideal 4 | --- 5 | {{context.AutoGenDeclaration}} 6 | 7 | {{context.Extension "file_head" .}} 8 | {{context.Extension "before_import" .}} 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | {{context.Extension "after_import" .}} 15 | 16 | namespace {{context.Pkg.Name}} { 17 | {{context.Extension "before_service" .}} 18 | {{context.Extension "service_front" .}} 19 | {{context.Extension "service_back" .}} 20 | {{context.Extension "after_service" .}} 21 | {{context.Extension "file_end" .}} 22 | } 23 | -------------------------------------------------------------------------------- /templates/beans/cpp/service.h.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 23:34 3 | author: mkideal 4 | --- 5 | {{context.AutoGenDeclaration}} 6 | 7 | {{- context.Extension "file_head" .}} 8 | 9 | {{- context.Extension "before_import" .}} 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | {{- context.Extension "after_import" .}} 16 | 17 | namespace {{context.Pkg.Name}} { 18 | {{- $type := .Name}} 19 | {{- context.Extension "before_service" .}} 20 | {{- $extends := .BuildExtends context}} 21 | {{.Doc}}class {{$type}}{{if ne (len $extends) 0}}: public {{$extends | join " "}}{{end}} { 22 | {{- context.Extension "service_front" .}} 23 | {{range $field := .Fields}} 24 | {{- $strs := splitN "(" 2 (context.BuildType $field.Type)}} 25 | {{- if true}} virtual {{stringAt $strs 0}} {{$field.Name}} ({{stringAt $strs 1}} = 0;{{$field.Comment}}{{end}} 26 | {{end}} 27 | {{- context.Extension "service_back" .}} 28 | }; 29 | {{- context.Extension "after_service" .}} 30 | 31 | {{- context.Extension "file_end" .}} 32 | } 33 | -------------------------------------------------------------------------------- /templates/beans/cpp/struct.cpp.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 23:34 3 | author: mkideal 4 | --- 5 | {{context.AutoGenDeclaration}} 6 | 7 | {{context.Extension "file_head" .}} 8 | {{context.Extension "before_import" .}} 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | {{context.Extension "after_import" .}} 15 | 16 | namespace {{context.Pkg.Name}} { 17 | {{context.Extension "before_struct" .}} 18 | {{context.Extension "struct_front" .}} 19 | {{context.Extension "struct_back" .}} 20 | {{context.Extension "after_struct" .}} 21 | {{context.Extension "file_end" .}} 22 | } 23 | -------------------------------------------------------------------------------- /templates/beans/cpp/struct.h.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 23:34 3 | author: mkideal 4 | --- 5 | {{context.AutoGenDeclaration}} 6 | 7 | {{- context.Extension "file_head" .}} 8 | 9 | {{- context.Extension "before_import" .}} 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | {{- context.Extension "after_import" .}} 16 | 17 | namespace {{context.Pkg.Name}} { 18 | {{- $type := .Name}} 19 | {{- context.Extension "before_struct" .}} 20 | {{- $extends := .BuildExtends context}} 21 | {{.Doc}}struct {{$type}}{{if ne (len $extends) 0}}: public {{$extends | joinStrings " "}}{{end}} { 22 | {{- context.Extension "struct_front" .}} 23 | {{range $field := .Fields}} 24 | {{- context.BuildType $field.Type}} {{$field.Name}};{{$field.Comment}} 25 | {{end}} 26 | {{- context.Extension "struct_back" .}} 27 | }; 28 | {{- context.Extension "after_struct" .}} 29 | 30 | {{- context.Extension "file_end" .}} 31 | } 32 | -------------------------------------------------------------------------------- /templates/beans/go/const.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 23:30 3 | author: mkideal 4 | --- 5 | {{context.AutoGenDeclaration}} 6 | 7 | {{range $decl := .}} 8 | {{context.Extension "file_head" $decl}} 9 | {{end}} 10 | package {{context.Pkg.Name}} 11 | 12 | {{context.Extension "before_import" .}} 13 | {{context.Extension "after_import" .}} 14 | 15 | {{range $decl := .}} 16 | {{context.Extension "before_const" $decl}} 17 | {{$decl.Doc}}const ( 18 | {{context.Extension "const_front" $decl}} 19 | {{range $field := $decl.Consts}}{{$field.Name}} = {{$field.ValueString}} 20 | {{end}} 21 | {{context.Extension "const_back" $decl}} 22 | ) 23 | {{context.Extension "after_const" $decl}} 24 | {{context.Extension "file_end" $decl}} 25 | {{end}} 26 | -------------------------------------------------------------------------------- /templates/beans/go/enum.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 23:30 3 | author: mkideal 4 | --- 5 | {{context.AutoGenDeclaration}} 6 | 7 | {{context.Extension "file_head" .}} 8 | package {{context.Pkg.Name}} 9 | 10 | {{context.Extension "before_import" .}} 11 | {{context.Extension "after_import" .}} 12 | 13 | {{$type := .Name}} 14 | type {{$type}} int 15 | {{context.Extension "before_enum" .}} 16 | {{.Doc}}const ( 17 | {{context.Extension "enum_front" .}} 18 | {{range $field := .Fields}}{{$type}}_{{$field.Name}} {{$type}} = {{$field.Value}}{{$field.Comment}} 19 | {{end}} 20 | {{context.Extension "enum_back" .}} 21 | ) 22 | {{context.Extension "after_enum" .}} 23 | -------------------------------------------------------------------------------- /templates/beans/go/protocol.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 23:31 3 | author: mkideal 4 | --- 5 | {{context.AutoGenDeclaration}} 6 | 7 | {{context.Extension "file_head" .}} 8 | package {{context.Pkg.Name}} 9 | 10 | {{context.Extension "before_import" .}} 11 | {{context.Extension "after_import" .}} 12 | 13 | {{$type := .Name}} 14 | {{context.Extension "before_protocol" .}} 15 | {{.Doc}}type {{$type}} struct { 16 | {{context.Extension "protocol_front" .}} 17 | {{range $field := .Extends}}{{context.BuildType $field}} 18 | {{end}} 19 | {{range $field := .Fields}} {{if ne $field.Name "_"}} {{$field.Name | title}} {{end}} {{context.BuildType $field.Type}}{{$field.Comment}} 20 | {{end}} 21 | {{context.Extension "protocol_back" .}} 22 | } 23 | {{context.Extension "after_protocol" .}} 24 | {{context.Extension "file_end" .}} 25 | -------------------------------------------------------------------------------- /templates/beans/go/service.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 23:31 3 | author: mkideal 4 | --- 5 | {{context.AutoGenDeclaration}} 6 | 7 | {{context.Extension "file_head" .}} 8 | package {{context.Pkg.Name}} 9 | 10 | {{context.Extension "before_import" .}} 11 | {{context.Extension "after_import" .}} 12 | 13 | {{$type := .Name}} 14 | {{context.Extension "before_service" .}} 15 | {{.Doc}}type {{$type}} interface { 16 | {{context.Extension "service_front" .}} 17 | {{range $field := .Extends}}{{context.BuildType $field}} 18 | {{end}} 19 | {{range $field := .Fields}}{{$field.Name | title}} {{context.BuildType $field.Type}}{{$field.Comment}} 20 | {{end}} 21 | {{context.Extension "service_back" .}} 22 | } 23 | {{context.Extension "after_service" .}} 24 | {{context.Extension "file_end" .}} 25 | -------------------------------------------------------------------------------- /templates/beans/go/struct.go.temp: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-12-04 23:31 3 | author: mkideal 4 | --- 5 | {{context.AutoGenDeclaration}} 6 | 7 | {{context.Extension "file_head" .}} 8 | package {{context.Pkg.Name}} 9 | 10 | {{context.Extension "before_import" .}} 11 | {{context.Extension "after_import" .}} 12 | 13 | {{$type := .Name}} 14 | {{context.Extension "before_struct" .}} 15 | {{.Doc}}type {{$type}} struct { 16 | {{context.Extension "struct_front" .}} 17 | {{range $field := .Extends}}{{context.BuildType $field}} 18 | {{end}} 19 | {{range $field := .Fields}} {{if ne $field.Name "_"}} {{$field.Name | title}} {{end}} {{context.BuildType $field.Type}}{{$field.Comment}} 20 | {{end}} 21 | {{context.Extension "struct_back" .}} 22 | } 23 | {{context.Extension "after_struct" .}} 24 | {{context.Extension "file_end" .}} 25 | -------------------------------------------------------------------------------- /templates/default/cpp/package.cpp.temp: -------------------------------------------------------------------------------- 1 | {{context.AutoGenDeclaration}} 2 | 3 | {{- context.Extension "file_head" .}} 4 | {{- context.Extension "before_import" .}} 5 | #include "{{.Name}}.h" 6 | {{- context.Extension "after_import" .}} 7 | 8 | {{- define "T_const"}} 9 | {{range $decl := .}} 10 | {{- context.Extension "before_const" $decl}} 11 | {{- context.Extension "const_front" $decl}} 12 | {{- context.Extension "const_back" $decl}} 13 | {{- context.Extension "after_const" $decl}} 14 | {{end}} 15 | {{end}} 16 | 17 | {{- define "T_enum"}} 18 | {{- context.Extension "before_enum" .}} 19 | {{- context.Extension "enum_front" .}} 20 | {{- context.Extension "enum_back" .}} 21 | {{- context.Extension "after_enum" .}} 22 | {{end}} 23 | 24 | {{- define "T_struct"}} 25 | {{- context.Extension "before_struct" .}} 26 | {{- context.Extension "struct_front" .}} 27 | {{- context.Extension "struct_back" .}} 28 | {{- context.Extension "after_struct" .}} 29 | {{end}} 30 | 31 | {{- define "T_protocol"}} 32 | {{- context.Extension "before_protocol" .}} 33 | {{- context.Extension "protocol_front" .}} 34 | {{- context.Extension "protocol_back" .}} 35 | {{- context.Extension "after_protocol" .}} 36 | {{end}} 37 | 38 | {{- define "T_service"}} 39 | {{- context.Extension "before_service" .}} 40 | {{- context.Extension "service_front" .}} 41 | {{- context.Extension "service_back" .}} 42 | {{- context.Extension "after_service" .}} 43 | {{end}} 44 | 45 | namespace {{.Name}} { 46 | {{.GenerateDeclsBySubTemplates}} 47 | } // end namespace {{.Name}} 48 | 49 | {{context.Extension "file_end" .}} 50 | -------------------------------------------------------------------------------- /templates/default/cpp/package.h.temp: -------------------------------------------------------------------------------- 1 | {{context.AutoGenDeclaration}} 2 | 3 | {{- context.Extension "file_head" .}} 4 | 5 | {{- context.Extension "before_import" .}} 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | {{- context.Extension "after_import" .}} 12 | 13 | {{- define "T_const"}} 14 | {{range $decl := .}} 15 | {{- context.Extension "before_const" $decl}} 16 | {{- context.Extension "const_front" $decl}} 17 | {{$decl.Doc}}{{range $field := $decl.Consts}}const int {{$field.Name}} = {{$field.ValueString}};{{$field.Comment}} 18 | {{- context.Extension "const_back" $decl}} 19 | {{end}} 20 | {{- context.Extension "after_const" $decl}} 21 | {{end}} 22 | {{end}} 23 | 24 | {{- define "T_enum"}} 25 | {{- $type := .Name}} 26 | {{- context.Extension "before_enum" .}} 27 | {{.Doc}}enum {{$type}} { 28 | {{- context.Extension "enum_front" .}} 29 | {{range $field := .Fields}} 30 | {{- $field.Name}} = {{$field.Value}},{{$field.Comment}} 31 | {{end}} 32 | {{- context.Extension "enum_back" .}} 33 | }; 34 | {{- context.Extension "after_enum" .}} 35 | {{end}} 36 | 37 | {{- define "T_struct"}} 38 | {{- $type := .Name}} 39 | {{- context.Extension "before_struct" .}} 40 | {{- $extends := .BuildExtends context}} 41 | {{.Doc}}struct {{$type}}{{if ne (len $extends) 0}}: public {{joinStrings " " $extends}}{{end}} { 42 | {{- context.Extension "struct_front" .}} 43 | {{range $field := .Fields}} 44 | {{- context.BuildType $field.Type}} {{$field.Name}};{{$field.Comment}} 45 | {{end}} 46 | {{- context.Extension "struct_back" .}} 47 | }; 48 | {{- context.Extension "after_struct" .}} 49 | {{end}} 50 | 51 | {{- define "T_protocol"}} 52 | {{- $type := .Name}} 53 | {{- context.Extension "before_protocol" .}} 54 | {{- $extends := .BuildExtends context}} 55 | {{.Doc}}struct {{$type}}{{if ne (len $extends) 0}}: public {{$extends | join " "}}{{end}} { 56 | {{- context.Extension "protocol_front" .}} 57 | {{range $field := .Fields}} 58 | {{- context.BuildType $field.Type}} {{$field.Name}};{{$field.Comment}} 59 | {{end}} 60 | {{- context.Extension "protocol_back" .}} 61 | }; 62 | {{- context.Extension "after_protocol" .}} 63 | {{end}} 64 | 65 | {{- define "T_service"}} 66 | {{- $type := .Name}} 67 | {{- context.Extension "before_service" .}} 68 | {{- $extends := .BuildExtends context}} 69 | {{.Doc}}class {{$type}}{{if ne (len $extends) 0}}: public {{$extends | join " "}}{{end}} { 70 | {{- context.Extension "service_front" .}} 71 | {{range $field := .Fields}} 72 | {{- $strs := splitN "(" 2 (context.BuildType $field.Type)}} 73 | {{- if true}} virtual {{stringAt $strs 0}} {{$field.Name}} ({{stringAt $strs 1}} = 0;{{$field.Comment}}{{end}} 74 | {{end}} 75 | {{- context.Extension "service_back" .}} 76 | }; 77 | {{- context.Extension "after_service" .}} 78 | {{end}} 79 | 80 | namespace {{.Name}} { 81 | {{.GenerateDeclsBySubTemplates}} 82 | } // end namespace {{.Name}} 83 | 84 | {{context.Extension "file_end" .}} 85 | -------------------------------------------------------------------------------- /templates/default/go/package.go.temp: -------------------------------------------------------------------------------- 1 | {{context.AutoGenDeclaration}} 2 | 3 | {{context.Extension "file_head" .}} 4 | package {{.Name}} 5 | 6 | {{context.Extension "before_import" .}} 7 | {{context.Extension "after_import" .}} 8 | 9 | {{define "T_const"}} 10 | {{range $decl := .}} 11 | {{context.Extension "before_const" $decl}} 12 | {{$decl.Doc}}const ( 13 | {{context.Extension "const_front" $decl}} 14 | {{range $field := $decl.Consts}}{{$field.Name}} = {{$field.ValueString}}{{$field.Comment}} 15 | {{end}} 16 | {{context.Extension "const_back" $decl}} 17 | ) 18 | {{context.Extension "after_const" $decl}} 19 | {{end}} 20 | {{end}} 21 | 22 | {{define "T_enum"}} 23 | {{$type := .Name}} 24 | type {{$type}} int 25 | {{context.Extension "before_enum" .}} 26 | {{.Doc}}const ( 27 | {{context.Extension "enum_front" .}} 28 | {{range $field := .Fields}}{{$type}}_{{$field.Name}} {{$type}} = {{$field.Value}}{{$field.Comment}} 29 | {{end}} 30 | {{context.Extension "enum_back" .}} 31 | ) 32 | {{context.Extension "after_enum" .}} 33 | {{end}} 34 | 35 | {{define "T_struct"}} 36 | {{$type := .Name}} 37 | {{context.Extension "before_struct" .}} 38 | {{.Doc}}type {{$type}} struct { 39 | {{context.Extension "struct_front" .}} 40 | {{range $field := .Extends}}{{context.BuildType $field}} 41 | {{end}} 42 | {{range $field := .Fields}}{{$field.Name | title}} {{context.BuildType $field.Type}}{{$field.Comment}} 43 | {{end}} 44 | {{context.Extension "struct_back" .}} 45 | } 46 | {{context.Extension "after_struct" .}} 47 | {{end}} 48 | 49 | {{define "T_protocol"}} 50 | {{$type := .Name}} 51 | {{context.Extension "before_protocol" .}} 52 | {{.Doc}}type {{$type}} struct { 53 | {{context.Extension "protocol_front" .}} 54 | {{range $field := .Extends}}{{context.BuildType $field}} 55 | {{end}} 56 | {{range $field := .Fields}}{{$field.Name | title}} {{context.BuildType $field.Type}}{{$field.Comment}} 57 | {{end}} 58 | {{context.Extension "protocol_back" .}} 59 | } 60 | {{context.Extension "after_protocol" .}} 61 | {{end}} 62 | 63 | {{define "T_service"}} 64 | {{$type := .Name}} 65 | {{context.Extension "before_service" .}} 66 | {{.Doc}}type {{$type}} interface { 67 | {{context.Extension "service_front" .}} 68 | {{range $field := .Extends}}{{context.BuildType $field}} 69 | {{end}} 70 | {{range $field := .Fields}}{{$field.Name | title}} {{context.BuildType $field.Type}}{{$field.Comment}} 71 | {{end}} 72 | {{context.Extension "service_back" .}} 73 | } 74 | {{context.Extension "after_service" .}} 75 | {{end}} 76 | 77 | {{.GenerateDeclsBySubTemplates}} 78 | 79 | {{context.Extension "file_end" .}} 80 | -------------------------------------------------------------------------------- /templates/default/js/package.js.temp: -------------------------------------------------------------------------------- 1 | {{context.AutoGenDeclaration}} 2 | 3 | {{- context.Extension "file_head" .}} 4 | 5 | {{- context.Extension "before_import" .}} 6 | 7 | {{- context.Extension "after_import" .}} 8 | 9 | {{- define "T_const"}} 10 | {{range $decl := .}} 11 | {{- context.Extension "before_const" $decl}} 12 | {{$decl.Doc}} 13 | {{- context.Extension "const_front" $decl}} 14 | {{range $field := $decl.Consts}}const {{$field.Name}} = {{$field.ValueString}};{{$field.Comment}} 15 | {{end}} 16 | {{- context.Extension "const_back" $decl}} 17 | {{- context.Extension "after_const" $decl}} 18 | {{end}} 19 | {{end}} 20 | 21 | {{- define "T_enum"}} 22 | {{- context.Extension "before_enum" .}} 23 | {{- $type := .Name}} 24 | {{.Doc}} 25 | {{- context.Extension "enum_front" .}} 26 | {{range $field := .Fields}}const {{$type}}_{{$field.Name}} = {{$field.Value}};{{$field.Comment}} 27 | {{end}} 28 | {{- context.Extension "enum_back" .}} 29 | {{- context.Extension "after_enum" .}} 30 | {{end}} 31 | 32 | {{- define "T_struct"}} 33 | {{- $type := .Name}} 34 | {{- $extends := .BuildExtends context}} 35 | {{- $extendsString := newString}} 36 | {{- if eq (len $extends) 1}}{{$extendsString.Set (join " " " extends" (stringAt $extends 0))}}{{end}} 37 | {{.Doc}}class {{$type}}{{$extendsString.Get}} { 38 | {{- context.Extension "before_struct" .}} 39 | constructor() { 40 | {{- context.Extension "struct_front" .}} 41 | {{if eq (len $extends) 1}}super();{{end}} 42 | {{range $field := .Fields}}this.{{$field.Name}} = {{context.JSInitValue $field.Type}};{{$field.Comment}} 43 | {{end}} 44 | {{- context.Extension "struct_back" .}} 45 | } 46 | {{- context.Extension "after_struct" .}} 47 | } 48 | {{end}} 49 | 50 | {{- define "T_protocol"}} 51 | {{- $type := .Name}} 52 | {{- $extends := .BuildExtends context}} 53 | {{- $extendsString := newString}} 54 | {{- if eq (len $extends) 1}}{{$extendsString.Set (join " " " extends" (stringAt $extends 0))}}{{end}} 55 | {{.Doc}}class {{$type}}{{$extendsString.Get}} { 56 | {{- context.Extension "before_protocol" .}} 57 | constructor() { 58 | {{- context.Extension "protocol_front" .}} 59 | {{if eq (len $extends) 1}}super();{{end}} 60 | {{range $field := .Fields}}this.{{$field.Name}} = {{context.JSInitValue $field.Type}};{{$field.Comment}} 61 | {{end}} 62 | {{- context.Extension "protocol_back" .}} 63 | } 64 | {{- context.Extension "after_protocol" .}} 65 | } 66 | {{end}} 67 | 68 | {{- define "T_service"}} 69 | {{- $type := .Name}} 70 | {{- $extends := .BuildExtends context}} 71 | {{- $extendsString := newString}} 72 | {{- if eq (len $extends) 1}}{{$extendsString.Set (join " " " extends" (stringAt $extends 0))}}{{end}} 73 | {{.Doc}}class {{$type}}{{$extendsString.Get}} { 74 | {{- context.Extension "before_service" .}} 75 | constructor() { 76 | {{- context.Extension "service_front" .}} 77 | {{if eq (len $extends) 1}}super();{{end}} 78 | {{range $field := .Fields}}this.{{$field.Name}} = function() {};{{$field.Comment}} 79 | {{end}} 80 | {{- context.Extension "service_back" .}} 81 | } 82 | {{- context.Extension "after_service" .}} 83 | } 84 | {{end}} 85 | 86 | {{.GenerateDeclsBySubTemplates}} 87 | 88 | {{context.Extension "file_end" .}} 89 | -------------------------------------------------------------------------------- /templates/storage/go/const.go.temp: -------------------------------------------------------------------------------- 1 | {{include_template (joinPath (pwd) "../../_common/go/head.go.temp") .}} 2 | 3 | {{include_template (joinPath (pwd) "../../_common/go/const.go.temp") .}} 4 | 5 | -------------------------------------------------------------------------------- /templates/storage/go/enum.go.temp: -------------------------------------------------------------------------------- 1 | {{include_template (joinPath (pwd) "../../_common/go/head.go.temp") .}} 2 | 3 | {{include_template (joinPath (pwd) "../../_common/go/enum.go.temp") .}} 4 | 5 | -------------------------------------------------------------------------------- /templates/storage/go/package.go.init.temp: -------------------------------------------------------------------------------- 1 | --- 2 | file: {{context.Pkg.Name}}_init.go 3 | --- 4 | {{include_template (joinPath (pwd) "../../_common/go/head.go.temp") .}} 5 | 6 | {{include_template (joinPath (pwd) "../../_common/go/import.go.temp") .}} 7 | 8 | {{include_template (joinPath (pwd) "../../_common/go/storage_init.go.temp") .}} 9 | -------------------------------------------------------------------------------- /templates/storage/go/package.sql.temp: -------------------------------------------------------------------------------- 1 | {{include_template (joinPath (pwd) "../../_common/go/package.sql.temp") .}} 2 | -------------------------------------------------------------------------------- /templates/storage/go/protocol.go.temp: -------------------------------------------------------------------------------- 1 | {{include_template (joinPath (pwd) "../../_common/go/head.go.temp") .}} 2 | 3 | {{include_template (joinPath (pwd) "../../_common/go/import.go.temp") .}} 4 | 5 | {{include_template (joinPath (pwd) "../../_common/go/protocol.go.temp") .}} 6 | -------------------------------------------------------------------------------- /templates/storage/go/service.go.temp: -------------------------------------------------------------------------------- 1 | {{include_template (joinPath (pwd) "../../_common/go/head.go.temp") .}} 2 | 3 | {{include_template (joinPath (pwd) "../../_common/go/service.go.temp") .}} 4 | -------------------------------------------------------------------------------- /templates/storage/go/struct.go.temp: -------------------------------------------------------------------------------- 1 | {{include_template (joinPath (pwd) "../../_common/go/head.go.temp") .}} 2 | 3 | {{include_template (joinPath (pwd) "../../_common/go/struct.go.temp") .}} 4 | -------------------------------------------------------------------------------- /templates/storage_onefile/go/package.go.temp: -------------------------------------------------------------------------------- 1 | {{include_template (joinPath (pwd) "../../_common/go/head.go.temp") .}} 2 | 3 | {{include_template (joinPath (pwd) "../../_common/go/import.go.temp") .}} 4 | 5 | {{include_template (joinPath (pwd) "../../_common/go/storage_init.go.temp") .}} 6 | 7 | {{define "T_const"}} 8 | {{include_template (joinPath (pwd) "../../_common/go/const.go.temp") .}} 9 | {{end}} 10 | 11 | {{define "T_enum"}} 12 | {{include_template (joinPath (pwd) "../../_common/go/enum.go.temp") .}} 13 | {{end}} 14 | 15 | {{define "T_struct"}} 16 | {{include_template (joinPath (pwd) "../../_common/go/struct.go.temp") .}} 17 | {{end}} 18 | 19 | {{define "T_service"}} 20 | {{include_template (joinPath (pwd) "../../_common/go/service.go.temp") .}} 21 | {{end}} 22 | 23 | {{define "T_protocol"}} 24 | {{include_template (joinPath (pwd) "../../_common/go/protocol.go.temp") .}} 25 | {{end}} 26 | 27 | {{.GenerateDeclsBySubTemplates}} 28 | -------------------------------------------------------------------------------- /templates/storage_onefile/go/package.sql.temp: -------------------------------------------------------------------------------- 1 | {{include_template (joinPath (pwd) "../../_common/go/package.sql.temp") .}} 2 | -------------------------------------------------------------------------------- /testdata/demo.mid: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | // constants 4 | const ( 5 | A = 1; 6 | B = 2; 7 | ) 8 | 9 | const ( 10 | C = 3; 11 | D = 4; 12 | ) 13 | 14 | // doc: Status 15 | enum Status { 16 | Ok = 0, // ok 17 | Bad = 1, // bad 18 | } 19 | 20 | group Test { 21 | 22 | struct User { 23 | optional int64 id; 24 | string name; 25 | vector otherNames; 26 | array code; 27 | } 28 | 29 | protocol UserList { 30 | map users; 31 | } 32 | 33 | } 34 | 35 | service UserService { 36 | sayHello() 37 | getUsers() UserList 38 | findUser(int64 uid) User 39 | delUser(int64) Status 40 | } 41 | 42 | struct Info extends User { 43 | string desc; 44 | map>>> xxx; 45 | int a; 46 | int8 b; 47 | int16 c; 48 | int32 d; 49 | int64 e; 50 | uint f; 51 | uint8 g; 52 | uint16 h; 53 | uint32 i; 54 | uint64 j; 55 | bool k; 56 | byte l; 57 | } 58 | -------------------------------------------------------------------------------- /testdata/demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kinds=' 4 | default 5 | beans 6 | ' 7 | 8 | for kind in $kinds 9 | do 10 | midc \ 11 | -Ogo=generated/go_$kind \ 12 | -Ocpp=generated/cpp_$kind \ 13 | -Eautogen_decl="// NOTE: generated file, DON'T edit!!" \ 14 | -Ecpp:unordered_map \ 15 | -Xcodec \ 16 | -K $kind \ 17 | --log=debug \ 18 | ./demo.mid 19 | done 20 | 21 | #-Euse_fixed_encode \ 22 | -------------------------------------------------------------------------------- /testdata/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | 8 | "github.com/midlang/mid/testdata/generated/go_beans/demo" 9 | ) 10 | 11 | func main() { 12 | info := demo.Info{ 13 | User: demo.User{ 14 | Id: 1, 15 | Name: "user1", 16 | OtherNames: []string{"用户1", "ユーザー1"}, 17 | Code: [6]byte{1, 2, 3, 4, 5, 6}, 18 | }, 19 | Desc: "test info", 20 | Xxx: map[int64][]map[int][5]bool{ 21 | 10: []map[int][5]bool{ 22 | map[int][5]bool{ 23 | 100: [5]bool{true, true, false, true, true}, 24 | 200: [5]bool{true, true, false, false, true}, 25 | }, 26 | map[int][5]bool{ 27 | 300: [5]bool{true, true, false, false, false}, 28 | }, 29 | map[int][5]bool{}, 30 | }, 31 | 20: []map[int][5]bool{ 32 | map[int][5]bool{ 33 | 400: [5]bool{true, false, false, false, false}, 34 | }, 35 | }, 36 | 30: []map[int][5]bool{}, 37 | }, 38 | A: 1, 39 | B: 2, 40 | C: 3, 41 | D: 4, 42 | E: 5, 43 | F: 6, 44 | G: 7, 45 | H: 8, 46 | I: 9, 47 | J: 10, 48 | K: true, 49 | L: 12, 50 | } 51 | 52 | var buf bytes.Buffer 53 | if err := info.Encode(&buf); err != nil { 54 | fmt.Printf("Encode error: %v\n", err) 55 | return 56 | } 57 | info2 := demo.Info{} 58 | if err := info2.Decode(&buf); err != nil { 59 | fmt.Printf("Decode error: %v\n", err) 60 | return 61 | } 62 | data, _ := json.MarshalIndent(info2, "", " ") 63 | fmt.Printf("decoded data: %v\n", string(data)) 64 | } 65 | -------------------------------------------------------------------------------- /x/cpp/include/mid/core/std.h: -------------------------------------------------------------------------------- 1 | // includes standard header files 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | -------------------------------------------------------------------------------- /x/cpp/include/mid/proto/decoder.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace mid { 4 | namespace proto { 5 | 6 | class Decoder { 7 | int8_t decodeInt8(Reader r, size_t& size); 8 | }; 9 | 10 | } // namespace proto 11 | } // namespace mid 12 | -------------------------------------------------------------------------------- /x/cpp/include/mid/proto/encoder.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/midlang/mid/a996341e16ef8d651e81436fbb34cf34bc11bf25/x/cpp/include/mid/proto/encoder.h -------------------------------------------------------------------------------- /x/cpp/include/mid/proto/proto.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | namespace mid { 5 | namespace proto { 6 | 7 | class Writer { 8 | virtual int write(const char* buf, size_t size) = 0; 9 | virtual int writeByte(char b) = 0; 10 | }; 11 | 12 | class Reader { 13 | virtual int read(char* buf, size_t size) = 0; 14 | virtual int readByte(char* buf) = 0; 15 | }; 16 | 17 | } // namespace proto 18 | } // namespace mid 19 | -------------------------------------------------------------------------------- /x/cpp/proto/decoder.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/midlang/mid/a996341e16ef8d651e81436fbb34cf34bc11bf25/x/cpp/proto/decoder.cpp -------------------------------------------------------------------------------- /x/cpp/proto/encoder.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/midlang/mid/a996341e16ef8d651e81436fbb34cf34bc11bf25/x/cpp/proto/encoder.cpp -------------------------------------------------------------------------------- /x/cpp/proto/proto.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/midlang/mid/a996341e16ef8d651e81436fbb34cf34bc11bf25/x/cpp/proto/proto.cpp -------------------------------------------------------------------------------- /x/cpp/tests/cbuild.json: -------------------------------------------------------------------------------- 1 | { 2 | "dep_dirs": [ 3 | "../" 4 | ], 5 | "include_dirs": [ 6 | "../include" 7 | ], 8 | "libs": [ 9 | "gtest" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /x/cpp/tests/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char** argv) { 4 | testing::InitGoogleTest(&argc, argv); 5 | 6 | return RUN_ALL_TESTS(); 7 | } 8 | -------------------------------------------------------------------------------- /x/go/codec/codec.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | ) 7 | 8 | const Unused = 0 9 | 10 | var ( 11 | ErrNegativeLength = errors.New("negative length") 12 | ErrTooBigLength = errors.New("too big length") 13 | ) 14 | 15 | type Dispatcher interface { 16 | Dispatch(id uint32, body Reader) (int, error) 17 | } 18 | 19 | type Message interface { 20 | MessageId() int 21 | MessageName() string 22 | Encode(Writer) (int, error) 23 | Decode(Reader) (int, error) 24 | } 25 | 26 | // sizedReader implements Reader interface 27 | type sizedReader struct { 28 | reader Reader 29 | size int 30 | } 31 | 32 | var EOF = errors.New("eof") 33 | 34 | func (sr *sizedReader) Read(p []byte) (n int, err error) { 35 | size := len(p) 36 | if size > sr.size { 37 | n, err = sr.reader.Read(p[:sr.size]) 38 | if err == nil { 39 | err = EOF 40 | } 41 | } else { 42 | n, err = sr.reader.Read(p) 43 | } 44 | sr.size -= n 45 | return n, err 46 | } 47 | 48 | func (sr *sizedReader) ReadByte() (byte, error) { 49 | if sr.size < 1 { 50 | return 0, EOF 51 | } 52 | b, err := sr.reader.ReadByte() 53 | if err == nil { 54 | sr.size -= 1 55 | } 56 | return b, err 57 | } 58 | 59 | // MessageReader read and dispatch Message 60 | type MessageReader struct { 61 | sr *sizedReader 62 | dispatcher Dispatcher 63 | } 64 | 65 | func NewMessageReader(reader io.Reader, dispatcher Dispatcher) *MessageReader { 66 | mr := &MessageReader{ 67 | sr: &sizedReader{reader: WrapReader(reader)}, 68 | dispatcher: dispatcher, 69 | } 70 | return mr 71 | } 72 | 73 | func (mr *MessageReader) Read() (int, error) { 74 | total := 0 75 | // read message length 76 | mr.sr.size = 4 77 | size, n, err := Dec.DecodeInt32f(mr.sr) 78 | total += n 79 | if err != nil { 80 | return total, err 81 | } 82 | if size > MaxLength { 83 | return total, ErrTooBigLength 84 | } 85 | mr.sr.size = int(size) 86 | // read message id 87 | id, n, err := Dec.DecodeUint32v(mr.sr) 88 | total += n 89 | if err != nil { 90 | return total, err 91 | } 92 | // dispatch message body by id 93 | n, err = mr.dispatcher.Dispatch(id, mr.sr) 94 | total += n 95 | if err != nil && err != EOF { 96 | return total, err 97 | } 98 | return total, nil 99 | } 100 | 101 | const ( 102 | MaxLength = 1 << 20 // 1M 103 | ) 104 | 105 | var ( 106 | errLengthTooMax = errors.New("length too max") 107 | 108 | Enc = NewEncoder() 109 | Dec = NewDecoder() 110 | ) 111 | 112 | func NewEncoder() Encoder { return zencoder{} } 113 | func NewDecoder() Decoder { return zdecoder{} } 114 | 115 | type Writer interface { 116 | io.Writer 117 | io.ByteWriter 118 | } 119 | 120 | type extendByteWriter struct { 121 | w io.Writer 122 | buf [1]byte 123 | } 124 | 125 | func (w extendByteWriter) Write(b []byte) (int, error) { return w.w.Write(b) } 126 | func (w extendByteWriter) WriteByte(c byte) error { 127 | w.buf[0] = c 128 | _, err := w.w.Write(w.buf[:]) 129 | return err 130 | } 131 | 132 | func WrapWriter(w io.Writer) Writer { 133 | if wc, ok := w.(Writer); ok { 134 | return wc 135 | } 136 | return extendByteWriter{w: w} 137 | } 138 | 139 | type Reader interface { 140 | io.Reader 141 | io.ByteReader 142 | } 143 | 144 | type extendByteReader struct { 145 | r io.Reader 146 | buf [1]byte 147 | } 148 | 149 | func (r extendByteReader) Read(p []byte) (int, error) { return r.r.Read(p) } 150 | func (r extendByteReader) ReadByte() (byte, error) { 151 | _, err := r.r.Read(r.buf[:]) 152 | return r.buf[0], err 153 | } 154 | 155 | func WrapReader(r io.Reader) Reader { 156 | if rc, ok := r.(Reader); ok { 157 | return rc 158 | } 159 | return extendByteReader{r: r} 160 | } 161 | 162 | type Encoder interface { 163 | // Fixed-length integer 164 | EncodeInt8(w Writer, v int8) (n int, err error) 165 | EncodeInt16f(w Writer, v int16) (n int, err error) 166 | EncodeInt32f(w Writer, v int32) (n int, err error) 167 | EncodeInt64f(w Writer, v int64) (n int, err error) 168 | EncodeUint8(w Writer, v uint8) (n int, err error) 169 | EncodeUint16f(w Writer, v uint16) (n int, err error) 170 | EncodeUint32f(w Writer, v uint32) (n int, err error) 171 | EncodeUint64f(w Writer, v uint64) (n int, err error) 172 | 173 | // Variable-length integer 174 | EncodeInt16v(w Writer, v int16) (n int, err error) 175 | EncodeInt32v(w Writer, v int32) (n int, err error) 176 | EncodeInt64v(w Writer, v int64) (n int, err error) 177 | EncodeUint16v(w Writer, v uint16) (n int, err error) 178 | EncodeUint32v(w Writer, v uint32) (n int, err error) 179 | EncodeUint64v(w Writer, v uint64) (n int, err error) 180 | 181 | EncodeFloat32(w Writer, v float32) (n int, err error) 182 | EncodeFloat64(w Writer, v float64) (n int, err error) 183 | EncodeBool(w Writer, v bool) (n int, err error) 184 | EncodeString(w Writer, v string) (n int, err error) 185 | EncodeBytes(w Writer, v []byte) (n int, err error) 186 | } 187 | 188 | type Decoder interface { 189 | // Fixed-length integer 190 | DecodeInt8(r Reader) (v int8, n int, err error) 191 | DecodeInt16f(r Reader) (v int16, n int, err error) 192 | DecodeInt32f(r Reader) (v int32, n int, err error) 193 | DecodeInt64f(r Reader) (v int64, n int, err error) 194 | DecodeUint8(r Reader) (v uint8, n int, err error) 195 | DecodeUint16f(r Reader) (v uint16, n int, err error) 196 | DecodeUint32f(r Reader) (v uint32, n int, err error) 197 | DecodeUint64f(r Reader) (v uint64, n int, err error) 198 | 199 | // Variable-length integer 200 | DecodeInt16v(r Reader) (v int16, n int, err error) 201 | DecodeInt32v(r Reader) (v int32, n int, err error) 202 | DecodeInt64v(r Reader) (v int64, n int, err error) 203 | DecodeUint16v(r Reader) (v uint16, n int, err error) 204 | DecodeUint32v(r Reader) (v uint32, n int, err error) 205 | DecodeUint64v(r Reader) (v uint64, n int, err error) 206 | 207 | DecodeFloat32(r Reader) (v float32, n int, err error) 208 | DecodeFloat64(r Reader) (v float64, n int, err error) 209 | DecodeBool(r Reader) (v bool, n int, err error) 210 | DecodeString(r Reader) (v string, n int, err error) 211 | DecodeBytes(r Reader) (v []byte, n int, err error) 212 | } 213 | 214 | const ( 215 | i06 = 1<<6 - 1 216 | i13 = 1<<13 - 1 217 | i20 = 1<<20 - 1 218 | i27 = 1<<27 - 1 219 | i34 = 1<<34 - 1 220 | i41 = 1<<41 - 1 221 | i48 = 1<<48 - 1 222 | i55 = 1<<55 - 1 223 | i62 = 1<<62 - 1 224 | 225 | m06 = 0x80 226 | m13 = 0xC000 227 | m20 = 0xE00000 228 | m27 = 0xF0000000 229 | m34 = 0xF800000000 230 | m41 = 0xFC0000000000 231 | m48 = 0xFE000000000000 232 | m55 = 0xFF00000000000000 233 | m62 = 0xFF80 234 | m69 = 0xFFC0 235 | 236 | u06 = 0x40 237 | u13 = 0x2000 238 | u20 = 0x100000 239 | u27 = 0x08000000 240 | u34 = 0x0400000000 241 | u41 = 0x020000000000 242 | u48 = 0x01000000000000 243 | u55 = 0x0080000000000000 244 | u62 = 0x0040 245 | u69 = 0x0020 246 | ) 247 | -------------------------------------------------------------------------------- /x/go/codec/decoder.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "math" 5 | ) 6 | 7 | // Implements Decoder 8 | type zdecoder struct{} 9 | 10 | func (de zdecoder) DecodeInt8(r Reader) (v int8, n int, err error) { 11 | var b byte 12 | b, err = r.ReadByte() 13 | if err == nil { 14 | n = 1 15 | } 16 | v = int8(b) 17 | return 18 | } 19 | 20 | func (de zdecoder) DecodeInt16f(r Reader) (v int16, n int, err error) { 21 | var uv uint16 22 | uv, n, err = de.DecodeUint16f(r) 23 | v = int16(uv) 24 | return 25 | } 26 | 27 | func (de zdecoder) DecodeInt32f(r Reader) (v int32, n int, err error) { 28 | var uv uint32 29 | uv, n, err = de.DecodeUint32f(r) 30 | v = int32(uv) 31 | return 32 | } 33 | 34 | func (de zdecoder) DecodeInt64f(r Reader) (v int64, n int, err error) { 35 | var uv uint64 36 | uv, n, err = de.DecodeUint64f(r) 37 | v = int64(uv) 38 | return 39 | } 40 | 41 | func (de zdecoder) DecodeUint8(r Reader) (v uint8, n int, err error) { 42 | var b byte 43 | b, err = r.ReadByte() 44 | if err == nil { 45 | n = 1 46 | } 47 | v = uint8(b) 48 | return 49 | } 50 | 51 | func (de zdecoder) DecodeUint16f(r Reader) (v uint16, n int, err error) { 52 | var uv uint64 53 | uv, n, err = de.readUint64(r, 2) 54 | v = uint16(uv) 55 | return 56 | } 57 | 58 | func (de zdecoder) DecodeUint32f(r Reader) (v uint32, n int, err error) { 59 | var uv uint64 60 | uv, n, err = de.readUint64(r, 4) 61 | v = uint32(uv) 62 | return 63 | } 64 | 65 | func (de zdecoder) DecodeUint64f(r Reader) (v uint64, n int, err error) { 66 | return de.readUint64(r, 8) 67 | } 68 | 69 | func (de zdecoder) DecodeInt16v(r Reader) (v int16, n int, err error) { 70 | var uv uint64 71 | uv, n, err = de.zdecodeUint64v(r) 72 | v = int16(int64(uv)) 73 | return 74 | } 75 | 76 | func (de zdecoder) DecodeInt32v(r Reader) (v int32, n int, err error) { 77 | var uv uint64 78 | uv, n, err = de.zdecodeUint64v(r) 79 | v = int32(int64(uv)) 80 | return 81 | } 82 | 83 | func (de zdecoder) DecodeInt64v(r Reader) (v int64, n int, err error) { 84 | var uv uint64 85 | uv, n, err = de.zdecodeUint64v(r) 86 | v = int64(uv) 87 | return 88 | } 89 | 90 | func (de zdecoder) DecodeUint16v(r Reader) (v uint16, n int, err error) { 91 | var uv uint64 92 | uv, n, err = de.zdecodeUint64v(r) 93 | v = uint16(uv) 94 | return 95 | } 96 | 97 | func (de zdecoder) DecodeUint32v(r Reader) (v uint32, n int, err error) { 98 | var uv uint64 99 | uv, n, err = de.zdecodeUint64v(r) 100 | v = uint32(uv) 101 | return 102 | } 103 | 104 | func (de zdecoder) DecodeUint64v(r Reader) (v uint64, n int, err error) { 105 | return de.zdecodeUint64v(r) 106 | } 107 | 108 | func (de zdecoder) DecodeFloat32(r Reader) (v float32, n int, err error) { 109 | b, n, err := de.DecodeUint32f(r) 110 | v = math.Float32frombits(b) 111 | return v, n, err 112 | } 113 | 114 | func (de zdecoder) DecodeFloat64(r Reader) (v float64, n int, err error) { 115 | b, n, err := de.DecodeUint64f(r) 116 | v = math.Float64frombits(b) 117 | return v, n, err 118 | } 119 | 120 | func (de zdecoder) DecodeBool(r Reader) (v bool, n int, err error) { 121 | var uv uint8 122 | uv, n, err = de.DecodeUint8(r) 123 | v = uv != 0 124 | return 125 | } 126 | 127 | func (de zdecoder) DecodeString(r Reader) (v string, n int, err error) { 128 | var l uint32 129 | var m int 130 | l, n, err = de.DecodeUint32v(r) 131 | if err != nil { 132 | return 133 | } 134 | if l > MaxLength { 135 | err = errLengthTooMax 136 | } 137 | p := make([]byte, l) 138 | m, err = r.Read(p) 139 | if err != nil { 140 | return 141 | } 142 | n += m 143 | v = string(p) 144 | return 145 | } 146 | 147 | func (de zdecoder) DecodeBytes(r Reader) (v []byte, n int, err error) { 148 | var l uint32 149 | var m int 150 | l, n, err = de.DecodeUint32v(r) 151 | if err != nil { 152 | return 153 | } 154 | if l > MaxLength { 155 | err = errLengthTooMax 156 | } 157 | v = make([]byte, l) 158 | m, err = r.Read(v) 159 | if err != nil { 160 | return 161 | } 162 | n += m 163 | return 164 | } 165 | 166 | func (de zdecoder) readUint64(r Reader, byteSize uint64) (v uint64, n int, err error) { 167 | var b byte 168 | for i := uint64(0); i < byteSize; i++ { 169 | b, err = r.ReadByte() 170 | if err != nil { 171 | return 172 | } 173 | n++ 174 | v |= uint64(b) << ((byteSize - i - 1) << 3) 175 | } 176 | return 177 | } 178 | 179 | func (de zdecoder) zdecodeUint64v(r Reader) (v uint64, n int, err error) { 180 | var ( 181 | positive bool 182 | b byte 183 | byteSize = 1 184 | ) 185 | // read first byte 186 | b, err = r.ReadByte() 187 | if err != nil { 188 | return 189 | } 190 | n++ 191 | positive = b&0x80 != 0 192 | // read byte size 193 | index := 1 194 | for { 195 | fromIndex := index 196 | index = readBit(b, uint(fromIndex), positive) 197 | byteSize += index - fromIndex 198 | if index < 8 { 199 | break 200 | } 201 | b, err = r.ReadByte() 202 | if err != nil { 203 | return 204 | } 205 | n++ 206 | // reset index 207 | index = 0 208 | } 209 | remainByteSize := uint64(byteSize - n) 210 | if index <= 6 { 211 | off := uint64(index) + 1 212 | v |= uint64(b<>off) << (remainByteSize << 3) 213 | } 214 | // read value 215 | for i := uint64(0); i < remainByteSize; i++ { 216 | b, err = r.ReadByte() 217 | if err != nil { 218 | return 219 | } 220 | n++ 221 | v |= uint64(b) << ((remainByteSize - i - 1) << 3) 222 | } 223 | if !positive { 224 | v = uint64(-v) 225 | } 226 | return 227 | } 228 | 229 | func readBit(b byte, fromIndex uint, positive bool) int { 230 | for i := fromIndex; i < 8; i++ { 231 | v := b & (0x80 >> i) 232 | if positive == (v == 0) { 233 | return int(i) 234 | } 235 | } 236 | return 8 237 | } 238 | -------------------------------------------------------------------------------- /x/go/codec/encoder.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "io" 5 | "math" 6 | ) 7 | 8 | // Implements Encoder 9 | type zencoder struct{} 10 | 11 | func (en zencoder) EncodeInt8(w Writer, v int8) (n int, err error) { 12 | err = w.WriteByte(byte(v)) 13 | if err == nil { 14 | n = 1 15 | } 16 | return 17 | } 18 | 19 | func (en zencoder) EncodeInt16f(w Writer, v int16) (n int, err error) { 20 | return en.EncodeUint16f(w, uint16(v)) 21 | } 22 | 23 | func (en zencoder) EncodeInt32f(w Writer, v int32) (n int, err error) { 24 | return en.writeUint64(w, 4, uint64(v)) 25 | } 26 | 27 | func (en zencoder) EncodeInt64f(w Writer, v int64) (n int, err error) { 28 | return en.writeUint64(w, 8, uint64(v)) 29 | } 30 | 31 | func (en zencoder) EncodeUint8(w Writer, v uint8) (n int, err error) { 32 | err = w.WriteByte(byte(v)) 33 | if err == nil { 34 | n = 1 35 | } 36 | return 37 | } 38 | 39 | func (en zencoder) EncodeUint16f(w Writer, v uint16) (n int, err error) { 40 | err = w.WriteByte(byte(v >> 8)) 41 | if err != nil { 42 | return 43 | } 44 | n += 1 45 | err = w.WriteByte(byte(v & 0x00FF)) 46 | if err != nil { 47 | return 48 | } 49 | n += 1 50 | return 51 | } 52 | 53 | func (en zencoder) EncodeUint32f(w Writer, v uint32) (n int, err error) { 54 | return en.writeUint64(w, 4, uint64(v)) 55 | } 56 | 57 | func (en zencoder) EncodeUint64f(w Writer, v uint64) (n int, err error) { 58 | return en.writeUint64(w, 8, uint64(v)) 59 | } 60 | 61 | func (en zencoder) EncodeInt16v(w Writer, v int16) (n int, err error) { 62 | if v < 0 { 63 | return en.zencodeUint64v(w, false, uint64(-int32(v))) 64 | } 65 | return en.zencodeUint64v(w, true, uint64(v)) 66 | } 67 | 68 | func (en zencoder) EncodeInt32v(w Writer, v int32) (n int, err error) { 69 | if v < 0 { 70 | return en.zencodeUint64v(w, false, uint64(-int64(v))) 71 | } 72 | return en.zencodeUint64v(w, true, uint64(v)) 73 | } 74 | 75 | func (en zencoder) EncodeInt64v(w Writer, v int64) (n int, err error) { 76 | if v < 0 { 77 | return en.zencodeUint64v(w, false, uint64(-v)) 78 | } 79 | return en.zencodeUint64v(w, true, uint64(v)) 80 | } 81 | 82 | func (en zencoder) EncodeUint16v(w Writer, v uint16) (n int, err error) { 83 | return en.zencodeUint64v(w, true, uint64(v)) 84 | } 85 | 86 | func (en zencoder) EncodeUint32v(w Writer, v uint32) (n int, err error) { 87 | return en.zencodeUint64v(w, true, uint64(v)) 88 | } 89 | 90 | func (en zencoder) EncodeUint64v(w Writer, v uint64) (n int, err error) { 91 | return en.zencodeUint64v(w, true, uint64(v)) 92 | } 93 | 94 | func (en zencoder) EncodeFloat32(w Writer, v float32) (n int, err error) { 95 | return en.EncodeUint32f(w, math.Float32bits(v)) 96 | } 97 | 98 | func (en zencoder) EncodeFloat64(w Writer, v float64) (n int, err error) { 99 | return en.EncodeUint64f(w, math.Float64bits(v)) 100 | } 101 | 102 | func (en zencoder) EncodeBool(w Writer, v bool) (n int, err error) { 103 | if v { 104 | return en.EncodeUint8(w, 1) 105 | } 106 | return en.EncodeUint8(w, 0) 107 | } 108 | 109 | func (en zencoder) EncodeString(w Writer, v string) (n int, err error) { 110 | l := uint32(len(v)) 111 | n, err = en.EncodeUint32v(w, l) 112 | if err != nil { 113 | return 114 | } 115 | n2, err2 := io.WriteString(w, v) 116 | n += n2 117 | err = err2 118 | return 119 | } 120 | 121 | func (en zencoder) EncodeBytes(w Writer, v []byte) (n int, err error) { 122 | l := uint32(len(v)) 123 | n, err = en.EncodeUint32v(w, l) 124 | if err != nil { 125 | return 126 | } 127 | n2, err2 := w.Write(v) 128 | n += n2 129 | err = err2 130 | return 131 | } 132 | 133 | func (en zencoder) zencodeUint64v(w Writer, positive bool, v uint64) (n int, err error) { 134 | var byteSize uint64 135 | switch { 136 | case v <= i06: 137 | if positive { 138 | v |= m06 139 | } else { 140 | v |= u06 141 | } 142 | byteSize = 1 143 | case v <= i13: 144 | if positive { 145 | v |= m13 146 | } else { 147 | v |= u13 148 | } 149 | byteSize = 2 150 | case v <= i20: 151 | if positive { 152 | v |= m20 153 | } else { 154 | v |= u20 155 | } 156 | byteSize = 3 157 | case v <= i27: 158 | if positive { 159 | v |= m27 160 | } else { 161 | v |= u27 162 | } 163 | byteSize = 4 164 | case v <= i34: 165 | if positive { 166 | v |= m34 167 | } else { 168 | v |= u34 169 | } 170 | byteSize = 5 171 | case v <= i41: 172 | if positive { 173 | v |= m41 174 | } else { 175 | v |= u41 176 | } 177 | byteSize = 6 178 | case v <= i48: 179 | if positive { 180 | v |= m48 181 | } else { 182 | v |= u48 183 | } 184 | byteSize = 7 185 | case v <= i55: 186 | if positive { 187 | v |= m55 188 | } else { 189 | v |= u55 190 | } 191 | byteSize = 8 192 | case v <= i62: 193 | if positive { 194 | // m62=0xFF80 195 | err = w.WriteByte(0xFF) 196 | v |= 0x80 << 56 197 | } else { 198 | // u62=0x0040 199 | err = w.WriteByte(0x00) 200 | v |= 0x40 << 56 201 | } 202 | if err != nil { 203 | return 204 | } 205 | n += 1 206 | byteSize = 8 207 | n2, err2 := en.writeUint64(w, byteSize, v) 208 | n += n2 209 | if err2 != nil { 210 | err = err2 211 | } 212 | return 213 | default: 214 | if positive { 215 | n, err = en.writeUint64(w, 2, m69) 216 | } else { 217 | n, err = en.writeUint64(w, 2, u69) 218 | } 219 | if err != nil { 220 | return 221 | } 222 | byteSize = 8 223 | n2, err2 := en.writeUint64(w, byteSize, v) 224 | n += n2 225 | if err2 != nil { 226 | err = err2 227 | } 228 | return 229 | } 230 | return en.writeUint64(w, byteSize, v) 231 | } 232 | 233 | func (en zencoder) writeUint64(w Writer, byteSize uint64, v uint64) (n int, err error) { 234 | const c = 0xFF 235 | for i := uint64(0); i < byteSize; i++ { 236 | off := (byteSize - i - 1) << 3 237 | b := (v & (c << off)) >> off 238 | err = w.WriteByte(byte(b)) 239 | if err != nil { 240 | return 241 | } 242 | n++ 243 | } 244 | return 245 | } 246 | -------------------------------------------------------------------------------- /x/go/codec/zcode_bench_test.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "math" 5 | "testing" 6 | ) 7 | 8 | type mockWriter int 9 | 10 | func (w mockWriter) Write(p []byte) (int, error) { return len(p), nil } 11 | func (w mockWriter) WriteByte(b byte) error { return nil } 12 | 13 | func Benchmark_EncodeInt32v_Big(b *testing.B) { 14 | en := NewEncoder() 15 | w := mockWriter(0) 16 | 17 | for i := 0; i < b.N; i++ { 18 | en.EncodeInt32v(w, math.MaxInt32) 19 | } 20 | } 21 | 22 | func Benchmark_EncodeInt64v_Big(b *testing.B) { 23 | en := NewEncoder() 24 | w := mockWriter(0) 25 | 26 | for i := 0; i < b.N; i++ { 27 | en.EncodeInt64v(w, math.MaxInt64) 28 | } 29 | } 30 | 31 | func Benchmark_EncodeInt32f_Big(b *testing.B) { 32 | en := NewEncoder() 33 | w := mockWriter(0) 34 | 35 | for i := 0; i < b.N; i++ { 36 | en.EncodeInt32f(w, math.MaxInt32) 37 | } 38 | } 39 | 40 | func Benchmark_EncodeInt64f_Big(b *testing.B) { 41 | en := NewEncoder() 42 | w := mockWriter(0) 43 | 44 | for i := 0; i < b.N; i++ { 45 | en.EncodeInt64f(w, math.MaxInt64) 46 | } 47 | } 48 | 49 | func Benchmark_EncodeInt32v_Small(b *testing.B) { 50 | en := NewEncoder() 51 | w := mockWriter(0) 52 | 53 | for i := 0; i < b.N; i++ { 54 | en.EncodeInt32v(w, 1) 55 | } 56 | } 57 | 58 | func Benchmark_EncodeInt64v_Small(b *testing.B) { 59 | en := NewEncoder() 60 | w := mockWriter(0) 61 | 62 | for i := 0; i < b.N; i++ { 63 | en.EncodeInt64v(w, 1) 64 | } 65 | } 66 | 67 | func Benchmark_EncodeInt32f_Small(b *testing.B) { 68 | en := NewEncoder() 69 | w := mockWriter(0) 70 | 71 | for i := 0; i < b.N; i++ { 72 | en.EncodeInt32f(w, 1) 73 | } 74 | } 75 | 76 | func Benchmark_EncodeInt64f_Small(b *testing.B) { 77 | en := NewEncoder() 78 | w := mockWriter(0) 79 | 80 | for i := 0; i < b.N; i++ { 81 | en.EncodeInt64f(w, 1) 82 | } 83 | } 84 | --------------------------------------------------------------------------------