Skip to content

Latest commit

 

History

History
307 lines (214 loc) · 14.4 KB

zullang_documentation.md

File metadata and controls

307 lines (214 loc) · 14.4 KB

줄랭 Documentation

목차

  1. ㅎㅇ 키워드
  2. ㄱㄱ 키워드
  3. ㅇㅈ?, ㄴㄴ?, ㄴㄴ 키워드
  4. ㅈㅈ, ㅅㄱ, ㅌㅌ 키워드
  5. 입, 출 함수
  6. 변수 생성
  7. 리터럴
  8. 블록
  9. 연산자
  10. 작명
  11. 프로그램 진입점

키워드 및 타입 표

키워드 의미
ㅎㅇ 구조체, 함수 정의
ㄱㄱ 반복문 정의 (for)
ㅇㅈ? 조건문 정의 (if)
ㄴㄴ? 조건문 정의 (else if)
ㄴㄴ 조건문 정의 (else)
ㅈㅈ 함수 반환 (return)
ㅅㄱ 반복문 정지 (break)
ㅌㅌ 다음 반복 (continue)
표준 입력 함수 (scanf)
표준 출력 함수 (printf)
타입 이름 의미
논리 1비트 정수
글자 8비트 정수
64비트 정수
실수 64비트 실수

ㅎㅇ 키워드: (하이)

함수 또는 구조체를 정의할 때 사용하는 키워드입니다.
아래처럼 ()를 사용하면 함수, 그렇지 않으면 클래스입니다.
(클래스는 아직 지원되진 않지만, 미래의 사용을 위해 문법이 예약되어 있습니다.)

  • ㅎㅇ 함수이름():
  • ㅎㅇ 클래스이름:

아래처럼 리턴 타입을 명시할 수 있습니다. 명시하지 않으면 기본적으로 void로 인식됩니다.

  • ㅎㅇ 함수이름() 수:

함수 선언만 하고 싶다면 함수 프로토타입 끝에 콜론을 쓰지 않으면 됩니다.

  • ㅎㅇ 함수이름() 글자
  • ㅎㅇ 함수이름()

함수 프로토타입을 선언할 때 매개변수 이름을 생략하고 타입만 나열할 수 있습니다.

  • ㅎㅇ 함수이름(실수, 실수, 글자)

... 을 사용하면 가변 인자를 받는 함수를 선언할 수 있습니다. 하지만 va_arg 등의 지원이 없기 때문에 가변 인자를 사용할 순 없습니다. 외부 라이브러리 함수 선언용으로 존재합니다.

  • ㅎㅇ 함수이름(수, ...) 수

ㄱㄱ 키워드: (고고)

반복문을 정의할 때 사용하는 키워드입니다.
go언어의 for문처럼 다양한 형태로 사용 가능합니다.

  • ㄱㄱ a = 1; a < 10; a+=1:
    일반적인 반복문
  • ㄱㄱ a < 10:
    while문처럼 사용 가능
  • ㄱㄱ :
    아무것도 넣지 않으면 무한루프

ㅇㅈ?, ㄴㄴ?, ㄴㄴ 키워드: (인정?, 노노?, 노노)

조건문을 정의할 때 사용하는 키워드입니다. 각각 if, else if, else에 대응합니다. 아래와 같은 형태로 사용할 수 있습니다.

  • ㅇㅈ? <조건>:
  • ㄴㄴ? <조건>: (ㄴㄴ? 는 여러 개 가능)
  • ㄴㄴ :

ㅈㅈ, ㅅㄱ, ㅌㅌ 키워드: (GG, 수고, 튀튀)

ㅈㅈ는 return, ㅅㄱ는 break, ㅌㅌ는 continue의 의미를 가집니다.

입, 출 함수:

각각 C의 scanf, printf에 대응하는 함수입니다.

a = 10 (수)
b = 10.0 (실수)
c = 'a' (글자)

변수는 위처럼 정의되었다고 가정하겠습니다.

입 함수는 입(a,b,c) 과 같은 형식으로 사용하고, 이는 scanf("%lld %lf %c", &a, &b, &c) 와 똑같이 작동합니다.
줄랭 컴파일러가 정적 타입 추론 기능으로 포멧 문자열을 자동 생성하고, 실제 코드를 scanf 호출 구문으로 치환합니다.
따라서 입(a)도 가능하고, 입(a,b,c,d,e, .....) 처럼 인자를 계속 넣을 수도 있습니다.

출 함수도 비슷합니다. 출(a,b,c) 을 사용하면, printf("%lld %lf %c\n", a, b, c) 로 변환됩니다.
출()처럼 아무것도 넣지 않으면 printf("\n")로 추론되기 때문에, 빈 줄만 출력됩니다.
원리는 완전히 다르지만 파이썬의 print와 거의 똑같이 작동한다고 보시면 됩니다.

함수를 치환하고 포멧 문자열을 생성하는 동작은 모두 컴파일 타임에 일어나기 때문에, 런타임 오버헤드가 전혀 없고, 실제 scanf, printf 함수를 사용하는 것과 성능이 똑같습니다.

