연결됨 다시 연결 중 다시 연결 연결 실패 연결 일시 중지 복구 실패
공개 지식 로그 출처 @dimohy 리비전 v1 3개 관련 로그 1개 이전/다음 로그 0개 댓글

Sollang의 Stream이 이제 Stage2와 웹에서 끝까지 흐릅니다

공개 로그
@dimohy 팔로우 0개 2026.07.25 11 분 4 조회관계 잇기

로그 요약

본문과 댓글은 @dimohy의 #sollang 태그, Sollang 개발기 시리즈, 리비전 v1, 1개 이전/다음 로그에 이어진 지식 로그입니다.

주요 태그 #sollang 로그 시리즈 Sollang 개발기 리비전 v1 3개 관련 로그 1개 이전/다음 로그

지연 실행 Stream<T>, EventStream<T>, Stage2 WASM, 정확한 31개 출력 회귀와 모바일 플레이그라운드 개선까지 마친 개발 기록입니다.

Sollang의 Stream 작업을 이번에는 정말 끝까지 연결했습니다.

처음 질문은 단순했습니다. LINQ처럼 만든 stream을 변수에 담은 뒤 다시 each할 수 있는가? 결과를 먼저 메모리에 복사하지 않고 바로 흘려보낼 수 있는가? 마우스 클릭이나 이동 같은 이벤트도 같은 조합 방식으로 처리할 수 있는가?

이번 작업의 답은 가능하다입니다.

Stream<T>는 컨테이너가 아니라 실행 계획입니다

Stream<T>를 변수에 담아도 결과 배열을 즉시 만들지 않습니다. 변수에는 지연 실행 계획이 남고, each, fold, take 같은 terminal 연산이 붙는 순간 upstream에서 필요한 값만 당겨옵니다.

그래서 10억 개 센서 값을 선언해도 10억 개를 메모리에 만들지 않습니다. 현재 예제는 경고 5개를 얻기 위해 실제로 54개만 읽고 멈춥니다. flatMap 안쪽에서도 downstream take가 채워지면 중첩 upstream 전체가 즉시 취소됩니다.

이 구조는 라이브러리 경계에서도 동일합니다. 사용자가 만든 stream 함수가 실행 계획을 반환하고, 호출자가 나중에 each로 소비할 수 있습니다.

EventStream<T>도 같은 조합 모델을 사용합니다

마우스 이동과 클릭처럼 값이 앞으로 도착하는 입력은 EventStream<T>로 분리했습니다. pull 기반 Stream<T>와 수명 모델은 다르지만 map/filter/take 같은 조합 감각은 유지합니다.

네이티브 이벤트 스트림은 bounded queue, overflow 정책, 구독 해제와 drop을 명시적으로 다룹니다. 브라우저 타깃은 아직 host callback lowering이 없는 상태를 조용히 무시하지 않고, 현재 사용할 수 없다는 컴파일 진단을 냅니다. 지원하지 않는 기능을 성공한 것처럼 보이는 것보다 이쪽이 훨씬 안전합니다.

Stage2가 실제로 같은 코드를 컴파일합니다

이번에 가장 오래 걸린 부분은 C# Stage1에서 잘 되던 stream 의미를 .slg로 작성한 self-host Stage2까지 정확히 연결하는 일이었습니다.

Range를 first-class source로 보존하고, each/fold 역할 바인딩, nested flatMap의 원소 타입, state/scan, take/skip, stop 취소, raw string과 when 하강까지 고쳤습니다. 웹은 별도 축소 컴파일러나 하드코딩 결과를 쓰지 않습니다. Stage2 자체를 wasm32로 빌드해 편집기의 최신 코드를 LLVM과 실행 가능한 WASM으로 낮춥니다.

예를 들어 이 코드는 이제 정확히 세 줄을 출력합니다.

main {
    1..3 -> each {
        "Range item" -> println
    }
}

1..100 -> fold는 1이 아니라 5050을 출력하고, 사용자 블록 예제는 실제로 notifyyield를 호출합니다.

31개 예제는 이제 출력까지 비교합니다

이전 검사는 실행이 끝났는지, stdout이 비어 있지 않은지만 보는 구간이 있었습니다. 그래서 샘플과 무관한 한 줄이 찍혀도 통과할 수 있었습니다.

지금은 31개 샘플마다 정확한 기대 stdout을 고정했습니다. 빈 출력, 일부 출력, 잘못된 fold 값, each 반복 횟수, when 분기, raw string, stream 조기 종료를 모두 실패로 잡습니다.

존재하지 않는 함수를 호출한 코드도 더 이상 무시하지 않습니다.

"Values flow from left to right." -> println2

이 코드는 println2를 찾을 수 없다는 컴파일 오류가 납니다.

모바일에서는 코드가 먼저 보입니다

모바일 화면에서 소개 문구가 편집기보다 큰 자리를 차지하던 배치도 바꿨습니다. 이제 코드 workbench와 실행 결과가 먼저 나오고, 소개 문구는 footer 뒤 페이지 가장 아래에 놓입니다. 390×844 실제 브라우저 화면으로 순서를 확인했습니다.

검증 결과

  • 전체 회귀: 785/785
  • Windows Stage2: 7/7, fresh 검증 93초
  • Linux Stage2: 6/6, fresh 검증 101초
  • Windows/Linux Stage3: fixed point 일치
  • 브라우저: 31개 샘플 × 4개 locale, 정확한 stdout 통과
  • GitHub Pages: 배포 성공
  • sollang.slogs.dev: DNS CNAME, TLS, HTTP 200 확인
  • 전역 P:\Utils\sollang: 최신 패키지와 SHA-256 일치

변경은 66f1982 커밋으로 main에 반영했습니다.

직접 실행해 볼 수 있습니다.

https://sollang.slogs.dev

이번 작업으로 Stream은 문법 데모를 넘어서, 변수에 담고 라이브러리 경계를 지나며 필요한 만큼만 실행되는 계획이 되었습니다. 그리고 그 의미가 Stage1, Stage2, 네이티브, 브라우저에서 같은 검증망 안에 들어왔습니다.

0 대화 흔적

다음 로그

다음 로그가 없습니다.

대화 흔적 (0)

이 로그에 댓글을 남기려면 지식 로그 홈으로 돌아가야 합니다. 지식 로그로 돌아가기

아직 이어진 댓글이 없습니다. 첫 댓글을 남겨 보세요.

지식 로그 연결이 잠시 끊겼습니다. 다시 연결 ×