토파즈 배우기

첫 애플리케이션

소스 파일 두 개로 학습 계획을 만들고 테스트한 뒤, 빌드한 실행 파일을 소스 프로젝트 밖에서 실행합니다.

소스 파일 두 개로 학습 계획을 만들고 테스트와 실행을 마쳐 보세요. 이어서 네이티브 실행 파일을 빌드하고 소스 프로젝트 밖에서 실행합니다.

실패와 리소스를 먼저 마치세요. topaz와 사용하는 플랫폼용 Rust 툴체인이 필요합니다. 설치 방법은 첫 프로그램에서 확인하세요.

프로젝트 만들기

프로젝트를 둘 폴더에서 다음 명령을 실행하세요.

BASH
topaz init --root study-plan
cd study-plan

init은 topaz.toml과 src/main.tpz를 만듭니다. 기존 프로젝트를 덮어쓰지 않으므로 study-plan이 이미 있다면 새 폴더 이름을 쓰세요.

study-plan 안에 tests 폴더를 만드세요. 다음 절의 코드로 src/main.tpz를 교체하고 나머지 두 파일을 추가하면 아래 구조가 됩니다.

study-plan/
├── topaz.toml
├── src/
│   ├── main.tpz
│   └── plan.tpz
└── tests/
    └── plan.tpz

자동으로 만든 topaz.toml에는 아래 설정이 들어 있습니다. 이 프로젝트 설정 파일을 매니페스트라고 부릅니다.

TOML
[package]
name = "study-plan"
version = "0.1.0"
language = "5.20"
entry = "src/main.tpz"

[build]
target = "native"
deterministic = true

[dependencies]
std = "5.20"

entry는 실행할 파일을, target = "native"는 운영체제에서 실행할 파일 형식을 지정합니다. 매니페스트에는 패키지 이름과 버전, 언어 버전, 의존성도 기록합니다.

소스 파일과 테스트 작성하기

아래 코드를 src/plan.tpz에 저장하세요. 과제를 만들고 아직 끝내지 않은 과제의 시간을 합산합니다.

TOPAZ
export record 학습과제 {
    제목: string,
    분: int,
    완료: bool = false,
}

function 분해석(텍스트: string) -> Result<int, string> {
    match toInt(텍스트) {
        case Some(값) if 값 > 0 => Ok(값)
        case _ => Err("minutes must be a positive integer")
    }
}

export function 과제만들기(
    제목: string,
    분문자열: string,
    완료: bool = false,
) -> Result<학습과제, string> {
    let 분 = 분해석(분문자열)?
    Ok(학습과제 { 제목: 제목, 분: 분, 완료: 완료 })
}

export function 요약(과제들: Array<학습과제>) -> string {
    let mut 남음 = 0
    for 과제 in 과제들 {
        if !과제.완료 {
            남음 = 남음 + 과제.분
        }
    }
    "tasks={과제들.length}, remaining={남음} minutes"
}

소스 파일 하나가 모듈 하나입니다. export를 붙인 선언은 다른 모듈에서 가져올 수 있습니다. 분해석에는 export가 없으므로 다른 파일에서는 과제만들기를 통해 과제를 만듭니다.

src/main.tpz를 다음 코드로 교체하세요.

TOPAZ
import src.plan { 학습과제, 과제만들기, 요약 }

export function main(인자: Array<string>, 표준입력: string) -> Result<int, string> {
    let 과제들: Array<학습과제> = [
        과제만들기("Run first program", "10", true)?,
        과제만들기("Build application", "25", false)?,
    ]
    print(요약(과제들))
    Ok(0)
}

import src.plan은 src/plan.tpz가 공개한 이름을 가져옵니다. main은 과제 두 개를 만들고 요약을 출력합니다. 명령행 인자와 표준 입력도 받지만 이 예제에서는 사용하지 않습니다. Ok(0)은 성공 종료 코드를 반환합니다.

아래 테스트를 tests/plan.tpz에 저장하세요.

TOPAZ
import src.plan { 학습과제, 과제만들기, 요약 }

match 과제만들기("Read syntax map", "15") {
    case Ok(과제) => assert(과제.분 == 15, "valid minutes")
    case Err(메시지) => assert(false, 메시지)
}

match 과제만들기("Read syntax map", "later") {
    case Ok(_) => assert(false, "invalid minutes were accepted")
    case Err(메시지) => assert(
        메시지 == "minutes must be a positive integer",
        "invalid minutes",
    )
}

let 과제들: Array<학습과제> = [
    학습과제 { 제목: "Run first program", 분: 10, 완료: true },
    학습과제 { 제목: "Build application", 분: 25 },
]
assert(
    요약(과제들) == "tasks=2, remaining=25 minutes",
    "summary",
)

테스트는 "15"를 받아들이고 "later"를 거절하는지, 요약이 예상과 같은지 확인합니다. topaz test에서 제공하는 assert로 이 결과들을 검사합니다.