만약 포멧 문자열을 바꾸고 싶다면, 그냥 printf와 scanf를 직접 사용하면 됩니다. 함수 테이블에 기본으로 존재하기 때문에 선언할 필요가 없습니다.

배열은 기본적으로 %p로 추론되고, '글자' 배열만 예외적으로 %s로 지정되어 있습니다.

'논리' 자료형은 %u로 추론되긴 하나, C언어에는 1비트 자료형이 없기 때문에 printf와 scanf가 정상 작동하지 않습니다. 사용하지 않는 것을 권장합니다.

변수 생성:

변수 생성은 3가지 방법으로 할 수 있습니다.

  • a: 실수
    자료형을 명시해서 '실수' 자료형이 되었고, 초기화는 되지 않음.
  • a = 10
    대입식을 가지고 타입이 자동 추론되어 '수' 자료형이 됨.
  • a: 실수 = 10
    자료형을 '실수'로 명시했기에, 대입식의 타입은 '수' 이지만 자동 캐스팅되어 10.0으로 초기화됨

전역 공간에서 선언과 동시에 초기화를 할 경우, 대입식은 반드시 상수식이어야 합니다. 현재 줄랭에는 상수 선언이 없기 때문에, 리터럴 자체와 리터럴들의 연산식만 상수로 취급됩니다.

배열

배열과 포인터는 아직 완벽하게 지원되지 않습니다. 오로지 전역 공간의 1차원 배열만 지원합니다. 리터럴 배열 역시 지원되지 않습니다.
아래와 같이 사용할 수 있습니다.

  • 배열1: 수[100]
  • 배열2: 글자[50]

변수에 관한 설명 (중요)

  1. 다중 대입은 불가능합니다. 단순 = 뿐만 아니라, +=, /= 등 대입 계열 연산자는 모두 한 구문에서 한 번만 사용할 수 있습니다.

  2. 스코프 규칙은 C언어와 동일합니다. 함수, ㅇㅈ?문, ㄱㄱ문 등 블록이 생성되는 모든 곳에 지역 변수를 정의할 수 있습니다. 또한 안쪽 스코프에서는 바깥쪽 변수에 접근이 가능하고, 바깥쪽에서는 안쪽 스코프에 정의된 변수에 접근할 수 없습니다.

  3. 줄랭은 변수 생성과 대입의 문법이 완전히 똑같기 때문에, 이를 구분할 수 없습니다. 따라서 줄랭 컴파일러는 이미 존재하는 변수면 대입문, 존재하지 않는 변수면 생성문으로 추론합니다.

  4. 위의 이유로 외부 스코프의 변수와 같은 이름을 가지는 변수를 생성할 수 없습니다. 항상 대입으로 추론됩니다.
    ㄱ: 실수 또는 ㄱ: 실수 = 10 처럼 타입을 명시하는 변수 생성 방식은 생성으로 명확히 추론할 수 있지만, 일관성을 위해 생성하지 못하게 되어 있습니다.
    (모든 변수가 스코프를 공유한다는 의미가 아닙니다. 외부 스코프 변수를 덮어쓰는 지역 변수를 생성할 수 없다는 의미입니다.)

  5. 줄랭에는 함수 포인터나 함수를 객체처럼 취급하는 기능이 아예 없기 때문에, 함수와 변수의 이름 테이블이 완전히 분리되어 있습니다. 따라서 함수의 이름과 똑같은 변수를 만들어도 됩니다. 호출 구문 '()' 이 사용되면 함수가 호출되고, 이외에는 모두 변수로 판단합니다.

리터럴

줄랭의 리터럴은 5가지가 있습니다.

  1. 논리 리터럴 , 거짓:
    1비트 정수인 논리 자료형의 리터럴입니다. 이름 그대로 각각 true, false에 해당합니다.
    거짓 은 리터럴로 사용되기 때문에 변수명으로 사용할 수 없습니다.

  2. 글자 리터럴:
    C언어의 char와 같습니다 작은따옴표를 사용하고, 1바이트를 초과할 수 없습니다. a = 'x' 처럼 사용하면 됩니다.
    아직 글자 리터럴에서 이스케이프 문자는 지원되지 않습니다. 곧 추가될 예정입니다.

  3. 수 리터럴:
    수 리터럴은 일반적인 숫자입니다. a = 10 처럼 사용하면 됩니다.

  4. 실수 리터럴:
    수 리터럴과 비슷하나, 소숫점이 포함되어 있으면 실수로 추론됩니다. 소숫점은 반드시 하나만 있어야 하고, 소숫점 앞 또는 뒤에만 숫자가 있어도 됩니다.

  5. 문자열 리터럴:
    C언어의 문자열 리터럴과 비슷합니다. 큰따옴표를 사용해 정의하고, 프로그램에 글로벌 스트링으로 저장됩니다.
    a = "안녕"처럼 사용하면 됩니다. 유일하게 \n은 이스케이프 문자로 인식해서, 줄바꿈 문자로 사용할 수 있습니다.

