diff --git a/assets/basic.js b/assets/basic.js index 4934e94..2dcf8f4 100644 --- a/assets/basic.js +++ b/assets/basic.js @@ -568,6 +568,27 @@ bStatus.getDefunThunk = function(lnum, stmtnum, exprTree) { return resolve(bF._executeSyntaxTree(lnum, stmtnum, tree, 0)); } }; +/* Accepts troValue, assignes to BASIC variable, and returns internal_assign_object + * @params troValue Variable to assign into + * @params rh the value, resolved + */ +bStatus.addAsBasicVar = function(troValue, rh) { + if (troValue.arrFull !== undefined) { // assign to existing array + if (isNaN(rh) && !Array.isArray(rh)) throw lang.illegalType(lnum, rh); + let arr = eval("troValue.arrFull"+troValue.arrKey); + if (Array.isArray(arr)) throw lang.subscrOutOfRng(lnum, arr); + eval("troValue.arrFull"+troValue.arrKey+"=rh"); + return {asgnVarName: troValue.arrName, asgnValue: rh}; + } + else { + let varname = troValue.toUpperCase(); + //println("input varname: "+varname); + let type = JStoBASICtype(rh); + if (_basicConsts[varname]) throw lang.asgnOnConst(lnum, varname); + bStatus.vars[varname] = new BasicVar(rh, type); + return {asgnVarName: varname, asgnValue: rh}; + } +} bStatus.builtin = { /* @param lnum line number @@ -592,29 +613,7 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length //try { println(lnum+" = rh resolved entries: "+Object.entries(rh)); } //catch (_) {} - - if (troValue.arrFull !== undefined) { // assign to existing array - if (isNaN(rh) && !Array.isArray(rh)) throw lang.illegalType(lnum, rh); - let arr = eval("troValue.arrFull"+troValue.arrKey); - if (Array.isArray(arr)) throw lang.subscrOutOfRng(lnum, arr); - eval("troValue.arrFull"+troValue.arrKey+"=rh"); - return {asgnVarName: troValue.arrName, asgnValue: rh}; - } - else { - var varname = troValue.toUpperCase(); - var type = JStoBASICtype(rh); - if (_basicConsts[varname]) throw lang.asgnOnConst(lnum, varname); - // special case for scalar array - // it basically bypasses the regular resolve subroutine - if (args[1].troType !== undefined && args[1].troType == "array") { - bStatus.vars[varname] = new BasicVar(args[1].troValue, "array"); - return {asgnVarName: varname, asgnValue: rh}; - } - else { - bStatus.vars[varname] = new BasicVar(rh, type); - return {asgnVarName: varname, asgnValue: rh}; - } - } + return bStatus.addAsBasicVar(troValue, rh); }}, "IN" : {f:function(lnum, stmtnum, args) { // almost same as =, but don't actually make new variable. Used by FOR statement if (args.length != 2) throw lang.syntaxfehler(lnum, args.length+lang.aG); @@ -1040,21 +1039,10 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length // NOTE: empty string will be cast to 0, which corresponds to GW-BASIC if (!isNaN(rh)) rh = rh*1 - if (troValue.arrFull !== undefined) { // assign to existing array - if (isNaN(rh) && !Array.isArray(rh)) throw lang.illegalType(lnum, rh); - let arr = eval("troValue.arrFull"+troValue.arrKey); - if (Array.isArray(arr)) throw lang.subscrOutOfRng(lnum, arr); - eval("troValue.arrFull"+troValue.arrKey+"=rh"); - return {asgnVarName: troValue.arrName, asgnValue: rh}; - } - else { - let varname = troValue.toUpperCase(); - //println("input varname: "+varname); - let type = JStoBASICtype(rh); - if (_basicConsts[varname]) throw lang.asgnOnConst(lnum, varname); - bStatus.vars[varname] = new BasicVar(rh, type); - return {asgnVarName: varname, asgnValue: rh}; - } + return bStatus.addAsBasicVar(troValue, rh); +}}, +"CIN" : {f:function(lnum, stmtnum, args) { + return sys.read().trim(); }}, "END" : {f:function(lnum, stmtnum, args) { serial.println("Program terminated in "+lnum); @@ -1121,8 +1109,18 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length DATA_CURSOR = 0; }}, "READ" : {f:function(lnum, stmtnum, args) { - let r = DATA_CONSTS.shift(); + if (args.length != 1) throw lang.syntaxfehler(lnum, args.length+lang.aG); + let troValue = args[0].troValue; + + let rh = DATA_CONSTS[DATA_CURSOR++]; + if (rh === undefined) throw lang.outOfData(lnum); + + return bStatus.addAsBasicVar(troValue, rh); +}}, +"DGET" : {f:function(lnum, stmtnum, args) { + let r = DATA_CONSTS[DATA_CURSOR++]; if (r === undefined) throw lang.outOfData(lnum); + return r; }}, "OPTIONBASE" : {f:function(lnum, stmtnum, args) { return oneArgNum(lnum, stmtnum, args, (lh) => { diff --git a/assets/tbas/doc/concepts.tex b/assets/tbas/doc/concepts.tex index 070f92e..c681e56 100644 --- a/assets/tbas/doc/concepts.tex +++ b/assets/tbas/doc/concepts.tex @@ -1,7 +1,7 @@ \quad -\chapterprecishere{``Caution! Under no circumstances confuse the adjective \emph{basic} with the noun \emph{BASIC}, except under confusing circumstances!''\par\raggedleft --- \textup{\tbas{} Reference Manual, \theedition}\footnote{Original quotation is from \emph{The INTERCAL Programming Language Reference Manual} by Donald R. Woods and James M. Lyon}} +\chapterprecishere{``Caution! Under no circumstances confuse the adjective \emph{basic} with the noun \emph{BASIC}, except under confusing circumstances!''\par\raggedleft --- \textup{\tbas\ Reference Manual, \theedition}\footnote{Original quotation is from \emph{The INTERCAL Programming Language Reference Manual} by Donald R. Woods and James M. Lyon}} -This chapter describes the basic concepts of the \tbas{} language. +This chapter describes the basic concepts of the \tbas\ language. \section{Values and Types} @@ -29,7 +29,7 @@ A program is executed starting with its lowest line number. Statements on a line You can dive into other line in the middle of the program with \code{GOTO}. The program flow will continue normally at the new line \emph{and it will never know ya just did that}. -If you want less insane jumping, \code{GOSUB} is used to jump to a subroutine. Subroutine is a little section of a code that serves as a tiny program inside of a program. \code{GOSUB} will remember from which statement in the line you have came from, and will return your program flow to that line when \code{RETURN} statement is encountered. (of course, if \code{RETURN} is used without \code{GOSUB}, program will raise some error) Do note that while you can reserve some portion of a program line as a \code{subroutine}, \tbas{} will not provide local variables and whatnot as all variables in \tbas{} are global, and you can just \code{GOTO} out of a subroutine to anywhere you desire and wreak havoc \emph{if you really want to}. +If you want less insane jumping, \code{GOSUB} is used to jump to a subroutine. Subroutine is a little section of a code that serves as a tiny program inside of a program. \code{GOSUB} will remember from which statement in the line you have came from, and will return your program flow to that line when \code{RETURN} statement is encountered. (of course, if \code{RETURN} is used without \code{GOSUB}, program will raise some error) Do note that while you can reserve some portion of a program line as a \code{subroutine}, \tbas\ will not provide local variables and whatnot as all variables in \tbas\ are global, and you can just \code{GOTO} out of a subroutine to anywhere you desire and wreak havoc \emph{if you really want to}. The \code{ON} statement provides alternative branching construct. You can enter multiple line numbers and let your variable (or mathematical expression) to choose which index of line numbers to \code{GOTO}- or \code{GOSUB} into. diff --git a/assets/tbas/doc/functions.tex b/assets/tbas/doc/functions.tex index 5a975cb..45f5c7c 100644 --- a/assets/tbas/doc/functions.tex +++ b/assets/tbas/doc/functions.tex @@ -1,6 +1,6 @@ \label{functions} -Functions are a form of expression that may taks input arguments surrounded by parentheses. Most of the traditional BASIC \emph{statements} that does not return a value are \emph{functions} in \tbas , and like those, while \tbas{} functions can be called without parentheses, it is highly \emph{discouraged} because of the ambiguities in syntax. \textbf{Always use parentheses on function call!} +Functions are a form of expression that may taks input arguments surrounded by parentheses. Most of the traditional BASIC \emph{statements} that does not return a value are \emph{functions} in \tbas , and like those, while \tbas\ functions can be called without parentheses, it is highly \emph{discouraged} because of the ambiguities in syntax. \textbf{Always use parentheses on function call!} \section{Mathematical} @@ -71,6 +71,15 @@ Functions are a form of expression that may taks input arguments surrounded by p \section{Input} + \subsection{CIN} + \codeline{S \textbf{= CIN()}}\par + Waits for the user input and returns it. + \subsection{DATA} + \codeline{\textbf{DATA} CONST0 [\textbf{,} CONST1]\ldots}\par + Adds data that can be read by \code{READ} function. \code{DATA} declarations need not be reacheable in the program flow. + \subsection{DGET} + \codeline{S \textbf{= DGET()}}\par + Fetches a data declared from \code{DATA} statements and returns it, incrementing the \code{DATA} position. \subsection{DIM} \codeline{Y \textbf{= DIM(}X\textbf{)}}\par Returns array with size of \code{X}, all filled with zero. @@ -80,8 +89,13 @@ Functions are a form of expression that may taks input arguments surrounded by p Actual keycode and the array length depends on the machine: in \thismachine , array length will be fixed to 8. For the list of available keycodes, see \ref{implementation}. \subsection{INPUT} \codeline{\textbf{INPUT} VARIABLE}\par - Prints out \code{? } to the console and waits for user input. Input can be any length and terminated with return key. The input will be stored to given variable. - + Prints out \code{? } to the console and waits for user input. Input can be any length and terminated with return key. The input will be stored to given variable.\par + This behaviour is to keep the compatibility with the traditional BASIC. For function-like usage, use \code{CIN} instead. + \subsection{READ} + \codeline{\textbf{READ} VARIABLE}\par + Assigns data declared from \code{DATA} statements to given variable. Reading starts at the current \code{DATA} position, and the data position will be incremented by one. The position is reset to the zero by the \code{RUN} command.\par + This behaviour is to keep the compatibility with the traditional BASIC. For function-like usage, use \code{DGET} instead. + \section{Output} \subsection{EMIT} @@ -99,9 +113,6 @@ Functions are a form of expression that may taks input arguments surrounded by p \subsection{CLEAR} \codeline{\textbf{CLEAR}}\par Clears all declared variables. - \subsection{DATA} - \codeline{\textbf{DATA} CONST0 [\textbf{,} CONST1]\ldots}\par - Adds data that can be read by \code{READ} function. \code{DATA} declarations need not be reacheable in the program flow. \subsection{END} \codeline{\textbf{END}}\par Stops program execution and returns control to the user. @@ -131,9 +142,6 @@ Functions are a form of expression that may taks input arguments surrounded by p \subsection{NEXT} \codeline{\textbf{NEXT}}\par Iterates \code{FOR-NEXT} loop and increments the loop variable from the most recent \code{FOR} statement and jumps to that statement. - \subsection{READ} - \codeline{\textbf{READ} VARIABLE}\par - Assigns data declared from \code{DATA} statements to given variable. Reading starts at the current \code{DATA} position, and the data position will be incremented by one. The position is reset to the zero by the \code{RUN} command. \subsection{RESTORE} \codeline{\textbf{RESTORE}}\par Resets the \code{DATA} pointer. @@ -159,6 +167,22 @@ Functions are a form of expression that may taks input arguments surrounded by p \subsection{SPC} \codeline{STR \textbf{= SPC(}STR \textbf{,} NUM\_CHARS\textbf{)}}\par Returns a string of \code{NUM\_CHARS} spaces. + +\section{Array Manipulation} + + \subsection{HEAD} + \codeline{K \textbf{= HEAD(}ARRAY\textbf{)}}\par + Returns the head element of the given array. + \subsection{INIT} + \codeline{K \textbf{= INIT(}ARRAY\textbf{)}}\par + Returns the new array that has its last element removed. + \subsection{LAST} + \codeline{K \textbf{= LAST(}ARRAY\textbf{)}}\par + Returns the last element of the given array. + \subsection{TAIL} + \codeline{K \textbf{= TAIL(}ARRAY\textbf{)}}\par + Returns the new array that has its head element removed. + \section{Graphics} \subsection{PLOT} diff --git a/assets/tbas/doc/implementation.tex b/assets/tbas/doc/implementation.tex index b67d56d..3ca1e0a 100644 --- a/assets/tbas/doc/implementation.tex +++ b/assets/tbas/doc/implementation.tex @@ -1,10 +1,10 @@ \label{implementation} -This chapter explains implementation details of \tbas{} running on TSVM. +This chapter explains implementation details of \tbas\ running on \thismachine. \section{Keycodes} -This is a keycodes recognised by LibGDX, a framework that TSVM runs on. +This is a keycodes recognised by LibGDX, a framework that \thismachine\ runs on. \begin{longtable}{*{2}{m{\textwidth}}}\hline \endfirsthead diff --git a/assets/tbas/doc/intro.tex b/assets/tbas/doc/intro.tex index 3799262..cfad247 100644 --- a/assets/tbas/doc/intro.tex +++ b/assets/tbas/doc/intro.tex @@ -1,6 +1,6 @@ -\tbas{} is a BASIC dialect and its interpreter. \tbas{} emulates most of the common BASIC syntax while adds more advanced and up-to-date concepts gracefully, such as user-defined function that can \emph{actually} recurse, arbitrary list construction using CONS-operator and some of the features in the realm of functional programming from \code{MAP} and \code{FOLD} to \code{CURRY}-ing a function. +\tbas\ is a BASIC dialect and its interpreter. \tbas\ emulates most of the common BASIC syntax while adds more advanced and up-to-date concepts gracefully, such as user-defined function that can \emph{actually} recurse, arbitrary list construction using CONS-operator and some of the features in the realm of functional programming from \code{MAP} and \code{FOLD} to \code{CURRY}-ing a function. -This is the documentation for \tbas{} \tbasver{}. +This is the documentation for \tbas\ \tbasver. \vfill diff --git a/assets/tbas/doc/langref.tex b/assets/tbas/doc/langref.tex index 7f688cb..4741dd2 100644 --- a/assets/tbas/doc/langref.tex +++ b/assets/tbas/doc/langref.tex @@ -1,6 +1,6 @@ \newcommand{\intrange}{\hl{[$0..2^{53}-1$]}} -This chapter describes the \tbas{} language. +This chapter describes the \tbas\ language. \section{Metasyntax} @@ -19,7 +19,7 @@ In the descriptions of BASIC syntax, these conventions apply. A \emph{Program Line} consists of a line number followed by a \emph{Statements}. Program Lines are terminated by a line break or by the end-of-the-file. -A \emph{Line Number} is an integer within the range of \intrange{}. +A \emph{Line Number} is an integer within the range of \intrange. A \emph{Statement} is special form of code which has special meaning. A program line can be composed of 1 or more statements, separated by colons. For the details of statements available in \tbas , see \ref{statements}. @@ -58,7 +58,7 @@ Numeric literals take one of the following forms: \codeline{\textbf{0}\{\textbf{x}|\textbf{X}\}[\textbf{0}|\textbf{1}|\textbf{2}|\textbf{3}|\textbf{4}|\textbf{5}|\textbf{6}|\textbf{7}|\textbf{8}|\textbf{9}]\ldots}\\ \codeline{\textbf{0}\{\textbf{b}|\textbf{B}\}[\textbf{0}|\textbf{1}|\textbf{2}|\textbf{3}|\textbf{4}|\textbf{5}|\textbf{6}|\textbf{7}|\textbf{8}|\textbf{9}]\ldots} -Hexadecimal and binary literals are always interpreted as \emph{unsigned} integers. They must range between \intrange{}. +Hexadecimal and binary literals are always interpreted as \emph{unsigned} integers. They must range between \intrange. \subsection{Variables} @@ -66,11 +66,11 @@ Variable names must start with a letter and all characters of the name must be l Unlike conventional BASIC dialects (especially GW-BASIC), name pool of variables are shared between all the types. For example, if you have a numeric variable \code{A}, and define an array named \code{A} later in the program, the new array will overwrite your numeric \code{A}. -Furthermore, \emph{sigils} are not used in the \tbas{} and attempting to use one will raise syntax-error or undefined behaviour. +Furthermore, \emph{sigils} are not used in the \tbas\ and attempting to use one will raise syntax-error or undefined behaviour. \subsection{Types} -Types of data recognised by \tbas{} are distinguished by some arcane magic of Javascript auto-casing mumbo-jumbo +Types of data recognised by \tbas\ are distinguished by some arcane magic of Javascript auto-casing mumbo-jumbo \begin{tabulary}{\textwidth}{rCL} Type & Range & Precision \\ @@ -245,8 +245,8 @@ Function operators operate on functions and some values. \begin{tabulary}{\textwidth}{clL} Code & Operation & Result \\ \hline -\emph{f} \basiccurry{} \emph{x} & Curry & Apply \emph{x} into the first parameter of the function \emph{f} \\ -%{[}\emph{x},\,\emph{y}\ldots{]} \basicclosure{} \emph{e} & Closure & Creates a closure (anonymous function) from one or more parameters \emph{x},\,\emph{y}\ldots\ and an expression \emph{e} \\ +\emph{f} \basiccurry\ \emph{x} & Curry & Apply \emph{x} into the first parameter of the function \emph{f} \\ +%{[}\emph{x},\,\emph{y}\ldots{]} \basicclosure\ \emph{e} & Closure & Creates a closure (anonymous function) from one or more parameters \emph{x},\,\emph{y}\ldots\ and an expression \emph{e} \\ \end{tabulary} \emph{Currying} is an operation that returns new function that has given value applied to the original function's first parameter. See \ref{currying101} for tutorials. diff --git a/assets/tbas/doc/statements.tex b/assets/tbas/doc/statements.tex index 4cc69ec..73fb24b 100644 --- a/assets/tbas/doc/statements.tex +++ b/assets/tbas/doc/statements.tex @@ -31,7 +31,7 @@ Jumps to the line number returned by the \code{INDEX\_EXPRESSION}. If the result \section{DEFUN} -\emph{There it is, the} DEFUN. \emph{All those new-fangled parser\footnote{a computer program that translates program code entered by you into some data bits that only it can understand} and paradigms\footnote{a guidance to in which way you must think to assimilate your brain into the computer-overlord} are tied to this very statement on \tbas{}, and only Wally knows its secrets\ldots} +\emph{There it is, the} DEFUN. \emph{All those new-fangled parser\footnote{a computer program that translates program code entered by you into some data bits that only it can understand} and paradigms\footnote{a guidance to in which way you must think to assimilate your brain into the computer-overlord} are tied to this very statement on \tbas, and only Wally knows its secrets\ldots} \codeline{\textbf{DEFUN} NAME \textbf{(} [ARGS0 [\textbf{,} ARGS1]\ldots] \textbf{)} \textbf{=} EXPRESSION } diff --git a/assets/tbas/doc/tbasman.tex b/assets/tbas/doc/tbasman.tex index b626364..9641584 100644 --- a/assets/tbas/doc/tbasman.tex +++ b/assets/tbas/doc/tbasman.tex @@ -143,13 +143,15 @@ \newcommand{\theedition}{First Edition} \newcommand{\oreallypress}{\large\textbf{O'REALLY\raisebox{1ex}{\scriptsize ?}} \normalsize Press} -\title{\HUGE\textbf{TERRAN BASIC \\ REFERENCE MANUAL} \\ \Large \vspace{1em} For Version \tbasver \\ \vspace{7mm} \theedition} +\title{\HUGE\textbf{\MakeUppercase{\tbas} \\ REFERENCE MANUAL} \\ \Large \vspace{1em} For Language Version \tbasver \\ \vspace{7mm} \theedition} \date{} \author{} \hypersetup{ - pdfauthor={Torvald et al.}, - pdftitle={\tbas{} Reference Manual, \theedition{} (BASIC version \tbasver{})}, - unicode=true + pdfauthor={CuriousTorvald}, + pdftitle={\tbas\ Reference Manual For Language Version \tbasver, \theedition}, + unicode=true, + pdfkeywords={BASIC} {Functional Programming} {Improper Hierarchy}, + pdfcreator=\oreallypress } \begin{document}