문법

Haxe에서는 모든 표현식이 같은 레벨을 갖습니다. 따라서 표현식들이 서로를 포함하는 재귀적인 관계를 가져도 아무런 문제가 되지 않습니다. 예를 들어서 foo(if (x == 3) 5 else 8)은 유효한 Haxe 표현식입니다. 이 예제가 보여주듯이 모든 표현식은 주어진 타입의 값을 반환합니다.

상수

다음과 같은 상수값들을 사용할 수 있습니다 :

    0; // Int
    -134; // Int
    0xFF00; // Int

    123.0; // Float
    .14179; // Float
    13e50; // Float
    -1e-99; // Float

    "hello"; // String
    "hello \"world\" !"; // String
    'hello "world" !'; // String

    true; // Bool
    false; // Bool

    null; // Unknown<0>

    ~/[a-z]+/i; // EReg : 정규 표현식

null은 아무런 타입에나 사용될 수 있는 특별한 값입니다. Dynamic 타입과는 다르게 조금 특이하게 작동하는데 이 부분에 대해서는 타입 추론에서 다루겠습니다.

연산자

다음의 연산자들을 사용할 수 있습니다. 연산자 우선순위로 정렬되어있습니다 :

  • 단항 연산자( 아래 세션을 보세요 ).
  • e1 % e2 : 두 숫자의 나머지를 반환합니다. 반환형은 빼기 연산과 동일합니다.
  • e1 / e2 : 두 숫자를 나눕니다. Float형을 반환합니다.
  • e1 * e2 : 두 숫자를 곱합니다. 반환형은 빼기 연산과 동일합니다.
  • e1 - e2 : 두 IntFloat형 표현식 간의 빼기 연산을 수행합니다. 두 표현식이 Int형일 경우 Int형을 반환하고 둘 중 하나라도 Float형일 경우 Float형을 반환합니다.
  • e1 + e2 : 더하기 연산을 수행합니다. 두 표현식이 정수형이라면 Int형을 반환하고 하나가 Float거나 둘 다 Float형이라면 Float형을 반환하고 그 외의 경우는 String형을 반환합니다.
  • << >> >>> : 두 정수 표현식의 비트 시프트 연산을 처리합니다. Int형을 반환합니다.
  • | & ^ : 두 정수 표현식의 비트 연산을 처리합니다. Int형을 반환합니다.
  • == != > < >= <= : 두 표현식을 비교합니다. Bool형을 반환합니다.
  • e1...e2 : 정수형 반복자를 생성합니다. 반복자에서 자세히 다루겠습니다.
  • e1 && e2 : 만약 e1false라면 false를 반환하고 그렇지 않으면 e2의 값을 반환합니다. e1e2는 둘 다 Bool형이어야 합니다.
  • e1 || e2 : 만약 e1true라면 true를 반환하고 그렇지 않으면 e2의 값을 반환합니다. e1e2는 둘 다 Bool형이어야 합니다.
  • += -= *= /= %= &= |= ^= <<= >>= >>>= : 좌항과 우항을 전치 연산자로 먼저 처리한 결과로 좌항에 대입연산을 수행합니다.
  • v = e : 표현식에 값을 대입합니다. e를 반환합니다.

참고 : 연산자 결합에 관해서는 여기서 알아볼 수 있습니다.

단항 연산자

다음의 단항연산자들을 사용할 수 있습니다 :

  • ! : not 부울연산을 수행합니다. Bool형 값을 갖는 표현식을 뒤집습니다.
  • - : 숫자를 반전시킵니다. IntFloat형 값의 부호를 바꿉니다.
  • ++--는 표현식의 앞이나 뒤에 올 수 있습니다. 앞에 작성할 경우 먼저 값을 증가시킨 다음 그 값을 반환합니다. 뒤에 작성할 경우엔 값을 증가시키지만 증가시키기 전의 값을 반환합니다. IntFloat형에만 사용할 수 있습니다.
  • ~ : Int형의 1의 보수를 반환합니다.

참고 : ~는 언제나 32비트 정수형에 사용됩니다. 따라서 Neko 31비트 정수형에서는 제대로 작동하지 않습니다.

괄호

표현식은 괄호로 인해 연산자 우선순위 처리에서 빠져나올 수 있습니다. ( e )의 타입은 e와 같고 똑같은 값을 표현합니다.

블록

블록은 여러 표현식을 실행할 수 있습니다. 블록의 문법은 다음과 같습니다 :

    {
        e1;
        e2;
        // ...
        eX;
    }

블록은 블록의 마지막 표현식의 값과 타입을 표현합니다. 다음의 코드를 보세요 :

    { f(); x = 124; true; }

이 블록은 Bool타입을 갖고 true값을 표현합니다.

{ }처럼 비어있는 블록은 예외적으로 Void형을 표현합니다.

지역변수

지역변수는 블록 안쪽에서 var를 이용하여 선언될 수 있습니다. 다음의 코드를 보세요 :

    {
        var x;
        var y = 3;
        var z : String;
        var w : String = "";
        var a, b : Bool, c : Int = 0;
    }

