[프로그래밍언어론] 13. 가시성 규칙(Visibility Rules), 범위 규칙(Scope Rules)

2023. 10. 10. 16:50·프로그래밍언어론
목차
  1. 가시성 규칙(Visibility Rules)
  2. 환경
  3. 그래도 이것만으로는 부족하다.
  4. 범위 규칙(Scope Rules)
  5. 정적 vs. 동적
  6. 정적 범위 규칙
  7. 규칙 1. 지역 선언
  8. 규칙 2. 가장 가까운 중첩 범위
  9. 규칙 3: 블록에 할당된 이름
  10. 정적 범위의 장점
  11. 동적 범위
  12. 동적 범위의 장점

가시성 규칙(Visibility Rules)

  • 비공식적인 개념이다.
  • 이름의 가시성을 결정하고 특정 블록에서 어떤 바인딩을 사용할 수 있는지 결정하는 규칙.
    • 블록의 로컬 선언은 해당 블록과 해당 블록 내의 다른 모든 블록에 표시된다.
    • 블록에 동일한 이름의 새 선언이 있는 경우 이 새 선언은 이전 선언을 숨긴다.

 

0: { int a = 1;
    1: { int b = 2;
        2: { int b = 3;
                int c = a + b;
                printf("%d\n", c);
            }
        3: { int d = a + b;
                printf("%d\n", d);
            }
        }
    }
  • 블록 0~3이 있다.
  • 현재 블록이 변경되면 환경도 변경된다.
  • 따라서 동일한 이름이 다른 개체에 연결될 수 있다.
  • 변수 c의 값 : 4
  • 변수 d의 값 : 3
    • 먼저 블록 0에 a가 선언되어 있으므로 블록  0~3 모두에서 볼 수 있다.
    • 첫 번째 b는 블록 1에서 선언되므로 블록 1, 2, 3에서 볼 수 있다.
    • 두 번째 b는 블록 2에서 선언되며 블록 2에서만 볼 수 있다.
    • 블록 2의 첫 번째 b를 숨기므로 블록 2에서 b는 항상 두 번째 b를 나타낸다.
    • 반면, 블록 3에서는 두 번째 b(블록 2의)가 표시되지 않는다.
    • 블록 1의 첫 번째 b는 블록 3에서 볼 수 있으므로 d를 계산하는 데 사용된다.
    • 따라서 c는 4이고 d는 3이다.

 


 

환경

  • 위의 예시에서 변수 a가 글로벌 변수라고 가정해보자.
  • 그러면 a는 모든 블록에 표시되며 글로벌 환경의 일부가 된다.
  • 블록 1의 경우 a의 바인딩은 글로벌 환경이자 비로컬 환경이다.
  • 로컬 환경의 이름은 내부 블록에 표시된다.
  • 로컬 환경의 이름은 외부 블록에 표시되지 않는다.
  • 로컬이 아닌 환경의 이름은 로컬 환경의 동일한 이름으로 숨겨진다.
  • 예) 블록 2의 로컬 환경에서 첫 번째 b의 바인딩이 비활성화된다.

 


 

그래도 이것만으로는 부족하다.

  • 우리가 논의한 가시성 규칙은 대략적인 큰 그림을 설명한다.
  • 구체적이고 세부적인 규칙은 언어마다 다를 수 있다.
  • 예를 들어 방금 설명한 경우는 Java에서는 유효하지 않다.
  • 이전 예제는 C로 작성되었으며 오류 없이 작동한다.
  • Java에서는 로컬변수 중복이 허용되지 않는다.
  • 반면에 전역 변수를 재정의할 수 있다.
  • 그러므로 우리는 각 프로그래밍 언어에 대한 구체적인 규칙을 이해해야 한다.
0: { int a = 1;
    1: { int b = 2;
        2: { int b = 3;             // 오류가 발생
                int c = a + b;
                printf("%d\n", c);
            }
        3: { int d = a + b;
                printf("%d\n", d);
            }
        }
    }

 


 

범위 규칙(Scope Rules)

  • 블록과 관련된 다양한 환경에서 이름이 표시되는 방식을 대략적으로 설명한다.
  • 본 포스트에서는 정적과 동적 관점에 대해 다룬다.

 


 

정적 vs. 동적

  • 정적 범위 : 프로그램 자체의 구문 구조에만 의존
    • 따라서 환경은 컴파일러에 의해 완전히 결정될 수 있다.
  • 동적 범위 : 프로그램의 역방향 실행을 사용하여 바인딩을 결정
    • 따라서 런타임 중에 결정될 수 있다.

 


 

정적 범위 규칙

  • 정적 범위 규칙은 가장 가까운 중첩 범위의 규칙으로 간주될 수 있다.
  • 세 가지 규칙
    • 규칙 1. 블록에 대한 로컬 선언은 해당 블록의 로컬 환경을 정의
    • 규칙 2. 이름이 블록 내에서 사용되는 경우 이 이름의 유효한 바인딩은 로컬 환경에 존재.
      존재하지 않는 경우 가장 가까운 외부 블록에 존재
    • 규칙 3. 블록 자체는 이름과 연관될 수 있으며 이러한 이름은 블록의 로컬 환경의 일부이다.

 


 

규칙 1. 지역 선언

  • 지역적으로 선언된 변수는 지역 환경을 정의한다.
  • 블록 1의 경우 이 블록에는 변수 b만 선언된다.
  • 다른 변수는 표시되지 않거나 표시되지만 로컬 환경에는 포함되지 않는다.


 

규칙 2. 가장 가까운 중첩 범위

  • 변수 a는 블록 3에서 참조된다.
  • 단, 이 블록에는 a가 선언되지 않는다.
  • 규칙 2에 따라 블록 1을 먼저 검색한다.
  • 아직 찾을 수 없으므로 블록 0을 시도한다. → a가 여기에 선언되어 있다.
  • 블록 2는 "중첩된" 블록만 검색하므로 건너뛰었다.

 


 

