木蘭 (程式語言)

木蘭（Mulan），名稱來自模塊單元語言（Module Unit Language）的縮寫，是一種教學用程式語言，其語法規範來自Lua，編譯與執行環境使用Python實現。由中國科學院計算技術研究所入股的中科智芯公司於2020年1月15日發表，團隊領導人為中科院副研究員劉雷。這套程式語言是中科智芯公司的重點產品，主要應用於中華人民共和國境內的中小學及幼稚園，作教育使用。

發表之初，研發團隊曾稱這個程式語言可使用於人工智慧與物聯網，完全自主研發，編譯器與集成開發環境套件也完全由團隊開發。在發表後，被質疑是以Python 3.7套件套殼產生。開發者劉雷承認是基於Python做二次開發，完全自主研發以及針對人工智慧及物聯網應用開發等說法為過度誇大。至2020年1月20日，官方下載網頁無法打開，劉雷也被中科院停職接受調查。

## 簡介

木蘭由中國科學院計算技術研究所國家重點實驗室編譯組研發團隊於2020年1月15日發表。在發表時，開發團隊領導人劉雷聲稱這套程式語言完全由這個研發團隊進行自主設計、開發、編程，編譯器與集成開發工具套件也完全自主開發，完全掌握核心技術；劉雷認為這個程式語言將會成為「智能物聯時代的C語言」。劉雷聲稱，木蘭是為針對人工智慧與物聯網應用而開發的程式語言；不過因為有易於理解及使用的特性，在尚未被大量使用於應用開發的情況下，木蘭已經投入中小學及幼稚園的教育課程中使用。在硬體上，能夠搭配中華人民共和國自主研發的龍芯、寒武紀處理器，在作業系統上可搭配Android、iOS、Linux、Windows系統跨平台運作。

中科智芯科技有限公司提供「青少年人工智慧教育」相關的服務，其網頁上介紹木蘭語言時則僅聲稱該語言是「專為人工智慧教育而生的程式語言」。2020年1月20日，中科智芯科技網站所提供的木蘭的「語言環境」的安裝包名稱為ulang-0.2.2.exe。

## 語法內容

因為官方尚沒有提供完整開發文件與集成開發套件，這個程式語言的實質內容並不清楚，但在開放 ulang.exe 下載後，開發者社群對它進行逆向工程，對它的特性有基礎了解。通過重現項目，發現了更多語法特性。下面是用木蘭源碼編寫的猜 1-100 數字例程，可用 ulang.exe 運行。

```swift
using Cmd in cmd; using exit in sys; using randrange in random

type GuessNumber : Cmd {
  {
    intro, prompt = "I have a number within 100 in mind, guess which one?", "Try: "
    numberInMind = randrange(1000) / 10; history = []; closestDiffSoFar = 100
  }

  func $default(row) {
    try { n = int(row) }
    catch e : ValueError { println("`row` is not a number, try again"); return }
    $history.append(n); $compare(n)
  }

  func $compare(n) {
    if n == $numberInMind { println("Bingo!"); exit() }
    else {
      println("Too " + (n > $numberInMind ? "large" : "small") + "!")
      println("Getting close though") if $gettingCloser()
    }
  }

  func $gettingCloser {
    minDiff = min(map(n -> { diff = n - $numberInMind; return diff > 0 ? diff : -diff }, $history))
    { $closestDiffSoFar = minDiff; return true } if $closestDiffSoFar > minDiff
  }
}
GuessNumber().cmdloop()
```

其語法的最直觀特色之一是取消了 Python 的強制縮排，改用大括號。通過語句末尾的分號，支持一行內編寫多個語句。

函數方面，可以用 $ 代替 self；在函數無參數時，定義時可以省略；支持 lambda 函數內多個語句。

類型方面，類型擴展使用冒號表示；類型變量需用大括號包圍，如例程中的 intro、prompt 等。

內置函數方面，添加了 println；isinstance 改為 isa。

注釋段用 /* */，注釋行用 //。

關鍵詞方面有諸多修改，比如由 Python 使用的 def 改成 func，類似於Swift、Go與PHP；try...except 改為 try...catch；None 改為 nil，True/False 改為 true/false；class 改為 type 等等。