잠금 파일을 만들고 검사·테스트·실행하기

다음 명령은 study-plan에서 실행하세요. 먼저 의존성 잠금 파일을 만듭니다.

BASH
topaz lock --root .

명령을 실행하면 다음 내용의 topaz.lock이 생깁니다.

TOML
[[package]]
name = "study-plan"
version = "0.1.0"
source = "root"
manifest_hash = "sha256:780ff549a9fb9b09d27c62df8ce48e70c1fc7b33d6d429e6bb826685f42e7615"

topaz.lock은 확정한 패키지 설정과 매니페스트의 해시를 기록합니다. --locked를 붙인 명령은 잠금 파일과 매니페스트가 일치하는지 확인합니다. topaz.toml을 바꾸면 topaz lock --root .을 다시 실행하세요.

서식과 타입을 검사한 뒤 테스트를 실행하세요.

BASH
topaz fmt --check --root .
topaz check --root . --locked
topaz test tests/plan.tpz --root . --locked

fmt --check는 파일을 수정하지 않습니다. check는 진입 파일과 그 파일이 가져오는 모듈을 검사합니다. 두 명령 모두 검사를 통과하면 성공 종료합니다. 테스트는 다음 줄을 출력합니다.

출력
tests/plan.tpz: test-ok

서식이 다르면 topaz fmt --root .으로 파일을 정리한 뒤 다시 검사하세요. 타입이나 이름 오류는 진단이 가리키는 줄을 고칩니다. 테스트가 실패하면 tests/plan.tpz의 입력·예상 결과와 src/plan.tpz의 함수를 대조하세요.

검사를 통과하면 애플리케이션을 실행하세요.

BASH
topaz run --root . --locked

첫 과제는 이미 끝났으므로 두 번째 과제의 시간이 남습니다.

출력
tasks=2, remaining=25 minutes

빌드하고 프로젝트 밖에서 실행하기

같은 프로젝트 폴더에서 네이티브 실행 파일을 빌드하세요.

BASH
topaz build --release --root . --locked --out-dir ../study-plan-product

빌드는 플랫폼용 Rust 툴체인을 사용하며 결과를 ../study-plan-product에 저장합니다.

study-plan-product/
├── GENERATED-OUTPUT-NOTICE.txt
├── LICENSE
├── NOTICE
├── target
│   └── release
│       └── program[.exe]
└── topaz-artifact.json

program[.exe]는 Unix의 program과 Windows의 program.exe를 뜻합니다. 완성된 파일은 Rust나 토파즈 없이 실행됩니다. 제품 폴더를 복사할 때 메타데이터와 법적 고지 파일도 함께 보관하세요.

빌드가 Rust 툴체인을 찾지 못하면 플랫폼에 맞는 툴체인을 설치하세요. 출력 폴더에 다른 타깃이나 수정한 생성 파일이 있으면 그 폴더를 보존하고 비어 있는 새 출력 폴더를 지정하세요.

프로젝트 폴더에서 나와 이름을 바꾸고, 제품 폴더에서 실행하세요. source-unavailable이 이미 있다면 다른 이름을 쓰세요. 이름을 바꿔도 소스 파일은 남으므로 나중에 계속 작업할 수 있습니다.

BASH
cd ..
mv study-plan source-unavailable
cd study-plan-product
./target/release/program

PowerShell에서는 이름을 바꿀 때 Rename-Item study-plan source-unavailable을, 실행할 때 .\target\release\program.exe를 사용하세요. 같은 결과가 나옵니다.

출력
tasks=2, remaining=25 minutes

이제 .tpz 소스 파일이 없는 폴더에서 빌드한 프로그램을 실행했습니다. 소스는 source-unavailable에 남아 있습니다.

직접 해보기

source-unavailable/src/main.tpz에서 두 번째 과제의 시간 문자열을 "25"에서 "30"으로 바꾸세요. source-unavailable에서 위의 검사·테스트·실행·빌드 명령을 반복하세요. 이어서 study-plan-product에서 새 실행 파일을 실행하면 무엇이 달라질까요?

정답 보기

애플리케이션과 새 실행 파일은 tasks=2, remaining=30 minutes를 출력합니다. 테스트는 계속 통과합니다. tests/plan.tpz에서 자체적으로 25분짜리 과제를 만들기 때문에 예상 요약은 그대로입니다.

다음 단계로 넘어갈 준비

검사와 테스트를 통과하고, 애플리케이션과 실행 파일에서 예상한 요약이 나오면 됩니다. 실행 파일을 소스 프로젝트 밖에서 실행하면 실습이 끝납니다.

명령 순서는 애플리케이션 루프에서 다시 확인하세요. 다음은 실제 파일 읽기입니다. 자세한 규칙은 모듈과 가시성과 아티팩트와 배포를, 문법은 문법 한눈에 보기를 참고하세요.