Skip to content

Commit

Permalink
Merge pull request #56 from wcho21/dev
Browse files Browse the repository at this point in the history
support built-in functions
  • Loading branch information
wcho21 authored Feb 5, 2024
2 parents 5301e07 + 094e8be commit 25f6b81
Show file tree
Hide file tree
Showing 9 changed files with 246 additions and 50 deletions.
59 changes: 44 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,24 @@
[![Korean](https://img.shields.io/badge/Lang-ko-blue)][readme-ko]

[readme-en]: ./
[readme-ko]: ./docs/README_KR.md
[readme-ko]: ./docs/README.ko.md



# 🗡️ KAL
# 🗡️ KALANG

<img src="./docs/images/kal-logo.png" alt="KAL logo" width="128px" height="128px" />
<img src="./docs/images/kal-logo.png" alt="KALANG logo" width="192px" height="192px" />

_KAL: Korean Algorithmic Language_.
_KALANG: Korean Programming Language_.

A simple interpreted language which supports Korean.
- < 0.03 MB.
- Tested with >250 cases
- Written in JavaScript, natively runs on web browsers.
- Minimal syntax with Korean keywords.

You can load a _KAL_ interpreter in browsers, or build manually (see below).
Try _KALANG_ at [Playground][playground].

Try _KAL_ at [KAL Playground][playground].
You can load a _KALANG_ interpreter in browsers, or build manually (see below).

[playground]: https://kal-playground.rooi.dev/

Expand All @@ -30,12 +33,17 @@ Load the interpreter script in HTML as follows:
<script src="https://cdn.jsdelivr.net/gh/wcho21/kal@latest/dist/index.min.js"></script>
```

After that, you can execute _KAL_ code with `kal.execute(code-to-execute)` as follows:
After that, you can execute _KALANG_ code with `kal.execute(code-to-execute)` as follows:

```HTML
<script>
kal.execute("5+5"); // === 10
</script>
```javascript
kal.execute("5+5"); // === 10
```

You can attach an event handler for standard output writing as follows:
```javascript
const stdouts = [];

kal.execute("쓰기('사과')", stdout => stdouts.push(stdout)); // stdout === ["사과"]
```


Expand Down Expand Up @@ -89,6 +97,27 @@ which yields `43`.



### Builtin functions

`쓰기()`:
```
쓰기('사과')
쓰기('포도', '바나나')
```
which yields
```
사과
포도 바나나
```

`길이()`:
```
길이('사과')
```
which yields `2`.



### Types

_Number type_: any floating-point numbers
Expand All @@ -114,9 +143,9 @@ _Boolean type_: `참`, `거짓`

Note that building process is based on [Node.js][node].

With [`pnpm`][pnpm], you can build a _KAL_ interpreter by running `pnpm install && pnpm build && pnpm bundle`.
With [`pnpm`][pnpm], you can build a _KALANG_ interpreter by running `pnpm install && pnpm build`.

The output will be in the directory `/bundle/index.js`.
The output will be in the directory `/dist/index.min.js`.

[pnpm]: https://pnpm.io/
[node]: https://nodejs.org/
[pnpm]: https://pnpm.io/
2 changes: 1 addition & 1 deletion dist/index.min.js

Large diffs are not rendered by default.

65 changes: 45 additions & 20 deletions docs/README_KR.md → docs/README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,22 @@



# 🗡️ KAL
# 🗡️ KALANG

<img src="./images/kal-logo.png" alt="KAL logo" width="128px" height="128px" />
<img src="./images/kal-logo.png" alt="KALANG logo" width="192px" height="192px" />

_KAL: Korean Algorithmic Language_.
_KALANG: Korean Programming Language_.

한국어를 지원하는 인터프리터 언어.
한국어 프로그래밍 언어.

_KAL_ 인터프리터를 브라우저에 로드하거나 직접 빌드하는 방법은 아래를 참고하세요.
- < 0.03 MB.
- 250 개 이상의 테스트 케이스.
- 브라우저에서 바로 동작하는 자바스크립트 구현체.
- 한국어 키워드로 구성된 간단한 문법.

_KAL_[플레이그라운드][playground]에서 체험해보세요.
_KALANG_[플레이그라운드][playground]에서 체험해보세요.

_KALANG_ 인터프리터를 브라우저에 로드하거나 직접 빌드하는 방법은 아래를 참고하세요.

[playground]: https://kal-playground.rooi.dev/

Expand All @@ -30,12 +35,17 @@ _KAL_ 을 [플레이그라운드][playground]에서 체험해보세요.
<script src="https://cdn.jsdelivr.net/gh/wcho21/kal@latest/dist/index.min.js"></script>
```

이후, _KAL_ 코드는 다음과 같이 `kal.execute(code-to-execute)`로 실행합니다.
이후, _KALANG_ 코드는 다음과 같이 `kal.execute(code-to-execute)`로 실행합니다.

```HTML
<script>
kal.execute("5+5"); // === 10
</script>
```javascript
kal.execute("5+5"); // === 10
```

표준 출력을 위해 이벤트 핸들러를 등록할 수 있습니다.
```javascript
const stdouts = [];

kal.execute("쓰기('사과')", stdout => stdouts.push(stdout)); // stdout === ["사과"]
```


Expand Down Expand Up @@ -89,6 +99,27 @@ _KAL_ 을 [플레이그라운드][playground]에서 체험해보세요.



### 내장 함수

`쓰기()`:
```
쓰기('사과')
쓰기('포도', '바나나')
```
결과는 다음과 같습니다.
```
사과
포도 바나나
```

`길이()`:
```
길이('사과')
```
결과는 `2`입니다.



### 타입들

_숫자 타입_: 아무 부동소수점 숫자
Expand Down Expand Up @@ -116,15 +147,9 @@ _불리언 타입_: `참`, `거짓`

빌드 과정은 [Node.js][node]를 기반으로 합니다.

_KAL_ 인터프리터를 다음 커맨드로 [`pnpm`]을 이용해 빌드합니다.
[`pnpm`][pnpm]을 이용해, _KALANG_ 인터프리터를 `pnpm install && pnpm build`로 빌드할 수 있습니다.

```
pnpm install && pnpm build && pnpm bundle`
```
빌드 결과는 `/dist/index.min.js` 디렉토리에 위치합니다.



결과는 `/bundle/index.js` 디렉토리에 위치합니다.

[pnpm]: https://pnpm.io/
[node]: https://nodejs.org/
[pnpm]: https://pnpm.io/
42 changes: 42 additions & 0 deletions src/evaluator/builtin/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type * as Value from "../value";
import * as value from "../value";

export type BuiltinFunction = (args: any[], onStdout?: (toWrite: string) => void) => Value.Value;

const len: BuiltinFunction = (args) => {
const arg = args[0];
if (arg.type === "string") {
const length = arg.value.length;
return value.createNumberValue({ value: length }, String(length), arg.range);
}

throw new Error();
};

const write: BuiltinFunction = (args, onStdout) => {
if (args.length === 0) {
throw new Error();
}

const str = args.map(arg => arg.representation).join(" ");
if (onStdout !== undefined) {
onStdout(str);
}

const range = { begin: args[0].range.begin, end: args[args.length-1].range.end };
return value.createEmptyValue({ value: null }, "(없음)", range);
};

const builtins = {
get(identifier: string): BuiltinFunction | null {
switch (identifier) {
case "길이":
return len;
case "쓰기":
return write;
default:
return null;
}
}
};
export default builtins;
54 changes: 53 additions & 1 deletion src/evaluator/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import Parser from "../parser";
import Evaluator, * as Eval from "./";
import Environment from "./environment";

const evaluateInput = (input: string) => {
const evaluateInput = (input: string, onStdout?: (toWrite: string) => void) => {
const lexer = new Lexer(input);
const parser = new Parser(lexer);
const parsed = parser.parseSource();

const evaluator = new Evaluator();
if (onStdout !== undefined) {
evaluator.onStdout(onStdout);
}
const env = new Environment();
const evaluated = evaluator.evaluate(parsed, env);
return evaluated;
Expand All @@ -35,6 +38,14 @@ const testEvaluatingFunction = ({ input, expectedParamsLength }: { input: string
expect(evaluated).toHaveProperty("environment");
};

const testEvaluatingStdout = ({ input, expected }: { input: string, expected: any }): void => {
const stdouts: string[] = [];

evaluateInput(input, toWrite => stdouts.push(toWrite));

expect(stdouts).toEqual(expected);
};

describe("evaluate()", () => {
describe("single numbers", () => {
const cases = [
Expand Down Expand Up @@ -357,6 +368,47 @@ describe("evaluate()", () => {
it.each(cases)("evaluate $name", testEvaluatingPrimitive);
});

describe("builtin function calls", () => {
describe("길이()", () => {
const cases = [
{
name: "empty string",
input: "길이('')",
expected: 0,
},
{
name: "nonempty string",
input: "길이('사과')",
expected: 2,
},
];

it.each(cases)("evaluate $name", testEvaluatingPrimitive);
});

describe("쓰기()", () => {
const cases = [
{
name: "single string",
input: "쓰기('사과')",
expected: ["사과"],
},
{
name: "multiple string",
input: "쓰기('사과', '포도', '바나나')",
expected: ["사과 포도 바나나"],
},
{
name: "multiple calls",
input: "쓰기('사과') 쓰기('포도')",
expected: ["사과", "포도"],
},
];

it.each(cases)("evaluate $name", testEvaluatingStdout);
});
});

describe("errors", () => {
const cases = [
{
Expand Down
Loading

0 comments on commit 25f6b81

Please sign in to comment.