변수는 선택적으로 타입과 초기값을 정의할 수 있습니다. 만약 값이 주어지지 않을 경우 변수는 기본으로 null 값을 갖습니다. 아무런 타입이 주어지지 않을 경우 변수의 타입은 Unknown이지만 엄격한 타입검사가 적용됩니다. 이 부분에 대해서는 타입 추론에서 설명하겠습니다.

하나의 var 표현식으로 여러 지역변수를 선언할 수 있습니다.

지역변수는 블록 안에서만 정의될 수 있으며 닫혀있습니다. 지역변수들은 선언된 블록의 바깥쪽에서 접근될 수 없습니다( 즉, Haxe는 어휘 스코핑을 합니다 ).

식별자

식별자가 발견되면 다음의 순서로 해석됩니다 :

  • 최근에 선언된 지역변수
  • 클래스 멤버 ( 현재 클래스의 멤버들과 상속받은 필드 )
  • 현재 클래스의 정적 필드
  • 현재 파일에 선언 혹은 import된 enum 생성자
    enum Axis {
        x;
        y;
        z;
    }

    class C {
        static var x : Int;
        var x : Int;

        function new() {
            {
               // 여기서 x는 this.x를 뜻합니다.
                var x : String;
                // 여기서 x는 윗 줄의 x를 뜻합니다.
            }
        }

        function f(x : String) {
            // 여기서 x는 매개변수로 들어온 x를 뜻합니다.
        }

        static function f() {
            // 여기서 x는 정적변수 C.x를 뜻합니다.
        }
    }

    class D {
        function new() {
            // 여기서 x는 x Axis를 뜻합니다.
        }
    }

타입 식별자는 포함된 패키지에 따라 해석됩니다. 자세한건 후에 다루겠습니다.

필드 접근

객체 접근은 전통적인 점( 마침표 ) 표기법을 사용합니다 :

    o.field

호출

함수는 괄호를 사용하여 호출하고 콤마를 이용하여 인자를 분리할 수 있습니다. 다음과 같이 마침표로 객체에 접근하여 메서드를 호출할 수 있습니다 :

    f(1,2,3);
    object.method(1,2,3);

New

new 키워드가 사용된 표현식은 새로운 클래스 인스턴트를 생성합니다. 클래스명이 뒤에 오며 매개변수를 집어넣을 수 있습니다 :

    a = new Array();
    s = new String("hello");

배열

다음과 같은 문법을 이용하여 값들의 목록을 즉시 배열로 만들어낼 수 있습니다 :

    var a : Array<Int> = [1,2,3,4];

Array 타입은 배열 안에 들어갈 타입을 결정하는 타입 인자를 받는다는 걸 명심하세요. 타입 인자를 받으면 배열의 모든 항목이 같은 타입을 갖는다는 장점이 있습니다.

다음과 같이 대괄호로 접근하여 배열의 값을 읽고 쓸 수도 있습니다 :

    first = a[0];
    a[1] = value;

배열 인덱스는 Int형이어야 합니다.

If

아래 코드는 if 표현식의 예제입니다 :

    if (life == 0) destroy();
    if (flag) 1 else 2;

아래 코드는 일반적인 if 표현식의 문법입니다 :

    if( expr-cond ) expr-1 [else expr-2]

먼저 expr-cond가 처리됩니다. 이 값은 무조건 Bool형이어야 합니다. 그 값이 참일 경우 expr-1이 처리되고, 그렇지 않을경우 expr-2가 처리됩니다.

if 표현식은 false인데 else가 없을 경우에 반환되는 값은 Void형을 갖습니다. 만약 else가 있다면 expr-1expr-2는 같은 타입을 가질 것이고 이 것이 if 표현식의 타입이 됩니다 :

    var x : Void = if( flag ) destroy();
    var y : Int = if( flag ) 1 else 2;

Haxe에서 if는 C에서의 a?b:c( 삼항연산자 ) 문법과 비슷합니다.

만약 if 블록이 어떠한 값을 반환하기 위한 블록이 아니라면( 여러 표현식이 들어있다면 ) expr-1expr-2는 서로 다른 타입을 가져도 되고 그 때 if 블록의 타입은 Void가 됩니다.

While

while문은 선조건이나 후조건을 이용해서 반복연산을 수행할 수 있습니다 :

    while( expr-cond ) expr-loop;
    do expr-loop while( expr-cond );

while문은 다음과 같이 사용합니다 :

    var i = 0;
    while( i < 10 ) {
        // ...
        i++;
    }

do...while문은 다음과 같이 사용합니다 :

    var i = 0;
    do {
        // ...
        i++;
    } while( i < 10 );

if문 처럼 while문 안의 expr-cond는 무조건 Bool형이어야 합니다.

다음은 10부터 1까지 반복연산을 수행하는 예제입니다 :

    var i = 10;
    while( i > 0 ) {
    .......
    i--;
    }

For

