Divrac

From Esolang
Jump to navigation Jump to search

Divrac is an OISC by User:PythonshellDebugwindow.

Memory

Divrac uses an unbounded number of memory slots, each of which can hold a signed integer. All slots are assigned a index, which is a nonnegative integer.

Syntax

A program is made up of zero or more lines. Each line is of the form:

a,b,c,d,n

with optional (ignored) vertical whitespace. Lines are separated by newlines.

a {\displaystyle a} {\displaystyle a}, b {\displaystyle b} {\displaystyle b}, c {\displaystyle c} {\displaystyle c}, d {\displaystyle d} {\displaystyle d}, and n {\displaystyle n} {\displaystyle n} must be either integers, representing integer values, or integers surrounded by any number of brackets. Each pair of brackets represents a level of indirection. For example, 1 represents the number 1, [1] represents the value in the 1st memory space, [[1]] represents the value in the m {\displaystyle m} {\displaystyle m}th memory space where m {\displaystyle m} {\displaystyle m} is the value in the 1st memory slot, and so on.

BNF

Remove all vertical whitespace first.

program ::= lines | line | ""
lines ::= line "\n" | lines lines
line ::= val "," val "," val "," val "," val
val ::= int | "[" val "]"
int ::= digit | digit int

Semantics

Each line, the numerator and denominator of the reduced improper form of a b ÷ c d {\displaystyle {\frac {a}{b}}\div {\frac {c}{d}}} {\displaystyle {\frac {a}{b}}\div {\frac {c}{d}}} are calculated. If n {\displaystyle n} {\displaystyle n} is nonnegative, the numerator is stored in the n {\displaystyle n} {\displaystyle n}th memory slot, and the denominator in the n + 1 {\displaystyle n+1} {\displaystyle n+1}th.

If, however, n {\displaystyle n} {\displaystyle n} is negative, then it prints the numerator to STDOUT if it is -2, and sets the instruction pointer to the numerator if it is -1 (any other value is undefined behaviour).

A negative value of a {\displaystyle a} {\displaystyle a}, b {\displaystyle b} {\displaystyle b}, c {\displaystyle c} {\displaystyle c}, or d {\displaystyle d} {\displaystyle d} represents a special value: 1 {\displaystyle -1} {\displaystyle -1} represents the value of the instruction pointer, 2 {\displaystyle -2} {\displaystyle -2} reads a positive integer from STDIN, and all other negative values of these four are undefined behaviour.

Division by zero at any point causes the program to exit. If the numerator of a b ÷ c d {\displaystyle {\frac {a}{b}}\div {\frac {c}{d}}} {\displaystyle {\frac {a}{b}}\div {\frac {c}{d}}} is 0, then the denominator is redefined to be a random integer from 1 to 1000.

Examples

Truth-machine

Using the I/O extension:

0,1,1,1,0
1,1,1,1,1
[-2],1,1,1,2
[2],1,1,1,-2
1,1,[2],1,3
4,1,1,1,-1

Implementations

Swift

See #External resources.

Python 3

It is not specified what should happen if n < 2 {\displaystyle n<-2} {\displaystyle n<-2}. This implementation treats it as a nop. It also assumes that setting the IP to an invalid line number is a valid way to halt a program.

 import sys
 from math import gcd
 from functools import partial
 from collections import defaultdict
 def process(ip,entry,special=False):
 global memory
 if isinstance(entry,list):
 if len(entry)!=1: print("Invalid entry on line %d: %s"%(ip,str(entry)));sys.exit(1)
 return memory[process(ip,entry[0],special=special)]
 elif type(entry) == int:
 if special:
 return entry
 else:
 if entry>=0:
 return entry
 elif entry==-1:
 return ip+1
 elif entry==-2:
 return int(input())
 else:
 print("Invalid entry on line %d: %d"%(ip,entry));sys.exit(1)
 else:
 print("Invalid entry on line %d: %s"%(ip,str(entry)));sys.exit(1)
 if len(sys.argv)<2:
 print("No filename to execute.")
 else:
 try: 
 with open(sys.argv[1], "r") as f:
 prog = f.read().splitlines()
 except IOError: print("File '"+filename+"' not found."); sys.exit(1)
 for i in range(len(prog)):
 line = prog[i].strip()
 if not line: i-=1;continue
 try:
 prog[i] = list(map(eval,line.split(",")))
 except: print("Invalid instruction on line %d"%(i)); sys.exit(1)
 memory = defaultdict(int)
 ip = 0
 while 0<=ip<len(prog):
 line = prog[ip]
 a,b,c,d = map(partial(process,ip),line[:4])
 n=process(ip,line[4],special=True)
 numer = a*d
 denom = b*c
 if denom==0:sys.exit(1)
 div = gcd(numer,denom)
 numer//=div
 denom//=div
 if n>=0:
 memory[n]=numer
 memory[n+1]=denom
 elif n==-1:
 ip=numer-2
 elif n==-2:
 print(numer)
 ip+=1

External resources

Retrieved from "https://esolangs.org/w/index.php?title=Divrac&oldid=80748"