Divrac
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.
{\displaystyle a}, {\displaystyle b}, {\displaystyle c}, {\displaystyle d}, and {\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 {\displaystyle m}th memory space where {\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 {\displaystyle {\frac {a}{b}}\div {\frac {c}{d}}} are calculated. If {\displaystyle n} is nonnegative, the numerator is stored in the {\displaystyle n}th memory slot, and the denominator in the {\displaystyle n+1}th.
If, however, {\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 {\displaystyle a}, {\displaystyle b}, {\displaystyle c}, or {\displaystyle d} represents a special value: {\displaystyle -1} represents the value of the instruction pointer, {\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 {\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 {\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
- Divrac.swift on GitHub