20 Star 125 Fork 24

木兰编程语言 / mulan-rework

 / 详情

【老手】木兰源码转换为 Python

已完成
需求 拥有者
创建于  
2021-05-09 17:00

木兰原始可执行文件 的 --dump-python 命令行选项可以将木兰源码转换为 Python 源码。 以 超类.ul 为例:

type Animal {

  func $Animal() {
    println(1)
  }

  func $run(n) {
    println(n)
  }
}


type WildAnimal {

  func $WildAnimal(name) {
    println(name)
  }
}


type Person : Animal {

  func $Person() {
    super()
  }

  func $go() {
    super.run(3)
  }
}


type Wolf : WildAnimal {

  func $Wolf() {
    super(2)
  }
}
Person()
Wolf()
Person().go()

运行:

> .\ulang-0.2.2.exe --dump-python 测试\unittest\源码生成\类型\超类.ul

输出 Python 源码如下:

import sys
from math import *
ARGV = sys.argv[1:]
class Animal:

  def __init__(self):
    print(1)

  def run(self, n):
    print(n)


class WildAnimal:

  def __init__(self, name):
    print(name)


class Person(Animal):

  def __init__(self):
    super().__init__()

  def go(self):
    super().run(3)


class Wolf(WildAnimal):

  def __init__(self):
    super().__init__(2)
Person()
Wolf()
Person().go()

任务目标

复现此功能,包括完备的测试用例,即从木兰源码文件可以生成对应的 Python 源码文件。实现上,除 逆向工程 之外,可参考已部分实现的从语法树生成木兰源码的功能,测试运行脚本在此。测试用例应覆盖实现的所有逻辑分支。

要求

  • 在实现前,讨论决定如何拆分实现到多个提交(git commit),并在第一个提交时就创建 PR,以便于及时交流代码避免过大偏差。
  • 确保添加的测试用例能集成到 两项测试中 一并运行并通过。
  • 如果有木兰语法尚未支持导致测试用例无法通过,请用 Python 例程生成语法树代替。
  • 测试用例之外的代码请用中文命名标识符,包括类、变量、方法名等等。
  • 如有两位以上达成目标,将按提交顺序等因素选择中标者。

评论 (31)

吴烜 创建了需求
吴烜 修改了描述
吴烜 置顶等级设置为
吴烜 修改了描述
展开全部操作日志

@Hydration 欢迎前来。搭建开发环境如遇到任何问题欢迎随时提出,会尽快回应。此任务是开出悬赏以来工作量最大的一个,希望在着手实现前讨论一下,以便同步认识,合作时也希望多多交流、少走弯路。

关于交流风格,与另一位合作者的初个任务供参考:#I3QHKV:【合作示范】重现一个内置函数——bytes 有兴趣的话也可看看其他已完成的悬赏任务(不少讨论在 PR 中进行)。

期待~

欢迎报价并提供相应依据。

木兰源码生成抽象语法树(AST)接口有了吗? 发出来看下, 这样才能评估把抽象语法树转成py工作量。 如果连自己语法的抽象语法树都没有, 那工作量就大了。

你好,木兰源码语法分析后就生成 Python 语法树(参考了逆向的实现),具体实现请见 语法分析器.py,相关单元测试在 测试/unittest/语法树.py
交互环境下可如下输出语法树细节:

$ python -m 木兰 -树 测试/流程控制/条件三段.ul
Module(body=[If(test=Num(n=0, lineno=1, col_offset=4), body=[Expr(value=Call(func=Name(id='print', ctx=Load(), lineno=2, col_offset=5), args=[Num(n=3, lineno=2, col_offset=11)], keywords=[], lineno=2, col_offset=5), lineno=2, col_offset=5)], orelse=[If(test=Num(n=0, lineno=3, col_offset=8), body=[Expr(value=Call(func=Name(id='print', ctx=Load(), lineno=4, col_offset=5), args=[Num(n=2, lineno=4, col_offset=11)], keywords=[], lineno=4, col_offset=5), lineno=4, col_offset=5)], orelse=[Expr(value=Call(func=Name(id='print', ctx=Load(), lineno=6, col_offset=5), args=[Num(n=5, lineno=6, col_offset=11)], keywords=[], lineno=6, col_offset=5), lineno=6, col_offset=5)], lineno=3, col_offset=3)], lineno=1, col_offset=1)])

可以解除 此处注释,输出更可读的语法树:

Module(
  body=[If(
      test=Num(
        n=0
        lineno=1
        col_offset=4
      )
      body=[Expr(
          value=Call(
            func=Name(
              id='print'
              ctx=Load()
              lineno=2
              col_offset=5
            )
            args=[Num(
                n=3
                lineno=2
                col_offset=11
              )]
            keywords=[]
            lineno=2
            col_offset=5
          )
          lineno=2
          col_offset=5
        )]
      orelse=[If(
          test=Num(
            n=0
            lineno=3
            col_offset=8
          )
          body=[Expr(
              value=Call(
                func=Name(
                  id='print'
                  ctx=Load()
                  lineno=4
                  col_offset=5
                )
                args=[Num(
                    n=2
                    lineno=4
                    col_offset=11
                  )]
                keywords=[]
                lineno=4
                col_offset=5
              )
              lineno=4
              col_offset=5
            )]
          orelse=[Expr(
              value=Call(
                func=Name(
                  id='print'
                  ctx=Load()
                  lineno=6
                  col_offset=5
                )
                args=[Num(
                    n=5
                    lineno=6
                    col_offset=11
                  )]
                keywords=[]
                lineno=6
                col_offset=5
              )
              lineno=6
              col_offset=5
            )]
          lineno=3
          col_offset=3
        )]
      lineno=1
      col_offset=1
    )]
)

从逆向(见说明中的链接)看,从语法树生成 Python 这部分实现是扩展了 codegen.SourceGenerator。

你这语法树不对吧, 连每个单词的类型都没有标记出来, 比如是关键字,还是数值, 还是变量命等等类型都要有的.

语法树是 Python 的 ast 库生成的,上面不带格式的输出是 ast.dump 产生的:https://gitee.com/MulanRevive/mulan-rework/blob/master/%E6%9C%A8%E5%85%B0/%E4%B8%AD.py#L76

以上面 测试代码 为例:

if 0 {
    print(3)
} elif 0 {
    print(2)
} else {
    print(5)
}

语法树中此段对应常数 0:

    Num(
        n=0
        lineno=1
        col_offset=4
      )

此段对应函数名 print:

Name(
                  id='print'
                  ctx=Load()
                  lineno=4
                  col_offset=5
                )

非常欢迎。如果对逆向工程中的实现细节有任何问题,欢迎在此提出一同研究。也欢迎任何其他开发问题,会尽快回应。

已经可以使用,但需要测试

不妨先建个pr,一起看看如何完善测试用例。

像0要改成True

@街头艺术家工作室 0不需改为True吧, python中也支持如下:

if 0:
    print(3)

另外, 可与木兰原始可执行文件的行为作对比, 比如:

> .\ulang-0.2.2.exe --dump-python 测试\流程控制\条件.ul
import sys
from math import *
ARGV = sys.argv[1:]
if 1:
  print(3)
if True:
  print(1)

很多人打着开源的名号。行的是廉价招工的事实。国内并不像国外。没利益的事根本不会有人发起。

木兰项目的各项收支见 知乎专栏 相关文章。
欢迎推荐变现渠道。

@吴烜 可以提供一些文档吗?如 “怎么测试” “代码结构分析”

请看项目首页说明的“新手开发”一段。
另外,之前的 pr 供参考。

您好!关于生成 Python 代码的问题,目前我正在开发着一个语言项目,里面的 ail/core/aparser.py 就包含了一个由自身的语法树生成 Python 语法树的转换器,同时 ail/core/pyast.py 里面对大部分的 Python 语法树类型进行了类型标注工作。如果可以的话,我可以使用我这个转换器进行修改,达到对您的语言的适配,您看可以吗?

这个语言是运行在 Python 之上的,大部分特性也是通过转换出特定的 Python 语句实现的

欢迎选用与原始木兰实现不同的方案,但请参阅 先例,尤其是项目目标的重申:

不过鉴于本项目目标是完全复现原始木兰的功能,希望针对逆向中的各段代码编写对应测试用例,以确保本pr的行为与原始木兰相同。

您好,请问这个问题的需求是在于,仅仅将木兰的源码转换为 Python 的源码吗,还需要做一些额外的工作吗

但我实现了代码生成器之后,需要做什么?

说具体些吧。不知打算覆盖哪些测试用例呢?

大概意思是说,当 codegen 部分完成之后,除了单元测试之外的工作,还需要做什么工作呢

主要是确保测试用例覆盖原始木兰的功能。像 pr29就有至少这两个用例未覆盖

嗯明白了!

验收完毕,合作顺利。请查收reward。

此条评论已被系统屏蔽 2022-06-22 09:27
吴烜 置顶等级 修改为不置顶
吴烜 置顶等级设置为
吴烜 添加了
 
悬赏
标签
吴烜 任务状态待办的 修改为已完成
吴烜 置顶等级 修改为不置顶

登录 后才可以发表评论

状态
负责人
项目
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
预计工期 (小时)
参与者(8)
Python
1
https://gitee.com/MulanRevive/mulan-rework.git
git@gitee.com:MulanRevive/mulan-rework.git
MulanRevive
mulan-rework
mulan-rework

搜索帮助