다오 (프로그래밍 언어)

다오()는 객체 지향 스크립트 언어이다. 복잡합 자료 구조를 지원하는 동적 타이핑 변수(dynamically typed variables)를 지원한다. 정규 표현식 매칭 같은 텍스트 처리 기능이 들어가 있다. 복소수, 다차원 배열 및 그것에 맞는 연산 등 여러 다양한 자료형을 언어 자체에서 지원한다.  다오는 또한 자체적으로 멀티 스레드 프로그래밍을 지원한다.

다오 인터프린터는 가볍고 효율적인 가상 레지스터(register) 머신 (Dao VM) 형태로 구현되어 있으며, C로 구현되어 있다. 간단하고 평이한 인터페이스를 통해 C 혹은 C++ 과 같이 확장되어 사용될 수 있다. 

다오의 특징은 다음과 같다:

 정적 그리고 동적 형체계(type system)을 섞어서 지원. 자동 형 유추 기능.
 유연한 매크로 체계. 새로운 문법 정의 가능.
 동시적이며(Concurrent) 분산된(distributed) 프로그래밍. 메시지 전달 인터페이스 제공.
 다오 프로그램에 C 코드를 직접 포함(embedding) 가능

기초

Hello World

Hello world 프로그램을 다오를 써서 작성해보면 다음과 같다.

 stdio.print ( "Hello world!" )

여기서 stdio는 입출력을 처리하는 표준 라이브러리이다. 다오에는 내장 함수(built-in function)이 없다. 모든 함수는 어떤 라이브러리의 일부이다. 예를 들면, stdio, stdlib, math, coroutine, reflect, mpi (message passing interface), network, 그리고 thread 같은 것들이다.

프로그래머는 stdlib.listmath 루틴을 사용하여 라이브러리 내의 메소드들을 출력해볼 수 있다. 예를 들면, math의 메소드들은 다음과 같이 하면 출력된다.
  stdlib.listmath ( math )

자료형 

다오의 변수는 암묵적으로(implicitly) 선언된다. 어떤 익스프레션의 결과를 대입하면 선언된다.

  a_number = 123
  a_string = "abc"
  a_list = { 1, 2, 3 }
  a_hash = { "CD"=>123, "AB"=>456 }
  a_vector = [ 1, 2, 3 ]
  a_matrix = [ 1, 2; 3, 4 ]

기본적으로, 변수는 변수를 선언하는 데 쓰인 익스프레션에서 다오 인터프린터가 유추해낸 형을 갖게 된다. 사람들은 이러한 타이핑을 암묵적 타이핑(implicit typing)이라고 부른다. 프로그래머는 변수의 형을 명시적으로 정의할 수 있는데, 다음과 같이 파스칼 (프로그래밍 언어) 비슷한 문법을 쓰면 된다.

  var_typed : type
  var_typed : type = value

type 자리에는 다음과 같은 내장 형(type)들이 들어갈 수 있다. int, float, double, string, complex, list, hash, array, buffer, routine 같은 것들이다.
혹은 이들의 조합 중 일부가 들어갈 수 있다.

예:

  a_list2 : list<list<float> >
  a_list3 : list<list<string> > = {}
  a_hash2 : hash<string,int> = { "ABC"=>123 }

type 자리에는 다오 클래스 이름이 들어갈 수도 있으며, 사용자가 정의한 C 형(type)의 이름이 들어갈 수 있다. 이른바 "무엇이든 형"(any type)에는 any 키워드를 쓴다. , 정의 안 된 형(undefined types)에는 ?를 쓴다. 

형이 결정된(typed) 변수는 다오 인터프리터 측에서 정적 형 검사(static checking)을 해준다.

제어 

If-Elif-Else:

  a = math.rand();
  if( a > 0.75 ){
     a -= 0.75
  }elif( a > 0.5 ){
     a -= 0.5
  }else{
     a -= 0.25
  }

While:

  i = 0;
  while( i < 10 ) i++

For:

  for( i=0; i<10; i++ ) stdio.println( i )
  for( i=0 : 9 ) stdio.println( i )
  for( i=0 : 2 : 9 ) stdio.println( i )

For-in:

  a_list = { 1, 2, 3 }
  for( it in a_list ) stdio.println( it )
  a_list2 = { "a", "b", "c" }
  for( it in a_list; it2 in a_list2 ) stdio.println( it, it2 )

For-in 구문은 해시(hash)에도 쓸 수 있다.

Switch

  a = "abc"
  switch( a ){
    case 1 : a += 123;
    case "abc" : a += "456"
    default : stdio.println( "default case" )
  }

함수 

다오에서는 기본적인 함수를 "루틴"(routine)이라고 부른다. 기본적인 함수는 다음과 같은 모양새를 갖는다.

  routine foo( a, b : string, c = 123 ) => int
  {
     return 456;
  }

다오는 일차 함수(first-order functions)를 지원한다. 보통의 함수 정의와 정의 방식은 똑같다. 하지만 다음과 같은 차이점을 갖는다.
 함수 이름을 꼭 써 줄 필요가 없다. 하지만 생성한 함수는 꼭 변수에 할당하여야 한다.
 기본값(the default value) 식(expressions)은 상수 식(constant expressions)일 필요가 없다. 런타임에 함수가 생성될 때, 계산된다.
 함수 바디(body)는 그 함수를 생성해주는 "상위" 함수에서 정의하고 있는 변수들을 포함할 수 있다.

  a = "ABC";
  rout = routine( x, y : string, z = a+a ){
     a += "_abc";
     stdio.println( "lambda ", a )
     stdio.println( "lambda ", y )
     stdio.println( "lambda ", z )
  }
  rout( 1, "XXX" );

클래스

  class MyNumber( value = 0 )
  {
    private
    my Value = 0; # default value is zero
    Value = value;
    public
    routine setValue( value : int ){ Value = value }
    routine getValue(){ return Value }
  }

매크로

프로그래머는 다오 매크로를 다음과 같이 정의할 수 있다.

  syntax{
    source_syntax_pattern
  }as{
    target_syntax_pattern
  }

"while-do-end"를 {} 괄호 없이 쓰면 다음과 같다.

  syntax{
     while $EXP do \[ $BL \] end
  }as{
     while( $EXP ){ \[ $BL \] }
  }

동시적이며(Concurrent) 분산된(distributed) 프로그래밍

비동기 함수 호출 

다오에서 멀티 스레드 프로그램을 만드는 가장 쉬운 방법은 아마도 비동기 함수 호출(AFC)일 것이다. 비동기 함수 호출은 동기 함수 호출과 매우 비슷하다. 끝에 키워드 async를 붙이면 된다.

  myfunc( myparams ) async;
  myobj.mymeth( myparams ) async;

모든 함수들은 이와 같은 방식으로 비동기 방식 호출이 가능하다.

보통, AFC는 상호 다른 네이티브 스레드 상에서 실행된다. 스레드 풀 중에서 사용 가능한 아이들(idle) 스레드일 수 있고, 그때그때 생성된 새 스레드 일 수도 있다.

외부 링크 
  Dao Language
  Daoscript

스크립트 언어
가상 머신