모듈, import와 FFI

로컬·표준·패키지 import, 공개 항목과 C ABI의 extern/export 선언을 설명합니다.

Wave Foundation

import 문법

import("std::string::len");

import는 모듈 경로를 문자열로 받고 ;로 끝납니다. 모듈 전체, 별칭 또는 선택 가져오기 형태를 사용할 수 있습니다.

import("add");
import("./helpers" as helpers);
import("add")::{sum, Point};

표준 라이브러리 import

std::로 시작하는 경로는 설치된 Wave 표준 라이브러리에서 해석됩니다.

import("std::fs::file");
import("std::io::fd");

wavec print std-path로 설치된 표준 라이브러리 위치를 확인할 수 있습니다.

로컬 파일 import

로컬 파일 경로는 ./로 시작하며 import 문장을 작성한 소스 파일의 디렉터리를 기준으로 합니다. .wave 확장자는 생략할 수 있습니다.

import("./math");
import("./helpers" as helpers);

첫 문장은 같은 디렉터리의 math.wave를 가져옵니다. 별칭을 사용하면 helpers::function_name처럼 모듈 이름을 명시해서 공개 항목에 접근할 수 있습니다. 로컬 경로에는 .., 역슬래시 또는 절대 경로를 사용할 수 없습니다.

패키지 import

./std::로 시작하지 않는 경로의 첫 부분은 패키지 이름입니다. 패키지 이름만 적으면 패키지의 src/lib.wave를 가져오고, :: 뒤에 경로를 붙이면 패키지 안의 모듈을 가져옵니다.

import("add");
import("add::math");

외부 패키지 위치는 다음 옵션으로 제공할 수 있습니다.

wavec --dep-root .vex/deps build main.wave
wavec --dep math=/absolute/path/to/math build main.wave

여러 dependency root에서 같은 패키지가 발견되면 해석이 모호하므로 --dep name=path로 경로를 고정합니다.

선택 가져오기와 공개 항목

선택 가져오기는 모듈에서 필요한 공개 항목만 이 파일의 이름 공간으로 가져옵니다.

import("add")::{sum, Point};

fun main() {
    var total: i32 = sum(2, 3);
    var point: Point = Point { x: 0, y: 0 };
}

함수, 구조체, 열거형, 타입 별칭, 상수와 정적 선언 앞에 pub을 붙이면 다른 모듈에서 가져올 수 있습니다.

pub struct Point {
    x: i32;
    y: i32;
}

pub fun sum(left: i32, right: i32) -> i32 {
    return left + right;
}

pub import는 선택한 공개 항목을 다시 내보냅니다.

pub import("./extra")::{increment};

별칭 가져오기와 선택 가져오기는 한 import 문장에서 함께 사용할 수 없습니다. pub은 Wave 모듈 사이의 공개 범위를 정하며 C ABI 심볼을 만드는 export(c)와는 별개의 기능입니다.

C 함수 가져오기

extern(c) fun puts(text: ptr<i8>) -> i32;

ABI 이름 뒤에는 실제 심볼 이름을 문자열로 지정할 수 있습니다.

extern(c, "native_symbol") fun local_name(value: i32) -> i32;

Wave 함수 내보내기

export(c) fun wave_add(left: i32, right: i32) -> i32 {
    return left + right;
}

externexport는 단일 함수와 블록 형태로 사용할 수 있습니다. 내보내는 함수는 구체적인 ABI 시그니처를 가져야 하므로 제네릭일 수 없습니다.

ABI에서 직접 확인할 항목

  • 정수와 포인터 너비
  • 호출 규약과 대상 ABI 이름
  • 외부 심볼 이름
  • 문자열의 실제 표현
  • 포인터의 유효 기간과 소유권
  • 링크할 라이브러리와 검색 경로

링크에 성공했다는 사실만으로 함수 시그니처와 메모리 계약까지 일치한다는 뜻은 아닙니다.

대상 조건 속성

최상위 항목에는 대상 조건 속성을 붙일 수 있습니다.

#[target(os="linux", arch="x86_64")]
extern(c) fun platform_call(value: i32) -> i32;

조건 키는 arch, os, env, abi이며 속성은 바로 다음 최상위 항목에 적용됩니다.