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.3
import std.json4
import schema { 들여쓰기 }5
import types { 인쇄조각범위, 인쇄조각판 }7
export function 인쇄조각판만들기() -> 인쇄조각판 {8
인쇄조각판 {9
종류들: [0], 글들: [""], 왼들: [-1], 오른들: [-1],10
시작들: [0], 끝들: [0], 횟수들: [0], 길이들: [0],11
행수들: [0], 첫글들: [""], 끝글들: [""]12
}13
}15
function 글행사건수(글자들: Array<string>) -> int {16
let mut 행수 = 017
let mut 색인 = 018
while 색인 < 글자들.length {19
let 글자 = 글자들[색인]20
if 글자 == "\r" && 색인 + 1 < 글자들.length && 글자들[색인 + 1] == "\n" {21
행수 = 행수 + 122
색인 = 색인 + 223
continue24
}25
if 글자 == "\n" || 글자 == "\r" || 글자 == "
" || 글자 == "
" {26
행수 = 행수 + 127
}28
색인 = 색인 + 129
}30
행수31
}33
export function 인쇄글조각(판: 인쇄조각판, 글: string) -> int {34
let 글자들 = 글.scalars()35
if 글자들.length == 0 { return 0 }36
let 번호 = 판.종류들.length37
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
번호48
}50
export function 인쇄조각이음(판: 인쇄조각판, 왼: int, 오른: int) -> int {51
if 왼 == 0 { return 오른 }52
if 오른 == 0 { return 왼 }53
let 번호 = 판.종류들.length54
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
번호69
}71
function 인쇄조각반복(판: 인쇄조각판, 글: 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 번호 = 판.종류들.length77
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(번호)93
}95
function 인쇄조각글자들(판: 인쇄조각판, 뿌리: 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 꼭대기 = 1102
let mut 단계수 = 0103
let 최대단계수 = 판.종류들.length * 4 + 판.길이들[뿌리] + 16104
while 꼭대기 > 0 {105
단계수 = 단계수 + 1106
if 단계수 > 최대단계수 { return Err("인쇄 조각 순회 단계 한도를 넘었습니다") }107
꼭대기 = 꼭대기 - 1108
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
꼭대기 = 꼭대기 + 1128
}129
let 왼시작 = if 일.시작 < 왼길이 { 일.시작 } else { 왼길이 }130
let 왼끝 = if 일.끝 < 왼길이 { 일.끝 } else { 왼길이 }131
if 왼시작 < 왼끝 {132
let 왼일 = 인쇄조각범위 { 조각: 왼, 시작: 왼시작, 끝: 왼끝 }133
if 꼭대기 < 일들.length { 일들[꼭대기] = 왼일 } else { 일들.push(왼일) }134
꼭대기 = 꼭대기 + 1135
}136
} else if 종류 == 3 {137
let 원본 = 판.왼들[일.조각]138
let 원본일 = 인쇄조각범위 {139
조각: 원본,140
시작: 판.시작들[일.조각] + 일.시작,141
끝: 판.시작들[일.조각] + 일.끝142
}143
if 꼭대기 < 일들.length { 일들[꼭대기] = 원본일 } else { 일들.push(원본일) }144
꼭대기 = 꼭대기 + 1145
} else if 종류 == 4 {146
let 글자들 = 판.글들[일.조각].scalars()147
let mut 색인 = 일.시작148
while 색인 < 일.끝 {149
결과.push(글자들[색인 % 글자들.length])150
색인 = 색인 + 1151
}152
} else if 종류 != 0 {153
return Err("인쇄 조각 종류가 틀립니다")154
}155
}156
}157
Ok(결과)158
}160
export 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 번호 = 판.종류들.length166
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(번호)179
}181
export 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))188
}190
export function 인쇄조각행수(판: 인쇄조각판, 조각: int) -> int {191
판.행수들[조각]192
}194
export function 인쇄조각같음(판: 인쇄조각판, 왼: int, 오른: int) -> Result<bool, string> {195
if 판.길이들[왼] != 판.길이들[오른] { return Ok(false) }196
let 왼글자들 = 인쇄조각글자들(판, 왼)?197
let 오른글자들 = 인쇄조각글자들(판, 오른)?198
let mut 색인 = 0199
while 색인 < 왼글자들.length {200
if 왼글자들[색인] != 오른글자들[색인] { return Ok(false) }201
색인 = 색인 + 1202
}203
Ok(true)204
}206
export function 인쇄조각접두(판: 인쇄조각판, 조각: int, 접두: string) -> Result<bool, string> {207
let 접두조각 = 인쇄글조각(판, 접두)208
if 판.길이들[접두조각] > 판.길이들[조각] { return Ok(false) }209
let 앞 = 인쇄조각자름(판, 조각, 0, 판.길이들[접두조각])?210
인쇄조각같음(판, 앞, 접두조각)211
}213
export function 인쇄조각접미(판: 인쇄조각판, 조각: int, 접미: string) -> Result<bool, string> {214
let 접미조각 = 인쇄글조각(판, 접미)215
if 판.길이들[접미조각] > 판.길이들[조각] { return Ok(false) }216
let 뒤 = 인쇄조각자름(판, 조각, 판.길이들[조각] - 판.길이들[접미조각], 판.길이들[조각])?217
인쇄조각같음(판, 뒤, 접미조각)218
}220
export function 글자합치기(글자들: Array<string>, 시작: int, 끝: int) -> string {221
글자들.slice(시작, 끝).join("")222
}224
export function 글평평하게(글: string) -> string {225
let 글자들 = 글.scalars()226
글자합치기(글자들, 0, 글자들.length)227
}229
export function 제이슨문자필드(뿌리: JSONValue, 이름: string) -> Result<string, string> {230
match json.get(뿌리, 이름).flatMap((값) => json.asString(값)) {231
case Some(글) => Ok(글)232
case None => Err("분리 본문 키의 {이름} 필드가 문자열이 아닙니다")233
}234
}236
export function 제이슨정수필드(뿌리: JSONValue, 이름: string) -> Result<int, string> {237
match json.get(뿌리, 이름).flatMap((값) => json.asInt(값)) {238
case Some(수) => Ok(수)239
case None => Err("분리 본문 키의 {이름} 필드가 정수가 아닙니다")240
}241
}243
// 언어마다 분리 댓글로 다루는 코드워드다. 러스트는 여기에 없다. 러스트의244
// 주석은 원본 인쇄 경로가 잎 토큰으로 직접 나르기 때문이다.245
export 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
false256
}258
export function 줄과들여쓰기(줄수: int, 깊이: int) -> string {259
let mut 글 = ""; let mut 남음 = 줄수260
while 남음 > 0 { 글 = 글 + "\n" + 들여쓰기(깊이); 남음 = 남음 - 1 }261
글262
}264
// 인쇄는 재귀 대신 명시적 호출 더미로 돈다. 깊이는 힙에 쌓이고265
// 네이티브 스택은 한 층에 머무니 깊은 나무도 두렵지 않다.266
export record 인쇄호출 {267
모드: int,268
순번: int,269
깊이: int270
}272
// 파이썬과 고와 러스트와 자바는 잎 토큰의 행과 칸 간격에서 원형을 복원한다.273
// 들여쓰기가 문법인 언어에서는 배치가 곧 구조다.274
// 세 언어의 원본 인쇄가 같은 손질을 쓴다. 줄 끝의 공백을 걷어내고275
// 줄바꿈 여부를 살피는 일에는 언어의 사투리가 없다.276
export function 끝공백제거(글: string) -> string {277
let 글자들 = 글.scalars()278
let mut 끝 = 글자들.length279
while 끝 > 0 {280
let 글자 = 글자들[끝 - 1]281
if 글자 != " " && 글자 != "\t" && 글자 != "\n" && 글자 != "\r" { break }282
끝 = 끝 - 1283
}284
글자합치기(글자들, 0, 끝)285
}287
export function 줄끝인가(글: string) -> bool {288
let 글자들 = 글.scalars()289
if 글자들.length == 0 { return false }290
let 끝 = 글자들[글자들.length - 1]291
끝 == "\n" || 끝 == "\r"292
}294
export function 고여는구분자(글: string) -> bool {295
if 글 == "\{" { return true }296
if 글 == "(" { return true }297
글 == "["298
}300
export function 고닫는구분자(글: string) -> bool {301
if 글 == "\}" { return true }302
if 글 == ")" { return true }303
글 == "]"304
}306
// SE-06. There is exactly ONE guest cursor. Which scalars end a row and how307
// wide a scalar is are parameters supplied by the caller from the language's308
// declared carried geometry (core.tpz `언어행종결자` / `언어열규칙`), never309
// properties of whichever helper a printer happened to forward to. Forwarding310
// aliases are what let the Elm, PHP and Solidity printers measure their output311
// 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 carriage313
// return is a column; true = a lone carriage return also ends a314
// 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.317
export function 위치전진(318
복귀행종결: bool,319
열규칙: int,320
행: int,321
열: int,322
본문: string323
) -> Array<int> {324
let mut 현재행 = 행325
let mut 현재열 = 열326
let mut 이전복귀 = false327
let 글자들 = 본문.scalars()328
let mut 색인 = 0329
while 색인 < 글자들.length {330
let 글자 = 글자들[색인]331
if 글자 == "\r" && 복귀행종결 {332
현재행 = 현재행 + 1333
현재열 = 0334
이전복귀 = true335
} else if 글자 == "\n" {336
if !이전복귀 { 현재행 = 현재행 + 1 }337
현재열 = 0338
이전복귀 = false339
} else if 글자 == "\r" && 열규칙 == 2 {340
이전복귀 = false341
} else {342
현재열 = 현재열 +343
(if 열규칙 == 1 { Bytes.encodeUtf8(글자).length() } else { 1 })344
이전복귀 = false345
}346
색인 = 색인 + 1347
}348
[현재행, 현재열]349
}351
export function 끝가로공백제거(글: string) -> string {352
let 글자들 = 글.scalars()353
let mut 끝 = 글자들.length354
while 끝 > 0 {355
let 글자 = 글자들[끝 - 1]356
if 글자 != " " && 글자 != "\t" { break }357
끝 = 끝 - 1358
}359
글자합치기(글자들, 0, 끝)360
}SHA256 338733abd6bd5765bf4cae1fb7bb88fc69fcc1a4ee6280be5a7ed49926ae7aa8