20 명령 pnx
(1) pnx 는 이 라이브러리를 쓰는 호스트이자 개발 도구다. 표준 호스트 모듈(17절)을 모두 등록한다.
pnx [--lib NAME=PATH]... [--capacity NAME=N]... file.pnx [arguments]
pnx test file.pnx
pnx repl
pnx see file.pnx
pnx fmt file.pnx
pnx export-c file.pnx [NAME]20.1 돌리기
(1) pnx file.pnx 인자… 는 파일을 적재하고 적재 코드를 돌린다. 파일이 use 하는 모듈 가운데 등록되지 않은 것은 파일 옆의 모듈.pnx 에서 먼저 적재한다(13.1). 파일은 이름에서 .pnx 를 뗀 모듈로 적재된다 — 그 이름이 낱말처럼 적히지 않으면(숫자로 시작하거나 - 를 담으면) 이름 없는 모듈이 된다.
(2) 종료 상태는 셋이고, 프로그램이 sh.exit(17.5)로 주는 것이 있다.
| 상태 | 언제 |
| 0 | 적재 코드가 끝까지 돌았다. pnx test 는 모든 시험이 통과했다 |
| 1 | 거절: 파일:줄:칸: 까닭 을 표준 오류에. 결함: 파일:줄: 갈래 와 그 낱말의 지역 변수를. pnx test 는 실패한 시험이 있다 |
| 2 | 명령이 틀렸다(사용법을 보인다), 파일을 읽지 못한다, --lib 의 라이브러리를 열지 못한다, --capacity 가 NAME=N 이 아니다 |
(3) --lib NAME=PATH 는 PATH 의 공유 라이브러리를 열어 extern … from "NAME"(18절)의 해결 함수가 그 라이브러리의 함수를 찾게 한다. 그 라이브러리가 정의한 함수만 찾는다(그것이 들여온 함수는 찾지 않는다). --lib 가 없으면 extern 은 모두 거절된다.
(3a) --capacity NAME=N 은 소스가 host 로 쓴 용량(8 (4a), 19.4 (1d))을 준다. 실행, pnx test, pnx see, pnx export-c, pnx repl 에 쓴다. 맨 NAME 은 그 파일의 선언이고, MODULE.NAME 은 그 파일이 쓰는 모듈의 선언이다. N 은 1 부터 231 − 1 까지이고, 16 개까지 준다. 이것이 없으면 host 를 쓴 소스는 적재 때 용량의 이름을 대며 거절된다.
(3b) 스크립트가 io.print 와 io.println 으로 쓰는 것은 버퍼에 모였다가, 버퍼가 찰 때, io.eprint· clock.sleep 앞에서, io.read_line 이 시스템에 표준 입력을 더 청하기 전에, 그리고 실행이 끝나거나 결함으로 멈출 때 쓰인다. 그래서 표준 출력과 표준 오류는 스크립트가 쓴 차례대로 나오고, 프로그램이 줄을 기다리기 전에 프롬프트가 보인다. pnx repl 이 아니면 io.read_line 은 표준 입력을 미리 읽으며, 이미 미리 읽은 줄은 쓰지 않고 준다. 라이브러리를 품은 호스트는 둘 다 버퍼 없이 쓰고 읽는다.
20.2 시험
구문
test = "test" NAME { body } "end" ;(1) test 이름 … end 는 시험(test)을 정의한다. 시험은 받는 것도 주는 것도 없는 낱말이다. 적재할 때는 돌지 않는다. pnx test file.pnx 는 그 파일의 시험을 차례로 돌리고, 시험마다 ok 나 FAIL 을 쓰고, 모두 통과하면 0, 하나라도 실패하면 1 로 끝난다. 시험 안의 결함(거짓인 assert 를 포함해)은 그 시험의 실패다.
20-test.pnx
use str
word middle (s str gives str) s 1 str.skip 1 str.skip_last end
test middle_trims_both_ends
"[abc]" middle "abc" eq assert
end
test middle_of_two_is_empty
"ab" middle str.is_empty assert
end
시험 결과
$ pnx test 20-test.pnx
ok middle_trims_both_ends
ok middle_of_two_is_empty
2 tests, 0 failed
20-test-fail.pnx
word twice (n int gives int) n 2 mul end
test doubles 21 twice 42 eq assert end
test wrong 21 twice 43 eq assert end
test-fail
$ pnx test 20-test-fail.pnx
ok doubles
FAIL wrong (failed)
2 tests, 1 failed
20.3 대화
(1) pnx repl 은 표준 입력에서 한 줄씩 읽어 돌린다(19.4 의 pinax_eval). 줄마다, 세션 스택이 비어 있지 않으면 가장 깊은 값부터 표준 출력에 쓴다. 앞 줄에서 정의한 것과 앞 줄이 남긴 값을 뒤 줄에서 쓸 수 있다(19.4 (2a)). 정의나 블록이 끝나지 않은 줄은 다음 줄과 이어 읽는다. 거절되거나 결함으로 끝난 줄은 스택을 그대로 둔다. 줄의 끝(Enter)은 점이다(10.8): 줄이 쓴 것은 프롬프트가 돌아오기 전에 화면에 있다.
(2) 대화에서만 쓰는 도구 낱말이 있다: list_words(정의한 낱말), stack(그 자리의 스택의 타입), clear(줄 맨 앞에서: 그 줄은 빈 스택에서 시작한다), see(뒤따르는 정의의 줄마다 스택), redefine word …(있는 낱말에 쓴 word … 와 같다, (2a)).
(2a) 세션의 앞 줄에서 정의한 낱말의 이름으로 word 이름 … 을 쓰면 그 낱말을 다시 정의한다. 서명이 같으면 그 낱말을 부르는 모든 낱말이 새것을 부른다. 서명이 다르면 새 낱말이 이름을 가져가고, 그 전에 컴파일된 낱말들은 이름이 없어진 옛 몸을 계속 부르며, pnx repl 이 그 낱말들을 알린다(“2 words still call the old sq: quad, cube”). 한 줄에서 낱말 하나를 다시 정의하고, 작업이 살아 있는 동안에는 다시 정의하지 않는다. 파일에서 적재한 모듈의 낱말은 세션에서 다시 정의하지 않는다: 파일을 고쳐 다시 적재한다.
20-repl.pnx
use str
3 4
mul
word sq (n int gives int) n n mul end
sq
"x" 3 str.repeat
1 0 div
clear
2 sq
대화
$ pnx repl
3 4
12
12
144
144 "xxx"
error: line 1: div_zero
4
20.4 스택 보기와 정리
(1) pnx see file.pnx 는 정의의 줄마다 그 줄이 끝난 자리의 스택(타입)을 보인다.
20-see.pnx
use str
word tally (s str gives n int, longest int)
0 to n
0 to longest
s str.words do (w str)
n 1 add to n
w str.len
longest max to longest
end each
n longest
end
목록
$ pnx see 20-see.pnx
3 0 to n | (empty)
4 0 to longest | (empty)
5 s str.words do (w str) | (empty)
6 n 1 add to n | (empty)
7 w str.len | int
8 longest max to longest | (empty)
9 end each | (empty)
10 n longest | int int
(1a) 소스가 거절되면 pnx see 는 거절된 자리 앞의 줄들을 보이고, 거절 진단을 내고, 1 로 끝난다.
20-see-refused.pnx
word f (n int gives int)
n 1 add
n
end
목록과 거절
$ pnx see 20-see-refused.pnx
2 n 1 add | int
3 n | int int
20-see-refused.pnx:4:1: the stack does not hold exactly the results of the signature here
(1b) pnx see --checks file.pnx 는 파일을 pnx file.pnx 처럼 적재하고(정의 밖의 코드가 돈다), 그 다음 낱말마다 적재기가 «울릴 수 없다»고 증명한 실행 때의 검사를 보인다: 낱말의 검사 수와 증명된 수, 그리고 증명된 명령마다 그 줄, 명령, 까닭. 증명은 프로그램의 동작을 바꾸지 않는다. 검사는 그대로 돈다.
20-see-checks.pnx
use io
use str
const days 7
array rain int days
record city
name str(8)
people int
end
list cities city 4
word wettest (gives int) rem the index of the largest cell
0 to best
0 rain len range do (i int)
i rain idx best rain idx gt if i to best end
end each
best
end
word people_of (i int gives int) i cities idx city.people end
assign rain (3, 0, 12, 7, 0, 1, 2)
wettest str.to_str io.println
출력과 검사 목록
$ pnx see --checks 20-see-checks.pnx
2
word wettest: 3 checks, 3 proven
line 13: AGET: the index lies below the capacity of the array
line 13: AGET: the index lies below the capacity of the array
line 14: ADDI: the operands are in ranges whose result fits
word people_of: 2 checks, 1 proven
line 17: FGET: the row passed this table's check before
word (load): 7 checks, 7 proven
line 18: ASET: the index lies below the capacity of the array
line 18: ASET: the index lies below the capacity of the array
line 18: ASET: the index lies below the capacity of the array
line 18: ASET: the index lies below the capacity of the array
line 18: ASET: the index lies below the capacity of the array
line 18: ASET: the index lies below the capacity of the array
line 18: ASET: the index lies below the capacity of the array
(1c) pnx see --effects file.pnx 는 파일을 돌리지 않고 적재해, 파일의 낱말마다 스택과 지역 변수 밖에서 할 수 있는 일(pinax_word_effects, 19.5 (5))을 보인다: 읽고 쓰는 전역, 닿는 호스트 모듈과 그것을 통해 읽는지 쓰는지, extern 이면 “anything (a C function)”, “may yield”, “may fail”. 스택과 지역 변수만 쓰는 낱말은 “none” 이다.
20-see-effects.pnx
use io
global total int
word sq (n int gives int) n n mul end
word add_up (n int) total n add set total end
word report () cat ("total ", total sq) io.println end
word ask (gives line str or fail) io.read_line or_fail end
낱말마다 효과
$ pnx see --effects 20-see-effects.pnx
sq: none
add_up: reads total; writes total
report: reads total; io writes
ask: io reads; may fail
(2) pnx fmt file.pnx 는 들여쓰기와 공백만 고친 글을 표준 출력에 쓴다. 토큰과 줄바꿈의 자리, 주석은 그대로다. 고친 글을 다시 고쳐도 같다.
20-fmt.pnx
use io
word sign (n int gives r int)
n 0 gt if
1
else
n 0 lt if -1 else 0 end
end
end
정리한 모양
$ pnx fmt 20-fmt.pnx
use io
word sign (n int gives r int)
n 0 gt if
1
else
n 0 lt if -1 else 0 end
end
end
(3) pnx export-c file.pnx [NAME] 은 pnx file.pnx 처럼 파일을 적재하되 그 코드는 하나도 돌리지 않고, 프로그램의 코드를 C 로 표준 출력에 쓴다. pinax_native_attach(19.11)에 줄 표 NAME(빠지면 pnx_native)을 정의하는 파일이다.