Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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만약 조건 이면 { }, 조건 동안 { }
  • String interpolation"${expr}" auto-desugars to 형식()
  • Korean logical operators그리고, 또는
  • Dual execution — interpreter (hgl interpret) and compiler (hgl build)
  • Toolinghgl check, hgl init, VS Code extension, and LSP support
  • Learning pathexamples/교육_*.hgl includes 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

git clone https://github.com/xodn348/han.git
cd han
cargo install --path .

hgl is now 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.0
종료: 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

CodePronunciationMeaningWhat it does
함수ham-sufunction (math term)defines a function
만약man-yakif/supposestarts a conditional
이면i-myeonthen/if-thenmarks the Korean-default conditional ending
반환ban-hwanreturn/give backreturns a value
변수byeon-suvariable (math term)declares a mutable variable
상수sang-suconstantdeclares an immutable constant
반복ban-bokrepetitionfor loop
동안dong-anduring/whilewhile loop
출력chul-ryeokoutputprints to console
입력ip-ryeokinputreads from console
chamtrue/truthboolean true
거짓geo-jitfalse/lieboolean false
없음eop-seumnothing/nonenull value
구조gu-jostructuredefines a struct
열거yeol-geoenumerationdefines an enum
아니면a-ni-myeonotherwiseelse branch
멈춰meom-chwostopbreak
계속gye-sokcontinuecontinue
시도si-doattempttry block
처리cheo-rihandling/processcatch block
맞춤mat-chwomatch/fitpattern matching
포함po-haminclude/containimport module
그리고geu-ri-goand (conjunction)logical AND
또는tto-neunor (alternative)logical OR
안에서an-e-seoinside/withinfor-in iteration

Method Names

Array and string methods are also real Korean verbs:

MethodPronunciationMeaning
추가chu-gaadd/append
삭제sak-jedelete/remove
포함po-hamcontain/include
정렬jeong-ryeolsort/arrange
역순yeok-sunreverse order
분리bun-riseparate/split
바꾸기ba-kku-gichange/replace
합치기hap-chi-gicombine/join
길이gi-rilength

Type Names

