Han (한) Programming Language
Han is a statically-typed, compiled programming language where every keyword is written in Korean (Hangul). It compiles to native binaries through LLVM IR and includes a tree-walking interpreter for instant execution.
Quick Example
함수 인사(이름: 문자열) {
출력("${이름}님 안녕하세요")
}
인사("세계")
Output: 세계님 안녕하세요
Key Features
- Korean keywords —
함수,만약,이면,반복,변수 - Korean word order —
만약 조건 이면 { },조건 동안 { }(SOV) and동안 조건 { }(SVO) - String interpolation —
"${expr}"auto-desugars to형식() - Korean logical operators —
그리고,또는 - Dual execution — interpreter (
hgl interpret) and compiler (hgl build) - Tooling —
hgl check,hgl init, VS Code extension, and LSP support - Learning path —
examples/교육_*.hglincludes 10 SOV-first educational programs - Arrays, structs, enums, tuples, closures, pattern matching
- Error handling —
시도/처리with Elm-style source-context errors - File I/O, format strings, module imports
How It Works
Source (.hgl) → Lexer → Parser → AST → Interpreter (direct execution)
→ CodeGen → LLVM IR → clang → Binary
Installation
Prerequisites
- Rust 1.70+
- clang (for
hgl build/hgl run) — optional for interpreter-only use
macOS
xcode-select --install
Linux
sudo apt install clang
Install Han
For most Rust users, install Han from crates.io:
cargo install han-lang
The crates.io package is named han-lang. The language name remains Han, and the installed command-line tool remains hgl.
The default crates.io install does not enable Python interop, so the CLI does not require a local Python dynamic library. Enable it explicitly with cargo install han-lang --features python if you need the 파이썬() / 파이썬_값() built-ins.
To install from a local checkout instead:
git clone https://github.com/xodn348/han.git
cd han
cargo install --path .
After either install path, hgl is available globally.
Verify Installation
hgl --help
Hello World
Create a file called hello.hgl:
출력("안녕하세요, 세계!")
Run it:
hgl interpret hello.hgl
Output:
안녕하세요, 세계!
With a Function
함수 main() {
출력("Hello from Han!")
}
main()
Compile to Binary
hgl build hello.hgl # creates ./hello binary
./hello # runs natively
REPL
Start the interactive REPL:
hgl repl
Han (한) REPL v0.2.1
종료: Ctrl+D 또는 '나가기' 입력
한> 변수 x = 42
한> 출력(x * 2)
84
한> 나가기
안녕히 가세요!
The REPL maintains state between lines — variables and functions persist across inputs.
Learn Korean Through Coding
Every keyword in Han is a real Korean word. If you're learning Korean, writing Han code is a way to practice reading Hangul in context.
Keyword Pronunciation Guide
| Code | Pronunciation | Meaning | What it does |
|---|---|---|---|
함수 | ham-su | function (math term) | defines a function |
만약 | man-yak | if/suppose | starts a conditional |
이면 | i-myeon | then/if-then | marks the Korean-default conditional ending |
반환 | ban-hwan | return/give back | returns a value |
변수 | byeon-su | variable (math term) | declares a mutable variable |
상수 | sang-su | constant | declares an immutable constant |
반복 | ban-bok | repetition | for loop |
동안 | dong-an | during/while | while loop |
출력 | chul-ryeok | output | prints to console |
입력 | ip-ryeok | input | reads from console |
참 | cham | true/truth | boolean true |
거짓 | geo-jit | false/lie | boolean false |
없음 | eop-seum | nothing/none | null value |
구조 | gu-jo | structure | defines a struct |
열거 | yeol-geo | enumeration | defines an enum |
아니면 | a-ni-myeon | otherwise | else branch |
멈춰 | meom-chwo | stop | break |
계속 | gye-sok | continue | continue |
시도 | si-do | attempt | try block |
처리 | cheo-ri | handling/process | catch block |
맞춤 | mat-chwo | match/fit | pattern matching |
포함 | po-ham | include/contain | import module |
그리고 | geu-ri-go | and (conjunction) | logical AND |
또는 | tto-neun | or (alternative) | logical OR |
안에서 | an-e-seo | inside/within | for-in iteration |
Method Names
Array and string methods are also real Korean verbs:
| Method | Pronunciation | Meaning |
|---|---|---|
추가 | chu-ga | add/append |
삭제 | sak-je | delete/remove |
포함 | po-ham | contain/include |
정렬 | jeong-ryeol | sort/arrange |
역순 | yeok-sun | reverse order |
분리 | bun-ri | separate/split |
바꾸기 | ba-kku-gi | change/replace |
합치기 | hap-chi-gi | combine/join |
길이 | gi-ri | length |
Type Names
| Type | Pronunciation | Meaning |
|---|---|---|
정수 | jeong-su | integer (whole number) |
실수 | sil-su | real number (float) |
문자열 | mun-ja-yeol | character string |
불 | bul | boolean (fire/light) |
Example: Reading Han Code as Korean
함수 인사(이름: 문자열) {
출력("${이름}님 안녕하세요")
}
Reading this as Korean:
함수(function)인사(greeting) — "define a greeting function"이름(name):문자열(string) — "parameter: name of type string"출력(output) — "print"${이름}— insert the이름variable into the string안녕하세요(annyeonghaseyo) — "hello" (formal)
Every line is readable Korean.
Language Guide
A tour of Han's syntax — variables, functions, conditionals, and loops. For deeper coverage of any single feature, see the dedicated pages under "Language Reference" in the sidebar.
Variables and Constants
변수 이름 = 42 // mutable variable
변수 메시지 = "안녕하세요" // string variable
상수 파이 = 3.14 // immutable constant
With explicit type annotations:
변수 나이: 정수 = 25
변수 키: 실수 = 175.5
변수 이름: 문자열 = "홍길동"
변수 활성: 불 = 참
Functions
함수 더하기(가: 정수, 나: 정수) -> 정수 {
반환 가 + 나
}
함수 인사(이름: 문자열) {
출력("안녕하세요, " + 이름)
}
Conditionals
Han still supports the older minimal conditional form, but the Korean-default docs style uses 이면:
만약 점수 >= 90 이면 {
출력("A")
} 아니면 점수 >= 80 이면 {
출력("B")
} 아니면 {
출력("C")
}
Loops
For loop (반복):
반복 변수 i = 0; i < 10; i += 1 {
출력(i)
}
While loop (동안):
SOV:
변수 n = 0
n < 5 동안 {
출력(n)
n += 1
}
SVO alternative:
변수 n = 0
동안 n < 5 {
출력(n)
n += 1
}
Loop control — 멈춰 (break) and 계속 (continue):
반복 변수 i = 0; i < 100; i += 1 {
만약 i == 50 이면 {
멈춰
}
만약 i % 2 == 0 이면 {
계속
}
출력(i)
}
Keyword Reference
| Keyword | Meaning | English Equivalent |
|---|---|---|
함수 | function definition | fn / function |
반환 | return value | return |
변수 | mutable variable | let mut / var |
상수 | immutable constant | const |
만약 | conditional | if |
이면 | conditional marker | then / if-then |
아니면 | else branch | else |
그리고 | and (logical) | && |
또는 | or (logical) | ` |
반복 | for loop | for |
동안 | while loop | while |
멈춰 | break loop | break |
계속 | continue loop | continue |
참 | boolean true | true |
거짓 | boolean false | false |
출력 | print to console | print |
입력 | read from console | input |
Type System & Operators
| Type | Description | LLVM Type | Examples |
|---|---|---|---|
정수 | 64-bit integer | i64 | 42, -10 |
실수 | 64-bit float | f64 | 3.14, -0.5 |
문자열 | UTF-8 string | i8* | "안녕하세요" |
불 | boolean | i1 | 참, 거짓 |
없음 | void / no value | void | (function return type) |
| Operator | Description |
|---|---|
+, -, *, /, % | Arithmetic |
==, != | Equality |
<, >, <=, >= | Comparison |
&&, ||, !, 그리고, 또는 | Logical |
=, +=, -=, *=, /= | Assignment |
Variables & Constants
Mutable Variables
변수 이름 = 42
변수 메시지 = "안녕하세요"
이름 = 100 // reassignment allowed
Constants
상수 파이 = 3.14
// 파이 = 3.0 → runtime error: cannot reassign constant
Type Annotations
변수 나이: 정수 = 25
변수 키: 실수 = 175.5
변수 이름: 문자열 = "홍길동"
변수 활성: 불 = 참
Null Values
변수 값 = 없음
출력(값) // 없음
Data Types
Primitive Types
| Type | Han | Description | Examples |
|---|---|---|---|
| Integer | 정수 | 64-bit signed integer | 42, -10, 0 |
| Float | 실수 | 64-bit floating point | 3.14, -0.5 |
| String | 문자열 | UTF-8 string | "안녕하세요" |
| Boolean | 불 | true/false | 참, 거짓 |
| Void | 없음 | null/void | 없음 |
Type Coercion
Int and Float mix automatically:
출력(1 + 1.5) // 2.5 (Float)
출력(3 * 2.0) // 6.0 (Float)
출력(10 - 0.5) // 9.5 (Float)
Compound Types
- Arrays:
[1, 2, 3]— type[정수] - Tuples:
(1, "hello", 참)— type(정수, 문자열, 불) - Structs:
구조 사람 { 이름: 문자열 } - Enums:
열거 방향 { 위, 아래 }
Functions
Declaration
함수 더하기(가: 정수, 나: 정수) -> 정수 {
반환 가 + 나
}
Calling
변수 결과 = 더하기(3, 4)
출력(결과) // 7
No Return Type (void)
함수 인사(이름: 문자열) {
출력(형식("안녕, {0}!", 이름))
}
Recursion
함수 피보나치(n: 정수) -> 정수 {
만약 n <= 1 이면 {
반환 n
}
반환 피보나치(n - 1) + 피보나치(n - 2)
}
Generics (syntax only)
함수 첫번째<T>(arr: [T]) -> T {
반환 arr[0]
}
Type parameters are parsed but erased at runtime.
Function Type Parameter
함수 적용(f: 함수, x: 정수) -> 정수 {
반환 f(x)
}
Control Flow
If / Else-If / Else
The Korean-default conditional form uses 이면. The older minimal form is still supported, but the docs use the 이면 style:
만약 점수 >= 90 이면 {
출력("A")
} 아니면 점수 >= 80 이면 {
출력("B")
} 아니면 {
출력("C")
}
Logical Operators
만약 로그인됨 그리고 관리자 이면 {
출력("관리자 메뉴")
}
만약 오프라인 또는 점검중 이면 {
출력("잠시 후 다시 시도하세요")
}
For Loop
반복 변수 i = 0; i < 10; i += 1 {
출력(i)
}
For-In Loop
Iterate over arrays:
반복 과일 안에서 ["사과", "배", "포도"] {
출력(과일)
}
Iterate over strings:
반복 글자 안에서 "한글" {
출력(글자) // 한, 글
}
Iterate over ranges:
반복 i 안에서 0..5 {
출력(i) // 0, 1, 2, 3, 4
}
While Loop
SOV:
변수 n = 0
n < 5 동안 {
출력(n)
n += 1
}
SVO (traditional alternative):
변수 n = 0
동안 n < 5 {
출력(n)
n += 1
}
Break and Continue
반복 i 안에서 0..100 {
만약 i == 50 이면 { 멈춰 }
만약 i % 2 == 0 이면 { 계속 }
출력(i)
}
Range Operator
변수 범위 = 0..10 // creates [0, 1, 2, ..., 9]
변수 길이 = 범위.길이() // 10
Arrays
Creating Arrays
변수 숫자 = [1, 2, 3, 4, 5]
변수 빈배열 = []
Indexing
출력(숫자[0]) // 1
출력(숫자[-1]) // 5 (negative indexing)
숫자[0] = 99 // mutation
Methods
| Method | Description | Example |
|---|---|---|
.추가(값) | Append element | arr.추가(6) |
.삭제(인덱스) | Remove at index | arr.삭제(0) |
.길이() | Length | arr.길이() → 5 |
.포함(값) | Contains | arr.포함(3) → 참 |
.역순() | Reverse (new array) | arr.역순() |
.정렬() | Sort (new array) | arr.정렬() |
.합치기(구분자) | Join to string | arr.합치기(", ") |
Iteration
반복 항목 안에서 [1, 2, 3] {
출력(항목)
}
Structs
Definition
구조 사람 {
이름: 문자열,
나이: 정수
}
Instantiation
변수 홍길동 = 사람 { 이름: "홍길동", 나이: 30 }
Field Access
출력(홍길동.이름) // 홍길동
출력(홍길동.나이) // 30
Field Mutation
홍길동.나이 = 31
Nested Structs
구조 주소 { 도시: 문자열 }
구조 직원 { 이름: 문자열, 주소: 주소 }
변수 p = 직원 { 이름: "김철수", 주소: 주소 { 도시: "서울" } }
출력(p.주소.도시) // 서울
p.주소.도시 = "부산" // nested mutation
Impl Blocks (Methods)
구현 사람 {
함수 소개(자신: 사람) {
출력(형식("{0}, {1}세", 자신.이름, 자신.나이))
}
}
홍길동.소개() // 홍길동, 30세
자신 is the self parameter — refers to the struct instance.
Enums
Definition
열거 방향 {
위,
아래,
왼쪽,
오른쪽
}
Access
Variants are accessed with :::
출력(방향::위) // 0
출력(방향::아래) // 1
출력(방향::오른쪽) // 3
Variants are integer values starting from 0.
Pattern Matching with Enums
맞춤 방향::아래 {
0 => 출력("위")
1 => 출력("아래")
_ => 출력("기타")
}
Tuples
Creating Tuples
변수 좌표 = (10, 20)
변수 사람 = ("홍길동", 30, 참)
Access by Index
출력(좌표.0) // 10
출력(좌표.1) // 20
출력(사람.0) // 홍길동
As Return Type
함수 최소최대(arr: [정수]) -> (정수, 정수) {
변수 최소 = arr[0]
변수 최대 = arr[0]
반복 v 안에서 arr {
만약 v < 최소 이면 { 최소 = v }
만약 v > 최대 이면 { 최대 = v }
}
반환 (최소, 최대)
}
변수 결과 = 최소최대([5, 1, 9, 3, 7])
출력(형식("최소: {0}, 최대: {1}", 결과.0, 결과.1))
Closures
Anonymous Functions
변수 두배 = 함수(x: 정수) { 반환 x * 2 }
출력(두배(5)) // 10
Environment Capture
Closures capture variables from their enclosing scope:
변수 배수 = 3
변수 곱하기 = 함수(x: 정수) { 반환 x * 배수 }
출력(곱하기(5)) // 15
Passing as Arguments
함수 적용(f: 함수, x: 정수) -> 정수 {
반환 f(x)
}
변수 제곱 = 함수(x: 정수) { 반환 x * x }
출력(적용(제곱, 4)) // 16
Pattern Matching
Basic Match
맞춤 값 {
1 => 출력("하나")
2 => 출력("둘")
_ => 출력("기타")
}
With Blocks
맞춤 상태 {
"활성" => {
출력("활성 상태")
처리하기()
}
"비활성" => 출력("비활성")
_ => 출력("알 수 없음")
}
Pattern Types
| Pattern | Example | Description |
|---|---|---|
| Integer | 42 | Matches exact integer |
| String | "hello" | Matches exact string |
| Boolean | 참, 거짓 | Matches boolean |
| Wildcard | _ | Matches anything |
| Binding | x | Matches anything, binds to variable x |
| Array | [1, 2, 3] | Matches array structure |
Variable Binding
맞춤 값 {
0 => 출력("영")
n => 출력(형식("값: {0}", n))
}
Error Handling
Try / Catch
시도 {
변수 내용 = 파일읽기("없는파일.txt")
출력(내용)
} 처리(오류) {
출력(형식("에러: {0}", 오류))
}
The error variable (오류) contains the error message as a string. V2 errors use Elm-style messaging with source context, so the printed text points back to the original code location.
What Gets Caught
- Division by zero
- File not found
- Index out of bounds
- Undefined variable access
- Type mismatches at runtime
Example: Safe Division
함수 안전나누기(a: 정수, b: 정수) -> 정수 {
시도 {
반환 a / b
} 처리(오류) {
출력(형식("나누기 실패: {0}", 오류))
반환 0
}
}
Example error shape:
타입 오류: 정수를 기대했지만 문자열을 받았습니다
--> main.hgl:3:10
|
3 | 변수 x: 정수 = "hello"
| ^^^^^^^^^^^^^ 여기서 타입이 맞지 않습니다
Modules
Importing Files
포함 "수학도구.hgl"
This executes the file and imports all its definitions (functions, variables, structs) into the current scope.
Duplicate Includes
Han tracks imported files by canonical path and skips duplicate includes.
포함 "utils.hgl"
포함 "./utils.hgl" // same file -> skipped
This keeps include behavior idempotent for repeated module wiring.
Example
수학도구.hgl:
함수 최대값(a: 정수, b: 정수) -> 정수 {
만약 a > b 이면 { 반환 a }
반환 b
}
main.hgl:
포함 "수학도구.hgl"
출력(최대값(10, 20)) // 20
String Methods
| Method | Description | Example | Result |
|---|---|---|---|
.길이() | Character count | "한글".길이() | 2 |
.분리(sep) | Split by separator | "a,b,c".분리(",") | ["a", "b", "c"] |
.포함(s) | Contains substring | "hello".포함("ell") | 참 |
.바꾸기(from, to) | Replace | "hello".바꾸기("l", "r") | "herro" |
.앞뒤공백제거() | Trim whitespace | " hi ".앞뒤공백제거() | "hi" |
.대문자() | Uppercase | "hello".대문자() | "HELLO" |
.소문자() | Lowercase | "HELLO".소문자() | "hello" |
.시작(s) | Starts with | "hello".시작("he") | 참 |
.끝(s) | Ends with | "hello".끝("lo") | 참 |
String Indexing
변수 s = "한글"
출력(s[0]) // 한
출력(s[1]) // 글
String Iteration
반복 글자 안에서 "한글" {
출력(글자)
}
Concatenation
변수 full = "안녕" + "하세요"
출력(full) // 안녕하세요
Array Methods
| Method | Description | Example | Result |
|---|---|---|---|
.추가(값) | Append | arr.추가(6) | mutates in place |
.삭제(인덱스) | Remove at index | arr.삭제(0) | returns removed value |
.길이() | Length | arr.길이() | 5 |
.포함(값) | Contains | arr.포함(3) | 참 |
.역순() | Reverse | arr.역순() | new reversed array |
.정렬() | Sort | arr.정렬() | new sorted array |
.합치기(구분자) | Join to string | arr.합치기(", ") | "1, 2, 3" |
HashMap / Dictionary
Creating a Map
변수 점수 = 사전("수학", 95, "영어", 88, "과학", 92)
변수 빈맵 = 사전()
Arguments are key-value pairs: 사전(key1, val1, key2, val2, ...).
Access and Mutation
출력(점수["수학"]) // 95
점수["국어"] = 100 // add new key
점수["수학"] = 99 // update existing
Methods
| Method | Description | Example |
|---|---|---|
.키목록() | All keys as array | 점수.키목록() → ["수학", "영어", "과학"] |
.값목록() | All values as array | 점수.값목록() → [95, 88, 92] |
.길이() | Number of entries | 점수.길이() → 3 |
.포함(키) | Key exists | 점수.포함("수학") → 참 |
.삭제(키) | Remove key | 점수.삭제("영어") |
Iteration
변수 키들 = 점수.키목록()
반복 키 안에서 키들 {
출력(형식("{0}: {1}", 키, 점수[키]))
}
I/O
Output
출력("안녕하세요") // print to stdout
출력(42) // prints any value
출력("이름:", 이름) // multiple args, space-separated
출력오류("에러 메시지") // print to stderr
Input
변수 이름 = 입력()
출력(형식("안녕, {0}!", 이름))
입력() reads one line from stdin and returns it as a string.
Math Functions
| Function | Description | Example | Result |
|---|---|---|---|
제곱근(x) | Square root | 제곱근(16.0) | 4.0 |
절댓값(x) | Absolute value | 절댓값(-5) | 5 |
거듭제곱(밑, 지수) | Power | 거듭제곱(2, 10) | 1024.0 |
사인(x) | Sine | 사인(파이() / 2.0) | 1.0 |
코사인(x) | Cosine | 코사인(0.0) | 1.0 |
탄젠트(x) | Tangent | ||
로그(x) | Natural log (ln) | 로그(자연상수()) | 1.0 |
로그10(x) | Log base 10 | ||
지수(x) | e^x | 지수(1.0) | 2.718... |
올림(x) | Ceiling | 올림(2.3) | 3.0 |
내림(x) | Floor | 내림(2.9) | 2.0 |
반올림(x) | Round | 반올림(2.5) | 3.0 |
최대(a, b) | Maximum | 최대(3, 7) | 7.0 |
최소(a, b) | Minimum | ||
난수() | Random 0~1 | ||
난수(a, b) | Random int a~b | 난수(1, 10) | |
파이() | Pi constant | 3.14159... | |
자연상수() | Euler's number | 2.71828... | |
행렬곱(A, B) | Matrix multiply | 행렬곱(A, B) | [[실수]] |
전치(A) | Matrix transpose | 전치(A) | [[실수]] |
스칼라곱(A, s) | Scalar multiply | 스칼라곱(A, 2.0) | [[실수]] |
행렬합(A, B) | Matrix addition | 행렬합(A, B) | [[실수]] |
행렬차(A, B) | Matrix subtraction | 행렬차(A, B) | [[실수]] |
내적(a, b) | Dot product | 내적([1,2], [3,4]) | 11.0 |
외적(a, b) | Cross product (3D) | 외적([1,0,0], [0,1,0]) | [0,0,1] |
단위행렬(n) | Identity matrix | 단위행렬(3) | [[1,0,0],...] |
텐서곱(A, B) | Tensor/Kronecker product | 텐서곱(A, B) | [[실수]] |
All math functions accept both 정수 and 실수 inputs.
Matrix Operations
행렬곱 and 전치 work with 2D arrays (array of arrays):
변수 A = [[1.0, 2.0], [3.0, 4.0]]
변수 B = [[5.0, 6.0], [7.0, 8.0]]
변수 결과 = 행렬곱(A, B)
// [[19.0, 22.0], [43.0, 50.0]]
변수 T = 전치(A)
// [[1.0, 3.0], [2.0, 4.0]]
These can be used to implement algorithms like self-attention (Attention(Q,K,V) = softmax(QK^T / √d_k) × V). See examples/어텐션.hgl for a full implementation.
Type Conversion
| Function | Description | Example | Result |
|---|---|---|---|
정수변환(x) | Convert to integer | 정수변환("42") | 42 |
실수변환(x) | Convert to float | 실수변환(42) | 42.0 |
길이(s) | String length | 길이("한글") | 2 |
Conversion Rules
정수변환(3.14) // 3 (truncates)
정수변환("42") // 42 (parse string)
정수변환(참) // 1
정수변환(거짓) // 0
실수변환(42) // 42.0
실수변환("3.14") // 3.14
Format Strings
Positional Arguments
형식("이름: {0}, 나이: {1}", "홍길동", 30)
// → "이름: 홍길동, 나이: 30"
Named Arguments (from scope)
변수 이름 = "홍길동"
변수 나이 = 30
형식("이름: {이름}, 나이: {나이}")
// → "이름: 홍길동, 나이: 30"
String Interpolation
변수 이름 = "홍길동"
출력("${이름}님 안녕하세요")
// desugars to: 출력(형식("{0}님 안녕하세요", 이름))
Named mode substitutes {변수명} with the variable's value from the current scope. Interpolated strings are automatically desugared to 형식().
출력("합: ${1 + 2}")
// desugars to: 출력(형식("합: {0}", 1 + 2))
Use interpolation for simple expressions. 형식() remains the most explicit option for complex templates.
File I/O
| Function | Description | Example |
|---|---|---|
파일읽기(경로) | Read file to string | 파일읽기("data.txt") |
파일쓰기(경로, 내용) | Write string to file | 파일쓰기("out.txt", "hello") |
파일추가(경로, 내용) | Append to file | 파일추가("log.txt", "line\n") |
파일존재(경로) | Check if file exists | 파일존재("data.txt") → 참/거짓 |
Example: Read and Process
시도 {
변수 내용 = 파일읽기("data.txt")
변수 줄들 = 내용.분리("\n")
반복 줄 안에서 줄들 {
출력(줄)
}
} 처리(오류) {
출력(형식("파일 오류: {0}", 오류))
}
JSON
Powered by Rust's serde_json crate.
Parse JSON
변수 텍스트 = "{\"이름\": \"홍길동\", \"나이\": 30}"
변수 데이터 = 제이슨_파싱(텍스트)
출력(데이터["이름"]) // 홍길동
출력(데이터["나이"]) // 30
JSON objects become 사전, arrays become 배열.
Generate JSON
변수 사용자 = 사전("이름", "홍길동", "나이", 30)
변수 json = 제이슨_생성(사용자)
출력(json) // {"나이":30,"이름":"홍길동"}
Pretty Print
변수 예쁜 = 제이슨_예쁘게(사용자)
출력(예쁜)
Functions
| Function | Description |
|---|---|
제이슨_파싱(문자열) | Parse JSON string → Han value |
제이슨_생성(값) | Han value → JSON string |
제이슨_예쁘게(값) | Han value → pretty-printed JSON |
HTTP
Powered by Rust's reqwest crate (blocking mode).
GET Request
변수 응답 = HTTP_포함("https://httpbin.org/get")
출력(응답)
POST Request
변수 본문 = 제이슨_생성(사전("이름", "홍길동"))
변수 응답 = HTTP_보내기("https://httpbin.org/post", 본문)
출력(응답)
POST sends with Content-Type: application/json. If the body is not a string, it's auto-converted to JSON.
Error Handling
시도 {
변수 응답 = HTTP_포함("https://invalid-url.example")
} 처리(오류) {
출력(형식("HTTP 오류: {0}", 오류))
}
Functions
| Function | Description |
|---|---|
HTTP_포함(url) | GET request → response body as string |
HTTP_보내기(url, body) | POST request with JSON body → response as string |
Regex
Powered by Rust's regex crate.
Find All Matches
변수 결과 = 정규식_찾기("[0-9]+", "abc 123 def 456")
출력(결과) // [123, 456]
Test Match
출력(정규식_일치("^[0-9]+$", "12345")) // 참
출력(정규식_일치("^[0-9]+$", "abc")) // 거짓
Replace
변수 결과 = 정규식_바꾸기("[0-9]+", "전화: 010-1234-5678", "***")
출력(결과) // 전화: ***-***-***
Functions
| Function | Description |
|---|---|
정규식_찾기(패턴, 텍스트) | Find all matches → array of strings |
정규식_일치(패턴, 텍스트) | Test if pattern matches → bool |
정규식_바꾸기(패턴, 텍스트, 대체) | Replace all matches → string |
Date & Time
Powered by Rust's chrono crate.
Current Time
출력(현재시간()) // 2025-03-15 12:30:45
출력(현재날짜()) // 2025-03-15
출력(타임스탬프()) // 1710500000 (Unix timestamp)
Functions
| Function | Return | Example |
|---|---|---|
현재시간() | 문자열 | "2025-03-15 12:30:45" |
현재날짜() | 문자열 | "2025-03-15" |
타임스탬프() | 정수 | 1710500000 |
현재시간() and 현재날짜() use local time. 타임스탬프() returns UTC Unix timestamp.
System & Process
Shell Command
변수 결과 = 실행("ls -la")
출력(결과)
Runs the command via sh -c and returns stdout as a string.
Environment Variables
변수 홈 = 환경변수("HOME")
출력(홈) // /Users/username
변수 없는변수 = 환경변수("NONEXISTENT")
출력(없는변수) // 없음
Returns 없음 if the variable doesn't exist.
CLI Arguments
변수 인자들 = 명령인자()
반복 인자 안에서 인자들 {
출력(인자)
}
Returns arguments passed after the filename: hgl interpret file.hgl arg1 arg2
Sleep
잠자기(1000) // sleep 1 second (1000 milliseconds)
Type Introspection
출력(타입(42)) // 정수
출력(타입("hello")) // 문자열
출력(타입([1,2,3])) // 배열
출력(타입(사전())) // 사전
출력(타입(참)) // 불
Functions
| Function | Description |
|---|---|
실행(명령어) | Run shell command → stdout string |
환경변수(이름) | Get env var → string or 없음 |
명령인자() | CLI args → array of strings |
잠자기(밀리초) | Sleep for N milliseconds |
타입(값) | Type name → string |
출력오류(값) | Print to stderr |
Examples Index
Han ships with a growing set of example programs in the examples/ directory of the repository. Each file is a self-contained .hgl program you can run with:
hgl interpret examples/<name>.hgl
Tutorial Series (교육)
A 10-step progressive tutorial covering the language from basics to integration:
| File | Topic |
|---|---|
| 교육_01_변수조건.hgl | Variables and conditionals |
| 교육_02_반복문.hgl | Loops |
| 교육_03_함수.hgl | Functions |
| 교육_04_배열.hgl | Arrays |
| 교육_05_구조체.hgl | Structs |
| 교육_06_클로저.hgl | Closures |
| 교육_07_패턴매칭.hgl | Pattern matching |
| 교육_08_모듈.hgl | Modules |
| 교육_09_에러처리.hgl | Error handling |
| 교육_10_종합.hgl | Integrated example |
Classic Algorithms
| File | Topic |
|---|---|
| 피보나치.hgl | Fibonacci (recursive) |
| 피보나치_SOV.hgl | Fibonacci with SOV 동안 form |
| 팩토리얼.hgl | Factorial |
| 소수판별.hgl | Prime number check |
| 정렬알고리즘.hgl | Sorting algorithms |
| 합계.hgl | Sum 1..n |
| 구구단.hgl | Multiplication table |
| 별찍기.hgl | Star pattern printing |
| 짝홀.hgl | Even/odd checker |
Strings, Arrays, Structures
| File | Topic |
|---|---|
| 문자열보간.hgl | String interpolation |
| 단어세기.hgl | Word counter |
| 배열연산.hgl | Array operations |
| 구조체메서드.hgl | Struct methods |
| 패턴매칭.hgl | Pattern matching |
| 범위반복.hgl | Range iteration |
| 클로저고차.hgl | Higher-order closures |
| 할일목록.hgl | Todo list with structs |
| 한글연산자.hgl | Korean logical operators |
I/O and Systems
| File | Topic |
|---|---|
| 파일처리.hgl | File read/write |
| 에러처리.hgl | 시도/처리 error handling |
| 정규식.hgl | Regex |
| JSON처리.hgl | JSON parsing and generation |
| HTTP_API.hgl | HTTP GET/POST |
| 시스템정보.hgl | System / environment info |
| 온도변환.hgl | Temperature conversion |
Mini Apps
| File | Topic |
|---|---|
| 계산기.hgl | String calculator |
| 가위바위보.hgl | Rock-paper-scissors |
| 어텐션.hgl | Attention mechanism demo |
| 안녕.hgl | Hello world |
Sample: Factorial
함수 팩토리얼(n: 정수) -> 정수 {
만약 n <= 1 이면 {
반환 1
}
반환 n * 팩토리얼(n - 1)
}
함수 main() {
출력(팩토리얼(10))
}
main()
Output: 3628800
Sample: Sum 1 to 100
함수 합계(n: 정수) -> 정수 {
변수 합 = 0
반복 변수 i = 1; i <= n; i += 1 {
합 += i
}
반환 합
}
함수 main() {
출력(합계(100))
}
main()
Output: 5050
CLI Usage
hgl interpret <file.hgl> Run with interpreter
hgl build <file.hgl> Compile to native binary
hgl run <file.hgl> Compile and run immediately
hgl check <file.hgl> Type-check only (no execution)
hgl init [name] Create new Han project
hgl repl Interactive REPL
hgl lsp Start LSP server
Examples
hgl interpret examples/피보나치.hgl
hgl check examples/합계.hgl
hgl build examples/합계.hgl && ./합계
hgl init hello-han
hgl repl
hgl check (Type Check Only)
hgl check parses and type-checks a file without running interpreter/codegen.
hgl check examples/합계.hgl
- Success: prints
✓ 타입 검사 통과 - Failure: prints parser/type diagnostics and exits with non-zero status
hgl init (Project Scaffold)
hgl init hello-han
Creates:
hello-han/main.hglhello-han/.gitignore
Default main.hgl prints 안녕하세요!.
VS Code Extension
Install from Source
cd editors/vscode
npm install
npm run compile
Press F5 in VS Code to launch with the extension loaded.
Features
- Syntax highlighting for
.hglfiles - Keyword, type, builtin, string, number, comment coloring
- Auto-closing brackets and quotes
- LSP integration (hover docs + completion)
LSP Setup
Make sure hgl is in your PATH:
cargo install --path .
The extension automatically starts hgl lsp when you open a .hgl file.
Compiler Architecture
How the Han toolchain is organized — from .hgl source text to either a tree-walked result or a native binary.
How Han Works
Han follows the classical compiler pipeline, implemented entirely in Rust with zero external compiler dependencies (LLVM IR is generated as plain text):
Source (.hgl)
│
▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Lexer │ ──▶ │ Parser │ ──▶ │ AST │
│(lexer.rs)│ │(parser.rs)│ │ (ast.rs) │
└─────────┘ └─────────┘ └────┬────┘
│
┌────────────┼────────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Interpreter │ │ CodeGen │
│(interpreter.rs)│ │ (codegen.rs) │
└──────┬───────┘ └──────┬───────┘
│ │
▼ ▼
Direct Output LLVM IR (.ll)
│
▼
clang → Binary
Project Structure
han/
├── src/
│ ├── main.rs CLI entry point (hgl command)
│ ├── lexer.rs Lexer: Korean source → token stream
│ ├── parser.rs Parser: tokens → AST (recursive descent)
│ ├── ast.rs AST node type definitions
│ ├── interpreter.rs Tree-walking interpreter
│ ├── codegen.rs LLVM IR text code generator
│ └── lsp.rs LSP server (hover + completion)
├── editors/
│ └── vscode/ VS Code extension (syntax highlighting + LSP)
├── examples/ Example .hgl programs
├── spec/
│ └── SPEC.md Formal language specification (EBNF)
└── tests/ Integration tests
Design Decisions
Why text-based LLVM IR instead of the LLVM C API?
Han generates LLVM IR as plain text strings, avoiding the complexity of linking against LLVM libraries. This keeps the build simple (cargo build — no LLVM installation required) while still producing optimized native binaries through clang.
Why both interpreter and compiler? The interpreter enables instant execution without any toolchain dependencies beyond Rust. The compiler path exists for production use where performance matters. Same parser, same AST, two backends.
Why Rust? Rust's enum types map naturally to AST nodes and token variants. Pattern matching makes parser and interpreter logic clear and exhaustive. Memory safety without garbage collection suits a language toolchain.
Lexer & Token Analysis
This page covers Han's lexer (the lexer.rs stage that turns Korean source text into a token stream) and how Korean source code interacts with modern AI/LLM tokenizers.
Token Analysis (AI/LLM)
We tested Han code against Python and JavaScript using GPT-4o's tokenizer (tiktoken):
| Program | Han | Python | JavaScript |
|---|---|---|---|
| Fibonacci | 88 tokens | 54 tokens | 69 tokens |
Han uses more tokens, not fewer. Korean keywords average 2-3 tokens each vs 1 for English. This is because BPE (Byte Pair Encoding) tokenizers are trained on English-dominant data — function appears billions of times and merges into a single token, while 함수 is rare and gets split into byte-level pieces.
This is a tokenizer training bias, not a property of Korean. If BPE were trained on Korean-heavy data, 함수 could easily be a single token.
Relevant discussion: Ukrainian LLM Lapa replaced 80K tokens and achieved 1.5x efficiency
Why this matters for Han
This finding is part of Han's mission. From the project README:
LLMs are trained on English-dominant data. BPE tokenizers treat Korean characters as rare, splitting
함수into multiple byte-level tokens whilefunctionbecomes one. The more Korean code exists on the internet — in repos, in documentation, in examples — the better future tokenizers will represent the Korean language. Han is a small contribution to that corpus.
The current cost is real (more tokens per request when an LLM reads Han), but the long-term benefit accrues to every Korean-language application — not just programming languages.
Keyword Reference
Control Keywords
| Keyword | English | Syntax |
|---|---|---|
함수 | function | 함수 이름(매개변수: 타입) -> 반환타입 { } |
반환 | return | 반환 값 |
변수 | let (mutable) | 변수 이름 = 값 |
상수 | const | 상수 이름 = 값 |
만약 | if | 만약 조건 이면 { } |
이면 | then/if-then | 만약 조건 이면 { } |
아니면 | else | 아니면 { } or 아니면 조건 이면 { } |
그리고 | and (logical) | a 그리고 b |
또는 | or (logical) | a 또는 b |
반복 | for | 반복 변수 i = 0; i < n; i += 1 { } |
동안 | while | 조건 동안 { } or 동안 조건 { } |
멈춰 | break | 멈춰 |
계속 | continue | 계속 |
안에서 | in (for-in) | 반복 x 안에서 배열 { } |
Type Keywords
| Keyword | English | LLVM |
|---|---|---|
정수 | int | i64 |
실수 | float | f64/double |
문자열 | string | i8* |
불 | bool | i1 |
없음 | void/null | void |
Structure Keywords
| Keyword | English | Syntax |
|---|---|---|
구조 | struct | 구조 이름 { 필드: 타입 } |
구현 | impl | 구현 구조체 { 함수 메서드(자신: T) { } } |
열거 | enum | 열거 이름 { 변형1, 변형2 } |
시도 | try | 시도 { } 처리(오류) { } |
처리 | catch | 처리(오류) { } |
맞춤 | match | 맞춤 값 { 패턴 => 결과 } |
포함 | import | 포함 "파일.hgl" |
Literal Keywords
| Keyword | English |
|---|---|
참 | true |
거짓 | false |
없음 | null/void |
Built-in Functions
| Function | Signature | Description |
|---|---|---|
출력(값) | (any...) -> 없음 | Print to stdout |
입력() | () -> 문자열 | Read line from stdin |
제곱근(x) | (숫자) -> 실수 | Square root |
절댓값(x) | (숫자) -> 숫자 | Absolute value |
거듭제곱(밑, 지수) | (숫자, 숫자) -> 실수 | Power |
정수변환(x) | (any) -> 정수 | Convert to integer |
실수변환(x) | (any) -> 실수 | Convert to float |
길이(s) | (문자열) -> 정수 | String length |
형식(template, ...) | (문자열, any...) -> 문자열 | Format string |
파일읽기(경로) | (문자열) -> 문자열 | Read file |
파일쓰기(경로, 내용) | (문자열, 문자열) -> 없음 | Write file |
파일추가(경로, 내용) | (문자열, 문자열) -> 없음 | Append to file |
파일존재(경로) | (문자열) -> 불 | File exists |
출력오류(값) | (any...) -> 없음 | Print to stderr |
Complete API Reference
This page is optimized for LLM consumption. It contains every keyword, type, builtin, method, and operator in Han in a structured, machine-readable format.
Language: Han (한)
File Extension: .hgl
Execution: hgl interpret <file>, hgl build <file>, hgl check <file>, or hgl init [name]
KEYWORDS
함수 → function definition
반환 → return
변수 → mutable variable (let)
상수 → immutable constant (const)
만약 → if
이면 → then (conditional marker)
아니면 → else
그리고 → logical and
또는 → logical or
반복 → for loop
동안 → while loop
멈춰 → break
계속 → continue
안에서 → in (for-in iteration)
구조 → struct definition
구현 → impl block
열거 → enum definition
시도 → try
처리 → catch
맞춤 → match (pattern matching)
포함 → import
참 → true
거짓 → false
없음 → null/void
TYPES
정수 → i64 (64-bit integer)
실수 → f64 (64-bit float)
문자열 → String (UTF-8)
불 → bool
없음 → void
[정수] → Array of integers
(정수, 문자열) → Tuple
OPERATORS
+ - * / % → arithmetic
== != < > <= >= → comparison
&& || ! → logical
그리고 또는 → Korean logical aliases
|> → pipe operator
= += -= *= /= → assignment
-> → return type arrow
=> → match arm arrow
.. → range (0..10)
:: → enum access (방향::위)
. → field/method access
BUILTIN FUNCTIONS
출력(값...) → print to stdout
입력() → read line from stdin → 문자열
출력오류(값...) → print to stderr
제곱근(x) → sqrt(x) → 실수
절댓값(x) → abs(x) → 숫자
거듭제곱(밑, 지수) → pow(base, exp) → 실수
사인(x) → sin(x) → 실수
코사인(x) → cos(x) → 실수
탄젠트(x) → tan(x) → 실수
로그(x) → ln(x) → 실수
로그10(x) → log10(x) → 실수
지수(x) → e^x → 실수
올림(x) → ceil(x) → 실수
내림(x) → floor(x) → 실수
반올림(x) → round(x) → 실수
최대(a, b) → max(a, b) → 실수
최소(a, b) → min(a, b) → 실수
난수() → random float 0..1 → 실수
난수(a, b) → random int a..b → 정수
파이() → pi constant → 실수
자연상수() → Euler's number → 실수
정수변환(x) → int(x) → 정수
실수변환(x) → float(x) → 실수
길이(s) → len(s) → 정수
행렬곱(A, B) → matrix multiply → [[실수]]
전치(A) → matrix transpose → [[실수]]
스칼라곱(A, s) → scalar multiply → [[실수]]
행렬합(A, B) → matrix addition → [[실수]]
행렬차(A, B) → matrix subtraction → [[실수]]
내적(a, b) → dot product → 실수
외적(a, b) → cross product (3D) → [실수]
단위행렬(n) → identity matrix → [[실수]]
텐서곱(A, B) → tensor/Kronecker product → [[실수]]
형식(template, args...) → format string / interpolation target → 문자열
파일읽기(경로) → read file → 문자열
파일쓰기(경로, 내용) → write file
파일추가(경로, 내용) → append to file
파일존재(경로) → file exists → 불
사전(키, 값, ...) → create HashMap → 사전
제이슨_파싱(문자열) → parse JSON → value
제이슨_생성(값) → value → JSON string
제이슨_예쁘게(값) → value → pretty JSON string
HTTP_포함(url) → GET request → 문자열
HTTP_보내기(url, body) → POST request → 문자열
정규식_찾기(패턴, 텍스트) → find matches → [문자열]
정규식_일치(패턴, 텍스트) → test match → 불
정규식_바꾸기(패턴, 텍스트, 대체) → replace → 문자열
현재시간() → current datetime → 문자열
현재날짜() → current date → 문자열
타임스탬프() → unix timestamp → 정수
실행(명령어) → shell command → 문자열
환경변수(이름) → env var → 문자열 or 없음
명령인자() → CLI args → [문자열]
잠자기(밀리초) → sleep
타입(값) → type name → 문자열
파이썬(코드) → execute Python, return stdout → 문자열
파이썬_값(표현식) → evaluate Python expression → 값
MAP METHODS
.키목록() → all keys → [T]
.값목록() → all values → [T]
.길이() → entry count → 정수
.포함(키) → key exists → 불
.삭제(키) → remove entry → removed value
ARRAY METHODS
.추가(값) → push element
.삭제(인덱스) → remove at index → removed value
.길이() → length → 정수
.포함(값) → contains → 불
.역순() → reversed copy → [T]
.정렬() → sorted copy → [T]
.합치기(구분자) → join to string → 문자열
STRING METHODS
.길이() → character count → 정수
.분리(구분자) → split → [문자열]
.포함(부분) → contains → 불
.바꾸기(전, 후) → replace → 문자열
.앞뒤공백제거() → trim → 문자열
.대문자() → uppercase → 문자열
.소문자() → lowercase → 문자열
.시작(접두사) → starts with → 불
.끝(접미사) → ends with → 불
SYNTAX PATTERNS
// Variable declaration
변수 이름 = 값
변수 이름: 타입 = 값
상수 이름 = 값
// Function
함수 이름(매개변수: 타입) -> 반환타입 {
반환 값
}
// If/else (Korean-default)
만약 조건 이면 {
...
} 아니면 조건2 이면 {
...
} 아니면 {
...
}
// Older minimal form is still supported, but docs prefer the `이면` pattern.
// For loop
반복 변수 i = 0; i < n; i += 1 {
...
}
// For-in
반복 항목 안에서 배열 {
...
}
// While (SOV default)
조건 동안 {
...
}
// While (SVO alternative)
동안 조건 {
...
}
// Struct
구조 이름 {
필드: 타입,
필드2: 타입
}
// Impl
구현 구조체이름 {
함수 메서드(자신: 구조체이름) {
...
}
}
// Enum
열거 이름 {
변형1,
변형2
}
// Match
맞춤 값 {
패턴1 => 결과1
패턴2 => { ... }
_ => 기본값
}
// Try/catch
시도 {
...
} 처리(오류변수) {
...
}
// Import
포함 "파일.hgl"
// Closure
변수 f = 함수(x: 정수) { 반환 x * 2 }
// Tuple
변수 t = (1, "hello", 참)
t.0 // 1
// Range
0..10 // [0, 1, 2, ..., 9]
// Array
변수 arr = [1, 2, 3]
arr[0] // indexing
arr[-1] // negative indexing
arr[0] = 99 // mutation