자기 통역 통역사


25

이 질문에 대한 George Edison의 의견을 바탕으로 가장 작은 자기 해석 통역사를 작성하십시오.

  • 선택한 언어를 사용할 수 있습니다.
  • 빈 언어는 포함되지 않습니다. 프로그램은 2 자 이상이어야합니다.
  • 이 프로그램은 전체 언어 를 통역 할 필요가 없으며 , 통역사를 포함하는 언어 기능의 Turing-complete 서브 세트 일뿐입니다.
  • Quines는 계산되지 않습니다.
  • 언어의 내장 eval기능 또는 이와 동등한 기능을 사용하지 마십시오 . apply등도 마찬가지입니다 .

1
/usr/bin/cat-완전성은 어떻습니까?
Ming-Tang

@ SHINNKiROU : 고마워, 나는 그것을 테스트로 생각하지 않았다. 업데이트되었습니다.
호아 롱 탐

관련 : Stack Overflow에 작성된 가장 작은 인터프리터가있는 언어 이지만 실제로 여기에 주어진 규칙을 따르는 답변은 거의 없습니다 (단 하나입니까?).
dmckee

1
Scheme sexp 구문 분석기를 다시 작성해야합니까, 아니면 호스트 언어의 상태를 고려할 수 있습니까?
JB

@ JB : sexp파서를 포함하여 언어의 문자열 처리 유틸리티가 좋습니다.
호아 롱 탐

답변:


19

CI-260

,(1p0(2d())(41(2d())('#((1p0()(10()(1d,1p$)=)<)$2d,1p$)(40(1d,1c$^)(''(1d,^)('0
'9('0-(,'0'9('0-2p10*+1p$)(!1d)~)$^)(0($)'$(^)'^(&)'&(c)'c(p)'p(d)'d(=)'=(<)'<(
>)'>(~)'~(.)'.(,)',(!)'!(+)'+(-)'-(*)'*(/)'/(%)'%()38p(1p3p0(3d)((2)(3)=p1d1p$)
=)$)~)=)=,2p$&)=)=)<)$$

320 → 260 : 간단한 문자-명령어 매핑을 누른 다음 접습니다. 이 경우 코드 당 크기가 절반이지만 (18 개의 경우가 있음) 접는 데 30 자입니다.

이것은 내가 만든 언어 중 하나입니다 ( Gist에서 호스팅되는 기본 통역사 ). 이 언어는 코드 조각을 유지한다는 점에서 독특합니다. 즉,이 스택 기반 언어의 명령 문자열은 다른 언어의 데이터 구조 또는 클로저와 동일한 효과를 위해 사용됩니다.

1^      # Push a 1, and "lift" it to be a code literal.
(5 +)   # Define a code literal.
&       # Join the two code literals, forming (1 5 +)
$       # Execute the code literal.

인터프리터는 실행하기 전에 전체 프로그램의 코드 단편을 빌드하므로 컴파일러로 간주 될 수도 있습니다. 이로 인해 인터프리터를 쌓아도 지수 런타임 오버 헤드가 발생하지 않습니다.

인터프리터는 모든 연산자를 호스트 인터프리터에서 직접 파생시킵니다. 그러나 자체적으로 구문 분석을 수행하므로 대부분의 코드는 문자를 해당 코드 리터럴로 변환하는 시퀀스 일뿐입니다. 이것은을 사용하는 것과 같지 eval않지만 프로그래밍 언어 구현이 호스트 언어 / 아키텍처의 의미에 얼마나 의존 하는지를 보여줍니다.


언어 참조 :

통역사를 여기로

블록

  • ( ... )

    컨텍스트가없는 명령어 목록 인 "블록"을 만듭니다. 내부적으로 기계 코드 일 수도 있습니다.

  • 블록 $

    블록을 호출하십시오. 수신자는 호출되는 블록을 포함하는 전역 스택을 전달받습니다.

  • ^

    가치를 높이십시오. 즉, 그 값을 밀어주는 블록으로 바꾸십시오.

    :

       1 ^
    == (1)
    
  • 블록 1 블록 2 &

    두 블록을 결합하여 두 블록을 순서대로 실행하십시오.

    :

       (1) (2) &
    == (1 2)
    

