웹어셈블리 기반 한국어 프로그래밍 언어.
코미는 다음과 같은 작은 인터프리터입니다.
- 웹어셈블리로 컴파일되어 웹 브라우저에서 네이티브하게 실행됩니다.
- Rust를 이용해 메모리에 안전하게 작성되었습니다.
- 사이드 이펙트를 동반하는 파일 시스템이나 네트워크 I/O와 같은 기능이 배제되어, 애플리케이션 수준에서 악성 코드 주입으로 인한 피해를 방지합니다.
다음과 같이 내장 함수 쓰기()
를 통해 문자열을 쓸 수 있습니다.
쓰기("안녕!👋")
안녕!👋
코미는 기본적으로 키워드에 한글을 지원하며 모든 유니코드를 문자열로 표현할 수 있습니다. 내부적으로 문자를 UTF-8로 처리하기 때문입니다.
이 예제가 조금 심심하다면, 이름을 넣어 인사해봅시다.
변수에 값을 할당하고, 중괄호 {}
를 통해 문자열에 끼워넣을 수 있습니다.
이름 = "코미"
쓰기("{이름}, 안녕!👋")
코미, 안녕!👋
다른 사람에게도 인사하고 싶다면, 함수
키워드를 사용해 클로저를 만들 수 있습니다.
인사 = 함수 이름 {
"{이름}, 반가워😎"
}
인사("코미")
코미, 반가워😎
클로저는 그저 값에 불과하므로 변수에 할당할 수 있습니다.
또한 클로저는 (다른 프로그래밍 언어들처럼) 바깥 스코프에 있는 변수를 캡처해 자신의 실행 환경에 포함시킵니다. 따라서 인사말을 클로저 바깥으로 이렇게 옮길 수 있습니다.
인사말 = "반가워😎" # 🖼️ 캡처됨
인사 = 함수 이름 {
"{이름}, {인사말}" # 📸 캡처함
}
인사("코미")
코미, 반가워😎
고차 함수 클로저의 정의와 커링 또한 가능합니다.
인사 = 함수 이름 {
함수 인사말 {
"{이름}, {인사말}!"
}
}
인사("코미")("반가워😎")
코미, 반가워😎
물론 매개변수를 함수 이름, 인사말
과 같이 쓰고 인사("코미", "반가워😎")
처럼 호출할 수도 있습니다.
코미는 표현식 기반 언어입니다.
앞서 소개했듯이, 문자열과 클로저는 표현식입니다. 그리고 표현식의 나열 또한 표현식입니다.
평균 = 함수 숫자1, 숫자2 {
합 = 숫자1 + 숫자2
합 / 2
}
평균(10, 20)
15
클로저를 호출하면 그 안의 모든 표현식이 실행되지만, 그 결과는 마지막 표현식의 값이 됩니다. 이것이 마지막 표현식이 리턴 값이 되는 이유입니다.
코미에서 모든 것은 표현식이고, 반드시 표현식이어야 합니다. 따라서 클로저 본문은 비어 있을 수는 없습니다.
브랜칭도 표현식이므로, 양쪽 모두 적어도 하나의 표현식이 있어야 합니다.
온도 = 35
만약 온도 > 30 {
"더워"
} 아니면 {
"안 더워"
}
더워
또한, 다른 언어의 else if
처럼, 아니면 만약
을 사용해 조건을 추가할 수 있습니다.
만약 온도 > 30 {
"더워"
} 아니면 만약 온도 > 10 {
"괜찮아"
} 아니면 {
"추워"
}
코미는 기본 타입으로 숫자, 문자열, 불리언을 지원합니다.
숫자 = 42
문자 = "사과"
불 = 참 # or 거짓
타입 간에는 자동 변환이 일어나지 않습니다.
예를 들어, 0
을 거짓 불리언 값으로 다룰 수는 없습니다. (다른 느슨한 타입 언어와 다른 점입니다.)
코미는 강한 타입 언어는 아니지만, 내장 함수 타입()
으로 언제든 값의 타입을 확인할 수 있습니다.
타입(42)
숫자
클로저를 만들었다면, 코미는 자동으로 메소드 스타일 호출 문법을 지원합니다.
최대 = 함수 이전, 새값 {
만약 이전 > 새값 {
이전
} 아니면 {
새값
}
}
10.최대(15)
15
점 연산자(.
)를 이용해 왼쪽 값을 첫 번째 인자로, 호출 인자를 두 번째 이후 인자로 하여 클로저를 호출할 수 있습니다.
객체 지향 용어로 왼쪽 객체에 오른쪽 메소드를 호출하는 방법입니다.
사실 a.b
는 a
를 b
의 첫 번째 인자로 고정한 새로운 클로저를 리턴하는 것과 같습니다.
이것을 이용해, 다음과 같이 메소드 체이닝 또한 가능합니다.
10.최대(5).최대(-5).최대(15)
이 표현식은 사실상 다음과 같은 호출과 같습니다.
최대(최대(최대(10, 5), -5), 15)
Warning
이 기능은 아직 구현되지 않았습니다.
코미는 이터레이터를 통해 반복을 지원합니다.
범위(5).줄이기(더하기) # 0부터 4까지의 합
10
이터레이터는 기본적으로 늦게 평가됩니다.
그래서 0
부터 무한대까지의 범위도 표현할 수 있습니다.
따라서 위 예시는 이렇게 표현할 수도 있습니다.
범위(0, ..).갖기(5).줄이기(더하기) # 0부터 4까지의 합
다른 함수형 프로그래밍 언어가 map()
, filter()
, reduce()
와 같은 함수를 지원하듯이, 코미 또한 이를 이용할 수 있습니다.
# 홀수의 제곱 합
범위(5)
.고르기(함수 숫자 { 숫자 % 2 == 0 }) # 1, 3, 5
.바꾸기(함수 숫자 { 숫자 * 숫자 }) # 1, 9, 25
.줄이기(더하기) # 35
35
패키지의 execute()
함수로 인터프리터를 실행할 수 있습니다.
import { execute } from "@wcho21/komi_wasm";
execute("안녕")
정상적인 코드를 성공적으로 실행한 결과는 다음과 같은 오브젝트와 같습니다.
interface ExecOut {
value: string;
stdout: string;
}
여기서 value
는 평가된 값을, stdout
은 표준 출력을 가집니다.
실행이 실패한 경우는 자바스크립트 Error
인스턴스가 던져집니다.
interface ExecError {
name: "LexError" | "ParseError" | "EvalError";
message: string;
cause: {
location: {
begin: {
col: number;
row: number;
},
end: {
col: number;
row: number;
},
};
};
}
여기서 name
과 messsage
는 오류의 원인을, cause
는 소스 코드 상 오류의 위치를 가집니다.
이 패키지는 GitHub Packages 저장소를 통해 npm install @wcho21/komi_wasm
로 설치할 수 있습니다.
이 문서를 참고하세요.