Repository: source-academy/js-slang
Pull request #95 (2018-10-14 07:51:05)

Source Specification 2019

coveralls: ## Pull Request Test Coverage Report for [Build 175](https://coveralls.io/builds/19509555)

* **0** of **0**   changed or added relevant lines in **0** files are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage remained the same at **60.397%**

---



|  Totals | [![Coverage Status](https://coveralls.io/builds/19509555/badge)](https://coveralls.io/builds/19509555) |
| :-- | --: |
| Change from base [Build 153](https://coveralls.io/builds/19346361): |  0.0% |
| Covered Lines: | 787 |
| Relevant Lines: | 1232 |

---
##### 💛  - [Coveralls](https://coveralls.io)

thomastanck: This PR resolves #89. Would be great to get this doc PR merged (after resolving the merge conflicts with #130)
martin-henz: I've pushed the requested changes.

Note that I'm proposing 
;
as empty statement.

Asking everyone to comment, in the group.
thomastanck: After Daryl's thorough review it looks good to me.
martin-henz: Quite close to deciding to drop objects altogether, also for Sem 2. The MCE wouldn't change that much. After all, the authors made a point at wrapping things quite well into an abstract syntax, with accessor functions. I'm keen to get rid of objects, to get closer to SICP. We don't need to cover objects, and the objects that we do cover don't add much, conceptually.

So how about just ripping out objects, already now?
thomastanck: Agreed, as we discussed during the meeting we won't need objects during Sem 2. We can always change it back later if we change our minds, too.
thomastanck: https://github.com/source-academy/js-slang/pull/95/files#diff-6a9133abb057030b6d9882f0cb7492d1R120

This needs to be removed from source_4.tex
martin-henz: Just removed empty statements. All good?

Patch:
diff --git a/doc/source_1.tex b/doc/source_1.tex
index c7960526..4fd7b895 100644
--- a/doc/source_1.tex
+++ b/doc/source_1.tex
@@ -2,7 +2,7 @@
 
 \begin{document}
 	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-	\docheader{2018}{Source}{\S 1}
+	\docheader{2019}{Source}{\S 1}
 	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 \input source_intro.tex
@@ -10,6 +10,8 @@
 \input source_bnf.tex
 
 \begin{alignat*}{9}
+&& \textit{program}    &&\quad ::= &\quad && \textit{statement} \ \ldots
+                                                           && \textrm{statement sequence} \\[1mm]
 && \textit{statement}    &&\quad ::= &\quad && \textbf{\texttt{const}}\  \textit{name} \ 
                                            \textbf{\texttt{=}}\  \textit{expression} \ \textbf{\texttt{;}}
                                                            && \textrm{constant declaration} \\
@@ -20,12 +22,10 @@
                                                            && \textrm{return statement}\\
 &&                       && |   &\quad && \textit{if-statement} \quad
                                                            && \textrm{conditional statement}\\
-&&                       && |   &\quad &&  \textit{statement} \ 
-                                    \textit{statement}     && \textrm{statement sequence} \\
 &&                       && |   &\quad &&  \textit{block} 
                                                            && \textrm{block statement}\\
 &&                       && |   &\quad &&  \textit{expression} \ \textbf{\texttt{;}}
-                                                           && \textrm{expression statement} \\[1mm] 
+                                                           && \textrm{expression statement} \\[1mm]
 && \textit{parameters}   && ::= &\quad &&  \epsilon\ | \  \textit{name} \ 
                                                    (\ \textbf{\texttt{,}} \ \textit{name}\ )\ \ldots
                                                             && \textrm{function parameters}   \\[1mm]
@@ -37,7 +37,7 @@
                                           \ | \
                                           \textit{if-statement} \ )
                                                             && \textrm{conditional statement}   \\[1mm]
-&& \textit{block}        && ::= &      && \textbf{\texttt{\{}}\  \textit{statement}   \ \textbf{\texttt{\}}} \quad
+&& \textit{block}        && ::= &      && \textbf{\texttt{\{}}\  \textit{program}   \ \textbf{\texttt{\}}} \quad
                                                            && \textrm{block statement}\\[1mm]         
 && \textit{expression}   && ::= &\quad &&  \textit{number}   && \textrm{primitive number expression}\\
 &&                       && |   &\quad && \textbf{\texttt{true}}\ |\ \textbf{\texttt{false}}
@@ -58,7 +58,12 @@
                                                \textbf{\texttt{(}}\ \textit{parameters}\ \textbf{\texttt{)}}\
                                             )\    
                                             \texttt{\textbf{=>}}\ \textit{expression}
-                                                           && \textrm{function definition expression}\\
+                                                           && \textrm{function definition (expr. body)}\\
+&&                       && |   &\quad &&   (\ \textit{name}\ | \
+                                               \textbf{\texttt{(}}\ \textit{parameters}\ \textbf{\texttt{)}}\
+                                            )\    
+                                            \texttt{\textbf{=>}}\ \textit{block}
+                                                           && \textrm{function definition (block body)}\\
 &&                       && |   &\quad &&   \textit{expression} \ \textbf{\texttt{?}}\ 
                                             \textit{expression}
                                             \ \textbf{\texttt{:}}\
diff --git a/doc/source_2.tex b/doc/source_2.tex
index 0acaef29..f171ff06 100644
--- a/doc/source_2.tex
+++ b/doc/source_2.tex
@@ -2,7 +2,7 @@
 
 \begin{document}
 	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-	\docheader{2018}{Source}{\S 2}
+	\docheader{2019}{Source}{\S 2}
 	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 \input source_intro.tex
@@ -11,7 +11,7 @@
 
 Compared to Source \S 1, Source \S 2 has the following changes:
 \begin{itemize}
-\item \lstinline{[]}: Empty list.
+\item \lstinline{null}: primitive list expression (empty list).
 \item List library: Functions for creating, accessing and processing lists.
 \end{itemize}
 
@@ -20,6 +20,8 @@ Compared to Source \S 1, Source \S 2 has the following changes:
 \input source_bnf.tex
 
 \begin{alignat*}{9}
+&& \textit{program}    &&\quad ::= &\quad && \textit{statement} \ \ldots
+                                                           && \textrm{statement sequence} \\[1mm]
 && \textit{statement}    &&\quad ::= &\quad && \textbf{\texttt{const}}\  \textit{name} \ 
                                            \textbf{\texttt{=}}\  \textit{expression} \ \textbf{\texttt{;}}
                                                            && \textrm{constant declaration} \\
@@ -30,12 +32,10 @@ Compared to Source \S 1, Source \S 2 has the following changes:
                                                            && \textrm{return statement}\\
 &&                       && |   &\quad && \textit{if-statement} \quad
                                                            && \textrm{conditional statement}\\
-&&                       && |   &\quad &&  \textit{statement} \ 
-                                    \textit{statement}     && \textrm{statement sequence} \\
 &&                       && |   &\quad &&  \textit{block} 
                                                            && \textrm{block statement}\\
 &&                       && |   &\quad &&  \textit{expression} \ \textbf{\texttt{;}}
-                                                           && \textrm{expression statement} \\[1mm] 
+                                                           && \textrm{expression statement} \\[1mm]
 && \textit{parameters}   && ::= &\quad &&  \epsilon\ | \  \textit{name} \ 
                                                    (\ \textbf{\texttt{,}} \ \textit{name}\ )\ \ldots
                                                             && \textrm{function parameters}   \\[1mm]
@@ -47,11 +47,13 @@ Compared to Source \S 1, Source \S 2 has the following changes:
                                           \ | \
                                           \textit{if-statement} \ )
                                                             && \textrm{conditional statement}   \\[1mm]
-&& \textit{block}        && ::= &      && \textbf{\texttt{\{}}\  \textit{statement}   \ \textbf{\texttt{\}}} \quad
+&& \textit{block}        && ::= &      && \textbf{\texttt{\{}}\  \textit{program}   \ \textbf{\texttt{\}}} \quad
                                                            && \textrm{block statement}\\[1mm]         
 && \textit{expression}   && ::= &\quad &&  \textit{number}   && \textrm{primitive number expression}\\
 &&                       && |   &\quad && \textbf{\texttt{true}}\ |\ \textbf{\texttt{false}}
                                                            && \textrm{primitive boolean expression}\\
+&&                       && |   &\quad && \textbf{\texttt{null}}
+                                                           && \textrm{primitive list expression}\\
 &&                       && |   &\quad &&  \textit{string}   && \textrm{primitive string expression}\\
 &&                       && |   &\quad &&  \textit{name}   && \textrm{name expression}\\
 &&                       && |   &\quad &&  \textit{expression} \  \textit{binary-operator} \ 
@@ -68,14 +70,17 @@ Compared to Source \S 1, Source \S 2 has the following changes:
                                                \textbf{\texttt{(}}\ \textit{parameters}\ \textbf{\texttt{)}}\
                                             )\    
                                             \texttt{\textbf{=>}}\ \textit{expression}
