diff --git a/.github/ISSUE_TEMPLATE/issue.md b/.github/ISSUE_TEMPLATE/issue.md index 7c403404..576f2405 100644 --- a/.github/ISSUE_TEMPLATE/issue.md +++ b/.github/ISSUE_TEMPLATE/issue.md @@ -1,32 +1,17 @@ --- name: Issue -about: General Issue +about: Issue title: "" --- - - -## Describe your issue/suggestions - - - -## Checklist - -Before you create this issue, Please make sure ALL the following items are checked - -- [ ] If this is a feature request, it's NOT listed [Here](https://github.com/LingDong-/wenyan-lang#feature-requests) -- [ ] If this is a bug report, it's NOT listed [Here](https://github.com/LingDong-/wenyan-lang#known-bugs) \ No newline at end of file +Thank you! +--> \ No newline at end of file diff --git a/.gitignore b/.gitignore index 0f56ea83..bc3dfb96 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ dist /tools/calendar.html 藏書樓 .node-xmlhttprequest-* -typings \ No newline at end of file +typings +tools/wiki/repo \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..67f47cf1 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +# Contributing + +Please check out the contributing guide on [wiki](https://github.com/wenyan-lang/wenyan/wiki/Contributing) \ No newline at end of file diff --git a/README.md b/README.md index 5f5882a5..e38e880b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![build](https://img.shields.io/github/workflow/status/LingDong-/wenyan-lang/Build%20%26%20Test)](https://github.com/LingDong-/wenyan-lang/actions) [![Netlify Status](https://api.netlify.com/api/v1/badges/c36d4838-1c8f-4cfe-986e-43e0de6f71a3/deploy-status)](https://app.netlify.com/sites/wenyan-lang/deploys) -### [https://wy-lang.org](https://wy-lang.org) +### [wy-lang.org](https://wy-lang.org) | [Wiki](https://github.com/wenyan-lang/wenyan/wiki) English | [简体中文](./README.zh-Hans.md) | [繁体中文](./README.zh-Hant.md) @@ -20,7 +20,6 @@ English | [简体中文](./README.zh-Hans.md) | [繁体中文](./README.zh-Hant. > 夫[唐](https://en.wikipedia.org/wiki/Emperor_Yao)、[虞](https://en.wikipedia.org/wiki/Emperor_Shun)之世,[結繩而足治](https://ctext.org/book-of-changes/xi-ci-xia/zh),屈指而足算。是時豈料百代之後,計算機械之巧,精於[公輸](https://en.wikipedia.org/wiki/Lu_Ban)之[木鳶](https://en.wikipedia.org/wiki/Lu_Ban#Inventions),善於[武侯](https://en.wikipedia.org/wiki/Zhuge_Liang)之[流馬](https://en.wikipedia.org/wiki/Wooden_ox);程式語言之多,繁若[《天官》](https://ctext.org/shiji/tian-guan-shu/zh)之星宿,奇勝[《山經》](https://en.wikipedia.org/wiki/Classic_of_Mountains_and_Seas)之走獸。[鼠](https://golang.org/)、[蟹](https://www.rust-lang.org/)、[鑽](http://ruby-lang.org/)、[魚](https://fishshell.com/),或以速稱。[蛇](https://www.python.org/)、[象](https://www.php.net/)、[駱](https://www.perl.org/)、[犀](http://shop.oreilly.com/product/9780596805531.do),各爭文采。方知[鬼之所以夜哭,天之所以雨粟](https://ctext.org/huainanzi/ben-jing-xun/zh)。然以文言編程者 ,似所未有。此誠非文脈之所以傳,文心之所以保。[嗟予小子](https://zh.wikisource.org/zh-hant/%E6%A6%AE%E6%9C%A8_(%E9%99%B6%E6%B7%B5%E6%98%8E)),遂有斯志。然則數寸之烏絲猶覆於頭,[萬卷之素書未破於手](https://zh.wikisource.org/zh-hant/%E5%A5%89%E8%B4%88%E9%9F%8B%E5%B7%A6%E4%B8%9E%E4%B8%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E9%9F%BB);一身長羈於遠邦,兩耳久曠于[雅言](https://zh.wikipedia.org/wiki/%E9%9B%85%E9%9F%B3)。然夫文章者吾之所宿好,程式者偶承時人之謬譽。故[希孟](https://en.wikipedia.org/wiki/Wang_Ximeng)不慚年少,[莊生](https://en.wikipedia.org/wiki/Zhuang_Zhou)不望[無涯](https://ctext.org/zhuangzi/nourishing-the-lord-of-life/zh)。乃作斯言。誠未能嘔瀝[長吉](https://en.wikipedia.org/wiki/Li_He)之[心血](https://zh.wikisource.org/zh-hant/%E6%9D%8E%E8%B3%80%E5%B0%8F%E5%82%B3),亦庶幾免於[義山](https://en.wikipedia.org/wiki/Li_Shangyin)之[流沫](https://zh.wikisource.org/zh-hant/%E9%9F%93%E7%A2%91)。既成之後,復學[干將鑄劍](https://zh.wikisource.org/wiki/%E9%91%84%E5%8A%8D)而自飼,[越王嚐糞](https://ctext.org/wu-yue-chun-qiu/yue-wang-gou-jian-wu-nian/zh)而當先。自謂偶追[《十書》](https://en.wikipedia.org/wiki/Ten_Computational_Canons)之筆意,但恨少[八家](https://en.wikipedia.org/wiki/Eight_Masters_of_the_Tang_and_Song)之淋漓。此[子山](https://en.wikipedia.org/wiki/Yu_Xin)所謂[士衡撫掌而甘心,平子見陋而固宜](https://zh.wikisource.org/zh-hant/%E5%93%80%E6%B1%9F%E5%8D%97%E8%B3%A6)。然則雖實[覆甕](https://zh.wikisource.org/zh-hant/%E6%99%89%E6%9B%B8/%E5%8D%B7092#%E5%B7%A6%E6%80%9D)之質,尚存斧正之望;雖乏[呂相](https://en.wikipedia.org/wiki/L%C3%BC_Buwei)之金,[易字](https://zh.wikisource.org/zh/%E5%8F%B2%E8%A8%98/%E5%8D%B7085)之渴蓋同。此亦開源之大義,吾輩之所以勉勵也。一笑。 - ## Helloworld Wenyan: @@ -60,13 +59,22 @@ More sophisticated examples, such as the Sieve of Eratosthenes, Quicksort, Mande - [Natural Language Programming](https://en.wikipedia.org/wiki/Natural-language_programming) sharing the grammar of [Classical Chinese](https://en.wikipedia.org/wiki/Classical_Chinese) - Compiles to [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript), [Python](https://python.org), or [Ruby](http://ruby-lang.org) - [Turing complete](https://github.com/LingDong-/wenyan-lang/blob/master/examples/turing.wy) -- An [online IDE](https://wy-lang.org/ide) +- An [Online IDE](https://wy-lang.org/ide) - [Examples](https://github.com/LingDong-/wenyan-lang/tree/master/examples) to get started +## Try it out + +### [The Online IDE](https://wy-lang.org/ide) -## Installation +![](screenshots/screenshot02.png) -### The Compiler +### Text Editor Plugins + +- [Plugin for VSCode](https://github.com/antfu/wenyan-lang-vscode) by [antfu](https://github.com/antfu) +- [Plugin for Vim](https://github.com/voldikss/vim-wenyan) by [voldikss](https://github.com/voldikss) +- [Plugin for Sublime Text](https://github.com/absop/SublimeWenyan) by [absop](https://github.com/absop) + +### Command Line Compiler Install the compiler by @@ -81,14 +89,6 @@ wenyan examples/helloworld.wy # will outputs: 問天地好在。 ``` -> From v0.1.0, the `wenyan` command will direct execute the script by default. If you are migrating from previous versions, please use `wenyan -h` to output the help and check [this PR](https://github.com/LingDong-/wenyan-lang/pull/356) for the detailed changes. - - -### [The Online IDE](https://wy-lang.org/ide) - -![](screenshots/screenshot02.png) - - ### [The Decompiler](https://zxch3n.github.io/wenyanizer/) You can now translate JavaScript to wenyan-lang using the [wenyanizer](https://github.com/zxch3n/wenyanizer) by [zxch3n](https://github.com/zxch3n). @@ -97,146 +97,13 @@ You can now translate JavaScript to wenyan-lang using the [wenyanizer](https://g - [JVM compiler](https://github.com/MagicLu550/wenyan-lang_jvm) by [MagicLu550](https://github.com/MagicLu550) -### Text Editor Plugins - -- [Plugin for VSCode](https://github.com/antfu/wenyan-lang-vscode) by [antfu](https://github.com/antfu) -- [Plugin for Vim](https://github.com/voldikss/vim-wenyan) by [voldikss](https://github.com/voldikss) -- [Plugin for Sublime Text](https://github.com/absop/SublimeWenyan) by [absop](https://github.com/absop) - -### Browser Runtime - -You can now run Wenyan scripts right in your html file. - -Please refer to [Browser Runtime](./documentation/Runtime.md) - -### Advance Usage - -[Compiler API Specification](./documentation/Compiler-API.md) - -## Syntax Cheatsheet - -You can find the Language Specification [here](https://wy-lang.org/spec) (WIP). To get started, you can also check the cheatsheet below, or look into `src/parser.js` to learn more. Be sure to check out the examples from the online IDE too! - -### Variables - -| wenyan | JavaScript | -|---|---| -|`吾有一數。曰三。名之曰「甲」。` | `var a = 3;` | -|`有數五十。名之曰「大衍」。` | `var dayan = 50;` | -|`昔之「甲」者。今「大衍」是矣。` | `a = dayan;` | -|`吾有一言。曰「「噫吁戲」」。名之曰「乙」。` | `var b = "alas!";` | -|`吾有一爻。曰陰。名之曰「丙」。` | `var c = false;` | -|`吾有一列。名之曰「丁」。` | `var d = [];` | -|`吾有三數。曰一。曰三。曰五。名之曰「甲」曰「乙」曰「丙」。` | `var a=1,b=3,c=5;` | -|`吾有一元` | `(auto type)` | - -### Control - -| wenyan | JavaScript | -|---|---| -|`若三大於二者。乃得「「想當然耳」」也。` | `if (3>2){ return "of course"; }` | -|`若三不大於五者。乃得「「想當然耳」」。若非。乃得「「怪哉」」也。` | `if(3<=5){return "of course"}else{return "no way"}` | -|`為是百遍。⋯⋯ 云云。` | `for (var i = 0; i < 100; i++){ ... }` | -|`恆為是。⋯⋯ 云云。` | `while (true) { ... }` | -|`凡「天地」中之「人」。⋯⋯ 云云。` | `for (var human of world){ ... }` | -|`乃止。`|`break;`| -|`乃止是遍`|`continue`| -|`或若`|`else if` | -|`若其然者` |`if (ans) {` | -|`若其不然者`|`if (!ans) {` | - -### Math - -| wenyan | JavaScript | -|---|---| -|`加一以二。` | `1+2` | -|`加一於二。` | `2+1` | -|`加一以二。乘其以三。` | `(1+2)*3` | -|`除十以三。所餘幾何。` | `10%3` | -|`減七百五十六以四百三十三。名之曰「甲」。` | `var a = 756-433;` | -|`夫「甲」「乙」中有陽乎。` | `a \|\| b` | -|`夫「甲」「乙」中無陰乎。` | `a && b` | - - -### Containers -Arrays are 1-indexed. - -| wenyan | JavaScript | -|---|---| -|`吾有一列。名之曰「甲」。充「甲」以四。以二。` | `var a = []; a.push(4, 2);` | -|`銜「甲」以「乙」。以「丙」` | `a.concat(b).concat(c);` | -|`夫「甲」之一。` | `a[0]` | -|`夫「甲」之其餘。` | `a.slice(1);` | -|`夫「玫瑰」之「「名」」。` | `rose["name"]` | -|`夫「寶劍」之長。` | `sword.length;` | - - -### Objects - -| wenyan | JavaScript | -|---|---| -|`吾有一物。名之曰「甲」。` | `var a = {};` | -|`吾有一物。名之曰「甲」。其物如是。物之「「乙」」者。數曰三。物之「「丙」」者。言曰「「丁」」。是謂「甲」之物也。` | `var a = {b:3, c:"d"}` | - - -### Functions - -| wenyan | JavaScript | -|---|---| -|`吾有一術。名之曰「吸星大法」。是術曰。⋯⋯是謂「吸星大法」之術也。`|`function f(){...}`| -|`吾有一術。名之曰「六脈神劍」。欲行是術。必先得六數。曰「甲」。曰「乙」。曰「丙」。曰「丁」。曰「戊」。曰「己」乃行是術曰。⋯⋯是謂「六脈神劍」之術也。`|`function f(a,b,c,d,e,f){...}`| -|`吾有一術。名之曰「翻倍」。欲行是術。必先得一數。曰「甲」。乃行是術曰。乘「甲」以二。名之曰「乙」。乃得「乙」。是謂「翻倍」之術也。`|`function double(a){var b = a * 2; return b;}`| -|`施「翻倍」於「大衍」。`|`double(dayan);`| -|`吾有一術。名之曰「甲」。欲行是術。必先得一數曰「乙」。二言。曰「丙」。曰「丁」`|`function a(float b, string c, string d)`| -|`夫「甲」。夫「乙」。夫「丙」。取二以施「丁」。取二以施「戊」。名之曰「己」。` | `var f = e(a,d(b,c))`| -|`夫「甲」。夫「乙」。夫「丙」。取二以施「丁」。取二以施「戊」。取一以施「己」。夫「庚」。夫「辛」。取三以施「壬」。名之曰「癸」。` | `var j = i(f(e(a,d(b,c))),g,h)`| -| `乃得四十九` | `return 49;` | -| `減五十以一。乃得矣` | `return 50-1;` | -| `乃歸空無` | `return;` | - - -### Import - -| wenyan | JavaScript | -|---|---| -|`吾嘗觀「「算經」」之書。方悟「正弦」「餘弦」之義。` | `var {sin,cos} = require("math");` | -|`吾嘗觀「「某樓」」中「「某閣」」中「「某書」」之書。`|`require('path/to/something')` | - - -### Misc - -| wenyan | JavaScript | -|---|---| -|`吾有一數。曰五。書之。`|`console.log(5);`| - -### Comments - -| wenyan | JavaScript | -|---|---| -|`批曰。「「文氣淋灕。字句切實」」。` | `/*文氣淋灕。字句切實*/` | -|`注曰。「「文言備矣」」。` | `/*文言備矣*/` | -|`疏曰。「「居第一之位故稱初。以其陽爻故稱九」」。` | `/*居第一之位故稱初。以其陽爻故稱九*/` | - -### Advance Features - -- [Standard Library](./documentation/Standard-Lib.md) -- [Try...Catch](./documentation/Try-Catch.md) -- [Nested Function Calls](./documentation/Nested-Function-Calls.md) -- [Importing](./documentation/Importing.md) -- [Macros](./documentation/Macros.md) - -## Renderer - -```bash -wenyan examples/turing.wy --render --title 圖靈機 -``` - -Render a wenyan script into an image that resembles pages from historical printed books. -It can also parse the resultant SVG file back to the original program. For more details, please refer to the help by `wenyan -h`. - -Below is the rendering of the Universal Turing Machine written in wenyan: - -![](screenshots/screenshot03.png) +## Documentation +Check out our [Wiki pages](https://github.com/wenyan-lang/wenyan/wiki) -Feature Requests & Known Issues are now hosted on the [Wiki page](https://github.com/wenyan-lang/wenyan/wiki/Feature-Requests-&-Known-Issues). +- [Syntax Cheatsheet](https://github.com/wenyan-lang/wenyan/wiki/Syntax-Cheatsheet) +- [Standard Library Cheatsheet](https://github.com/wenyan-lang/wenyan/wiki/Standard-Library-Cheatsheet) +- [API Specifcations](https://github.com/wenyan-lang/wenyan/wiki/Compiler-API) +- [Browser Runtime](https://github.com/wenyan-lang/wenyan/wiki/Browser-Runtime) +- [Feature Requests](https://github.com/wenyan-lang/wenyan/wiki/Feature-Requests) +- [Known Issues](https://github.com/wenyan-lang/wenyan/wiki/Known-Issues) \ No newline at end of file diff --git a/README.zh-Hans.md b/README.zh-Hans.md index 2ab232a4..3a55ae06 100644 --- a/README.zh-Hans.md +++ b/README.zh-Hans.md @@ -2,12 +2,14 @@ # 文言 wenyan-lang -[http://wenyan-lang.lingdong.works](http://wenyan-lang.lingdong.works) +### [wy-lang.org](https://wy-lang.org) | [Wiki](https://github.com/wenyan-lang/wenyan/wiki) [English](./README.md) | 简体中文 | [繁体中文](./README.zh-Hant.md) 文言文編程語言。 [在线体验](http://wenyan-lang.lingdong.works/ide.html) +> 🚧 请注意,中文文档并非实时更新,仅供参考。如有歧义,请以英文版文档为主。 + ![](screenshots/screenshot01.png) ## 序 diff --git a/README.zh-Hant.md b/README.zh-Hant.md index f40120c8..c2590399 100644 --- a/README.zh-Hant.md +++ b/README.zh-Hant.md @@ -2,12 +2,14 @@ # 文言 wenyan-lang -[http://wenyan-lang.lingdong.works](http://wenyan-lang.lingdong.works) +### [wy-lang.org](https://wy-lang.org) | [Wiki](https://github.com/wenyan-lang/wenyan/wiki) [English](./README.md) | [简体中文](./README.zh-Hans.md) | 繁体中文 文言文編程語言。 [在線體驗](http://wenyan-lang.lingdong.works/ide.html) +> 🚧 請註意,中文文檔並非實時更新,僅供參考。如有歧義,請以英文版文檔為主。 + ![](screenshots/screenshot01.png) ## 序 diff --git a/documentation/Compiler-API.md b/documentation/Compiler-API.md index b4ae9c70..068d0b80 100644 --- a/documentation/Compiler-API.md +++ b/documentation/Compiler-API.md @@ -1,96 +1 @@ -[Back to README](../README.md) - -# Compiler API Specification - -> 🚧 Please note this project is still under heavy development. The API might be changed frequently and this doc any not be always update to date. If you get any questions, feel free to raise an issue. - - -## Installation - -We provide a compiler runs both in Node.js and modern browsers. - -### Node.js - -You can install the dependence by following command. - -```bash -npm install @wenyanlang/core -``` - -```js -const Wenyan = require('@wenyanlang/core') -// or -const { compile } = require('@wenyanlang/core') -// or -import { compile } from '@wenyanlang/core' -``` - -### Browsers - -You can add the following line to the head of your html body. - -```html - -``` - -```html - -``` - -## Exposed Functions - -- core - - [compile](#compile) - - [execute](#execute) - -### Execute - -[Source](../src/parser.js) - -```ts -function execute(source: string, options?: ExecuteOptions) -``` - -**Parameters** - -| Name | Type | Note | -| --- | --- | --- | -| source | string | The Wenyan source code | -| options | object | [Execute Options](#Execute-Options) | - -### Compile - -[Source](../src/parser.js) - -```ts -function compile(source: string, options?: CompilerOptions) -``` - -**Parameters** - -| Name | Type | Note | -| --- | --- | --- | -| source | string | The Wenyan source code | -| options | object | [Compiler Options](#Compiler-Options) | - -#### Compiler Options - -| Fields | Default Value | Note | -| --- | --- | --- | -| lang | `js` | Target language, can be `js`, `py` or `rb` | -| romanizeIdentifiers | none | Romanize variable identifiers (e.g. `甲` to `JIA2`) | -| resetVarCnt | false | Reset temporary variable counter | -| logCallback | console.log | Get verbose debug log | -| errorLog | process.exit | Error log | - -#### Execute Options - -Execute Options extends all field in [Compiler Options](#Compiler-Options) - -| Fields | Default Value | Note | -| --- | --- | --- | -| outputHanzi | true | Convert numbers and bools to Hanzi | -| output | `console.log` | You can redirect the output if you don't want to use `console.log` | +This document is moved to [the wiki page](https://github.com/wenyan-lang/wenyan/wiki/Compiler-API) \ No newline at end of file diff --git a/documentation/Importing.md b/documentation/Importing.md index 156531ba..683b58e3 100644 --- a/documentation/Importing.md +++ b/documentation/Importing.md @@ -1,117 +1 @@ -[Back to README](../README.md) - -# Importing Scripts - -## 1. Import statement (experimental) - -Below is the new import syntax. Thanks everyone for the inspiration! - -``` -吾嘗觀「「算經」」之書。方悟「正弦」「餘弦」「圓周率」之義。 -``` - -``` -from math import sin, cos, pi -``` - -New usage of `今有`. `今有` is now used for exported/public variables, while `吾有` is private/scoped. Think of `今有` like `module.exports.x=`. Think of `吾有` like `var x=` - -Example: - -`易經.wy`(a.k.a. Random) - -``` -吾有一數。曰四十二。名之曰「運數」。 - -今有一術。名之曰「運」。欲行是術。必先得一數。曰「甲」。乃行是術曰。 - 注曰「「運者。隨機種子也」」 - 昔之「運數」者。今「甲」是矣。 -是謂「運」之術也。 - -今有一術。名之曰「占」。是術曰。 - 注曰「「線性同餘方法所得隨機數也」」 - 有數四十二億九千四百九十六萬七千二百九十六。名之曰「模」。 - 有數二千二百六十九萬五千四百七十七。名之曰「倍」。 - 有數一。名之曰「增」。 - 乘「倍」以「運數」。加其以「增」。除其以「模」。所餘幾何。昔之「運數」者。今其是矣。 - 除「運數」以「模」。名之曰「卦」。 - 乃得「卦」。 -是謂「占」之術也。 -``` - -`some_example.wy`(where you import random) - -``` -吾嘗觀「「易經」」之書。方悟「占」之義。 -施「占」。書之。 -``` - -Notice that in `易經.wy` the random seed (運數) is not exported. while its setter (運) is exported, but not imported by `some_example.wy`. Only `占` the generator is exported and imported, and can be used directly. - - -### JS implementation details - -(Python, Ruby are not implemented yet) - - -JS Implementation uses `var MODULE_NAME = new function(){ ... }` trick to wrap imported modules. `今有` maps to `this.` So they can be accessed using `MOUDLE_NAME.identifier`. The import statements specifies which identifiers are actually required, and those that are are extracted from its scope using `var identifier = MODULE_NAME.identifier`. Therefore, `some_example.wy` compiles to this: - -``` -var 易經 = new function() { - var 運數 = 42; - this.運 = () => 0; - this.運 = function(甲) { - /*"運者。隨機種子也"*/ - 運數 = 甲; - }; - this.占 = () => 0; - this.占 = function() { - /*"線性同餘方法所得隨機數也"*/ - var 模 = 4294967296; - var 倍 = 22695477; - var 增 = 1; - var _ans49 = 倍 * 運數; - var _ans50 = _ans49 + 增; - var _ans51 = _ans50 % 模; - 運數 = _ans51; - var _ans52 = 運數 / 模; - var 卦 = _ans52; - return 卦 - }; -}; -var 占 = 易經.占; -var _ans48 = 占(); -console.log(_ans48); -``` - -You can check out a more sophisticated example on the online IDE. In the IDE, you can import an example from another example, or the a module from standard lib. - -`parser.compiler` has a new option called `reader`, which is a function you can provide to tell compiler how to read a module. The default for node.js is to look in current directory plus one directory down. For browser-side you might give it something fancy like AJAX calls or something. - -When you build the CLI compiler, the source of the standard libraries are included, so you can still use it without having the `./lib` folder. - -Please let me know if found any issue or have any suggestion! - - -## 2. Standard Library implementers needed! - -You think you can write wenyan? Please join us! - -Currently in the `./lib` folder there are a couple of "stubs" such as `算經`(math) `位經`(bit ops) `易經`(random). - -They contain many functions to be implemented in wenyan. e.g. The `sin()` function currently contains this HACK: - -``` -今有一術。名之曰「正弦」。欲行是術。必先得一數。曰「甲」。乃行是術曰。 - 施「Math.sin」於「甲」。名之曰「乙」。乃得「乙」。 -是謂「正弦」之術也。 -``` - -What we need to do is to replace `Math.sin` hack to a proper implementation (Taylor series?). - -Our goal is to implement the most commonly used library functions. If you are familiar with one or two of them, please submit a pull request! - - -## 3. Thanks!! - -As you might have noticed, much of the syntax and many ideas are inspired by / borrowed from numerous posts and feature requests. Therefore, a thank you to everyone! \ No newline at end of file +This document is moved to [the wiki page](https://github.com/wenyan-lang/wenyan/wiki/Importing) \ No newline at end of file diff --git a/documentation/Macros.md b/documentation/Macros.md index 30eaf623..052d292c 100644 --- a/documentation/Macros.md +++ b/documentation/Macros.md @@ -1,66 +1 @@ -[Back to README](../README.md) - -# Macros (Experimental) - -As you might (not) have noticed, *wenyan-lang* strives to be more readable (for ancient Chinese people). **Macros** provide syntactic sugars to bring the 文采 of your code to the next level. - -E.g. Now you can patch wenyan-lang's notorius print function like so: - -``` -或云「「書「甲」焉」」。 -蓋謂「「吾有一言。曰「甲」。書之」」。 - -書「「問天地好在」」焉。 -``` - -Since we're beating JavaScript to macros, here is a rough C equivalence: - -``` -#define 書(甲)焉 吾有一言。曰甲。書之 -書("問天地好在")焉。 -``` - -See `./examples/macro.wy` for detailed usage! - -## How it works - -In the `或云` statement, you specify the alternative syntax, using `「甲」`,`「乙」`,`「丙」`etc. (十天干) to denote arguments, and in the `蓋謂` statement you specify what that statment should be replaced by, referencing the arguments using the same 天干. (more than 10 arugments is considered too hideous and therefore not possible). - -It's just like regex. - -Macros potentially solve other problems such as using 爲 instead of 為 etc. Currently, stdlib `列經` uses a couple of macros to make Higher-order functions such as `map` `filter` and `reduce` look prettier. - -So instead of - -``` -施「遍施」於「加一」於「某列」。書之。 -``` - -you can also do - -``` -凡「某列」皆「加一」其上者。書之。 - -``` - -where the syntax is defined by this macro in `列經`: - -``` -或云「「凡「甲」皆「乙」其上者」」。 -蓋謂「「施「遍施」於「乙」於「甲」」」 -``` - -## Cautions - -Your macros cannot start or end with identifier/arguments (e.g. `或云「「書「甲」」」` or `或云「「「甲」焉」」` are BAD. It has to be `或云「「書「甲」焉」」`). Otherwise the preprocesser cannot find out where it starts/ends and might not work as expected. - - -## Implementation details - -The preprocessing is done before tokenization, and it searches all imported modules and gather all the macros and do the finding and replacing. (It might not be the most efficient way to do it, so if you have a better idea please let me know!). See `src/macro.js` for details. - -## Your opinion - -As you can see the macros are very powerful (maybe too powerful). And the downside is that it opens the door to a new dimension of hacks (probably wilder than I can imagine :) - -Please let me know what you think! Thanks! \ No newline at end of file +This document is moved to [the wiki page](https://github.com/wenyan-lang/wenyan/wiki/Macros) \ No newline at end of file diff --git a/documentation/Nested-Function-Calls.md b/documentation/Nested-Function-Calls.md index 56fdc428..810da0fe 100644 --- a/documentation/Nested-Function-Calls.md +++ b/documentation/Nested-Function-Calls.md @@ -1,80 +1 @@ -[Back to README](../README.md) - -# Nested Function Calls - -## Stack-based way to nest function calls - -Due to popular demand, nested function calls is now a feature. Here is a taste: - -``` -注曰「「辛 = 戊(甲,丁(乙,丙))」」 - -夫「甲」。夫「乙」。夫「丙」。取二以施「丁」。取二以施「戊」。名之曰「辛」。 -``` - -More complex example for the courageous: - -``` -注曰「「壬 = 丁(己(戊(甲,丁(乙,丙))),甲,乙)」」 - -夫「甲」。夫「乙」。夫「丙」。取二以施「丁」。取二以施「戊」。取一以施「己」。夫「甲」。夫「乙」。取三以施「丁」。名之曰「壬」。 -``` - -## How it works - -The original syntax of wenyan already employs a stack-like behavior. You can use `其` to refer to the previous unnamed variable, you can use `書之` to print all the unnamed variables, use `名之曰` to name them etc. Therefore, it is natural to use the same system for function calls. - -Now I'll refer to the "list of unnamed variables" as the "stack" for convenience. - -`夫` keyword pushes a variable in into the stack. `取n` marks the last `n` items on the stack as "usable". `以施f` takes all the items marked "usable" and apply function `f` that takes those items as arguments, and push the result onto the stack. Finally you can use `名之曰` to take stuff from back the stack and give them names for later use. - -Recap on other features that already existed before this update: - -- `噫` Clears the stack, discarding everything. -- `其` Refers to the most recent item on the stack. It also clears the stack. The reason for this is not techincal, but is purely done from Classical Chinese readability standpoint: if you use multiple `其` in a row, it can be very confusing: `加其以其。乘其以其。昔之其者。今其是矣。`. Hence. - -More examples, showing that you can also push items of an Array, math results, and so on to stack: - -``` -注曰「「庚 = 丁(甲+乙,癸[3],癸.length)」」 - -加「甲」以「乙」。夫「癸」之三。夫「癸」之長。取三以施「丁」。名之曰「庚」。 -``` - -You can find more examples in `./examples/nested_fun.wy` - -A thank you to @Lotayou and everyone for the discussion in #285 and #301. More functional programming goodies are on their way! - -## Automatically curried functions - -functions in wenyan are now automatically curried, that is, partially applied to return a new function. - -``` -吾有一術。名之曰「丁」。欲行是術。必先得三數。曰「寅」曰「卯」曰「辰」乃行是術曰。 - 乘「寅」以「卯」。加其以「辰」。乃得其。 -是謂「丁」之術也。 - -施「丁」於一於二。名之曰「半丁」。 -施「半丁」於三。書之。 -``` - -compiles to - -``` -var 丁 = () => 0; -丁 = function(寅) { - return function(卯) { - return function(辰) { - var _ans1 = 寅 * 卯; - var _ans2 = _ans1 + 辰; - return _ans2 - }; - }; -}; -var _ans3 = 丁(1)(2); -var 半丁 = _ans3; -var _ans4 = 半丁(3); -console.log(_ans4); -``` - -Again, more FP on its way. +This document is moved to [the wiki page](https://github.com/wenyan-lang/wenyan/wiki/Function-Call) \ No newline at end of file diff --git a/documentation/Runtime.md b/documentation/Runtime.md index 80f8163e..c858a28e 100644 --- a/documentation/Runtime.md +++ b/documentation/Runtime.md @@ -1,69 +1 @@ -[Back to README](../README.md) - -# Wenyan Browser Runtime - -You can now run Wenyan as normal Javscript script right in your html. - -[**Check out the demo**](https://jsfiddle.net/antfu/u532ny49/) - -## Installation - -Add following script in the `` of your html file. - -```html - -``` - -That's all, you are good to go! - -## Usage - -To use wenyan in script, you **HAVE TO** specify `type="application/wenyan"` for the ` -``` - -### Scoped script - -By default, all the variables in wenyan will exposed globally. For the previous example, `甲` is accessible by `window.甲`. If you do not want to messed up your globals, you can specify the `scoped` attr. - -```html - -``` - -### Remote scripts - -You can import remote scripts as you will do for Javascript. - -```html - -``` - -### Outputing Hanzi - -By default, it will convert numbers and bools to hanzi. If you want to output raw numbers, you can specify `outputHanzi="false"` in attr of script tag. - -```html - -``` - -### DOM Hacks - -There are some hacks you can do to access the DOM and browser APIs. This allows wenyan to do some realworld applications. - -```html - -``` +This document is moved to [the wiki page](https://github.com/wenyan-lang/wenyan/wiki/Brower-Runtime) \ No newline at end of file diff --git a/documentation/Standard-Lib.md b/documentation/Standard-Lib.md index 7297fc4d..e39ac22d 100644 --- a/documentation/Standard-Lib.md +++ b/documentation/Standard-Lib.md @@ -1,143 +1 @@ - - -# Standard Library Cheatsheet - -Last updated: Thu, 16 Jan 2020 21:33:41 GMT - - -## Usage - -```wenyan -吾嘗觀「「算經」」之書。方悟「正弦」「餘弦」「圓周率」之義。 -``` - -## [列經](https://github.com/wenyan-lang/wenyan/tree/master/lib/列經.wy) - -| Wenyan | Javascript Equivalent | -|---|---| - -## [易經 - Random](https://github.com/wenyan-lang/wenyan/tree/master/lib/易經.wy) - -| Wenyan | Javascript Equivalent | -|---|---| - -## [曆法 - Calendar](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy) - -> 💬 This library uses your system timezone setting - -| Wenyan | Javascript Equivalent | -|---|---| -| [`今何紀元時`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L9) | `Date.now() / 1000` | -| [`言今之日時`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L14) | `new Date().toString(), in Chinese calendar` | -| [`言今之年月日`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L19) | `new Date().toDateString(), in Chinese calendar` | -| [`言今之時刻`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L24) | `new Date().toTimeString(), in Chinese calendar` | -| [`今年何年號`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L29) | `"西元" for modern dates` | -| [`今年何年`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L34) | `new Date().getFullYear() for modern dates, in Chinese calendar` | -| [`今年何干支`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L40) | `Get index (1 to 60) of this year in the 60-year cycle` | -| [`今年積何年`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L46) | `new Date().getFullYear() + 2697, in Chinese calendar` | -| [`今月何月`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L53) | `new Date().getMonth() + 1, N + 0.5 for leap months, in Chinese calendar` | -| [`今月積何月`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L60) | `Get continuously counting month number of this month` | -| [`今日何日`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L67) | `new Date().getDate(), in Chinese calendar` | -| [`今日何干支`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L74) | `Get index (1 to 60) of today in the 60-day cycle` | -| [`今日積何日`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L80) | `Get continuously counting day number of today` | -| [`今時何時`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L87) | `Get index (1 to 12) of current time in the 12 divisions of day` | -| [`今時何小時`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L94) | `new Date().getHours()` | -| [`今刻何刻`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L101) | `Math.floor(new Date().getMinutes() / 15)` | -| [`今分何分`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L108) | `new Date().getMinutes() % 15` | -| [`今秒何秒`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L113) | `new Date().getSeconds()` | -| [`言彼之日時`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L234) | `new Date(x * 1000).toString(), in Chinese calendar` | -| [`言彼之年月日`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L243) | `new Date(x * 1000).toDateString(), in Chinese calendar` | -| [`言彼之時刻`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L250) | `new Date(x * 1000).toTimeString(), in Chinese calendar` | -| [`彼年何年號`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L257) | `"西元" for modern dates` | -| [`彼年何年`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L262) | `new Date(x * 1000).getFullYear() for modern dates, in Chinese calendar` | -| [`彼年何干支`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L267) | `Get index (1 to 60) in the 60-year cycle` | -| [`彼年積何年`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L273) | `new Date(x * 1000).getFullYear() + 2697, in Chinese calendar` | -| [`彼月何月`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L280) | `new Date(x * 1000).getMonth() + 1, N + 0.5 for leap months, in Chinese calendar` | -| [`彼月積何月`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L291) | `Get continuously counting month number` | -| [`彼日何日`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L296) | `new Date(x * 1000).getDate(), in Chinese calendar` | -| [`彼日何干支`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L302) | `Get index (1 to 60) in the 60-day cycle` | -| [`彼日積何日`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L308) | `Get continuously counting day number` | -| [`彼時何時`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L315) | `Get index (1 to 12) in the 12 divisions of day` | -| [`彼時何小時`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L324) | `new Date(x * 1000).getHours()` | -| [`彼刻何刻`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L332) | `Math.floor(new Date(x * 1000).getMinutes() / 15)` | -| [`彼分何分`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L340) | `new Date(x * 1000).getMinutes() % 15` | -| [`彼秒何秒`](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆法.wy#L348) | `new Date(x * 1000).getSeconds()` | - -## [曆表](https://github.com/wenyan-lang/wenyan/tree/master/lib/曆表.wy) - -| Wenyan | Javascript Equivalent | -|---|---| - -## [算經 - Math](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy) - -| Wenyan | Javascript Equivalent | -|---|---| -| [`圓周率`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L166) | `Math.PI` | -| [`倍圓周率`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L169) | `Math.PI * 2` | -| [`半圓周率`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L172) | `Math.PI / 2` | -| [`四分圓周率`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L175) | `Math.PI / 4` | -| [`自然常數`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L177) | `Math.E` | -| [`歐拉常數`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L179) | `0.5772156649015329` | -| [`黃金分割數`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L181) | `1.618033988749895` | -| [`二之平方根`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L183) | `Math.SQRT2` | -| [`二之對數`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L185) | `Math.LN2` | -| [`十之對數`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L187) | `Math.LN10` | -| [`不可算數乎`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L190) | `Number.isNaN` | -| [`浮點移位`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L392) | `x * Math.pow(2, y), y is integer` | -| [`析浮點數`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L428) | `N/A` | -| [`取底除`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L474) | `{ 商: Math.floor(x / y), 餘: x - y * quo }` | -| [`取整除`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L491) | `{ 商: Math.round(x / y), 餘: x - y * quo }` | -| [`正弦`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L565) | `Math.sin` | -| [`餘弦`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L594) | `Math.cos` | -| [`反正弦`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L637) | `Math.asin` | -| [`反餘弦`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L663) | `Math.acos` | -| [`正切`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L694) | `Math.tan` | -| [`反正切`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L748) | `Math.atan` | -| [`勾股求角`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L781) | `Math.atan2` | -| [`勾股求弦`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L804) | `Math.hypot` | -| [`對數`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L841) | `Math.log` | -| [`指數`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L884) | `Math.exp` | -| [`冪`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L920) | `Math.pow` | -| [`平方根`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L944) | `Math.sqrt` | -| [`絕對`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L1005) | `Math.abs` | -| [`取頂`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L1010) | `Math.ceil` | -| [`取底`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L1015) | `Math.floor` | -| [`取整`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L1030) | `Math.round, but rounded away from zero when the fractional part is exactly 0.5` | -| [`捨餘`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L1044) | `Math.trunc` | -| [`正負`](https://github.com/wenyan-lang/wenyan/tree/master/lib/算經.wy#L1054) | `Math.sign` | - -## [籌經 - Collection Operations](https://github.com/wenyan-lang/wenyan/tree/master/lib/籌經.wy) - -| Wenyan | Javascript Equivalent | -|---|---| -| [`求和`](https://github.com/wenyan-lang/wenyan/tree/master/lib/籌經.wy#L1) | `reduce((a,b)=>a+b)` | - -## [位經 - Bit Manipulation](https://github.com/wenyan-lang/wenyan/tree/master/lib/js/位經.wy) - -| Wenyan | Javascript Equivalent | -|---|---| - -## [畫譜 - Canvas](https://github.com/wenyan-lang/wenyan/tree/master/lib/js/畫譜.wy) - -| Wenyan | Javascript Equivalent | -|---|---| - -## [西曆法](https://github.com/wenyan-lang/wenyan/tree/master/lib/js/西曆法.wy) - -| Wenyan | Javascript Equivalent | -|---|---| - - - - -## Help update this cheatsheet - -This cheatsheet is generated direct from stdlibs. There are still a lot of functions are not listed above. If you would like to hep update this cheatsheet, here is the steps. - -Add comments in the stdlib files (one line above the function/value), the format should look like this: - -```wenyan -注曰「「餘弦。同Javascript之Math.cos也。」」 -``` - -After you fill the comments, commit and open a pull request. Thank you! +This document is moved to [the wiki page](https://github.com/wenyan-lang/wenyan/wiki/Standard-Library-Cheatsheet) \ No newline at end of file diff --git a/documentation/TODO.md b/documentation/TODO.md index e58d6cb1..d19ebc62 100644 --- a/documentation/TODO.md +++ b/documentation/TODO.md @@ -1,13 +1,13 @@ - ~~multiple push to array~~ - ~~syntax highlighting~~ - auto indent / format -- compile to python +- ~~compile to python~~ - compile to c - ~~logical and / or~~ -- for loop with iterator +- ~~for loop with iterator~~ - ~~while loop~~ - ASC edge case near end of program -- strict parse error checking +- ~~strict parse error checking~~ - ~~traditional chinese~~ -- negative numbers +- ~~negative numbers~~ - source mapping \ No newline at end of file diff --git a/documentation/Testing.md b/documentation/Testing.md index 8190e40a..a0fe1d4e 100644 --- a/documentation/Testing.md +++ b/documentation/Testing.md @@ -1,26 +1 @@ -[Back to README](../README.md) - -## Testing - -This project uses [Jest](https://jestjs.io/) for unit testing and snapshot testing. - -You can run all the tests by - -```bash -npm test -``` - -### Snapshot Testing - -There are some articles about snapshot testing: - - - https://jest-bot.github.io/jest/docs/snapshot-testing.html - - https://scotch.io/tutorials/writing-snapshot-tests-for-react-components-with-jest - -This prevents you from accidentally changes the things that affects the output. - -**If you made changes by purpose, you may need to update the snapshoot by** - -```bash -npm run test:update -``` \ No newline at end of file +This document is moved to [the wiki page](https://github.com/wenyan-lang/wenyan/wiki/Testing) \ No newline at end of file diff --git a/documentation/Try-Catch.md b/documentation/Try-Catch.md index c851ff01..320412ba 100644 --- a/documentation/Try-Catch.md +++ b/documentation/Try-Catch.md @@ -1,77 +1 @@ -[Back to README](../README.md) - -# Try-Catch - -``` -姑妄行此。 - 嗚呼。「「滅頂」」之禍。 - -如事不諧。豈「「ReferenceError」」之禍歟。 - 吾有一言。曰「「本無此物。奈何用之」」。書之。 - -豈「「SyntaxError」」之禍歟。 - 吾有一言。曰「「不合文法。不通之甚」」。書之。 - -豈「「TypeError」」之禍歟。 - 吾有一言。曰「「物各其類。豈可混同」」。書之。 - -豈「「滅頂」」之禍歟。 - 吾有一言。曰「「嗚呼哀哉。伏维尚飨」」。書之。 - -不知何禍歟。名之曰「奇禍」。 - 吾有一言。曰「「人坐家中。禍從天降」」。書之。 - -乃作罷。 - -``` - -Which is roughly equivalent to this JavaScript: - -```JavaScript -try { - var e = new Error(); e.name = "滅頂"; throw e; -} catch(e) { - if (e.name == "ReferenceError") {console.log("本無此物。奈何用之")} - else if (e.name == "SyntaxError") {console.log("不合文法。不通之甚")} - else if (e.name == "TypeError") {console.log("物各其類。豈可混同")} - else if (e.name == "滅頂") {console.log("嗚呼哀哉。伏维尚飨")} - else {var err = e; console.log("人坐家中。禍從天降")} -} - -``` - -If you do not need to catch the errors, you can do: - -``` -姑妄行此。 - 嗚呼。「「無足輕重」」之禍。 -如事不諧乃作罷。 -``` - -Which roughly equals to: - -```JavaScript -try{ - var e = new Error(); e.name = "無足輕重"; throw e; -}catch(_){} -``` - -You can also do this to catch any error: - -``` -姑妄行此。 - 嗚呼。「「事不關心」」之禍。 -如事不諧。不知何禍歟。書之。乃作罷。 -``` - -Which roughly equals to: - -```JavaScript -try{ - var e = new Error(); e.name = "事不關心"; throw e; -}catch(e){ - console.log(e); -} -``` - -You can see details about the usage in `./examples/try.wy`. \ No newline at end of file +This document is moved to [the wiki page](https://github.com/wenyan-lang/wenyan/wiki/Error-Handling) \ No newline at end of file diff --git a/documentation/syntax.txt b/documentation/syntax.txt deleted file mode 100644 index 28e2cc72..00000000 --- a/documentation/syntax.txt +++ /dev/null @@ -1,111 +0,0 @@ -// Work in progress - -program := statement* -statement := declare_statement - | define_statement - | assign_statement - | if_statement - | for_statement - | break - | math_statement - | array_statement - | object_statement - | import_statement - | function_statement - | print_statement - | clean_statement - | return_statement - | comment_statement - | mention_statment - -// Variables -character := Unicode - -identifier := 「character+」 -string_literal := 「「character*」」 - -num := int_num | float_num -int_num := (int_num_keywords)+ -int_num_keywords := 零|一|二|三|四|五|六|七|八|九|十|百|千|萬|億|兆|京|垓|秭|穣|溝|澗|正|載|極 -float_num := int_num 又 (int_num float_num_keywords)+ -float_num_keywords := 分|釐|毫|絲|忽|微|塵|埃|渺|漠 -type := 數|列|言|爻|術 -data := num|string_literal|bool_value|identifier - -bool_value := 陰|陽 -assign := 曰 -declare_statement := (吾有|今有) int_num type (assign data)* - -reference_multi_statement := 名之(assign identifier)+ -reference_single_statement := 名之(assign identifier) -init_define_statement := 有 type data [reference_single_statement] -define_statement := (declare_statement reference_multi_statement)|init_define_statement - -assign_statement := 昔之 identifier (之 int_num)? 者 今 ((identifier (之 int_num)?)|其) 是矣 - -// Control -break := 乃止 - -if := 若 -else := 若非 -if_end := 也 -logic_if_op := 等於|不等於|不大於|不小於|大於|小於 -unary_if_expression := num|identifier|(identifier之(長|string_literal))|其 -binary_if_expression := unary_if_expression logic_if_op unary_if_expression -if_expression := unary_if_expression|binary_if_expression -if_statement := if if_expression statement else statement if_end - -for := 凡 -for_in := 中之 -for_end := 云云|也 - -for_c_statement := 為是 int_num 遍 statement* for_end -while_true_statement := 恆為是 statement* for_end -for_arr_statement := for identifier for_in identifier statement* for_end -for_statement := for_c_statement - | whiletrue_statement - | for_arr_statement - -// Math -arith_binary_op := 加|減|乘|除 -logic_binary_op := 中有陽乎|中無陰乎 -post_mod_math_op := 所餘幾何 -preposition := 以|於 -unary_op := 變 -arith_math_statement := arith_binary_op num|identifier|其 preposition num|identifier -mod_math_statement := 除 num|identifier|其 preposition num|identifier post_mod_math_op -logic_math_statement := 夫 identifier identifier logic_binary_op -math_statement := arith_math_statement|logic_math_statement - -// Array -array_func_statement := 夫 identifier 之 其餘|長|string_literal|int_num -array_cat_statement := 銜 identifier|其 (以 identifier)+ -array_push_statement := 充 identifier|其 (以 num|identifier)+ -array_statement := array_func_statement|array_cat_statement|array_fill_statement - -// Object -object_define_statement := 其物如是 (物之 string_literal 者 type 曰 data)+ 是謂 identifier 之物也 -object_statement := 吾有 int_num 物 reference_single_statement [object_define_statement] - -// Import -import_statement := 吾嘗觀 string_literal 之書 方悟 identifier+ 之義 - -// Push -mention_statement := (夫 identifier(之 int_num|長)? - -// Function -function_start := 吾有 int_num 術 reference_single_statement 欲行是術 -function_arg := 必先得 num type [assign identifier] 是術曰|乃行是術曰 -function_end := 是謂 identifier 之術也 -function_define_statement := function_start function_arg statement+ function_end -function_plain_call := 施 identifier|其 (於 identifier)* -function_nested_call := (取 int_num 以施 identifier)+ reference_single_statement -function_call_statement := function_plain_call|function_nested_call -function_statement := function_define_statement|function_call_statement - -// Misc -print_statement := 書之 -clean_statement := 噫 -return_statement := 乃得 data|乃歸空無|乃得矣 -comment := 注曰|疏曰|批曰 -comment_statement := comment string_literal \ No newline at end of file diff --git "a/lib/js/\350\245\277\346\233\206\346\263\225.wy" "b/lib/js/\350\245\277\346\233\206\346\263\225.wy" index 87414642..f84fdd7c 100644 --- "a/lib/js/\350\245\277\346\233\206\346\263\225.wy" +++ "b/lib/js/\350\245\277\346\233\206\346\263\225.wy" @@ -1,4 +1,3 @@ - 今有一術。名之曰「紀元時」。是術曰。 施「(()=>new Date().getTime()/1000)」。乃得矣。 是謂「紀元時」之術也。 diff --git "a/lib/\345\210\227\347\266\223.wy" "b/lib/\345\210\227\347\266\223.wy" index e564c9ee..a9b1622a 100644 --- "a/lib/\345\210\227\347\266\223.wy" +++ "b/lib/\345\210\227\347\266\223.wy" @@ -7,7 +7,7 @@ 或云「「併「甲」於「乙」以「丙」者」」 蓋謂「「施「左併」於「丙」於「乙」於「甲」」」 - +注曰「「遍施。同Javascript之Array.forEach也。」」 今有一術。名之曰「遍施」。欲行是術。必先得一術。曰「甲」。一列。曰「乙」。乃行是術曰。 吾有一列。名之曰「丙」。 凡「乙」中之「丁」。 @@ -15,7 +15,7 @@ 乃得「丙」。 是謂「遍施」之術也。 - +注曰「「篩剔。同Javascript之Array.filter也。」」 今有一術。名之曰「篩剔」。欲行是術。必先得一術。曰「甲」。一列。曰「乙」。乃行是術曰。 吾有一列。名之曰「丙」。 凡「乙」中之「丁」。 @@ -25,7 +25,6 @@ 乃得「丙」。 是謂「篩剔」之術也。 - 今有一術。名之曰「左併」。欲行是術。必先得一術。曰「甲」。一元。曰「乙」。一列。曰「丙」。乃行是術曰。 吾有一元曰「乙」。名之曰「丁」。 凡「丙」中之「戊」。 @@ -46,7 +45,7 @@ 乃得「丁」。 是謂「右併」之術也。 - +注曰「「排序。同Javascript之Array.sort也。」」 今有一術。名之曰「排序」。欲行是術。必先得一術。曰「甲」。一列。曰「乙」。乃行是術曰。 若「乙」之長不大於一者。乃得「乙」也。 @@ -72,7 +71,7 @@ 是謂「排序」之術也。 - +注曰「「倒序。同Javascript之Array.reverse也。」」 今有一術。名之曰「倒序」。欲行是術。必先得一列。曰「甲」。乃行是術曰。 吾有一列。名之曰「乙」。 夫「甲」之長。名之曰「戊」。 @@ -82,7 +81,7 @@ 乃得「乙」。 是謂「倒序」之術也。 - +注曰「「擷取。同Javascript之Array.slice也。」」 今有一術。名之曰「擷取」。欲行是術。必先得一列。曰「甲」。二數。曰「乙」曰「丙」。乃行是術曰。 吾有一列。名之曰「丁」。 吾有一數。曰「乙」。名之曰「戊」。 diff --git a/package-lock.json b/package-lock.json index fd94067b..d3760c8c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1342,6 +1342,15 @@ "type-fest": "^0.8.1" } }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", @@ -1357,6 +1366,12 @@ "color-convert": "^1.9.0" } }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, "any-observable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", @@ -1657,6 +1672,15 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, + "autolinker": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-0.28.1.tgz", + "integrity": "sha1-BlK0kYgYefB3XazgzcoyM5QqTkc=", + "dev": true, + "requires": { + "gulp-header": "^1.7.1" + } + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -2624,6 +2648,12 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, + "coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", + "dev": true + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -2706,6 +2736,15 @@ "typedarray": "^0.0.6" } }, + "concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + } + }, "configstore": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", @@ -2737,6 +2776,12 @@ } } }, + "consola": { + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.11.3.tgz", + "integrity": "sha512-aoW0YIIAmeftGR8GSpw6CGQluNdkWMWh3yEFjH/hmynTYnMtibXszii3lxCXmk8YxJtI3FAK5aTiquA5VH68Gw==", + "dev": true + }, "console-browserify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", @@ -3154,6 +3199,12 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, + "diacritics-map": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/diacritics-map/-/diacritics-map-0.1.0.tgz", + "integrity": "sha1-bfwP+dAQAKLt8oZTccrDFulJd68=", + "dev": true + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -3815,6 +3866,57 @@ } } }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "^2.1.0" + }, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -5147,12 +5249,47 @@ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, + "gray-matter": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-2.1.1.tgz", + "integrity": "sha1-MELZrewqHe1qdwep7SOA+KF6Qw4=", + "dev": true, + "requires": { + "ansi-red": "^0.1.1", + "coffee-script": "^1.12.4", + "extend-shallow": "^2.0.1", + "js-yaml": "^3.8.1", + "toml": "^2.3.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, "growly": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", "dev": true }, + "gulp-header": { + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", + "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", + "dev": true, + "requires": { + "concat-with-sourcemaps": "*", + "lodash.template": "^4.4.0", + "through2": "^2.0.0" + } + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -5726,6 +5863,12 @@ "binary-extensions": "^1.0.0" } }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, "is-callable": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", @@ -7052,6 +7195,15 @@ "package-json": "^4.0.0" } }, + "lazy-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", + "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", + "dev": true, + "requires": { + "set-getter": "^0.1.0" + } + }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", @@ -7257,6 +7409,47 @@ } } }, + "list-item": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/list-item/-/list-item-1.1.1.tgz", + "integrity": "sha1-DGXQDih8tmPMs8s4Sad+iewmilY=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "extend-shallow": "^2.0.1", + "is-number": "^2.1.0", + "repeat-string": "^1.5.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "listr": { "version": "0.14.3", "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", @@ -7530,6 +7723,12 @@ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -7548,6 +7747,25 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, "log-symbols": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", @@ -7765,6 +7983,38 @@ "object-visit": "^1.0.0" } }, + "markdown-link": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/markdown-link/-/markdown-link-0.1.1.tgz", + "integrity": "sha1-MsXGUZmmRXMWMi0eQinRNAfIx88=", + "dev": true + }, + "markdown-toc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/markdown-toc/-/markdown-toc-1.2.0.tgz", + "integrity": "sha512-eOsq7EGd3asV0oBfmyqngeEIhrbkc7XVP63OwcJBIhH2EpG2PzFcbZdhy1jutXSlRBBVMNXHvMtSr5LAxSUvUg==", + "dev": true, + "requires": { + "concat-stream": "^1.5.2", + "diacritics-map": "^0.1.0", + "gray-matter": "^2.1.0", + "lazy-cache": "^2.0.2", + "list-item": "^1.1.1", + "markdown-link": "^0.1.1", + "minimist": "^1.2.0", + "mixin-deep": "^1.1.3", + "object.pick": "^1.2.0", + "remarkable": "^1.7.1", + "repeat-string": "^1.6.1", + "strip-color": "^0.1.0" + } + }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -9041,6 +9291,25 @@ "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", "dev": true }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -9411,6 +9680,16 @@ "rc": "^1.0.1" } }, + "remarkable": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/remarkable/-/remarkable-1.7.4.tgz", + "integrity": "sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg==", + "dev": true, + "requires": { + "argparse": "^1.0.10", + "autolinker": "~0.28.0" + } + }, "remove-strict-webpack-plugin": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/remove-strict-webpack-plugin/-/remove-strict-webpack-plugin-0.1.2.tgz", @@ -9867,6 +10146,15 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "set-getter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", + "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", + "dev": true, + "requires": { + "to-object-path": "^0.3.0" + } + }, "set-tz": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/set-tz/-/set-tz-0.2.0.tgz", @@ -10435,6 +10723,12 @@ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, + "strip-color": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz", + "integrity": "sha1-EG9l09PmotlAHKwOsM6LinArT3s=", + "dev": true + }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -10747,6 +11041,12 @@ "is-number": "^7.0.0" } }, + "toml": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.6.tgz", + "integrity": "sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==", + "dev": true + }, "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", diff --git a/package.json b/package.json index c05f130e..d34b3468 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "build:dev": "npm run clear && npm run build:type && webpack --mode development", "build:site": "webpack --mode development --config webpack.site.config.js", "build:docs": "node ./tools/make_examples_readme.js && node ./tools/make_stdlib_cheatsheet.js", + "build:wiki": "node ./tools/wiki/update.js", "build:type": "tsc --emitDeclarationOnly --declaration --declarationDir ./typings && move-cli ./typings/package.d.ts ./typings/package.json.d.ts", "dev:site": "webpack --mode development --config webpack.site.config.js --watch", "dev": "npm run clear && npm run build:type && webpack --mode development --watch", @@ -29,6 +30,7 @@ "clear": "rimraf dist typings", "publish": "bump --commit && node ./tools/publish.js", "publish:ci": "node ./tools/publish.js", + "update:wiki": "node ./tools/wiki/update.js --push", "release": "bump --commit --tag && git push --follow-tags", "test": "jest", "test:update": "jest --updateSnapshot", @@ -60,6 +62,7 @@ "@typescript-eslint/eslint-plugin": "^2.16.0", "@typescript-eslint/parser": "^2.16.0", "commander": "^4.0.1", + "consola": "^2.11.3", "dts-bundle": "^0.7.3", "eslint": "^6.7.2", "eslint-config-prettier": "^6.7.0", @@ -72,6 +75,7 @@ "husky": "^3.1.0", "jest": "^24.9.0", "lint-staged": "^9.5.0", + "markdown-toc": "^1.2.0", "move-cli": "^1.2.1", "nodemon": "^2.0.2", "prettier": "^1.19.1", diff --git a/src/parser.ts b/src/parser.ts index fa5b23d5..6033c8c4 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -20,7 +20,7 @@ import { NUMBER_KEYWORDS, KEYWORDS } from "./keywords"; import { STDLIB } from "./stdlib"; import { typecheck, printSignature } from "./typecheck"; import transpilers from "./transpilers"; -import { match } from "./utils"; +import { match, defaultAssert, isRoman } from "./utils"; import { evalCompiled, isLangSupportedForEval } from "./execute"; const defaultTrustedHosts = [ @@ -29,12 +29,7 @@ const defaultTrustedHosts = [ const IGNORE_SYMBOLS = "。、\n\r\t "; -function wy2tokens( - txt: string, - assert = (msg, pos, b) => { - if (!b) console.log(`ERROR@${pos}: ${msg}`); - } -) { +function wy2tokens(txt: string, assert = defaultAssert()) { var tokens: Token[] = []; var tok = ""; var idt = false; @@ -177,9 +172,6 @@ function tokenRomanize(tokens: Token[], system: RomanizeSystem) { } return true; } - function isRoman(x: string) { - return x.replace(/[ -~]/g, "").length == 0; - } for (const token of tokens) { if (token[0] == "iden" && !isRoman(token[1])) { @@ -210,12 +202,7 @@ function defaultErrorCallback(e: any) { process.exit(); } -function tokens2asc( - tokens: Token[], - assert = (msg, pos, b) => { - if (!b) console.log(`ERROR@${pos}: ${msg}`); - } -) { +function tokens2asc(tokens: Token[], assert = defaultAssert()) { var asc: ASCNode[] = []; var i = 0; while (i < tokens.length) { diff --git a/src/typecheck.ts b/src/typecheck.ts index 4b17a335..d29a0064 100644 --- a/src/typecheck.ts +++ b/src/typecheck.ts @@ -1,4 +1,14 @@ -function printType(t, n = 0, d = 0) { +import { + ASCNode, + isASCNodeOperator, + Token, + IdenType, + TypeSignature, + TypeScope +} from "./types"; +import { defaultAssert, isRoman } from "./utils"; + +function printType(t: IdenType, n = 0, d = 0): string { if (d > 100) { return "..."; } @@ -38,7 +48,7 @@ function printType(t, n = 0, d = 0) { return t.type; } -function printSignature(signature) { +function printSignature(signature: TypeSignature) { let s = ""; signature = signature.filter(x => Object.keys(x[1]).length); signature.sort((x, y) => x[0][0] - y[0][0]); @@ -69,23 +79,18 @@ function printSignature(signature) { return s; } -function typecheck( - asc, - assert = (msg, pos, b) => { - if (!b) console.log(`ERROR@${pos}: ${msg}`); - } -) { - let imported = []; - let strayvar = []; - let scope = [{}]; - let scopestarts = [{ pos: 0, op: "global" }]; - let signature = []; - let funstack = []; - let funretcnt = []; +function typecheck(asc: ASCNode[], assert = defaultAssert()) { + let imported: string[] = []; + let strayvar: IdenType[] = []; + let scope: TypeScope[] = [{}]; + let scopestarts: ASCNode[] = [{ pos: 0, op: "global" }]; + let signature: TypeSignature = []; + let funstack: string[] = []; + let funretcnt: number[] = []; let prevobj = ""; let took = 0; - function checkscopei(i, name) { + function checkscopei(i: number, name: string) { if (scope[i][name]) { return scope[i][name]; } @@ -105,11 +110,7 @@ function typecheck( } } - function isRoman(x) { - return x.replace(/[ -~]/g, "").length == 0; - } - - function checkscopeall(name) { + function checkscopeall(name: string) { for (let i = scope.length - 1; i >= 0; i--) { let b = checkscopei(i, name); if (b) { @@ -126,7 +127,8 @@ function typecheck( return undefined; } - function checkscopethis(name, pos) { + + function checkscopethis(name: string, pos: number) { assert( "Scope stack depleted, possibly due to extraneous end-block statement.", pos, @@ -135,14 +137,14 @@ function typecheck( return checkscopei(scope.length - 1, name); } - function inittype(type) { + function inittype(type: IdenType["type"]): IdenType { if (type == "any") { return { type: "any" }; } if (type == "nil") { return { type: "nil" }; } - let x: any = { type: type }; + let x: IdenType = { type: type }; if (type == "fun") { x.in = { type: "any" }; x.out = { type: "any" }; @@ -154,7 +156,7 @@ function typecheck( return x; } - function gettype(tok) { + function gettype(tok: Token): IdenType { if (tok[0] == "lit") { return inittype("str"); } else if (tok[0] == "bool") { @@ -171,38 +173,38 @@ function typecheck( assert(`[Type] Expecting value, found '${tok[0]}'`, tok[2], false); } - function objfield(t, x) { + function objfield(t: IdenType, x: string) { if (t.isarg) { t.fields[x] = inittype("any"); } return t.fields[x]; } - function scopepush(tok) { + function scopepush(node: ASCNode) { scope.push({}); - scopestarts.push(tok); + scopestarts.push(node); } - function scopepop(tok, ...acceptScopeStartOps) { + function scopepop(node: ASCNode, ...acceptScopeStartOps) { let ss = scopestarts.pop(); let s = scope.pop(); assert( - `[Type] Unexpected '${tok.op}' in '${ss.op}' block`, - tok.pos, + `[Type] Unexpected '${node.op}' in '${ss.op}' block`, + node.pos, acceptScopeStartOps.indexOf(ss.op) >= 0 ); - signature.push([[ss.pos, tok.pos, scope.length], s]); + signature.push([[ss.pos, node.pos, scope.length], s]); } function logscope() { console.dir(scope, { depth: null, maxArrayLength: null }); } - function typeeq(a, b) { - if (a == "any" || a.type == "any") { + function typeEqual(a: IdenType, b: IdenType) { + if (a.type == "any") { return b; } - if (b == "any" || b.type == "any") { + if (b.type == "any") { return a; } if (a.type != b.type) { @@ -210,13 +212,13 @@ function typecheck( } if (a.type == b.type) { if (a.type == "arr") { - if (typeeq(a.element, b.element)) { + if (typeEqual(a.element, b.element)) { return a; } - if (a.element == "any" && b.element) { + if (b.element) { return b; } - if (a.element && b.element == "any") { + if (a.element) { return a; } } @@ -229,7 +231,7 @@ function typecheck( [x, y] = [a, b]; } for (var k in x.fields) { - if (!typeeq(x.fields[k], y.fields[k])) { + if (!typeEqual(x.fields[k], y.fields[k])) { return false; } } @@ -240,7 +242,7 @@ function typecheck( return false; } - function typeassert(who, want, got, pos) { + function typeassert(who: string, want: IdenType[], got: Token, pos: number) { let t = gettype(got); assert(`[Type] Undeclared variable '${got[1]}'`, pos, t); @@ -248,7 +250,7 @@ function typecheck( let ut = []; for (let i = 0; i < want.length; i++) { ut.push("(" + printType(want[i]) + ")"); - if (typeeq(want[i], t)) { + if (typeEqual(want[i], t)) { ok = true; break; } @@ -364,13 +366,11 @@ function typecheck( // console.log(ptr.out.type,ty.type) typeassert(`Function return`, [ptr.out], a.value, a.pos); - ptr.out = typeeq(ptr.out, gettype(a.value)); + ptr.out = typeEqual(ptr.out, gettype(a.value)); } } - } else if (a.op.startsWith("op")) { + } else if (isASCNodeOperator(a)) { let op = a.op.slice(2); - let tl = gettype(a.lhs); - let tr = gettype(a.rhs); let otype; if (op == "+") { @@ -386,7 +386,7 @@ function typecheck( a.rhs, a.pos ); - otype = Object.assign({}, typeeq(gettype(a.lhs), gettype(a.rhs))); + otype = Object.assign({}, typeEqual(gettype(a.lhs), gettype(a.rhs))); } else if (["-", "*", "/", "%"].includes(op)) { typeassert(`${op} operator`, [inittype("num")], a.lhs, a.pos); typeassert(`${op} operator`, [inittype("num")], a.rhs, a.pos); @@ -434,7 +434,7 @@ function typecheck( args[j] )}`, a.pos, - typeeq(args[j], ta) + typeEqual(args[j], ta) ); } else { typeassert(`Function argument`, [ta], args[j], a.pos); @@ -522,7 +522,7 @@ function typecheck( let typ = gettype(a.containers[0]); let olt = typ; for (let j = 1; j < a.containers.length; j++) { - typ = typeeq(typ, gettype(a.containers[j])); + typ = typeEqual(typ, gettype(a.containers[j])); if (!typ) { typeassert(`Concat`, [olt], a.containers[j], a.pos); } @@ -539,7 +539,7 @@ function typecheck( let olt = typ; for (let j = 0; j < a.values.length; j++) { // console.log(a.values[j],gettype(a.values[j])) - typ = typeeq(typ, gettype(a.values[j])); + typ = typeEqual(typ, gettype(a.values[j])); if (!typ) { typeassert(`Push RHS`, [olt], a.values[j], a.pos); } @@ -644,7 +644,7 @@ function typecheck( assert(`[Type] Reassignment LHS is not declared`, a.pos, tlv); assert(`[Type] Reassignment RHS is not declared`, a.pos, trv); // console.log(a,tlv,trv,tl,tr) - let typ = typeeq(tlv, trv); + let typ = typeEqual(tlv, trv); // console.log(a.lhs,a.rhs,gettype(a.rhs),tl,tr,tlv,trv) assert( `[Type] Reassignment type mismatch: LHS:${printType( diff --git a/src/types.ts b/src/types.ts index df8bfe6a..db24fbe0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -83,7 +83,7 @@ export type TokenType = | "type" | "throw"; -export type Token = [TokenType, string | undefined, number]; +export type Token = [TokenType, string | undefined, number] | ["ans"]; export interface ASCNodeCommon { pos: number; @@ -97,12 +97,12 @@ export interface ASCNodeOperator { export interface ASCNodeReturn { op: "return"; - value?: Token | ["ans"]; + value?: Token; } export interface ASCNodeIf { op: "if"; - test: (Token | ["ans"])[]; + test: Token[]; elseif?: boolean; not?: boolean; } @@ -206,6 +206,14 @@ export interface ASCNodePropertry { value: Token; } +export interface ASCNodeGlobal { + op: "global"; +} + +export interface ASCNodeEOF { + op: "EOF"; +} + export interface ASCNodeSimple { op: | "break" @@ -246,4 +254,26 @@ export type ASCNode = ASCNodeCommon & | ASCNodeSubscript | ASCNodeVariable | ASCNodePropertry + | ASCNodeGlobal + | ASCNodeEOF ); + +export function isASCNodeOperator( + node: ASCNode +): node is ASCNodeCommon & ASCNodeOperator { + return node.op.startsWith("op"); +} + +export interface IdenType { + type: "any" | "nil" | "fun" | "obj" | "arr" | "str" | "bol" | "num" | string; + name?: string; + isarg?: boolean; + in?: IdenType; + out?: IdenType; + element?: IdenType; + fields?: {}; +} + +export type TypeScope = Record; + +export type TypeSignature = [[number, number, number], TypeScope][]; diff --git a/src/utils.ts b/src/utils.ts index 8e96ddc6..7b807f33 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -8,3 +8,17 @@ export function match(src: string, startAt: number, target: string) { } return true; } + +export const defaultAssertLogger: (...messages: any[]) => void = console.log; + +export const defaultAssert = (logger = defaultAssertLogger) => ( + msg: string, + pos: number, + b: any +) => { + if (!b) logger(`ERROR@${pos}: ${msg}`); +}; + +export function isRoman(x: string) { + return x.replace(/[ -~]/g, "").length == 0; +} diff --git a/static/ide.html b/static/ide.html index 6855914c..ce910cdb 100644 --- a/static/ide.html +++ b/static/ide.html @@ -154,7 +154,8 @@ - + + diff --git a/static/index.html b/static/index.html index 5ff11f4f..08c50a17 100644 --- a/static/index.html +++ b/static/index.html @@ -65,10 +65,11 @@