스택 조작

  • c

    스택의 n 번째 값을 복사하십시오.

    :

       5 4 3 2 1 0 3c
    == 5 4 3 2 1 0 3
    
  • p

    스택의 n 번째 값을 뽑습니다 (제거하고 앞으로 가져옵니다).

    :

       5 4 3 2 1 0 3p
    == 5 4 2 1 0 3
    
  • d

    스택에서 n 값을 삭제하십시오. 0dno-op입니다.

    :

       5 4 3 2 1 0 3d
    == 5 4 3
    

관계 연산자

  • ab (on_true) (on_false) =

    a가 같은지 테스트 b. 첫 번째 인수를 제외한 모든 것을 소비하고 on_true 또는 on_false를 호출하십시오. 한 인수가 0이고 다른 인수가 다른 유형 인 경우 결과는 false입니다. 그렇지 않으면 a와 b는 정수 여야합니다.

    :

       3 3 ('0+ .) (1d) =
    == 3 '0+ .
    
  • ab (on_true) (on_false) <

    a가 b보다 작은 지 테스트합니다. a와 b는 정수 여야합니다.

    :

       3 5 (1d 5) () <
    == 3 1d 5
    == 5
    
  • ab (on_true) (on_false) >

    a가 b보다 큰지 테스트합니다. a와 b는 정수 여야합니다.

    :

       3 5 (1d 5) () >
    == 3
    
  • lo hi (on_true) (on_false) ~

    lo <= a <= hi인지 테스트하십시오. a, lo 및 hi는 정수 여야합니다.

    :

       3 0 10 ('0+ .) (1d) ~
    == 3 '0+ .
    

I / O

  • 기음 .

    문자 c를 넣습니다 (스택에서 소비).

  • ,

    캐릭터를 가져 와서 스택에 넣습니다. 파일의 끝에 도달하면 -1이 푸시됩니다.

  • 기음 !

    캐릭터를 꺼냅니다. C의 ungetc와 마찬가지로 푸시 백은 하나만 허용됩니다.

정수 리터럴

  • 'c

    문자 c를 누릅니다.

  • [0-9] +

    십진 정수를 누릅니다.

산수

  • ab +
  • ab -
  • ab *

    두 숫자를 더하거나 빼거나 곱하십시오.

    :

       3 5 + 7 3 + *
    == 80
    
  • ab /

  • ab %

    나눗셈과 계수. C와 달리 음의 무한대로 향합니다.

여러 가지 잡다한

  • 코드 #주석

    #문자가 줄의 끝으로 모든 걸 코멘트.

  • )

    블록을 종료하는 데 사용됩니다. 전체 프로그램을 종료하는 데에도 사용할 수 있습니다.

  • 다른 모든 문자는 무시됩니다.


24

이진 Lambda 미적분, 232 비트 (29 바이트)

0101000110100000000101011000000000011110000101111110011110000101110011110000001111000010110110111001111100001111100001011110100111010010110011100001101100001011111000011111000011100110111101111100111101110110000110010001101000011010

자세한 내용은 http://en.wikipedia.org/wiki/Binary_lambda_calculus#Lambda_encoding 을 참조하십시오


2
이것이 받아 들여지는 답이 아닌 이유 D : BLC는 놀랍습니다!
고양이

당신은 그것을 전혀 설명 할 수 있습니까?
PyRulez 2016 년

1
불행하게도, Wikipedia는 Binary Lambda Calculus 페이지를 제거했습니다. 내 tromp.github.io/cl/cl.html 페이지는 보존 된 사본과 통역사의 작업을 설명하는 논문으로 연결됩니다.
John Tromp

13

나는 이것에 대한 신용을 얻을 수 없지만 나는이 놀라운 것을 공유 할 것이라고 생각했다.

Brainf *** (423)

>>>+[[-]>>[-]++>+>+++++++[<++++>>++<-]++>>+>+>+++++[>++>++++++<<-]+>>>,<++[[>[
->>]<[>>]<<-]<[<]<+>>[>]>[<+>-[[<+>-]>]<[[[-]<]++<-[<+++++++++>[<->-]>>]>>]]<<
]<]<[[<]>[[>]>>[>>]+[<<]<[<]<+>>-]>[>]+[->>]<<<<[[<<]<[<]+<<[+>+<<-[>-->+<<-[>
+<[>>+<<-]]]>[<+>-]<]++>>-->[>]>>[>>]]<<[>>+<[[<]<]>[[<<]<[<]+[-<+>>-[<<+>++>-
[<->[<<+>>-]]]<[>+<-]>]>[>]>]>[>>]>>]<<[>>+>>+>>]<<[->>>>>>>>]<<[>.>>>>>>>]<<[
>->>>>>]<<[>,>>>]<<[>+>]<<[+<<]<]

10

블록 스크립트-535

{[B':=?0:B';=?0:B'}=?0:B'{=?,A!,A!d1c&:B'?=?,A!,A!2e&:B''=?,,A!d3c&:B{[B'0<?0:B
'9>?0:1}!?B'0-{[,g!?c'0-B10*d+A!:Bd]A!d3c&}!:B'#=?{[,10=?,]A!:A!}!:,A!Bb&}{[AC[
B]DB?[AB{[Bh&hbhn!}{[B[AB]C?1-eA!:b}&[C1=?E[C]FHc&B!:C2=?{G?D:E[C}!FHcI!:C3=?E[
C]B!:C'!=?G[ABC]Hc&dbh&D?b@I!B!:b@I!:C'&=?HB!:C'@=?FGDI!:C'[=?GF&HDI!:C']=?F[A]
HDI!:C',=?,B!:C'.=?G.FHDI!:C'a'z{[DC<?0:DB>?0:1}!?Ce-HA!B!:C'A'Ze!?F[B]Cg-dA!B!
:{C'+=?{[CB+}:C'-=?{[CB-}:C'*=?{[CB*}:C'/=?{[CB/}:C'%=?{[CB%}:C'<=?{[CB<}:C'>=?
{[CB>}:C'==?{[CB=}:0}!?H[A][B]Ge!B!:FHDI!:c},c!0ac&0&0&0bho!;

BlockScript는 이 도전을 위해 특별히 만든 간단한 스파게티 스택 기반 언어입니다. 기본 인터프리터는 blockscript.c 입니다.

샘플 프로그램 (처음 15 피보나치 수를 인쇄) :

{[B?B10/A!B10%d&:0}
{[B0<?'-.0B-A!:{B?Bh!{[B?B[A]A!B[B]'0+.:}!:'0.}!10.}
{[B?Dd!DC+B1-CecA!:}
0 1 15d!
;

인터프리터는 표준 입력에서 소스 코드와 프로그램 입력을 순서대로 읽습니다. 즉, 인터프리터 내에서 인터프리터 내에서 인터프리터를 실행하려면 간단히 복사하여 붙여 넣습니다.

# Level 1
{[B':=?0:B';=?0:B'}=?0:B'{=?,A!,A!d1c&:B'?=?,A!,A!2e&:B''=?,,A!d3c&:B{[B'0<?0:B
'9>?0:1}!?B'0-{[,g!?c'0-B10*d+A!:Bd]A!d3c&}!:B'#=?{[,10=?,]A!:A!}!:,A!Bb&}{[AC[
B]DB?[AB{[Bh&hbhn!}{[B[AB]C?1-eA!:b}&[C1=?E[C]FHc&B!:C2=?{G?D:E[C}!FHcI!:C3=?E[
C]B!:C'!=?G[ABC]Hc&dbh&D?b@I!B!:b@I!:C'&=?HB!:C'@=?FGDI!:C'[=?GF&HDI!:C']=?F[A]
HDI!:C',=?,B!:C'.=?G.FHDI!:C'a'z{[DC<?0:DB>?0:1}!?Ce-HA!B!:C'A'Ze!?F[B]Cg-dA!B!
:{C'+=?{[CB+}:C'-=?{[CB-}:C'*=?{[CB*}:C'/=?{[CB/}:C'%=?{[CB%}:C'<=?{[CB<}:C'>=?
{[CB>}:C'==?{[CB=}:0}!?H[A][B]Ge!B!:FHDI!:c},c!0ac&0&0&0bho!;

# Level 2
{[B':=?0:B';=?0:B'}=?0:B'{=?,A!,A!d1c&:B'?=?,A!,A!2e&:B''=?,,A!d3c&:B{[B'0<?0:B
'9>?0:1}!?B'0-{[,g!?c'0-B10*d+A!:Bd]A!d3c&}!:B'#=?{[,10=?,]A!:A!}!:,A!Bb&}{[AC[
B]DB?[AB{[Bh&hbhn!}{[B[AB]C?1-eA!:b}&[C1=?E[C]FHc&B!:C2=?{G?D:E[C}!FHcI!:C3=?E[
C]B!:C'!=?G[ABC]Hc&dbh&D?b@I!B!:b@I!:C'&=?HB!:C'@=?FGDI!:C'[=?GF&HDI!:C']=?F[A]
HDI!:C',=?,B!:C'.=?G.FHDI!:C'a'z{[DC<?0:DB>?0:1}!?Ce-HA!B!:C'A'Ze!?F[B]Cg-dA!B!
:{C'+=?{[CB+}:C'-=?{[CB-}:C'*=?{[CB*}:C'/=?{[CB/}:C'%=?{[CB%}:C'<=?{[CB<}:C'>=?
{[CB>}:C'==?{[CB=}:0}!?H[A][B]Ge!B!:FHDI!:c},c!0ac&0&0&0bho!;

# Level 3
{[B?B10/A!B10%d&:0}
{[B0<?'-.0B-A!:{B?Bh!{[B?B[A]A!B[B]'0+.:}!:'0.}!10.}
{[B?Dd!DC+B1-CecA!:}
0 1 15d!
;

영화의 시작 과 마찬가지로 , 당신은 거의 세 단계보다 더 깊이 갈 수 없습니다. 시간 문제가 아니라 공간 문제입니다. BlockScript는 메모리를 풍부하게 누출하며 이는 언어 자체의 설계 방식과 관련이 있습니다.


언어 참조 :

통역사를 여기로

BlockScript에서 "스택"은 익숙한 후속 작업으로 덮어 쓰는 배열이 아닙니다. 실제로 변경 불가능한 연결 목록으로 구현되며 프로그램 기간 동안 스택이 유지됩니다. 또한 연산자 (제외 @)는 스택에서 값을 제거 하지 않습니다 . 그러나 스택 수정은 발생하는 블록에만 영향을줍니다.

값 선택

  • a ...을 통하여 z

    스택에서 0-25 번째 항목을 가져 와서 스택으로 밉니다. a스택의 헤드 또는 가장 최근에 밀린 항목을 나타냅니다.

  • A ...을 통하여 Z

    현재 프레임의 0-25 번째 항목을 가져 와서 스택으로 밉니다.

  • [

    "프레임"을 열어 스택 헤드의 스택 참조 (아래 참조)에서 항목을 선택하십시오. [일치하지 않아도 ]되지만 프레임 범위는 어휘 범위입니다. BlockScript에서 "scope"는 블록을 형성 하는 중괄호 ( {... })로 결정됩니다 . 따라서 블록 내부에서 프레임을 여는 것은 블록 외부의 코드에 영향을 미치지 않습니다.

  • ]

    현재 프레임을 닫고 이전 프레임 (있는 경우)으로 돌아갑니다.

블록

  • { ... }

    "블록"을 만들고 스택으로 밀어 넣습니다. 블록 안에서는 스택이 블록 앞의 위치에서 시작합니다. 단, 호출자의 스택은 맨 위로 밀립니다. 스택은 BlockScript에서 영구적이며 불변이므로 블록은 클로저입니다. 관용구 {[는 블록을 연 다음 프레임을 열어 인수 선택을 시작합니다 (를 A통해 사용 Z). 블록의 반환 값 }은 도달 했을 때 스택의 헤드입니다 .

    예:

    '3 '2 '1 {[ b. d. f. B. C. D. A! } 'D 'C 'B d!;
    

    이 인쇄 123BCD123DCB123BCD123DCB…됩니다. 소문자는 스택 값을 나타내며 대문자는 인수를 나타냅니다 (프레임이 호출자의 스택으로 설정 되었기 때문에). A!호출자의 머리를 잡고 (호출되는 블록으로 보장됨) 호출합니다. 왜 BCD매번 B. C. D.역순으로 바뀌는 지 궁금하다면 블록이 호출되기 직전에 해당 인수를 역순으로 푸시 하기 때문 입니다.

  • !

    블록을 호출하십시오. 반환 값을 스택으로 밉니다.

스택 레퍼런스

  • &

    스택 참조를 작성하여 스택으로 밉니다. 스택의 모든 항목을 효과적으로 가져 와서 "튜플"을 형성하므로이를 "초과 단점"이라고 생각하십시오. 관용구의 &[것을 어떤 수단 a, b, c라고는 이전에 지금 액세스 할 수 있습니다하는 A, B, C(블록의 나머지 나까지 ]발생).

    &BlockScript는 일반적으로 필요한 것보다 많은 값을 캡처 하기 때문에 의도적으로 메모리가 누수됩니다.

  • @

    스택 참조가 가리키는 스택으로 전환합니다 a. 이 연산자는 다소 이상하지만 BlockScript 자체 통역사는이 인수를 두 번 사용하여 동일한 인수를 두 번 푸시하지 않아도됩니다. 그 문제에 대한 영향 @(또는 그 문제에 대한 스택 작업)은 그것이 호출되는 블록으로 제한됩니다. 또한 프레임은의 영향을받지 않으므로 @스택을 전환 한 후 필요한 값을 가져 오는 데 프레임을 사용할 수 있습니다.

조건식

  • ? <참 사실> < : 거짓>

    C의 삼항 연산자와 같은 조건식입니다. 즉, a"true"인 경우 (즉, 정수 0과 같지 않은 경우) <on true>를 수행 하고 그렇지 않으면 <on false>를 수행하십시오 .

I / O

참고 : 입력 및 출력은 UTF-8로 수행됩니다. "문자"는 유니 코드 인덱스에 해당하는 정수입니다.

  • ,

    다음 입력 문자를 가져 와서 스택으로 푸시하십시오. 입력의 끝에 도달하면 대신 -1을 누르십시오.

  • .

    스택 헤드에 문자를 출력합니다.

정수 / 문자 리터럴

참고 : 정수 및 문자는 BlockScript에서 동일합니다.

  • 'c

    문자 c를 누릅니다.

  • [0-9] +

    십진 정수를 누릅니다.

산수

이 연산자는 정수 값에서만 작동합니다.

  • +계산 b+ a(결과를 푸시하지만 값을 버리지 않음)
  • -계산 b- a.
  • *계산 b* a.
  • /계산 b/ a(정수 나누기; 음의 무한대로 반올림).
  • %계산 b% a(정수 계수, 음의 무한대로 반올림).

관계 연산자

이 연산자는 정수 값에서만 작동합니다.

  • <경우 b미만이다 a푸시 1, 다른 푸시 0.
  • >
  • =

여러 가지 잡다한

  • # 줄의 끝까지 주석
  • 이 프로그램은 ;
  • 다른 모든 문자는 무시됩니다.

2
그리스도. CI와 같은 사양을 공유하고 싶으십니까?
Casey

@Casey : 참조가 추가되었습니다.
Joey Adams

1
당신이 꿈꾸고 있다는 것을 알고 싶으십니까? ... 4 레벨에
Mateen Ulhaq

3

조조 츠 LISP : 414

멋진 블록을 얻기 위해 추가 된 줄 바꿈은 필요하지 않으며 계산되지 않습니다.

((\(E V A L)(E(r)'(())))(\(x e)(?(s x)(V x e)((\(b j)(?(= b ")(a j)(?(= b \)x
(?(= b ?)(?(E(a j)e)(E(a(d j))e)(E(a(d(d j)))e))(?(s b)(A b(E(a j)e)(E(a(d j)
)e))(E(a(d(d b)))(L(a(d b))j e)))))))(E(a x)e)(d x))))(\(x g)(? g(?(= x(a(a
g)))(d(a g))(V x(d g)))x))(\(f h v)(?(= f r)(r)(?(= f p)(p h)(?(= f s)(s h)(?
(= f a)(a h)(?(= f d)(d h)(?(= f =)(= h v)(c h v))))))))(\(k v i)(? k(L(d k)(
d v)(c(c(a k)(E(a v)i))i))i)))

이론적으로는 스스로 실행할 수 있어야하지만 원래 해석기는 BrainFuck 바이너리이고 해석기 자체이므로 각 부분 만 테스트 할 수있었습니다. 그 자체와 간단한 표현이 주어지면 (p p)지금까지 기다린 40 분보다 더 많은 시간이 필요하다고 생각하며 빠른 jitbf실행을 사용하여 Perl Inline-C를 사용하여 C 코드를 즉석에서 실행합니다.

Zozotez에서 전체 Zozotez를 구현하는 것은 불가능합니다. 왜냐하면 cons를 변경하는 수단이 없으며 :바인딩을 업데이트하기 위해 (setq / define) 필요하기 때문입니다. 또한 인터프리터에서 사용하지 않았기 때문에 명시적인 begin / progn 또는 & rest 인수, 매크로 및 특수 인쇄 인수를 구현하지 않았습니다. 나는 그것을 p사용하지 않더라도 (인쇄)를 포함 했으므로 프로그램은 원래 해석기와 마찬가지로 계산을 명시 적으로 인쇄해야합니다.

같은 ungolfed :

;; A stand alone Zozotez script need to be
;; contained in one expression, here with
;; all functions provided as arguments to
;; get them bound in the dynamic environment
((\ (E V A L)
  (E(r)'(())))
 ;; E (EVAL)
 (\ (x e)
   (? (s x)
      (V x e)
      ((\ (b j)
         (? (= b ") (a j)
         (? (= b \) x
         (? (= b ?) (? (E(a j)e) (E(a(d j))e) (E(a(d(d j)))e))
         (? (s b)
            (A b (E(a j)e) (E (a(d j))e))
            (E (a(d(d b))) (L(a(d b))j e)))))))
       (E (a x) e)(d x))))
 ;; V (VALUE / symbol->value)
 (\ (x g)
   (? g
      (? (= x (a (a g)))
         (d (a g))
         (V x (d g)))
      x))
 ;; A (APPLY) but just for primitives
 (\ (f h v)
   (? (= f r) (r)
   (? (= f p) (p h)
   (? (= f s) (s h)
   (? (= f a) (a h)
   (? (= f d) (d h)
   (? (= f =)
      (= h v)
      (c h v))))))))
 ;; L ( joint evLis / extend-env)
 (\ (k v i)
   (? k
      (L (d k) 
         (d v)
     (c (c (a k) 
           (E (a v) i)) 
        i))
      i)))

0

CHIQRSX9 + (아마도 경쟁하지 않음), 2 바이트

+I

STDIN을 처리하는 내장 인터프리터를 실행하는 을 사용하지 않고이 HQ9 + 기반 언어로 자체 해석 인터프리터를 작성할 수있는 방법이 I없습니다.


1
내장 된 자체 통역사가 허용되지 않는다는 규칙은 없습니다. 그것은 eval프로그램이 아니라 표현을위한 것입니다.
Outgolfer Erik

이 언어에서 소수를 어떻게 계산합니까?
pppery

@ppperry X는 구현에 의존하는 방식으로 언어 Turing-complete (프라임을 계산할 수 있음)로 만들어야합니다.
user8397947

Esolang 페이지에 따르면 Perl 인터프리터의 X명령은 프로그램을 무작위로 혼란스럽게 만들고 실행합니다. 즉, 소수를 결정적으로 계산하는 데 명령보다 명령을 사용할 수 없습니다. X지정한 방식으로 사용할 수있는 통역사 예제를 제공해 주시겠습니까?
pppery

@ppperry 분명히 Perl로 작성된 통역사가 유일한 통역사입니다. 또한 특정 값으로 "무작위 화"할 때 소수를 계산하는 프로그램이 있다면 어떨까요?
user8397947 2016 년

0

동시 파일 시스템 Befunge 98-53 \ 18 바이트 (거의 확실하게 부정 행위)

제한이없는 전체 53 바이트 인터프리터 (IP 분할 및 래핑과 관련된 복잡한 타이밍 상호 작용을 테스트하지는 않았지만) :

v ;;;;;;;;
>]390'ai@
 t;;;;;;;;
;>zzzzz#;

명명 된 파일에서 입력을 읽고 a실행합니다. 자체 수정 코드를 사용할 수없는 규칙에는 지정되어 있지 않습니다.

랩핑을 허용하지 않는 18 바이트 인터프리터 (코드의 한쪽 가장자리의 IP 이동 및 반대쪽 가장자리에서 시작) :

]210'ai@
t
><
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.