TypePronunciationMeaning
정수jeong-suinteger (whole number)
실수sil-sureal number (float)
문자열mun-ja-yeolcharacter string
bulboolean (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.

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

TypeHanDescriptionExamples
Integer정수64-bit signed integer42, -10, 0
Float실수64-bit floating point3.14, -0.5
String문자열UTF-8 string"안녕하세요"
Booleantrue/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

MethodDescriptionExample
.추가(값)Append elementarr.추가(6)
.삭제(인덱스)Remove at indexarr.삭제(0)
.길이()Lengtharr.길이()5
.포함(값)Containsarr.포함(3)
.역순()Reverse (new array)arr.역순()
.정렬()Sort (new array)arr.정렬()
.합치기(구분자)Join to stringarr.합치기(", ")

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

PatternExampleDescription
Integer42Matches exact integer
String"hello"Matches exact string
Boolean, 거짓Matches boolean
Wildcard_Matches anything
BindingxMatches 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

MethodDescriptionExampleResult
.길이()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

MethodDescriptionExampleResult
.추가(값)Appendarr.추가(6)mutates in place
.삭제(인덱스)Remove at indexarr.삭제(0)returns removed value
.길이()Lengtharr.길이()5
.포함(값)Containsarr.포함(3)
.역순()Reversearr.역순()new reversed array
.정렬()Sortarr.정렬()new sorted array
.합치기(구분자)Join to stringarr.합치기(", ")"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

MethodDescriptionExample
.키목록()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

FunctionDescriptionExampleResult
제곱근(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 constant3.14159...
자연상수()Euler's number2.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

FunctionDescriptionExampleResult
정수변환(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

FunctionDescriptionExample
파일읽기(경로)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

FunctionDescription
제이슨_파싱(문자열)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

FunctionDescription
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

FunctionDescription
정규식_찾기(패턴, 텍스트)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

FunctionReturnExample
현재시간()문자열"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

FunctionDescription
실행(명령어)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

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.hgl
  • hello-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 .hgl files
  • 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.

Architecture

Compiler Pipeline

Source (.hgl)
    │
    ▼
┌─────────────┐
│   Lexer     │  Source text → Token stream
│ (lexer.rs)  │  "함수" → Token::함수
└──────┬──────┘
       ▼
┌─────────────┐
│   Parser    │  Token stream → AST
│ (parser.rs) │  Recursive descent, precedence climbing
└──────┬──────┘
       ▼
┌─────────────┐
│    AST      │  Tree representation of the program
│  (ast.rs)   │  Expr, StmtKind, Pattern, Type
└──────┬──────┘
       │
       ├─────────────────┐
       ▼                 ▼
┌─────────────┐   ┌─────────────┐
│ Interpreter │   │  CodeGen    │
│(interpreter)│   │(codegen.rs) │
│             │   │             │
│ Tree-walking│   │ LLVM IR text│
│ execution   │   │ generation  │
└─────────────┘   └──────┬──────┘
                         ▼
                    clang → Binary

Source Files

FileLinesPurpose
lexer.rs~550Tokenization, Korean keyword recognition
parser.rs~1280Recursive descent parser, precedence climbing
ast.rs~270AST node definitions (Expr, Stmt, Type, Pattern)
interpreter.rs~1760Tree-walking interpreter, builtins, methods
codegen.rs~1430LLVM IR text generation (Korean→ASCII sanitization)
typechecker.rs~280Compile-time type checker (warning mode)
lsp.rs~330LSP server (hover, completion)
main.rs~310CLI entry point (clap)
builtins/Builtin function catalog (math, io, string, system)

Builtin Module Structure

src/builtins/
├── mod.rs      — module declarations
├── math.rs     — 제곱근, 절댓값, 거듭제곱, 정수변환, 실수변환, 행렬곱, 전치
├── io.rs       — 출력, 입력, 형식, 파일읽기/쓰기
├── string.rs   — 길이, 분리, 포함, 바꾸기, 대문자, 소문자
└── system.rs   — 실행, HTTP, 정규식, 제이슨, 날짜/시간

Codegen: Korean Identifier Handling

LLVM IR only allows ASCII identifiers. Han's codegen sanitizes Korean variable and function names using Unicode hex encoding:

변수 두배 = ...  →  %var_uB450uBC30 = alloca i64
함수 인사() { }  →  define void @uc778uc0ac() { }

This allows Korean-named functions and variables to compile to native binaries.

Token Analysis (AI/LLM)

Benchmark Results

Tested with GPT-4o tokenizer (tiktoken), comparing the same Fibonacci program:

LanguageTokens
Python54
JavaScript69
Han88

Why Korean Uses More Tokens

LLM tokenizers use BPE (Byte Pair Encoding):

  1. Start with raw bytes
  2. Find the most frequent byte pairs in training data
  3. Merge them into single tokens
  4. Repeat

Since training data is predominantly English:

  • function → appears billions of times → merged into 1 token
  • 함수 → rarely appears → stays as 2-3 byte-level tokens

Per-Keyword Comparison

HanTokensEnglishTokens
함수2function1
반환2return1
변수2let1
아니면3else1
멈춰3break1
동안1while1
1true1

This Is a Tokenizer Problem, Not a Korean Problem

If BPE were trained on a Korean-heavy corpus, 함수 could be a single token. The inefficiency comes from training data distribution, not from the script itself.

Relevant work:

  • Ukrainian LLM "Lapa" replaced 80K tokens and achieved 1.5x efficiency for Ukrainian text
  • Custom BPE training on Korean programming text could close the gap

Keyword Reference

Control Keywords

KeywordEnglishSyntax
함수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

KeywordEnglishLLVM
정수inti64
실수floatf64/double
문자열stringi8*
booli1
없음void/nullvoid

Structure Keywords

KeywordEnglishSyntax
구조struct구조 이름 { 필드: 타입 }
구현impl구현 구조체 { 함수 메서드(자신: T) { } }
열거enum열거 이름 { 변형1, 변형2 }
시도try시도 { } 처리(오류) { }
처리catch처리(오류) { }
맞춤match맞춤 값 { 패턴 => 결과 }
포함import포함 "파일.hgl"

Literal Keywords

KeywordEnglish
true
거짓false
없음null/void

Built-in Functions

FunctionSignatureDescription
출력(값)(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