# NME 문법 레퍼런스 [English](language.md) | 한국어 [README](../README.ko.md) | [설치](install.ko.md) | [5분 시작](getting-started.ko.md) | [학습 과정](tutorial.ko.md) NME는 하나의 컴파일러 안에 세 문법 단계가 있습니다. 모드를 바꾸는 선언은 없습니다. 한 파일과 한 블록 안에서 고급 Python, 초급 NME, 문장형 NME, 한국어, 영어를 모두 섞을 수 있습니다. ## 호환성 규칙 올바른 Python이 항상 우선합니다. NME는 쉬운 문법을 찾기 전에 실제 Python 파서로 그 줄이 올바른지 확인합니다. 따라서 올바른 Python 프로그램은 바이트 하나도 바뀌지 않습니다. ```python say = print say("Python 호출") if 준비됨: print("Python 조건") ``` 세 단계는 다음처럼 같은 Python으로 컴파일될 수 있습니다. | 단계 | NME | 생성되는 Python | | --- | --- | --- | | 문장형 | `3번 반복해서 안녕 말해줘` | `for _ in range(3): print("안녕")` | | 초급 | `3번: 말해 "안녕"` | `for _ in range(3): print("안녕")` | | 고급 | `for _ in range(3): print("안녕")` | 그대로 유지 | ## 문장형 단계 문장형은 코딩 첫날을 위한 문법입니다. 아래의 자주 쓰는 작업에서는 따옴표, 쉼표, 괄호, 중괄호, 등호, 콜론이 필요하지 않습니다. 평범한 문장부호 `?`와 `!`는 따옴표 없이 쓸 수 있습니다. ### 글과 값 보여 주기 ```text 안녕하세요! 말해줘 보여줘 반갑습니다 보여줘 나 반갑습니다 show Hello world! Hello world show ``` 입력이나 문장형 저장으로 앞에서 만든 이름은 자동으로 값이 들어갑니다. ```text 이름을 물어봐 이름이 뭐예요? 물어봐 이름, 이름이 뭐예요? 안녕하세요 이름! 말해줘 ask name What is your name? show Hello name! ``` `이름`과 `name` 자리에는 실제 대답이 들어가고 나머지는 글로 남습니다. 알고 있는 한국어 이름 뒤의 조사는 출력에 그대로 붙습니다. 분명한 여러 단어 문장은 동작 단어 없이도 바로 보여 줍니다. ```text 오늘도 반가워요! Hello everyone! ``` 한 단어만 있는 줄은 올바른 Python 이름일 수 있으므로 Python 우선 규칙에 따라 그대로 둡니다. 한 단어를 출력하려면 `말해`나 `보여줘`를 붙이세요. 가장 짧은 대화는 질문과 특수문자가 없어도 됩니다. ```text 이름을 물어봐 안녕하세요 이름 말해줘 ``` 더 쉬운 첫 입력은 평범한 질문으로 적는 것입니다. ```text 이름이 뭐예요? 이름은 뭐예요? 나이는 몇 살이에요? 안녕하세요 이름! ``` 질문의 이름(`이름`, `나이`)에 답이 자동으로 저장됩니다. `몇 살이에요?`처럼 대상을 생략한 나이 질문도 `나이`에 저장합니다. 영어 `What is your name`, `What's your city?`, `How old are you`, `How old am I`도 같은 방식으로 동작합니다. 마지막 `?`는 생략할 수 있습니다. 숫자로 바꿔야 하거나 질문이 복잡하면 `숫자로 물어봐` 또는 명시적인 `물어봐`를 사용하세요. 출력 동작으로 `보여줘`, `말해줘`, `말해주세요`, `출력해`, `출력해줘`, `show`, `display`, `tell`, `say`를 쓸 수 있습니다. 정확한 초급 표기인 `말해 표현식`과 `say expression`은 올바른 Python 표현식을 코드로 처리합니다. ### 글이나 숫자 물어보기 ```text 이름을 물어봐 이름이 뭐예요? ask name What is your name? ask name, What is your name? 나이를 숫자로 물어봐 몇 살인가요? ask number age How old are you? ``` 따옴표 없는 질문 끝에는 입력하기 편하도록 공백이 자동으로 하나 붙습니다. 쉼표 뒤에도 평범한 문장을 쓸 수 있고, 따옴표나 표현식을 쓰는 정확한 초급형도 그대로 지원합니다. 글 입력은 `input(...)`, 숫자 입력은 `int(input(...))`로 컴파일됩니다. `물어봐`, `물어봐줘`, `질문해`, `입력받아`, `ask`, `prompt`를 쓸 수 있습니다. 입력받을 한국어 이름의 `을`과 `를`은 변수 이름에서 빠집니다. ### 값 저장하기 ```text 인사는 안녕하세요 정답은 7 점수에 1 더해 점수에서 1 빼줘 set greeting to Hello set answer to 7 greeting save Hello 이름 저장 민수 ``` 평범한 대입문으로 바뀝니다. `name save Mina`나 `이름 저장 민수`처럼 이름을 먼저 말하는 저장도 지원합니다. 숫자와 분명한 표현식은 코드, 평범한 단어는 글로 저장합니다. 저장한 이름은 뒤의 문장 출력과 조건에서 사용할 수 있습니다. 작은 값 변경은 `+`, `-`, `=` 없이도 쓸 수 있습니다. `점수에 1 더해`와 `점수에서 1 빼줘`처럼 적으면 Python의 대입으로 바뀝니다. 영어에서는 `score add 1`, `add 1 to score`, `score increase by 1`, `subtract 1 from score`도 사용할 수 있습니다. ### 반복하기 한 문장을 한 줄에서 반복합니다. ```text 3번 반복해서 다시 말해줘 repeat 3 times and show Again 3 times 반복해서 mixed 말해줘 3번 안녕하세요 3 times Welcome to NME ``` 횟수 뒤에 평범한 글을 바로 쓰면 그 글을 반복해서 출력합니다. 처음에는 이 형식을 쓰고, 뜻을 분명히 보이고 싶을 때만 `말해줘`나 `show`를 붙이세요. 여러 문장은 콜론 없이 들여씁니다. ```text 3번 반복해 첫째 말해줘 show second repeat 3 times show First 둘째 말해줘 ``` `반복`, `반복해`, `반복해서`, `repeat`를 `번` 또는 `times`와 섞어도 됩니다. 횟수에는 올바른 Python 표현식을 사용할 수 있습니다. 초급형 콜론 표기도 명시적인 닫는 말과 함께 쓰면 들여쓰기를 생략할 수 있습니다. ```text 3번: 첫 번째 문장 말해줘 두 번째 문장 말해줘 끝 ``` 영어 `3 times:`와 `end`도 같은 방식으로 작동합니다. 일반 Python `for`나 콜론이 붙은 `if`는 Python 문법이므로 Python의 들여쓰기 규칙을 그대로 따릅니다. ### 들여쓰기 없이 블록 닫기 Python으로 갈 준비가 되기 전에는 들여쓰기가 가장 어렵게 느껴질 수 있습니다. 이때는 블록 안 문장을 다음 줄에 그대로 쓰고 마지막에 `끝` 또는 `end`를 한 줄로 적으면 됩니다. 이 방식으로 Python으로 넘어갈 때 필요한 제어 흐름도 배웁니다. ```text 점수는 0 점수가 3보다 작을 동안 점수 말해줘 점수는 점수 + 1 끝 만약 준비 그리고 점수가 2보다 크면 성공 말해줘 아니면 만약에 점수가 0과 같으면 다시 말해줘 아니면 아직 말해줘 끝 동안 준비 또는 기다리는중 계속 말해줘 멈춰 끝 ``` `동안`, `만약`, `아니면`, `아니면만약에`, `멈춰`, `끝`은 영어 `while`, `if`, `else`, `elif`, `break`, `end`와 같은 뜻입니다. `그리고`와 `또는`은 각각 `and`와 `or`로 섞어 쓸 수 있습니다. 익숙해지면 같은 블록을 네 칸 들여쓰기로 쓰거나 Python 문법으로 한 줄씩 바꿔도 됩니다. `준비하는동안`, `준비 하는 동안`, `준비 동안`처럼 주어 뒤에 `동안`을 붙여 말해도 됩니다. 영어 `while` 키워드 뒤에 한국어 문장 조건과 `동안` 끝맺음을 섞어서도 쓸 수 있습니다. 예: `while 점수가 3보다 작을 동안`. ### 조건 사용하기 콜론이 없는 블록입니다. ```text 만약에 이름이 있으면 안녕하세요 이름 말해줘 if 준비됨 show 시작 ``` 한 문장은 `then`이나 `하면` 같은 한국어 연결 어미 뒤에 바로 적습니다. ```text 만약에 점수가 10보다 크면 성공 말해줘 if score is greater than 10 then show You won ``` `만약`을 앞에 쓰지 않고 주어부터 말해도 됩니다. ```text 점수가 5보다 크면 높아요 말해줘 이름이 있으면 환영해요 이름 말해줘 색이 빨강과 같으면 맞아요 말해줘 ``` 비교·존재 확인과 실행 동작이 분명할 때만 이 형태로 해석합니다. `Hello then world`처럼 평범한 말은 문장 출력으로 남습니다. 지원하는 문장형 비교입니다. | 한국어 | 영어 | 뜻 | | --- | --- | --- | | `만약에 이름이 있으면` | `if name exists` | 값이 있음/참 | | `만약에 이름이 없으면` | `if name missing` | 값이 없음/거짓 | | `만약에 점수가 10과 같으면` | `if score equals 10` | `==` | | `만약에 점수가 10과 같지 않으면` | `if score is not equal to 10` | `!=` | | `만약에 점수가 10보다 크면` | `if score is greater than 10` | `>` | | `만약에 점수가 10보다 작으면` | `if score is less than 10` | `<` | `만약 조건`, `만약에 조건`, `when condition`, 혼합형 `if 조건`도 전부 동작합니다. 모든 Python 표현식이 필요한 조건은 정확한 초급형을 쓰세요. `and`는 `or`보다 먼저 계산됩니다. 영어와 한국어를 섞어도 됩니다. ```text if 준비 그리고 점수 > 2 then 성공 말해줘 만약 준비 또는 기다리는중이 있으면 기다려 말해줘 ``` `만약`이나 `동안` 헤더에서 괄호로 NME 조건 전체를 감쌀 수도 있습니다. 예를 들어 `만약 (준비 그리고 점수 > 2)`처럼 씁니다. NME 블록으로 해석하려면 헤더에 콜론을 붙이지 않아야 하며, `when(ready and score > 2)`처럼 올바른 Python 호출은 바이트 단위로 그대로 Python으로 남습니다. 자연스러운 조건 끝말도 `만약 (점수가 2보다 작으면)`처럼 괄호 안에 둘 수 있습니다. 괄호 안의 논리 연결어 앞에 조건 끝말을 둘 수도 있습니다. 예를 들어 `만약 (점수가 2보다 크면 그리고 준비)`처럼 씁니다. 같은 방식으로 한국어 `while` 끝말도 `동안 (횟수가 2보다 작을 동안 그리고 준비)`처럼 쓸 수 있습니다. 연결어 표기는 섞어도 되므로 `만약 (점수가 2보다 크면 and 준비)`처럼 적을 수도 있습니다. 한국어 NME 동작어는 올바른 Python 식별자이기도 합니다. 따라서 `만약`이 바인딩된 상태에서 `만약 (준비)`는 올바른 Python 호출 형태이므로 바이트 단위로 그대로 남습니다. NME 블록으로 쓰려면 `만약 준비라면`처럼 문장형 조건 끝말을 붙이거나, `만약 ((준비 그리고 참))`처럼 NME 연결어를 넣어 주세요. ### 코드용 특수문자 없는 랜덤 ```text 주사위는 1부터 6까지 랜덤정수 주사위 말해줘 색은 빨강 또는 초록 또는 파랑 중에서 랜덤선택 show 색 ``` Python에 포함된 `random`을 바로 사용하므로 별도 모듈 줄도 필요 없습니다. ### 오타와 연결어 복구 문서에 있는 동작 단어와 논리·조건 연결어의 여러 표현을 받아들이며, Python이 그 줄을 거부한 뒤에 한 글자 삽입·삭제·교체 또는 붙어 있는 두 글자 순서 바뀜을 복구합니다. 글자 하나가 더해지거나 빠지면서 자리 바꿈이 함께 생긴 흔한 오타도 뜻이 하나면 복구합니다. `물어바` → `물어봐`, `말헤` → `말해`, `repaet` → `repeat`, `shwoe` → `show`, `thne` → `then`, `그리거` → `그리고`, `같먄` → `같으면`, `만악에` → `만약에`가 예입니다. 한국어 조건은 `이름이 철수면`, `이름이 철수라면`, `준비가 거짓이면`처럼 짧게 말해도 됩니다. 조사를 띄워 `이름 이 철수 면`이라고 쓰거나 `준비면`처럼 주어 뒤에 바로 말해도 됩니다. `있으먄`, `철수먄`, `같먄`, `만악에`처럼 연결 어미를 한 글자 잘못 쓴 경우도 뜻이 하나면 복구합니다. 이 형태는 한 줄 조건에서만 쓸 수 있어요. 복구는 동작·조건 연결 토큰에만 적용하며 Python 표현식, 문자열, 주석은 고치지 않습니다. 고칠 방법이 하나로 정해지지 않거나 동작이 분명하지 않으면 억지로 추측하지 않고 정확한 위치와 고치는 예시를 보여 줍니다. 모든 가능한 오타와 모든 사람의 문장을 안전하게 추측할 수 있는 컴파일러는 없으므로 이 경계는 의도적입니다. ## 초급 단계 초급 문법은 짧고 정확합니다. 모든 Python 표현식을 쓸 수 있으며 문장형 해석이 애매할 때 유용합니다. 문서에 있는 초급 동작은 모두 한국어 이름이 있으며 한 줄에서 영어와 한국어를 섞어도 됩니다. 아래 `<...>` 부분은 실제 값으로 바꿔 써야 하는 자리 표시자입니다. 그대로 복사하지 말고 `<>`를 알맞은 값으로 바꾸세요: ```text 말해 say 물어봐 <이름> 물어봐 <이름>, 저장 <이름> <값> 설정 <이름> <값> 저장 <이름>을 <값> save to ask ask , <횟수>번: times: 만약 <조건>: when : 동안 <조건> while 멈춰 break 아니면 만약에 <조건> 아니면만약에 <조건> else if 아니면 else 끝 end 랜덤 사용 use random 영지식 사용 use zero_knowledge ``` 콜론 뒤에 한 문장을 바로 쓰거나 여러 줄을 들여쓸 수 있습니다. ```text 3번: 말해 "안녕" 3 times: say "Hi" print("고급 Python도 가능") ``` 정확한 변환입니다. | NME | Python | | --- | --- | | `말해 값` / `say value` | `print(value)` | | `물어봐 이름` / `ask name` | `name = input()` | | `물어봐 이름, 질문` | `name = input(prompt)` | | `저장 이름 값` / `save name to value` | `name = value` | | `횟수번:` / `count times:` | `for _ in range(count):` | | `만약 조건:` / `when condition:` | `if (condition):` | | `동안 조건` ... `끝` / `while condition` ... `end` | `while (condition):` | | `멈춰` / `break` | `break` | | `아니면 만약에 조건` / `아니면만약에 조건` / `else if condition` | `elif (condition):` | | `아니면` / `else` | `else:` | 표현식은 NME가 다시 만들지 않는 Python 원본 범위입니다. 올바른지만 확인하고 적힌 그대로 복사합니다. ## 고급 단계 고급 NME는 Python 문법과 같습니다. 대입, 함수, 클래스, import, 예외, 비동기 코드, 패턴 매칭, 설치한 Python 패키지와 모든 올바른 Python 기능이 변경 없이 동작합니다. ```python from pathlib import Path def 단어들(경로): return Path(경로).read_text(encoding="utf-8").split() for 단어 in 단어들("notes.txt"): show 단어 ``` 마지막 줄처럼 고급 Python 블록 안에 영어 문장형 NME를 쓸 수 있습니다. ## 버전이 있는 내장 모듈 NME에는 초보자용 모듈 세 개가 들어 있습니다: 주사위·선택용 `random`(`랜덤`), 읽기·쓰기·JSON용 `file`(`파일`), 실제 슈노르 지식 증명 계산을 제공하는 `zero_knowledge`(`영지식`)입니다. 랜덤과 파일 어댑터는 `0.0.1`, 영지식 어댑터는 `0.0.2`가 내장됩니다. 모듈마다 `사용` 줄 하나면 충분하며 같은 모듈을 두 번 가져오면 충돌 오류가 납니다. ```text 랜덤 사용 파일 사용 영지식 사용 ``` `랜덤 사용 최신`, `최신 랜덤 사용`, `랜덤 사용 버전 "0.0.1"`도 같은 뜻이며, 영어 표기 `use random`, `use random latest`, `use latest random`, `use random version "0.0.1"`도 같습니다. `file` 모듈도 같은 형태를 `file`/`파일`로 받습니다: `파일 사용`, `파일 사용 최신`, `파일 사용 버전 "0.0.1"`. 영지식 어댑터는 `zero_knowledge`/`영지식`을 같은 방식으로 받으며 `영지식 사용 최신`도 사용할 수 있습니다. 구두점 없는 영어 문장형 소스에서는 밑줄 없는 별칭 `use zeroknowledge latest`도 같은 모듈을 불러옵니다. `최신` / `latest`는 설치한 NME 컴파일러에 들어 있는 가장 새 어댑터를 고릅니다. 제어되지 않은 네트워크 업데이트가 아니라 로컬에서 항상 같은 결과를 내는 선택입니다. 없는 정확한 버전을 요청하면 설치된 버전을 알려 주는 오류가 나옵니다. `랜덤 사요 최신`처럼 뜻이 분명한 한 글자 오타도 복구합니다. 어느 언어로 불러와도 두 언어의 이름이 모두 생깁니다. | 한국어 | 영어 | Python 뜻 | | --- | --- | --- | | `랜덤정수(가, 나)` | `random_number(a, b)` | `random.randint(a, b)` | | `랜덤선택(값들)` | `random_pick(values)` | `random.choice(values)` | | `섞기(값들)` | `shuffle(values)` | `random.shuffle(values)` | | `랜덤버전` | `random_version` | 어댑터 버전 문자열 | | 한국어 | 영어 | Python 뜻 | | --- | --- | --- | | `파일읽기(경로)` | `file_read(path)` | `pathlib.Path(path).read_text()` | | `파일쓰기(경로, 내용)` | `file_write(path, text)` | `pathlib.Path(path).write_text(text)` | | `json읽기(경로)` | `json_load(path)` | `json.loads(pathlib.Path(path).read_text())` | | `json저장(경로, 값)` | `json_save(path, value)` | `pathlib.Path(path).write_text(json.dumps(value))` | | `파일버전` | `file_version` | 어댑터 버전 문자열 | 모든 내장 모듈은 위의 도우미 이름을 예약합니다. 이미 같은 이름을 쓰고 있으면 값을 조용히 덮어쓰지 않고 이름을 바꾸라는 오류를 보여 줍니다. ### 슈노르 영지식 어댑터 영지식 어댑터는 고정된 유한체 군을 사용합니다. 3072비트 안전 소수인 RFC 3526 MODP 그룹 15, 생성원 2, 소수 차수 부분군 `q = (p - 1) / 2`, 256비트 검증자 도전을 사용합니다. 보안 난수는 Python의 `secrets`에서 가져옵니다. | 한국어 도우미 | 영어 도우미 | 뜻 | | --- | --- | --- | | `영지식비밀만들기()` | `zk_secret()` | 0이 아닌 비밀 스칼라 만들기 | | `영지식공개값(비밀값)` | `zk_public(secret)` | 공개값 만들기 | | `영지식일회값만들기()` | `zk_nonce()` | 증명자의 일회값 만들기 | | `영지식약속(일회값)` | `zk_commitment(nonce)` | 슈노르 첫 메시지 만들기 | | `영지식도전만들기()` | `zk_challenge()` | 새 256비트 검증자 도전 만들기 | | `영지식다른도전(도전값)` | `zk_challenge_except(c)` | 주어진 값과 다른 새 도전 만들기 | | `영지식응답(일회값,비밀값,도전값)` | `zk_response(v,a,c)` | 슈노르 응답 만들기 | | `영지식검증(공개값,약속값,도전값,응답값)` | `zk_verify(A,V,c,r)` | 증명 전사록 검증하기 | | `영지식모의응답만들기()` | `zk_simulated_response()` | 모의 응답 고르기 | | `영지식모의약속(공개값,도전값,응답값)` | `zk_simulated_commitment(A,c,r)` | 미리 고른 도전용 전사록 모의하기 | 완전한 증명 흐름은 괄호 없이 한국어와 영어 문장형으로도 쓸 수 있습니다. 영어에서는 `zero knowledge secret make`, `secret zero knowledge public make`, `zero knowledge nonce make`, `nonce zero knowledge commitment make`, `secret context zero knowledge proof make`, `public proof context zero knowledge verify`, `public commitment context zero knowledge challenge make`를 사용합니다. 순수 영어 문장형 예시는 `examples/needmorecoin-sentence.en.nme`, 한국어 증명 흐름은 `examples/zk-schnorr-relay.ko.nme`를 보세요. 검증 함수는 슈노르 등식을 확인하기 전에 공개값과 약속값의 부분군 소속, 응답 범위, 도전 범위를 검사합니다. 저장된 전사록은 다른 새 도전에 답할 수 없습니다. 반면 도전을 미리 고르면 비밀값 없이도 그 도전용 전사록을 모의할 수 있어 영지식 성질을 보여 줍니다. 실시간 중계는 다른 문제입니다. 공격자가 검증자의 도전을 실제 증명자에게 즉시 전달하고 실제 응답을 되돌려 주면 검증은 통과할 수 있습니다. 중계 저항이 필요한 인증은 의도한 채널이나 세션에 별도로 결합해야 합니다. 이 어댑터는 수학적으로 실제 슈노르 계산을 쓰는 학습·기준 구현입니다. CPython 큰 정수 연산은 상수 시간이나 부채널 방어를 보장하지 않으므로 실제 자격 증명, 돈, 민감한 시스템에는 감사된 실서비스 암호 구현을 사용하세요. `nme 모듈`(영어 `nme modules`)로 버전과 이름을 확인합니다. 파일은 프로그램을 실행하는 폴더에 만들어지므로 프로젝트 폴더에 저장하세요. 보안 번호나 비밀번호에는 랜덤 도구를 사용하지 마세요. ## 모듈: 다른 `.nme` 프로그램 가져오기 같은 폴더에 있는 다른 `.nme` 파일에서 이름 있는 값을 가져올 수 있습니다. 이름 목록이 곧 모듈의 인터페이스입니다. 그 이름들만 파일 경계를 넘으므로 숨은 전역 상태가 없습니다: ```text from "helper.nme" import greet, score show greet ``` 모듈 파일은 일반 NME 또는 Python으로 값을 정의합니다: ```text # helper.nme greet = "hello" score = 0 ``` `nme 실행`(`nme 검사`/`nme 빌드`도)은 주 프로그램 옆에서 `helper.nme`를 찾아 변환하고 가져올 수 있게 만듭니다. 모듈 오류는 모듈 파일 이름과 함께 표시됩니다. 가져오기는 이어질 수 있고(`helper.nme`가 다른 모듈을 가져올 수 있음), 파일 이름은 Python 식별자여야 하며(`my-helper.nme`나 `shapes.ko.nme`는 안 됨), 두 모듈이 이름을 공유하면 안 됩니다. 이 충돌은 고치는 방법을 안내하는 E9028로 표시됩니다. `nme 컴파일`(영어 `nme compile`)은 아직 모듈 가져오기를 지원하지 않아 E9029를 표시하므로, 다른 `.nme` 파일을 가져오는 프로그램은 `nme 실행`, `nme 검사`, 또는 `nme 빌드`를 사용하세요. 가져온 파일을 열 수 없으면 CLI가 모듈 경로와 함께 E9007을 표시합니다. 문장형에서는 모듈 줄이나 Python 특수문자 없이도 파일을 읽고 쓸 수 있습니다. 경로는 항상 따옴표로 감싼 문자열입니다. ```text read "notes.txt" into memo memo read "notes.txt" memo에 "notes.txt" 읽어서 memo에 "notes.txt" 읽어서 저장해 ``` ```text write "hello" to "out.txt" "out.txt" 파일에 "hello"를 저장해 ``` 이 문장들은 `pathlib.Path(...).read_text()` / `.write_text(...)` 줄로 내려가므로 만들어진 Python이 `file` 모듈이 가르치는 것과 같은 표준 라이브러리입니다. `read the book`이나 `write hello`처럼 애매한 줄은 파일 동작이 아니라 평범한 문장 출력으로 남습니다. ## 프로그램 인자로 실행하기 프로그램 이름 뒤에 적은 말은 `python program.py ...`처럼 프로그램으로 전달됩니다: ```sh nme 실행 greet Mina nme r dice 6 nme 실행 todo add "buy milk" ``` 프로그램은 `sys.argv`에서 읽습니다: `sys.argv[0]`은 프로그램 경로, `sys.argv[1]`부터가 인자입니다. `--python` 같은 옵션은 파일 이름 앞에 있어야 하고, 파일 이름 뒤의 모든 말은 프로그램의 것입니다. ## 네이티브 백엔드 제한된, 정적 타입의 코어 부분집합은 CPython과 무관하게 바로 네이티브 기계어로 컴파일할 수 있습니다. `nme 네이티브 실행 hello`는 시스템 C 컴파일러로 C를 만들어 실행 파일을 돌리고, `nme 네이티브 빌드 hello -o hello`는 C 소스와 실행 파일을 남깁니다. 네이티브 코어: 불리언·정수·유한 실수 값과 `+ - * %` 산술(정수 나머지; 실수 나머지는 거부); 문자열 리터럴·변수와 이항 `+` 이어붙이기 하나, `len`, 문자열 `==`/`!=` 비교; 정수·실수·문자열 비교(그리고 `<=`/`>=`와 자연어 "or equal" 연결사)와 정수·유한 실수 참/거짓(`if ready`, `while turns`; 0은 거짓), 불리언 리터럴·바인딩(`if ready`, `while ready`; `False`는 거짓), 불리언 같음·다름 비교의 `while`/`if`/`else`/`else if`; 초급 `번:`(`times:`) 반복; `break`; 논리 `and`/`or` 조건은 Python 우선순위와 단락 평가를 따르며; `if`/`else` 블록 뒤로 계속되는 모든 경로에서 대입한 이름은 그 뒤에 사용할 수 있고, 일찍 반환하거나 감싼 반복문을 빠져나가는 분기는 그 이름을 대입할 필요가 없으며, 종료 경로 안에 중첩 조건문이 있어도 같은 규칙을 따릅니다. 정수 스칼라 매개변수와 필요한 최상위 정수 `return`을 쓰는 함수(재귀 동작); 정수·실수·불리언·문자열의 `say`/`show`/`말해`. 불리언 산술·값 변경·불리언 함수 인자와 반환·일반 Python `for` 반복문·Python 인라인 본문·인라인 값 변경은 네이티브 코어 밖입니다. 문장형 반복과 초급 `times:`/`번:` 반복은 한 줄 NME 출력 본문을 쓸 수 있고, `then`/`그러면` 뒤의 한 줄 NME `say`/`show`/`말해` 또는 `break` 본문은 이 제어문과 분기 사슬에서 지원합니다. 한 줄 `break`는 네이티브 반복문 안에서만 쓸 수 있으며, 밖에서는 `E0102`로 거부됩니다. 문장형 반복도 `3번 반복해서 여기서 멈춰`처럼 문장형 한 줄 `break` 본문을 쓸 수 있습니다. 실수 산술 결과가 유한하지 않게 되면 이중 언어 런타임 오류로 멈춥니다. 그 밖의 모든 것 — 입력, 모듈, 파일, 클래스, 패키지 — 은 명확한 진단으로 거부되며 `nme 실행`으로 CPython에서 그대로 실행됩니다. C 키워드와 충돌하는 식별자는 바꾸지 않고 거부합니다. 허용 표면은 [네이티브 코어 레퍼런스](native-reference.ko.md)에, 설계와 정직하게 측정한 벤치마크는 [네이티브 백엔드 메모](native-backend.ko.md)에 있습니다. ## Python 변환 `nme 변환`은 고른 단계와 언어로 Python을 안전하게 바꿉니다. ```sh nme 변환 app.py --level 문장형 --language 한국어 -o app.nme ``` 뜻을 보존할 수 있는 단일 값 `print`, `input` 대입, `int(input(...))`, `for _ in range(...)`, `if`, 간단한 대입을 바꿉니다. 일반 `import random`은 이름이 덮어써질 위험이 있어 그대로 고급 Python으로 둡니다. 나머지는 올바른 NME인 고급 Python으로 남깁니다. [Python 변환 안내](converting-python.ko.md)를 참고하세요. ## 소스 보존과 오류 - Python 토큰화가 문자열과 주석을 보호합니다. - 올바른 Python은 바이트 단위로 같습니다. - 들여쓰기, 빈 줄, 주석, 줄바꿈 방식, 실제 줄 수를 보존합니다. - NME 오류에는 쉬운 설명, 정확한 캐럿 위치, 고치는 힌트가 있습니다. - 모든 오류에는 `E0102` 같은 안정적인 오류 코드가 붙어 있으며 `error[E0102]:`처럼 메시지 옆에 표시됩니다. 자세한 한국어 설명은 `nme ko <코드>`(영어는 `nme en <코드>`)로 볼 수 있고, `nme ko`만 실행하면 모든 코드를 나열해 줍니다. 컴파일러 오류는 `E0001`부터, 명령줄 오류(파일 없음, 알 수 없는 명령, Python 시작 실패)는 `E9xxx` 번호를 쓰며 같은 방식으로 설명됩니다. - Python `def` 함수 밖의 최상위 또는 인라인 `return`에는 이중 언어 `E0106` 오류와 고치는 힌트가 표시됩니다. 한 줄 클래스 본문도 바깥 함수 문맥을 물려받지 않으며, 함수 안의 올바른 `return`은 Python으로 그대로 남습니다. - 반복문 밖의 최상위 또는 인라인 Python `continue`에는 이중 언어 `E0107` 오류와 고치는 힌트가 표시됩니다. 한 줄 함수·클래스 본문은 바깥 반복문을 물려받지 않고, 반복문 안의 올바른 `continue`는 Python으로 그대로 남습니다. - 반복문 밖의 Python `break`에는 `E0102`가 표시됩니다. 한 줄 함수·클래스 본문은 바깥 반복문을 물려받지 않으며, 반복문 안의 올바른 `break`는 그대로 남습니다. 같은 한 줄 본문에서 앞에 세미콜론으로 구분한 단순 문장이 있어도 이 검사는 적용됩니다. - 함수 밖의 최상위 또는 인라인 Python `yield`에는 `E0108`, `async def` 함수 밖의 `await`에는 `E0109`가 표시됩니다. 올바른 제너레이터와 비동기 함수 본문은 Python으로 그대로 남습니다. - `async def` 함수 안의 `yield from`에는 `E0110`이 표시됩니다. 그 안에서는 `async for`를 사용하고, 일반 제너레이터 함수의 `yield from`은 그대로 둘 수 있습니다. - `async def` 함수 밖의 Python `async for`와 `async with`에는 각각 `E0111`과 `E0112`가 표시됩니다. 올바른 비동기 함수 본문은 그대로 보존됩니다. - 바깥 함수가 없는 Python `nonlocal`에는 한 줄 함수·클래스 본문을 포함해 `E0113`이 표시됩니다. 바깥 함수 아래의 중첩 함수나 클래스에서는 그대로 보존하며, 요청한 이름이 그 바깥 함수에 실제로 바인딩됐는지는 CPython이 따로 검사합니다. - Python 함수나 클래스 안의 `from ... import *`에는 한 줄 본문과 앞선 세미콜론 구분 문장 뒤의 별표 import를 포함해 `E0114`가 표시되므로 그 안에서는 이름을 명시적으로 import하세요. 모듈 수준의 별표 import와 모듈 수준 조건문 안의 사용은 그대로 보존됩니다. - Python은 `except*` 블록 안의 `break`, `continue`, `return`을 허용하지 않으며, 핸들러 안에서 앞선 세미콜론 구분 문장 뒤에 나와도 NME는 `E0115`를 표시합니다. 중첩 함수 본문과 핸들러 뒤의 제어 흐름은 그대로 보존됩니다. - Python은 리스트·집합·딕셔너리·제너레이터 컴프리헨션 안의 `yield`를 허용하지 않으며 NME는 `E0116`을 표시합니다. 일반 `yield` 표현식과 Python이 허용하는 제너레이터 람다는 그대로 보존됩니다. - `async def` 함수 밖의 리스트·집합·딕셔너리·제너레이터 컴프리헨션에 `async for`가 있으면 `E0117`이 표시됩니다. 컴프리헨션을 비동기 함수 안으로 옮기고, 올바른 비동기 컴프리헨션은 그대로 보존됩니다. - 비동기 제너레이터에서는 값을 반환할 수 없으며 NME는 첫 `yield`보다 앞에 있는 반환에도 `E0118`을 표시합니다. `async def stream(): yield 1; return 2`처럼 한 줄에 쓴 Python 본문도 들여쓴 본문과 같은 함수 문맥으로 처리하고, 값 없는 `return`과 중첩 함수 안의 반환은 올바른 Python으로 남습니다. - 같은 범위에서 이름을 먼저 사용하거나 대입한 뒤의 `global`·`nonlocal` 선언에는 한 줄 본문을 포함해 각각 `E0119`·`E0120`이 표시되며, 매개변수와 annotation 대상에는 두 선언을 사용할 수 없습니다. 선언을 먼저 적고, annotation에서 사용한 이름도 사용으로 계산합니다. f-string 검증은 CPython에 맡기며 올바른 모듈·중첩 함수·컴프리헨션 범위는 보존됩니다. - 제너레이터 람다는 올바른 고급 Python으로 남습니다. `lambda: ...` 안의 `yield`는 람다 자체의 함수 문맥에서 검사됩니다. - 인라인 본문에는 실행 문장 하나만 쓸 수 있습니다. 열린 조건이 없는 인라인 `else`/`elif`는 `E0103`으로 거부되므로, 가지 줄은 `끝` 앞의 같은 명시적 조건 블록에 적어 주세요. - 가능하면 서로 독립적인 문제를 한 번에 모읍니다. - 한국어 CLI 명령으로 시작한 오류는 `nme 실행`, `nme 컴파일`, `nme 설치`처럼 한국어 명령을 먼저 안내하고, 영어 명령으로 시작한 오류는 영어로만 안내합니다. ## 현재 제한 - 문장 출력은 간단한 대입, 함수 매개변수, 단순한 Python 반복 변수, NME 입력, 문장형 저장으로 만든 이름을 찾습니다. 동적으로 만든 특이한 이름이나 애매한 글은 초급 표현식을 쓰세요. - 문장형 비교 단어는 의도적으로 작습니다. `그리고`/`또는` 논리와 복잡한 표현식은 명시적 `끝` 블록이나 고급 Python을 쓰세요. - 내장 `random`, `file`, `zero_knowledge` 모듈은 이 베타에서 쉬운 모듈 문법을 지원하며, 다른 Python 라이브러리는 일반 `import`를 사용합니다. - 영지식 어댑터는 학습·기준 구현이며 부채널 방어가 된 실서비스 암호 라이브러리를 대신하지 않습니다. - `검사`와 `빌드`는 생성된 Python을 선택한 CPython으로 컴파일까지 확인하지만 실행하지는 않습니다. 실행 오류는 CPython이 담당합니다. - `실행`, `빌드`, `검사`에는 CPython이 필요합니다. 선택적인 `컴파일`에는 Python, Nuitka, 운영체제용 C 컴파일러가 필요합니다. - 네이티브 컴파일이 모든 프로그램을 무조건 빠르고 작게 만들지는 않습니다. 필요한 결과물을 직접 측정하세요.