← 목록
한선씨 2026-06-18 6KB 읽기 6분

순수 한선씨 추출기(고수준→RPN) 완성

개요

C가 아닌 순수 한선씨로 작성된 고수준→RPN 트랜스파일러 tools/clike_to_rpn.한선를 무손실로 완성했다. 그동안 RPN 추출기는 C(hanseonc_high --rpn)뿐이었고, 순수 한선씨 트랜스파일러는 "깨짐+폐기 권장" 상태였다. 직접 수정 4건으로 모든 핵심 구문 + 깊은 중첩 + 정규/압축 양형식을 왕복 무손실로 통과시켰다.

검증 기준: 입력.한선 → (이 추출기) → .rpn.한선 → hanseonc_rpn → toau → crownyc run 출력이 hanseonc_high 직접 실행과 동일.

무엇을 했는지 (4개 직접 수정 — 각각 생성 RPN 검사→수정→왕복검증)

  1. foreach 버그: 반복 v 안에서 [10,20,30]의 배열 리터럴을 리스트 이름으로 그대로 RPN에 넣어 길이/꺼내가 실패(B=0). → 리스트 식을 식RPN로 임시변수(_lst)에 한 번 평가 후 순회하도록 수정.
  2. 시도/오류(try/catch) 신설: 줄변환에 핸들러 추가. 라벨 기반 @잡기 시도 / [본문] 잡아 @시도끝 점프 / .잡기 →e [catch본문] .시도끝. hanseonc_rpn은 시도(558)/잡아(559)/던져(560)/오류생성(562)을 이미 지원 → C 수정 불필요. (VM ABI: TRY=핸들러주소 pop 후 rpush(handler,sp,0), THROW=프레임 pop+sp복원+값 push+pc=handler, CATCH=정상경로 프레임 정리.)
  3. 계속(continue) 타겟 분리: for/foreach의 continue가 루프 최상단으로 점프해 증가 단계를 건너뛰어 무한루프. → 루프 스택에 "계속 라벨"을 3번째로 추가. 동안=최상단, 반복문/foreach=증가 직전 라벨(.포계속/.이치계속).
  4. 형식 정규화 정규화(t): 식RPN이 공백 구분 토크나이저라 s+i가 변환 안 됨. → 줄 단위로 모든 이항 연산자 양쪽 공백화 + ){) {. 문자열 리터럴 내부·==/<=/>=/!=·단항 -(피연산자 맥락 판별)는 보존. 헬퍼 오른트림/공백스킵/피연산자끝 추가.

검증 결과 (전부 왕복 티 일치)

  • 정규 10구문: 변수·만약·혹시·동안·반복문·foreach·탈출·계속·시도오류·함수재귀
  • 깊은 중첩 합성(함수+for+while+if/혹시/아니면+continue+try+foreach+throw)
  • 엣지: 탈출+계속 동일 루프, 중첩 루프 안쪽 계속, 음수/단항, 문자열 등호("a=b+c")
  • 정규 형식 + 압축 형식 양쪽 모두 무손실

관련 파일

  • /Users/ef/CrownyOS/crownyc/tools/clike_to_rpn.한선 (수정 본체, 백업 .bak)
  • /Users/ef/CrownyOS/crownyc/hanseonc_rpn.c (RPN→TOAU, 예외 키워드 기지원 — 무수정)
  • /Users/ef/CrownyOS/crownyc/crownyc.c (VM, 558/559/560 ABI — 무수정)

추가 수정 (2026-06-19, 실제파일 전수검증으로 발견)

실제 tests/*.한선 자족파일 종단검증 → 시작 38/48 → 40/48. 추가 직접수정:
  1. 단일행 블록 만약(x){ 출력값(1) } — 재귀 분할(매칭 }가 같은 줄일 때만), } 아니면 { 전이줄 보존.
  2. 문자열 다중연결 "a"+"b"+"c" — 식RPN이 "a"+"b"를 통째 문자열로 오인(첫·끝 따옴표) → 여는따옴표 짝이 마지막일 때만 인정.
  3. 괄호 그룹핑 (3+4)*2 — 전체괄호식 바깥괄호 벗기기.
  4. 프레임 기반 재귀 — 파라미터를 전역(→n)이 아닌 FRAME_ENTER 프레임에 저장. 이중재귀(피보) 정상화(55). 식RPN보다 스코프전역 먼저 선언, 인라인주석 금지, 배열인덱싱 배열명도 프레임해결.

개별 4개 추가 수정 (2026-06-19) → 43/48

  1. 연산자 좌결합 우선순위: 102000/10*255/10=260100(좌결합) — */보다 먼저 분할하던 버그. 식RPN을 4우선순위그룹(논리<비교<덧셈<곱셈)으로 재구성, 그룹 내 최우측 분할. (나눗셈회귀 통과)
  2. &&/||: opdb·그룹에 &&→그리고·||→또는 추가.
  3. 글자(s,i): hanseonc_high처럼 부분(s,i,i+1)(1글자)로 낮춤 (343=코드값 아님). (고수준_v10회귀 통과)
  4. 인자분리 문자열/대괄호 추적: ","(문자열 속 콤마)를 인자구분자로 오인하던 버그 → 인스트·대괄호깊이 추가. (opcode415 통과)

OOP 구현 (2026-06-19, 수정 #14~16) → 46/48

  1. 구조체+필드접근 (고수준_구조체): 구조체=맵, obj.field=맵꺼내(obj,"field"), 생성자 자동생성. 단일행 분리 제외.
  2. 메서드+가상디스패치 (동적디스패치): 메서드 타입.이름()→함수, obj.m()@m_dispatch 호출. 디스패치함수 파일끝 생성, __type__ 비교분기. (멍멍/야옹/음매)
  3. 상속 (구조체상속): 상속 키워드→부모필드 병합+메서드해결 부모체인 walk(override/상속 자동). (나는개/냠냠/바둑이/진돗개)
  • 트랜스파일러 자체 일관 키잉(필드명 문자열)이라 hanseonc_high의 해시 복제 불필요.

남은 2개 (46/48) — 전부 비-코어

  • 특수 빌트인 1 (벡터729): 큐브729생성/읽기·트릿6묶기·__내장__ 729-코덱 전용 빌트인 — hanseonc_rpn.c 키워드테이블 지원 필요(트랜스파일러 범위 밖).
  • 환경 1 (ab비교러너): 폰트파일 핸들(0 vs 경로) — 코어버그 아님.

반복 함정 (★)

hanseonc_high는 인라인 ; 주석(코드 뒤) 미지원 — 코드로 파싱돼 컴파일에러("미정의변수"/"→뒤 변수명필요"). 주석은 항상 전체줄. 이 세션 3회 자초.

잔여 이슈

  • 단일행 블록 만약 (x) { 출력값(1) }(문장과 {가 같은 줄)=미지원. 구조적 줄 분리(전처리) 필요.
  • 가져오기는 주석 처리(라이브러리 인라인 불가) — 내장함수만 사용하는 프로그램 대상.
  • 정규화는 줄 단위 char 스캔이라 매우 긴 줄에서 O(n²) — 일반 줄은 무해.

의의

"추출기도 C"였던 갭 해소. 4상태(고수준↔RPN↔크라우니어 TOAU↔2비트) 동시 포팅이 순수 한선씨 도구로 성립. 자체호스팅(C→한선씨) 한 칸 전진.

정직한 메타 교훈

검증은 양방향으로 어렵다. 서브에이전트는 거짓 성공(과대 PASS), 나는 거짓 실패를 냈다 — 테스트 입력의 압축 공백, macOS에 없는 timeout 명령, 단일행 블록을 3회 자초해 트랜스파일러를 실제보다 나쁘게 판정했다. 일관된 정규 형식 하니스 + 직접 왕복 실행으로만 진실이 확정된다.