Compilation

Get

- GITHUB + WIKI + GITHUB ONLINE EDITOR LANGUAGE SPEC - REFERENCE + REFERENCE
diff --git a/tools/make_stdlib_cheatsheet.js b/tools/wiki/stdlib_cheatsheet.js similarity index 83% rename from tools/make_stdlib_cheatsheet.js rename to tools/wiki/stdlib_cheatsheet.js index 8010f087..e2e0a64f 100644 --- a/tools/make_stdlib_cheatsheet.js +++ b/tools/wiki/stdlib_cheatsheet.js @@ -1,10 +1,15 @@ const fs = require("fs-extra"); const path = require("path"); +const consola = require("consola"); +const toc = require("markdown-toc"); const DocRegex = /注曰「「(.+?)。同Javascript之(.+?)也。」」/g; const GithubRoot = "https://github.com/wenyan-lang/wenyan/tree/master"; const Info = { + 列經: { + name: "Array" + }, 易經: { name: "Random" }, @@ -12,6 +17,9 @@ const Info = { name: "Calendar", description: "> 💬 This library uses your system timezone setting" }, + 曆表: { + private: true + }, 算經: { name: "Math" }, @@ -23,12 +31,16 @@ const Info = { }, 畫譜: { name: "Canvas" + }, + 格物: { + name: "Object" + }, + 西曆法: { + private: true } }; const HEAD = ` - -# Standard Library Cheatsheet `; const BODY = ` @@ -81,6 +93,9 @@ function readFile(filepath, relativePath) { const lines = getLineIndexes(text); const results = []; const { name } = path.parse(filepath); + + if (Info[name] && Info[name].private) return ""; + let match; while ((match = DocRegex.exec(text))) { @@ -119,7 +134,7 @@ function readFile(filepath, relativePath) { return markdown + "\n"; } -function update(srcDir, outputFile) { +function updateStdlibCheatsheet(srcDir, outputFile) { let markdown = HEAD + "\n"; markdown += `Last updated: ${new Date().toGMTString()}\n\n`; @@ -130,26 +145,26 @@ function update(srcDir, outputFile) { ...fs.readdirSync(path.join(srcDir, "js")).map(i => "js/" + i) ]; + let libs = ""; for (const file of files) { if (file.endsWith(".wy")) { - markdown += readFile(path.join(srcDir, file), file); + libs += readFile(path.join(srcDir, file), file); } } + markdown += "## Table of Contents\n"; + + markdown += toc(libs).content; + + markdown += "\n\n"; + + markdown += libs; + markdown += "\n" + TAIL; fs.writeFileSync(outputFile, markdown, "utf-8"); - console.log("Standard Library Cheatsheet updated."); + consola.success("Standard Library Cheatsheet updated"); } -module.exports = { - update -}; - -if (require.main === module) { - update( - path.resolve(__dirname, "../lib"), - path.resolve(__dirname, "../documentation/Standard-Lib.md") - ); -} +module.exports = updateStdlibCheatsheet; diff --git a/tools/wiki/update.js b/tools/wiki/update.js new file mode 100644 index 00000000..fcf39194 --- /dev/null +++ b/tools/wiki/update.js @@ -0,0 +1,34 @@ +const exec = require("child_process").execSync; +const fs = require("fs-extra"); +const path = require("path"); +const consola = require("consola"); +const updateStdlibCheatsheet = require("./stdlib_cheatsheet"); + +const repo = path.resolve(__dirname, "repo"); + +function ensureRepo(url, dir) { + if (fs.existsSync(path.join(dir, ".git"))) { + exec(`git -C "${dir}" pull -f`, { stdio: "inherit" }); + exec(`git -C "${dir}" checkout .`, { stdio: "inherit" }); + } else { + exec(`git clone ${url} "${dir}"`, { stdio: "inherit" }); + } +} + +function pushChanges(dir, msg) { + exec(`git -C "${dir}" add .`, { stdio: "inherit" }); + exec(`git -C "${dir}" commit -m "${msg}"`, { stdio: "inherit" }); + exec(`git -C "${dir}" push`, { stdio: "inherit" }); +} + +ensureRepo("https://github.com/wenyan-lang/wenyan.wiki.git", repo); + +updateStdlibCheatsheet( + path.resolve(__dirname, "..", "..", "lib"), + path.resolve(repo, "Standard-Library-Cheatsheet.md") +); + +if (process.argv.includes("--push")) { + pushChanges(repo, "Update Wiki"); + consola.success("Changes updated to Wiki"); +}