본문으로 건너뛰기

타입

정보

FunC 문서는 처음에 @akifoq가 작성했습니다.

FunC는 다음과 같은 내장 타입을 가지고 있습니다.

원자적 타입

  • int는 257비트 부호 있는 정수의 타입입니다. 기본적으로 오버플로우 체크가 활성화되어 있으며, 정수 오버플로우 예외가 발생합니다.
  • cell은 TVM 셀의 타입입니다. TON 블록체인의 모든 영구 데이터는 셀의 트리에 저장됩니다. 각 셀은 최대 1023비트의 임의 데이터와 다른 셀에 대한 최대 4개의 참조를 가질 수 있습니다. 셀은 스택 기반 TVM의 메모리 역할을 합니다.
  • slice는 셀 슬라이스의 타입입니다. 셀은 슬라이스로 변환될 수 있으며, 그 후 셀의 데이터 비트와 다른 셀에 대한 참조는 슬라이스에서 로드하여 얻을 수 있습니다.
  • builder는 셀 빌더의 타입입니다. 데이터 비트와 다른 셀에 대한 참조를 빌더에 저장할 수 있으며, 그 후 빌더를 새로운 셀로 완성할 수 있습니다.
  • tuple은 TVM 튜플의 타입입니다. 튜플은 서로 다를 수 있는 임의의 값 타입을 가진 최대 255개의 컴포넌트로 이루어진 정렬된 컬렉션입니다.
  • cont는 TVM 연속체의 타입입니다. 연속체는 TVM 프로그램 실행 흐름을 제어하는 데 사용됩니다. FunC의 관점에서는 상당히 저수준 객체이지만, 역설적으로 꽤 일반적입니다.

위의 타입들은 모두 TVM 스택의 단일 항목만을 차지한다는 점에 주목하세요.

불리언 타입의 부재

FunC에서 불리언은 정수로 표현됩니다; false0으로, true-1(이진 표기법으로 257개의 1)로 표현됩니다. 논리 연산은 비트 단위 연산으로 수행됩니다. 조건을 검사할 때는 0이 아닌 모든 정수가 true 값으로 간주됩니다.

Null 값

TVM 타입 Null의 값 null로, FunC는 일부 원자적 타입 값의 부재를 나타냅니다. 표준 라이브러리의 일부 프리미티브는 원자적 타입을 반환하는 것으로 타입이 지정되어 있지만 실제로는 일부 경우에 null을 반환할 수 있습니다. 다른 프리미티브는 원자적 타입의 값을 기대하지만 null 값과도 잘 작동할 수 있습니다. 이러한 동작은 프리미티브 명세에 명시적으로 기술되어 있습니다. 기본적으로 null 값은 금지되어 있으며 런타임 예외를 발생시킵니다.

이러한 방식으로, 원자적 타입 A는 암시적으로 타입 A^? 또는 Maybe A로 변환될 수 있습니다(타입 체커는 이러한 변환을 인식하지 못합니다).

홀 타입

FunC는 타입 추론을 지원합니다. _var 타입은 타입 체크 중에 나중에 실제 타입으로 채워질 수 있는 타입 "홀"을 나타냅니다. 예를 들어, var x = 2;2와 같은 변수 x의 정의입니다. 2int 타입을 가지고 있고 할당의 왼쪽과 오른쪽은 같은 타입을 가져야 하기 때문에, 타입 체커는 xint 타입을 가진다고 추론할 수 있습니다.

복합 타입

타입은 더 복잡한 타입으로 조합될 수 있습니다.

함수 타입

A -> B 형태의 타입은 지정된 도메인과 코도메인을 가진 함수를 나타냅니다. 예를 들어, int -> cell은 하나의 정수 인수를 받아 TVM 셀을 반환하는 함수의 타입입니다.

내부적으로 이러한 타입의 값은 연속체로 표현됩니다.

텐서 타입

(A, B, ...) 형태의 타입은 기본적으로 TVM 스택 항목을 하나 이상 차지하는 A, B, ... 타입의 값들의 정렬된 컬렉션을 나타냅니다.

예를 들어, 함수 fooint -> (int, int) 타입을 가지고 있다면, 이 함수는 하나의 정수를 받아 두 개의 정수 쌍을 반환한다는 의미입니다.

이 함수의 호출은 (int a, int b) = foo(42);와 같이 보일 수 있습니다. 내부적으로 함수는 하나의 스택 항목을 소비하고 두 개를 남깁니다.

(int, (int, int)) 타입의 값 (2, (3, 9))(int, int, int) 타입의 값 (2, 3, 9)는 저수준 관점에서 스택 항목 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 튜플의 타입입니다. []는 빈 튜플의 타입입니다(유일한 값으로 빈 튜플을 가짐). 단위 타입 ()와는 달리, []의 값은 하나의 스택 항목을 차지한다는 점에 주목하세요.

타입 변수를 사용한 다형성

FunC는 다형성 함수를 지원하는 Miller-Rabin 타입 시스템을 가지고 있습니다. 예를 들어, 다음 함수:

forall X -> (X, X) duplicate(X value) {
return (value, value);
}

는 (단일 스택 항목) 값을 받아 이 값의 두 복사본을 반환하는 다형성 함수입니다. duplicate(6)은 값 6 6을 생성하고, duplicate([])는 빈 튜플의 두 복사본 [] []을 생성합니다.

이 예제에서 X는 타입 변수입니다.

이 주제에 대한 자세한 내용은 함수 섹션을 참조하세요.

사용자 정의 타입

현재 FunC는 위에서 설명한 타입 구성 외에는 타입을 정의하는 것을 지원하지 않습니다.

타입 너비

보셨듯이, 타입의 모든 값은 일정 수의 스택 항목을 차지합니다. 타입의 모든 값에 대해 이 수가 동일한 경우, 이 수를 타입 너비라고 합니다. 다형성 함수는 현재 타입 너비가 고정되어 있고 미리 알려진 타입에 대해서만 정의될 수 있습니다.