12
\$\begingroup\$

Introduction

Kipple is a stack-based, esoteric programming language invented by Rune Berg in March 2003.

Kipple has 27 stacks, 4 operators, and a control structure.

Stacks

The stacks are named a-z and contain 32-bit signed integers. There is also a special stack, @, to make outputting numbers more convenient. When a number is pushed onto @, the ASCII values of that number's digits are in fact pushed instead. (For example, if you push 12 to @, it will push 49 and then 50 to @ instead.)

Input is pushed onto the input stack i before the program is executed. The interpreter will ask for values to store in i before execution. After execution finishes, anything on the output stack o is popped to output as ASCII character . Since this is Kipple's only IO mechanism, interacting with a Kipple program is impossible.

Operators

An operand is either a stack identifier or a signed 32 bit integer.

Push: > or <

Syntax: Operand>StackIndentifier or StackIndentifier<Operand

The Push operator takes the operand to the left and pushes it onto the specified stack. For example, 12>a will push the value 12 onto stack a. a>b will pop the topmost value from stack a and push it onto stack b. Popping an empty stack always returns 0. a<b is equivalent to b>a. a<b>c pops topmost value from b and pushes to both c and a.

Add: +

Syntax: StackIndentifier+Operand

The Add operator pushes the sum of the topmost item on the stack and the operand onto the stack. If the operand is a stack, then the value is popped from it. For example, if the topmost value of stack a is 1, then a+2 will push 3 onto it. If a is empty, then a+2 will push 2 onto it. If the topmost values of stack a and b are 1 and 2, then a+b will pop the value 2 from stack b and push 3 onto stack a.

Subtract: -

Syntax: StackIndentifier-Operand

The Subtract operator works exactly like the Add operator, except that it subtracts instead of adding.

Clear: ?

Syntax: StackIndentifier?

The Clear operator empties the stack if its topmost item is 0.

The interpreter will ignore anything that isn't next to an operator, so the following program would work: a+2 this will be ignored c<i. However, the proper way to add comments is by using the # character. Anything between a # and an end-of-line character is removed before execution. ASCII character #10 is defined as end-of-line in Kipple.

Operands may be shared by two operators, e.g. a>b c>b c? may be written as a>b<c?.

The program 1>a<2 a+a will result in a containing the values [1 4] (from bottom to top) and not [1 3]. Likewise for the - operator.

The Control Structure

There is only one control structure in Kipple: the loop.

Syntax: (StackIndentifier code )

As long as the specified stack is not empty, the code within the matching parentheses will be repeated. Loops may contain other loops. For example, (a a>b) will move all the values of stack a onto stack b, though the order will be reversed. A functionally identical, but more elegant way to do this is (a>b).

Examples

100>@ (@>o)

This will output 100

33>o 100>o 108>o 114>o 111>o 87>o 32>o 111>o 108>o 108>o 101>o 72>o

This will print "Hello World!". When the o stack is being output, it starts to pop characters from top of the stack to bottom.

#prime.k by Jannis Harder
u<200
#change 200


k<2>m
u-2
(u-1 u>t u>z u<t
  (k>e e+0 e>r)
  (e>k)
  m+1
  m>t
  m>z
  m<t
  t<0>z? t?
  1>g
  (r>b
    m+0 m>a
    b+0 b>w
    (a-1 
      b+0 b>j
      j?
      1>s
      (j<0>s j?)
      s?
      (s<0 w+0 w>b s?)
      a>t
      a>z
      t>a
      b-1
      b>t
      b>z
      t>b
      z<0>t? z?
    a?)
    b?
    1>p
    (b<0 b? 0>p)
    p?
    (p 0>r? 0>p? 0>g)
  )
  g?
  (g m+0 m>k 0>g?)
u?)
(k>@
  10>o
  (@>o)
)

This is a prime number generator, but I'm not sure how it works.

