본문으로 건너뛰기
토파즈6.0 · 출시 전
다운로드

문서 검색

Specification 6.0

방향키로 결과를 고르고 Enter를 눌러 여세요.

API 이름, 진단 번호, 규칙 또는 프로젝트 주제를 입력하세요.

    토파즈 6.0

    말하는 방법은 하나.

    토파즈는 조판을 내장한 범용 프로그래밍 언어입니다. 같은 일을 하는 코드는 누가 써도 같은 모양입니다.

    6.0 매뉴얼은 영어로 읽을 수 있습니다.

    투어언어라이브러리도구진단플레이그라운드

    591규칙15장340API, 모듈 19개109진단1,332예제

    oneway-ko.tpz
    1. import std.io
    2. import std.bigint { BigInt }
    3. let 쪽표시 = ["12", "표지", "14"]
    4. let 번호 = 쪽표시.map((글) => match (BigInt.parse(글, 10)) {
    5. case Some(수) => 수.toInt()
    6. case None() => None()
    7. })
    8. io.writeLine("{번호}")
    기대 출력
    [Some(12), None, Some(14)]

    map은 목록 뒤에 씁니다. BigInt.parse로 각 문자열을 읽고 toInt로 정수를 바꿉니다. ‘표지’가 있던 자리에는 None이 남습니다.

    누가, 무엇을

    이런 팀을 위해 만들었습니다

    책을 짜는 엔진을 만드는 팀

    원고에서 지면으로

    원고를 받아 줄과 쪽을 정하는 엔진을 만듭니다. 문단 줄바꿈과 한중일 금칙은 표준 라이브러리에서 가져옵니다. 같은 줄바꿈 코드를 브라우저 미리보기와 인쇄용 조판에서 함께 씁니다.

    브라우저 패키지 · 실행 파일

    std.typeset 레퍼런스 → (영어)

    출판사마다 규칙이 다른 팀

    책마다 다른 판단은 규칙 파일로

    장을 어느 쪽에서 시작할지, 외톨이 줄을 몇 줄까지 둘지는 출판사와 책마다 다릅니다. 이런 판단은 리스펙스 규칙 파일에 두고 줄을 나누는 코드는 여러 책에 함께 씁니다. 교재나 보고서처럼 고객마다 서식이 바뀌어도 앱 코드는 그대로입니다.

    실행 파일 · 리스펙스 규칙

    리스펙스 규칙 부르기 → (영어)

    웹 도구를 만드는 팀

    웹 앱 안의 데이터 처리

    JSON 검사처럼 입력을 다루는 함수를 토파즈로 쓰고 브라우저 패키지로 빌드합니다. 기존 웹 앱에서는 JavaScript로 부릅니다. 제니앱의 브라우저 도구들도 이렇게 만들었습니다.

    npm · 브라우저 패키지

    JavaScript에서 부르기 → (영어)

    std.typeset

    조판을 표준 라이브러리로

    토파즈 6.0의 std.typeset은 문단을 줄로 나누는 표준 모듈입니다. 아래 프로그램은 한국어 문장 하나를 한글 열 자 너비로 나눕니다. 문단 전체를 보고 나누면 마지막 줄에 낱말 하나만 남지 않습니다.

    typeset-ko.tpz
    1. import std.io
    2. import std.typeset {
    3. BreakCluster, BreakPolicy, BreakMode, KinsokuRules, BreakOpportunity, Paragraph, Item,
    4. Box, Penalty, BreakRule, DistanceGrid, CostModel, LineGeometry, JustificationPolicy,
    5. JustificationMode, KnuthPlassPolicy, ParagraphPlan, classifyBreaks,
    6. breakParagraph,
    7. }
    8. let 문장 = "문단 전체를 보고 줄을 나누면 마지막 줄이 짧게 남지 않고 줄마다 길이가 고르게 됩니다."
    9. let 글자들 = 문장.scalars().map(글자)
    10. let 결과 = match (classifyBreaks(글자들, 한국어규칙(글자들))) {
    11. case Ok(자리들) => breakParagraph(문단(글자들, 자리들))
    12. case Err(오류) => Err(오류)
    13. }
    14. match (결과) {
    15. case Ok(나눔) => {
    16. io.writeLine("문단 전체를 보고 나눔\n{줄글(글자들, 나눔.optimized)}\n")
    17. io.writeLine("앞에서부터 채움\n{줄글(글자들, 나눔.greedy)}")
    18. }
    19. case Err(오류) => io.writeLine("{오류}")
    20. }
    기대 출력
    문단 전체를 보고 나눔
    문단 전체를 보고
    줄을 나누면 마지막
    줄이 짧게 남지
    않고 줄마다 길이가
    고르게 됩니다.
    
    앞에서부터 채움
    문단 전체를 보고 줄을
    나누면 마지막 줄이
    짧게 남지 않고 줄마다
    길이가 고르게
    됩니다.

    프로그램의 핵심 부분입니다. 글자 너비를 정하고 문단을 만드는 도움 함수는 전체 소스에 있습니다.

    문단 줄바꿈

    문단 전체를 보고 고른 줄 나눔과 앞에서부터 채운 탐욕 줄 나눔을 함께 받습니다. 비용 모델은 Knuth-Plass와 고정소수점 모델 가운데 고릅니다.

    유니코드 줄바꿈 규칙

    유니코드 16.0의 줄바꿈 규칙(UAX #14)으로 줄을 나눌 수 있는 자리를 찾습니다.

    언어별 금칙

    한국어(KLReq), 일본어(JLReq), 중국어(CLReq) 규칙을 더하면 여는 괄호는 줄 끝에, 닫는 괄호와 마침표는 줄 머리에 오지 않습니다. 일본어 규칙은 JLReq의 문자 분류를 따릅니다.

    동아시아 문자 폭

    유니코드 동아시아 문자 폭 정보로 한중일 글자 옆 따옴표와 괄호에서 줄을 나눌지 정합니다.

    간격

    양쪽 맞춤에서 라틴 낱말 사이는 얼마나 늘이고 줄일지, 한중일 글자 사이는 얼마나 늘일지 정합니다.

    길이 단위

    12pt, 3mm, 1cm, 1in, 1em 같은 길이를 코드에 그대로 쓰고 단위를 바꿉니다.

    std.typeset 레퍼런스 (영어)

    아틀라스

    토파즈로 짓는 조판 도구

    아틀라스는 원고를 인쇄용 책 지면으로 조판합니다. 아틀라스로 조판한 책의 한 쪽과 금칙 함수를 6.0 문법으로 옮긴 표본을 함께 실었습니다. 소스의 함수 이름에는 한국어 조판 용어를 그대로 씁니다.

    아틀라스로 조판한 한국어 책의 본문 18쪽
    아틀라스로 조판한 책의 본문 18쪽

    atlas-ko.tpz
    1. function 다음은라틴공백아님(다음: Option<string>) -> bool {
    2. match (다음) {
    3. case Some(텍스트) => !라틴공백인가(텍스트)
    4. case None() => true
    5. }
    6. }
    7. function 다음은줄머리금지없음(다음: Option<string>) -> bool {
    8. match (다음) {
    9. case Some(텍스트) => !일부줄머리금지(텍스트)
    10. case None() => true
    11. }
    12. }
    기대 출력
    false true
    false true

    아틀라스의 금칙 함수 두 개를 토파즈 6.0 문법으로 옮겼습니다. 전체 표본에는 동작을 보여 주는 짧은 도움 함수와 입력을 더했습니다.

    아틀라스 보기

    토파즈가 조판에 강한 이유

    말하는 방법은 하나

    자주 하는 일은 쓰는 방법이 하나로 정해져 있습니다. 사람이 짜든 에이전트가 짜든 코드가 같은 모양이 되므로, 리뷰할 때는 코드가 하는 일만 보면 됩니다.

    쓰는 방법은 하나

    수를 문자열로 바꾸는 일과 컬렉션 연산은 값의 메서드로 씁니다. 배열에는 map을, 수에는 toString을 씁니다. 서식은 topaz fmt로 맞춥니다.

    컬렉션 연산 (영어)

    없음과 실패는 다른 값

    값이 없을 수 있으면 Option, 실패할 수 있으면 Result를 돌려주고 정리 작업은 defer로 씁니다. 문단 끝이라 다음 글자가 없으면 금칙 함수는 오류가 아니라 None을 받습니다.

    null·Option·Result·실행 오류 (영어)

    바깥과 주고받는 일은 import로

    화면 출력도 파일도 표준 모듈을 불러와 씁니다. 검토하는 사람은 import를 보고 입출력이 일어나는 자리를 바로 찾습니다.

    표준 라이브러리 개요 (영어)

    빠뜨린 경우는 빌드에서

    줄바꿈 종류처럼 경우가 정해진 목록을 열거형으로 두면 match가 모든 경우를 다루는지 컴파일러가 확인합니다. 새 경우를 더하면 그 경우를 아직 다루지 않은 match를 빌드가 알려 줍니다.

    패턴과 제어 흐름 (영어)

    넘침은 그 자리에서 멈춤

    정수는 64비트이고, 값이 넘치면 틀린 값으로 계속하지 않고 그 자리에서 멈춥니다. 줄 길이와 배치 비용을 정수로 셈하면 넘침이 조용한 오차로 남지 않습니다.

    런타임 동작 (영어)

    어디서 돌려도 같은 규칙

    직접 실행, 네이티브 실행 파일, 브라우저 패키지가 같은 언어 규칙을 따릅니다. 그래서 화면 미리보기와 인쇄용 조판이 같은 자리에서 줄을 바꿉니다.

    실행 대상 (영어)

    리스펙스

    계산은 토파즈, 판단은 리스펙스

    줄 나누기 같은 계산은 토파즈 코드가 합니다. 장을 어느 쪽에서 시작할지, 외톨이 줄을 몇 줄까지 둘지처럼 출판사와 책마다 달라지는 판단은 리스펙스 규칙으로 따로 씁니다. 토파즈 6.0은 std.lispex로 리스펙스 2.0 규칙을 실행하며 준비, 값 변환, 평가의 한도를 따로 정합니다. 규칙 소스를 바꾸고 다시 준비하면 앱 코드를 고치지 않고 같은 원고를 다른 스타일로 짤 수 있습니다.

    • 규칙은 파일, 시스템 시계, 네트워크에 손대지 않습니다.
    • 한도를 넘으면 그 자리에서 멈춥니다.
    • 같은 규칙, 입력, 설정이면 매번 같은 판단을 냅니다.
    lispex-ko.scm
    1. (define rule
    2. (lambda (input)
    3. (let ((min-lines 2))
    4. (if (< input min-lines) "다음-쪽으로" "그대로"))))

    lispex-ko.scm 전체

    lispex-ko.tpz
    1. import std.io
    2. import std.bigint { BigInt }
    3. import std.lispex {
    4. LispexPackage, LispexHostLimits, LispexPreparationLimits, LispexSource,
    5. LispexSourceBundle, PreparedLispexRule, LispexDatumView, LispexValue,
    6. applicationPackage, defaultLimits, prepare, valueFromDatum, valueView, evaluate,
    7. }
    8. export function main(args: Array<string>, stdin: string) -> Result<int, string> {
    9. let 응용 = packageOf()?
    10. let 한도 = defaultLimits()
    11. let 규칙 = ruleFrom(응용, stdin, 한도.preparation)?
    12. for 남은줄 in ([1, 2]) {
    13. let 입력 = numberOf(응용, "{남은줄}", 한도.host)?
    14. let 평가 = match (evaluate(규칙, 입력, 한도.evaluation)) {
    15. case Ok(값) => 값
    16. case Err(_) => { return Err("The evaluation could not complete.") }
    17. }
    18. match (평가.settlement) {
    19. case Complete(결과) => io.writeLine("남은 줄 {남은줄} {textOf(결과, 한도.host)?}")
    20. case SemanticFailure(_) => { return Err("The rule returned a language failure.") }
    21. case LimitExhaustion(_) => { return Err("The rule reached its evaluation limit.") }
    22. }
    23. }
    24. return Ok(0)
    25. }
    기대 출력
    남은 줄 1 다음-쪽으로
    남은 줄 2 그대로

    lispex-ko.tpz의 핵심 부분입니다. 준비와 값 변환을 위한 도움 함수는 전체 소스에 있습니다.

    prepare로 규칙을 준비하고 evaluate로 실행합니다.

    리스펙스 보기

    토파즈로 만든 프로그램

    조판 밖에서도

    토파즈 컴파일러의 핵심은 토파즈로 썼습니다. 브라우저 도구도 같은 언어로 씁니다.

    compiler.tpz
    1. function assignmentRoot(node: SyntaxNode) -> Option<SyntaxNode> {
    2. if (node.kind == "expression/identifier") {
    3. return Some(node)
    4. }
    5. match (child(node, "object")) {
    6. case Some(object) => assignmentRoot(object)
    7. case None() => None()
    8. }
    9. }
    기대 출력
    expression/identifier
    None

    compiler/crates/topaz_self_frontend/topaz/checker/expression_core.tpz의 대입 대상 탐색 함수를 토파즈 6.0 문법으로 옮겼습니다.

    컴파일러

    이름과 타입을 검사하고 Rust 코드를 만드는 일을 토파즈 코드가 합니다. topaz check로 프로그램을 검사하고 topaz build로 실행 파일을 만듭니다.

    토파즈로 만든 프로그램

    브라우저 도구

    제니앱의 JSON 포매터는 토파즈로 쓴 파서로 입력을 정리하고, 닫는 괄호가 빠지면 오류가 난 줄과 열을 알려 줍니다.

    JavaScript에서 부르기 (영어)

    토파즈 살펴보기

    어디서부터 읽을지 고르세요

    토파즈 소개

    토파즈가 어떤 문제에 알맞고 코드가 어떤 모습인지 첫 프로그램을 작성하기 전에 살펴봅니다.

    토파즈 알아보기 (영어)

    토파즈 배우기

    작은 프로그램 하나로 시작해 검사와 테스트를 거친 두 모듈 애플리케이션까지 순서대로 완성합니다.

    학습 시작하기 (영어)

    메뉴

    다운로드