xodn348/han: A compiled programming language with Korean keywords, written in Rust · GitHub

Written in Rust – a general-purpose compiled language with Korean keywords

function · if · iteration · variable · output
Write code in one of the world’s most beautifully designed writing systems.


Han is a statically typed, compiled programming language where each keyword is written in Korean. It compiles to native binaries via LLVM IR and also comes with a tree-walking interpreter for immediate execution. The compiler toolchain is written entirely in Rust.

HAN was born from the idea that programming did not need to look the same in every country. Hangul – the Korean writing system – is one of the most scientifically designed scripts in human history, and Han makes it work as a first-class programming language rather than just a display string.


  • Korean keywords함수, 만약, 반복, 변수 – write logic in hangul
  • hangul identifier — Name your variables and functions in Korean
  • compiled language – LLVM generates IR → Clang → Native binary
  • interpreter mode – Run immediately without any sound
  • REPL — with interactive mode hgl repl
  • lsp serverhgl lsp Editor hover for document and completeness
  • static typing – 5 primitive types: 정수 (int), 실수 (float), 문자열 (string), (bool), 없음 (void)
  • arrays[1, 2, 3]indexing, negative indexing, .추가/.삭제/.정렬/.역순 etc.
  • structures구조 사람 { 이름: 문자열 } With field access and impl block
  • Close변수 f = 함수(x: 정수) { 반환 x * 2 } with nav capture
  • pattern matching맞춰 값 { 1 => ..., _ => ... }
  • error handling시도 { } 실패(오류) { } try/catch
  • file I/O파일읽기, 파일쓰기, 파일추가, 파일존재
  • format strings형식("이름: {0}", 이름) positional or 형식("이름: {이름}") Name
  • string methods.분리, .포함, .바꾸기, .대문자, .소문자etc.
  • module import가져오기 "파일.hgl"
  • generic syntax함수 최대값(a: T, b: T) -> T
  • underlying mathematics제곱근, 절댓값, 거듭제곱, 정수변환, 실수변환, 길이

create hello.hgl: :

출력("안녕하세요, 세계!")

run it:

hgl interpret hello.hgl
# Output: 안녕하세요, 세계!

Or jump into the REPL:

hgl repl
한> 출력("안녕!")
안녕!

변수 텍스트 = "hello world hello han world hello"
변수 단어들 = 텍스트.분리(" ")
변수 단어목록 = []
변수 개수목록 = []

반복 변수 i = 0; i < 단어들.길이(); i += 1 {
    변수 찾음 = 거짓
    반복 변수 j = 0; j < 단어목록.길이(); j += 1 {
        만약 단어목록[j] == 단어들[i] {
            개수목록[j] = 개수목록[j] + 1
            찾음 = 참
        }
    }
    만약 찾음 == 거짓 {
        단어목록.추가(단어들[i])
        개수목록.추가(1)
    }
}

반복 변수 i = 0; i < 단어목록.길이(); i += 1 {
    출력(형식("{0}: {1}", 단어목록[i], 개수목록[i]))
}
함수 계산(식: 문자열) -> 정수 {
    변수 부분 = 식.분리(" ")
    변수 왼쪽 = 정수변환(부분[0])
    변수 연산자 = 부분[1]
    변수 오른쪽 = 정수변환(부분[2])

    맞춰 연산자 {
        "+" => { 반환 왼쪽 + 오른쪽 }
        "-" => { 반환 왼쪽 - 오른쪽 }
        "*" => { 반환 왼쪽 * 오른쪽 }
        "https://github.com/" => {
            만약 오른쪽 == 0 {
                출력("오류: 0으로 나눌 수 없습니다")
                반환 0
            }
            반환 왼쪽 / 오른쪽
        }
        _ => {
            출력(형식("알 수 없는 연산자: {0}", 연산자))
            반환 0
        }
    }
}

출력(계산("10 + 20"))     // 30
출력(계산("6 * 7"))       // 42
구조 할일 {
    제목: 문자열,
    완료: 불
}

변수 목록 = []

함수 추가하기(목록: [할일], 제목: 문자열) {
    목록.추가(할일 { 제목: 제목, 완료: 거짓 })
}

함수 완료처리(목록: [할일], index: 정수) {
    목록[index].완료 = 참
}

함수 출력목록(목록: [할일]) {
    반복 변수 i = 0; i < 목록.길이(); i += 1 {
        변수 상태 = "[ ]"
        만약 목록[i].완료 {
            상태 = "[✓]"
        }
        출력(형식("{0} {1}. {2}", 상태, i + 1, 목록[i].제목))
    }
}

