basicdoc: adding missing array manipulating functions

This commit is contained in:
minjaesong
2020-12-23 16:44:26 +09:00
parent d143b32ff2
commit 5c97ce97ee
8 changed files with 91 additions and 67 deletions

View File

@@ -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) => {

View File

@@ -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.

View File

@@ -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}

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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 }

View File

@@ -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}