제 4장 블록 및 유효범위
4.1 변수 선언 및 유효범위
변수 선언과 유효범위
변수 선언
Declaration before Use !
대부분의 언어에서 변수는 사용 전에 먼저 선언해야 한다.
변수의 유효범위 (scope)
선언된 변수가 유효한(사용될 수 있는) 프로그램 내의 범위/영역
변수 이름뿐 아니라 함수 등 다른 이름도 생각해야 한다.
정적 유효범위 (Static scope) 규칙
선언된 이름은 선언된 블록 내에서만 유효함
대부분 언어에서 표준 규칙으로 사용됨
변수 선언
Syntax
S → …
| let T x = E in S end T → int | bool
Semantics
변수 x는 t 타입이다.
변수 x의 유효범위는 선언된 블록 내이다.
Syntactic sugar let D1,D2 in
S end
let D1 in
let D2 in S
end end
변수 선언
Example in S
let int x = 1 in x = x + 1
end
Example in C
{ int x = 1;
x = x + 1;
}
변수의 의미 (시맨틱스)
대입문
x = E;
예를 들어 x = x + 1;
오른쪽 x와 왼쪽 x의 의미가 다르다 !
변수 x의 의미
V[x]s = s(x) 메모리 위치에 저장된 값(r-value)
(s, x = E) → s[x ↦[E]s] 메모리 위치(l-value)
중첩 블록
Example in S
let int x = 2 in
let int y = 3 in x = y + 2
end end
Example in C
{ int x = 2;
{ int y = 3;
x = y+2;
new variables declared in nested blocks
inner outer
block local variable
블록 (Blocks)
Pascal
procedure or function
C, C++, Java
{ . . . }
Ada
declare . . .
begin … end
ML
let … in … end
같은 이름의 변수
같은 이름의 변수가 여러 개 선언될 수 있다 .
Example
let int x = 1 in
let int y = 2 in x = x + y end;
let int x = 5 in x = x + 1 end;
x = x * 2 end
Example in C
{ int x = 1;
{ int y = 2;
x = x + y;
}
{ int x = 5;
x = x + 1;
}
x = x * 2;
시맨틱스
수식 혹은 문장의 의미 파악
현재 유효한 변수들에 대한 바인딩 정보가 필요하다.
같은 이름의 변수가 여러 개 있을 수도 있다.
각 변수의 바인딩 정보
변수의 선언된 타입
변수의 유효범위
변수의 위치
컴파일러 /인터프리터
번역/해석을 위해서 변수의 바인딩 정보 유지 관리
실행
실행을 위해서 변수 값을 저장하기 위한 메모리(memory) 관리
4.2 함수 및 유효범위 규칙
함수 선언
Syntax
S → …
| let fun t1 f(t2 x) => S in S end
| return E
| f(E)
Semantics
이름 f는 선언된 블록 내에서만 유효하다.
이름 f는 정의된 함수를 나타낸다.
Example
let int y = 0,
fun int square(int x) => return x * x in
y = square(5) end
함수의 시맨틱스
수식 혹은 문장의 의미 파악
현재 유효한 함수들에 대한 바인딩 정보가 필요하다.
함수의 바인딩 정보
함수의 선언된 타입
함수의 유효범위
함수의 코드 위치
컴파일러 /인터프리터
번역/해석을 위해서 함수의 바인딩 정보도 유지 관리
선언의 유효범위
선언된 식별자 (이름)의 유효범위(scope)
선언된 이름이 유효한(사용 가능한) 프로그램의 범위 혹은 영역
변수 이름뿐 아니라 함수 이름 등도 생각해야 한다.
정적 유효범위 (static scope) 규칙
선언된 이름은 선언된 블록 내에서만 유효함
대부분 언어에서 표준 규칙으로 사용됨
동적 유효범위 (dynamic scope)
선언된 이름은 선언된 블록의 실행이 끝날 때까지 유효함
실행 경로에 따라 유효범위가 달라질 수 있다.
Old Lisp와 SNOBOL에서 사용됨
Example 2
0 let int x = 0 in
1 let fun int addsq(int y) => x = x + y * y in 2 let int x = 2 in
3 addsq(5)
4 end
5 end
6 end
정적 유효범위 규칙
동적 유효범위 규칙
4.3 바인딩 정보 유지/관리
왜 바인딩 정보를 관리 ?
유효한 이름 (식별자)
프로그램 각 지점에서 유효한 이름들은 다르다.
컴파일러 /인터프리터
프로그램을 한 줄씩 읽으면서 번역/해석한다.
프로그램의 각 지점에서 유효한 이름들에 대한 정보가 있어야 번역/해석할 수 있다.
따라서 프로그램 각 지점에서 유효한 이름들에 대한 정보를 유 지 관리해야 한다.
바인딩 유지 관리
다음 블록을 살펴보자
let int x = 2 in
let int y = 3 in x = y + 2
end end
아이디어
블록 시작
선언된 변수들의 바인딩 정보를 유지한다.
문장
바인딩 정보를 이용해서 문장들을 컴파일/인터프리터 한다.
블록 끝
선언된 변수들은 더 이상 유효하지 않으므로 바인딩 정보를 제거 한다.
Example
0 let int x = 0 in
1 let fun int addsq(int y) => x = x + y * y in 2 let int x = 2 in
3 addsq(5)
4 end
5 end
6 end
변수 이름뿐만 아니라 함수 이름의 바인딩 정보도 유지/관리해야 한다.
바인딩 유지 관리
심볼 테이블 (Symbol Table)
현재 유효한 바인딩 정보를 유지/관리하기 위한 자료 구조
환경(environment)라고도 한다.
심볼 테이블 유지 /관리
컴파일러
컴파일 하기 위해 바인딩 정보 유지/관리
인터프리터
해석해서 실행하기 위해 바인딩 정보 유지/관리
블록 구조를 위한 심볼 테이블
스택 형태로 유지 관리
블록 시작
블록 내의 선언을 처리한다.
선언된 이름의 바인딩 정보를 심볼 테이블에 추가한다.
블록의 끝
블록 내의 선언의 바인딩 정보를 제거한다.
더 이상 필요 없다.
예
let int x = 1 in
let int y = 2 in x = x + y end;let int x = 5 in
x = x + 1 end;x = x * 2
end
token val lexptr
ID ID
x \0 y \0 lexemes[]
lastchar lastentry
1 2 symtable[]
…
x \0 x \0 ID 5
HW #4
let 블록을 포함한 언어 S에 대한 인터프리터 작성
심볼 테이블 관리
Syntax
S → …
| let T x = E {,T x = E} in S end T → int | bool
Semantics
변수 x는 t 타입이다.
4.4 Case Study
다른 언어에서 선언 및 유효범위
무엇을 선언하는가 ?
상수, 변수, 함수, 클래스
어디에 선언하는가 ?
블록 내 혹은 밖
구조체(struct)
클래스
어떻게 선언하는가 ?
명시적 선언: Pascal, C, C++, Java, …
묵시적 선언: Lisp, partly in FORTRAN
블록 구조 언어
블록의 중첩을 허용하는 언어
Algol, Pascal, Modula, Ada, C, ...
A B
C D
C의 블록
int x;
double y;
void p (void)
{ int x = 2; /* p의 블록 */
…
{ int y = 3; /* 또 하나의 중첩 블록 */
x = y + 2;
}
… }
Ada 블록
declare x:integer;
y: boolean;
begin
x := 2;
y := true;
x := x+1;
… end
Pascal의 블록
program ex; (* main 프로그램 *)
var x: integer; (* 전역 선언 *) procedure p; (* 전역 선언 *)
var y: boolean; (* p 내의 선언 *) begin
if x = 2 then begin … end;
end;
begin (* main *) (* 선언할 수 없음 *)
…
end. (* 프로그램 *)
클래스 내의 선언
public class IntWithGcd {
private int value; /* value 필트 지역 선언 */
public int intValue() /* intValue 메쏘드 지역선언 */
{
return value;
}
public int gcd(int v) /* gcd 메쏘드 지역선언 */
{
… }
}
예 : C 언어의 유효범위 규칙
핵심 아이디어
사용 전 선언(Declaration before use)
선언의 유효범위는 선언된 지점부터 선언된 블록 끝까지
지역 변수의 유효 범위
선언된 지점부터 함수 끝까지
전역 변수의 유효범위
선언된 지점부터 파일 끝까지
예제
void p( ) p
{ char y; y
… }
int x; x
void q( ) q
{ double z; z
… }
main() main
{ int w[10]; w
… }
예 : Ada 언어의 유효범위 규칙
핵심 아이디어
선언의 유효범위는 선언된 블록 내
예
B1: declare
x: integer;
y: boolean;
begin
x := 2;
y := false;
B2: declare
a, b: integer;
begin
if y then a := x;
else b := x;
중첩 블록에서 선언
최중첩 우선 규칙 (Most closely nested rule)
한 식별자가 여러 번 선언된 경우 최중첩된 선언을 우선 한다.
예
int x;
void p( ) { char x;
x = ‘a’; /* local x */
… }
main()
{ x = 2; /* global x */
… }