program-in-chinese / overview

中文编程的历史、现状和展望。issue 中进行相关问题的讨论.
https://zhuanlan.zhihu.com/codeInChinese
GNU General Public License v3.0
383 stars 34 forks source link

方舟编译器中文化的相关话题 #166

Closed nobodxbodon closed 3 days ago

nobodxbodon commented 4 years ago

欢迎加入“方舟编译器中文化”qq群(313105842)。讨论内容大概包括:

以及开发上述过程中的辅助工具。在此过程中,尽可能多与官方代码库互动。

各种平台下对方舟编译器源码编译的结果在此

nobodxbodon commented 4 years ago

根据统计, 当前开放的代码行数在十万之内,排除src/third_party下的代码应该会更少的多,源码汉化希望在11月前完成。 方舟编译器源码行数统计

nobodxbodon commented 4 years ago

中文重命名mpl2mpl/src/class_init.cpp中的标识符后初测结果:生成的out/bin下输出文件与英文命名源码生成的相同。这样的话,就可以保证在中文重命名标识符过程中的功能正确性了—直接比较编译输出文件是否相同 但是, 对字符串的汉化暂时只能倚靠人工检查. 暂时先在独立的汉化文件中记录英中对应字符串, 打算待所有标识符汉化后, 再进行汉化. 60天汉化5万行(下面为工具细测)代码, 还是很有挑战.

行数 目录 按语言分行数
22338 maple_ir cpp=22338
13534 maple_me cpp=13534
6315 mpl2mpl cpp=6315
3778 huawei_secure_c ansic=3778
2191 maple_driver cpp=2191
1116 maple_util cpp=840,ansic=276
504 mempool cpp=504
353 maple_ipa cpp=353
300 maple_phase cpp=300
nobodxbodon commented 4 years ago

手工翻译方舟编译器源码:尝试重命名标识符与文本, 入口部分

nobodxbodon commented 4 years ago

开始对mir_nodes.h中的节点类进行汉化. 各操作语义参考IR设计文档.

参考节点类对应操作参考def文件, 共180个操作符左右. 汉化补完中

手工翻译方舟编译器源码: IR相关节点类

nobodxbodon commented 4 years ago

在进一步进行标识符中文化之前, 打算先提取所有标识符并进行统计, 以预估工作量和细化计划.

项目源码在src/下, 其中这几个目录下的内容不需提取:

下面是初步设想的提取结果, 每个源码文件(包括.h, .cpp, .def等等)对应一个提取文件. 以较短的src/maple_driver/src/file_utils.cpp为例.

注释

1-14行为注释, 可直接提取全文. 最好标记为注释, 比如这样(方便二次处理)), 具体格式待定, 请多提意见建议:

<注释>
1
2 Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved.
3
4 OpenArkCompiler is licensed under the Mulan PSL v1. 
5 You can use this software according to the terms and conditions of the Mulan PSL v1.
6 You may obtain a copy of Mulan PSL v1 at:
7
8   http://license.coscl.org.cn/MulanPSL 
9
10 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11 EITHER 
12 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 13 MERCHANTABILITY OR
14 FIT FOR A PARTICULAR PURPOSE.  
15 See the Mulan PSL v1 for more details.  
</注释>

include部分

15-17行为include部分, 提取文件路径部分:

<头文件>
15 "file_utils.h"
16 <cstdio>
17 "string_utils.h"
</头文件>

源码主体

将C++关键字过滤(namespace, const, bool, if, return等等), 仅留下标识符, 最好也过滤C++标准库部分(std::打头的), 以19-26行为例:

<源码>
19 maple
20 FileUtils GetFileName filePath isWithExtension
21 fullFileName StringUtils GetStrAfterLast filePath FileSeperator kFileSeperatorStr
22 isWithExtension
23 fullFileName
24
25 StringUtils GetStrBeforeLast fullFileName
26
</源码>

继续改进的可能(格式需相应修改):

nobodxbodon commented 4 years ago

