Repository: syuilo/aiscript
Pull request #234 (2023-02-11 17:43:43)

update documents: old syntax(<1.12.0)
<!-- ℹ お読みください
PRありがとうございます！ PRを作成する前に、以下をご確認ください:
- 可能であればタイトルに、以下で示すようなPRの種類が分かるキーワードをプリフィクスしてください。
  - fix / refactor / feat / enhance / perf / chore
  - また、PRの粒度が適切であることを確認してください。ひとつのPRに複数の種類の変更や関心を含めることは避けてください。
- このPRによって解決されるIssueがある場合は、そのIssueへの参照を本文内に含めてください。
- CHANGELOG.mdに変更点を追記してください。リファクタリングなど、利用者に影響を与えない変更についてはこの限りではありません。
- この変更により新たに作成、もしくは更新すべきドキュメントがないか確認してください。
- 機能追加やバグ修正をした場合は、可能であればテストケースを追加してください。
- テスト、Lintが通っていることを予め確認してください。
  - `npm run test`、`npm run lint`でぞれぞれ実施可能です
- `npm run api`を実行してAPIレポートを更新し、差分がある場合はコミットしてください。
ご協力ありがとうございます🤗
-->
<!-- ℹ README
Thank you for your PR! Before creating a PR, please check the following:
- If possible, prefix the title with a keyword that identifies the type of this PR, as shown below.
  - fix / refactor / feat / enhance / perf / chore
  - Also, make sure that the granularity of this PR is appropriate. Please do not include more than one type of change or interest in a single PR.
- If there is an Issue which will be resolved by this PR, please include a reference to the Issue in the text.
- Please add the summary of the changes to CHANGELOG.md. However, this is not necessary for changes that do not affect the users, such as refactoring.
- Check if there are any documents that need to be created or updated due to this change.
- If you have added a feature or fixed a bug, please add a test case if possible.
- Please make sure that tests and Lint are passed in advance.
  - You can run it with `npm run test` and `npm run lint`.
- Run `npm run api` to update the API report and commit it if there are any diffs.
Thanks for your cooperation 🤗
-->

# What
<!-- このPRで何をしたのか？ どう変わるのか？ -->
<!-- What did you do with this PR? How will it change things? -->
ドキュメントで0.12.0以前の構文になっている所を修正

# Why
<!-- なぜそうするのか？ どういう意図なのか？ 何が困っているのか？ -->
<!-- Why do you do it? What are your intentions? What is the problem? -->

# Additional info (optional)
<!-- テスト観点など -->
<!-- Test perspective, etc -->


