B1nary

==B1NARY==
B1nary is a language developed while UtilityHotbar was attempting to create a tally/prediction machine for use as an example introduction to programming. A combination with a desire to see what only two data values could make, a love of complex looking strings of 0s and 1s and a rudimentary attempt at "entanglement" (the state of the first program affects the state of every other program until the interpreter is restarted) led to several other features and the creation of B1nary.
==Introduction==
Full name: B1nary (stylised as B1NARY)
Type: Imperative programming
Paradigm: Procedural paradigm
Features: Simple flow control, loops, simple arithmetic
Inspiration (Esolang): Brainfuck, Malbolge and Binaryfuck
Inspiration (Concept): Encryption (Enigma), prediction, entanglement, binary sh*t (Phenomenon in movies where all code is treated as strings of 0s and 1s)
Creator: UtilityHotbar
==Concepts==
====Counter manipulation and the trash function====
B1nary has 2 counters, named CTR-0 and CTR-1, which hold a maximum value of 255 and wraps around. Each time 0 is inputted, counter 0 goes up. as such, Counter0 = 6 is represented as
 000000
Two "hidden" counters, PREF-0 and PREF-1, track every time 0 or 1 is directly inputted. These counters have no memory limit. Thus, after our previous program, this is the state of the interpreter:
 CTR-0: 6
 CTR-1: 0
 PREF-0: 6
 PREF-1: 0
 PREF: 0 (We will get to this later)
All other non-command inputs are treated as "trash". Trash is dealt with as thus: the interpreter looks in the command string for the last number (1/0) and assigns the trash to that counter. However, the preference counters are not updated since it is not a 0 or 1. For example, the program "0trash" generates this state:
 CTR-0: 6
 CTR-1: 0
 PREF-0: 1 <-One 0 in the program
 PREF-1: 0
 PREF: 0
These five variables, known as the "state", are stored between command blocks (/). The state can never be reset save an interpreter shutdown. This, the "o" in "Hello" and the "o" in "World" would be programmed differently depending on their place in the program. The "o" in "World" would also be different to the "o" in "world" or the second "o" in "Hello world" or the second "o" in "hello world".
====Preference generation====
A preference is generated with this sequence:
 if CTR-0 is larger than CTR-1:
 PREF is 1
 else if CTR-1 is larger than CTR-0:
 PREF is 1
 else:
 if PREF-0 is larger than PREF-1:
 PREF is 0
 else if PREF-1 is larger than PREF-0:
 PREF is 1
 else:
 PREF is LAST_INPUTTED_NUMBER of CURRENT_CODE_BLOCK
 if CURRENT_CODE_BLOCK has no 0 or 1:
 PREF is 0 
====Output====
Output is created with this formula:
 CTR-A - CTR-B + PREF-C - PREF-D + PREF (Where CTR-A >= CTR- B and CTR-C >= CTR-D)
The Unicode symbol with this code point is then outputted.
==Syntax and Commands==
Programs in B1nary are read left-to-right as a pointer travels along the program, interpreting each character in order.
There are 16 valid commands/characters in B1nary. All others are treated as "?" (trash) including WHITESPACE.
All B1nary commands are as follows (written in pseudo assembly style):
====Basic commands:====
 1 INC CTR-1 & PREF-1
 0 INC CTR-0 & PREF-0
 ? INC CTR-P [WHERE P IS PREV NUM]
 ! REV INC->DEC & JMP R->JMP L
 . OUT CHR ( (ROW-A - ROW-B) + (PREF-C- PREF-D) + PREF ) WHERE A >= B AND C >= D
*Note: (!) Reverses all operations (0 becomes CTR-0 - 1, * Jumps backward(see below)) until the program encounters a second (!)
====Loops:====
 [ STR LOOP
 ] END LOOP
*Note: All loops function like this: [ defines start point, when the pointer reaches ] it moves to start point. The start point, if undefined, is set to 0. Therefore 0] is a valid program, if not very useful.
====Conditions====
 ( STR COND
 ) END COND
 - DIV COND
 < LWR COND TYPE
 > LGR COND TYPE
 = EQL COND TYPE
 | NOT COND TYPE
 # RTN PREF-P IN COND
 : RTN CTR-P IN COND
 * TST COND IF FAIL JMP 1 R