这个汉化项目本身的目标有几种可能. 一是作为汉化源码的实战; 二是作为新创中文编程语言的基础. 两者并不矛盾, 参与者可以自行选择着手点.

由于将源代码的标识符汉化将会大大降低参与贡献的门槛, 一个比较可能的定位是作为方舟编译器官方代码库的一个参与门槛更低的镜像.

潜在的参与开发者是国内对编译器技术有兴趣, 但又出于某些原因暂时无法参与到主库开发中的开发者. 在非技术优势方面, 想得到一点, 就是作为一些不便向华为贡献代码的开发者, 也许更方便向此库贡献代码.

在此定位下, 意味着要在官方库之外维护一个分支, 而且本分支最好保持功能上与主库的同步. 也就是说, 可以增加功能(比如对中文关键字的支持), 但不可以减少或影响主库的功能. 这点能够保持多久是个未知数, 当然也和项目能够积累的人气有关.

个人来说, 打算短期内着重在汉化方舟源代码本身, 并小结出一套比较实用的汉化源码流程及工具.

现在一个比较大的不定因素是方舟本身的开源程度, 以及测试集的覆盖程度. 当前没有任何自动测试用例, 已在官网提问题. 在这种条件下, 只能倚靠手工测试来确保源码汉化后的功能保持不变.

nobodxbodon commented 4 years ago

初步统计下, 在9492个标识符中, 下面是前X个占总出现次数的比例(比如前71个占总出现次数的10%). 更全表(wiki渲染时间过长导致只能贴部分)在此:

前几个 占总出现次数的比例
71 10%
224 20%
458 30%
796 40%
1305 50%
2039 60%
2148 70%
4899 80%
7195 90%
9492 100%

虽然标识符提取和统计过程尚有改进空间, 但应该差距不会太大. 接下去打算从高频标识符开始汉化. 原本打算按照驼峰/下划线分词后再进行统计, 但考虑到分词后的结果对汉化的指导性尚不明显, 决定暂缓.

在一周内, 对前10%的标识符(70个左右)进行汉化, 并进行总结(包括是否/如何对标识符统计进行改进).

nobodxbodon commented 4 years ago

在尝试汉化MapleLogger为"日志"时, 发现编译错误, 推测时由于maple_util目录只有头文件, 编译时依靠现成的src/deplibs/libmplutil.a, 而.a文件并无"日志"接口, 导致错误.

想到之前的StmtNode命名为声明节点类时, 也碰到类似问题:

