NOR
Description
NOR is an esoteric language created by Dylan Turner to replicate how a processor interprets data on a physical transistor level.
However, instead of using all the logic gates (AND, OR, NOT, NAND, XOR, etc.) it just uses NOR.
NOR is a universal logic gate and thus can be used to make the other gates, just in a much less convenient way.
Data Manipulation
NOR stores data in a strange way. Instead of a data pointer or variables, every time you call the NOR operation, it stores that operation as that line's value. This can be accessed by other NOR calls and outputs. You can access these stored values for lines by placing a "#" followed by a number, a ":", and a default value ("0" or "1"). When the interpreter reads this value, it does the default value if the number hasn't happened yet. It also as an array of input values for program input. At the beginning of each program, you place a line of a single number which is the size of that array. You access the values of this array by saying "IN" and then the index of that array.
Example to show Data Manipulation:
"100 NOR #300:0, 1" - stores the NOR of line 300 and 1 into line 100. Except that at the start, line 300 hasn't happened yet, so it does the default value of 0.
"200 OUT #100:1" - prints the value of that last NOR
"300 NOR 0, IN0" - stores the NOR of 0 and input[0]
"400 JMP 100" - Jumps back to 100, now with a value for line 300
Op Codes
NOR has 10 OpCodes: NOR, INP, OUT, OLN, JMP, REM, RND, OFF, MUX, and RST, and it works much like basic, with line numbers. Commas are optional, but they help to make the code look nice.
OpCode | Arguments | Meaning |
---|---|---|
NOR | LN NOR #1, #2 | At line LN, set the line value to the NOR operation of #1 and #2 |
INP | LN INP IN# | At line LN, input a 0 or 1 to the array of input values |
OUT | LN OUT # | At line LN, prints out the value of # |
OLN | LN OLN | At line LN, prints a new line |
JMP | LN JMP # | At line LN, jump to line # |
REM | LN REM blah blah blah | Works as a comment (NOTE: still needs a line number) |
RND | LN RND IN# | At line LN, sets input[#] to a random value between 0 and 1, or without argument sets the line to a random number. |
OFF | LN OFF | At Line LN, turn off the circuit (end the program) |
MUX | LN MUX #, Jump1, Jump2 | At line LN, if # is 0 go to line Jump1, and if # is 1 go to line Jump2. This is essentially a multiplexer. |
RST | LN RST | At line LN, reset all line values to nonexistance |
Obviously the key opcode is the NOR opcode. Not only does it work as a NOR, but it can be used to represent some conditionals.
LN NOR #, 0
Is the same as:
if (# == 0) line[LN]=1 else line[LN]=0
Where line is an infinite array that stores the value of each line number, and # is a value equal to 0, 1, line[some number], or input[some number].
For the multiplexer command:
LN MUX #, Jump1, Jump2
Is the same as
if(# == 0) Goto Jump1 else if(# == 1) Goto Jump2
Turing Completeness
NOR was previously proven to not be Turing-complete because it was possible to solve for the halting problem, but that was before the OFF and MUX commands were added which change this result. No longer is that known.
Example Programs
Here are a few example programs:
1bit Adder.nor
Adds two 1bit numbers together (w/ carry):
2 0 INP IN0 100 INP IN1 150 OLN 200 REM XOR logic here 300 NOR IN0, IN0 400 NOR IN1, IN1 500 NOR #300:0, #400:0 600 NOR IN0, IN1 650 NOR #600:0, #620:0 700 REM AND logic here 800 NOR IN0, IN0 900 NOR IN1, IN1 1000 NOR #800:0, #900:0 1100 REM Output carry then value 1200 OUT #1000:0 1300 OUT #650:0 1310 OLN 1325 JMP 1375 1350 OFF 1375 REM Input and repeat if 1 1400 INP IN0 1500 MUX IN0, 1350, 1600 1600 OLN 1700 JMP 0
Infinite Loop.nor
Infinitely prints 0 and 1 (alternating)
0 0 REM Infinite loop 50 NOR #50:0, 0 100 OUT #50:0 200 JMP 50
Truth Machine.nor
Prints 0 if input is 0.
Prints 1 infinitely if input is 1
1 0 REM Input a value 10 INP in1 20 REM Split the circuit into two paths: 30 REM if 0, goto OUT 0 (Line 70) 40 REM if 1, goto OUT 1 (Line 100 - the infinite loop) 50 MUX in1, 70, 100 60 REM Print 0 and then quit 70 OUT 0 80 OFF 90 REM Print 1 indefinitely 100 OUT 1 110 JMP 100
Hello, world.nor
You can't print ascii values directly, but you can print the binary equivalent
Also, you can print directly 1s and 0s with OUT, but I take the long way, changing individual line values and printing a string of changing values
Because of its tediousness, I only go to print "Hello" in ascii
1 0 REM store the H in line values 10 NOR 0, 1 20 NOR 0, 0 30 NOR 0, 1 40 NOR 0, 1 50 NOR 0, 0 60 NOR 0, 1 70 NOR 0, 1 80 NOR 0, 1 90 REM print it all out 100 OUT #10:0 110 OUT #20:0 120 OUT #30:0 130 OUT #40:0 140 OUT #50:0 150 OUT #60:0 160 OUT #70:0 170 OUT #80:0 175 OLN 180 REM Change to little e 190 NOR #30:0, 0 200 NOR #50:0, 0 210 NOR #60:0, 0 230 NOR #80:0, 0 240 REM Output with replaced values 250 OUT #10:0 260 OUT #20:0 270 OUT #190:0 280 OUT #40:0 290 OUT #200:0 300 OUT #210:0 310 OUT #70:0 320 OUT #230:0 325 OLN 330 REM Change to little l 340 NOR #200:0, 0 350 NOR #230:0, 0 360 REM Output little l twice 370 OUT #10:0 380 OUT #20:0 390 OUT #190:0 400 OUT #40:0 410 OUT #340:0 420 OUT #210:0 430 OUT #70:0 440 OUT #350:0 445 OLN 450 OUT #10:0 460 OUT #20:0 470 OUT #190:0 480 OUT #40:0 490 OUT #340:0 500 OUT #210:0 510 OUT #70:0 520 OUT #350:0 525 OLN 530 REM Change to little o 540 NOR #70:0, 0 550 NOR #350:0, 0 560 REM Output little o 570 OUT #10:0 580 OUT #20:0 590 OUT #190:0 600 OUT #40:0 610 OUT #340:0 620 OUT #210:0 630 OUT #540:0 640 OUT #550:0 645 OLN 650 REM Pause at end 660 INP in0
Decrement Test.nor
A program which counts down two line numbers.
It outputs 11, 10, 01, 00.
1 0 REM Decreases line values from 11 -> 10 -> 0 -> 00 10 NOR #90:0, #90:0 20 NOR #60:0, #60:0 30 NOR #10:1, #20:1 40 MUX #30:0, 50, 100 50 NOR #20:1, 0 60 NOR #50:0, #50:0 70 NOR #10:1, #10:1 80 NOR #70:1, #50:0 90 NOR #80:1, #80:1 95 JMP 10 24 OUT #10:1 25 OUT #20:1 26 OLN 100 INP IN0
Guess the Number (4-bit).nor
Input 4 bits of a number as your guess.
It says "L" in binary if your guess is less than the number, meaning you should guess higher.
It says "G" in binary if your guess is greater than the number, meaning you should guess lower.
It says "W" in binary if you guess the number and waits to see if you want to play again.
It says "D" in binary if you run out of guesses (you start with 3) and waits to see if you want to play again.
At the end it inputs a value: a 0 ends the program, a 1 has you play again.
4 99 REM Get 4 inputs and 4 random numbers 100 RND 101 RND 102 RND 103 RND 150 INP in0 200 INP in1 250 INP in2 300 INP in3 301 REM Store value of lives, starting with lives = 11 (3) 302 NOR #4101:0, #4101:0 303 NOR #4051:0, #4051:0 349 REM Check for in0 == 1 && #100 == 0 350 NOR in0, 0 400 NOR #100:0, #350:0 450 REM if #400 == 0, Move on, else Check for error 500 MUX #400:1, 650, 550 550 REM Number is greater than #100: print "G" in binary 599 OLN 600 OUT 0 601 OUT 1 602 OUT 0 603 OUT 0 604 OUT 0 605 OUT 1 606 OUT 1 607 OUT 1 608 OLN 610 JMP 4000 4000 REM Decrease lives and retake input 4050 NOR #303:1, 0 4051 NOR #4050:0, #4050:0 4052 NOR #302:1, #302:1 4100 NOR #4052:0, #4050:0 4101 NOR #4100:0, #4100:0 4102 REM Check if dead 4103 NOR #4100:1, #4050:1 4104 MUX #4103:0, 4150, 4200 4150 JMP 150 4200 REM Game over: print "D" in binary 4249 OLN 4250 OUT 0 4251 OUT 1 4252 OUT 0 4253 OUT 0 4254 OUT 0 4255 OUT 1 4256 OUT 0 4257 OUT 0 4300 OLN 4350 JMP 2560 650 REM Check for less than => in0 == 0 && #100 = 1 700 NOR #100:1, 0 750 NOR #700:0, in0 800 MUX #750:1, 950, 850 850 REM if input is less than #100: print "L" in binary 900 OLN 901 OUT 0 902 OUT 1 903 OUT 0 904 OUT 0 905 OUT 1 906 OUT 1 907 OUT 0 908 OUT 0 909 OLN 910 JMP 4000 950 REM they must be equal, so repeat with next part of the nibble 1000 REM Check for in0 == 1 && #100 == 0 1050 NOR in0, 0 1100 NOR #100:0, #350:0 1150 REM if #400 == 0, Move on, else Check for error 1200 MUX #400:1, 1250, 550 1250 REM Check for less than => in0 == 0 && #100 = 1 1300 NOR #100:1, 0 1350 NOR #700:0, in0 1400 MUX #750:1, 1450, 850 1450 REM Next part is equal, so move on 1500 REM Check for in0 == 1 && #100 == 0 1550 NOR in0, 0 1600 NOR #100:0, #350:0 1650 REM if #400 == 0, Move on, else Check for error 1700 MUX #400:1, 1750, 550 1750 REM Check for less than => in0 == 0 && #100 = 1 1800 NOR #100:1, 0 1850 NOR #700:0, in0 1900 MUX #750:1, 1950, 850 1950 REM Next part is equal, so move on 2000 REM Check for in0 == 1 && #100 == 0 2050 NOR in0, 0 2100 NOR #100:0, #350:0 2150 REM if #400 == 0, Move on, else Check for error 2200 MUX #400:1, 2250, 550 2250 REM Check for less than => in0 == 0 && #100 = 1 2300 NOR #100:1, 0 2350 NOR #700:0, in0 2400 MUX #750:1, 2450, 850 2450 REM Last part is equal, you win 2500 REM print W in binary 2550 OLN 2551 OUT 0 2552 OUT 1 2553 OUT 0 2554 OUT 1 2555 OUT 0 2556 OUT 1 2557 OUT 1 2558 OUT 1 2559 OLN 2560 INP in0 2600 MUX in0, 2650, 2700 2650 OFF 2700 RST 2750 JMP 99
Interpreter/Compiler
So far there's just one interpreter made in C# for the language: NOR Language Interpreter which can run all NOR programs.