Haxe의 for문은 C의 for문과 약간 다릅니다. 나중에 다루겠지만 Haxe에서는 반복자 라는 것을 씁니다. 아래 코드는 for문 예제입니다 :

    for( i in 0...a.length ) {
        foo(a[i]);
    }

Return

함수의 중간에 빠져나오거나 값을 반환하기 위해 return 표현식을 사용할 수 있습니다 :

    function odd( x : Int ) : Bool {
        if( x % 2 != 0 )
            return true;
        return false;
    }

return 표현식은 함수가 값을 반환할 필요가 없을 때는 인자를 안 받아도 됩니다 :

    function foo() : Void {
        // ...
        if( abort )
            return;
        // ....
    }

Break와 Continue

이 두 키워드는 forwhile문에서 루프를 중간에 빠져나오거나 다음 루프로 넘어가기 위해 사용됩니다 :

    var i = 0;
    while( i < 10 ) {
        if( i == 7 )
            continue; // 현 루프의 문장들을 더이상 실행하지 않고 반복자의 다음 순서로 넘어갑니다. ''while''문의 경우는 표현식을 다시 검사합니다.
        if( flag )
            break; // 루프를 조기에 중단합니다.
    }

예외

예외는 전역 점프를 하기 위해 사용합니다. 스택의 아무 함수에서나 예외를 throw 시킬 수 있고 catch 해낼 수 있습니다 :

    function foo() {
        // ...
        throw "invalid foo";
    }

    // ...

    try {
        foo();
    } catch( e : String ) {
        // 예외 처리
    }

try문 뒤에는 서로 다른 타입의 예외 catch를 하기 위해 여러개의 catch문이 올 수 있습니다. 각각의 catch문은 그들에게 선언된 타입의 에러를 잡아냅니다. Dynamic 타입은 모든 예외를 잡아냅니다 :

    try {
        foo();
    } catch( e : String ) {
        // String 타입의 에러 처리
    } catch( e : Error ) {
        // Error 타입의 에러 처리
    } catch( e : Dynamic ) {
        // 모든 종류의 에러 처리
    }

trycatch 표현식은 ( if문 처럼 )아무런 값이 필요하지 않은 경우를 제외하고 무조건 같은 타입을 반환합니다.
더 자세한 내용은 예외를 보면 됩니다.

Switch

switch문은 같은 값을 처리하는 여러 if...elseif...else if... 문들을 표현하고 싶을 때 사용합니다 :

    if( v == 0 )
        e1
    else if( v == foo(1) )
        e2
    else if( v == 65 || v == 90 )
        e3
    else
        e4;

위의 코드를 switch문으로 아래와 같이 바꿀 수 있습니다 :

    switch( v ) {
    case 0:
        e1;
    case foo(1):
        e2;
    case 65, 90:
        e3;
    default:
        e4;
    }

참고 : 위의 예제에서 65, 90이라고 쓰인 부분을 보세요. 이런 식으로 여러가지 상황을 하나의 명령으로 묶어서 처리하고 싶을 때에 상황을 콤마로 구분합니다.

Haxeswitch문은 전통적인 switch문들과는 약간 다릅니다. 모든 case문은 분리된 표현식으로 처리되므로 하나의 case가 처리되면 자동적으로 switch 블록에서 빠져나오게 됩니다. 따라서 switch문에서 break문은 필요하지 않으며 default 케이스의 위치는 별로 중요하지 않습니다.

일부 플랫폼에서 switch문에 ( 특히 정수형 )상수값이 들어가면 최적화에 도움이 됩니다.

switch문은 enum을 다룰 때는 다른 의미를 갖습니다. 이 부분에 대해서는 후에 다루겠습니다.

지역함수

지역함수는 function 키워드로 선언될 수 있지만 이름을 가질 수는 없습니다. 지역함수는 리터럴 정수나 문자열과 같은 입니다 :

    var f = function() { /* ... */ };
    f(); // 위의 함수를 호출합니다.

지역함수는 매개변수에 접근할 수 있습니다. 현 클래스의 정적 멤버나 지역변수들은 다음과 같이 사용되곤 했습니다 :

    var x = 10;
    var add = function(n) { x += n; };
    add(2);
    add(3);
    // now x is 15

하지만 메서드에 선언된 지역함수는 this 값에 접근할 수 없습니다. 지역함수는 아래 코드의 me 같은 지역변수만 사용할 수 있습니다 :

    class C {

        var x : Int;

        function f() {
            // 다음은 컴파일될 수 없는 코드입니다.
            var add = function(n) { this.x += n; };
        }

        function f2() {

            // 다음은 컴파일될 수 있는 코드입니다.
            var me = this;
            var add = function(n) { me.x += n; };
        }
    }

익명 객체

익명 객체는 다음의 문법으로 선언될 수 있습니다 :

    var o = { age : 26, name : "Tom" };

익명 객체도 엄격한 타입검사가 적용됩니다. 자세한 내용은 타입 추론에서 다루겠습니다.

«« 기초 타입 - 타입 추론 »»

version #14063, modified 2012-05-20 12:03:38 by disjukr