KR100287061B1 - 로토스 자료 명세로부터 객체지향 프로그램의 자동 생성 방법및 이를 위한 코드 생성기 - Google Patents

로토스 자료 명세로부터 객체지향 프로그램의 자동 생성 방법및 이를 위한 코드 생성기 Download PDF

Info

Publication number
KR100287061B1
KR100287061B1 KR1019980052022A KR19980052022A KR100287061B1 KR 100287061 B1 KR100287061 B1 KR 100287061B1 KR 1019980052022 A KR1019980052022 A KR 1019980052022A KR 19980052022 A KR19980052022 A KR 19980052022A KR 100287061 B1 KR100287061 B1 KR 100287061B1
Authority
KR
South Korea
Prior art keywords
lotos
operator
class
code
oriented program
Prior art date
Application number
KR1019980052022A
Other languages
English (en)
Other versions
KR20000034648A (ko
Inventor
천윤식
오영배
김흥남
Original Assignee
정선종
한국전자통신연구원
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by 정선종, 한국전자통신연구원 filed Critical 정선종
Priority to KR1019980052022A priority Critical patent/KR100287061B1/ko
Publication of KR20000034648A publication Critical patent/KR20000034648A/ko
Application granted granted Critical
Publication of KR100287061B1 publication Critical patent/KR100287061B1/ko

Links

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F8/00Arrangements for software engineering
    • G06F8/30Creation or generation of source code
    • G06F8/33Intelligent editors
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F8/00Arrangements for software engineering
    • G06F8/20Software design
    • G06F8/24Object-oriented

Landscapes

  • Engineering & Computer Science (AREA)
  • Software Systems (AREA)
  • General Engineering & Computer Science (AREA)
  • Theoretical Computer Science (AREA)
  • Physics & Mathematics (AREA)
  • General Physics & Mathematics (AREA)
  • Stored Programmes (AREA)

Abstract

본 발명은 LOTOS(Language of Temporal Ordering Specification) 자료 명세로부터 객체지향 프로그램의 자동 생성 방법 및 이를 위한 코드 생성기에 관한 것이다.
본 발명에서는 LOTOS 자료 명세로부터 객체지향 프로그램을 생성하기 위한 다수의 모듈로 구성된 핵심층과, 사용자 지향적인 GUI를 제공하며, 파일 검색, 소스 코드 보기, 오류 출력 및 환경 설정등의 기능을 제공하는 사용자 접속층과, 상기 핵심층의 모듈간 또는 상기 상위층과의 통신 채널을 제공하고, 자료 코드의 생성, 프로토 타입의 생성 및 실행 기능을 수행하며, 상기 핵심층의 모듈들을 동적으로 배치 및 연결하는 관리층으로 이루어진 코드 생성기를 이용하여 LOTOS 자료 명세로부터 중간 코드를 생성하고, 이 중간 코드를 통해 객체지향 프로그램을 생성한다.
본 발명에 의하면 산업계에서 실제 적용하여 소프트웨어 개발의 생산성과 개발된 소프트웨어의 품질 향상에 지대한 기여를 할 것으로 기대된다.

Description

로토스 자료 명세로부터 객체지향 프로그램의 자동 생성 방법 및 이를 위한 코드 생성기
본 발명은 정형 명세 언어인 일시적 순서 기술 언어(Language of Temporal Ordering Specification: 이하 LOTOS라 함)로 기술된 자료 명세로부터 객체지향 프로그램의 자동 생성 방법에 관한 것으로, 특히 LOTOS 자료 명세로부터 C++ 구현 프로그램의 자동 생성 방법 및 그 지원 도구에 관한 것이다.
LOTOS는 개방형 분산 시스템의 서비스와 프로토콜을 명세하기 위하여 국제표준화기구(International Organization for Standardization; ISO)에서 개발한 정형 명세 언어이다. LOTOS는 시스템이 외부와 일으키는 상호 작용의 시간적 순서를 정의함으로써 시스템을 명세한다. 이를 위하여 CCS(Calculus of Communicating Systems)와 CSP(Communicating Sequential Processes)를 합성한 프로세스 논리(Process Algebra)를 사용한다. 상호작용시 자료가 교환될 수 있는데, 교환되는 자료를 표현하기 위하여 대수 방식의 정형 명세 언어 ACT ONE를 사용한다. 따라서 LOTOS는 자료와 제어의 상호 보완적인 명세를 위하여 ACT ONE과 CCS/CSP라는 두 정형 명세 언어를 결합한 것이다.
코드 생성이라 함은 주어진 명세로부터 이를 만족하는 프로그램을 기계적으로 생성하는 것을 말한다. 코드 생성의 가장 큰 목적은 명세의 동작 모형이다. 명세를 실제 실행해 봄으로써 다양한 형태로 명세의 특성을 검사하고 분석할 수 있고, 명세의 작동 상황을 가시화할 수도 있다. 명세의 동작 모형이 실제 구현 언어로 주어진다면, 실제 구현에도 사용할 수 있다. 최근 경향은 코드 생성을 기반으로 명세의 검증 및 증명 도구를 개발하는 추세이다. 따라서 코드 생성은 정형 지원 도구의 핵심 모듈로 사용될 수 있다.
대부분의 코드 생성기는 프롤로그(Prolog)나 SML(Standard Meta Language)과 같은 논리 언어나 함수 언어를 사용한다. 하지만 단순한 동작 모형이 아니라 산업계 개발자가 실제 사용하기 위해서는 프로그래밍 언어 C나 C++와 같은 실제 구현 언어로 주어져야 한다.
현재 C를 지원하는 도구는 프랑스 INRIA(The French National Institute for Research in Computer Science and Control)에서 개발한 Caesar.ADT와 스페인 마드리드(Madrid) 대학에서 개발한 TOPO가 있다. Caesar.ADT는 패턴 매칭 기반의 정적 컴파일을 통하여 빠른 코드 생성이 가능하며, 생성된 코드의 효율성도 높은 것으로 평가되고 있다. 그러나, 생성된 프로그램의 조율과 수작업 코드와 연계가 어렵다는 단점이 있다. TOPO는 모듈성, 확장성, 이식성이 뛰어나고 다양한 부가 기능을 제공하며, PC 환경에서도 사용 가능하다는 장점이 있다. 하지만 아직까지 C++를 지원하는 도구는 개발 되지 않고 있다.
많은 개발자가 C++로 이동하는 추세일 뿐만 아니라 C++가 제공하는 객체 지향 개념은 코드 생성에 많은 혜택을 줄 것으로 기대된다. 예를 들면, 생성된 코드의 모듈화, 재사용, 상속을 통한 조율과 수작업 코드와 연계 등을 들 수 있다.
따라서, 본 발명은 C 언어를 지원하는 종래의 기술에 의해 자동 생성된 코드가 읽기 힘들 뿐만 아니라 모듈성, 확장성, 이식성이 부족한 문제점을 해결하기 위하여 LOTOS 자료 명세로부터 실행 가능한 C++ 구현 프로그램을 자동으로 생성하는 방법을 제공하는데 그 목적이 있다.
상술한 목적을 달성하기 위한 본 발명에 따른 LOTOS 자료 명세로부터 객체지향 프로그램의 자동 생성을 위한 코드 생성기는 LOTOS 자료 명세로부터 코드 생성을 위한 기능을 제공하기 위한 다수의 모듈으로 구성된 핵심층과, 사용자 지향적인 GUI를 제공하며, 파일 검색, 소스 코드 보기, 오류 출력 및 환경 설정등의 기능을 제공하는 사용자 접속층과, 상기 핵심층의 모듈간 또는 상기 상위층과의 통신 채널을 제공하고, 자료 코드의 생성, 프로토 타입의 생성 및 실행 기능을 수행하며, 상기 핵심층의 모듈들을 동적으로 배치 및 연결하는 관리층을 포함하여 이루어진 것을 특징으로 한다.
또한, 상술한 목적을 달성하기 위한 본 발명에 따른 LOTOS 자료 명세로부터 객체지향 프로그램의 자동 생성 방법은 LOTOS 자료 명세의 문법을 검사한 후 추상 문법 트리를 생성하는 단계와, 상기 문법이 검사된 상기 LOTOS 자료 명세를 구성하는 타입을 검사하는 단계와, 상기 문법 및 타입이 검사된 LOTOS 자료 명세에 대하여 주석을 처리하는 단계와, 상기 문법 검사, 타입 검사 및 주석 처리가 완료된 LOTOS 자료 명세로부터 중간 코드를 생성하는 단계와, 상기 중간 코드로부터 객체지향 프로그램의 헤더 및 소스를 생성하는 단계를 포함하여 이루어진 것을 특징으로 한다.
또한, 상술한 목적을 달성하기 위한 본 발명은 LOTOS 자료 명세의 문법을 검사하고 그 결과에 따라 추상 문법 트리를 생성하기 위한 수단과, 상기 문법 검사가 완료된 상기 LOTOS 자료 명세를 구성하는 타입을 검사하기 위한 수단과, 상기 문법 및 타입 검사가 완료된 LOTOS 자료 명세에 대하여 주석을 처리하기 위한 수단과, 상기 문법 검사, 타입 검사 및 주석 처리가 완료된 LOTOS 자료 명세로부터 중간 코드를 생성하기 위한 수단과, 상기 중간 코드를 일반 객체와 주석 객체로 구성하여 코러스 계층 구조로 표현하기 위한 수단과, 상기 중간 코드의 소트 및 연산자 선언 부분으로부터 객체지향 프로그램의 헤더 파일을 생성하기 위한 수단과, 상기 중간 코드의 연산자 정의 부분으로부터 객체지향 프로그램의 소스 파일을 생성하기 위한 수단을 기능시키기 위한 프로그램을 기록한 컴퓨터로 읽을 수 있는 기록매체인 것을 특징으로 한다.
도 1은 본 발명에 따른 자동 생성된 C++ 프로그램을 지원하기 위한 커널 모듈의 구조도.
도 2는 본 발명에 따른 LOTOS 자료 명세의 추상 값을 C++ 자료 구조로 표현한 예시도.
도 3은 본 발명에 따른 LOTOS 자료 명세의 C++ 프로그램으로의 변환 규칙을 적용한 예시도.
도 4는 본 발명에 따른 C++ 코드 생성기의 구조도.
도 5는 본 발명에 따른 C++ 구현 프로그램을 생성하는 과정을 설명하기 위한 흐름도.
도 6은 본 발명에 따른 중간 코드의 C++ 변환을 위한 추상 문법 트리의 객체도.
도 7은 본 발명에 따른 중간 코드의 C++ 변환을 위한 주석의 객체도.
도 8은 본 발명에 따른 중간 코드의 C++ 변환을 위한 자료 흐름도.
도 9는 본 발명에 따른 프로세스 gen_header의 정의를 나타내는 자료 흐름도.
도 10은 본 발명에 따른 프로세스 gen_source의 정의를 나타내는 자료 흐름도.
도 11은 본 발명에 따른 프로세스 trn_srt_dcls의 정의를 나타내는 자료 흐름도.
도 12는 본 발명에 따른 프로세스 trn_opn_dcls의 정의를 나타내는 자료 흐름도.
도 13은 본 발명에 따른 프로세스 trn_opn_dfns의 정의를 나타내는 자료 흐름도.
도 14는 본 발명에 따른 프로세스 gc_cns_dfn의 정의를 나타내는 자료 흐름도.
도 15는 본 발명에 따른 프로세스 gc_cns_rules의 정의를 나타내는 자료 흐름도.
도 16은 본 발명에 따른 프로세스 gc_cns_build의 정의를 나타내는 자료 흐름도.
도 17은 본 발명에 따른 프로세스 gc_opn_dfn의 정의를 나타내는 자료 흐름도.
도 18은 본 발명에 따른 프로세스 gc_opn_rules의 정의를 나타내는 자료 흐름도.
도 19는 본 발명에 따른 프로세스 gc_pat의 정의를 나타내는 자료 흐름도.
도 20은 본 발명에 따른 프로세스 gc_match의 정의를 나타내는 자료 흐름도.
도 21은 본 발명에 따른 프로세스 gc_cond의 정의를 나타내는 자료 흐름도.
도 22는 본 발명에 따른 프로세스 gc_eval의 정의를 나타내는 자료 흐름도.
도 23은 본 발명에 따른 프로세스 gc_repl의 정의를 나타내는 자료 흐름도.
도 24는 본 발명에 따른 프로세스 gc_opn_build의 정의를 나타내는 자료 흐름도.
본 발명에서는 종래의 기술에 의해 자동 생성된 코드가 읽기 힘들 뿐만 아니라 모듈성, 확장성, 이식성이 부족한 문제점을 해결하기 위하여 C++의 객체 지향 개념을 사용하여 LOTOS 자료 명세를 C++ 프로그램으로 변환하는 방법을 제안한다. 이를 위하여 다음과 같은 기술적인 문제를 해결하고자 한다.
1. 생성되는 C++ 프로그램의 양식과 지원 라이브러리 제안
2. LOTOS 자료 명세를 C++ 프로그램으로 변환하는 규칙 제안
3. LOTOS 자료 명세로부터 C++ 프로그램의 생성 절차 제안
4. 코드 생성을 위한 내부 표현법인 중간 코드로부터 C++ 코드를 생성하는 방법 제안
5. LOTOS 자료 명세로부터 C++ 프로그램을 생성하는 지원 도구 시스템의 제안
이하, 첨부된 도면 및 표를 이용하여 본 발명을 상세히 설명하기로 한다.
1. 코드 생성 원리
[표 1]은 LOTOS 자료 명세에 관한 간단한 예이다.
type Stack is Boolean, Naturalsort Stackopns empty:-〉 Stack push: Stack, Nat-〉 Stack pop: Stack-〉 Stack top: Stack-〉 Nat isempty: Stack-〉 Booleqns forall s: Stack, n, m: Nat ofsort Nat top(push(s,n))=n; ofsort Stack pop(push(s,n)=s; pop(empty)=empty; ofsort Bool isempty(empty)=true; isempty(push(s,n))=false;endtype
일반적으로 자료 명세는 소트 정의, 연산자 정의, 자료 등식의 세 부분으로 구성된다. 먼저 추상 값의 집합을 나타내는 소트를 정의하고 연산자라 불리는 소트상에 정의된 전칭 함수를 정의한다. 전통적으로 대수 명세에서는 타입을 소트라 부른다. 연산자의 의미는 연산자 상호 관계를 등식으로 서술한다. LOTOS 자료 명세의 수학 모형은 다종 대수(many-sorted algebra)이다. 특히, 초기 의미론(initial semantics)을 갖는데, 이는 수학적으로 잘 정립되었으나 명세의 실행 모형으로 사용될 수 없다. 따라서 텀 개서 시스템(term rewrite system; TRS)을 사용한다. 명세의 등식으로부터 개서 규칙을 도출하고 개서 규칙에 따라 텀을 개서한다. 예를 들면, [표 1]의 자료 명세에서 연산자 pop를 제약하는 두 등식은 [표 2]과 같은 개서 규칙으로 변환할 수 있다.
pop(push(s,n))→spop(empty)→empty
개서 시스템은 등식에 종속적인 컴파일 방법으로 구현할 수 있다. 예를 들면, 소트 Stack을 C++ 클래스 Stack으로 구현한다고 가정할 때, 연산자 pop는 [표 3]과 같은 형태의 C++ 멤버 함수로 구현할 수 있다.
CVRef은 자동 생성된 프로그램에서 동적 메모리를 자동으로 관리하기 위한 주형(template) 클래스이다(도 1 참조). 예에서 switch 문장은 pop 연산자에 적용 가능한 모든 개서 규칙을 케이스 분석 방식으로 구현한다.
2. 생성되는 C++ 프로그램의 양식
생성되는 C++ 프로그램은 어떤 양식을 가져야 하는가? 구문적인 측면에서 보면, 소트는 C++ 클래스로 구현하고 연산자는 기본적으로 해당 클래스의 멤버 함수로 구현한다. 예를 들면, 앞 절의 Stack 명세는 [표 4]와 같은 C++ 헤더 파일을 생성한다.
CVRef〈Stack〉Stack::pop(){ CVRef〈Stack〉_v; switch (this-〉oid(){ case 15:/*push*/ _v=((Stack*)this-〉arg()-〉val.deref()); break; case 14:/*empty*/ _v=empty(); bteak; } if(!_v){ KLink *_s1; _s1=new KLine(this); _v = new Stack(16,_s1); }return_v;
CVRef〈Stack〉empty();class Stack: public KSort{public: Stack(int oid = 0,KLine*p = (KLine*)NULL): KSort(oid,p){} CVRef〈Bool〉 isempty(); CVRef〈Nat〉 top(); CVRef〈Stack〉 pop(); CVRef〈Stack〉 push(const CVRef〈Nat〉&);};
따라서 LOTOS 자료 명세의 값 표현식 pop(push(empty,0))은 [표 5]와 같은 C++ 문장으로 번역되어야 한다.
CVRef〈Stack〉 s = empty()-〉push(zero())-〉pop();
위 예에서 보는 것과 같이 프로그램 모듈화를 위해 생성된 모든 클래스는 커널 클래스라 불리는 시스템 클래스 KSort의 서브 클래스로 정의한다(도 1 참조). 따라서 실행 가능한 완전한 C++ 프로그램은 자동 생성 코드와 커널 클래스가 결합된 형태이다. 커널은 생성된 모든 클래스의 공통된 특성을 정의한다.
2.1 커널 모듈의 구성
도 1은 커널 모듈이라 불리는 자동 생성된 C++ 프로그램을 지원하기 위한 시스템 클래스로 구성된 C++ 클래스 라이브러리이다. 사용자 측면에서 커널 클래스는 크게 XSort, KSort, USort의 세 개의 클래스로 구성된다. 커널 클래스 KSort는 자동 생성된 모든 클래스의 공통된 특성을 정의하며, USort는 자동 생성된 클래스와 수작업 클래스의 인터페이스를 위한 프로토콜과 서비스를 정의한다. 커널 클래스 XSort는 KSort와 USort의 공통 특성을 추상화 한 추상 클래스이다. 커널 클래스는 추상 값의 표현을 위하여 KLink, OpnInfo와 같은 클래스를 사용한다(도 2의 추상 표현의 예 참조). 마지막으로 시스템 클래스 CVRef은 자동 생성된 C++ 프로그램에서 동적 메모리를 자동으로 관리하기 위한 주형(template) 클래스이다.
커널 클래스 KSort는 XSort의 서브 클래스로 자동 생성된 모든 C++가 가져야 하는 특성을 정의한다. 예를 들면, 추상 값을 구현하기 위한 자료 구조라던지 이를 조작하기 위한 함수를 제공한다. 특히, 내부 자료 구조의 초기화, 대수 명세의 초기 모형(initial model) 구현, 추상 값의 스트링 변환, 동적 메모리 할당과 같은 서비스를 정의한다. 커널 클래스 USort는 자동 생성 코드와 수작업 코드의 연계를 위한 메커니즘과 서비스를 제공한다. 예를 들면, 수작업 클래스의 자료 구조에 대한 관습과 기능에 관한 프로토콜을 정의한다. 모든 수작업 클래스는 커널 클래스 USort의 서브 클래스로 구현되어야 한다. 코드 생성이 소프트웨어 개발에 실질적으로 사용되기 위해서는 생성된 코드를 부분적으로 조율하고 대치하고 기존 혹은 수작업 코드와 연계하여 작동할 수 있어야 한다. 또한 수정 첨가되는 코드는 모듈화 되어 유지 보수 관리가 용이하여야 한다. 예를 들면, 코드를 재생성할 때 수정 첨가된 코드를 재작업할 필요가 없어야 한다. 객체 지향의 상속 개념은 함수와 클래스 단위로 자동 생성 코드를 정제하고 일부분을 대치할 수 있도록 한다. 커널 클래스 USort가 이러한 서비스를 제공한다.
2.2 추상 값 표현
LOTOS 자료 명세의 추상 값(abstract value)을 어떻게 C++의 구체 값(concrete value)으로 표현할 것인가? LOTOS와 같은 대수 명세에서 추상 값은 값 표현식 즉, 해당 소트를 결과 소트로 갖는 연산자의 적용으로 표현된다. 예를 들면, push(push(empty,0),0)은 소트 Stack이라는 집합에 속하는 추상 값을 나타낸다. 추상 자료 값을 구현하는 방법은 다양하나 본 발명에서는 추상 구문 트리(abstract syntax tree; AST) 표현 방식을 사용한다. 도 2는 추상 값 push(push(empty,0),0)를 C++ 자료 구조를 사용하여 구체 값으로 구현한 예이다. 도 2의 왼편은 추상 문법 트리를 나타내고 오른편은 이를 C++ 자료 구조를 사용하여 커널 모듈에서 구현한 예이다. 추상 값의 표현을 위해 모든 연산자에 연산자 식별자(operation identification number)라는 고유 번호가 부여된다. 추상 문법 트리 구축을 위한 자료 구조와 관련 함수는 커널에 정의되며, 생성된 모든 클래스는 커널 클래스의 서브클래스로 정의되어 이를 상속 받는다.
3. LOTOS 자료 명세의 C++ 변환 규칙
LOTOS 명세의 C++ 프로그램으로의 정확한 변환 규칙은 다음과 같다. 아래 규칙은 LOTOS 자료 명세의 구성 요소인 소트와 연산자가 C++의 어떤 구성 요소로 구현되는가에 대한 규칙을 정의한다(규칙 적용의 예는 도 3 참조).
규칙 1 : LOTOS 자료 명세의 소트는 C++의 클래스로 변환된다. 소트를 구현하는 C++ 클래스를 구현 클래스라 부른다. 구현 클래스의 이름은 이름(Name) 주석으로 주어질 수 있다. 이름 주석이 첨부되지 않으면 시스템이 생성한 고유한 이름, 예를 들면, s1, s2,… 등이 사용된다.
규칙 2 : 자료 명세의 연산자는 기본적으로 C++ 구현 클래스의 멤버 함수로 변환된다(예외: 규칙 2.1 참조). 연산자를 구현하는 C++ 함수를 구현 함수라고 부른다. 구현 함수의 이름은 이름 주석으로 주어질 수 있는데, 이름 주석이 생략되면 시스템에서 자동 생성한 고유한 이름, 예를 들면, g1, g2,… 등이 사용된다.
규칙 2.1 : 자료 명세의 생성 연산자(constructor) 중 입력 매개 값을 하나도 갖지 않은 기본 생성자는 C++의 독립(stand-alone) 함수로 변환된다.
규칙 2.2 : 입력 매개 값을 하나 이상 갖는 연산자는 일반적으로 첫 번째 입력 매개 소트에 해당하는 C++ 구현 클래스의 멤버 함수로 변환된다(예외: 규칙 2.4 참조).
규칙 2.3 : 연산자의 삽입(infix)성은 해당 구현 함수의 이름에 의하여 결정된다. 즉, 선언된 삽입 연산자 중 이름 주석으로 주어진 구현 함수의 이름이 특수 기호일 경우 해당 연산자는 C++의 연산자(operator)로 변환된다. 그 밖의 경우에는 일반 멤버 함수로 변환된다. 구현 함수의 이름이 시스템에 의하여 자동 생성되었을 경우에도 동일한 규칙이 적용된다.
규칙 2.4 : C++의 연산자(operator)로 변환되는 모든 연산자는 해당 클래스의 멤버 함수가 아니라 독립 프렌드(friend) 함수로 구현된다. C++에서 이진 연산자(operator)는 하나의 매개 값을 갖는 비정적(non-static) 멤버 함수나 두 개의 매개 값을 갖는 비멤버 함수로 선언될 수 있다. 예를 들어, 연산자 +: nat, nat -〉 nat의 경우, nat 클래스의 멤버 함수 nat operator+(nat)으로 구현될 수도 있고, 혹은 독립 함수 nat operator+(nat,nat)으로 구현될 수도 있다. 하지만 자동 생성된 코드에서는 매개 값의 타입이 CVRef〈nat〉이어야 하므로, operator+는 nat의 멤버 함수가 될 수 없다.
4. 코드 생성기의 구조
도 4는 C++ 코드 생성기의 기본 구조를 나타낸다. 코드 생성기는 핵심층(Core Layer), 관리층(Manager Layer), 사용자 접속층(GUI Layer)의 3개의 층으로 구성된다. 가장 하위 층인 핵심층은 코드 생성에 필요한 기본적인 기능을 제공한다. 예를 들면, LOTOS 명세의 구문 및 타입 검사, 주석(Annotation) 처리, LOTOS 명세의 중간 코드로의 변환, 중간 코드의 C++ 변환 등의 기능을 제공한다. 이들 기능은 외부 실행 파일 형태의 독립 모듈로 제공된다. 관리층은 코드 생성기의 총괄 관리자의 역할을 수행하며 핵심층의 모듈간 혹은 상위층과의 통신 채널을 제공한다. 상위층에서 요구하는 서비스를 제공하기 위하여 핵심층의 모듈들을 동적으로 배치 및 연결한다. 대표적인 기능은 C++ 코드의 생성과 프로토타입의 생성 및 실행이다. 가장 상위층인 사용자 접속층은 편리하고 사용자 지향적인 GUI(Graphical User Interface)를 제공하며 파일 검색, 소스 코드 보기, 환경 설정 등과 같은 부가적인 기능도 수행한다.
도 5에서 보는 것과 같이 코드 생성은 크게 구문 및 타입 검사, 중간 코드 생성, C++ 변환의 세 단계를 거쳐서 일어난다. 즉, 명세를 직접 C++ 코드로 변환하는 것이 아니라 먼저 중간 코드를 생성하고, 생성된 중간 코드를 C++ 프로그램으로 변환한다. 중간 코드는 LOTOS 자료 명세를 코드 생성에 편리한 형태로 변환한 형태이다. 기술적으로는 텀 개서 시스템(Term Rewrite System; TRS)을 중간 코드로 사용한다. 중간 코드의 사용은 시스템 개발을 모듈화할 뿐만 아니라 잘 정의된 인터페이스를 통하여 상호 작용하므로 수정, 갱신, 확장성이 뛰어나고 유지 보수가 용이하다. 예를 들면, 자바(Java) 언어를 지원하기 위해서는 중간 코드로부터 자바(Java)로의 변환 모듈만 개발하면 된다. 도 5에서 주석 처리 모듈은 구현 종속적인 사항을 명세하기 위하여 LOTOS 명세에 첨가되는 주석이라 불리는 특수한 코멘트를 처리한다(주석의 예는 도 3 참조). 주석은 어휘 관습과 같은 단순한 구문적인 요소에서부터 부분 구현과 같은 의미적인 요소까지 명세할 수 있다. 도 5에서 보는 것과 같이 생성되는 C++ 프로그램은 헤더 파일과 소스 파일로 분할된다.
5. 중간 코드의 C++ 변환
5.1 중간 코드 양식
중간 코드는 코드 생성의 두 과정, 즉 LOTOS 명세로부터 개서 시스템의 도출과 개서 시스템의 프로그램화의 교량 역할을 한다. 두 과정은 중간 코드를 통하여 상호 인터페이스한다. 첫 단계에서는 중간 코드가 생성되어 외부 파일에 저장되고, 두 번째 단계에서는 저장된 외부 파일을 읽어 들인다. 중간 코드는 순수한 ASCII 파일로 저장된다. 예를 들어, [표 6]과 같은 LOTOS 자료 명세의 일부를 가정하자.
sorts natopns 0: -〉 nat succ: nat -〉 nat
이에 해당하는 중간 코드는 [표 7] 및 [표 8]과 같다. [표 7]은 시스템에서 생성된 ASCII 형태의 실제 중간 코드이고, [표 8]은 이를 읽기 쉽게 표현한 것이다.
a 1# natb s1 -1 nat gcd 2# 0:-〉 nate g1 1 0 g -1 0# succ: nat-〉 nate g3 3 succ g -1 1 -1f
BEGIN_SORTS_DECL 1 # nat SORT_DECL s1 -1 nat DEFINEDEND_SORTS_DECLBEGIN_OPERATION_DECL 2 # 0:-〉 nat OPERATION_DECL g1 1 0 DEFINED -1 0 # succ: nat-〉 nat OPERATION_DECL g3 3 succ DEFINED -1 1 -1END_OPERATION_DECL
[표 9a] 및 [표 9b]는 중간 코드의 양식을 나타낸다. 양식 칼럼에서 n, s, t는 각각 숫자, 스트링, 텍스트를 나타낸다. 주석을 제외한다면 중간 코드는 소트 선언, 연산자 선언, 연산자 정의의 세 부분으로 구성된다. 소트 선언 부분은 LOTOS 명세의 sorts절에 해당하는 중간 코드이고, 연산자 선언 부분은 opns절에 해당하고, 연산자 정의 부분은 eqns절에 해당한다.
소트 선언(SORT_DECL)은 명세된 소트에 관한 사항을 나열한다. 즉, 선언된 소트 이름, 소트 식별자, 해당 C++ 클래스 이름, 코드 생성 유무 등의 정보를 나타낸다. 소트 선언은 주석이 첨부될 수 있는데, free, equal, draw, parse의 네 가지 종류가 있다.
연산자 선언(OPERATIONS_DECL)은 소트 선언 다음에 오며 LOTOS 자료 명세에 나타나는 모든 자료 연산자에 대한 여러 가지 구문적 정보를 제공한다. 예를 들면, 구현 함수, 연산자 식별자, 연산자 이름, 코드 생성 유무, 결과 소트, 차수(arity), 입력 소트 등이다. 선언된 연산자의 이진성에 관해서는 삽입(infix) 주석으로 첨부되며, 호출(call) 주석은 연산자 이름에 첨부되어 해당하는 구현 함수가 생성되지 않는 대신 첨부된 C++ 표현식이 불려짐을 명세한다.
연산자 정의(OPERATION_DEF)는 선언된 연산자의 의미, 즉 연산자에 관한 개서 규칙을 정의하며, 헤더 부분과 의미 정의 부분으로 나눌 수 있다. 헤더 부분은 연산자 선언과 유사하며 의미 정의 부분은 개서 규칙을 정의한다. 헤더는 C++ 구현 함수의 헤더를 생성하는데 필요한 정보를 제공하고, 의미 정의 부분은 구현 함수의 본문을 생성하는데 필요한 정보를 제공한다. 연산자는 구축(BUILD), 개서(REWRITE), 일반(GENERAL)으로 분류된다. 구축(BUILD)은 연산자가 기본 생성자이며, 더 이상 개서할 수 없는 정규 값을 나타낸다는 뜻이고, 개서(REWRITE)는 연산자가 나타내는 값은 개서될 수 있다는 의미이다. 일반(GENERAL)은 입력 값의 형태에 따라 구축(BUILD)과 개서(REWRITE)의 특성을 모두 가질 수 있다는 뜻이다.
연산자의 의미를 정의하는 규칙(RULE)은 개서 규칙을 코드 생성에 편리한 형태로 표기한 것으로, 입력 매개 값의 형태 혹은 패턴(PATTERN), 입력 값이 만족해야 할 조건(CONDITION), 결과 값, 즉 개서된 값을 나타내는 대치(REPLACEMENT)로 구성된다. 패턴은 연산자 매치와 값 매치로 구성된다. 조건(CONDITION)은 입력 매개 값이 만족해야 할 사항을 나타내며, 규칙 정의에서 패턴 다음에 오는 선택 사항이다. 대치(REPLACEMENT)는 개서 규칙(l→r)의 우측 편(r)에 해당하며, 개서된 값을 나타낸다. 구현 함수의 입장에서 보면 함수 호출의 결과 값이다. 연산자 평가(OPERATION_EVAL)는 조건과 대치에 사용되는데, 해당 연산자를 가장 상위 연산자로 가지는 LOTOS 자료 표현식을 나타낸다. 값 평가(VALUE_EVAL)는 조건과 대치에 사용되며, LOTOS 자료 표현식에서 특정한 서브 표현식, 일반적으로 변수를 나타낸다. 연산자 정의의 맨 마지막에 오는 선택 사항인 값 구축(BUILD)은 해당 연산자가 더 이상 개서될 수 없음을 나타낸다.
5.2 자료 구조
C++ 변환의 가장 핵심적인 자료 구조는 입력 중간 파일의 파싱과 C++ 코드 생성의 교량 역할을 하는 추상 문법 트리(abstract syntax tree; AST)이다. 추상 문법 트리는 외부 ASCII 파일로 입력되는 중간 코드를 코드 생성에 편리한 내부 자료 구조로 표현한 것이다. 즉, 파서에서 생성된 파서 트리(parse tree)에서 불필요한 내부 노드들을 제거한 것이다. 본 발명에서는 트리의 각 노드를 객체로 정의하고 C++ 변환 알고리즘을 노드 객체의 멤버 함수로 정의한다. 추상 문법 트리 객체를 그 기능과 역할에 따라 일반 객체와 주석 객체로 나눈다.
이름 코드 양식
BEGIN_SORTS_DECL SORT_DECLEND_SOETS_DECL abc a nb s n s nc
BEGIN_OPERATIONS_DECL OPERATIONS_DECLEND_OPERATIONS_DECL def d ne s n s s n [n…]c
DEFINEDIMPORTED gh gh
BEGIN_OPERATIONS_DEF BEGIN_RULE BEGIN_PATTERN OPERATION_MATCH VALUE_MATCH END_PATTERN BEGIN_CONDITION END_CONDITION BEGIN_REPLACEMENT OPERATION_EVAL VALUE_EVAL END_REPLADEMENT END_RULE BUILDEND_OPERATION_DEF Ijklmnopqrstuvw I s s n [n…]j nk n nl n n [n…]m n [n…]nopqr s n n [n…]s n [n…]tuv n nw
REWRITEGERERAL xy xy
EQUAL z z
COMMENTBEGIN_COMMENTEND_COMMENTANNOTATIONBEGIN_ANNOTATIONEND_ANNOTATIONLINE_QUOTE #[]!{}% # t[]! s n s | t{}%
LDC_ANNOTATIONDRAW_ANNOTATIONPARSE_ANNOTATIONEQUAL_ANNOTATIONFREE_ANNOTATIONPARTIAL_ANNOTATIONFAIL_ANNOTATIONRULE_ANNOTATIONSORT_ANNOTATIONLDCINIT_ANNOTATIONINFIX_ANNOTATIONLDCEND_ANNOTATIONCALL_ANNOTATION ABCDEFGHIJKLM ABCDEFGHIJKLM
도 6은 추상 문법 트리의 노드 객체를 나타낸다. 추상 문법 트리는 중간 코드 양식을 반영한다. 중간 코드는 크게 연산자 선언, 연산자 정의로 구성된다. 따라서 중간 코드를 나타내는 클래스 CVN_LDM은 크게 CVN_SortDecl, CVN_OpnDecl, CVN_OpnDef의 합성으로 정의된다. 소트 선언전에 코드 변환 전반에 관한 사항을 명세하는 LDC 관련 주석이 선택적으로 올 수 있다. LDC 관련 주석에는 LDC, LDCInit, LDCEnd의 세 종류가 있으며, 각 종류의 주석은 최대한 한번 사용될 수 있다. LDC 관련 주석을 나타내는 클래스 CVN_LDCRelAnt는 도 7을 참조하기 바란다.
클래스 CVN_SortDecl은 소트 선언을 나타내며, 최대한 4개의 소트 관련 주석 CVN_SortRelAnt를 가질 수 있다. CVN_SortDecl 객체는 선언된 소트에 관한 여러 정보, 예를 들면, 선언된 소트 이름, 소트 식별자, 해당 C++ 클래스 이름, 코드 생성 유무등을 제공한다. 객체도에서 보는 바와 같이 중간 코드는 하나 이상의 소트 선언을 가진다.
연산자 선언은 클래스 CVN_OpnDecl으로 모형화하는데, LOTOS 자료 명세에 나타나는 모든 자료 연산자에 대한 여러 가지 구문적 정보를 제공한다. 예를 들면, 선언된 연산자의 이름, 서명(signature), 구현 함수 등을 들 수 있다. 연산자에 관한 의미론적 정보는 클래스 CVN_OpnDef에 의해 제공된다. 연산자 선언은 LOTOS 자료 명세의 opns절로부터 생성된다. CVN_OpnDecl 객체는 call 주석(CVN_CallAnt)과 infix 주석(CVN_InfixAnt)을 구성 요소로 가질 수 있다. 해당 주석에 관해서는 도 7을 참조하기 바란다.
클래스 CVN_Opn_Def로 모형화되는 연산자 정의는 선언된 연산자의 의미를 표현한다. 즉, 중간 코드로 표현되는 개서 시스템의 개서 규칙에 관한 정보를 제공한다. 클래스 CVN_Opn_Def는 하나 이상의 규칙과 선택 사항인 구축과 일부(Partial) 주석으로 구성된다. 이들은 각각 클래스 CVN_Rule, CVN_Build, CVN_PtlAnt로 모형화 한다. 값 구축은 해당 연산자가 더이상 개서될 수 없는 값을 나타낸다는 것을 의미한다. 즉, 더이상 개서될 수 없는 정규 값(normal term)을 나타낸다. 클래스 CVN_Build은 선택적으로 Fail 주석을 나타내는 클래스 CVN_FailAnt를 구성 요소로 가질 수 있다.
중간 코드 규칙을 나타내는 CVN_Rule 객체는 개서 시스템의 개서 규칙을 코드 생성에 편리한 형태로 표기한 것이다. 규칙은 입력 매개 값의 형태 혹은 패턴, 입력 값이 만족해야 할 조건, 결과 값, 즉 개서된 값을 나타내는 대치로 구성된다. 패턴이란 개서 가능한 자료 표현식의 형태를 말한다. 즉, 자료 연산자의 구현 함수 측면에서 보면 입력 매개 값의 형태를 말한다. 패턴은 클래스 CVN_Pattern으로 모형화하는데, 입력 매개 값의 형태를 정의하는 매치의 열로 구성된다. 매치는 클래스 CVN_Match로 모형화하는데, 연산자 매치 CVN_OpnMatch와 값 매치 CVN_ValMatch로 구체화되는 추상 클래스이다. 연산자 매치는 입력 매개 변수가 자료 연산자로 구성되는 특정한 형태의 자료 표현식임을 나타내고, 값 매치는 그러한 형태가 아님을 나타낸다.
조건은 입력 매개 값들이 만족해야 할 사항을 나타내는 선택 사항이다. 반면, 대치는 개서 규칙(l→r)의 우측 편(r)에 해당하며 개서된 값을 나타낸다. 즉, 구현 함수의 입장에서 보면 함수 호출의 결과 값이다. 조건과 패턴은 동일한 구조를 갖는다. 즉, 평가를 나타내는 추상 클래스 CVN_Eval의 합성 클래스이다. CVN_Eval은 클래스 CVN_OpnEval과 CVN_ValEval로 구체화된다. 연산자 평가를 나타내는 클래스 CVN_OpnEval은 명세된 자료 연산자를 가장 상위 연산자로 가지는 자료 표현식을 나타낸다. 일반적으로 연산자 평가는 연산자 이름과 해당 연산자의 차수로 구성된다. 값 평가를 나타내는 클래스 CVN_ValEval은 자료 표현식에서 특정한 서브 표현식-일반적으로 변수-를 나타내는데 사용된다. 클래스 CVN_ValEval은 선택 사항인 Sort 주석을 가질 수 있는데, 이는 해당 객체가 나타내는 값의 소트를 명세 한다. 소트 주석은 클래스 CVN_SortAnt로 모형화한다.
자료 컴파일러는 정상적인 LOTOS 명세 뿐만 아니라 주석이라는 특수한 형태의 코멘트를 포함한 명세도 입력으로 받아들인다. 주석은 추상적인 LOTOS 명세에 구현 종속적인 사항을 추가한다. 예를 들면, 임의의 LOTOS 연산자에 대하여 생성되는 C++ 함수의 이름을 명세한다던지 혹은 해당 C++ 함수는 자동적으로 생성되지 않고 사용자에 의하여 수작업으로 작성된다던지 하는 사항을 명세할 수 있다. 도 7은 추상 문법 트리에 나타날 수 있는 주석의 클래스 계층도을 보여 주고 있다. 그림에서 리프(leaf)에 해당하는 클래스만 구체 클래스이고 나머지는 추상 클래스이다. 모든 주석 클래스는 궁극적으로 추상 클래스 CVN_Ant의 서브 클래스이다. 주석은 크게 두 가지 종류로 분류할 수 있다. 중간 코드 파일에서 한 줄에 모두 명세되는 것과 여러 줄에 걸쳐서 명세되는 것이다. 전자는 클래스 CVN_InlineAnt로 모형화하고 후자는 CVN_MultilineAnt로 모형화한다. 구문적 표현법이 다르다는 것을 제외하면 의미에 있어서는 별다른 차이가 없다. CVN_InlineAnt의 특성을 가지는 주석은 CVN_InfixAnt, CVN_FailAnt, CVN_SortAnt가 있다.
클래스 CVN_InfixAnt는 infix 주석을 정의한다. Infix 주석은 연산자 선언에 나타나며 선언된 연산자가 infix 연산자임을 나타낸다. LOTOS에서는 명세의 간결성을 위하여 연산자 이름과 함께 매개 변수의 위치로-예를 들어, _ne_- 연산자의 infix 특성을 나타내지만, 중간 코드에서는 조작의 편의를 위해 주석을 사용한다. 클래스 CVN_FailAnt는 중간 코드의 fail 주석을 모형화한다. Fail 주석은 값 구축에 첨부되는데, 해당 연산자가 생성자가 아니므로 값을 구축할 수 없다는 것을 나타내며, 오류 메시지 출력을 위한 정보를 제공한다. 마지막으로 CVN_SortAnt는 중간 코드의 sort 주석을 모형화한다. Sort 주석은 값 평가를 선행하는데, 다음에 오는 값 평가의 소트를 나타낸다.
추상 클래스 CVN_MultilineAnt는 4개의 서브 클래스를 가진다. 추상 클래스 CVN_LDCRelAnt, CVN_SortRelAnt와 구체 클래스 CVN_PtlAnt, CVN_CallAnt이다. 먼저 추상 클래스 CVN_LDCRelAnt는 자료 컴파일 전반에 관한 사항을 명세하는 LDC 관련 주석을 모형화한다. LDC 관련 주석에는 LDC, LDCInit, LDCEnd의 세 종류가 있으며, 각각 구체 클래스 CVN_LDCAnt, CVN_LDCInitAnt, CVN_EndAnt로 모형화한다. LDC와 LDCEnd 주석은 해당 C++ 코드를 각각 결과 파일 ldc.hpp와 ldc.cpp에 그대로 복사한다. LDCInit 주석은 수작업으로 구현된 소트의 상수나 자료 구조를 초기화하기 위하여 사용된다.
클래스 CVN_PtlAnt는 중간 코드의 partial 주석을 나타낸다. Partial 주석은 연산자 이름에 첨부되며, 해당 연산자가 호출될 때 관련된 C++ 표현식을 실행하도록 한다. 시스템이 실행을 계속하기 위해서는 실행의 결과가 참 값, 즉 0이 아니어야 한다. 만약 결과 값이 0이면, 실행시 예외 상황이 일어난다.
클래스 CVN_CallAnt는 중간 코드의 call 주석을 모형화한다. Call 주석은 연산자 이름에 첨부되어 해당하는 구현 함수가 생성되지 않는 대신 첨부된 C++ 표현식이 불려짐을 명세한다.
마지막으로 클래스 CVN_SortRelAnt는 중간 코드의 소트 관련 주석을 나타내는 추상 클래스이다. 소트 관련 주석은 소트 선언에 주석이 첨부되는데, 소트 관련 주석은 해당 소트의 구현이 사용자에 의해 제공될 때, 소트 객체를 조작하기 위한 여러 함수의 이름을 명세한다. 소트 관련 주석은 free, equal, draw, parse의 네 가지 종류가 있다. 각각은 구체 클래스 CVN_FreeAnt, CVN_EqualAnt, CVN_DrawAnt, CVN_ParseAnt로 모형화한다. 주석 free는 해당 소트 객체에 할당된 메모리를 시스템에 되돌려 주는 함수 이름을 명세한다. 즉, 동적 메모리 할당에 관련된 함수를 명세한다. 주석 equal은 해당 소트에 속하는 두 객체가 동일한 값을 나타내는지를 판단하는 함수 이름을 명세한다. 즉, 명세된 함수는 자료형 대수 명세의 초기 모형(initial model)을 구현한다. 주석 draw와 parse는 각각 해당 소트의 값을 스트링으로 변환과 역변환할 수 있는 함수 이름을 명세한다. 즉, 명세된 두 함수는 해당 소트 값에 대한 입출력 함수이다.
5.3 변환 알고리즘
5.3.1 C++ 헤더 생성
도 8의 프로세스 gen_header는 C++ 헤더 파일을 생성한다. 헤더 파일에는 include문, 클래스 선언, 독립 함수 선언 등과 같은 정보가 포함된다. 도 9는 프로세스 gen_header를 좀더 상세히 나타낸 것이다. 헤더 파일을 생성하는데 필요한 모든 정보는 중간 코드의 LDC 주석, 소트 선언, 연산자 선언에 포함되어 있다. 따라서 다른 중간 코드 구성 요소는 프로세스 gen_header에 의해 무시된다. 사용되는 중간 코드 구성 요소는 각각 추상 문법 트리의 노드를 나타내는 객체 CVN_LDCAnt, CVN_SortDecl, CVN_OpnDecl로 표현된다(도 6 참조). 프로세스 gen_header는 합성된 각각의 객체를 처리하기 위한 서브프로세스, C++ 헤더 파일 생성을 초기화하고 종결하기 위한 서브프로세스, 내부 저장소 관리를 위한 서브프로세스로 구성된다. 각 서브프로세스의 기능과 역할은 다음과 같다.
프로세스 trn_init_hdr : 단위 프로세스로 C++ 헤더 파일 생성을 초기화한다. 예를 들면, 필요한 시스템 헤더 파일을 include하고 내부 변수나 자료 구조(dcl_tbl)를 초기화한다.
프로세스 trn_ldc_ant : LDC 주석을 처리하는 프로세스로 LDC 주석을 결과 파일인 헤더 파일에 그대로 복사한다. 참고로, 유사한 기능을 하는 LDC 관련 주석 LDCInit과 LDCEnd는 무시되는데, 이는 C++ 소스 파일을 생성하는 프로세스 gen_source에 의해 사용된다.
프로세스 trn_srt_dcls_hdr : 중간 코드의 소트 선언 부분에 해당하는 객체 CVN_SortDecl를 입력으로 받아들여 클래스와 함수 선언 정보를 저장하는 저장소 dcl_tbl에 저장한다. 입력 객체인 CVN_SortDecl은 선언된 소트에 관한 여러 가지 정보(소트 이름, 소트 식별자, 구현 클래스 이름, 코드 생성 유무)를 제공한다. 소트에 관한 모든 정보가 dcl_tbl 저장된다. 저장소 dcl_tbl은 소트 정보와 연산자 정보를 취합하여 어떤 연산자 어떤 클래스의 멤버 함수로 구현되는가에 대한 정보를 생성하는 역할을 한다(도 trn_opn_dcls_hdr 참조).
프로세스 trn_opn_dcls_hdr : 중간 코드의 연산자 선언 부분을 처리한다. 즉, 선언된 모든 연산자에 관한 정보를 제공하는 CVN_OpnDecl 객체를 입력으로 받아 연산자 정보를 저장소 dcl_tbl에 저장한다. 또한 연산자가 독립 함수로 구현 될 것인지 아니면 멤버 함수로 구현될 것인지를 결정하여 dcl_tbl에 저장한다. 멤버 함수로 구현된다면, 이에 관한 정보가 해당 소트에 저장된다. 저장되는 연산자 정보는 다음과 같다. 연산자 이름, 연산자 식별자 번호, 구현 함수, 구현 클래스, 결과 소트, 차수(arity), 코드 자동 생성 유무, Infix 특성 등이다. 이들 대부분은 CVN_OpnDecl 객체로부터 수정없이 복사된다.
프로세스 prt_dcl_tbl : 저장소 dcl_tbl에 저장된 클래스 선언과 독립 함수 선언을 표현하는 C++ 문장을 헤더 파일에 출력한다. 클래스 선언과 독립 함수 선언에 대한 정보는 소트 선언과 연산자 선언으로부터 서브프로세스 trn_srt_dcls_hdr와 trn_opn_dcls_hdr에 의해 생성된다.
프로세스 trn_end_header : 단위 프로세스로 헤더 파일 생성을 종료한다.
5.3.2 C++ 소스 생성
도 8의 프로세스 gen_source는 중간 코드의 내부 표현인 추상 문법 트리 객체(CVN_LDM)를 입력으로 받아 들여 이를 구현하는 C++ 소스 프로그램 파일을 생성한다. 소스 파일에 나타나는 클래스나 전역 변수 등은 프로세스 gen_header에 의해 생성된 헤더 파일에 선언된다. 프로세스 gen_source를 상세하게 나타내면 도 10과 같다.
입력 객체인 CVN_LDM은 LDC 관련 주석, 소트 선언, 연산자 선언, 연산자 정의를 나타내는 4개의 객체 CVN_SortRelAnt, CVN_SortDecl, CVN_OpnDecl, CVN_OpnDef로 합성되어 있다(표 9 참조). 따라서 프로세스 gen_source는 합성된 각각의 객체를 처리하기 위한 서브프로세스와 코드 생성을 초기화하고 종결하기 위한 두 프로세스로 구성된다. 서브 프로세스의 기능과 역할은 다음과 같다.
프로세스 trn_init : 단위 프로세스로 C++ 소스 파일 생성을 초기화한다. 예를 들면, 필요한 C++ 매크로를 정의하고 프로세스 gen_header에 의해 생성된 헤더 파일 ldc.hpp를 include한다.
프로세스 trn_ldcrel_ant : LDC 관련 주석을 처리하는데, LDC 주석은 무시하고, LDCInit 주석이나 LDCEnd 주석이 있으면 이에 해당하는 C++ 코드를 생성한다. LDC 주석은 헤더 파일 생성에 사용된다. LDC 관련 주석의 코드 생성은 아주 간단하다. 즉, 주석에 명세된 해당 C++ 코드를 소스 파일에 그대로 복사한다.
프로세스 trn_srt_dcls : 중간 코드의 소트 선언 부분에 해당하는 객체CVN_SortDecl를 입력으로 받아 이를 처리한다. 선언된 모든 소트에 관한 여러 정보들을 수집하여 소트 테이블(srt_tbl)로 만들고, 소트 테이블에 저장된 결과를 C++ 자료 구조 형식으로 표현하여 결과 파일에 출력한다. 생성된 소트 테이블은 프로세스 trn_opn_dfns에 의해 사용된다.
프로세스 trn_opn_dcls : 중간 코드의 연산자 선언 부분을 처리한다. 즉, 선언된 모든 연산자에 관한 정보를 담고있는 연산자 테이블(opn_tbl)를 구축하고, 이를 C++ 소스 파일에 출력한다. 연산자 테이블은 프로세스 trn_opn_dfns에 의해 사용된다.
프로세스 trn_opn_dfns : 코드 생성의 핵심으로 중간 코드의 연산자 정의 부분을 처리한다. 즉, 정의된 연산자를 구현하는 C++ 멤버 함수를 생성한다. 프로세스 trn_opn_dfns은 C++ 코드 생성을 위하여 소트 테이블과 연산자 테이블을 사용한다. 이 두 테이블은 소트와 연산자에 관한 독자적인 정보 뿐만 아니라 정의된 연산자가 어떤 클래스의 멤버 함수로 구현되어야 하는지에 대한 정보도 포함한다.
프로세스 trn_end : 단위 프로세스로 코드 생성을 종결한다.
참고로 각각의 서브프로세스에 의해 C++ 프로그램이 순차적으로 출력되기 때문에, 정의된 프로세스는 일정한 순서에 따라 호출되어야 한다. 즉, 프로세스 trn_init가 맨 처음 호출되어야 하고, trn_end는 맨 마지막에 호출되어야 한다. 프로세스 trn_srt_dcls과 trn_opn_dcls는 프로세스 trn_opn_dfns보다 먼저 호출되어야 한다. 마지막으로 프로세스 trn_ldcrel_ant는 trn_opn_dfns 이후에 그리고 trn_end 이전에 호출되어야 한다.
5.3.2.1 소트 선언 변환
도 11은 프로세스 trn_srt_dcls를 정의하는데, 선언된 모든 소트에 관한 정보를 저장하는 소트 테이블(srt_tbl)을 작성하고 이를 출력한다. 소트 테이블은 연산자 정의 부분의 변환시 사용된다. 핵심 자료 구조인 소트 테이블과 이를 생성하고 출력하기 위한 4개의 서브프로세스 init_srt_tbl, gen_srt_tbl, trn_srt_ant, prt_srt_tbl로 구성된다. 각 서브프로세스의 기능은 다음과 같다.
프로세스 init_srt_tbl : 소트 테이블을 초기화한다. 즉, 선언된 소트 개수 만큼의 소트 테이블 목록을 할당하고 초기 값을 설정한다.
프로세스 gen_srt_tbl : 소트 선언으로부터 소트 관련 정보를 추출하여 소트 테이블에 저장한다. 일반적으로 소트 선언에 나타나는 모든 정보가 소트 테이블에 저장된다. 예를 들면, 선언된 모든 소트에 관하여 소트 이름, 소트 식별자 번호 (sort identification number), 구현 클래스 이름, 코드 생성 여부와 소트 코멘트와 같은 정보이다.
프로세스 trn_srt_ant : 소트 선언 중 소트 관련 주석을 처리한다. 소트 관련 주석은 클래스 CVN_SortRelAnt와 해당 서브 클래스의 객체로 표현된다(도 7 참조). 소트 관련 주석은 소트를 구현하는 C++ 프로그램이 자동 생성되지 않고 사용자에 의해 제공될 때, 소트 객체를 조작하기 위한 여러 함수의 이름을 명세한다. 즉, free, equal, draw, parse 함수이다. 프로세스 trn_srt_ant는 해당 함수의 이름을 소트 테이블에 등록한다.
프로세스 prt_srt_tbl : 소트 테이블을 C++ 문장으로 출력한다. 소트 정보는 생성된 C++ 프로그램의 구동시 사용된다. 소트 정보를 생성된 모든 소트 객체가 조회 할 수 있도록 커널 클래스 USort의 static 변수로 저장한다. 예를 들면, 아래의 LOTOS 소트 선언 부분에 해당하는 C++ 소트 테이블의 정의는 [표 10] 및 [표 11]과 같다.
sorts nat, bool (*|extern|*)(*|nofree|*)(*|parse parse_bool|*) (*|equal equal_bool|*)(*|draw draw_bool|*)
unsigned USort::sort_tbl_size=3;tSORT_TBL USort::sort_tbl= {0, FALSE, NULL, NULL, NULL, NULL, NULL, NULL}, {1, FALSE, "nat", "s1", NULL, NULL, NULL, NULL}, {2, TRUE, "bool", "s2", NULL, equal_bool, draw_bool, parse_bool}};
5.3.2.2 연산자 선언 변환
도 12는 프로세스 trn_opn_dcls를 정의한다. 프로세스 trn_opn_decls는 연산자 선언 부분을 처리하는데, trn_srt_dcls과 유사한 기능을 수행한다. 즉, 선언된 모든 연산자에 관한 정보를 저장하는 연산자 테이블(opn_tbl)을 작성하고, 이를 C++ 문장으로 출력한다. 연산자 테이블은 소트 테이블과 함께 연산자 정의 부분의 변환과 생성된 C++ 프로그램의 구동시 사용된다. 핵심 자료 구조인 연산자 테이블과 이를 생성하고 출력하기 위한 5개의 서브프로세스로 구성된다.
프로세스 init_opn_tbl : 연산자 테이블을 초기화한다. 즉, 선언된 연산자 개수 만큼의 연산자 테이블 항목의 초기 값을 설정하고 기타 필요한 변수의 값을 초기화한다.
프로세스 gen_opn_tbl : 실제로 연산자 테이블에 저장될 값을 연산자 선언을 나타내는 객체 CVN_OpnDecl로부터 생성한다. 프로세스 gen_opn_tbl에 의해 저장되는 연산자 정보는 다음과 같다. 연산자 이름, 연산자 식별자 번호(operation identifier number), 구현 함수, 구현 클래스, 결과 소트, 차수(arity), 코드 자동 생성 유무, infix 특성 등이다. 대부분의 정보는 CVN_OpnDecl 객체로부터 변경없이 복사되나 몇몇 정보는 가공된다.
프로세스 trn_call_ant : 중간 코드의 call 주석은 연산자 선언에 첨부되어 해당 함수가 자동 생성되지 않으며, 대신 첨부된 C++ 표현식이 실행됨을 명세한다. 프로세스 trn_call_ant는 소트 테이블의 해당 연산자 항에 이러한 정보를 저장한다.
프로세스 prt_opn_tbl : 연산자 테이블을 정의하는 C++ 문장을 출력한다. 연산자 정보는 생성된 C++ 프로그램의 구동시 사용된다. 생성된 모든 객체가 조회할 수 있도록 커널 클래스 USort의 static 변수로 저장된다.
프로세스 prt_eval_opn : 프로세스 prt_eval_opn는 코드가 자동 생성되지 않는, 예를 들면, call 주석이 첨부된 함수를 구현하는 함수++를 생성한다. 선언된 함수를 대신하여 생성된 함수가 연산자 식별자와 해당 매개 값을 사용하여 호출된다.
5.3.2.3 연산자 정의 변환
코드 생성의 핵심이라고 할 수 있는 프로세스 trn_opn_dfns은 중간 코드의 연산자 정의 부분을 처리한다(도 13 참조). 즉, 연산자 정의 부분을 표현하는 객체 CVN_OpnDef를 입력으로 받아 이를 구현하는 C++ 함수를 생성한다. 연산자 정의 부분의 변환시 각각 프로세스 trn_srt_dcls과 trn_opn_dcls에 의해 생성된 소트 테이블과 연산자 테이블의 정보가 사용된다.
의미론적 측면에서 볼 때 임의의 소트에 속한 연산자는 생성자(constructor)와 관측자(observer)로 나눌 수 있다. 생성자는 특정한 소트에 속하는 추상 값을 나타낸다. 즉, 해당 소트의 값을 생성한다. 반면, 관측자는 해당 소트의 값을 나타내지 않고 다른 소트의 값을 나타낸다. 즉, 해당 소트의 값을 관측한 정보-즉, 다른 소트의 값을 나타낸다. 구문적 측면에서 보면, 생성자의 결과 소트는 해당 소트이며 관측자는 해당 소트를 입력 소트로 갖고 해당 소트 이외의 소트를 결과 소트로 갖는다. 예를 들어, 소트 nat의 입장에서 보면, 연산자 0:-〉 nat과 연산자 succ: nat -〉 nat은 생성자이다. 반면, 연산자 even: nat -〉 bool은 관측자이다. 생성자를 더욱 세분화하여 기본 생성자(basic constructor)와 확장 생성자(extended constructor)로 나눌 수 있다. 기본 생성자는 특정한 소트에 속하는 고유한 값- 즉, 정규 값을 나타낸다. 확장 생성자는 해당 소트의 정규 값을 나타내지 않으며, 기본 생성자로 표현될 수 있다. 예를 들어, 연산자 0와 succ은 소트 nat의 기본 생성자이다. 하지만 연산자 +: nat, nat -〉 nat은 확장 생성자이다. 즉, 가장 상위 연산자가 +인 모든 자료 표현식은 연산자 0과 succ으로 표현될 수 있다. 불행하게도 LOTOS에서는 구문적으로 기본 연산자와 확장 연산자를 구분할 수 없다. 이는 연산자의 의미-등식 규칙에 따라 분류된다. 하지만 LOTOS 자료 명세는 초기 의미론(initial semantics)을 채택하므로 차수(arity)가 0인 생성자는 기본 생성자이다.
연산자 정의로부터 이를 구현하는 C++ 함수를 생성하는 프로세스 trn_opn_dfns에 관한 상세한 정의는 도 13과 같다. 프로세스 trn_opn_dfns는 연산자를 기본 생성자와 일반 연산자로 구분하여 변환한다. 의미론에 바탕을 둔 엄격한 의미에서의 기본생성자가 아니라 차수가 0인 연산자를 말한다. 기본 생성자일 경우에는 프로세스 gc_cns_dfn에 의해 해당 코드가 생성되고 일반 연산자일 경우에는 프로세스 gc_opn_dfn에 의해 코드가 생성된다. 기본 생성자는 C++의 독립 함수(stand-alone function)으로 구현되고 일반 연산자는 클래스의 멤버 함수로 구현된다.
5.3.2.4 생성자 정의 변환
정의된 연산자가 차수가 0인 기본 생성자일 때 이는 도 14에 정의된 프로세스 gc_cns_dfn에 의해 처리된다. 프로세스 gc_cns_dfn은 2개의 단위 프로세스 prt_cns_dfn와 prt_ptl_ant 그리고 아래에서 상세하게 정의될 2개의 프로세스 gc_cns_rules와 gc_cns_build로 구성된다. 모든 프로세스는 소트 테이블의 정보를 사용하는데, 그 기능은 다음과 같다.
프로세스 prt_cns_dfn : 생성자 코드 생성의 초기화와 종결에 관련된 업무를 처리한다. 예를 들면, C++ 함수 정의의 헤더 부분을 생성하고 다른 서브 프로세스를 호출하고 코드 생성을 종결한다.
프로세스 prt_ptl_ant : Partial 주석은 해당 연산자가 호출될 때 명세된 C++ 표현식을 실행하도록 한다. 시스템이 실행을 계속하기 위해서는 실행의 결과가 참 값-즉, 0이 아니어야 한다. 만약 결과 값이 0이면, 실행시 예외 상황이 일어난다. 프로세스 prt_ptl_ant는 연산자 정의 부분에 partial 주석이 포함되었을 때 이를 처리한다. 즉, 명세된 C++ 표현식을 실행하고 결과 값이 0이면, 명세된 오류 정보를 사용하여 오류 메시지를 출력하도록 하는 C++ 문장을 출력한다. 예를 들어, 연산자 pred가 pred (*| partial $1-〉equal(zero()) |*) : nat -〉 nat와 같이 선언되었다면, 연산자 pred를 구현하는 C++ 함수의 시작 부분에 [표 12]와 같은 코드가 첨가 된다.(참고로 연산자 pred가 멤버 함수로 구현되기 때문에 첫 번째 매개 변수를 나타내는 $1은 C++ pseudo 변수 this로 번역된다.)
if(!(!this-〉equal(zero()))) { put_error("partial operation failure: (line 17 of file "example.lot\)\n"); put_error("name: pred\n"); put_error(arg 1: %s\n", this-〉draw()); exit(1);}
프로세스 gc_cns_rules : 코드 생성의 핵심 프로세스로 연산자 정의가 개서 규칙을 포함할 때 이를 C++의 switch와 case문으로 번역하여 출력한다. 자세한 사항은 그림~\ref{fig-gc-cns-rules과 해당 설명을 참조하기 바란다.
프로세스 gc_cns_build : 연산자 정의가 객체 CVN_Build로 표현되는 값 구축을 포함할 때, 이에 해당하는 C++ 문장을 출력한다. 값 구축의 처리시 프로세스 prt_cns_dfn에서 생성되는 논리 값 has_rules을 사용한다. 논리 값 has_rules는 연산자 정의가 개서 규칙을 포함하는지를 나타낸다. 프로세스 gc_cns_builds는 도 16을 참조하기 바란다.
도 15는 프로세스 gc_cns_dfn의 정의(도 14 참조)에 나타나는 서브프로세스 gc_cns_rules를 정제한 것이다. 일반적으로 중간 코드의 개서 규칙은 패턴, 조건, 대치로 구성되나 기본 생성자일 경우에는 패턴 부분이 없다. 따라서 프로세스 gc_cns_rules은 크게 조건과 대치를 처리하는 두개의 서브프로세스 prt_cond와 prt_repl로 구성된다. 중간 코드의 조건과 대치는 값 평가와 연산자 평가의 열로 구성된다. 값 평가와 연산자 평가는 서브프로세스 wrt_exp에 의해 C++ 표현식으로 변환되어 출력된다. 변환 과정에서 소트 테이블이 참조된다. 일반적으로 조건은 C++의 if문으로 번역되고 대치는 설정(assignment)문으로 번역된다.
도 16은 프로세스 gc_cns_build는 프로세스 gc_cns_dfn의 정의(도 14 참조)에 나타나는 서브프로세스 gc_cns_build를 상세히 나타낸 것이다. 프로세스 gc_cns_build는 중간 코드의 값 구축을 처리한다. 값 구축은 연산자 정의의 맨 마지막에 오는 선택 사항이며, 해당 연산자가 더 이상 개서될 수 없는 정규 값(normal term)임을 나타낸다. 값 구축에는 fail 주석이 첨부될 수 있다. Fail 주석은 해당 연산자의 값을 구축할 수 없다는 것을 나타내며, 오류 메시지 출력을 위한 정보를 제공한다. 따라서 프로세스 gc_cns_build는 fail 주석을 포함하는 경우를 처리하는 서브프로세스 wrt_bfl과 그렇지 않을 경우를 처리하는 서브프로세스 wrt_bld로 구성된다. 서브프로세스 prt_cns_build는 코드 생성의 초기화와 종결을 담당한다. 값 규칙에서와 같이 정규 값에 해당하는 C++ 표현 값은 매우 간단하다. 즉, 정규 값을 나타내는 추상 문법 트리를 C++ 자료 구조로 직선적으로 표현한다. 값 구축에 해당하는 C++ 코드 생성의 사례는 프로세스 gc_gpn_build의 설명을 참조하기 바란다.
5.3.2.5 일반 연산자 정의 변환
본 절에서는 일반 연산자 정의의 C++ 변환을 나타내는 프로세스 gc_opn_dfn을 상세히 정의한다(도 13 참조). 자료 흐름도의 기본적인 계층 구조는 프로세스 gc_cns_dfn와 유사하나 깊이가 깊고 각각의 자료 흐름도가 다소 복잡하다. 참고로 일반 연산자는 C++의 멤버 함수로 구현된다. 구체적으로 첫 번째 매개 변수의 타입을 나타내는 C++ 클래스의 멤버 함수로 구현된다.
도 17은 프로세스 gc_opn_dfn를 상세히 정의한 것이다. 기본 구조는 프로세스 gc_cns_dfn과 유사하다(도 14 참조). 다만 코드 생성 전반을 관장하는 서브프로세스 prt_opn_dfn이 입력 매개 값과 소트에 관한 정보를 생성하고, 생성된 정보가 서브프로세스 prt_ptl_ant와 gc_opn_build에 사용된다는 차이가 있다. 각각의 서브프로세스의 역할은 다음과 같다.
프로세스 prt_opn_dfn : 일반 연산자 정의의 코드 생성 전반을 관장하며, 코드 생성의 초기화와 종결에 관련된 업무를 처리한다. 예를 들면, C++ 함수 정의의 헤더 부분을 생성하고 다른 서브 프로세스를 호출하고 함수 정의를 종결한다. 또한 다른 서브프로세스에서 사용할 수 있도록 입력 매개 변수와 해당 소트에 관한 정보(arg_info)를 생성한다.
프로세스 prt_ptl_ant : 연산자 정의 부분에 partial 주석이 포함되었을 때 이를 처리한다. 즉, 명세된 C++ 표현식을 실행하고 결과 값이 0이면, 명세된 오류 정보를 사용하여 오류 메시지를 출력하도록 하는 C++ 문장을 출력한다.
프로세스 gc_opn_rules : 연산자 정의가 개서 규칙을 포함할 때 이를 C++의 switch와 case문으로 번역하여 출력한다. 자세한 사항은 도 18과 해당 설명을 참조 하기 바란다.
프로세스 gc_opn_build : 프로세스 gc_opn_builds는 연산자 정의가 값 구축을 포함할 때, 이를 C++ 문장으로 변환하여 출력한다. 값 구축의 처리시 프로세스 prt_opn_dfn에서 생성되는 논리 값 has_rules과 입력 매개 변수와 소트에 대한 정보 arg info를 사용한다. 프로세스 gc_opn_builds에 관한 구체적인 설계와 설명은 도 16을 참조하기 바란다.
도 18은 서브프로세스 gc_opn_rules를 정의한 것이다. 중간 코드의 규칙은 개서 규칙을 코드 생성에 편리한 형태로 표기한 것이다. 일반적으로 일반 연산자일 경우에는 패턴, 조건, 대치의 3요소로 구성된다. 패턴은 입력 매개 값의 형태를 결정하고 조건은 입력 값이 만족해야 할 사항을 정의하며 대치는 결과 값-즉, 개서 된 값을 나타낸다. 따라서 프로세스 gc_opn_rules은 각각 패턴, 조건, 대치 부분을 처리하는 3개의 서브프로세스 gc_pat, gc_cond, gc_repl로 구성된다. 서브프로세스 gc_pat과 gc_cond는 규칙과 조건 개수에 대한 정보-예를 들면, rule_cnt와 cond_cnt-를 생성하여 control_info에 저장한다. 자료 저장소 control_info의 정보는 프로세스 gc_cond와 gc_repl에 의해 사용된다. 또한 소트 테이블(srt_tbl)도 사용된다. 프로세스 gc_pat, gc_cond, gc_repl에 대한 구체적인 정의와 설명은 각각 도 19, 도 21, 도 23을 참조하기 바란다.
도 19는 프로세스 gc_pat을 자세히 정의한 것이다. 프로세스 gc_pat은 CVN_Pattern 객체로 표현되는 중간 코드 패턴에 해당하는 C++ 문장을 출력한다. 중간 코드의 개서 규칙은 특정한 형태의 자료 표현식을 다른 형태의 자료 표현식으로 개서 할 수 있도록 한다. 패턴이란 이러한 개서 가능한 자료 표현식의 형태를 말한다. 자료 연산자의 구현 함수 측면에서 보면 입력 매개 값의 형태를 말한다. 예를 들면, 연산자 _+_: nat, nat -〉 nat에 대한 [표 13]과 같은 두 등식 규칙을 가정하자.
succ(succ(n))+0 = succ(succ(n));n+0 = n
설명의 편의상 연산자 +가 C++의 함수 plus로 구현된다고 가정한다면, 함수 plus는 두 개의 입력 매개 변수를 갖는다. 두 번째 입력 매개 값은 항상 0이어야 한다. 반면, 첫 번째 입력 매개 값은 succ(succ(n))의 형태일 경우와 그렇지 않을 경우가 있다. 이렇게 입력 매개 값의 형태를 결정하는 것이 패턴이다.
패턴은 C++의 switch, case, default문으로 구현된다. 예를 들면, 연산자 0과 succ의 연산자 식별자 번호가 각각 1과 2라고 가정하면, 연산자 +의 패턴에 해당하는 C++ 코드는 [표 14]와 같다.(변수 _p1과 _p2는 각각 함수 plus의 첫 번째와 두 번째 매개 변수를 나타낸다.)
switch (_p2-〉opn) {case 1:/* 0 */ switch (_p1-〉opn) {case 2:/* succ */ switch(_p1-〉lnk-〉arg-〉opn) {case 2:/* succ */ _v=_p1-〉lnk-〉arg-〉lnk-〉arg-〉copy()-〉succ()-〉succ(); break; default: _v= _p1-〉copy(); break; } break; }
프로세스 gc_pat은 두 개의 서브프로세스 prt_pat과 gc_match로 구성된다. 서브프로세스 prt_pat은 패턴에 해당하는 C++ 코드 생성을 초기화하고, 관리하며, 종결한다. 예를 들면, cond_cnt와 rule_cnt와 같은 조건과 대치 처리에 필요한 control_info 정보를 생성하며, 또한 패턴을 C++의 switch와 case문으로 변환할 때 필요한 관리 정보-예를 들면, 새 패턴 여부(new_ptn), 중첩(nesting) 정도(nest_cnt, nest_level)-도 생성하고 갱신한다. 실질적인 코드 생성은 서브프로세스 gc_match에 의하여 이루어진다. 구문적 측면에서 보면 패턴은 추상 클래스 CVN_Match로 표현되는 연산자 매치와 값 매치의 열이다. 서브프로세스 gc_match는 연산자 매치와 값 매치에 해당하는 C++의 switch, case 혹은 default문을 생성한다(도 20 참조). 프로세스 gc_match를 정제하면 도 20과 같다. 추상 클래스 CVN_Match는 각각 연산자 매치와 값 매치를 나타내는 구체 클래스 CVN_Opn_Match와 CVN_Val_Match의 두 서브클래스를 갖는다. 연산자 매치는 입력 매개 변수가 자료 연산자로 구성되는 특정한 형태의 자료 표현식임을 나타내고, 값 매치는 그러한 형태가 아님을 나타낸다. 따라서 프로세스 gc_match는 각각 연산자 매치와 값 매치를 처리하는 두 서브프로세스 prt_opn_match와 prt_val_match로 구성된다. 일반적으로 연산자 매치는 C++의 switch와 case문으로 번역되고, 값 매치는 default문으로 나타낸다. 그러므로 프로세스 prt_opn_match와 prt_val_match는 각각 switch, case와 default 문장을 생성하여 출력한다. 해당 문장의 C++ 표현식은 소트 테이블을 사용하여 서브프로세스 wrt_exp가 생성한다(도 16의 프로세스 wrt_exp 참조).
지금까지는 중간 코드 규칙의 첫 번째 구성 요소인 패턴의 변환에 관하여 설명하였다. 이제부터는 나머지 두 구성 요소인 조건과 대치를 변환하는 프로세스 gc_cond와 gc_repl을 구체적으로 정의한다. 두 프로세스는 매우 유사하며 많은 부분을 공유한다. 먼저 조건은 입력 매개 값이 만족해야 할 사항을 나타내며, 규칙 정의에서 패턴 다음에 오는 선택 사항이다. 일반적으로 조건은 C++의 if문으로 변환된다. 예를 들면, 연산자 _〉_: nat, nat -〉 bool을 위한 자료 등식이 succ(n) 〉 n = true 하나 뿐이고, 연산자 〉가 C++의 독립 함수 gt로 구현된다고 가정하면(설명의 편의를 위하여 독립 함수로 구현된다고 가정하였지만 실제로는 클래스 nat의 멤버 함수로 정의되어야 한다.) 생성되는 함수 gt를 개략적으로 나타내면 [표 15]와 같다.
bool gt(nat x, nat y) { if(x is of the form succ(n)) {/* pattern */ if(equal(1st arg of x(i.e., n), y)) {/* condition */ return true; } } /* rest of program */}
즉, 조건은 첫 번째 입력 매개 값(x)의 첫 번째 입력 값은 두 번째 입력 매개 값(y)과 같아야 함을 나타낸다. 위 예에서는 편의상 패턴을 if문으로 변환하였지만, 실제로는 switch와 case문으로 변환된다.
도 21은 프로세스 gc_cond를 구체적으로 나타낸 것이다(프로세스 gc_cond가 사용되는 문맥은 도 18 참조). 구문적인 측면에서 보면 조건은 연산자 평가와 값 평가의 열로 구성된다. 따라서 프로세스 gc_cond는 코드 생성을 관장하는 서브프로세스 prt_cond와 연산자 평가 혹은 값 평가를 C++ 표현식으로 변환하는 서브프로세스 gc_eval로 구성된다. 서브프로세스 prt_cond는 코드 생성의 초기화, 서브프로세스 gc_eval 호출, 코드 생성 종결을 담당하며, 이 과정에서 C++의 if문을 출력한다. 반면 서브프로세스 gc_eval은 if문의 조건이 되는 C++ 논리 표현식을 출력한다.
서브프로세스 gc_eval은 도 22와 같이 더욱 정제된다. 중간 코드의 평가를 나타내는 추상 클래스 CVN_Eval은 연산자 평가를 나타내는 구체 클래스 CVN_Opn_Eval과 값 평가를 나타내는 구체 클래스 CVN_Val_Eval의 두 서브클래스를 갖는다. 값 평가에는 해당 소트를 나타내는 소트 주석(CVN_SortAnt)이 선행 할 수 있다. 따라서 프로세스 gc_eval은 이러한 3종류의 자료를 처리하기 위한 서브프로세스 prt_opn_eval, prt_val_eval, prt_srt_ant로 구성된다. 연산자 평가는 입력 매개 값을 나타내는 LOTOS 자료 표현식에서 명세된 자료 연산자를 가장 상위 연산자로 가지는 서브 자료 표현식을 나타낸다. 반면 값 평가는 LOTOS 자료 표현식에서 특정한 서브 표현식-일반적으로 변수-를 나타내는데 사용된다. 연산자 평가와 값 평가 모두 C++의 표현식으로 변환되는데, 이는 소트 테이블에 저장된 소트 정보를 사용하여 서브프로세스 wrt_exp가 처리한다. 참고로 서브프로세스 wrt_exp는 프로세스 gc_cns_rules(도 15 참조)와 gc_match(도 20 참조)에서도 사용된다.
중간 코드의 규칙의 마지막 구성 요소인 대치를 처리하는 프로세스 gc_repl의 구조는 앞에서 설명한 프로세스 gc_cond와 유사하다. 대치는 개서 규칙의 우측 편에 해당하며 개서된 값을 나타낸다. 구현 함수의 입장에서 보면 함수 호출의 결과 값이다. 대치가 나타내는 결과 값은 자료식으로 표현되는데 구성 요소를 보면, 연산자 표현식과 값 표현식이 있다. 즉, 대치는 값 평가와 연산자 평가의 열로 구성된다. 일반적으로 대치는 C++의 설정(assignment)문으로 번역된다. 예를 들면, 연산자 succ2: nat -〉 nat의 자료 등식이 succ2(n) = succ(succ(n))이고, 클래스 Natural의 멤버 함수로 구현된다고 가정한다면, [표 16]과 같은 형태가 될 것이다.
Natural Natural::succ2(Natural_p1) { Natural_v; _v = this-〉copy()-〉succ()-〉succ(); return_v;}
프로세스 gc_repl은 코드 생성을 관장하는 서브프로세스 prt_repl과 연산자 평가 혹은 값 평가를 C++ 표현식으로 변환하는 서브프로세스 gc_eval로 구성된다. 서브프로세스 prt_repl은 코드 생성의 초기화, 서브프로세스 gc_eval 호출, 코드 생성 종결을 담당하며, 이 과정에서 C++의 설정문을 출력한다. 반면 서브프로세스 gc_eval은 설정문의 우측편에 오는 C++ 표현식을 출력한다. 서브프로세스 gc_eval은 앞의 도 22를 참조하기 바란다.
일반 연산자 정의 변환의 마지막 단계는 프로세스 gc_opn_build로 값 구축의 처리이다(도 17 참조). 프로세스 gc_opn_build는 도 24와 같이 정의할 수 있다. 값 구축은 연산자 정의에 맨 마지막에 오는 선택 사항이며, 해당 연산자가 더 이상 개서될 수 없는 정규 값임을 나타낸다. 값 구축에는 fail 주석이 첨부될 수 있다. Fail 주석은 해당 연산자의 값을 구축할 수 없다는 것을 나타내며, 오류 메세지 출력을 위한 정보를 제공한다. 따라서 프로세스 gc_opn_build는 fail 주석을 포함하는 경우를 처리하는 서브프로세스 wrt_bfl과 그렇지 않을 경우를 처리하는 서브프로세스 wrt_bld로 구성된다. 서브프로세스 prt_opn_build는 코드 생성의 초기화와 종결을 담당한다. 값 규칙에서와 같이 정규 값에 해당하는 C++ 표현 값은 매우 간단하다. 즉, 정규 값을 나타내는 추상 문법 트리를 C++ 자료 구조로 직선적으로 표현한다.
Fail 주석을 포함하는 값 구축의 코드 생성 예를 보이기 위하여 [표 17]과 같은 LOTOS 자료 명세를 가정하자. 자료 연산자 pred가 생성자가 아니라고 명세되었음에 주의하라.
연산자 pred에 관한 공리가 불완전함에 주의하라. 즉, pred(0)에 관한 등식이 정의되지 않았다. 연산자 pred가 생성자가 아니므로 pred(0)는 소트 nat의 정규 값이 될 수 없다. 다시 말해서 이에 해당하는 nat 값을 구축할 수 없다. 만약 위 LOTOS 명세가 파일 test.lot에 정의되었고, 연산자 pred의 선언이 9번째 줄에 나타난다면, 연산자 pred를 구현하는 멤버 함수는 [표 18]과 같이 정의된다.(연산자 succ의 식별자가 2라고 가정한다.)
이상에서 설명된 본 발명은 본 발명이 속하는 기술분야에서 통상의 지식을 가진자에 있어 발명의 기술적 사상을 벗어나지 않는 범위내에서 여러 가지 치환, 변형 및 변경이 가능하므로 전술한 실시예 및 첨부된 도면에 한정되는 것은 아니다.
type Natural is sorts nat(*|name Natural|*) opns 0 : -〉 nat succ: nat-〉 nat pred(*|name pred|*)(*|nonconstructor|*):nat-〉 nat eqns forall n: nat ofsort nat pred(succ(n))=nendtype
Natural Natural::pred() { Natural_v= NULL; switch (this-〉 opn) { case 2:/* succ */ _v= this-〉lnk-〉arg-〉copy(); break; } if (_v == NULL) { put_error("Nonconstructor failure: unable to build term\n"); put_error("name: pred (see line 9 of file "test.lot\")\n"); put_error("arg 1: %s\n", this-〉draw()); exit(1); } return_v;}
상술한 바와 같이 본 발명에 따른 LOTOS 자료 명세로부터 C++ 프로그램의 자동 생성 방법과 지원 도구는 산업계에서 실제 사용한 기술로 소프트웨어 개발의 생산성과 개발된 소프트웨어의 품질 향상에 지대한 기여를 할 것으로 기대된다. 궁극적으로는 코드 생성기와 같이 실사용 가능한 기술을 통하여 수학 기반의 엄격한 소프트웨어 개발 방법인 정형 방법(Formal Methods)이 산업계에 보급되고 활용되는 촉매 작용을 할 것으로 본다. 정형 방법은 요구 분석과 같은 개발 초기 단계에 가장 효과적인 것으로 보고되고 있다. 요구 분석의 오류가 설계 및 구현으로 전달되는 파급 효과를 방지할 수 있기 때문이다. 소프트웨어 오류의 80% 이상이 요구 사항의 잘못된 이해에 기인한다는 사실을 감안할 때 바람직한 접근 방식이다. 하지만 정형 방법이 효과적으로 적용되기 위해서는 수학적 소프트웨어 개발을 지원하는 지원 도구와 개발 환경이 필요하다. 특히, 정형 증명과 같은 이론 지향적인 도구 보다는 실사용 가능한 -예를 들면, 사용자의 요구 사항이 명세에 제대로 반영되었는지 파악할 수 있는 확인 위주의 경량 도구가 필요하다. 본 발명에 따른 코드 생성이 이런 부류에 속한다.
본 발명에 따른 코드 생성 기술은 명세의 동작 모형으로 사용될 수 있다. 명세를 실제 실행해 봄으로써 다양한 형태로 명세의 특성을 검사하고 분석할 수 있고, 명세의 작동 상황을 가시화할 수도 있다. 명세의 동작 모형이 실제 구현 언어인 C++로 주어지므로 실제 구현에도 사용할 수 있다. 코드 생성 기법을 기반으로 하여 명세의 검증 및 증명 도구를 개발할 수도 있다. 즉, 고안된 기술은 LOTOS 기반의 정형 지원 도구 개발의 핵심 모듈로 사용될 수 있다.
본 발명에 따른 코드 생성 기법은 확장성이 뛰어나므로 C++ 이외의 다른 프로그래밍 언어도 손쉽게 지원할 수 있다. 예를 들면, 프로그래밍 언어 Java를 지원하기 위해서는 중간 코드에서 Java로의 변환 모듈과 해당 커널 라이브러리만 개발하면 된다. 기타 모듈은 거의 수정없이 재사용될 수 있다.

Claims (9)

  1. LOTOS 자료 명세로부터 코드 생성을 위한 기능을 제공하기 위한 다수의 모듈으로 구성된 핵심층과,
    사용자 지향적인 GUI를 제공하며, 파일 검색, 소스 코드 보기, 오류 출력 및 환경 설정등의 기능을 제공하는 사용자 접속층과,
    상기 핵심층의 모듈간 또는 상기 상위층과의 통신 채널을 제공하고, 자료 코드의 생성, 프로토 타입의 생성 및 실행 기능을 수행하며, 상기 핵심층의 모듈들을 동적으로 배치 및 연결하는 관리층을 포함하여 이루어진 것을 특징으로 하는 LOTOS 자료 명세로부터 객체지향 프로그램의 자동 생성을 위한 코드 생성기.
  2. 제 1 항에 있어서, 상기 핵심층은 상기 LOTOS 자료 명세가 문법에 맞는가를 검사하기 위한 구문 검사 모듈과,
    상기 문법 검사가 완료된 LOTOS 자료 명세에 대해 LOTOS 자료 명세를 구성하는 타입을 검사하기 위한 타입 검사 모듈과,
    상기 구문 검사 및 타입 검사가 완료된 LOTOS 자료 명세에 구현 종속적인 사항을 처리하기 위해 첨가되는 주석을 처리하기 위한 주석 처리 모듈과,
    상기 구문 검사, 타입 검사 및 주석 처리된 LOTOS 자료 명세로부터 중간 코드를 생성하기 위한 중간 코드 생성 모듈과,
    상기 중간 코드로부터 객체지향 프로그램을 생성하기 위한 위한 객체지향 프로그램 모듈을 포함하여 이루어진 것을 특징으로 하는 LOTOS 자료 명세로부터 객체지향 프로그램의 자동 생성을 위한 코드 생성기.
  3. LOTOS 자료 명세의 문법을 검사한 후 추상 문법 트리를 생성하는 단계와,
    상기 문법이 검사된 상기 LOTOS 자료 명세를 구성하는 타입을 검사하는 단계와,
    상기 문법 및 타입이 검사된 LOTOS 자료 명세에 대하여 주석을 처리하는 단계와,
    상기 문법 검사, 타입 검사 및 주석 처리가 완료된 LOTOS 자료 명세로부터 중간 코드를 생성하는 단계와,
    상기 중간 코드로부터 객체지향 프로그램의 헤더 및 소스를 생성하는 단계를 포함하여 이루어진 것을 특징으로 하는 LOTOS 자료 명세로부터 객체지향 프로그램의 자동 생성 방법.
  4. 제 3 항에 있어서, 상기 객체지향 프로그램은 하기와 같은 상기 LOTOS 자료 명세의 구성 요소로부터 상기 객체지향 프로그램의 구성 요소로의 변환 규칙에 따른 알고리즘에 의해 생성되는 것을 특징으로 하는 LOTOS 자료 명세로부터 객체지향 프로그램의 자동 생성 방법.
    규칙 1 : LOTOS 자료 명세의 소트는 객체지향 프로그램의 클래스로 변환된다.
    규칙 2 : LOTOS 자료 명세의 연산자는 기본적으로 객체지향 프로그램 구현 클래스의 멤버 함수로 변환된다.
    규칙 3 : 상기 LOTOS 자료 명세의 생성 연산자중 입력 매개 값을 하나도 갖지 않은 기본 생성자는 객체지향 프로그램의 독립 함수로 변환된다.
    규칙 4 : 상기 LOTOS 자료 명세의 생성 연산자중 입력 매개 값을 하나 이상 갖는 연산자는 첫 번째 입력 매개 소트에 해당하는 객체지향 프로그램 구현 클래스의 멤버 함수로 변환된다.
    규칙 5 : 상기 LOTOS 자료 명세의 연산자의 삽입성은 해당 구현 함수의 이름에 의하여 결정된다.
    규칙 6 : 상기 객체지향 프로그램의 연산자로 변환되는 모든 연산자는 해당 클래스의 독립 프렌드 함수로 구현된다.
  5. 제 3 항에 있어서, 상기 객체지향 프로그램의 헤더 및 소스는 중간 코드를 일반 객체와 주석 객체로 구성하여 클래스 계층 구조로 표현하는 단계와,
    상기 중간 코드의 소트 및 연산자 선언 부분으로부터 객체지향 프로그램의 헤더 파일을 생성하는 단계와,
    상기 중간 코드의 연산자 정의 부분으로부터 객체지향 프로그램의 소스 파일을 생성하는 단계에 의해 생성되는 것을 특징으로 하는 LOTOS 자료 명세로부터 객체지향 프로그램의 자동 생성 방법.
  6. 제 3 항에 있어서, 상기 객체지향 프로그램은 커널 클래스에 의해 지원되는 것을 특징으로 하는 LOTOS 자료 명세로부터 객체지향 프로그램의 자동 생성 방법.
  7. 제 6 항에 있어서, 상기 커널 클래스는 자동 생성된 모든 클래스의 공통된 특성을 정의하는 제 1 커널 클래스와,
    자동 생성된 클래스와 수작업 클래스의 인터페이스를 위한 프로토콜 및 서비스를 정의하는 제 2 커널 클래스와,
    상기 제 1 및 제 2 커널 클래스의 공통 특성을 추상화하는 제 3 커널 클래스와,
    자동 생성된 객체지향 프로그램에서 동적 메모리를 자동으로 관리하기 위한 시스템 클래스를 포함하여 이루어진 것을 특징으로 하는 LOTOS 자료 명세로부터 객체지향 프로그램의 자동 생성 방법.
  8. 제 6 항에 있어서, 상기 제 1 커널 클래스에서 LOTOS 자료 명세의 추상값을 구현하기 위하여 추상 문법 트리 표현법을 사용하고, 이를 객체로 구성되는 객체지향 프로그램의 자료 구간을 사용하여 실현하는 것을 특징으로 하는 LOTOS 자료 명세로부터 객체지향 프로그램의 자동 생성 방법.
  9. LOTOS 자료 명세의 문법을 검사하고 그 결과에 따라 추상 문법 트리를 생성하기 위한 수단과,
    상기 문법 검사가 완료된 상기 LOTOS 자료 명세를 구성하는 타입을 검사하기 위한 수단과,
    상기 문법 및 타입 검사가 완료된 LOTOS 자료 명세에 대하여 주석을 처리하기 위한 수단과,
    상기 문법 검사, 타입 검사 및 주석 처리가 완료된 LOTOS 자료 명세로부터 중간 코드를 생성하기 위한 수단과,
    상기 중간 코드를 일반 객체와 주석 객체로 구성하여 클래스 계층 구조로 표현하기 위한 수단과,
    상기 중간 코드의 소트 및 연산자 선언 부분으로부터 객체지향 프로그램의 헤더 파일을 생성하기 위한 수단과,
    상기 중간 코드의 연산자 정의 부분으로부터 객체지향 프로그램의 소스 파일을 생성하기 위한 수단을 기능시키기 위한 프로그램을 기록한 컴퓨터로 읽을 수 있는 기록 매체.
KR1019980052022A 1998-11-30 1998-11-30 로토스 자료 명세로부터 객체지향 프로그램의 자동 생성 방법및 이를 위한 코드 생성기 KR100287061B1 (ko)

Priority Applications (1)

Application Number Priority Date Filing Date Title
KR1019980052022A KR100287061B1 (ko) 1998-11-30 1998-11-30 로토스 자료 명세로부터 객체지향 프로그램의 자동 생성 방법및 이를 위한 코드 생성기

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
KR1019980052022A KR100287061B1 (ko) 1998-11-30 1998-11-30 로토스 자료 명세로부터 객체지향 프로그램의 자동 생성 방법및 이를 위한 코드 생성기

Publications (2)

Publication Number Publication Date
KR20000034648A KR20000034648A (ko) 2000-06-26
KR100287061B1 true KR100287061B1 (ko) 2001-04-16

Family

ID=19560601

Family Applications (1)

Application Number Title Priority Date Filing Date
KR1019980052022A KR100287061B1 (ko) 1998-11-30 1998-11-30 로토스 자료 명세로부터 객체지향 프로그램의 자동 생성 방법및 이를 위한 코드 생성기

Country Status (1)

Country Link
KR (1) KR100287061B1 (ko)

Cited By (2)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US9898265B2 (en) 2012-11-30 2018-02-20 Inswave Systems Co., Ltd. Apparatus for situational cognition and position determination of screen object in program development, and method therefor
KR20200116312A (ko) * 2019-04-01 2020-10-12 국방과학연구소 시뮬레이션 모델 연동을 위한 어댑터 개발 지원 장치 및 방법

Families Citing this family (1)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
KR100985192B1 (ko) * 2007-09-14 2010-10-05 주식회사 티맥스 소프트 소프트웨어 개발 시스템

Cited By (3)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US9898265B2 (en) 2012-11-30 2018-02-20 Inswave Systems Co., Ltd. Apparatus for situational cognition and position determination of screen object in program development, and method therefor
KR20200116312A (ko) * 2019-04-01 2020-10-12 국방과학연구소 시뮬레이션 모델 연동을 위한 어댑터 개발 지원 장치 및 방법
KR102206019B1 (ko) * 2019-04-01 2021-01-21 국방과학연구소 시뮬레이션 모델 연동을 위한 어댑터 개발 지원 장치 및 방법

Also Published As

Publication number Publication date
KR20000034648A (ko) 2000-06-26

Similar Documents

Publication Publication Date Title
Muller et al. Weaving executability into object-oriented meta-languages
Van Gorp et al. Towards automating source-consistent UML refactorings
Czarnecki et al. Formalizing cardinality‐based feature models and their specialization
Mernik An object-oriented approach to language compositions for software language engineering
Bardohl et al. Integrating meta-modelling aspects with graph transformation for efficient visual language definition and model manipulation
Brown et al. Introduction: Models, modeling, and model-driven architecture (MDA)
Hölldobler et al. Software language engineering in the large: towards composing and deriving languages
Kolovos An extensible platform for specification of integrated languages for model management
CN115794254A (zh) 基于云计算的组件研发管理平台和方法
Mesa M2DAT: a technical solution for model-driven development of Web information systems
Favre et al. Formal mof metamodeling and tool support
Plasil et al. Getting'Whole picture'behavior in a use case model
Lourenço et al. OSTRICH: a rich template language for low-code development (extended version)
KR100287061B1 (ko) 로토스 자료 명세로부터 객체지향 프로그램의 자동 생성 방법및 이를 위한 코드 생성기
van den Berg et al. QRML: A component language and toolset for quality and resource management
Kulkarni Raising family is a good practice
JP2007122187A (ja) プログラム・コード生成装置
Merino et al. Projecting Textual Languages
WO2008015110A2 (en) Methods, apparatus and computer programs for modelling computer programs
Aarssen et al. Concrete syntax with black box parsers
Guyon et al. An integrated development environment for pattern matching programming
Jung Generator-composition for aspect-oriented domain-specific languages
Cruz et al. Constructing program animations using a pattern based approach
Bjarnason Interactive Tool Support for Domain-Specific Languages
Kallel et al. Combining formal methods and aspects for specifying and enforcing architectural invariants

Legal Events

Date Code Title Description
A201 Request for examination
E701 Decision to grant or registration of patent right
GRNT Written decision to grant
FPAY Annual fee payment

Payment date: 20080103

Year of fee payment: 8

LAPS Lapse due to unpaid annual fee