Rules

  • You must write a program/function that interprets Kipple. This program/function may get a Kipple program via a source file, or get it via STDIN directly from the user. If STDIN is not available, it must get it from keyboard input, and continue getting input until a specific unprintable character is entered. For example, if your interpreter is written in x86 machine code, it would get the Kipple program character by character from keyboard, and continue to do so until esc (or any other key other that does not emit a printable character) is pressed.

  • If there is an error, e.g. a syntax error or stack overflow, it must acknowledge it in some way, for example by returning 10 instead of 0 or error messages produced by the interpreter/compiler, BUT NOT PRINTING ERROR MESSAGES.

  • Any other regular rules for code golf apply for this challenge.

  • Your code will be tested with some of the examples in Kipple's samples archive

This is a . Shortest code in bytes will win. Good Luck!


Note that there is an optional operator in Kipple, ", but it is not a part of the specification and just an extra feature in official interpreter. I haven't mentioned it here so it does not need to be supported in your submission.

If you have any doubt about any part of specification , you can examine it with official interpreter written in Java . This will download a zip file containing compiled program and source code . It's licensed under the GPL.

\$\endgroup\$
  • 1
    \$\begingroup\$ Do we have to use 32-bit signed integers or can we go with the host implementation's natural integer type? (The most important cases are probably unsigned 32-bit integers, signed or unsigned 8-bit integers and arbitrary-precision integers.) \$\endgroup\$ – Martin Ender Jul 8 '16 at 15:21
  • \$\begingroup\$ well , it was what i found on esotric wiki . yes , because your interpreter may be incompatible with other kipple programs which their mechanism are based on this feature \$\endgroup\$ – user55673 Jul 8 '16 at 15:26
  • \$\begingroup\$ Can you be more specific about the behavior in the case of errors? So we can return an incorrect answer or emit an error, but we can't print the error? \$\endgroup\$ – Alex A. Jul 8 '16 at 18:18
  • \$\begingroup\$ @Alex A. Yes , because it can be considered as program's output , and you can make a kipple program which can have same output as error message . Also it is "cheaper" (uses less characters) not to have a function/statement that prints an error message . \$\endgroup\$ – user55673 Jul 8 '16 at 18:22
  • 3
    \$\begingroup\$ What whitespace can occur in a source program? How can I ask for input i if I take the source program from stdin? \$\endgroup\$ – orlp Jul 8 '16 at 20:11
6
\$\begingroup\$

C, 709 702 bytes

The byte score is with newlines (that can be removed) removed, but for ease of reading I post it here with newlines:

#define R return
#define C ;break;case
c[999]={};*P=c;*S[28];M[99999]={};t;*T;
u(s,v){S[s]+=28;*S[s]=v;
if(s>26){for(t=v/10;t;t/=10)S[s]+=28;T=S[s];do{*T=48+v%10;T-=28;}while(v/=10);}}
o(s){t=S[s]-M>27;S[s]-=28*t;R S[s][28]*t;}
I(s){R s<65?27:s-97;}
O(int*p){if(!isdigit(*p))R o(I(*p));
for(;isdigit(p[-1]);--p);for(t=0;isdigit(*p);t*=10,t+=*p++-48);R t;}

main(i,a){for(i=0;i<28;++i)S[i]=M+i;
for(;~(*++P=getchar()););P=c+1;
for(;;){i=I(P[-1]);switch(*P++){
case 35:for(;*P++!=10;)
C'<':u(i,O(P))
C'>':u(I(*P),O(P-2))
C'+':u(i,*S[i]+O(P))
C'-':u(i,*S[i]-O(P))
C'?':if(!*S[i])S[i]=M+i
C'(':for(i=1,T=P;i;++T)i+=(*T==40)-(*T==41);if(S[I(*P)]-M<28)P=T;else u(26,P-c)
C')':P=c+o(26)-1
C-1:for(;i=o(14);)putchar(i); R 0;}}}

Compile with gcc -w golf.c (-w silences warnings for your sanity).

Supports everything except the i input, as the asker has not responded yet to my inquiry on how to do it if you take the code from stdin. It does not report syntax errors.