-                                                           && \textrm{function definition expression}\\
+                                                           && \textrm{function definition (expr. body)}\\
+&&                       && |   &\quad &&   (\ \textit{name}\ | \
+                                               \textbf{\texttt{(}}\ \textit{parameters}\ \textbf{\texttt{)}}\
+                                            )\    
+                                            \texttt{\textbf{=>}}\ \textit{block}
+                                                           && \textrm{function definition (block body)}\\
 &&                       && |   &\quad &&   \textit{expression} \ \textbf{\texttt{?}}\ 
                                             \textit{expression}
                                             \ \textbf{\texttt{:}}\
                                             \textit{expression}\
                                                            && \textrm{conditional expression}\\
-&&                       && |   &\quad &&   \textbf{\texttt{[]}}
-                                                           && \textrm{primitive empty list expression}\\
 &&                       && |   &\quad &&  \textbf{\texttt{(}}\  \textit{expression} \ 
                                             \textbf{\texttt{)}} && \textrm{parenthesised expression}\\[1mm]
 && \textit{binary-operator}    \ 
diff --git a/doc/source_3.tex b/doc/source_3.tex
index c6f295e8..adf8b90d 100644
--- a/doc/source_3.tex
+++ b/doc/source_3.tex
@@ -2,7 +2,7 @@
 
 \begin{document}
 	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-	\docheader{2018}{Source}{\S 3}
+	\docheader{2019}{Source}{\S 3}
 	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 \input source_intro.tex
@@ -18,13 +18,18 @@ Compared to Source \S 2, Source \S 3 has the following changes:
 \item \textbf{\texttt{for}} loops
 \item \textbf{\texttt{break}} and \textbf{\texttt{continue}}
 \item array access expressions
+\item literal array expressions
+\item function
+\lstinline{is_array} is available, with its obvious meaning
 \end{itemize}
 
-\newpage
-
 \input source_bnf.tex
 
+\newpage
+
 \begin{alignat*}{9}
+&& \textit{program}    &&\quad ::= &\quad && \textit{statement} \ \ldots
+                                                           && \textrm{statement sequence} \\[1mm]
 && \textit{statement}    &&\quad ::= &\quad && \textbf{\texttt{const}}\  \textit{name} \ 
                                            \textbf{\texttt{=}}\  \textit{expression} \ \textbf{\texttt{;}}
                                                            && \textrm{constant declaration} \\
@@ -57,14 +62,10 @@ Compared to Source \S 2, Source \S 3 has the following changes:
                                                            && \textrm{break statement}\\
 &&                       && |   &\quad && \textbf{\texttt{continue}}\ \textbf{\texttt{;}}
                                                            && \textrm{continue statement}\\
-&&                       && |   &\quad &&  \textit{statement} \ 
-                                    \textit{statement}     && \textrm{statement sequence} \\
 &&                       && |   &\quad &&  \textit{block} 
                                                            && \textrm{block statement}\\
 &&                       && |   &\quad &&  \textit{expression} \ \textbf{\texttt{;}}
-                                                           && \textrm{expression statement} \\
-&&                       && |   &\quad &&  \epsilon
-                                                           && \textrm{empty statement} \\[1mm] 
+                                                           && \textrm{expression statement} \\[1mm]
 && \textit{parameters}   && ::= &\quad &&  \epsilon\ | \  \textit{name} \ 
                                                    (\ \textbf{\texttt{,}} \ \textit{name}\ )\ \ldots
                                                             && \textrm{function parameters}   \\[1mm]
@@ -76,7 +77,7 @@ Compared to Source \S 2, Source \S 3 has the following changes:
                                           \ | \
                                           \textit{if-statement} \ )
                                                             && \textrm{conditional statement}   \\[1mm]
-&& \textit{block}        && ::= &      && \textbf{\texttt{\{}}\  \textit{statement}   \ \textbf{\texttt{\}}} \quad
+&& \textit{block}        && ::= &      && \textbf{\texttt{\{}}\  \textit{program}   \ \textbf{\texttt{\}}} \quad
                                                            && \textrm{block statement}\\[1mm]         
 && \textit{let}          && ::= &\quad &&  \textbf{\texttt{let}}\  \textit{name} \ 
                                            \textbf{\texttt{=}}\  \textit{expression} 
@@ -87,6 +88,8 @@ Compared to Source \S 2, Source \S 3 has the following changes:
 && \textit{expression}   && ::= &\quad &&  \textit{number}   && \textrm{primitive number expression}\\
 &&                       && |   &\quad && \textbf{\texttt{true}}\ |\ \textbf{\texttt{false}}
                                                            && \textrm{primitive boolean expression}\\
+&&                       && |   &\quad && \textbf{\texttt{null}}
+                                                           && \textrm{primitive list expression}\\
 &&                       && |   &\quad &&  \textit{string}   && \textrm{primitive string expression}\\
 &&                       && |   &\quad &&  \textit{name}   && \textrm{name expression}\\
 &&                       && |   &\quad &&  \textit{expression} \  \textit{binary-operator} \ 
@@ -103,17 +106,24 @@ Compared to Source \S 2, Source \S 3 has the following changes:
                                                \textbf{\texttt{(}}\ \textit{parameters}\ \textbf{\texttt{)}}\
                                             )\    
                                             \texttt{\textbf{=>}}\ \textit{expression}
-                                                           && \textrm{function definition expression}\\
+                                                           && \textrm{function definition (expr. body)}\\
+&&                       && |   &\quad &&   (\ \textit{name}\ | \
+                                               \textbf{\texttt{(}}\ \textit{parameters}\ \textbf{\texttt{)}}\
+                                            )\    
+                                            \texttt{\textbf{=>}}\ \textit{block}
+                                                           && \textrm{function definition (block body)}\\
 &&                       && |   &\quad &&   \textit{expression} \ \textbf{\texttt{?}}\ 
                                             \textit{expression}
                                             \ \textbf{\texttt{:}}\
                                             \textit{expression}\
                                                            && \textrm{conditional expression}\\
-&&                       && |   &\quad &&   \textbf{\texttt{[]}}
-                                                           && \textrm{empty list/array expression}\\
 &&                       && |   &\quad && \textit{expression} \textbf{\texttt{[}}
                                           \textit{expression} \textbf{\texttt{]}}
                                                            && \textrm{array access} \\
+&&                       && |   &\quad &&   \textbf{\texttt{[}}\ 
+                                            \textit{expressions}\
+                                            \textbf{\texttt{]}}
+                                                           && \textrm{literal array expression}\\
 &&                       && |   &\quad &&  \textbf{\texttt{(}}\  \textit{expression} \ 
                                             \textbf{\texttt{)}} && \textrm{parenthesised expression}\\[1mm]
 && \textit{binary-operator}    \ 
@@ -146,6 +156,8 @@ Compared to Source \S 2, Source \S 3 has the following changes:
 
 \input source_array_support
 
+\input source_streams
+
 \input source_numbers
 
 \input source_strings
@@ -160,4 +172,8 @@ Compared to Source \S 2, Source \S 3 has the following changes:
 
 \input source_list_library
 
+\newpage
+
+\input source_stream_library
+
     \end{document}
diff --git a/doc/source_4.tex b/doc/source_4.tex
index 869d9198..5443d38d 100644
--- a/doc/source_4.tex
+++ b/doc/source_4.tex
@@ -2,7 +2,7 @@
 
 \begin{document}
 	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-	\docheader{2018}{Source}{\S 4}
+	\docheader{2019}{Source}{\S 4}
 	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 \input source_intro.tex
@@ -11,22 +11,17 @@
 
 Compared to Source \S 3, Source \S 4 has the following changes:
 \begin{itemize}
-\item literal object expressions
-\item dot abbreviation (see Section \textbf{Objects})
-\item Source \S 4 adds the functions \lstinline{parse},
-\lstinline{apply_in_underlying_javascript}, and
-\lstinline{JSON.stringify}.
-Furthermore, the functions \lstinline{is_boolean}, \lstinline{is_number},
-\lstinline{is_string}, \lstinline{is_function}, \lstinline{is_object} and
-\lstinline{is_array} are available, with their obvious meaning.
-Following JavaScript, \lstinline{is_object} returns \lstinline{true} when
-applied to arrays. For details, see 
+\item Source \S 4 adds the functions \lstinline{parse} and
+\lstinline{apply_in_underlying_javascript}. 
+For details, see 
 Section ``Interpreter Support'' below.
 \end{itemize}
 
 \input source_bnf.tex
 
 \begin{alignat*}{9}
+&& \textit{program}    &&\quad ::= &\quad && \textit{statement} \ \ldots
+                                                           && \textrm{statement sequence} \\[1mm]
 && \textit{statement}    &&\quad ::= &\quad && \textbf{\texttt{const}}\  \textit{name} \ 
                                            \textbf{\texttt{=}}\  \textit{expression} \ \textbf{\texttt{;}}
                                                            && \textrm{constant declaration} \\
@@ -37,7 +32,7 @@ Section ``Interpreter Support'' below.
 &&                       && |   &\quad && \textit{expression} \textbf{\texttt{[}}
                                           \textit{expression} \textbf{\texttt{]}}
                                            \textbf{\texttt{=}}\  \textit{expression} \ \textbf{\texttt{;}}
-                                                           && \textrm{array/object assignment} \\
+                                                           && \textrm{array assignment} \\
 &&                       && |   &\quad && \textbf{\texttt{function}}\  \textit{name} \ 
                                    \textbf{\texttt{(}}\  \textit{parameters} \ \textbf{\texttt{)}}\ \textit{block} \quad
                                                            && \textrm{function declaration}\\
@@ -59,12 +54,10 @@ Section ``Interpreter Support'' below.
                                                            && \textrm{break statement}\\
 &&                       && |   &\quad && \textbf{\texttt{continue}}\ \textbf{\texttt{;}}
                                                            && \textrm{continue statement}\\
-&&                       && |   &\quad &&  \textit{statement} \ 
-                                    \textit{statement}     && \textrm{statement sequence} \\
 &&                       && |   &\quad &&  \textit{block} 
                                                            && \textrm{block statement}\\
 &&                       && |   &\quad &&  \textit{expression} \ \textbf{\texttt{;}}
-                                                           && \textrm{expression statement} \\[1mm] 
+                                                           && \textrm{expression statement} \\[1mm]
 && \textit{parameters}   && ::= &\quad &&  \epsilon\ | \  \textit{name} \ 
                                                    (\ \textbf{\texttt{,}} \ \textit{name}\ )\ \ldots
                                                             && \textrm{function parameters}   \\[1mm]
@@ -76,7 +69,7 @@ Section ``Interpreter Support'' below.
                                           \ | \
                                           \textit{if-statement} \ )
                                                             && \textrm{conditional statement}   \\[1mm]
-&& \textit{block}        && ::= &      && \textbf{\texttt{\{}}\  \textit{statement}   \ \textbf{\texttt{\}}} \quad
+&& \textit{block}        && ::= &      && \textbf{\texttt{\{}}\  \textit{program}   \ \textbf{\texttt{\}}} \quad
                                                            && \textrm{block statement}\\[1mm]         
 && \textit{let}          && ::= &\quad &&  \textbf{\texttt{let}}\  \textit{name} \ 
                                            \textbf{\texttt{=}}\  \textit{expression} 
@@ -87,6 +80,8 @@ Section ``Interpreter Support'' below.
 && \textit{expression}   && ::= &\quad &&  \textit{number}   && \textrm{primitive number expression}\\
 &&                       && |   &\quad && \textbf{\texttt{true}}\ |\ \textbf{\texttt{false}}
                                                            && \textrm{primitive boolean expression}\\
+&&                       && |   &\quad && \textbf{\texttt{null}}
+                                                           && \textrm{primitive list expression}\\
 &&                       && |   &\quad &&  \textit{string}   && \textrm{primitive string expression}\\
 &&                       && |   &\quad &&  \textit{name}   && \textrm{name expression}\\
 &&                       && |   &\quad &&  \textit{expression} \  \textit{binary-operator} \ 
@@ -103,21 +98,24 @@ Section ``Interpreter Support'' below.
                                                \textbf{\texttt{(}}\ \textit{parameters}\ \textbf{\texttt{)}}\
                                             )\    
                                             \texttt{\textbf{=>}}\ \textit{expression}
-                                                           && \textrm{function definition expression}\\
+                                                           && \textrm{function definition (expr. body)}\\
+&&                       && |   &\quad &&   (\ \textit{name}\ | \
+                                               \textbf{\texttt{(}}\ \textit{parameters}\ \textbf{\texttt{)}}\
+                                            )\    
+                                            \texttt{\textbf{=>}}\ \textit{block}
+                                                           && \textrm{function definition (block body)}\\
 &&                       && |   &\quad &&   \textit{expression} \ \textbf{\texttt{?}}\ 
                                             \textit{expression}
                                             \ \textbf{\texttt{:}}\
                                             \textit{expression}\
                                                            && \textrm{conditional expression}\\
-&&                       && |   &\quad &&   \textbf{\texttt{[]}}
-                                                           && \textrm{empty list/array expression}\\
 &&                       && |   &\quad && \textit{expression} \textbf{\texttt{[}}
                                           \textit{expression} \textbf{\texttt{]}}
-                                                           && \textrm{array/object access} \\
-&&                       && |   &\quad &&   \textbf{\texttt{\{}}\ 
-                                            \textit{properties}\
-                                            \textbf{\texttt{\}}}
-                                                           && \textrm{literal object expression}\\
+                                                           && \textrm{array access} \\
+&&                       && |   &\quad &&   \textbf{\texttt{[}}\ 
+                                            \textit{expressions}\
+                                            \textbf{\texttt{]}}
+                                                           && \textrm{literal array expression}\\
 &&                       && |   &\quad &&  \textbf{\texttt{(}}\  \textit{expression} \ 
                                             \textbf{\texttt{)}} && \textrm{parenthesised expression}\\[1mm]
 && \textit{binary-operator}    \ 
@@ -131,15 +129,7 @@ Section ``Interpreter Support'' below.
                                                                \ \textbf{\texttt{,}} \
                                                                  \textit{expression} \ 
                                                                       )\ \ldots
-                                                            && \textrm{argument expressions} \\[1mm]
-&& \textit{properties}  && ::= &\quad && \epsilon\ | \ \textit{property}\ (
-                                                               \ \textbf{\texttt{,}} \
-                                                                 \textit{property} \ 
-                                                                      )\ \ldots
-                                                            && \textrm{object properties} \\[1mm]
-&& \textit{property}  && ::= &\quad && (\ \textit{string}\ |\ \textit{name}\ ) 
-                                        \ \textbf{\texttt{:}} \ \textit{expression} 
-                                                            && \textrm{object property}
+                                                            && \textrm{argument expressions}
 \end{alignat*}
 
 \newpage
@@ -158,14 +148,14 @@ Section ``Interpreter Support'' below.
 
 \input source_array_support
 
+\input source_streams
+
 \input source_numbers
 
 \input source_strings
 
 \input source_arrays
 
-\input source_objects
-
 \input source_typing
 
 \input source_interpreter
@@ -176,4 +166,8 @@ Section ``Interpreter Support'' below.
 
 \input source_list_library
 
+\newpage
+
+\input source_stream_library
+
     \end{document}
diff --git a/doc/source_array_support.tex b/doc/source_array_support.tex
index 36666d32..abad073f 100644
--- a/doc/source_array_support.tex
+++ b/doc/source_array_support.tex
@@ -1,11 +1,13 @@
 \subsection*{Array Support}
 
-The following array processing function is supported:
+The following array processing functions are supported:
 
 \begin{itemize}
-\item \lstinline{array_length(x)}: \textit{builtin}, returns
+\item \lstinline{array_length(x)}: \textit{built-in}, returns
   the current length of array \lstinline{x}, which is 1 plus the
 highest index \lstinline{i} that has been used so far in an array assignment on \lstinline{x}.
+\item \lstinline{is_array(x)}: \textit{built-in}, returns
+  returns \texttt{true} if \texttt{x} is an array, and \texttt{false} if it is not.
 \end{itemize}
 
   
diff --git a/doc/source_arrays.tex b/doc/source_arrays.tex
index 79621204..9519fec6 100644
--- a/doc/source_arrays.tex
+++ b/doc/source_arrays.tex
@@ -2,7 +2,8 @@
 
 Arrays in Source are created using the empty array syntax:
 \begin{lstlisting}
-let my_array = [];
+let my_array_1 = [];
+let my_array_2 = [42, 71, 13];
 \end{lstlisting}
 Arrays in Source are limited to integers as keys.
 In statements like
diff --git a/doc/source_bnf.tex b/doc/source_bnf.tex
index 82573659..4d496e1c 100644
--- a/doc/source_bnf.tex
+++ b/doc/source_bnf.tex
@@ -1,6 +1,6 @@
 \section*{Programs}
 
-A Source program is a \emph{statement}, defined using Backus-Naur Form\footnote{
+A Source program is a \emph{program}, defined using Backus-Naur Form\footnote{
 We adopt Henry Ledgard's BNF variant that he described in
 \emph{A human engineered variant of BNF}, ACM SIGPLAN Notices, Volume 15 Issue 10,
 October 1980, Pages 57-62. In our grammars, we use \textbf{\texttt{bold}} font for keywords,
diff --git a/doc/source_interpreter.tex b/doc/source_interpreter.tex
index 19e9be2d..2f1308ee 100644
--- a/doc/source_interpreter.tex
+++ b/doc/source_interpreter.tex
@@ -1,24 +1,9 @@
 \section*{Interpreter Support}
 
 \begin{itemize}
-\item \lstinline{is_number(x)}: \textit{builtin}, returns \lstinline{true} if \lstinline{x} is a number, and 
-\lstinline{false} otherwise.
-\item \lstinline{is_boolean(x)}: \textit{builtin}, returns \lstinline{true} if \lstinline{x} is \lstinline{true} or \lstinline{false}, and \lstinline{false} otherwise.
-\item \lstinline{is_string(x)}: \textit{builtin}, returns \lstinline{true} if \lstinline{x} is a
-string, and \lstinline{false} otherwise.
-\item \lstinline{is_function(x)}: \textit{builtin}, returns \lstinline{true} if \lstinline{x} is a
-function, and \lstinline{false} otherwise.
-\item \lstinline{is_object(x)}: \textit{builtin}, returns \lstinline{true} if \lstinline{x} is an
-object, and \lstinline{false} otherwise. Following JavaScript, arrays are considered
-objects.
-\item \lstinline{is_array(x)}: \textit{builtin}, returns \lstinline{true} if \lstinline{x} is an
-array, and \lstinline{false} otherwise. The empty array \lstinline{[]}, also known
-as the empty list, is an array.
-\item \lstinline{parse(x)}: \textit{builtin}, returns the parse tree that results from parsing
+\item \lstinline{parse(x)}: \textit{built-in}, returns the parse tree that results from parsing
 the string \lstinline{x} as a Source program.
-\item \lstinline{JSON.stringify(x)}: \textit{builtin}, returns a string that represents the given JSON object
-\lstinline{x}.
-\item \lstinline{apply_in_underlying_javascript(f, xs)}: \textit{builtin}, calls the function \lstinline{f}
+\item \lstinline{apply_in_underlying_javascript(f, xs)}: \textit{built-in}, calls the function \lstinline{f}
 with arguments \lstinline{xs}. For example:
 \begin{lstlisting}
 function times(x, y) {
diff --git a/doc/source_intro.tex b/doc/source_intro.tex
index ac8f9577..fce0f85f 100644
--- a/doc/source_intro.tex
+++ b/doc/source_intro.tex
@@ -3,7 +3,7 @@ of Computer Programs}, JavaScript Adaptation.
 You have never heard of Source? No worries! It was invented
 just for the purpose of the book. Source is a sublanguage of 
 \href{http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf}{
-ECMAScript 2016 ($7^{\textrm{th}}$ Edition)} 
+ECMAScript 2018 ($9^{\textrm{th}}$ Edition)} 
 and defined in the documents titled ``Source \S $x$'', where $x$ refers to the
 respective textbook chapter. For example, Source \S 3 is suitable for textbook Chapter 3
 and the preceeding chapters.
diff --git a/doc/source_list_library.tex b/doc/source_list_library.tex
index e952c0bf..8d7baff8 100644
--- a/doc/source_list_library.tex
+++ b/doc/source_list_library.tex
@@ -1,40 +1,41 @@
 \section*{Appendix: List library}
 
-Those list library functions that are not builtins are pre-declared as follows:
+Those list library functions that are not built-ins are pre-declared as follows:
 
 \begin{lstlisting}
-// is_list recurses down the list and checks that it ends with the empty list []
+// is_list recurses down the list and checks that it ends with the empty list null
 
 function is_list(xs) {
-    return is_empty_list(xs) || (is_pair(xs) && is_list(tail(xs)));
+    return is_null(xs) || (is_pair(xs) && is_list(tail(xs)));
 }
 
 // equal computes the structural equality 
 // over its arguments
 
-function equal(item1, item2){
-    return (is_pair(item1) && is_pair(item2))
-        || (is_empty_list(item1) && is_empty_list(item2))
-        || item1 === item2;
+function equal(x, y){
+    return (is_pair(x) && is_pair(y)) 
+        ? (equal(head(x), head(y)) &&
+           equal(tail(x), tail(y)))
+        : x === y;
 }
 
 // returns the length of a given argument list
 // assumes that the argument is a list
 
 function length(xs) {
-    return is_empty_list(xs) 
+    return is_null(xs) 
 	? 0
-        : length(tail(xs));
+        : 1 + length(tail(xs));
 }
 
 // map applies first arg f, assumed to be a unary function,
 // to the elements of the second argument, assumed to be a list.
 // f is applied element-by-element: 
-// map(f, [1, [2, []]]) results in [f(1), [f(2), []]]
+// map(f, list(1, 2)) results in list(f(1), f(2))
 
 function map(f, xs) {
-    return (is_empty_list(xs)) 
-        ? []
+    return is_null(xs)
+        ? null
         : pair(f(head(xs)), map(f, tail(xs)));
 }
 
@@ -45,26 +46,26 @@ function map(f, xs) {
 
 function build_list(n, fun){
     function build(i, fun, already_built) {
-	return i < 0
-	    ? already_built
-	    : build(i - 1, fun, pair(fun(i),
-		  		     already_built));
+        return i < 0
+            ? already_built
+            : build(i - 1, fun, pair(fun(i),
+                already_built));
     }
-    return build(n - 1, fun, []);
+    return build(n - 1, fun, null);
 }
 
 // for_each applies first arg fun, assumed to be a unary function,
 // to the elements of the second argument, assumed to be a list.
 // fun is applied element-by-element:
-// for_each(fun, [1, [2, []]]) results in the calls fun(1) and fun(2).
+// for_each(fun, list(1, 2)) results in the calls fun(1) and fun(2).
 // for_each returns true.
 
 function for_each(fun, xs) {
-    if (is_empty_list(xs)) {
-	return true;
+    if (is_null(xs)) {
+        return true;
     } else {
         fun(head(xs));
-	return for_each(fun, tail(xs));
+        return for_each(fun, tail(xs));
     }
 }
 
@@ -76,11 +77,11 @@ function to_string(x) {
 
 // list_to_string returns a string that represents the argument list.
 // It applies itself recursively on the elements of the given list.
-// When it encounters a non-list, it applies toString to it.
+// When it encounters a non-list, it applies to_string to it.
 
 function list_to_string(xs) {
-    return is_empty_list(xs)
-        ? "[]"
+    return is_null(xs)
+        ? "null"
         : is_pair(xs)
             ? "[" + list_to_string(head(xs)) + ","+
                     list_to_string(tail(xs))      + "]"
@@ -91,37 +92,37 @@ function list_to_string(xs) {
 
 function reverse(xs) {
     function rev(original, reversed) {
-	return is_empty_list(original)
-	    ? reversed
-	    : rev(tail(original), 
-	          pair(head(original), reversed));
+        return is_null(original)
+            ? reversed
+            : rev(tail(original), 
+                  pair(head(original), reversed));
     }
-    return rev(xs, []);
+    return rev(xs, null);
 }
 
 // append first argument, assumed to be a list, to the second argument.
-// In the result, the [] at the end of the first argument list
+// In the result null at the end of the first argument list
 // is replaced by the second argument, regardless what the second
 // argument consists of.
 
 function append(xs, ys) {
-    return is_empty_list(xs)
-	? ys
+    return is_null(xs)
+        ? ys
         : pair(head(xs),
-	       append(tail(xs), ys));
+            append(tail(xs), ys));
 } 
 
 // member looks for a given first-argument element in the 
 // second argument, assumed to be a list. It returns the first 
-// postfix sublist that starts with the given element. It returns [] if the 
+// postfix sublist that starts with the given element. It returns null if the 
 // element does not occur in the list
 
 function member(v, xs){
-    return is_empty_list(xs)
-	? []
+    return is_null(xs)
+        ? null
         : (v === head(xs))
-	    ? xs
-	    : member(v, tail(xs));
+            ? xs
+            : member(v, tail(xs));
 }
 
 // removes the first occurrence of a given first-argument element
@@ -129,24 +130,24 @@ function member(v, xs){
 // list if there is no occurrence.
 
 function remove(v, xs){
-    return is_empty_list(xs)
-	? []
+    return is_null(xs)
+        ? null
         : v === head(xs)
-	    ? tail(xs)
-	    : pair(head(xs), 
-		   remove(v, tail(xs)));
+            ? tail(xs)
+            : pair(head(xs), 
+                   remove(v, tail(xs)));
 }
 
 // Similar to remove, but removes all instances of v
 // instead of just the first
 
 function remove_all(v, xs) {
-    return is_empty_list(xs)
-	? []
+    return is_null(xs)
+        ? null
         : v === head(xs)
-	    ? remove_all(v, tail(xs))
-	    : pair(head(xs), 
-	  	   remove_all(v, tail(xs)));
+            ? remove_all(v, tail(xs))
+            : pair(head(xs), 
+                     remove_all(v, tail(xs)));
 }
 
 // filter returns the sublist of elements of the second argument
@@ -154,12 +155,12 @@ function remove_all(v, xs) {
 // returns true.
 
 function filter(pred, xs){
-    return is_empty_list(xs)
-	? xs
+    return is_null(xs)
+        ? xs
         : pred(head(xs))
-	    ? pair(head(xs),
-		   filter(pred, tail(xs)))
-	    : filter(pred, tail(xs));
+            ? pair(head(xs),
+                   filter(pred, tail(xs)))
+            : filter(pred, tail(xs));
 }
 
 // enumerates numbers starting from start, assumed to be a number,
@@ -168,9 +169,9 @@ function filter(pred, xs){
 
 function enum_list(start, end) {
     return start > end
-	? []
+        ? null
         : pair(start,
-	       enum_list(start + 1, end));
+               enum_list(start + 1, end));
 }
 
 // Returns the item in xs (assumed to be a list) at index n,
@@ -179,7 +180,7 @@ function enum_list(start, end) {
 
 function list_ref(xs, n) {
     return n === 0
-	? head(xs)
+        ? head(xs)
         : list_ref(tail(xs), n - 1);
 }
 
@@ -192,11 +193,11 @@ function list_ref(xs, n) {
 // accumulate(op, zero, list(1, 2, 3)) results in
 // op(1, op(2, op(3, zero)))
 
-function accumulate(op, initial, sequence) {
-    return is_empty_list(sequence)
+function accumulate(f, initial, xs) {
+    return is_null(xs)
         ? initial
-        : op(head(sequence),
-             accumulate(op, initial, tail(sequence)));
+        : f(head(xs),
+             accumulate(f, initial, tail(xs)));
 }
 \end{lstlisting}
 
diff --git a/doc/source_lists.tex b/doc/source_lists.tex
index 189d1712..660ff9d6 100644
--- a/doc/source_lists.tex
+++ b/doc/source_lists.tex
@@ -3,29 +3,31 @@
 The following list processing functions are supported:
 
 \begin{itemize}
-\item \lstinline{pair(x, y)}: \textit{builtin}, makes a pair from \lstinline{x} and \lstinline{y}.
-\item \lstinline{is_pair(x)}: \textit{builtin}, returns \lstinline{true} if \lstinline{x} is a
+\item \lstinline{pair(x, y)}: \textit{built-in}, makes a pair from \lstinline{x} and \lstinline{y}.
+\item \lstinline{is_pair(x)}: \textit{built-in}, returns \lstinline{true} if \lstinline{x} is a
   pair and \lstinline{false} otherwise.
-\item \lstinline{head(x)}: \textit{builtin}, returns the head (first component) of the pair \lstinline{x}.
-\item \lstinline{tail(x)}: \textit{builtin}, returns the tail (second component) of the
+\item \lstinline{head(x)}: \textit{built-in}, returns the head (first component) of the pair \lstinline{x}.
+\item \lstinline{tail(x)}: \textit{built-in}, returns the tail (second component) of the
   pair \lstinline{x}.
-\item \lstinline{is_empty_list(xs)}: \textit{builtin}, returns \lstinline{true} if \lstinline{xs} is the
-  empty list, and \lstinline{false} otherwise.
+\item \lstinline{is_null(xs)}: \textit{built-in}, returns \lstinline{true} if \lstinline{xs} is the
+  empty list \lstinline{null}, and \lstinline{false} otherwise.
 \item \lstinline{is_list(x)}: Returns \lstinline{true} if
   \lstinline{x} is a list as defined in the lectures, and
   \lstinline{false} otherwise. Iterative process; 
 time: $O(n)$, space: $O(1)$, where $n$ is the length of the 
 chain of \lstinline{tail} operations that can be applied to \lstinline{x}.
-\item \lstinline{list(x1, x2,..., xn)}: \textit{builtin}, returns a list with $n$ elements. The
+\item \lstinline{list(x1, x2,..., xn)}: \textit{built-in}, returns a list with $n$ elements. The
 first element is \lstinline{x1}, the second \lstinline{x2}, etc. Iterative
 process; time: $O(n)$, space: $O(n)$, since the constructed list data structure
 consists of $n$ pairs, each of which takes up a constant amount of space.
-\item \lstinline{draw_list(x)}: \textit{builtin}, visualizes \lstinline{x} in a separate drawing
+\item \lstinline{draw_list(x)}: \textit{built-in}, visualizes \lstinline{x} in a separate drawing
   area in the Source Academy using a box-and-pointer diagram; time, space:
   $O(n)$, where $n$ is the number of pairs in \lstinline{x}.
 \item \lstinline{equal(x1, x2)}: Returns \lstinline{true} if both
-have the same structure and the same numbers, boolean values, functions or empty list
-at corresponding leaf positions, and \lstinline{false} otherwise; time, space:
+  have the same structure with respect to \lstinline{pair},
+  and the same numbers, boolean values, functions or empty list
+  at corresponding leave positions (places that are not themselves pairs),
+  and \lstinline{false} otherwise; time, space:
   $O(n)$, where $n$ is the number of pairs in \lstinline{x}.
 \item \lstinline{length(xs)}: Returns the length of the list
   \lstinline{xs}. 
diff --git a/doc/source_loops.tex b/doc/source_loops.tex
index 2e072dad..680a7140 100644
--- a/doc/source_loops.tex
+++ b/doc/source_loops.tex
@@ -67,7 +67,7 @@ stands for
     for (^$\textrm{\textit{name}}$^ = ^$\textrm{\textit{name}}$^; ^$\textrm{\textit{expression}}_2$^; ^$\textrm{\textit{assignment}}$^) {
          const _copy_of_name = ^$\textrm{\textit{name}}$^;
          {
-             const ^$\textrm{\textit{name}}$^ = _copy_of_x;
+             const ^$\textrm{\textit{name}}$^ = _copy_of_name;
              ^$\textrm{\textit{block}}$^
          }
     }
diff --git a/doc/source_names.tex b/doc/source_names.tex
index 9308a2c3..98474f84 100644
--- a/doc/source_names.tex
+++ b/doc/source_names.tex
@@ -3,7 +3,7 @@
 Names\footnote{
 In
 \href{http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf}{
-ECMAScript 2016 ($7^{\textrm{th}}$ Edition)},
+ECMAScript 2018 ($9^{\textrm{th}}$ Edition)},
 these names are called \emph{identifiers}.
 } start with \verb@_@, \verb@$@ or a
 letter\footnote{
@@ -20,25 +20,25 @@ $\textbf{\texttt{break}}$, $\textbf{\texttt{case}}$, $\textbf{\texttt{catch}}$,
 } such as keywords are not allowed as names.
 
 Valid names are \verb@x@, \verb@_45@, \verb@$$@ and $\mathtt{\pi}$,
-but always keep in mind that programming is communicating, and therefore the familiarity of the
+but always keep in mind that programming is communicating and that the familiarity of the
 audience with the characters used in names is an important aspect of program readability.
 
 In addition to names that
 are declared using \texttt{\textbf{const}}, \texttt{\textbf{function}},
 $\texttt{\textbf{=>}}$ (and \texttt{\textbf{let}} in Source \S3 and 4), the following
-names refer to builtin functions and constants:
+names refer to built-in functions and constants:
 \begin{itemize}
 \item \lstinline{math_}$\textit{name}$,
 where $\textit{name}$ is any name specified in the
 JavaScript
 \texttt{Math} library, see\\
-\href{https://www.ecma-international.org/ecma-262/8.0/index.html#sec-math-object}{\color{DarkBlue}ECMAScript Specification, Section 20.2}. Examples:
+\href{https://www.ecma-international.org/ecma-262/9.0/index.html#sec-math-object}{\color{DarkBlue}ECMAScript Specification, Section 20.2}. Examples:
 \begin{itemize}
 \item \verb#math_PI#: Refers to the mathematical constant $\pi$,
 \item \verb#math_sqrt#\texttt{(n)}: Returns the square root of the \emph{number} \texttt{n}.
 \end{itemize}
 \item \texttt{runtime()}: Returns number of milliseconds elapsed since January 1, 1970 00:00:00 UTC
-\item \texttt{display(a)}: Displays \emph{any} value \texttt{a} in the console; returns \texttt{undefined}.
+\item \texttt{display(a)}: Displays \emph{any} value \texttt{a} in the console; returns the argument \texttt{a}.
 \item \texttt{error(a)}: Displays \emph{any} value \texttt{a} in the console with error flag. The evaluation
   of any call of \texttt{error} aborts the running program immediately.
 \item \texttt{prompt(s)}: Pops up a window that displays the \emph{string} \texttt{s}, provides
@@ -47,7 +47,11 @@ suspends execution of the program until the ``OK'' button is pressed, at which p
 returns the entered text as a string.
 \item \verb#parse_int#\texttt{(s, i)}:
 interprets the \emph{string} \texttt{s} as an integer, using the positive integer \texttt{i} as radix, and returns the respective value,
-see \href{https://www.ecma-international.org/ecma-262/8.0/index.html#sec-parseint-string-radix}{\color{DarkBlue}ECMAScript Specification, Section 18.2.5}.
+see \href{https://www.ecma-international.org/ecma-262/9.0/index.html#sec-parseint-string-radix}{\color{DarkBlue}ECMAScript Specification, Section 18.2.5}.
 \item \verb#undefined#, \verb#NaN#, \verb#Infinity#: Refer to JavaScript's undefined,
 NaN (``Not a Number'') and Infinity values, respectively.
+\item \verb#is_boolean#\texttt{(x)}, \verb#is_number#\texttt{(x)}, \verb#is_string#\texttt{(x)}, \verb#is_function#\texttt{(x)}:
+        return \texttt{true} if the type of \texttt{x} matches the function name and \texttt{false} if it does not. Following
+  JavaScript, we specify that \verb#is_number# returns \texttt{true} for \texttt{NaN} and \texttt{Infinity}.
 \end{itemize}
+All Source built-in functions can be assumed to run in $O(1)$ time.
diff --git a/doc/source_object_support.tex b/doc/source_object_support.tex
new file mode 100644
index 00000000..3de5b582
--- /dev/null
+++ b/doc/source_object_support.tex
@@ -0,0 +1,12 @@
+\subsection*{Object Support}
+
+The following object-processing function is supported:
+
+\begin{itemize}
+\item \lstinline{is_object(x)}: \textit{built-in}, returns
+  returns \texttt{true} if \texttt{x} is an object, and \texttt{false} if it is not.
+\end{itemize}
+
+  
+
+
diff --git a/doc/source_objects.tex b/doc/source_objects.tex
index 11935d31..792c4ed3 100644
--- a/doc/source_objects.tex
+++ b/doc/source_objects.tex
@@ -4,7 +4,7 @@
 
 Literal objects can be created using literal object expressions:
 \begin{lstlisting}
-var my_obj = { "key 1": 1,
+let my_obj = { "key 1": 1,
                "key 2": 2 };
 \end{lstlisting}
 
@@ -12,14 +12,14 @@ As keys, only strings are allowed in Source.
 If the string (without quotation marks) looks like a \textit{name}, the
 quotation marks around property keys can be omitted, for example:
 \begin{lstlisting}
-var my_motorcycle = { cc: 399,
+let the_motorcycle = { cc: 399,
                       number_of_cylinders: 4 };
 \end{lstlisting}
 
 The syntax
 \begin{lstlisting}
 my_obj["key 1"];
-my_motorcycle["cc"] = 1249;
+the_motorcycle["cc"] = 896;
 \end{lstlisting}
 allows for object access and assignment. Here, the quotation marks are not optional,
 even when the string (without quotation marks) looks like a \textit{name}.
@@ -30,11 +30,12 @@ In $\textit{statement}$ and $\textit{expression}$, the syntax
 \[
 \textit{expression} \ \texttt{.}\ \textit{id}
 \]
-is an abbreviation for
+can be used as an abbreviation for
 \[
 \textit{expression} \ \textbf{\texttt{[}}\  \texttt{\bf "} \textit{id}
 \texttt{\bf "}\ \textbf{\texttt{]}}
 \]
+if the string $\textit{id}$ looks like a \textit{name}.
 For example
 \begin{lstlisting}
 my_motorcyle . number_of_cylinders;
diff --git a/doc/source_pair_mutators.tex b/doc/source_pair_mutators.tex
index 09c52abc..d3f0b006 100644
--- a/doc/source_pair_mutators.tex
+++ b/doc/source_pair_mutators.tex
@@ -3,9 +3,9 @@
 The following pair mutator functions are supported:
 
 \begin{itemize}
-\item \lstinline{set_head(p, x)}: \textit{builtin}, changes the pair \lstinline{p} such that its head is \lstinline{x}.
+\item \lstinline{set_head(p, x)}: \textit{built-in}, changes the pair \lstinline{p} such that its head is \lstinline{x}.
 Returns \lstinline{undefined}.
-\item \lstinline{set_tail(p, x)}: \textit{builtin}, changes the pair \lstinline{p} such that its tail is \lstinline{x}.
+\item \lstinline{set_tail(p, x)}: \textit{built-in}, changes the pair \lstinline{p} such that its tail is \lstinline{x}.
 Returns \lstinline{undefined}.
 \end{itemize}
 
diff --git a/doc/source_stream_library.tex b/doc/source_stream_library.tex
new file mode 100644
index 00000000..d89bef68
--- /dev/null
+++ b/doc/source_stream_library.tex
@@ -0,0 +1,214 @@
+\section*{Appendix: Stream library}
+
+Those stream library functions that are not built-ins are pre-declared as follows:
+
+\begin{lstlisting}
+// stream.js: Supporting streams in the Scheme style, following
+//            "stream discipline"
+
+// is_stream recurses down the stream and checks that it ends with the
+// empty list null
+
+function is_stream(xs) {
+    return is_null(xs) || (is_pair(xs) && is_list(stream_tail(xs)));
+}
+
+// A stream is either null or a pair whose tail is
+// a nullary function that returns a stream.
+
+function list_to_stream(xs) {
+    return is_null(xs)
+        ? null
+        : pair(head(xs), 
+               () => list_to_stream(tail(xs))); 
+}
+
+// stream_to_list transforms a given stream to a list
+// Lazy? No: stream_to_list needs to force the whole stream
+function stream_to_list(xs) {
+    return is_null(xs)
+        ? null
+        : pair(head(xs), stream_to_list(stream_tail(xs)));
+}
+
+// stream_length returns the length of a given argument stream
+// throws an exception if the argument is not a stream
+// Lazy? No: The function needs to explore the whole stream
+function stream_length(xs) {
+    return is_null(xs)
+        ? 0
+        : 1 + stream_length(stream_tail(xs));
+}
+
+// stream_map applies first arg f to the elements of the second
+// argument, assumed to be a stream.
+// f is applied element-by-element:
+// stream_map(f,list_to_stream(list(1,2)) results in
+// the same as list_to_stream(list(f(1),f(2)))
+// stream_map throws an exception if the second argument is not a
+// stream, and if the second argument is a non-empty stream and the
+// first argument is not a function.
+// Lazy? Yes: The argument stream is only explored as forced by
+//            the result stream.
+function stream_map(f, s) {
+    return is_null(s)
+        ? null
+        : pair(f(head(s)), 
+                 () => stream_map(f, stream_tail(s)));
+}
+
+// build_stream takes a non-negative integer n as first argument,
+// and a function fun as second argument.
+// build_list returns a stream of n elements, that results from
+// applying fun to the numbers from 0 to n-1.
+// Lazy? Yes: The result stream forces the applications of fun
+//            for the next element
+function build_stream(n, fun) {
+    function build(i) {
+        return i >= n
+            ? null
+            : pair(fun(i), 
+                   () => build(i + 1)); 
+    }
+    return build(0);
+}
+
+// stream_for_each applies first arg fun to the elements of the stream
+// passed as second argument. fun is applied element-by-element:
+// for_each(fun,list_to_stream(list(1, 2,null))) results in the calls fun(1)
+// and fun(2).
+// stream_for_each returns true.
+// stream_for_each throws an exception if the second argument is not a 
+// stream, and if the second argument is a non-empty stream and the
+// first argument is not a function.
+// Lazy? No: stream_for_each forces the exploration of the entire stream
+function stream_for_each(fun, xs) {
+    if (is_null(xs)) {
+        return true;
+    } else {
+        fun(head(xs));
+        return stream_for_each(fun, stream_tail(xs));
+    }
+}
+
+// stream_reverse reverses the argument stream
+// stream_reverse throws an exception if the argument is not a stream.
+// Lazy? No: stream_reverse forces the exploration of the entire stream
+function stream_reverse(xs) {
+    function rev(original, reversed) {
+        return is_null(original)
+            ? reversed
+            : rev(stream_tail(original), 
+                  pair(head(original), () => reversed));
+    }
+    return rev(xs,null);
+}
+
+// stream_append appends first argument stream and second argument stream.
+// In the result, null at the end of the first argument stream
+// is replaced by the second argument stream
+// stream_append throws an exception if the first argument is not a
+// stream.
+// Lazy? Yes: the result stream forces the actual append operation
+function stream_append(xs, ys) {
+    return is_null(xs)
+        ? ys
+        : pair(head(xs),
+               () => stream_append(stream_tail(xs), ys)); 
+}
+
+// stream_member looks for a given first-argument element in a given
+// second argument stream. It returns the first postfix substream
+// that starts with the given element. It returns null if the
+// element does not occur in the stream
+// Lazy? Sort-of: stream_member forces the stream only until the element is found.
+function stream_member(x, s) {
+    return is_null(s)
+        ? null
+        : head(s) === x
+            ? s
+            : stream_member(x, stream_tail(s));
+}
+
+// stream_remove removes the first occurrence of a given first-argument element
+// in a given second-argument list. Returns the original list
+// if there is no occurrence.
+// Lazy? Yes: the result stream forces the construction of each next element
+function stream_remove(v, xs) {
+    return is_null(xs)
+        ? null
+        : v === head(xs)
+            ? stream_tail(xs)
+            :  pair(head(xs), 
+                    () => stream_remove(v, stream_tail(xs))); 
+}
+
+// stream_remove_all removes all instances of v instead of just the first.
+// Lazy? Yes: the result stream forces the construction of each next element
+function stream_remove_all(v, xs) {
+    return is_null(xs)
+        ? null
+        : v === head(xs)
+            ? stream_remove_all(v, stream_tail(xs))
+            : pair(head(xs), () => stream_remove_all(v, stream_tail(xs))); 
+}
+
+// filter returns the substream of elements of given stream s
+// for which the given predicate function p returns true.
+// Lazy? Yes: The result stream forces the construction of
+//            each next element. Of course, the construction
+//            of the next element needs to go down the stream
+//            until an element is found for which p holds.
+function stream_filter(p, s) {
+    return is_null(s)
+        ? null
+        : p(head(s))
+            ? pair(head(s), 
+                   () => stream_filter(p, stream_tail(s)))
+            : stream_filter(p, stream_tail(s));
+}
+
+// enumerates numbers starting from start,
+// using a step size of 1, until the number
+// exceeds end.
+// Lazy? Yes: The result stream forces the construction of
+//            each next element
+function enum_stream(start, end) {
+    return start > end
+        ? null
+        : pair(start, 
+               () => enum_stream(start + 1, end)); 
+}
+
+// integers_from constructs an infinite stream of integers
+// starting at a given number n
+// Lazy? Yes: The result stream forces the construction of
+//            each next element
+function integers_from(n) {
+    return pair(n,
+                () => integers_from(n + 1));
+}
+
+// eval_stream constructs the list of the first n elements
+// of a given stream s
+// Lazy? Sort-of: eval_stream only forces the computation of
+//                the first n elements, and leaves the rest of
+//                the stream untouched.
+function eval_stream(s, n) {
+    return n === 0
+        ? null
+        : pair(head(s),
+               eval_stream(stream_tail(s),
+                           n - 1));
+}
+
+// Returns the item in stream s at index n (the first item is at position 0)
+// Lazy? Sort-of: stream_ref only forces the computation of
+//                the first n elements, and leaves the rest of
+//                the stream untouched.
+function stream_ref(s, n) {
+    return n === 0
+        ? head(s)
+        : stream_ref(stream_tail(s), n - 1);
+}
+\end{lstlisting}
diff --git a/doc/source_streams.tex b/doc/source_streams.tex
new file mode 100644
index 00000000..508a7e8c
--- /dev/null
+++ b/doc/source_streams.tex
@@ -0,0 +1,90 @@
+\subsection*{Stream Support}
+
+The following stream processing functions are supported:
+
+\begin{itemize}
+\item \lstinline{stream_tail(x)}: \textit{Built-in}, assumes that the tail (second component) of the
+  pair \lstinline{x} is a nullary function, and returns the result of
+  applying that function.\\
+\emph{Laziness:}  Yes: \lstinline{stream_tail} only forces the direct tail of a given
+stream,
+but not the rest of the stream, i.e. not the tail of the tail, etc.
+\item \lstinline{stream(x1, x2,..., xn)}: \textit{Built-in}, returns a stream with $n$ elements. The
+first element is \lstinline{x1}, the second \lstinline{x2}, etc.\\
+\emph{Laziness:}  No: In this implementation, we generate first a
+           complete list, and then a stream using \lstinline{list_to_stream}.
+\item \lstinline{is_stream(x)}: Returns \lstinline{true} if
+  \lstinline{x} is a stream as defined in the lectures, and
+  \lstinline{false} otherwise.\\
+\emph{Laziness:}  No: \lstinline{is_stream} needs to force the given stream.
+\item \lstinline{list_to_stream(xs)}: transforms a given list to a stream.\\
+\emph{Laziness:}  Yes: \lstinline{list_to_stream} goes down the list only when forced.
+\item \lstinline{stream_to_list(s)}: transforms a given stream to a list.\\
+\emph{Laziness:}  No: \lstinline{stream_to_list} needs to force the whole stream.
+\item \lstinline{stream_length(s)}: Returns the length of the stream
+  \lstinline{s}.\\
+\emph{Laziness:}  No: The function needs to force the whole stream.
+\item \lstinline{stream_map(f, s)}: Returns a stream that results from stream
+  \lstinline{s} by element-wise application of \lstinline{f}.\\
+\emph{Laziness:}  Yes: The argument stream is only explored as forced by
+           the result stream.
+\item \lstinline{build_stream(n, f)}: Makes a stream with \lstinline{n}
+elements by applying the unary function \lstinline{f} to the numbers 0
+to \lstinline{n - 1}.\\
+\emph{Laziness:}  Yes: The result stream forces the applications of fun
+            for the next element.
+\item \lstinline{stream_for_each(f, s)}: Applies \lstinline{f} to every
+  element of the stream \lstinline{s}, and then returns
+  \lstinline{true}.\\
+\emph{Laziness:}  No: \lstinline{stream_for_each} forces the exploration of the entire stream.
+\item \lstinline{stream_reverse(s)}: Returns finite stream \lstinline{s} in reverse
+  order. Does not terminate for infinite streams.\\
+\emph{Laziness:}  No: \lstinline{stream_reverse} forces the exploration of the entire stream.
+\item \lstinline{stream_append(xs, ys)}: Returns a stream that results from 
+appending the stream \lstinline{ys} to the stream \lstinline{xs}.\\
+\emph{Laziness:}  Yes: Forcing the result stream activates the actual append operation.
+\item \lstinline{stream_member(x, s)}: Returns first postfix substream
+whose head is equal to
+\lstinline{x} (\lstinline{===}); returns \lstinline{null} if the
+element does not occur in the stream.\\
+ \emph{Laziness:}  Sort-of: \lstinline{stream_member} forces the stream only until the element is found.
+\item \lstinline{stream_remove(x, s)}: Returns a stream that results from
+given stream \lstinline{s} by removing the first item from \lstinline{s} that
+is equal (\lstinline{===}) to \lstinline{x}.
+Returns the original list
+if there is no occurrence.\\
+\emph{Laziness:}  Yes: Forcing the result stream leads to construction of each next element.
+\item \lstinline{stream_remove_all(x, s)}: Returns a stream that results from
+given stream \lstinline{s} by removing all items from \lstinline{s} that
+are equal (\lstinline{===}) to \lstinline{x}.\\
+\emph{Laziness:}  Yes: The result stream forces the construction of each next element.
+\item \lstinline{stream_filter(pred, s)}: Returns a stream that contains
+only those elements for which the one-argument function
+\lstinline{pred}
+returns \lstinline{true}.\\
+\emph{Laziness:}  Yes: The result stream forces the construction of
+            each next element. Of course, the construction
+            of the next element needs to go down the stream
+            until an element is found for which \lstinline{pred} holds.
+\item \lstinline{enum_stream(start, end)}: Returns a stream that enumerates
+numbers starting from \lstinline{start} using a step size of 1, until
+the number exceeds (\lstinline{>}) \lstinline{end}.\\
+ \emph{Laziness:}  Yes: Forcing the result stream leads to the construction of
+            each next element.
+\item \lstinline{integers_from(n)}: Constructs an infinite stream of integers
+starting at a given number \lstinline{n}.\\
+ \emph{Laziness:}  Yes: Forcing the result stream leads to the construction of 
+            each next element.
+\item \lstinline{eval_stream(s, n)}: Constructs the list
+of the first \lstinline{n} elements
+of a given stream \lstinline{s}.\\
+\emph{Laziness:}  Sort-of: \lstinline{eval_stream} only forces the computation of
+                the first \lstinline{n} elements, and leaves the rest of
+                the stream untouched.
+\item \lstinline{stream_ref(s, n)}: Returns the element
+of stream \lstinline{s} at position \lstinline{n}, 
+where the first element has index 0.\\
+ \emph{Laziness:}  Sort-of: \lstinline{stream_ref} only forces the computation of
+                the first \lstinline{n} elements, and leaves the rest of
+                the stream untouched.
+\end{itemize}
diff --git a/doc/source_typing.tex b/doc/source_typing.tex
index 90188855..35e1c086 100644
--- a/doc/source_typing.tex
+++ b/doc/source_typing.tex
@@ -35,8 +35,8 @@ operator & argument 1 & argument 2 & result\\ \hline
 \texttt{\textbf{>=}} & string   & string     & bool\\
 \texttt{\textbf{<=}}    & number   & number     & bool\\
 \texttt{\textbf{<=}} & string   & string     & bool\\
-\texttt{\textbf{\&\&}} & bool & bool & bool\\
-\texttt{\textbf{||}}   & bool & bool & bool\\
+\texttt{\textbf{\&\&}} & bool & any & any\\
+\texttt{\textbf{||}}   & bool & any & any\\
 \texttt{\textbf{!}}    & bool &      & bool\\
 \texttt{\textbf{-}}    & number &    & number
 \end{tabular}
diff --git a/src/createContext.ts b/src/createContext.ts
index 3686acc5..50678b0c 100644
--- a/src/createContext.ts
+++ b/src/createContext.ts
@@ -50,7 +50,15 @@ export const ensureGlobalEnvironmentExist = (context: Context) => {
 
 const defineSymbol = (context: Context, name: string, value: Value) => {
   const globalFrame = context.runtime.frames[0]
-  globalFrame.environment[name] = value
+  Object.defineProperty(
+    globalFrame.environment,
+    name,
+    {
+      value,
+      writable: false,
+      enumerable: true
+    }
+  )
 }
 
 export const importExternalSymbols = (context: Context, externalSymbols: string[]) => {
@@ -143,7 +151,7 @@ export const importBuiltins = (context: Context, externalBuiltIns: CustomBuiltIn
       function () {
         return context.metaCircularParser
           .parse.apply(context.metaCircularParser, arguments)
-      });
+      })
     defineSymbol(context, 'apply_in_underlying_javascript', function(
       fun: Function,
       args: Value
diff --git a/src/interpreter.ts b/src/interpreter.ts
index 0af46d41..d5262efc 100644
--- a/src/interpreter.ts
+++ b/src/interpreter.ts
@@ -86,6 +86,7 @@ function defineVariable(context: Context, name: string, value: Value, constant=f
 
   return frame
 }
+
 function* visit(context: Context, node: es.Node) {
   context.runtime.nodes.unshift(node)
   yield context
@@ -321,15 +322,6 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
     return new BreakValue()
   },
   ForStatement: function*(node: es.ForStatement, context: Context) {
-    // Check that all 3 expressions are not empty in a for loop
-    const missing_parts = ["init", "test", "update"].filter(
-      part => node[part] === null
-    );
-    if (missing_parts.length > 0) {
-      const error = new errors.EmptyForExpression(node, missing_parts);
-      handleError(context, error);
-    }
-
     // Create a new block scope for the loop variables
     const loopFrame = createBlockFrame(context, "forLoopFrame")
     pushFrame(context, loopFrame)
diff --git a/src/rules/forStatementMustHaveAllParts.ts b/src/rules/forStatementMustHaveAllParts.ts
new file mode 100644
index 00000000..6a3de415
--- /dev/null
+++ b/src/rules/forStatementMustHaveAllParts.ts
@@ -0,0 +1,44 @@
+import { stripIndent } from 'common-tags'
+import * as es from 'estree'
+
+import { ErrorSeverity, ErrorType, Rule, SourceError } from '../types'
+
+export class ForStatmentMustHaveAllParts implements SourceError {
+  public type = ErrorType.SYNTAX
+  public severity = ErrorSeverity.ERROR
+
+  constructor(public node: es.ForStatement, private missingParts :string[]) {}
+
+  get location() {
+    return this.node.loc!
+  }
+
+  public explain() {
+    return `Missing ${this.missingParts.join(', ')} expression${this.missingParts.length === 1 ? '' : 's'} in for statement.`
+  }
+
+  public elaborate() {
+    return stripIndent`
+      This for statement requires all three parts (initialiser, test, update) to be present.
+    `
+  }
+}
+
+const forStatementMustHaveAllParts: Rule<es.ForStatement> = {
+  name: 'for-statement-must-have-all-parts',
+
+  checkers: {
+    ForStatement(node: es.ForStatement) {
+      const missingParts = ["init", "test", "update"].filter(
+        part => node[part] === null
+      );
+      if (missingParts.length > 0) {
+        return [new ForStatmentMustHaveAllParts(node, missingParts)]
+      } else {
+        return []
+      }
+    }
+  }
+}
+
+export default forStatementMustHaveAllParts
diff --git a/src/rules/index.ts b/src/rules/index.ts
index 7ef3213f..c5bde15b 100644
--- a/src/rules/index.ts
+++ b/src/rules/index.ts
@@ -14,6 +14,7 @@ import noNonEmptyList from './noNonEmptyList'
 import noUnspecifiedLiteral from './noUnspecifiedLiteral'
 import noUnspecifiedOperator from './noUnspecifiedOperator'
 import singleVariableDeclaration from './singleVariableDeclaration'
+import forStatementMustHaveAllParts from './forStatementMustHaveAllParts'
 
 const rules: Array<Rule<es.Node>> = [
   bracesAroundIfElse,
@@ -27,7 +28,8 @@ const rules: Array<Rule<es.Node>> = [
   noDeclareReserved,
   noDeclareMutable,
   noUnspecifiedLiteral,
-  noUnspecifiedOperator
+  noUnspecifiedOperator,
+  forStatementMustHaveAllParts
 ]
 
 export default rules


Test patch:
diff --git a/src/__tests__/__snapshots__/disallowed_syntax.ts.snap b/src/__tests__/__snapshots__/disallowed_syntax.ts.snap
index f1d6c96e..6579a98c 100644
--- a/src/__tests__/__snapshots__/disallowed_syntax.ts.snap
+++ b/src/__tests__/__snapshots__/disallowed_syntax.ts.snap
@@ -1,11 +1,11 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`Cannot leave blank expressions in for loops 1`] = `"Line 2: For statement cannot have empty init expression."`;
+exports[`Cannot leave blank expressions in for loops 1`] = `"Line 2: Missing init expression in for statement."`;
 
-exports[`Cannot leave blank expressions in for loops 2`] = `"Line 2: For statement cannot have empty test expression."`;
+exports[`Cannot leave blank expressions in for loops 2`] = `"Line 2: Missing test expression in for statement."`;
 
-exports[`Cannot leave blank expressions in for loops 3`] = `"Line 2: For statement cannot have empty update expression."`;
+exports[`Cannot leave blank expressions in for loops 3`] = `"Line 2: Missing update expression in for statement."`;
 
-exports[`Cannot leave blank expressions in for loops 4`] = `"Line 2: For statement cannot have empty init,test,update expressions."`;
+exports[`Cannot leave blank expressions in for loops 4`] = `"Line 2: Missing init, test, update expressions in for statement."`;
 
 exports[`Cannot use update expressions 1`] = `"Line 3: Update expressions are not allowed"`;
diff --git a/src/__tests__/__snapshots__/interpreter-errors.ts.snap b/src/__tests__/__snapshots__/interpreter-errors.ts.snap
index 429aef8d..6b7585b8 100644
--- a/src/__tests__/__snapshots__/interpreter-errors.ts.snap
+++ b/src/__tests__/__snapshots__/interpreter-errors.ts.snap
@@ -27,6 +27,58 @@ Array [
 ]
 `;
 
+exports[`Error when assigning to builtin 1`] = `
+Object {
+  "status": "error",
+}
+`;
+
+exports[`Error when assigning to builtin 2`] = `
+Array [
+  ConstAssignment {
+    "location": SourceLocation {
+      "end": Position {
+        "column": 11,
+        "line": 2,
+      },
+      "start": Position {
+        "column": 4,
+        "line": 2,
+      },
+    },
+    "name": "map",
+    "severity": "Error",
+    "type": "Runtime",
+  },
+]
+`;
+
+exports[`Error when assigning to builtin 3`] = `
+Object {
+  "status": "error",
+}
+`;
+
+exports[`Error when assigning to builtin 4`] = `
+Array [
+  ConstAssignment {
+    "location": SourceLocation {
+      "end": Position {
+        "column": 17,
+        "line": 2,
+      },
+      "start": Position {
+        "column": 4,
+        "line": 2,
+      },
+    },
+    "name": "undefined",
+    "severity": "Error",
+    "type": "Runtime",
+  },
+]
+`;
+
 exports[`Error when assigning to property on undefined 1`] = `
 Object {
   "status": "error",
diff --git a/src/__tests__/interpreter-errors.ts b/src/__tests__/interpreter-errors.ts
index 39644f92..330133bd 100644
--- a/src/__tests__/interpreter-errors.ts
+++ b/src/__tests__/interpreter-errors.ts
@@ -15,6 +15,34 @@ test("Undefined variable error is thrown", () => {
   })
 })
 
+test('Error when assigning to builtin', () => {
+  const code = `
+    map = 5;
+   `;
+  const context = mockContext(3)
+  const promise = runInContext(code, context, { scheduler: 'preemptive' })
+  return promise.then(obj => {
+    expect(obj).toMatchSnapshot()
+    expect(obj.status).toBe('error')
+    expect(context.errors).toMatchSnapshot()
+    expect(parseError(context.errors)).toBe('Line 2: Cannot assign new value to constant map')
+  })
+})
+
+test('Error when assigning to builtin', () => {
+  const code = `
+    undefined = 5;
+   `;
+  const context = mockContext(3)
+  const promise = runInContext(code, context, { scheduler: 'preemptive' })
+  return promise.then(obj => {
+    expect(obj).toMatchSnapshot()
+    expect(obj.status).toBe('error')
+    expect(context.errors).toMatchSnapshot()
+    expect(parseError(context.errors)).toBe('Line 2: Cannot assign new value to constant undefined')
+  })
+})
+
 test('Error when assigning to property on undefined', () => {
   const code = `
     undefined.prop = 123;
@@ -100,4 +128,4 @@ test('In case a function ever returns null, should throw an error as well', () =
     expect(context.errors).toMatchSnapshot()
     expect(parseError(context.errors)).toBe('Line 3: Cannot read property prop of null')
   })
-})
\ No newline at end of file
+})