추가하기(목록, "한글 프로그래밍 언어 만들기")
추가하기(목록, "README 작성하기")
추가하기(목록, "HN에 올리기")

완료처리(목록, 0)
완료처리(목록, 1)

출력("=== 할일 목록 ===")
출력목록(목록)
=== 할일 목록 ===
[✓] 1. 한글 프로그래밍 언어 만들기
[✓] 2. README 작성하기
[ ] 3. HN에 올리기
함수 줄수세기(경로: 문자열) -> 정수 {
    시도 {
        변수 내용 = 파일읽기(경로)
        변수 줄들 = 내용.분리("\n")
        반환 줄들.길이()
    } 실패(오류) {
        출력(형식("오류: {0}", 오류))
        반환 0
    }
}

파일쓰기("/tmp/test.txt", "첫번째 줄\n두번째 줄\n세번째 줄\n")
출력(형식("줄 수: {0}", 줄수세기("/tmp/test.txt")))

  • Rust (1.70+)
  • to ring (for) hgl build / hgl run)- xcode-select --install Or brew install llvm
git clone https://github.com/xodn348/han.git
cd han
cargo install --path .

That’s it. hgl Now available globally.


hgl interpret     Run with interpreter (no clang needed)
hgl build         Compile to native binary (requires clang)
hgl run           Compile and run immediately
hgl repl                    Interactive REPL
hgl lsp                     Start LSP server (hover + completion)

What can Han do now?

data types

  • Integer (정수), floats (실수), Wire (문자열), booleans ()
  • Tables with negative indexing – arr[-1] Returns the last element
  • Structures with field access and mutation – 사람.이름 = "홍길동"

control the flow

  • 만약 / 아니면 만약 / 아니면 (if/otherwise-if/otherwise)
  • 반복 For-loop with init, condition, step
  • 동안 while-loop
  • 멈춰 (to break), 계속 (continue)
  • 맞춰 Pattern matching – integer, string, bool, wildcard _bond

Work

  • Named functions with typed parameters and return types
  • Recursion (Fibonacci, Factorial, etc.)
  • Closure/anonymous functions with environment capture – 변수 f = 함수(x: 정수) { 반환 x * 2 }
  • Clojure passed as argument (without type annotation)

strings

  • combination with +
  • Methods: .분리(sep), .포함(s), .바꾸기(from, to), .앞뒤공백제거(), .대문자(), .소문자(), .시작(s), .끝(s), .길이()
  • Character Sequencing – 문자열[0]

arrays

  • Methods: .추가(v), .삭제(i), .길이(), .포함(v), .역순(), .정렬(), .합치기(sep)
  • Read/Write Index – arr[i], arr[i] = v
  • Negative Indexing – arr[-1]

Structures and methods

  • define: 구조 사람 { 이름: 문자열, 나이: 정수 }
  • Immediately: 변수 p = 사람 { 이름: "홍길동", 나이: 30 }
  • Impl with block methods 자신 (Self): 구현 사람 { 함수 인사(자신: 사람) { ... } }

error handling

  • 시도 { } 실패(오류) { } – Catches any runtime errors including division by zero, file not found, out of range

file I/O

  • 파일읽기("path") – reads the entire file into a string
  • 파일쓰기("path", content) – writes string to file
  • 파일추가("path", content) – adds to the file
  • 파일존재("path") – returns bool

construction of mathematics

  • 제곱근(x), 절댓값(x), 거듭제곱(밑, 지수)
  • 정수변환(x), 실수변환(x), 길이(s)

format strings

  • Named: 형식("이름: {이름}, 나이: {나이}") – substitute from current scope
  • Positional: 형식("이름: {0}, 나이: {1}", 이름, 나이)

module

  • 가져오기 "파일.hgl" – runs another .hgl file in current scope

generic syntax

  • 함수 최대값(a: T, b: T) -> T – Type parameters are parsed and hashed at runtime

⚠️ partial/edge cases

Speciality Situation
Serves as typed parameter The syntax is not supported yet – f: 함수 fails. Pass closure without type annotation.
없음 as literal value can not write 변수 x = 없음 yet – parser can’t handle 없음 as an expression
float + int mixed arithmetic No inherent pressure – 1 + 1.5 fails. Use 실수변환(1) + 1.5
nested structure region mutation a.b.c = v Not supported – only one level deep
closed in 맞춰 Hand Works, but must use arm body { } block syntax
hgl build with arrays/structs Codegen stubs for arrays/structs – interpreter for those features only