규칙 3: 블록에 할당된 이름

  • Java 코드에서 메소드 이름 put, 매개변수 list, str는 실제로 블록 내부에 없다.
  • 단, 로컬 환경에서는 사용 가능하다.
  • 또한 로컬 환경의 일부이므로 외부 블록에는 표시되지 않는다.
    • put()은 선언이 포함된 블록에 표시되는 프로시저이기 때문에 예외이다.
public static void put(List<String> list, String str) {
	list.set(list.size()/2, str);
}

 


 

정적 범위의 장점

  • 이러한 모든 정적 범위 규칙은 미리 정의되어 있으며 코드의 구문 구조에만 의존한다.
  • 컴파일러는 사용된 이름의 모든 바인딩을 추론할 수 있다.
  • 이 사실은 큰 이점을 제공한다.
    • 프로그램에 대해 더 잘 이해할 수 있다.
    • 컴파일러는 정확성 테스트를 수행할 수 있다.
    • 컴파일러는 상당한 최적화를 수행할 수 있다.

 


 

동적 범위

  • 프로그램의 특정 지점 P에서 이름 X의 유효한 바인딩,
    • 가장 최근에 생성된 바인딩 X 이다.
  • X는 P 지점에서 계속 활성화되어 있어야 한다.
Shell Script

1:   x=1
2:   function foo() {
3:       echo $x;
4:       x=2;
5:   }
6:   function bar() {
7:       local x=3;
8:       foo;
9:   }
10: bar
11: echo $x
  • 정적 범위를 사용하는 경우
    • 1행의 x는 전역 변수
    • 함수 bar은 라인 10에서 호출
    • 내부에서 foo를 호출
    • foo 함수는 3행에서 1을 인쇄 → 1행의 x를 사용
    • 그런 다음 x는 11번 라인에서 다시 인쇄 → x는 4번 라인에서 변경
      • 따라서 2를 인쇄

 

  • 동적 범위를 사용하는 경우 이 스크립트의 실제 출력
    • 3(3번째 줄에 인쇄)
      1(11번째 줄에 인쇄)
  • 3행에서 이름 x의 가장 최근 바인딩은 7행에 있다.
    • 따라서 3이 인쇄
  • 11번째 줄에서 x의 가장 최근 바인딩(4번째 줄의 2)이 이미 사라졌다.
  • 따라서 1이 인쇄

 


 

동적 범위의 장점

  • 프로그램을 다시 작성하지 않고 프로그램의 동작을 더 쉽게 수정할 수 있다.
  • 실제로 정적 범위 규칙 OOP를 사용하여 언어로 비슷한 작업을 수행할 수 있다.
    • 데코레이터 패턴
  • 그러나 코드를 쉽게 이해하기 어렵다.
코드 작성

function pizza() {
    echo "A pizza $toppings"
    toppings=""
}
function cheese() {
    toppings="$toppings+cheese"
}
function peperoni() {
    toppings="$toppings+peperoni"
}


코드 실행, 런타임 명령

#cheese pizza
cheese
pizza

#peperoni pizza
peperoni
pizza

#double cheese pizza
cheese
cheese
pizza
실행 결과

A pizza +cheese
A pizza +peperoni
A pizza +cheese+cheese









저작자표시 변경금지 (새창열림)

'프로그래밍언어론' 카테고리의 다른 글

[프로그래밍언어론] 15. 정적 관리(Static Management)  (0) 2023.10.11
[프로그래밍언어론] 14. 스택(Stack), 힙(Heap)  (0) 2023.10.11
[프로그래밍언어론] 12. 블록(Block), 환경(Environment)  (0) 2023.10.10
[프로그래밍언어론] 11. 이름(Name), 바인딩(Binding)  (1) 2023.10.10
[프로그래밍언어론] 10. 추상 구문 트리(AST)를 EBNF로 변환  (1) 2023.10.10
  1. 가시성 규칙(Visibility Rules)
  2. 환경
  3. 그래도 이것만으로는 부족하다.
  4. 범위 규칙(Scope Rules)
  5. 정적 vs. 동적
  6. 정적 범위 규칙
  7. 규칙 1. 지역 선언
  8. 규칙 2. 가장 가까운 중첩 범위
  9. 규칙 3: 블록에 할당된 이름
  10. 정적 범위의 장점
  11. 동적 범위
  12. 동적 범위의 장점
'프로그래밍언어론' 카테고리의 다른 글
  • [프로그래밍언어론] 15. 정적 관리(Static Management)
  • [프로그래밍언어론] 14. 스택(Stack), 힙(Heap)
  • [프로그래밍언어론] 12. 블록(Block), 환경(Environment)
  • [프로그래밍언어론] 11. 이름(Name), 바인딩(Binding)
파스텔코랄
파스텔코랄
Developer Blog 📜 Lots of rules and no mercy ✨
파스텔코랄
슬기로운 개발일지
파스텔코랄
전체
오늘
어제
  • 스터디
    • 컴퓨터시스템구조
    • 모바일프로그래밍
    • 프로그래밍언어론
    • 운영체제
    • 컴퓨터네트워크
    • 데이터분석
    • 소프트웨어공학
    • 시스템프로그래밍

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • About

링크

공지사항

인기 글

태그

프로그래밍언어론
운영체제
어셈블리어
네트워크

최근 댓글

최근 글

hELLO· Designed By정상우.v4.6.1
파스텔코랄
[프로그래밍언어론] 13. 가시성 규칙(Visibility Rules), 범위 규칙(Scope Rules)
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.