不支援漢字作為變數名稱，保留的關鍵字中也沒有漢字，因此不能以中文來進行編程。與此相比，Python 3可以使用Unicode文字（包括漢字）作為變量名。

## 實現原理

在程序執行時，用 RPly 進行詞法與語法分析後生成 Python 抽象語法樹，調用 Python 內置函數 compile 生成可執行碼，再調用 Python 內置函數 exec 運行。運行速度與 Python 相近。由於基於 Python 的運行時環境，可以跨平臺運作。

除了運行木蘭源碼，ulang.exe 還有參數支持周邊功能。其中 --dump-python 藉助 codegen 庫將木蘭源碼生成對應的 Python 代碼。

通過擴展 Python 內置函數 __import__，支持導入木蘭模塊，同時仍支持導入 Python 模塊，而且不需 __init__.py 即可找到模塊。語法與 Python 基本對應。

```python
using some_module
using module1, module2
using some_method in some_module
using * in some_module
using * in .
using ceil in math
```

## 關於核心技術的爭議

在其執行檔ulang-0.2.2.exe開放下載後，CSDN網友「沉迷單車的追風少年」等開發者發現，這個執行檔是直接用PyInstaller將Python 3.7套件打包成一個執行檔，圖標直接使用Python的官方圖標。在解開後，其內容大部份都是python 3.7的官方套件，包括python的建構環境、套件等，自行撰寫的部份不多，與其宣稱完全自主開發不同。開發者劉雷回應，在8位元單晶片上的編譯器是由他們團隊自主開發，在32位元處理器上則是基於Python二次開發，其語法規範來自Lua，但擴充了資料類型，主要使用於中小學教育，而不是人工智慧與物聯網開發。1月19日，相關負責人劉雷被中科院停職檢查。之後劉雷則表示木蘭項目沒有使用任何科研經費。1月19日，官方下載網頁已經無法打開。

## 處罰

2020年1月23日，中國科學院計算技術研究所發布《關於「木蘭」語言問題的調查與處理意見》，認為劉雷在「木蘭」語言的宣傳活動中存在欺瞞、虛假陳述和誇大宣傳的行為，取消其五年內專業技術崗位晉升的申請資格，取消三年內科研項目的申請資格，崗位等級從工程師一級降為助理工程師一級。

## 評論

《經濟日報》（中國經濟網）認為，學術界的醜聞「讓人痛心」，認為科學不容玷污，應加強科學道德和學風建設。認為科研工作者應該「以身作則，還學術、還科研一片淨土」。

## 重現項目

由於木蘭源碼並未由官方發布，於1月16日在知乎提出問題『「木蘭」程式語言有什麼特色？』的程式語言愛好者吳烜隨即創建了木蘭程式語言重現項目，並開源在Gitee。2020年11月25日，該項目在開源中國（OSCHINA）主辦的評選活動中位列「最積極運營項目」前20名。

此項目通過修改詞法分析部分，使木蘭支持了中文標識符。猜數字例程改用中文命名如下。

```swift
using Cmd in cmd; using exit in sys; using 随机范围数 in 随机数

type 猜数字 : Cmd {
  {
    intro, prompt = "木兰想了个 100 之内的数，猜是几？", "猜猜吧: "
    想的 = 随机范围数(1000) / 10; 历史 = []; 至今最近 = 100
  }

  func $default(行) {
    try { 数 = int(行) }
    catch 例外 : ValueError { println("`行` 不是数，请再试"); return }
    $历史.append(数); $比较(数)
  }

  func $比较(数) {
    if 数 == $想的 { println("中了!"); exit() }
    else {
      println("太" + (数 > $想的 ? "大" : "小") + "了!")
      println("不过接近咯") if $接近了()
    }
  }

  func $接近了 {
    最近 = min(map(数 -> { 差 = 数 - $想的; return 差 > 0 ? 差 : -差 }, $历史))
    { $至今最近 = 最近; return true } if $至今最近 > 最近
  }
}
猜数字().cmdloop()
```

## 基本資料

- 日語原文：木蘭、Mulan
- 編程范型：多範式：面向對象
- 設計者：劉雷
- 開發者：中科智芯公司
- 發行日期：2020年1月15日
- 軟體版本週期：0.2.2
- 作業系統：跨平台