Releases: rubidus-api/lowent_lang
Release list
v1.3.0 — build 도 거절된 프로그램을 짓지 않는다 · 언어 개정 1.3
Lowent is still under active development, and the language design is still changing. 문법·진단 코드·명령줄 옵션이 예고 없이 바뀔 수 있다.
무엇이 바뀌었나
언어 개정 1.2 → 1.3(깨지는 변경 넷), 도구 결함 둘을 고쳤고, README 를 새로 썼다.
⚠ 깨지는 변경 (언어 1.2 → 1.3)
| 무엇 | 이제 | 어기면 |
|---|---|---|
몸이 C 에 있는 extern |
블록 선언: unsafe extern proc f do <절>* end |
짝 없는 end 는 E-STMT-NODO, 블록에 문장을 적으면 E-FFI-BODY |
| op 머리의 절 | 문장처럼 저마다 자기 점으로 닫는다 | E-DOT-MISSING (전에는 다음 절 낱말이 앞 절을 대신 닫았다) |
filter·any·all 의 판정 op |
bool 을 내야 한다 |
E-PIPE-PRED (전에는 0 아닌 수를 참으로 읽었다) |
collect into · 내장 map·filter 의 받는 자리가 참 |
말없이 남은 원소를 버리지 않는다 | 길이를 알면 E-COLLECT-FULL, 모르면 넘치는 순간 멈춘다 |
서식기(--fmt)가 새 꼴로 쓴다.
고침
lowentc build가 거절될 프로그램을 짓고 돌렸다.--check를 건너뛰어return true .(u8 op) 같은 프로그램도 실행 파일이 되었다.
이제 짓기 전에 같은 검사를 돌리고, 거절이면 진단을 보이고 종료 코드 2 로 멈춘다(--run·--test와 같은 문).0x·0b만 적은 수가 0 이 되었다. 진법 표시 뒤에는 숫자가 하나 이상 와야 한다 —E-NUM-EMPTY. 0 은0x0으로 적는다.trust.find_anchor가 파일을 못 읽어도 «없다»(ok 0)로 답했다 →error unreadable/error short_workspace.
문서
- README 를 새로 썼다 — 영어판이 먼저, 한국어판은
README.ko.md. 맨 위에 개발 중 경고. - 매뉴얼: 명세·매뉴얼을 현황에 맞게 정리하고, 어려운 장(ch13·17·24·28·29·30·31 등)에 도해를 넣었다.
확인
회귀 시험(golden) 2,065 / 2,065 통과 · 게이트 t3 · VM·네이티브 대조 50,390 건 동일. 알려진 결함 0.
짓기
cd impl && make # → build/lowentc (C23 컴파일러와 POSIX 셸만 있으면 된다)
build/lowentc --version # lowentc 1.3.0v1.2.0 — do … end 는 짝인 괄호, 검사가 안 닿던 자리 둘
무엇이 바뀌었나
이 판은 둘을 고친다 — 문법의 닫는 규칙과 검사가 안 닿던 자리.
언어 개정 1.1 → 1.2(깨지는 변경 하나), 알려진 결함 2 → 0.
⚠ 깨지는 변경 — do … end 는 짝인 괄호다: end 는 자기 do 만 닫는다
end 는 이제 { } 의 } 처럼 자기 do 만 닫는다. 바깥 요소는 제 닫개를 스스로 챙긴다.
rem 블록을 몸으로 갖는 구문은 블록에서 끝난다 — 뒤에 점을 찍지 않는다
if eq a 0 . do return 1 . end else do return 2 . end
rem 블록을 품은 값을 쓰는 문장은 자기 점으로 닫는다
let p pt be make pt do x 1 . end .
| 경우 | 쓰는 법 | 어기면 |
|---|---|---|
블록을 몸으로 갖는 구문 (fn if else while for match case struct enum region borrow pipe …) |
블록이 끝나면 끝난다 | 뒤에 점을 찍으면 E-DOT-STRAY |
블록을 품은 값을 쓰는 문장 (let … be make T do … end ., return pipe xs do … end .) |
자기 점으로 닫는다. 괄호 안이면 ) 가 닫는다 |
E-DOT-MISSING |
| 블록 안의 문장 · 열거형 갈래 | 저마다 자기 점으로 닫는다 (end 가 대신 닫지 않는다) |
E-DOT-MISSING |
머리 없이 홀로 선 do … end |
쓸 수 없다 | E-BLOCK-NOHEAD |
- 전엔
end .와end가 같은 뜻의 두 철자였다 — 처리기가 뒤의 점을 빈 폼으로 조용히 버렸다.
그리고let … be make T do … end의end하나가make의 블록과let문장을 함께 끝냈다. - 머리 없는 블록은 전엔
--check를 통과하고 실행되지 않았다. - 서식기(
--fmt)도 이 규칙으로 쓴다. - 이 저장소의 코드·문서·시험 전부를 옮겼다. 옮기기 전과 뒤에 방출 C 가 973 파일 모두 바이트 동일하다.
- 정본 §6.1.6 (2)–(2d) 와 부록 A 에 적혀 있고 거부 예제가 붙어 있다.
- 범위 밖: 타입을 겹쳐 닫는 점(
slice u8 . .)과 괄호 안 점((mul a 2 .))은 아직 그대로 선다.
고침 — guard … else 가 타입 검사 밖이었다
output result … 인 op 이 guard … else return 0 . 처럼 맨값을 돌려줘도 --check 가 초록이었고,
실행하면 두 뒤끝 다 멈췄다. guard 의 else 가 통째로 검사 밖이었기 때문이다(그 블록 안의 let z u8 be 300 조차 통과했다).
- 이제
else뒤의 한 문장과 블록 전체가 타입 검사를 받는다(E-TYPE-RETURN등). return <op>으로 다른 op 의 실패를 넘기면try와 똑같은 errors 닫힘을 따른다(E-ERR-UNDECLARED).errors절이 없는 op 을try·return으로 넘기면 그 op 의 오류 타입 전체를 기준으로 본다(전엔 아무것도 대조하지 않았다).- 이 검사가 라이브러리의 버그 하나를 드러냈다:
lib/random.low의seed_from_os가output u64인데return ok 0을 내고 있었다.
고침 — link "…" 절이 거짓 E-VISIBILITY 를 냈다
link "…" 가 붙은 export op 을, link 라는 이름의 op 을 가진 모듈이 부르면 «export 안 된 이름» 이라는 틀린 진단이 났다.
가시성 검사가 op 머리의 절 낱말 link 를 그 모듈의 비공개 op 이름으로 읽었다. 이제 op 머리의 절 낱말은 이름 참조로 보지 않는다.
확인
- 골든 2,060 / 2,060 · 단위 시험 전부 통과 · 매뉴얼 예제 476 · 정본 예제 129.
- ★ 이 저장소의 크립토는 상수시간을 약속하지 않고 감사받지 않았다.
v1.1.0 — 계산 잎을 자리에 가두고, 암호를 OpenSSL 옆에 세운다
무엇이 바뀌었나
이 판은 암호 처리량과 어휘의 범위, 둘을 고친다.
⚠ 깨지는 변경 — 계산 잎은 call_builtin 뒤에서만 선다
전역 어휘가 199 까지 왔고, 늘어난 것은 대부분 «한 프로그램이 한 번 쓰는» 낱말이었다.
그래서 계산 잎 열다섯을 자리로 가뒀다:
rem 전
let n u64 be sha256 msg out .
rem 후
let n u64 be call_builtin sha256 msg out .
- 가둔 이름:
clmul_loclmul_hiaes_roundaes_round_lastaes_ctrghash
chacha20poly1305aes_gcmchacha_polysha256sha384sha512
crc32hash_bytesrng_next - 맨몸으로 부르면
E-BUILTIN-BARE, 닫힌 집합 밖의 이름이면E-BUILTIN-NAME. - 전역 어휘 199 → 185. 앞으로 계산 잎이 몇이 늘든 전역은 안 는다.
- 새 장치가 아니다 —
pipe … do take 3 … end의 닫힌 어휘와cast u8 x의 타입 자리가
이미 같은 규율을 쓴다: 자리가 정해져 있어 사용자 이름과 안 부딪친다. - 정본 §6.3.3 (1c)(1d) 에 적혀 있고 거부 예제가 붙어 있다.
암호 처리량
같은 상자에서 OpenSSL 과 나란히 잰 수다(Intel CC150 @3.5GHz, gcc, 정렬 판 셋의 각 열 최선).
★ 이 저장소의 크립토는 상수시간을 약속하지 않고 감사받지 않았다. 이 표의 쓸모는 회귀 기준선이다.
| 크기 | AES-128-GCM 전 | 후 | OpenSSL |
|---|---|---|---|
| 1 KiB | 153 | 1,234 | 2,019 |
| 16 KiB | 1,482 | 3,322 | 4,593 |
| 4 MiB | 303.7 | 3,680 | ~5,000 |
| 크기 | ChaCha20-Poly1305 전 | 후 | OpenSSL |
|---|---|---|---|
| 1 KiB | 536 | 1,007 | 1,753 |
| 16 KiB | 1,061 | 1,606 | 1,914 |
| 4 MiB | 68.6 | 1,574 | 2,059 |
잎 단독으로는 aes_ctr 가 5,490 MB/s 로 같은 상자 OpenSSL(5,449)과 같거나 빠르다.
무엇이 그렇게 만들었나:
- 여덟 덩이를 엮는다 —
aesenc는 답이 나오기까지 네 사이클이라, 한 덩이를 직렬로 돌리면
파이프라인이 비어 있다. 독립인 카운터 블록 여덟을 엮으면 그 구멍이 메워진다. - 축약을 캐리 없는 곱셈 둘로 — H 를 미리 나눠 두고 몽고메리 꼴로. GHASH 82 → 6,491 MB/s.
- 폭 — ChaCha20 은 AVX2 여덟 블록(89 → 2,439), Poly1305 은 AVX2 네 블록(331 → 4,787).
- 흐름과 누산을 한 바퀴에(AES-GCM) — 지난 덩이를 누산하며 이번 덩이를 흘린다.
- 한 판을 여는 값을 없앴다 — 메시지마다 키 스케줄을 다시 펴고 있었다(16,505 사이클).
CTR 은 평문이 0 이면 답이 곧AES_K(카운터)이므로 잎 두 번이면 된다.
이 하나로 1 KiB 가 여덟 배가 됐다.
새 낱말 넷 (전부 call_builtin 뒤)
chacha20 · poly1305 · aes_gcm · chacha_poly.
뜻은 모두 «있는 잎을 차례로 부른 것» 과 같고, 기계 판만 다르게 돈다 —
그래서 회귀 시험의 판정이 «따로 부른 것과 같은가» 하나로 환원된다.
--hw 가 폭과 지름길을 받는다
--hw none | auto | pclmul,aes,sse2,avx2,asm.
담는 범위는 빌드가 정하고, 담은 것이 둘 이상이면 시작할 때 한 번 골라 고정한다.
없는 기계에 담으라면 E-HW-TARGET 으로 거절한다 — 조용히 평범한 코드로 바꾸지 않는다.
확인한 것
- 골든 전량 통과 · 게이트 t3 통과
- NIST SP 800-38D GCM 벡터와 RFC 8439 (§2.3.2 · §2.5.2 · §2.8.2 · 변조 거절)가
none|sse2|avx2|aes|pclmul|auto여섯 모드와 VM 에서 모두 선다 - 낱말과 이 언어로 쓴 정의(
lib/aes.low·lib/chacha.low·lib/poly.low·lib/gcm.low)가
같은 답을 낸다 — 그 정의들은 지워지지 않았다
알려진 한계
- 상수시간을 약속하지 않고 감사받지 않았다.
- 기계 명령 경로는 x86-64 에서만 돈다. 다른 기계는 같은 답을 내는 셈 판으로 돈다.
- 호환성 epoch 는 여전히
provisional— 표면은 조용히 바뀌지 않지만, 바뀔 수는 있다.
Lowent Book v0.1.0 (draft)
Lowent Book v0.1.0 (초안 · draft)
한국어판과 영어판 PDF입니다. 10부 43장, 부록 넷, 찾아보기. 책에 실린 예제 225편은 모두 이 커밋의 lowentc 로 실제로 돌려 확인했습니다.
Korean and English PDF editions: 10 parts, 43 chapters, four appendices and an index. All 225 examples were run with lowentc at this commit.
lowent_book-v0.1.0-ko.pdf— 한국어판 (583쪽)lowent_book-v0.1.0-en.pdf— English edition (603 pages)
원고: docs/book/ · 본문 CC BY-NC-SA 4.0, 예제 MIT.
Source: docs/book/ · Text CC BY-NC-SA 4.0, examples MIT.