Interpret Kipple!

12

2

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.

user55673

Posted 2016-07-08T14:59:29.830

Reputation:

1Do 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.) – Martin Ender – 2016-07-08T15:21:47.707

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 – None – 2016-07-08T15:26:30.497

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? – Alex A. – 2016-07-08T18:18:05.087

@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 . – None – 2016-07-08T18:22:48.057

Because of how the @ stack works, what happens if you run @+5? – Value Ink – 2016-07-08T18:27:31.313

@kevin lau - not kenny , it will just push topmost value +5 , like when applyed to other stacks – None – 2016-07-08T18:34:36.080

3What whitespace can occur in a source program? How can I ask for input i if I take the source program from stdin? – orlp – 2016-07-08T20:11:15.230

@orlp the things that come to mind are: 1. Take a file name as the first line of stdin, or 2. Pass the file name as command line. Or, for maximum craziness, pass the entire program as a string into command line? I wonder if that's possible – Value Ink – 2016-07-08T23:40:41.567

The spec says there are 29 stacks, but the only stacks I see are the 26 a-z stacks and @. Where are the last two stacks? – Value Ink – 2016-07-08T23:42:44.420

@KevinLau-notKenny I believe that's a typo, although my answer uses 28 stacks, I use the same data structure that I use for stacks for my call stack :) – orlp – 2016-07-08T23:47:38.810

@orlp "i" stack is like the input stack in fish . when the interpreter is excuted and the code is entered , before running the code , it will ask useres to give intial value to "i" stack . user can fill the stack , as much as needed (from bottom to top), and when excuted , program can get that user entered information from "i" stack , and extra values are left on stack. for example , if program needs 2 inputs and user enters "3 2 1" , "i" stack will be [3 2 1] from bottom to top . then 1 then 2 will be used as input and 3 will be left on stack , though programmer can clear or use "i" stack . – None – 2016-07-09T05:12:28.687

@KevinLau-notKenny , that was an error , there are 27 stacks - i've edited the main post . – None – 2016-07-09T05:17:11.463

@orlp as said in specification "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 " so there can be any type of white space in program . – None – 2016-07-09T05:21:54.897

Not clearly specified 1: the output from o stack is a string made of ascii char codes. It's only in the examples – edc65 – 2016-07-09T19:55:01.987

Not clearly specified 2: input number format. Is -12 a valid language token for the signed integer -12? – edc65 – 2016-07-09T19:55:54.800

Not clearly specified 3: stack underflow ? Popping an empty stack always returns 0 – edc65 – 2016-07-09T20:18:45.050

Checking again at https://esolangs.org/wiki/Kipple, this is the right answer: "An operand can either be a stack identifier or a nonnegative integer (0 to 2147483647)."

– edc65 – 2016-07-11T08:03:08.573

Just to be double-triple sure, when you say the program shouldn't print error messages, you mean that errors can be thrown, but should not appear on screen, yes? – Value Ink – 2016-07-11T08:55:44.587

Also, is the ? always the last operator in a group of commands, or is a?<b possible? – Value Ink – 2016-07-11T09:21:46.607

What's the defined behavior for a<b>c? Do they both use the top value of b, or does a take the top value and c take the next one? – Value Ink – 2016-07-11T23:06:33.587

@KevinLau-notKenny I've deleted my last comment , sorry , a<b>c pops topmost value from b and pushes to both c and a . – None – 2016-07-12T12:54:48.063

All right, thanks for the tip. You should update your spec to clarify it for other people, just in case. Also, what of my other question, regarding if a?<b is possible? – Value Ink – 2016-07-12T17:51:39.363

Not clearly specified 4: a<b>c pops topmost value from b and pushes to both c and a Missing this is a basic flaw (both here and in the original Kipple spec). Basically it's impossible to write a working interpreter based on this specifications - you have to check how the reference java interpreter works. That's why I downvote – edc65 – 2016-07-13T06:08:21.663

@GLASSIC Nope; it pushes the top value of b to a, and the second-to-top value of b to c. It's just like a<bb>c, or, more clearly, a<b c<b. It's just that Operands may be shared by two operators. No, the operand doesn't get a value before being evaluated, thus it will act differently on a<b>c the first and second times. – Erik the Outgolfer – 2016-07-15T13:15:14.110

Answers

6

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.

orlp

Posted 2016-07-08T14:59:29.830

Reputation: 37 067

i've answered your question about "i" stack in the main post's comments . – None – 2016-07-09T05:15:22.360

btw how it reads kipple programs ? via command arguments? how should i use it ? – None – 2016-07-09T12:56:30.533

@GLASSIC It expects the program on stdin. – orlp – 2016-07-09T13:05:42.160

Until when ? How to start excution ? – None – 2016-07-09T13:12:14.100

@GLASSIC Just pass the program on stdin. E.g. ./a.out < prime.k. – orlp – 2016-07-09T15:11:17.490

Do you have an online link where we can test? It's not working for me on repl.it – Value Ink – 2016-07-14T05:23:27.143

@KevinLau-notKenny https://ideone.com/FOy9kp

– orlp – 2016-07-14T08:51:20.807

3

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

Value Ink

Posted 2016-07-08T14:59:29.830

Reputation: 10 608

+1 anyway. Did you try the fibonacci program? – edc65 – 2016-07-14T09:01:33.107

@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 – Value Ink – 2016-07-14T19:54:15.510

No, the Fibonacci program is crap, for instance the line a+0 is nonsense – edc65 – 2016-07-16T08:33:23.750

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. – None – 2016-07-17T18:31:47.550

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.

– Value Ink – 2016-07-18T03:00:05.640

@GLASSIC sudden bounty? May I ask why? Assuming you were the one to award it – Value Ink – 2016-07-19T08:49:28.110

Bounty ??? No . i have not done any thing other than editing the post - Ah ... i hate touch screen devices ... – None – 2016-07-19T11:46:54.327

Someone just gave me a bounty though, don't know why – Value Ink – 2016-07-19T17:56:52.307