*Note: A condition is created like this: (TYPE-VAL.A-VAL.B) VAL.A and VAL.B can be: :0 (CTR-0), :1 (CTR-1), #0 (PREF-0), #1 (PREF-1), and any binary number (1010)
Conditions have three types: >, <, =, and |. (| means not equal) A new condition immediately overrides the old condition. The condition is tested with * (* can be used at any point in the program after the creation of the condition), which executes the next character if true and skips the next character if false. Except when ! appears, which causes the * to skip backwards in case of failure. A simple multiplication method can be created like this:
4 X 6:
 (<-:1-110)[00001*] 
Explanation: The program adds 4 to CTR-0 until CTR-1 is no longer smaller than 6 i.e. CTR-1 = 6, at which point the * skips the next character ] , the command to send the loop back to the beginning.
==Examples:==
H: (RUN WHEN STATE IS 0/0/0/0/0)
 (<-:0-100100)[0*]/.
==Interpreters:==
Original Programmable Output Machine project.
Python 3.5.2 (With simple Tkinter interface):
 from tkinter import *
 import sys
 root = Tk()
 class b1nary:
 def __init__(self,master):
 self.rec = {"0":0,"1":0,"p0":0,"p1":0}
 self.pref = 0
 self.inp = 0 # All inputs
 self.cyc = 0 # All valid inputs
 self.jump = 0
 self.loop = [0,0]
 self.cond = []
 self.flag = False
 self.cgrab = False
 self.reverse = False
 self.testing = False
 self.history = []
 self.master = master
 master.title("Programmable Output Machine")
 mainframe = Frame(master)
 mainframe.grid(row=0)
 in_field = Entry(master)
 def get_in_field():
 data = in_field.get()
 in_field.delete(0,"end")
 self.process(data)
 def reset():
 self.rec = {"0":0,"1":0,"p0":0,"p1":0}
 self.pref = 0
 self.inp = 0 # All inputs
 self.cyc = 0 # All valid inputs
 self.jump = 0
 self.loop = [0,0]
 self.cond = []
 self.flag = False
 self.cgrab = False
 self.reverse = False
 def toggle_test():
 if self.testing == False:
 self.testing = True
 print ('Testing mode is now TRUE')
 else:
 self.testing = False
 print ('Testing mode is now FALSE')
 # UI Element definitions
 description = Label(master, text="Programmable Output Machine v.1")
 get_button = Button(master, text="Submit", command=get_in_field)
 tester = Button(master, text="Toggle testing mode", command=toggle_test)
 self.status = Label(master, text="Inputs: {} Cycles: {}".format(self.inp,self.cyc))
 self.output = Button(master, text="State", command=self.readout)
 self.clear = Button(master, text="Reset", command=reset)
 # UI Element placement
 description.grid(row=0,column=0,columnspan=3,sticky="w")
 in_field.grid(row=1,column=0,columnspan=2,sticky="w")
 get_button.grid(row=1,column=2,sticky="w")
 self.status.grid(row=3,column=2)
 self.output.grid(row=2,column=0,sticky="w")
 self.clear.grid(row=2,column=1,sticky="w")
 tester.grid(row=3,columnspan=2,sticky="w")
 self.cycle_update()
 def readout(self):
 print ('CTR-0: {}'.format(self.rec["0"]))
 print ('CTR-1: {}'.format(self.rec["1"]))
 print ('PREF-0: {}'.format(self.rec["p0"]))
 print ('PREF-1: {}'.format(self.rec["p1"]))
 print ('Pref: {}'.format(self.pref))
 print ('Cond: {}'.format(self.cond))
 def process(self,data):
 self.jump = 0
 self.loop = [0,0]
 self.flag = False
 self.cgrab = False
 if data == "":
 try:
 data = self.history[len(self.history)-1]
 except:
 data = ' '
 self.history.append(data)
 if self.testing == True:
 print ('Data: {}'.format(data))
 datalist = data.split('/')
 for chunk in datalist:
 chunk = list(chunk)
 i = 0
 while True:
 chunk[i] = self.crunch(chunk,chunk[i])
 if self.jump > 0:
 if self.testing == True:
 print ('jumped')
 if self.reverse == False:
 i += self.jump
 else:
 i -= self.jump + 2
 self.jump = 0
 if self.loop[1] > self.loop[0] and self.flag == True:
 if self.testing == True:
 print ('looping')
 self.readout()
 i = self.loop[0]
 self.flag = False
 continue
 i += 1
 if i > len(chunk)-1:
 break
 self.update(chunk)
 def findnum(self,thing):
 n = None
 for _ in thing:
 if _ in ["1","0"]:
 n = _
 return n
 def prtout(self):
 out = 0
 if self.rec["0"] > self.rec["1"]:
 out += self.rec["0"] - self.rec["1"]
 elif self.rec["0"] < self.rec["1"]:
 out += self.rec["1"] - self.rec["0"]
 if self.rec["p0"] > self.rec["p1"]:
 out += self.rec["p0"] - self.rec["p1"]
 elif self.rec["p0"] < self.rec["p1"]:
 out += self.rec["p1"] - self.rec["p0"]
 out += self.pref
 return chr(out)
 def verify(self):
 if self.rec["0"] > 255:
 self.rec["0"] -= 255
 if self.rec["1"] > 255:
 self.rec["1"] -= 255 
 def crunch(self,chunk,t):
 self.inp += 1
 self.cyc += 1
 if self.testing == True:
 print ("Unit: {}".format(t))
 if self.cgrab == True and t != ')':
 self.cond.append(t)
 return t
 #0
 if t == "0":
 if self.reverse == False:
 self.rec["0"] += 1
 self.rec["p0"] += 1
 else:
 self.rec["0"] -= 1
 self.rec["p0"] += 1
 #1
 elif t == "1":
 if self.reverse == False:
 self.rec["1"] += 1
 self.rec["p1"] += 1
 else:
 self.rec["1"] -= 1
 self.rec["p1"] += 1
 #Output
 elif t == '.':
 sys.stdout.writelines(self.prtout())
 #Loop commands
 elif t == '[':
 self.loop[0] = chunk.index(t)
 elif t == ']':
 self.loop[1] = chunk.index(t)
 self.flag = True
 elif t == "(":
 self.cond = []
 self.cgrab = True
 elif t == ')':
 self.cgrab = False
 elif t == '*':
 if len(self.cond) >= 5:
 if self.check(self.cond) == False:
 self.jump += 1
 elif t == '!':
 if self.reverse == False:
 self.reverse = True
 else:
 self.reverse = False
 else:
 if self.testing == True:
 print ('Referring back...')
 self.cyc -= 1
 getnm = self.findnum(chunk[:chunk.index(t)])
 if getnm != None:
 if self.reverse == False:
 self.rec[getnm] += 1
 else:
 self.rec[getnm] -= 1
 else:
 pass
 self.verify()
 return t
 def ref(self,thing):
 if thing == ':0':
 return self.rec["0"]
 elif thing == ':1':
 return self.rec["1"]
 elif thing == '#0':
 return self.rec["p0"]
 elif thing == '#1':
 return self.rec["p1"]
 else:
 return int(thing, 2)
 def check(self,cnd):
 cnd = .join(cnd)
 cnd = cnd.split('-')
 if self.testing == True:
 print (cnd)
 a = self.ref(cnd[1])
 b = self.ref(cnd[2])
 if cnd[0] == '>':
 if a > b:
 return True
 elif cnd[0] == '<':
 if a < b:
 return True
 elif cnd[0] == '=':
 if a == b:
 return True
 elif cnd[0] == '|':
 if a != b:
 return True
 return False
 def update(self,chunk):
 if self.rec["0"] > self.rec["1"]:
 larger = '0'
 elif self.rec["1"] > self.rec["0"]:
 larger = '1'
 else:
 if self.rec["p0"] > self.rec["p1"]:
 larger = '0'
 elif self.rec["p1"] > self.rec["p0"]:
 larger = '1'
 else:
 if self.testing == True:
 print ('Defaulting to last num...')
 if self.findnum(chunk) != None:
 larger = self.findnum(chunk)
 else:
 if self.testing == True:
 print ('Defaulting to 0...')
 larger = "0" 
 if larger == '0':
 self.pref = 0
 else:
 self.pref = 1
 def cycle_update(self):
 self.status.configure(text="Inputs: {} Cycles: {}".format(self.inp,self.cyc))
 self.master.after(1000, self.cycle_update)
 print ('Programmable Output Machine (Tk-based B1nary Interpreter) 1.0.0')
 print ('Made by UtilityHotbar in 2017')
 ai = b1nary(root)
Category:Languages
Category:Turing complete