Speciality notes
Multi-Return / Tuples no tuple type yet
enms No 열거 keywords yet
Zero Security/Option Type No 없음? or option
async/concurrent Single-threaded only
Standard Library: Network, Process No HTTP, no subprocess
garbage collection only through reference counting Rc> – cycle leak
tail call optimization Deep recursion will cause stack overflow


beauty of hangul

Hangul (한글) is not simply a writing system – it is an achievement of intentional linguistic design. Created by King Sejong the Great in 1443, each letter encodes phonetic information in its geometric shape. Consonants reflect the position of the tongue and mouth used to pronounce them. The vowels are composed of three cosmic symbols: heaven (·), earth (ㅡ), and human (ㅣ).

Han brings this beauty to programming. when you write 함수 피보나치(n: 정수) -> 정수You’re not just defining a function – you’re writing in a script that was purpose-built for clarity and beauty.

ride the korean wave

Global interest in Korean culture has never been greater. From K-pop and Korean cinema to learning Korean cuisine and the language, millions of people around the world are connecting with Korean culture. Over 16 million people are actively studying Korean as a foreign language.

Han offers these learners something unexpected: a way to practice reading and writing Hangul through programming. It bridges the gap between cultural interest and technical skills, making Korean literacy functional in an area where it never existed before.


language guide
변수 이름 = 42              // mutable variable
변수 메시지 = "안녕하세요"     // string variable
상수 파이 = 3.14            // immutable constant

With explicit type annotations:

변수 나이: 정수 = 25
변수 키: 실수 = 175.5
변수 이름: 문자열 = "홍길동"
변수 활성: 불 = 참
함수 더하기(가: 정수, 나: 정수) -> 정수 {
    반환 가 + 나
}

함수 인사(이름: 문자열) {
    출력("안녕하세요, " + 이름)
}
만약 점수 >= 90 {
    출력("A")
} 아니면 만약 점수 >= 80 {
    출력("B")
} 아니면 {
    출력("C")
}

for loop (반복):

반복 변수 i = 0; i < 10; i += 1 {
    출력(i)
}

while loop (동안):

변수 n = 0
동안 n < 5 {
    출력(n)
    n += 1
}

loop control멈춰 (break) and 계속 (continue):

반복 변수 i = 0; i < 100; i += 1 {
    만약 i == 50 {
        멈춰
    }
    만약 i % 2 == 0 {
        계속
    }
    출력(i)
}
example program
함수 팩토리얼(n: 정수) -> 정수 {
    만약 n <= 1 {
        반환 1
    }
    반환 n * 팩토리얼(n - 1)
}

함수 main() {
    출력(팩토리얼(10))
}

main()

Output: 3628800

함수 합계(n: 정수) -> 정수 {
    변수 합 = 0
    반복 변수 i = 1; i <= n; i += 1 {
        합 += i
    }
    반환 합
}

함수 main() {
    출력(합계(100))
}

main()

Output: 5050

함수 main() {
    반복 변수 i = 1; i <= 10; i += 1 {
        만약 i % 2 == 0 {
            출력("짝수")
        } 아니면 {
            출력("홀수")
        }
    }
}

main()
keyword reference

keyword Meaning english equivalent
함수 function definition fn / function
반환 return value return
변수 variable variable let mut / var
상수 immutable constant const
만약 conditional if
아니면 other branch else
반복 for loop for
동안 while loop while
멈춰 break the loop break
계속 continue loop continue
boolean truth true
거짓 boolean false false
출력 print to console print
입력 read from console input


Type system and operator

Type Description llvm type Example
정수 64-bit integer i64 42, -10
실수 64-bit float f64 3.14, -0.5
문자열 utf-8 string i8* "안녕하세요"
boolean i1 , 거짓
없음 zero/no value void (function return type)


operator Description
+, -, *, /, % arithmetic
==, != Equality
<, >, <=, >= Compare
&&, ||, ! logical
=, +=, -=, *=, /= workload


Design and Architecture

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
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)
├── examples/            Example .hgl programs
├── spec/
│   └── SPEC.md          Formal language specification (EBNF)
└── tests/               Integration tests

Why text-based LLVM IR instead of LLVM C API?
Han generates LLVM IRs as plain text strings, avoiding the complexity of linking against LLVM libraries. This keeps construction simple (cargo build – no LLVM installation required) while still producing optimized native binaries via Clang.

Why both interpreter and compiler?
The interpreter enables quick 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 naturally map to AST nodes and token variants. Pattern matching makes the logic of the parser and interpreter clear and complete. Memory safety without garbage collection is suitable for a language toolchain.


46 tests (41 units + 5 integrations) covering lexer, parser, AST, interpreter and code generator.


MIT


Han – Where the beauty of Hangul meets the precision of the code.



<a href

Leave a Comment