\$\endgroup\$
  • \$\begingroup\$ i've answered your question about "i" stack in the main post's comments . \$\endgroup\$ – user55673 Jul 9 '16 at 5:15
  • \$\begingroup\$ btw how it reads kipple programs ? via command arguments? how should i use it ? \$\endgroup\$ – user55673 Jul 9 '16 at 12:56
  • \$\begingroup\$ @GLASSIC It expects the program on stdin. \$\endgroup\$ – orlp Jul 9 '16 at 13:05
  • \$\begingroup\$ Until when ? How to start excution ? \$\endgroup\$ – user55673 Jul 9 '16 at 13:12
  • \$\begingroup\$ @GLASSIC Just pass the program on stdin. E.g. ./a.out < prime.k. \$\endgroup\$ – orlp Jul 9 '16 at 15:11
3
+50
\$\begingroup\$

Ruby, 718 bytes (currently noncompeting)

i'm very tired

File is loaded as a command line argument, and input is sent through STDIN. Alternatively, pipe the file into STDIN if you don't need input in your i register.

Because of some confusion regarding the spec, the current version is not handling a<b>c properly, and therefore is noncompeting until it is fixed.

a<b>c is fixed now. However, it still returns the wrong result when running the primes function, so it still remains as a noncompeting answer.

(f=$<.read.gsub(/#.*?\n|\s[^+-<>#()?]*\s/m,' ').tr ?@,?`
t=Array.new(27){[]}
t[9]=STDIN.read.bytes
k=s=2**32-1
r=->c{c=c[0];c[0]==?(?(s[c[1..-2]]while[]!=t[c[1].ord-96]):(c=c.sub(/^(.)<(\D)>(.)/){$1+"<#{t[$2.ord-96].pop||0}>"+$3}.sub(/(\d+|.)(\W)(\d+|.)?/){_,x,y,z=*$~
a=x.ord-96
b=(z||?|).ord-96
q=->i,j=z{j[/\d/]?j.to_i: (t[i]||[]).pop||0}
l=t[a]
y<?-?(x==z ?l[-1]*=2:l<<(l.pop||0)+q[b]
l[-1]-=k while l[-1]>k/2):y<?.?(x==z ?l[-1]=0:l<<(l.pop||0)-q[b]
l[-1]+=k while l[-1]<-k/2-1):y<?>?t[a]+=a<1?q[b].to_s.bytes: [q[b]]:y<???
(t[b]+=b<1?q[a,x].to_s.bytes: [q[a,x]]): l[-1]==0?t[a]=[]:0
z||x}while c !~/^(\d+|.)$/)}
s=->c{(z=c.scan(/(\((\g<1>|\s)+\)|[^()\s]+)/m)).map &r}
s[f]
$><<t[15].reverse.map(&:chr)*'')rescue 0
\$\endgroup\$
  • \$\begingroup\$ +1 anyway. Did you try the fibonacci program? \$\endgroup\$ – edc65 Jul 14 '16 at 9:01
  • \$\begingroup\$ @edc65 Fibbonacci sequence program prints the wrong thing as well: 0 1 1 2 4 8 16... I wonder if it's a spec error \$\endgroup\$ – Value Ink Jul 14 '16 at 19:54
  • \$\begingroup\$ No, the Fibonacci program is crap, for instance the line a+0 is nonsense \$\endgroup\$ – edc65 Jul 16 '16 at 8:33
  • \$\begingroup\$ i guess the problem about prime numbers is that it doesn't handle nested control structures , but i don't know much about ruby , i doubt my guess's correct. \$\endgroup\$ – user55673 Jul 17 '16 at 18:31
  • \$\begingroup\$ This program should handle nested sets of parens properly because of the recursive regex match on /(\((\g<1>|\s)+\)|[^()\s]+)/m that it uses to split on tokens and groups of tokens. (Test it on regex101). It's probably an error in the rest of my parsing, but I don't know where. \$\endgroup\$ – Value Ink Jul 18 '16 at 3:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy