{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# NAND* programming languages specification\n",
"\n",
"_Version: 0.5_"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The NAND-CIRC, NAND-TM, and NAND-RAM programming languages were designed to accompany the upcoming book [\"Introduction to Theoretical Computer Science\"](http://introtcs.org). This is an appendix to this book, which is also available online as a Jupyter notebook in the [boazbk/tcscode](https://github.com/boazbk/tcscode) on Github. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The book is not a programming book, and readers can follow along without ever looking at the specifications of these programming languages. Still, for the sake of completeness, we provide these here."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We use the following main models of computation in this book:\n",
"\n",
"#### Computing __finite__ functions with __nonuniform__ algorithms:\n",
"\n",
"__Boolean Circuits__ and __NAND-CIRC__ straightline programs. We also use other variants that correspond to different gate sets. These models are presented in [Chapter 3: Defining Computatoin](https://introtcs.org/public/lec_03_computation.html).\n",
"\n",
"#### Computing __unbounded input length__ functions with __uniform__ algorithms:\n",
"\n",
"We have two main models, depending on the memory access. __Turing Machines__ have __sequential access__ to memory, and the programming language equivalent is __NAND-TM__. They are defined in [Chapter 6: Loops and infinity](https://introtcs.org/public/lec_06_loops.html). __RAM Machines__ have __random access__ (aka __indexed access__ or __indirect addressing__) to memory, and their programming language equivalent is __NAND-RAM__. They are defined in [Chapter 7: Equivalent models of computation](https://introtcs.org/public/lec_07_other_models.html). "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# The NAND-CIRC Programming Language"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A NAND-CIRC program is a sequence of lines. Every line in NAND-CIRC has the form \n",
"\n",
"` = NAND(,)`\n",
"\n",
"where `varid` (standing for _variable identifier_) is a sequence of letters, numbers, underscores, and brackets (`[`,`]`). Only variables of the form `X[]` and `Y[]` can contain brackets. Moreover, all other variables identifiers must begin with a lowercase letter. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Variables of the form `X[]` for a number `` are _input variables_, and variables of the form `Y[]` are _output variables_. \n",
"\n",
"For every valid NAND-CIRC program $P$, there must be some integers $n,m>0$ such that the input and output variables are `X[0]` ... `X[`$n-1$`]` for some $n>0$ and `Y[0]` ... `Y[`$m-1$`]` for some $m>0$ and all of those appear in the program. (For example, if a program contains the variable `X[3]` then it must also contain `X[2]`,`X[1]` and `X[0]`.\n",
"\n",
"An input variable can not appear on the lefthand side of the assignment operation `foo = NAND(bar,blah)`, and an output variable cannot appear on the righthand side of it."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"__Evaluating a NAND-CIRC program:__ If $P$ is a NAND-CIRC program with $n$ inputs and $m$ outputs, and $x\\in \\{0,1\\}^n$, then the _output of $P$ on input $x$_, denoted by $P(x)$, is defined as the string $y\\in \\{0,1\\}^m$ which is the result of the following process:\n",
"\n",
"1. We initialize the variables `X[0]` ... `X[`$n-1$`]` to $x_0,\\ldots,x_{n-1}$ and all other variables to $0$.\n",
"\n",
"2. We run the program line by line, where a line of the form `foo = NAND(bar,blah)` is evaluated by assigning to the variable `foo` the NAND of the values of the variables `bar` and `blah`\n",
"\n",
"3. At the end of the execution, output the values of the variables `Y[0]` ... `Y[`$m-1$`]`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### A Python implementation of NAND-CIRC evaluation:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def parseline(line, numargs = 0):\n",
" \"\"\"Parse a line of the form foo = 'OP( bar1, bar2, bar3)'\n",
" to ['foo','OP','bar1','bar2','bar2'].\n",
" If numargs > number of arguments in line then add empty strings to the list as needed.\"\"\"\n",
" i = line.find(\"=\")\n",
" j = line.find(\"(\")\n",
" k = line.find(\")\")\n",
" if i<0 or j<0 or k<0: raise Exception(f\"Line not formatted properly: {line}\")\n",
" args = [a.strip() for a in line[j+1:k].split(\",\")]\n",
" if len(args)\r\n",
"\r\n",
"\r\n",
"\r\n"
],
"text/plain": [
"