FAILED: /home/xw/git/OpenArkCompiler_cn/out/bin/maple 
/home/xw/git/OpenArkCompiler_cn/../OpenArkCompiler/tools/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-18.04/bin/clang++ -fPIC -std=c++11 -rdynamic -lpthread -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -fPIE -o /home/xw/git/OpenArkCompiler_cn/out/bin/maple -Wl,--start-group obj/src/maple_driver/src/maple.compiler.o obj/src/maple_driver/src/maple.compiler_factory.o obj/src/maple_driver/src/maple.compiler_selector.o obj/src/maple_driver/src/maple.driver_runner.o obj/src/maple_driver/src/maple.file_utils.o obj/src/maple_driver/src/maple.jbc2mpl_compiler.o obj/src/maple_driver/src/maple.maple.o obj/src/maple_driver/src/maple.maple_comb_compiler.o obj/src/maple_driver/src/maple.mplcg_compiler.o obj/src/maple_driver/src/maple.mpl_options.o lib/64/libHWSecureC.a lib/64/libmplipa.a lib/64/libmplir.a lib/64/libmplme.a /home/xw/git/OpenArkCompiler_cn/out/lib/libmplmewpo.a lib/64/libmpl2mpl.a lib/64/libz_maple_host.a **../src/deplibs/libmplphase.a** ../src/deplibs/libmempool.a ../src/deplibs/libmaple_driverutil.a ../src/deplibs/libmplutil.a -Wl,--end-group 
lib/64/libmpl2mpl.a(libmpl2mpl.class_init.o):(.data.rel.ro+0x38): undefined reference to `maple::FuncOptimizeImpl::ProcessBlock(maple::StmtNode1*)'

ProcessBlock接口在maple_phase下定义, 同样只有头文件, 编译依靠现成的src/deplibs/libmplphase.a. 因此重命名后出现链接错误.

观察src/deplibs下的库, 应该对应maple_phase, maple_util, mempool这几个目录下的头文件. libmaple_driverutil.a似乎包括maple_util下的OptionParser等等. 这样的话, 这几个库相关接口(包括如果其他接口所带参数的类型在这几个库中定义), 如果重命名后都会导致编译不过.

这对源码标识符翻译会带来不小的麻烦. 另一方面, 也可以促使首先理清不同目录间的接口依赖关系. 重点在maple_driver, maple_ipa, maple_ir, maple_me, mpl2mpl这几个. 根据此文及后续系列的分析, 基本确定首先从maple_driver开始, 而不根据之前的词频分析进行.

nobodxbodon commented 4 years ago

尝试用批量替换+字典的方式对源码标识符进行自动翻译. 字典来源于之前的手动提交. 由于基本没有任何语法分析, 仅用简单的字符串替换+少量注释/字符串识别处理. 阶段小结如下.

处理的结果与之前的手动修改比较. 生成的diff大约30k, 大约60多处不同. 相对修改的上千处代码来说, 比例很小.

存在的几种问题

  1. 同名标识符 有些本地标识符没有被替换的, 如DefaultOption中的mplOptions. 在汉化过程中, 同名标识符可能属于不同类, 不一定使用同一中文翻译, 这种情况暂时无法处理, 需要语法分析. 统计: 4 8 5 3 1 3 2 ret是否全都是"返回"的语义需逐个检查. 之前并非全局替换. 统计: 7 还有OptionParser中的Parse, 也和CompilerParse重名. 统计: 2 1

  2. 注释与字符串 一些标识符在注释/字符串中也应翻译, 如:ASSERT(i == 0, "Invalid operand idx in UnaryNode");中的UnaryNode. 统计: 15 11 1 当前默认不翻译, 是为了避免不完整翻译. 比如避免"Error while Exe, cmd: "这一字符串被译为"Error while 运行, cmd: "

  3. 标识符替换的硬伤:

    -    LogInfo::MapleLogger() << "/* &" << GlobalTables::GetGsymTable().GetSymbolFromStidx(m.first.Idx())->求名称();
    +    LogInfo::MapleLogger() << "/* &" << GlobalTables::GetGsymTable().GetSymbolFromStidx(m.first.Idx())->GetName();

    此处由于字符串中带有/*, 因此被误判为注释因而GetName未被翻译 统计: 2 1 2

  4. 命名冲突

    const int 运行(const 选项类 &mplOptions, const std::string &options) const;

    其他多数情况下, mplOptions和options都被翻译成"选项", 并无冲突. 但这种情况下, 需要区别. 统计: 1

问题分析

2可通过只当某些标识符在注释/字符串中出现时翻译来规避. 多数问题(1, 3, 4)需要更进一步的语法分析. 包括字符串/注释的识别, 以及不同类中的同名域的区分等等. 最好借助于现成的C++语言分析器.

自动修改的优点

相比手工修改, 减少了不少低级错误(已在主库修正). 比如手工替换时未注意大小写, 以及未对整体标识符进行替换等等.

结论

  1. 使用程序进行源码自动修改有可行性, 即使工具很简陋
  2. 在找到好用的C++源码分析器之前, 暂停改进此自动修改工具
nobodxbodon commented 4 years ago

将楼上小结整理在尝试自动批量翻译方舟编译器源码中的标识符. 暂时搁置, 希望找到合适的分析器. 打算重拾 #165 和 #97 .

nobodxbodon commented 4 years ago

方舟repo的issue提到了下一步开源大概在明年上半年。可能测试框架也会同时开源

nobodxbodon commented 4 years ago

更新的开源计划在此。测试框架已开源

nobodxbodon commented 3 days ago

方舟gitee仓库:https://gitee.com/openarkcompiler/OpenArkCompiler