함수
FunC 프로그램은 본질적으로 함수 선언/정의와 전역 변수 선언의 목록입니다. 이 섹션에서는 첫 번째 주제를 다룹니다.
모든 함수 선언이나 정의는 공통된 패턴으로 시작하며, 다음 세 가지 중 하나가 이어집니다:
-
단일
;
- 함수가 선언되었지만 아직 정의되지 않았음을 의미합니다. 같은 파일의 뒷부분이나 FunC 컴파일러에 현재 파일보다 먼저 전달된 다른 파일에서 정의될 수 있습니다. 예를 들어,int add(int x, int y);
는
(int, int) -> int
타입의add
라는 이름의 함수에 대한 간단한 선언입니다. -
어셈블러 함수 본문 정의 - FunC 프로그램에서 나중에 사용하기 위해 저수준 TVM 프리미티브로 함수를 정의하는 방법입니다. 예를 들어,
int add(int x, int y) asm "ADD";
는 TVM 오프 코드
ADD
로 변환될(int, int) -> int
타입의 동일한add
함수에 대한 어셈블러 정의입니다. -
일반적인 블록 문 함수 본문 정의 - 함수를 정의하는 일반적인 방법입니다. 예를 들어,
int add(int x, int y) {
return x + y;
}는
add
함수의 일반적인 정의입니다.
함수 선언
앞서 언급했듯이, 모든 함수 선언이나 정의는 공통된 패턴으로 시작합니다. 다음이 그 패턴입니다:
[<forall declarator>] <return_type> <function_name>(<comma_separated_function_args>) <specifiers>
여기서 [ ... ]
는 선택적 항목에 해당합니다.
함수 이름
함수 이름은 모든 식별자가 될 수 있으며, .
또는 ~
기호로 시작할 수도 있습니다. 이러한 기호의 의미는 statements 섹션에서 설명됩니다.
예를 들어, udict_add_builder?
, dict_set
, ~dict_set
은 모두 유효하고 서로 다른 함수 이름입니다. (이들은 stdlib.fc에 정의되어 있습니다.)
특별한 함수 이름
FunC(실제로는 Fift 어셈블러)는 미리 정의된 id를 가진 여러 예약된 함수 이름을 가지고 있습니다.
main
과recv_internal
은 id = 0recv_external
은 id = -1run_ticktock
은 id = -2
모든 프로그램은 반드시 id가 0인 함수, 즉 main
또는 recv_internal
함수를 가져야 합니다.
run_ticktock
은 특별한 스마트 컨트랙트의 틱톡 트랜잭션에서 호출됩니다.
내부 수신
recv_internal
은 스마트 컨트랙트가 인바운드 내부 메시지를 수신할 때 호출됩니다.
TVM이 초기화될 때 스택에 몇 가지 변수가 있으며, recv_internal
에 인수를 설정함으로써 스마트 컨트랙트 코드가 이들 중 일부를 인식하게 합니다. 코드가 알지 못하는 인수들은 스택의 맨 밑에서 전혀 건드리지 않은 채로 있게 됩니다.
따라서 다음의 recv_internal
선언들은 모두 올바르지만, 변수가 적은 것들이 약간의 가스를 덜 소비합니다(사용되지 않는 각 인수는 추가적인 DROP
명령어를 추가합니다)
() recv_internal(int balance, int msg_value, cell in_msg_cell, slice in_msg) {}
() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) {}
() recv_internal(cell in_msg_cell, slice in_msg) {}
() recv_internal(slice in_msg) {}
외부 수신
recv_external
은 인바운드 외부 메시지를 위한 것입니다.
반환 타입
반환 타입은 타입 섹션에서 설명된 모든 원자적 또는 복합 타입이 될 수 있습니다. 예를 들어,
int foo();
(int, int) foo'();
[int, int] foo''();
(int -> int) foo'''();
() foo''''();
는 모두 유효한 함수 선언입니다.
타입 추론도 허용됩니다. 예를 들어,
_ pyth(int m, int n) {
return (m * m - n * n, 2 * m * n, m * m + n * n);
}
는 피타고라스 삼중항을 계산하는 (int, int) -> (int, int, int)
타입의 pyth
함수의 유효한 정의입니다.
함수 인수
함수 인수는 쉼표로 구분됩니다. 인수의 유효한 선언은 다음과 같습니다:
- 일반 선언: 타입 + 이름. 예를 들어,
() foo(int x);
함수 선언에서int x
는int
타입과x
라는 이름을 가진 인수의 선언입니다. - 사용되지 않는 인수 선언: 타입만. 예를 들어,
는
int first(int x, int) {
return x;
}(int, int) -> int
타입의 유효한 함수 정의입니다 - 추론된 타입의 인수 선언: 이름만.
예를 들어,
는
int inc(x) {
return x + 1;
}int -> int
타입의 유효한 함수 정의입니다.x
의int
타입은 타입 체커에 의해 추론됩니다.
함수가 여러 인수를 가진 함수처럼 보일 수 있지만, 실제로는 하나의 텐서 타입 인수를 가진 함수라는 점에 주의하세요. 차이점을 이해하려면 함수 적용을 참조하세요. 그럼에도 불구하고, 인수 텐서의 구성 요소들은 관례적으로 함수 인수라고 불립니다.