Skip to content

Commit

Permalink
Merge pull request #417 from antfu/docs/readme
Browse files Browse the repository at this point in the history
docs: update documents
  • Loading branch information
LingDong- authored Dec 28, 2019
2 parents 2392375 + 4986ebe commit fa899d1
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 5 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ You can now translate JavaScript to wenyan-lang using the [wenyanizer](https://g

### Advance Usage

[API Specification](./documentation/API.md)
[Compiler API Specification](./documentation/Compiler-API.md)

## Syntax Cheatsheet

Expand Down Expand Up @@ -197,11 +197,16 @@ Arrays are 1-indexed.
|`注曰。「「文言備矣」」。` | `/*文言備矣*/` |
|`疏曰。「「居第一之位故稱初。以其陽爻故稱九」」。` | `/*居第一之位故稱初。以其陽爻故稱九*/` |

### Advance Features

- [Try...Catch](./documentation/Try-Catch.md)
- [Nested Function Calls](./documentation/Nested-Function-Calls.md)
- [Importing and Standard Library](./documentation/Importing.md)

## Renderer

```bash
wenyan examples/turing.wy --render 圖靈機 --output .
wenyan examples/turing.wy --render --title 圖靈機
```

Render a wenyan script into an image that resembles pages from historical printed books.
Expand Down
4 changes: 2 additions & 2 deletions documentation/API.md → documentation/Compiler-API.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# API Specification

[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.

Expand Down
117 changes: 117 additions & 0 deletions documentation/Importing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
[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!
80 changes: 80 additions & 0 deletions documentation/Nested-Function-Calls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
[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.
10 changes: 9 additions & 1 deletion documentation/Testing.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
[Back to README](../README.md)

## Testing

This project uses [Mocha](https://mochajs.org/) and [Chai](https://www.chaijs.com/) for unit testing and snapshot testing.

You can run all the tests by
You will need to build first

```bash
npm run build
```

Then you can run all the tests by

```bash
npm test
Expand Down
77 changes: 77 additions & 0 deletions documentation/Try-Catch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
[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`.

0 comments on commit fa899d1

Please sign in to comment.