유형
FunC 문서는 @akifoq가 처음 작성했습니다.
FunC에는 다음과 같은 기본 제공 유형이 있습니다.
원자 유형
- int`는 257비트 부호 있는 정수의 유형입니다. 기본적으로 오버플로 검사는 활성화되어 있으며 정수 오버플로 예외를 발생시킵니다.
- '셀'은 TVM 셀의 유형입니다. TON 블록체인의 모든 영구 데이터는 셀 트리에 저장됩니다. 모든 셀에는 최대 1023 비트의 임의 데이터와 다른 셀에 대한 최대 4개의 참조가 있습니다. 셀은 스택 기반 TVM에서 메모리 역할을 합니다.
- '슬라이스'는 셀 슬라이스의 유형입니다. 셀을 슬라이스로 변환한 다음 셀의 데이터 비트와 다른 셀에 대한 참조를 슬라이스에서 로드하여 얻을 수 있습니다.
- 빌더`는 셀 빌더의 유형입니다. 데이터 비트와 다른 셀에 대한 참조를 빌더에 저장한 다음 빌더를 새 셀로 완성할 수 있습니다.
- '튜플'은 TVM 튜플의 유형입니다. 튜플은 구별될 수 있는 임의의 값 유형을 가진 최대 255개의 컴포넌트로 구성된 정렬된 컬렉션입니다.
- 계속`은 TVM 연속의 유형입니다. 연속은 TVM 프로그램 실행의 흐름을 제어하는 데 사용됩니다. FunC의 관점에서 보면 다소 낮은 수준의 객체이지만 역설적으로 매우 일반적입니다.
위의 모든 유형은 TVM 스택에서 하나의 항목만 차지한다는 점에 유의하세요.
부울 유형이 없음
FunC에서 부울은 정수로 표현되며, '거짓'은 '0'으로, '참'은 '-1'로 표현됩니다(2진법 표기에서는 257개). 논리 연산은 비트 연산으로 수행됩니다. 조건이 확인되면 0이 아닌 모든 정수는 참
값으로 간주됩니다.
Null 값
TVM 타입 Null
의 null
값으로, FunC는 일부 원자 타입의 값이 없음을 나타냅니다. 표준 라이브러리의 일부 프리미티브는 원자 형을 반환하는 것으로 입력될 수 있으며 경우에 따라 실제로 null
을 반환할 수도 있습니다. 다른 것들은 원자 형의 값을 제외한 것으로 입력되었지만 null
값으로도 잘 작동할 수 있습니다. 이러한 동작은 프리미티브 사양에 명시적으로 명시되어 있습니다. 기본적으로 null
값은 금지되어 있으며 런타임 예외를 발생시킵니다.
이러한 방식으로 원자 유형 A
는 암시적으로 A^?
유형, 즉 Maybe A
로 변환될 수 있습니다(유형 검사기는 이러한 변환에 무관심합니다).
구멍 유형
FunC는 유형 추론을 지원합니다. 유형 _
와 var
는 나중에 유형 검사 중에 실제 유형으로 채워질 수 있는 유형 "구멍"을 나타냅니다. 예를 들어, var x = 2;
는 2
와 같은 변수 x
의 정의입니다. 타입 검사기는 2
의 타입이 int
이고 대입의 왼쪽과 오른쪽이 동일한 타입을 가져야 하므로 x
가 int
타입을 갖는다고 추론할 수 있습니다.
복합 유형
유형은 더 복잡한 유형으로 구성할 수 있습니다.
기능 유형
A -> B형식의 타입은 지정된 도메인과 코드 도메인을 가진 함수를 나타냅니다. 예를 들어
int -> cell`은 하나의 정수 인수를 받아 TVM 셀을 반환하는 함수 유형입니다.
내부적으로 이러한 유형의 값은 연속형으로 표시됩니다.
텐서 유형
(A, B, ...)형식의 타입은 기본적으로
A,
B,
...` 타입 값의 정렬된 컬렉션을 나타내며, 모두 함께 둘 이상의 TVM 스택 항목을 차지합니다.
예를 들어 함수 foo
의 타입이 int -> (int, int)
인 경우, 함수가 하나의 정수를 취하고 그 쌍을 반환한다는 의미입니다.
이 함수의 호출은 (int a, int b) = foo(42);
와 같이 보일 수 있습니다. 내부적으로 이 함수는 스택 항목 하나를 소비하고 그 중 두 개를 남깁니다.
저수준 관점에서 보면 (int, (int, int))
타입의 값 (2, (3, 9))
와 (int, int, int)
타입의 값 (2, 3, 9)
는 3개의 스택 항목 2
, 3
, 9
와 같은 방식으로 표현된다는 점에 유의하세요. FunC 타입 검사기에서는 다른 타입의 값입니다. 예를 들어, 코드 (int a, int b, int c) = (2, (3, 9));
는 컴파일되지 않습니다.
텐서 타입의 특별한 경우는 단위 타입 ()
입니다. 일반적으로 함수가 값을 반환하지 않거나 인수가 없다는 사실을 나타낼 때 사용됩니다. 예를 들어, 함수 print_int
는 int -> ()
타입을 가지며, 함수 random
은 () -> int
타입을 갖습니다. 이 함수는 스택 엔트리를 0개 차지하는 고유한 ()
를 가지고 있습니다.
(A)형식의 유형은 유형 검사기에서
A`와 동일한 유형으로 간주됩니다.
튜플 유형
A, B, ...]형식의 타입은 컴파일 타임에 알려진 특정 길이와 구성 요소의 유형을 가진 TVM 튜플을 나타냅니다. 예를 들어,
[int, cell]은 길이가 정확히 2이고 첫 번째 구성 요소가 정수이고 두 번째 구성 요소가 셀인 TVM 튜플의 유형입니다. '[]
는 빈 튜플의 유형입니다(유일한 거주자, 즉 빈 튜플을 가짐). 단위 유형 ()
와 달리 []
의 값은 스택 항목 하나를 차지한다는 점에 유의하세요.
유형 변수를 사용한 다형성
펀씨는 다형성 함수를 지원하는 밀러-라빈 타입 시스템을 갖추고 있습니다. 예를 들어 다음 함수가 있습니다:
forall X -> (X, X) duplicate(X value) {
return (value, value);
}
는 (단일 스택 항목) 값을 취하고 이 값의 복사본 두 개를 반환하는 다형성 함수입니다. 복제(6)는
6 6값을 생성하고
복제([])는 빈 튜플의 복사본
[][]` 두 개를 생성합니다.
이 예제에서 X
는 유형 변수입니다.
이 주제에 대한 자세한 내용은 함수 섹션을 참조하세요.
사용자 정의 유형
현재 FunC는 위에서 설명한 유형 구성을 제외하고는 유형 정의를 지원하지 않습니다.
유형 너비
눈치채셨겠지만, 타입의 모든 값은 스택 항목의 일정 개수를 차지합니다. 타입의 모든 값에 대해 동일한 숫자인 경우, 이 숫자를 타입 너비라고 합니다. 현재 다형성 함수는 유형 너비가 고정되어 있고 미리 알려진 유형에 대해서만 정의할 수 있습니다.