codecov[bot]: # [Codecov](https://codecov.io/gh/syuilo/aiscript/pull/234?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=syuilo) Report
Base: **86.75**% // Head: **86.75**% // No change to project coverage :thumbsup:
> Coverage data is based on head [(`4cb3d6f`)](https://codecov.io/gh/syuilo/aiscript/pull/234?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=syuilo) compared to base [(`b449b42`)](https://codecov.io/gh/syuilo/aiscript/commit/b449b42a31901025ac684a1e2db5a19e9a63977c?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=syuilo).
> Patch has no changes to coverable lines.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##           master     #234   +/-   ##
=======================================
  Coverage   86.75%   86.75%           
=======================================
  Files          19       19           
  Lines        2817     2817           
  Branches      438      438           
=======================================
  Hits         2444     2444           
  Misses        366      366           
  Partials        7        7           
```



Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=syuilo). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=syuilo)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/syuilo/aiscript/pull/234?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=syuilo).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=syuilo).

saki-lere: #233 日本語版の構文修正入ってるの気付かなくてちょっとかぶっちゃった

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e7acee9..cff0c72 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,7 @@
 [Read translated version (en)](./translations/en/CHANGELOG.md)
 
+- 配列プロパティ`map`,`filter`,`reduce`,`find`に渡すコールバック関数が受け取るインデックスを0始まりに
+
 # 0.12.4
 - block comment `/* ... */`
 - Math:Infinity
diff --git a/docs/get-started.md b/docs/get-started.md
index af69de6..56d475a 100644
--- a/docs/get-started.md
+++ b/docs/get-started.md
@@ -178,7 +178,7 @@ if (a == b) {
 ## 繰り返し
 AiScriptでの繰り返しは、次のように書きます:
 ```
-for (#i, 100) {
+for (let i, 100) {
 	<: i
 }
 ```
diff --git a/docs/syntax.md b/docs/syntax.md
index cf669d6..d699068 100644
--- a/docs/syntax.md
+++ b/docs/syntax.md
@@ -16,27 +16,27 @@ let answer = 42
 
 ## if
 ```
-? eq(answer, 42) {
+if answer == 42 {
 	print("correct answer")
 }
 ```
 
 else:
 ```
-? eq(answer, 42) {
+if answer == 42 {
 	print("correct answer")
-} . {
+} else {
 	print("wrong answer")
 }
 ```
 
 else if:
 ```
-? eq(answer, "bebeyo") {
+if eq(answer, "bebeyo") {
 	print("correct answer")
-} .? eq(answer, "ai") {
+} elif eq(answer, "ai") {
 	print("kawaii")
-} . {
+} else {
 	print("wrong answer")
 }
 ```
@@ -44,9 +44,9 @@ else if:
 as expression:
 ```
 let result =
-	? eq(answer, "bebeyo") { "correct answer" }
-	.? eq(answer, "ai") { "kawaii" }
-	. { "wrong answer" }
+	if answer == "bebeyo" { "correct answer" }
+	elif answer == "ai" { "kawaii" }
+	else { "wrong answer" }
 
 print(result)
 ```
@@ -60,10 +60,10 @@ for let i, 10 {
 
 ## Block
 ```
-let foo = {
+let foo = eval {
 	let x = 1
 	let y = 2
-	add(x, y)
+	x + y
 }
 
 print(foo) // 3
@@ -72,7 +72,7 @@ print(foo) // 3
 ## Function
 ```
 @inc(x) {
-	add(x, 1)
+	x + 1
 }
 
 print(inc(42)) // 43
diff --git a/src/interpreter/primitive-props.ts b/src/interpreter/primitive-props.ts
index 4d518cb..1c97d7c 100644
--- a/src/interpreter/primitive-props.ts
+++ b/src/interpreter/primitive-props.ts
@@ -112,7 +112,7 @@ export const PRIMITIVE_PROPS = {
 		map: (target: VArr): VFn => FN_NATIVE(async ([fn], opts) => {
 			assertFunction(fn);
 			const vals = target.value.map(async (item, i) => {
-				return await opts.call(fn, [item, NUM(i + 1)]);
+				return await opts.call(fn, [item, NUM(i)]);
 			});
 			return ARR(await Promise.all(vals));
 		}),
@@ -122,7 +122,7 @@ export const PRIMITIVE_PROPS = {
 			const vals = [] as Value[];
 			for (let i = 0; i < target.value.length; i++) {
 				const item = target.value[i]!;
-				const res = await opts.call(fn, [item, NUM(i + 1)]);
+				const res = await opts.call(fn, [item, NUM(i)]);
 				assertBoolean(res);
 				if (res.value) vals.push(item);
 			}
@@ -135,7 +135,7 @@ export const PRIMITIVE_PROPS = {
 			let accumulator = withInitialValue ? initialValue : target.value[0]!;
 			for (let i = withInitialValue ? 0 : 1; i < target.value.length; i++) {
 				const item = target.value[i]!;
-				accumulator = await opts.call(fn, [accumulator, item, NUM(i + 1)]);
+				accumulator = await opts.call(fn, [accumulator, item, NUM(i)]);
 			}
 			return accumulator;
 		}),
@@ -144,7 +144,7 @@ export const PRIMITIVE_PROPS = {
 			assertFunction(fn);
 			for (let i = 0; i < target.value.length; i++) {
 				const item = target.value[i]!;
-				const res = await opts.call(fn, [item, NUM(i + 1)]);
+				const res = await opts.call(fn, [item, NUM(i)]);
 				assertBoolean(res);
 				if (res.value) return item;
 			}
diff --git a/src/parser/parser.peggy b/src/parser/parser.peggy
index 575b984..214f004 100644
--- a/src/parser/parser.peggy
+++ b/src/parser/parser.peggy
@@ -231,20 +231,20 @@ Each
 // for statement
 
 For
-	= "for" _* "(" "let" _* varn:NAME _* from:("=" _* v:Expr { return v; })? ","? _* to:Expr ")" _* x:BlockOrStatement
+	= "for" _* "(" "let" _* varn:NAME _* from_:("=" _* v:Expr { return v; })? ","? _* to:Expr ")" _* x:BlockOrStatement
 {
 	return createNode('for', {
 		var: varn,
-		from: from ?? createNode('num', { value: 0 }),
+		from: from_ ?? createNode('num', { value: 0 }),
 		to: to,
 		for: x,
 	});
 }
-	/ "for" _+ "let" _* varn:NAME _* from:("=" _* v:Expr { return v; })? ","? _* to:Expr _+ x:BlockOrStatement
+	/ "for" _+ "let" _* varn:NAME _* from_:("=" _* v:Expr { return v; })? ","? _* to:Expr _+ x:BlockOrStatement
 {
 	return createNode('for', {
 		var: varn,
-		from: from ?? createNode('num', { value: 0 }),
+		from: from_ ?? createNode('num', { value: 0 }),
 		to: to,
 		for: x,
 	});
diff --git a/translations/en/docs/get-started.md b/translations/en/docs/get-started.md
index 3f89506..6dc982e 100644
--- a/translations/en/docs/get-started.md
+++ b/translations/en/docs/get-started.md
@@ -34,7 +34,7 @@ Comments do not affect the behavior of the program.
 	<tr><th>Type</th><th>Form</th><th>Example of literal</th></tr>
 	<tr><td>string</td><td><code>str</code></td><td><code>"kawaii"</code></td></tr>
 	<tr><td>numeric</td><td><code>num</code></td><td><code>42</code></td></tr>
-	<tr><td>truth-value</td><td><code>bool</code></td><td><code>yes</code>/<code>no</code></td></tr>
+	<tr><td>truth-value</td><td><code>bool</code></td><td><code>true</code>/<code>false</code></td></tr>
 	<tr><td>array</td><td><code>arr</code></td><td><code>["ai" "chan" "cute"]</code></td></tr>
 	<tr><td>object</td><td><code>obj</code></td><td><code>{ foo: "bar"; a: 42; }</code></td></tr>
 	<tr><td>null</td><td><code>null</code></td><td><code>null</code></td></tr>
@@ -48,13 +48,13 @@ The variable declaration is written as follows:
 #message = "Hello"
 ```
 
-Write the name of the variable after `#` and the value after `=`.
+Write the name of the variable after `let` and the value after `=`.
 
 In AiScript, variables declared in this way are immutable. In other words, you cannot change the value of a variable later.
-To create a variable that can be reassigned, declare the variable with `$` instead of `#`. Example:
+To create a variable that can be reassigned, declare the variable with `var` instead of `let`. Example:
 ```
 // Declare a mutable variable.
-$message = "Hello"
+var message = "Hello"
 
 // reassignment
 message = "Hi"
@@ -75,10 +75,10 @@ Enumerate expressions in an array `[]`, separated by spaces.
 ["ai" "chan" "kawaii"]
 ```
 
-To access an element of an array, write `[<index>]`. The index starts at 1.
+To access an element of an array, write `[<index>]`. The index starts at 0.
 ```
-#arr = ["ai" "chan" "kawaii"]
-<: arr[1] // "ai"
+let arr = ["ai" "chan" "kawaii"]
+<: arr[0] // "ai"
 ```
 
 ## Object
@@ -112,20 +112,20 @@ Note that it cannot be written as `(1 + 1 + 1)`, but must be nested as `(1 + (1
 	<tr><td><code>Core:mul</code></td><td><code>*</code></td><td>multiplication</td></tr>
 	<tr><td><code>Core:div</code></td><td><code>/</code></td><td>division</td></tr>
 	<tr><td><code>Core:mod</code></td><td><code>%</code></td><td>remainder</td></tr>
-	<tr><td><code>Core:eq</code></td><td><code>=</code></td><td>equal</td></tr>
-	<tr><td><code>Core:and</code></td><td><code>&</code></td><td>and</td></tr>
-	<tr><td><code>Core:or</code></td><td><code>|</code></td><td>or</td></tr>
+	<tr><td><code>Core:eq</code></td><td><code>==</code></td><td>equal</td></tr>
+	<tr><td><code>Core:and</code></td><td><code>&&</code></td><td>and</td></tr>
+	<tr><td><code>Core:or</code></td><td><code>||</code></td><td>or</td></tr>
 	<tr><td><code>Core:gt</code></td><td><code>></code></td><td>greater than</td></tr>
 	<tr><td><code>Core:lt</code></td><td><code><</code></td><td>less than</td></tr>
 </table>
 
 ## Block
-A block is a collection of processes, written as `{ ~ }`.
+A block is a collection of processes, written as `eval { ~ }`.
 The expression written at the end of the block will be returned as the value of the block.
 ```
-#foo = {
-	#a = 1
-	#b = 2
+let foo = eval {
+	let a = 1
+	let b = 2
 	(a + b)
 }
 
@@ -137,7 +137,7 @@ The block itself is also a formula.
 ## Conditional branching
 The conditional branch in AiScript is written as follows:
 ```
-if (a = b) {
+if (a == b) {
 	<: "a is equal to b"
 }
 ```
@@ -145,7 +145,7 @@ if (a = b) {
 After `if`, write an expression (condition) that returns a bool, followed by an expression (then clause) that will be evaluated if the condition is met.
 You can add `else` after the `then' clause and add an expression to handle the case when the condition is not met:
 ```
-if (a = b) {
+if (a == b) {
 	<: "a is equal to b"
 } else {
 	<: "a is not equal to b"
@@ -154,7 +154,7 @@ if (a = b) {
 
 You can also write conditional expressions after `elif` to make multiple conditional decisions:
 ```
-if (a = b) {
+if (a == b) {
 	<: "a is equal to b"
 } elif (a > b) {
 	<: "a is grater than b"
@@ -165,7 +165,7 @@ if (a = b) {
 
 Since these conditional branches are expressions, they can return a value in the block:
 ```
-<: if (a = b) {
+<: if (a == b) {
 	"a is equal to b"
 } elif (a > b) {
 	"a is grater than b"
@@ -177,7 +177,7 @@ Since these conditional branches are expressions, they can return a value in the
 ## Loop
 To iterate in AiScript, write the following:
 ```
-for (#i, 100) {
+for (let i, 100) {
 	<: i
 }
 ```
@@ -192,8 +192,8 @@ for (100) {
 ## Loop (array)
 You can use `each` to repeat items in an array:
 ```
-#items = ["a" "b" "c"]
-each (#item, items) {
+let items = ["a" "b" "c"]
+each (let item, items) {
 	<: item
 }
 ```
@@ -215,7 +215,7 @@ The value of the expression written at the end of the function will be the retur
 ## Template
 You can embed variables and expressions in a string:
 ```
-#ai = "kawaii"
+let ai = "kawaii"
 <: `Hello, {ai} world!`
 ```
 
@@ -231,10 +231,10 @@ This function allows you to embed metadata in AiScript files.
 # Examples
 ## FizzBuzz
 ```
-for (#i, 100) {
-	<: ? (i % 15 == 0) "FizzBuzz"
-		.? (i % 3 == 0) "Fizz"
-		.? (i % 5 == 0) "Buzz"
-		. i
+for (let i, 100) {
+	<: if (i % 15 == 0) "FizzBuzz"
+		elif (i % 3 == 0) "Fizz"
+		elif (i % 5 == 0) "Buzz"
+		else i
 }
 ```
diff --git a/translations/en/docs/syntax.md b/translations/en/docs/syntax.md
index 2877136..f25d413 100644
--- a/translations/en/docs/syntax.md
+++ b/translations/en/docs/syntax.md
@@ -8,59 +8,59 @@ Lines that begin with `//` are comments and do not affect the behavior of the pr
 
 ## Variable declaration
 ```
-#answer = 42
+let answer = 42
 ```
 
 ## if
 ```
-? eq(answer, 42) {
+if answer == 42 {
 	print("correct answer")
 }
 ```
 
 else:
 ```
-? eq(answer, 42) {
+if answer == 42 {
 	print("correct answer")
-} . {
+} elif {
 	print("wrong answer")
 }
 ```
 
 else if:
 ```
-? eq(answer, "bebeyo") {
+if answer == "bebeyo" {
 	print("correct answer")
-} .? eq(answer, "ai") {
+} elif answer == "ai" {
 	print("kawaii")
-} . {
+} else {
 	print("wrong answer")
 }
 ```
 
 as expression:
 ```
-#result =
-	? eq(answer, "bebeyo") { "correct answer" }
-	.? eq(answer, "ai") { "kawaii" }
-	. { "wrong answer" }
+let result =
+	if answer == "bebeyo" { "correct answer" }
+	elif answer == "ai" { "kawaii" }
+	else { "wrong answer" }
 
 print(result)
 ```
 
 ## for
 ```
-for #i, 10 {
+for let i, 10 {
 	print(i)
 }
 ```
 
 ## Block
 ```
-#foo = {
-	#x = 1
-	#y = 2
-	add(x, y)
+let foo = eval {
+	let x = 1
+	let y = 2
+	x + y
 }
 
 print(foo) // 3
@@ -69,7 +69,7 @@ print(foo) // 3
 ## Function
 ```
 @inc(x) {
-	add(x, 1)
+	x + 1
 }
 
 print(inc(42)) // 43


Test patch:
diff --git a/test/index.ts b/test/index.ts
index 4337c96..21c9866 100644
--- a/test/index.ts
+++ b/test/index.ts
@@ -232,7 +232,7 @@ describe('Comment', () => {
 		`);
 		eq(res, NUM(42));
 	});
-	
+
 	test.concurrent('multi line comment 2', async () => {
 		const res = await exe(`
 		/* variable declaration here...
@@ -991,7 +991,7 @@ describe('Function call', () => {
 		`);
 		eq(res, NUM(2));
 	});
-	
+
 	test.concurrent('std: throw AiScript error when required arg missing', async () => {
 		try {
 			await exe(`
@@ -1574,7 +1574,7 @@ describe('literal', () => {
 		const res = await exe('<: "ai saw a note \\"bebeyo\\"."');
 		eq(res, STR('ai saw a note "bebeyo".'));
 	});
-	
+
 	test.concurrent('Escaped single quote', async () => {
 		const res = await exe('<: \'ai saw a note \\\'bebeyo\\\'.\'');
 		eq(res, STR('ai saw a note \'bebeyo\'.'));
@@ -2242,6 +2242,15 @@ describe('primitive props', () => {
 			eq(res, ARR([NUM(2), NUM(4), NUM(6)]));
 		});
 
+		test.concurrent('map with index', async () =>
+		{
+			const res = await exe(`
+			let arr = [1, 2, 3]
+			<: arr.map(@(item, index) { item * index })
+			`);
+			eq(res, ARR([NUM(0), NUM(2), NUM(6)]));
+		});
+
 		test.concurrent('filter', async () => {
 			const res = await exe(`
 			let arr = [1, 2, 3]
@@ -2250,6 +2259,15 @@ describe('primitive props', () => {
 			eq(res, ARR([NUM(1), NUM(3)]));
 		});
 
+		test.concurrent('filter with index', async () =>
+		{
+			const res = await exe(`
+			let arr = [1, 2, 3, 4]
+			<: arr.filter(@(item, index) { item != 2 && index != 3 })
+			`);
+			eq(res, ARR([NUM(1), NUM(3)]));
+		});
+
 		test.concurrent('reduce', async () => {
 			const res = await exe(`
 			let arr = [1, 2, 3, 4]
@@ -2258,6 +2276,15 @@ describe('primitive props', () => {
 			eq(res, NUM(10));
 		});
 
+		test.concurrent('reduce with index', async () =>
+		{
+			const res = await exe(`
+			let arr = [1, 2, 3, 4]
+			<: arr.reduce(@(accumulator, currentValue, index) { (accumulator + (currentValue * index)) } 0)
+			`);
+			eq(res, NUM(20));
+		});
+
 		test.concurrent('find', async () => {
 			const res = await exe(`
 			let arr = ["abc", "def", "ghi"]
@@ -2266,6 +2293,15 @@ describe('primitive props', () => {
 			eq(res, STR('def'));
 		});
 
+		test.concurrent('find with index', async () =>
+		{
+			const res = await exe(`
+			let arr = ["abc1", "def1", "ghi1", "abc2", "def2", "ghi2"]
+			<: arr.find(@(item, index) { item.incl("e") && index > 1 })
+			`);
+			eq(res, STR('def2'));
+		});
+
 		test.concurrent('incl', async () => {
 			const res = await exe(`
 			let arr = ["abc", "def", "ghi"]