slow.monster

STUDIO HAZE · image

Topaz source

Open by house policy. Topaz is our own language.

Topaz 5.9 · 42 files

topaz/src/print.tpz

Topaz · 15199 B · Original file

1// Source projection and printer execution.
3import std.json
4import schema { 들여쓰기 }
5import types { 인쇄조각범위, 인쇄조각판 }
7export function 인쇄조각판만들기() -> 인쇄조각판 {
8 인쇄조각판 {
9 종류들: [0], 글들: [""], 왼들: [-1], 오른들: [-1],
10 시작들: [0], 끝들: [0], 횟수들: [0], 길이들: [0],
11 행수들: [0], 첫글들: [""], 끝글들: [""]
12 }
15function 글행사건수(글자들: Array<string>) -> int {
16 let mut 행수 = 0
17 let mut 색인 = 0
18 while 색인 < 글자들.length {
19 let 글자 = 글자들[색인]
20 if 글자 == "\r" && 색인 + 1 < 글자들.length && 글자들[색인 + 1] == "\n" {
21 행수 = 행수 + 1
22 색인 = 색인 + 2
23 continue
24 }
25 if 글자 == "\n" || 글자 == "\r" || 글자 == "
" || 글자 == "
" {
26 행수 = 행수 + 1
27 }
28 색인 = 색인 + 1
29 }
30 행수
33export function 인쇄글조각(판: 인쇄조각판, 글: string) -> int {
34 let 글자들 = 글.scalars()
35 if 글자들.length == 0 { return 0 }
36 let 번호 = 판.종류들.length
37 let mut 종류들 = 판.종류들; let mut 글들 = 판.글들
38 let mut 왼들 = 판.왼들; let mut 오른들 = 판.오른들
39 let mut 시작들 = 판.시작들; let mut 끝들 = 판.끝들
40 let mut 횟수들 = 판.횟수들; let mut 길이들 = 판.길이들
41 let mut 행수들 = 판.행수들
42 let mut 첫글들 = 판.첫글들; let mut 끝글들 = 판.끝글들
43 종류들.push(1); 글들.push(글); 왼들.push(-1); 오른들.push(-1)
44 시작들.push(0); 끝들.push(글자들.length); 횟수들.push(1)
45 길이들.push(글자들.length); 행수들.push(글행사건수(글자들)); 첫글들.push(글자들[0])
46 끝글들.push(글자들[글자들.length - 1])
47 번호
50export function 인쇄조각이음(판: 인쇄조각판, 왼: int, 오른: int) -> int {
51 if 왼 == 0 { return 오른 }
52 if 오른 == 0 { return 왼 }
53 let 번호 = 판.종류들.length
54 let mut 종류들 = 판.종류들; let mut 글들 = 판.글들
55 let mut 왼들 = 판.왼들; let mut 오른들 = 판.오른들
56 let mut 시작들 = 판.시작들; let mut 끝들 = 판.끝들
57 let mut 횟수들 = 판.횟수들; let mut 길이들 = 판.길이들
58 let mut 행수들 = 판.행수들
59 let mut 첫글들 = 판.첫글들; let mut 끝글들 = 판.끝글들
60 종류들.push(2); 글들.push(""); 왼들.push(왼); 오른들.push(오른)
61 시작들.push(0); 끝들.push(0); 횟수들.push(1)
62 길이들.push(길이들[왼] + 길이들[오른])
63 행수들.push(
64 행수들[왼] + 행수들[오른] -
65 (if 끝글들[왼] == "\r" && 첫글들[오른] == "\n" { 1 } else { 0 })
66 )
67 첫글들.push(첫글들[왼]); 끝글들.push(끝글들[오른])
68 번호
71function 인쇄조각반복(판: 인쇄조각판, 글: string, 횟수: int) -> Result<int, string> {
72 let 글자들 = 글.scalars()
73 if 횟수 <= 0 || 글자들.length == 0 { return Ok(0) }
74 if 횟수 == 1 { return Ok(인쇄글조각(판, 글)) }
75 if 글자들.length > 2147483647 / 횟수 { return Err("인쇄 조각 반복 길이가 너무 큽니다") }
76 let 번호 = 판.종류들.length
77 let mut 종류들 = 판.종류들; let mut 글들 = 판.글들
78 let mut 왼들 = 판.왼들; let mut 오른들 = 판.오른들
79 let mut 시작들 = 판.시작들; let mut 끝들 = 판.끝들
80 let mut 횟수들 = 판.횟수들; let mut 길이들 = 판.길이들
81 let mut 행수들 = 판.행수들
82 let mut 첫글들 = 판.첫글들; let mut 끝글들 = 판.끝글들
83 종류들.push(4); 글들.push(글); 왼들.push(-1); 오른들.push(-1)
84 시작들.push(0); 끝들.push(글자들.length); 횟수들.push(횟수)
85 길이들.push(글자들.length * 횟수)
86 행수들.push(
87 글행사건수(글자들) * 횟수 -
88 (if 글자들[글자들.length - 1] == "\r" && 글자들[0] == "\n" { 횟수 - 1 } else { 0 })
89 )
90 첫글들.push(글자들[0])
91 끝글들.push(글자들[글자들.length - 1])
92 Ok(번호)
95function 인쇄조각글자들(판: 인쇄조각판, 뿌리: int) -> Result<Array<string>, string> {
96 if 뿌리 < 0 || 뿌리 >= 판.종류들.length { return Err("인쇄 조각 번호가 범위를 벗어났습니다") }
97 let mut 결과: Array<string> = []
98 let mut 일들: Array<인쇄조각범위> = [
99 인쇄조각범위 { 조각: 뿌리, 시작: 0, 끝: 판.길이들[뿌리] }
100 ]
101 let mut 꼭대기 = 1
102 let mut 단계수 = 0
103 let 최대단계수 = 판.종류들.length * 4 + 판.길이들[뿌리] + 16
104 while 꼭대기 > 0 {
105 단계수 = 단계수 + 1
106 if 단계수 > 최대단계수 { return Err("인쇄 조각 순회 단계 한도를 넘었습니다") }
107 꼭대기 = 꼭대기 - 1
108 let 일 = 일들[꼭대기]
109 if 일.시작 < 0 || 일.끝 < 일.시작 || 일.끝 > 판.길이들[일.조각] {
110 return Err("인쇄 조각 범위가 틀립니다")
111 }
112 if 일.시작 < 일.끝 {
113 let 종류 = 판.종류들[일.조각]
114 if 종류 == 1 {
115 let 글자들 = 판.글들[일.조각].scalars()
116 let mut 색인 = 일.시작
117 while 색인 < 일.끝 { 결과.push(글자들[색인]); 색인 = 색인 + 1 }
118 } else if 종류 == 2 {
119 let 왼 = 판.왼들[일.조각]
120 let 오른 = 판.오른들[일.조각]
121 let 왼길이 = 판.길이들[왼]
122 let 오른시작 = if 일.시작 > 왼길이 { 일.시작 - 왼길이 } else { 0 }
123 let 오른끝 = if 일.끝 > 왼길이 { 일.끝 - 왼길이 } else { 0 }
124 if 오른시작 < 오른끝 {
125 let 오른일 = 인쇄조각범위 { 조각: 오른, 시작: 오른시작, 끝: 오른끝 }
126 if 꼭대기 < 일들.length { 일들[꼭대기] = 오른일 } else { 일들.push(오른일) }
127 꼭대기 = 꼭대기 + 1
128 }
129 let 왼시작 = if 일.시작 < 왼길이 { 일.시작 } else { 왼길이 }
130 let 왼끝 = if 일.끝 < 왼길이 { 일.끝 } else { 왼길이 }
131 if 왼시작 < 왼끝 {
132 let 왼일 = 인쇄조각범위 { 조각: 왼, 시작: 왼시작, 끝: 왼끝 }
133 if 꼭대기 < 일들.length { 일들[꼭대기] = 왼일 } else { 일들.push(왼일) }
134 꼭대기 = 꼭대기 + 1
135 }
136 } else if 종류 == 3 {
137 let 원본 = 판.왼들[일.조각]
138 let 원본일 = 인쇄조각범위 {
139 조각: 원본,
140 시작: 판.시작들[일.조각] + 일.시작,
141 끝: 판.시작들[일.조각] + 일.끝
142 }
143 if 꼭대기 < 일들.length { 일들[꼭대기] = 원본일 } else { 일들.push(원본일) }
144 꼭대기 = 꼭대기 + 1
145 } else if 종류 == 4 {
146 let 글자들 = 판.글들[일.조각].scalars()
147 let mut 색인 = 일.시작
148 while 색인 < 일.끝 {
149 결과.push(글자들[색인 % 글자들.length])
150 색인 = 색인 + 1
151 }
152 } else if 종류 != 0 {
153 return Err("인쇄 조각 종류가 틀립니다")
154 }
155 }
156 }
157 Ok(결과)
160export function 인쇄조각자름(판: 인쇄조각판, 원본: int, 시작: int, 끝: int) -> Result<int, string> {
161 if 원본 < 0 || 원본 >= 판.종류들.length { return Err("인쇄 조각 번호가 범위를 벗어났습니다") }
162 if 시작 < 0 || 끝 < 시작 || 끝 > 판.길이들[원본] { return Err("인쇄 조각 자름 범위가 틀립니다") }
163 if 시작 == 끝 { return Ok(0) }
164 if 시작 == 0 && 끝 == 판.길이들[원본] { return Ok(원본) }
165 let 번호 = 판.종류들.length
166 let mut 종류들 = 판.종류들; let mut 글들 = 판.글들
167 let mut 왼들 = 판.왼들; let mut 오른들 = 판.오른들
168 let mut 시작들 = 판.시작들; let mut 끝들 = 판.끝들
169 let mut 횟수들 = 판.횟수들; let mut 길이들 = 판.길이들
170 let mut 행수들 = 판.행수들
171 let mut 첫글들 = 판.첫글들; let mut 끝글들 = 판.끝글들
172 종류들.push(3); 글들.push(""); 왼들.push(원본); 오른들.push(-1)
173 시작들.push(시작); 끝들.push(끝); 횟수들.push(1); 길이들.push(끝 - 시작)
174 첫글들.push(""); 끝글들.push("")
175 let 글자들 = 인쇄조각글자들(판, 번호)?
176 행수들.push(글행사건수(글자들))
177 첫글들[번호] = 글자들[0]; 끝글들[번호] = 글자들[글자들.length - 1]
178 Ok(번호)
181export function 인쇄조각평평하게(판: 인쇄조각판, 조각: int) -> Result<string, string> {
182 if 조각 == 0 { return Ok("") }
183 if 조각 > 0 && 조각 < 판.종류들.length && 판.종류들[조각] == 1 {
184 return Ok(판.글들[조각])
185 }
186 let 글자들 = 인쇄조각글자들(판, 조각)?
187 Ok(글자합치기(글자들, 0, 글자들.length))
190export function 인쇄조각행수(판: 인쇄조각판, 조각: int) -> int {
191 판.행수들[조각]
194export function 인쇄조각같음(판: 인쇄조각판, 왼: int, 오른: int) -> Result<bool, string> {
195 if 판.길이들[왼] != 판.길이들[오른] { return Ok(false) }
196 let 왼글자들 = 인쇄조각글자들(판, 왼)?
197 let 오른글자들 = 인쇄조각글자들(판, 오른)?
198 let mut 색인 = 0
199 while 색인 < 왼글자들.length {
200 if 왼글자들[색인] != 오른글자들[색인] { return Ok(false) }
201 색인 = 색인 + 1
202 }
203 Ok(true)
206export function 인쇄조각접두(판: 인쇄조각판, 조각: int, 접두: string) -> Result<bool, string> {
207 let 접두조각 = 인쇄글조각(판, 접두)
208 if 판.길이들[접두조각] > 판.길이들[조각] { return Ok(false) }
209 let 앞 = 인쇄조각자름(판, 조각, 0, 판.길이들[접두조각])?
210 인쇄조각같음(판, 앞, 접두조각)
213export function 인쇄조각접미(판: 인쇄조각판, 조각: int, 접미: string) -> Result<bool, string> {
214 let 접미조각 = 인쇄글조각(판, 접미)
215 if 판.길이들[접미조각] > 판.길이들[조각] { return Ok(false) }
216 let 뒤 = 인쇄조각자름(판, 조각, 판.길이들[조각] - 판.길이들[접미조각], 판.길이들[조각])?
217 인쇄조각같음(판, 뒤, 접미조각)
220export function 글자합치기(글자들: Array<string>, 시작: int, 끝: int) -> string {
221 글자들.slice(시작, 끝).join("")
224export function 글평평하게(글: string) -> string {
225 let 글자들 = 글.scalars()
226 글자합치기(글자들, 0, 글자들.length)
229export function 제이슨문자필드(뿌리: JSONValue, 이름: string) -> Result<string, string> {
230 match json.get(뿌리, 이름).flatMap((값) => json.asString(값)) {
231 case Some(글) => Ok(글)
232 case None => Err("분리 본문 키의 {이름} 필드가 문자열이 아닙니다")
233 }
236export function 제이슨정수필드(뿌리: JSONValue, 이름: string) -> Result<int, string> {
237 match json.get(뿌리, 이름).flatMap((값) => json.asInt(값)) {
238 case Some(수) => Ok(수)
239 case None => Err("분리 본문 키의 {이름} 필드가 정수가 아닙니다")
240 }
243// 언어마다 분리 댓글로 다루는 코드워드다. 러스트는 여기에 없다. 러스트의
244// 주석은 원본 인쇄 경로가 잎 토큰으로 직접 나르기 때문이다.
245export function 댓글코드(언어번호: int, 코드워드: int) -> bool {
246 if 언어번호 == 1 { return 코드워드 == 7 || 코드워드 == 205 }
247 if 언어번호 == 2 { return 코드워드 == 349 || 코드워드 == 392 }
248 if 언어번호 == 3 { return 코드워드 == 289 }
249 if 언어번호 == 4 { return 코드워드 == 43 }
250 if 언어번호 == 5 { return false }
251 if 언어번호 == 6 { return false }
252 if 언어번호 == 7 { return false }
253 if 언어번호 == 8 { return false }
254 if 언어번호 == 9 { return false }
255 false
258export function 줄과들여쓰기(줄수: int, 깊이: int) -> string {
259 let mut 글 = ""; let mut 남음 = 줄수
260 while 남음 > 0 { 글 = 글 + "\n" + 들여쓰기(깊이); 남음 = 남음 - 1 }
261 글
264// 인쇄는 재귀 대신 명시적 호출 더미로 돈다. 깊이는 힙에 쌓이고
265// 네이티브 스택은 한 층에 머무니 깊은 나무도 두렵지 않다.
266export record 인쇄호출 {
267 모드: int,
268 순번: int,
269 깊이: int
272// 파이썬과 고와 러스트와 자바는 잎 토큰의 행과 칸 간격에서 원형을 복원한다.
273// 들여쓰기가 문법인 언어에서는 배치가 곧 구조다.
274// 세 언어의 원본 인쇄가 같은 손질을 쓴다. 줄 끝의 공백을 걷어내고
275// 줄바꿈 여부를 살피는 일에는 언어의 사투리가 없다.
276export function 끝공백제거(글: string) -> string {
277 let 글자들 = 글.scalars()
278 let mut 끝 = 글자들.length
279 while 끝 > 0 {
280 let 글자 = 글자들[끝 - 1]
281 if 글자 != " " && 글자 != "\t" && 글자 != "\n" && 글자 != "\r" { break }
282 끝 = 끝 - 1
283 }
284 글자합치기(글자들, 0, 끝)
287export function 줄끝인가(글: string) -> bool {
288 let 글자들 = 글.scalars()
289 if 글자들.length == 0 { return false }
290 let 끝 = 글자들[글자들.length - 1]
291 끝 == "\n" || 끝 == "\r"
294export function 고여는구분자(글: string) -> bool {
295 if 글 == "\{" { return true }
296 if 글 == "(" { return true }
297 글 == "["
300export function 고닫는구분자(글: string) -> bool {
301 if 글 == "\}" { return true }
302 if 글 == ")" { return true }
303 글 == "]"
306// SE-06. There is exactly ONE guest cursor. Which scalars end a row and how
307// wide a scalar is are parameters supplied by the caller from the language's
308// declared carried geometry (core.tpz `언어행종결자` / `언어열규칙`), never
309// properties of whichever helper a printer happened to forward to. Forwarding
310// aliases are what let the Elm, PHP and Solidity printers measure their output
311// with a terminator their kernel counterparts do not use, so there are none.
312// 복귀행종결: false = a row ends on a line feed alone and a lone carriage
313// return is a column; true = a lone carriage return also ends a
314// row and CRLF ends exactly one.
315// 열규칙: 0 = one column per scalar; 1 = UTF-8 bytes per scalar;
316// 2 = a carriage return takes no column at all.
317export function 위치전진(
318 복귀행종결: bool,
319 열규칙: int,
320 행: int,
321 열: int,
322 본문: string
323) -> Array<int> {
324 let mut 현재행 = 행
325 let mut 현재열 = 열
326 let mut 이전복귀 = false
327 let 글자들 = 본문.scalars()
328 let mut 색인 = 0
329 while 색인 < 글자들.length {
330 let 글자 = 글자들[색인]
331 if 글자 == "\r" && 복귀행종결 {
332 현재행 = 현재행 + 1
333 현재열 = 0
334 이전복귀 = true
335 } else if 글자 == "\n" {
336 if !이전복귀 { 현재행 = 현재행 + 1 }
337 현재열 = 0
338 이전복귀 = false
339 } else if 글자 == "\r" && 열규칙 == 2 {
340 이전복귀 = false
341 } else {
342 현재열 = 현재열 +
343 (if 열규칙 == 1 { Bytes.encodeUtf8(글자).length() } else { 1 })
344 이전복귀 = false
345 }
346 색인 = 색인 + 1
347 }
348 [현재행, 현재열]
351export function 끝가로공백제거(글: string) -> string {
352 let 글자들 = 글.scalars()
353 let mut 끝 = 글자들.length
354 while 끝 > 0 {
355 let 글자 = 글자들[끝 - 1]
356 if 글자 != " " && 글자 != "\t" { break }
357 끝 = 끝 - 1
358 }
359 글자합치기(글자들, 0, 끝)

SHA256 338733abd6bd5765bf4cae1fb7bb88fc69fcc1a4ee6280be5a7ed49926ae7aa8