블록

줄랭의 블록은 파이썬과 동일하게 들여쓰기로 구분됩니다. 하지만 탭 문자는 허용하지 않습니다. 오로지 공백 문자 4개만 하나의 들여쓰기로 인식합니다.

간단한 블록 예시를 보여드리겠습니다.

ㅎㅇ 시작() 수:
    출("함수 블록 시작입니다")

    ㄱㄱ :
        출("ㄱㄱ 블록 시작입니다")
        
        ㅇㅈ? 참:
            출("ㅇㅈ? 블록입니다")
            ㅅㄱ
        
        출("ㄱㄱ 블록 끝입니다")
        
    출("함수 블록 끝입니다")

실행 결과:

함수 블록 시작입니다
ㄱㄱ 블록 시작입니다
ㅇㅈ? 블록입니다
함수 블록 끝입니다

들여쓰기 횟수로 블럭이 구분되는 모습을 볼 수 있습니다.

ㅇㅈ?문에서 ㅅㄱㄱㄱ문을 종료했기 때문에 "ㄱㄱ 블록 끝입니다" 는 출력되지 않았고, "함수 블록 끝입니다" 는 잘 출력되었습니다.

연산자:

구조체, 포인터에 관련된 연산자를 제외하고 C언어에 존재하는 모든 연산자를 사용할 수 있습니다.
아래 연산자 우선순위 표를 확인하세요.

연산자 우선순위 표
연산자 종류 우선순위 그룹 번호 이름
~ 1 one's complement
! 1 logical not
- 1 unary negation
+ 1 unary plus
* 2 multiplication
/ 2 division
% 2 modulus
+ 3 addition
- 3 subtraction
<< 4 left shift
>> 4 right shift
< 5 less than
> 5 greater than
<= 5 less than equal to
>= 5 greater than equal to
== 6 equality
!= 6 inequality
& 7 bitwise AND
^ 8 bitwise exclusive OR
| 9 bitwise inclusive OR
&& 10 logical AND
|| 11 logical OR
= 12 assignment
*= 12 multiplication assignment
/= 12 division assignment
%= 12 modulus assignment
+= 12 addition assignment
-= 12 subtraction assignment
<<= 12 left-shift assignment
>>= 12 right-shift assignment
&= 12 bitwise AND assignment
|= 12 bitwise inclusive OR assignment
^= 12 bitwise exclusive OR assignment

&& 연산자와 || 연산자는 단락 평가를 지원합니다. 즉, && 연산자는 앞의 표현식이 거짓이면, 뒤의 표현식은 평가하지 않습니다.
마찬가지로 ||연산자는 앞의 표현식이 참이면, 뒤의 표현식은 평가하지 않습니다.

작명:

함수 이름, 변수 이름 등의 작명 규칙은 C언어와 거의 동일합니다. 한글, 알파벳, 언더바, 숫자를 사용할 수 있고, 숫자로 시작할 순 없습니다. 또한 알파벳 대소문자를 구분합니다.

한가지 유의 사항은 하나의 이름에 한글과 영어를 섞어서 작명을 할 수 없습니다. 즉 (한글, 언더바, 숫자) 또는 (영어, 언더바, 숫자)만 가능합니다.

한글로 인식하는 유니코드 범위는 아래와 같습니다.

이름 처음 개수
한글 자모 (Hangul Jamo) 1100 11FF 256
호환용 한글 자모 (Hangul Compatibility Jamo) 3130 318F 96
한글 자모 확장 A (Hangul Jamo Extended A) A960 A97F 32
한글 소리 마디 (Hangul Syllables) AC00 D7AF 11184
한글 자모 확장 B (Hangul Jamo Extended B) D7B0 D7FF 80

해당 범위는 Naver D2 한글 인코딩의 이해 2편 을 참고했습니다.

프로그램 진입점:

줄랭으로 만든 프로그램의 기본 진입점은 '시작' 함수입니다. 이 함수는 반드시 리턴 타입이 '수' 여야 하고, 매개 변수는 아무 의미가 없습니다. 추후에 포인터와 배열을 제대로 지원하게 되면 프로그램 인수를 받을 수 있도록 수정될 것입니다.

IR코드 또는 비트코드 파일로 컴파일하는 경우에는 C언어와의 호환성을 위해 '시작' 함수의 이름을 main으로 바꾸는 것으로 진입점을 설정합니다.

이미 main이라는 이름을 가진 함수가 있다면, 그 함수의 이름을 다른 것으로 바꿔버리기 때문에 충돌이 나진 않습니다. 하지만 main이라는 이름을 가진 함수를 정의하는 것은 별로 권장되는 행위는 아닙니다.

추가로 C언어의 main함수가 그러하듯, 시작 함수는 반환 구문을 작성하지 않아도 자동으로 0을 반환하는 구문이 삽입됩니다.