From 79ebc5099db54fd8b051dfc59a972dae3307dd96 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Fri, 13 Sep 2019 21:25:00 +0200 Subject: [PATCH 001/139] Add Index page --- doc/docs/index.md | 69 +++++++++++++++++++++++++++++++++++++++++++++ doc/mkdocs.yml | 5 ++++ doc/process_wiki.py | 56 ++++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 doc/docs/index.md create mode 100644 doc/mkdocs.yml create mode 100644 doc/process_wiki.py diff --git a/doc/docs/index.md b/doc/docs/index.md new file mode 100644 index 000000000..b5dcf78c9 --- /dev/null +++ b/doc/docs/index.md @@ -0,0 +1,69 @@ +#General +* [[ZX BASIC:About|About]] +
About the ZX BASIC SDK + +* [[ZX BASIC:ChangeLog|ChangeLog]] +
A reduced list of changes/bugfixes + +* [[ZX BASIC:Installation|Installation]] +
How to install the ZX Basic SDK in your system, and prerequisites for doing so. + +* [[ZX BASIC:Tools|SDK tools]] +
Tools available in the SDK. + +* [[ZX BASIC:Zxb#Command_Line_Options|Command line options]] +
Command line options table for the compiler (zxb) + +# Products + +* [[ZX BASIC:Released_Programs|Released programs]] +
A list of third-party released programs (mostly games) for the ZX-Spectrum developed with ZX BASIC. + +# Download + +Get the latest version of ZX BASIC from the [[ZX BASIC:Archive|archive]]. + +# Tutorials + +* [[ZX BASIC:Tutorials|Programming tutorials]] +
A collection of third-party tutorials about development with ZX BASIC. + +* [[ZX BASIC:Sample Programs|Sample programs]] +
Sample programs you can try to see what ZX BASIC looks like and how fast it runs. + +* [[ZX BASIC:Sample Programs#Games|Game examples]] +
Some little games examples. + +#Help and Support + +* [http://www.boriel.com/forum/zx-basic-compiler/ Community Forum] +
Have a question? Need help or comment a report a bug? Go to the [http://www.boriel.com/forum/zx-basic-compiler/ ZX BASIC forum] + +#External resources + +* Here you are [[ZX BASIC:External_Resources|external resources]]: other tools, IDEs, graphic designers and projects related to ZX BASIC. Have a look! + +#Language Reference +* [[ZX BASIC:Syntax|Language syntax]] +
Language Syntax is very close to the original Sinclair BASIC, but it's expanded and enhanced. + +* [[ZX BASIC:Types|Data types]] +
Language data types: Instead of working always with Floating Point numbers (also available), there are also some integer types which are faster an take less memory. + + * [[ZX BASIC:Identifier|Reserved words]] +
Comprehensive list (alphabetically ordered) of identifiers you shouldn't use as a ''variable name''. E.g. `FOR`, `PRINT`. If you want usage instructions on a statement, also look here. + +# External libraries + +* [[ZX BASIC:Library|Library]] +
Library of functions and subroutines you can use in your programs. You might find them really useful. + +# Inline assembler +Embedding inline assembler in your code is pretty easy. There's a [[ZX_BASIC:Tutorials tutorial]] on it. + +# Compiler internals +Only for true hackers: This explains how the compiler does it job, how to expand it, etc. You must be a bit crazy if you enter here... + +# Other Architectures +ZX Basic was designed from the base as a Retargeable Compiler, so it should be not hard to extend it to other architectures. This is `work in progress`. See [[ZX_BASIC:Other architectures|Other Architectures]] for more info. + diff --git a/doc/mkdocs.yml b/doc/mkdocs.yml new file mode 100644 index 000000000..0204667e6 --- /dev/null +++ b/doc/mkdocs.yml @@ -0,0 +1,5 @@ +site_name: ZX Basic Wiki +nav: + - Home: index.md + +theme: readthedocs diff --git a/doc/process_wiki.py b/doc/process_wiki.py new file mode 100644 index 000000000..7d31777fd --- /dev/null +++ b/doc/process_wiki.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from bs4 import BeautifulSoup as BS +import sys +import re + +RE_CODE = re.compile('|||') + + +def write_page(title, text, sha1): + fname = title.replace(' ', '_') + '.md' + with open(fname, 'wt', encoding='utf-8') as fout: + fout.write('#{}\n\n'.format(title)) + started = False + verbatim = False + + for line in text.split('\n'): + if line == sha1: + continue + + started = started or line == 'text/x-wiki' + if not started or line == 'text/x-wiki': + continue + + prefix = '' + if line.startswith(' ') or verbatim: + if not verbatim: + fout.write('```\n') + verbatim = True + elif line and not line.startswith(' '): + fout.write('```\n') + verbatim = False + print(line, sha1) + else: + while line and line[0] == line[-1] == '=': + line = line[1:-1] + prefix = prefix + '#' + + line = line.replace("'''", '**') + line = RE_CODE.sub(repl='```\n', string=line) + line = line.replace('', '_').replace('', '_') + fout.write(prefix + line + '\n') + + +# given your html as the variable 'html' +with open(sys.argv[1], 'rt') as f: + soup = BS(f.read(), "xml") + +pages = soup.find_all('page') +for page in pages: + title = page.title.text + if not title.startswith('ZX BASIC:'): + continue + title = title[9:] + write_page(title, page.text, page.sha1.text) From 734c5a59dcc4bd0ffe17558e207ea2fe32d3deb3 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Fri, 13 Sep 2019 22:55:21 +0200 Subject: [PATCH 002/139] Add READ and DATA help --- doc/docs/data.md | 49 ++++++++++++++++++++++++++++++++++++++++++ doc/docs/read.md | 52 +++++++++++++++++++++++++++++++++++++++++++++ doc/process_wiki.py | 44 +++++++++++++++++++++++++++++++++----- 3 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 doc/docs/data.md create mode 100644 doc/docs/read.md diff --git a/doc/docs/data.md b/doc/docs/data.md new file mode 100644 index 000000000..8a2cb95dc --- /dev/null +++ b/doc/docs/data.md @@ -0,0 +1,49 @@ +#DATA + +##Syntax +``` + DATA [, , ...] +``` + +**DATA** statement stores values to be retrieved using the [READ](read.md) sentence. These can be numerical or string expressions. +Instead of using INPUT() function or [LET](let.md) assignments, you can write a sequence (or several of them) of **DATA** +which might result in a compact and more readable code to initialize data variables. + +**DATA** statements can be placed anywhere in the code, but they're usually located at the end for better readability. + +##Example + +``` +FOR i = 1 TO 2 + READ a, b, c$ + + PRINT "a: "; a + PRINT "b: "; b + PRINT "c: "; c +NEXT i + +REM notice the a * a expression +DATA 2, a * a, "Hello" +DATA b * 5, 32, "World" +``` + +This will output: + +``` + a: 2 + b: 4 + c: Hello + a: 20 + b: 32 + c: World + +``` +Expressions are read and evaluated one by one. When a **DATA** line is finished, the next one in the listing will be read. +Traditionally if there's no more data to read, an _OUT of Data_ error happened. In ZX Basic, the read sequence restarts from the beginning. + +##Remarks +* This statement is Sinclair BASIC compatible. + +##See also +* [READ](read.md) +* [RESTORE](restore.md) diff --git a/doc/docs/read.md b/doc/docs/read.md new file mode 100644 index 000000000..f1133b161 --- /dev/null +++ b/doc/docs/read.md @@ -0,0 +1,52 @@ +#READ + +#READ + +##Syntax +``` + '''READ''' ''[, , ...]'' +``` +**READ** gets the next data expression available from a [DATA](data.md) line definition and stores it into a variable (not arrays) or an array element. +Instead of using INPUT() function or [LET](let.md) assignments, you can write a sequence (or several of them) of **READ** which might result in a compact and more readable code to initialize data variables. + +**READ** gets the items one after another. This order can be changed using [RESTORE](restore.md). + +##Example + +``` +DIM a(9) as UByte + +FOR i = 0 TO 9: REM 0 TO 9 => 10 elements + READ a(i) + PRINT a(i) +NEXT i + +REM notice the a(n) data entries +DATA 2, 4, 6 * i, 7, 0 +DATA a(0), a(1), a(2), a(3), a(4) +``` + +This will output: + +``` + 2 + 4 + 12 + 7 + 0 + 2 + 4 + 12 + 7 + 0 +``` +Expressions are read and evaluated one by one, **when the READ sentence is executed**. When a **DATA** line is finished, the next one in the listing will be read. +Traditionally if there's no more data to read, an _OUT of Data_ error happened. In ZX Basic, the read sequence restarts from the beginning. +The reading sequence can be altered with [RESTORE](restore.md) + +##Remarks +* This statement is Sinclair BASIC compatible. + +##See also +* [DATA](data.md) +* [RESTORE](restore.md) diff --git a/doc/process_wiki.py b/doc/process_wiki.py index 7d31777fd..e6ba96c7c 100644 --- a/doc/process_wiki.py +++ b/doc/process_wiki.py @@ -4,12 +4,33 @@ from bs4 import BeautifulSoup as BS import sys import re +import os RE_CODE = re.compile('|||') +RE_INTERNAL_LINK = re.compile(r'\[\[([^]|]+)(\|[^]]+)?\]\]') -def write_page(title, text, sha1): - fname = title.replace(' ', '_') + '.md' +def get_file_names(path): + result = set() + for root, dir, files in os.walk(path): + result.update([os.path.basename(x) for x in files]) + + return result + + +def link_to_fname(link): + if link.startswith('ZX_BASIC:'): + link = link[9:] + return link.replace(' ', '_').lower() + '.md' + + +def write_page(title, text, sha1, already_done): + fname = title.replace(' ', '_').lower() + '.md' + if fname in already_done: + return + + print('Processing {}'.format(fname)) + with open(fname, 'wt', encoding='utf-8') as fout: fout.write('#{}\n\n'.format(title)) started = False @@ -31,8 +52,8 @@ def write_page(title, text, sha1): elif line and not line.startswith(' '): fout.write('```\n') verbatim = False - print(line, sha1) - else: + + if not verbatim: while line and line[0] == line[-1] == '=': line = line[1:-1] prefix = prefix + '#' @@ -40,6 +61,17 @@ def write_page(title, text, sha1): line = line.replace("'''", '**') line = RE_CODE.sub(repl='```\n', string=line) line = line.replace('', '_').replace('', '_') + + lline = list(line) + for match in RE_INTERNAL_LINK.finditer(line): + a, b = match.span() + fname, txt = match.groups() + txt = (txt or fname).lstrip('|') + lline[a: b] = list('[{}]({})'.format(txt, link_to_fname(fname))) + + line = ''.join(lline) + line = line.replace('>', '>').replace('<', '<').replace('&', '&') + fout.write(prefix + line + '\n') @@ -47,10 +79,12 @@ def write_page(title, text, sha1): with open(sys.argv[1], 'rt') as f: soup = BS(f.read(), "xml") +already_done = get_file_names('./docs') + pages = soup.find_all('page') for page in pages: title = page.title.text if not title.startswith('ZX BASIC:'): continue title = title[9:] - write_page(title, page.text, page.sha1.text) + write_page(title, page.text, page.sha1.text, already_done) From 2677a7c135fc220ea120ec03dc5f927fd6f7c4d2 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Fri, 13 Sep 2019 22:55:54 +0200 Subject: [PATCH 003/139] Add Identifier.md page This is the list of reserved identifiers --- doc/docs/identifier.md | 132 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 doc/docs/identifier.md diff --git a/doc/docs/identifier.md b/doc/docs/identifier.md new file mode 100644 index 000000000..2419e8112 --- /dev/null +++ b/doc/docs/identifier.md @@ -0,0 +1,132 @@ +#Identifier + + +Identifiers are used in your ZX BASIC program to define ''variable names'', ''function names'', ''subroutine names'' and ''[labels](labels.md)''. ZX Basic identifiers **must** start with a letter (a..z / A..Z) followed by an arbitrary number of letters and or digits. Original Sinclair BASIC allows spaces within variable names, but ZX BASIC does not (in fact, I found it a bit confusing!) + +Some identifiers are **reserved words**. Most of them are either BASIC ''statements'' or ''functions''. Functions return a value to be used in an ''expression'' whilst statements do not. + +Note that there are a number of common statements that you may find in ZX BASIC programs that are not technically reserved words, but library functions. Some of the internal libraries form functions that may overlap with your subroutine and function names (such as POS). So while they may not be technically reserved, you should consider the library function names as ones you should avoid. Also, some Sinclair Basic statements are implemented as library functions, so you should be especially aware of identifiers of this type, such as INPUT, POINT and ATTR. + +## Reserved Identifiers + +The following identifiers are ''reserved words'', and can't be used as variables, functions or labels. Reserved identifiers are ''case insensitive'' (it doesn't matter whether you write them in upper or lower case letters, or a mix of them). So **PRINT**, **print** and **PrInT** means all the same in ZX BASIC. On the other hand, non-reserved words can be either case sensitive or not (depending on the [options](options.md)) in effect. + +Identifiers shown in bold are taken from the Sinclair BASIC (beware their meaning here might be different, however). Some of them has been marked as ''statements'', ''functions'' or ''operators'': + +* **[ABS](abs.md)** **(function)** +* **[ACS](acs.md)** **(function)** +* **[AND](operators#logical_operators.md)** **(operator)** +* [ALIGN](align.md) **(special)** +* [ASM](asm.md) **(special)** +* **[ASN](asn.md)** **(function)** +* **[AT](at.md)** +* **[ATN](atn.md)** **(function)** +* **[bAND](bitwiselogic.md)** **(operator)** +* **[bNOT](bitwiselogic.md)** **(operator)** +* **[bOR](bitwiselogic.md)** **(operator)** +* **[bXOR](bitwiselogic.md)** **(operator)** +* **[BEEP](beep.md)** **(statement)** +* [BOLD](bold.md) +* **[BORDER](border.md)** **(statement)** +* **[BRIGHT](bright.md)** **(statement)** +* [ByRef](byref.md) +* [ByVal](byval.md) +* [CAST](cast.md) **(function)** +* **[CHR](chr.md)** **(function)** (can also be written as **CHR$**) +* **[CIRCLE](circle.md)** **(statement)** +* **[CLS](cls.md)** **(statement)** +* **[CODE](code.md)** **(function)** +* [CONST](const.md) +* **[CONTINUE](continue.md)** **(statement)** +* **[COS](cos.md)** **(function)** +* **[DECLARE](declare.md)** **** +* **[DIM](dim.md)** **(statement)** +* [DO](do.md) **(statement)** +* **[DATA](data.md)** **(statement)** +* **[DRAW](draw.md)** **(statement)** +* [ELSE](if.md) +* [ELSEIF](if.md) +* [END](end.md) +* [EXIT](exit.md) **(statement)** +* **[EXP](exp.md)** **(function)** +* [FastCall](fastcall.md) +* **[FLASH](flash.md)** **(statement)** +* **[FOR](for.md)** **(statement)** +* [FUNCTION](function.md) +* **[GO TO](goto.md)** o[GOTO](goto.md)]] **(statement)** +* **[GO SUB](gosub.md)** o[GOSUB](gosub.md)]] **(statement)** +* **[IF](if.md)** **(statement)** +* **[IN](in.md)** **(function)** +* **[INK](ink.md)** **(statement)** +* **[INKEY](inkey.md)** **(function)** (can also be written as **INKEY$**) +* **[INT](int.md)** **(function)** +* **[INVERSE](inverse.md)** **(statement)** +* [ITALIC](italic.md) +* [LBOUND](lbound.md) **** +* **[LET](let.md)** **(statement)** +* **[LEN](len.md)** **(function)** +* **[LN](ln.md)** **(function)** +* **[LOAD](load.md)** **(statement)** +* [LOOP](do.md) **(statement)** +* [MOD](operators#arithmetic_operators.md) **(operator)** +* **[NEXT](for.md)** **(statement)** +* **[NOT](operators#logical_operators.md)** **(operator)** +* **[OR](operators#logical_operators.md)** **(operator)** +* **[OVER](over.md)** **(statement)** +* **[OUT](out.md)** **(statement)** +* **[PAPER](paper.md)** **(statement)** +* **[PAUSE](pause.md)** **(statement)** +* **[PEEK](peek.md)** **(function)** +* **[PI](pi.md)** **** +* **[PLOT](plot.md)** **(statement)** +* **[POKE](poke.md)** **(statement)** +* **[PRINT](print.md)** **(statement)** +* **[RANDOMIZE](randomize.md)** **(statement)** +* **[READ](read.md)** **(statement)** +* **[REM](comments.md)** **(commentary)** (can also be written as ') +* **[RESTORE](restore.md)** **(statement)** +* **[RETURN](return.md)** **(statement)** +* **[RND](rnd.md)** **(function)** +* **[SAVE](load.md)** **(statement)** +* **[SGN](sgn.md)** **(function)** +* [SHL or <<](shl.md) (operator) +* [SHR or >>](shl.md) (operator) +* **[SIN](sin.md)** **(function)** +* **[SQR](sqr.md)** **(function)** +* [StdCall](stdcall.md) +* **[STEP](for.md)** +* **[STOP](stop.md)** +* **[STR](str.md)** **(function)** (Can also be written as **STR$**) +* **[SUB](sub.md)** +* **[TAN](tan.md)** **(function)** +* **[THEN](if.md)** +* **[TO](to.md)** +* [UBOUND](ubound.md) **(function)** +* [UNTIL](do.md) **(statement)** +* **[VAL](val.md)** **(function)** +* **[VERIFY](load.md)** **(statement)** +* [WEND](while.md) **(statement)** +* [WHILE](while.md) **(statement)** +* **[XOR](operators#logical_operators.md)** **(operator)** + +##Inbuilt library Functions +You should also avoid defining (with a SUB or FUNCTION command) routines with the following names, as they are available in the internal library for your use, though you are almost certainly going to need to use #include before using them. Note that some Sinclair Basic words are listed here. Some Freebasic commands are also available through #include options for compatibility with freebasic. + +* [ASC (Library Function)](asc.bas.md) **(function)** +* **[ATTR (Library Function)](attr.md)** **(function)** +* **[CSRLIN (Library Function)](csrlin.md)** **(function)** +* [HEX (Library Function)](hex.md) **(function)** +* [HEX16 (Library Function)](hex.md) **(function)** +* **[INPUT (Library Function)](input.md)** **(function)** +* **[GetKey (Library Function)](keys.bas.md)** **(function)** +* **[MultiKeys (Library Function)](keys.bas.md)** **(function)** +* **[GetKeyScanCode (Library Function)](keys.bas.md)** **(function)** +* **[LCase (Library Function)](lcase.md)** **(function)** +* **[UCase (Library Function)](ucase.md)** **(function)** +* **[POINT (Library Function)](point.md)** **(function)** +* **[POS (Library Function)](pos.md)** **(function)** +* **[print42 (Library Subroutine)](print42.bas.md)** **(sub)** +* **[printat42 (Library Subroutine)](print42.bas.md)** **(sub)** +* **[print64 (Library Subroutine)](print64.bas.md)** **(sub)** +* **[printat64 (Library Subroutine)](print64.bas.md)** **(sub)** +* **[SCREEN(Library Function)](screen.md)** **(function)** From e5a76db8c82eb698442ac5112e7f80d5afe2d7ad Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Fri, 13 Sep 2019 23:00:54 +0200 Subject: [PATCH 004/139] add LET command --- doc/docs/index.md | 4 ++-- doc/docs/let.md | 13 +++++++++++++ doc/process_wiki.py | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 doc/docs/let.md diff --git a/doc/docs/index.md b/doc/docs/index.md index b5dcf78c9..8adb2abb3 100644 --- a/doc/docs/index.md +++ b/doc/docs/index.md @@ -1,5 +1,5 @@ #General -* [[ZX BASIC:About|About]] +* [About](about.md)
About the ZX BASIC SDK * [[ZX BASIC:ChangeLog|ChangeLog]] @@ -50,7 +50,7 @@ Get the latest version of ZX BASIC from the [[ZX BASIC:Archive|archive]]. * [[ZX BASIC:Types|Data types]]
Language data types: Instead of working always with Floating Point numbers (also available), there are also some integer types which are faster an take less memory. - * [[ZX BASIC:Identifier|Reserved words]] + * [Reserved words](identifier.md)
Comprehensive list (alphabetically ordered) of identifiers you shouldn't use as a ''variable name''. E.g. `FOR`, `PRINT`. If you want usage instructions on a statement, also look here. # External libraries diff --git a/doc/docs/let.md b/doc/docs/let.md new file mode 100644 index 000000000..5a0a83dd8 --- /dev/null +++ b/doc/docs/let.md @@ -0,0 +1,13 @@ +#LET + +Let sentence is used to assign a value to a variable or array element. It can be omitted. E.g.: +``` +LET a = 5 +``` +which can be also written as: +``` +a = 5 +``` + +##Remarks +* This sentence is 100% Sinclair BASIC Compatible diff --git a/doc/process_wiki.py b/doc/process_wiki.py index e6ba96c7c..fa575d8a6 100644 --- a/doc/process_wiki.py +++ b/doc/process_wiki.py @@ -6,7 +6,7 @@ import re import os -RE_CODE = re.compile('|||') +RE_CODE = re.compile('|||||') RE_INTERNAL_LINK = re.compile(r'\[\[([^]|]+)(\|[^]]+)?\]\]') From 745763ffd38ebd975050c82dcf227f17be26ab1e Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Fri, 13 Sep 2019 23:16:01 +0200 Subject: [PATCH 005/139] Main index updated completely --- doc/docs/index.md | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/doc/docs/index.md b/doc/docs/index.md index 8adb2abb3..c4d8d466f 100644 --- a/doc/docs/index.md +++ b/doc/docs/index.md @@ -2,52 +2,52 @@ * [About](about.md)
About the ZX BASIC SDK -* [[ZX BASIC:ChangeLog|ChangeLog]] +* [ChangeLog](https://github.com/boriel/zxbasic/blob/master/Changelog.md)
A reduced list of changes/bugfixes -* [[ZX BASIC:Installation|Installation]] +* [Installation](installation.md)
How to install the ZX Basic SDK in your system, and prerequisites for doing so. -* [[ZX BASIC:Tools|SDK tools]] +* [SDK tools](tools.md)
Tools available in the SDK. -* [[ZX BASIC:Zxb#Command_Line_Options|Command line options]] +* [Command line options](zxb.md#Command_Line_Options)
Command line options table for the compiler (zxb) # Products -* [[ZX BASIC:Released_Programs|Released programs]] +* [Released programs](released_programs.md)
A list of third-party released programs (mostly games) for the ZX-Spectrum developed with ZX BASIC. # Download -Get the latest version of ZX BASIC from the [[ZX BASIC:Archive|archive]]. +Get the latest version of ZX BASIC from the [archive](archive.md). # Tutorials -* [[ZX BASIC:Tutorials|Programming tutorials]] +* [Programming tutorials](tutorials.md)
A collection of third-party tutorials about development with ZX BASIC. -* [[ZX BASIC:Sample Programs|Sample programs]] +* [Sample Programs](sample_programs.md)
Sample programs you can try to see what ZX BASIC looks like and how fast it runs. -* [[ZX BASIC:Sample Programs#Games|Game examples]] +* [Sample Programs](sample_programs.md#Game Examples)
Some little games examples. #Help and Support -* [http://www.boriel.com/forum/zx-basic-compiler/ Community Forum] -
Have a question? Need help or comment a report a bug? Go to the [http://www.boriel.com/forum/zx-basic-compiler/ ZX BASIC forum] +* [Community Forum](http://www.boriel.com/forum/zx-basic-compiler) +
Have a question? Need help or comment a report a bug? Go to the [ZX BASIC forum](http://www.boriel.com/forum/zx-basic-compiler) #External resources -* Here you are [[ZX BASIC:External_Resources|external resources]]: other tools, IDEs, graphic designers and projects related to ZX BASIC. Have a look! +* Here you are [external resources](external_resources.md): other tools, IDEs, graphic designers and projects related to ZX BASIC. Have a look! #Language Reference -* [[ZX BASIC:Syntax|Language syntax]] +* [Language syntax](syntax.md)
Language Syntax is very close to the original Sinclair BASIC, but it's expanded and enhanced. -* [[ZX BASIC:Types|Data types]] +* [Data types](types.md)
Language data types: Instead of working always with Floating Point numbers (also available), there are also some integer types which are faster an take less memory. * [Reserved words](identifier.md) @@ -55,15 +55,14 @@ Get the latest version of ZX BASIC from the [[ZX BASIC:Archive|archive]]. # External libraries -* [[ZX BASIC:Library|Library]] +* [Library](library.md)
Library of functions and subroutines you can use in your programs. You might find them really useful. # Inline assembler -Embedding inline assembler in your code is pretty easy. There's a [[ZX_BASIC:Tutorials tutorial]] on it. +Embedding inline assembler in your code is pretty easy. There's a [tutorial](tutorial.md) on it. # Compiler internals Only for true hackers: This explains how the compiler does it job, how to expand it, etc. You must be a bit crazy if you enter here... # Other Architectures ZX Basic was designed from the base as a Retargeable Compiler, so it should be not hard to extend it to other architectures. This is `work in progress`. See [[ZX_BASIC:Other architectures|Other Architectures]] for more info. - From 7e85c2b12e818cd15e74b3c538008477acd8ef0b Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Fri, 13 Sep 2019 23:32:11 +0200 Subject: [PATCH 006/139] Add About section --- doc/docs/about.md | 20 ++++++++++++++++++++ doc/process_wiki.py | 21 ++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 doc/docs/about.md diff --git a/doc/docs/about.md b/doc/docs/about.md new file mode 100644 index 000000000..9385b3305 --- /dev/null +++ b/doc/docs/about.md @@ -0,0 +1,20 @@ +#About + + +##About the ZX BASIC Project + +ZX BASIC is a [BASIC](http://en.wikipedia.org/wiki/BASIC) ''cross compiler''. +It will compile BASIC programs (in your PC) for your [ZX Spectrum](http://en.wikipedia.org/wiki/Sinclair_ZX_Spectrum). +ZX BASIC is an SDK entirely written in [python](http://www.python.org). +The SDK is implemented using the [PLY](http://www.dabeaz.com/ply/) (Python Lex/Yacc) compiler tool. +It translates BASIC to Z80 assembler code, so it is easily portable to other Z80 platforms (Amstrad, MSX). +Other non Z80 targets could also be available in the future. + +ZX BASIC syntax tries to maintain compatibility as much as possible with +[Sinclair BASIC](http://en.wikipedia.org/wiki/Sinclair_BASIC), it also have many new features, mostly taken from +[FreeBASIC](http://www.freebasic.net/wiki) dialect. + +###Platform Availability +Since it is written in python, it is available for many platforms, like Windows, Linux and Mac. +You only need to have python installed on these. For windows, there also is an installable (.MSI) _compiled_ +version, which does not need python previously installed. diff --git a/doc/process_wiki.py b/doc/process_wiki.py index fa575d8a6..12ad92f80 100644 --- a/doc/process_wiki.py +++ b/doc/process_wiki.py @@ -8,6 +8,7 @@ RE_CODE = re.compile('|||||') RE_INTERNAL_LINK = re.compile(r'\[\[([^]|]+)(\|[^]]+)?\]\]') +RE_EXTERNAL_LINK = re.compile(r'\[(http://[^ ]+) ([^]]+)\]') def get_file_names(path): @@ -62,14 +63,28 @@ def write_page(title, text, sha1, already_done): line = RE_CODE.sub(repl='```\n', string=line) line = line.replace('', '_').replace('', '_') - lline = list(line) - for match in RE_INTERNAL_LINK.finditer(line): + while True: + match = RE_INTERNAL_LINK.search(line) + if not match: + break + lline = list(line) a, b = match.span() fname, txt = match.groups() txt = (txt or fname).lstrip('|') lline[a: b] = list('[{}]({})'.format(txt, link_to_fname(fname))) + line = ''.join(lline) + + while True: + match = RE_EXTERNAL_LINK.search(line) + if not match: + break + lline = list(line) + a, b = match.span() + link, txt = match.groups() + txt = (txt or link).strip() + lline[a: b] = list('[{}]({})'.format(txt, link)) + line = ''.join(lline) - line = ''.join(lline) line = line.replace('>', '>').replace('<', '<').replace('&', '&') fout.write(prefix + line + '\n') From 0ce9de7d9e757c3a522335e85db25998631a0fd6 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Fri, 13 Sep 2019 23:34:03 +0200 Subject: [PATCH 007/139] Added About section --- doc/mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/mkdocs.yml b/doc/mkdocs.yml index 0204667e6..8fb87da9a 100644 --- a/doc/mkdocs.yml +++ b/doc/mkdocs.yml @@ -1,5 +1,6 @@ site_name: ZX Basic Wiki nav: - Home: index.md + - About: about.md theme: readthedocs From 1c1ade73f2a8d71d812e0f551cbf52292768911a Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Fri, 13 Sep 2019 23:46:48 +0200 Subject: [PATCH 008/139] Remove doble title in READ --- doc/docs/read.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/docs/read.md b/doc/docs/read.md index f1133b161..985a02b04 100644 --- a/doc/docs/read.md +++ b/doc/docs/read.md @@ -1,7 +1,5 @@ #READ -#READ - ##Syntax ``` '''READ''' ''[, , ...]'' From 8f37effad39b94b69dc96363bbc4ebaf756d27ba Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Fri, 13 Sep 2019 23:58:14 +0200 Subject: [PATCH 009/139] Fix link --- doc/docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/docs/index.md b/doc/docs/index.md index c4d8d466f..76ce2c6cd 100644 --- a/doc/docs/index.md +++ b/doc/docs/index.md @@ -31,7 +31,7 @@ Get the latest version of ZX BASIC from the [archive](archive.md). * [Sample Programs](sample_programs.md)
Sample programs you can try to see what ZX BASIC looks like and how fast it runs. -* [Sample Programs](sample_programs.md#Game Examples) +* [Sample Games](sample_programs.md#Game Examples)
Some little games examples. #Help and Support From 468c600c6ed291b651444b4d93e2b47ab831144a Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Fri, 13 Sep 2019 23:58:35 +0200 Subject: [PATCH 010/139] Add 4inarow.bas listing --- doc/docs/4inarow.bas.md | 101 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 doc/docs/4inarow.bas.md diff --git a/doc/docs/4inarow.bas.md b/doc/docs/4inarow.bas.md new file mode 100644 index 000000000..4d9fa50fc --- /dev/null +++ b/doc/docs/4inarow.bas.md @@ -0,0 +1,101 @@ +#4 in a Row + + Program: 4inarow.bas + + This program first appeared in MicroHobby ZX Spectrum Spanish magazine. It has a + nice AI in BASIC that plays smartly against the human in only 16Kb! + +``` + 0 REM From MicroHOBBY magazine, Num. 18, page 27 :') + 1 BORDER 1: PAPER 1: INK 7: CLS : PRINT AT 10,10; FLASH 1;"STOP THE TAPE": PAUSE 200 + 5 DIM M(8,6): DIM p,pp,n as FLOAT + 6 BORDER 1: PAPER 1: INK 6: CLS + 10 LET x=0: LET y=0: LET j=0 + 20 PRINT INK 4;" \ : \: \:'\'' \:'\'.\ : \:'\': \:'\': \:.\.: \:'\': \''\: \:' \: \'. \: \.: \:.\.: \: \:.\.: \: \:.\.. \: \ : \: \'. \: \ : \: \: \ :"; INK 6;AT 21,5;" \* by \{vi}$R\{vn} R.Bernat." + 25 PRINT AT 15,3;"Who starts, You or Me? (y/m).": GOSUB 2800: PRINT AT 15,3;" ": GO SUB 2500 + 30 FOR i=1 TO 8: FOR m=1 TO 6 + 40 LET M(i,m)=0: NEXT m: NEXT i + 100 PLOT 0,16: DRAW 12,16: DRAW 0,100: DRAW 8,0: DRAW 0,-92 + 110 FOR n=1 TO 8: DRAW 8,0,PI: DRAW 0,92: DRAW 8,0: DRAW 0,-92: NEXT n: DRAW 0,-8: DRAW 12,-16: DRAW -25,0: DRAW 0,9: DRAW -110,0: DRAW 0,-9: DRAW -25,0 + 120 PRINT AT 5,1;"\{vi} 1 2 3 4 5 6 7 8 \{vn}" + 450 IF a$="m" THEN GO TO 700: END IF + 480 LET M(5,1)=1: LET xp=5: LET yp=1: LET color=1: GO SUB 3000 + 490 GO TO 700 + 500 PRINT AT 12,20; INK 4; FLASH 1;"THINKING ": LET pp=0 + 510 LET p=0 + 520 FOR i=1 TO 8 + 530 LET x=i: GO SUB 2000 + 540 IF y>6 THEN CONTINUE FOR: END IF: REM NEXT i + 550 LET color=1: GO SUB 1030: PRINT FLASH 1;AT 5,i+20;i + 560 IF psp>p AND psp<30 THEN GO SUB 1600: END IF + 570 IF psp>p THEN LET p=psp: LET xp=x: LET yp=y: END IF + 575 IF psp=.05 THEN CONTINUE FOR: END IF: REM NEXT i + 580 LET color=2: GO SUB 1030: IF psp>=30 THEN LET psp=29.9: GOTO 590: END IF + 585 LET pp=psp:GOSUB 1600:IF psp>=30 THEN LET pp=.05:END IF: LET psp=pp + 590 IF psp>p THEN LET p=psp: LET xp=x: LET yp=y: END IF + 600 NEXT i: PRINT INK 1; FLASH 0;AT 5,20;" " + 610 LET color=1: LET M(xp,yp)=1 + 620 GO SUB 2500: GO SUB 3000: LET j=j+1 + 630 IF p>=30 THEN GO TO 3500: END IF + 640 IF j=48 THEN PRINT AT 12,20;"-Draw-": GO TO 3600: END IF + 700 REM ******************************** YOU PLAY ******************************************* + 701 PRINT INK 4;AT 12,20;"YOUR MOVE" + 710 GOSUB 2700: LET x=VAL a$ + 720 IF x<1 OR x>8 THEN GO TO 710: END IF + 725 LET color=2: GO SUB 2000: IF y>6 THEN PRINT AT 12,20;"Not valid": GO TO 710: END IF + 730 LET yp=y: LET xp=x: LET color=2: GO SUB 3000 + 740 LET M(xp,yp)=2: LET j=j+1 + 750 REM check if you win + 760 GO SUB 1030 + 770 IF psp>=30 THEN GO TO 3550: END IF + 780 IF j=48 THEN PRINT OVER 1;AT 21,0;" ...end": GO TO 3600: END IF + 790 GO TO 500 +1030 LET psp=0: LET np=0 +1040 LET dx=1: LET dy=0: GO SUB 1500 +1050 LET psp=ps +1060 LET dx=-1: LET dy=0: GO SUB 1500 +1070 LET psp=psp+ps +1080 LET dx=0: LET dy=-1: GO SUB 1500 +1090 IF ps>psp THEN LET psp=ps: END IF +1100 LET dx=1: LET dy=-1: GO SUB 1500 +1200 LET np=ps +1210 LET dx=-1: LET dy=1: GO SUB 1500 +1220 LET np=np+ps +1230 IF np>psp THEN LET psp=np: END IF +1240 LET dx=1: LET dy=1: GO SUB 1500 +1250 LET np=ps +1260 LET dx=-1: LET dy=-1: GO SUB 1500 +1270 LET np=np+ps +1280 IF np>psp THEN LET psp=np: END IF +1290 RETURN +1500 LET ps=0: LET xx=x: LET yy=y: LET b=0 +1510 LET xx=xx+dx: LET yy=yy+dy +1520 IF (xx<1) OR (yy<1) OR (xx>8) OR (yy>6) THEN RETURN: END IF +1530 IF M(xx,yy)<>color AND M(xx,yy)<>0 THEN RETURN: END IF +1540 IF M(xx,yy)=color AND b=0 THEN LET ps=ps+10: GO TO 1510: END IF +1550 LET ps=ps+1: LET b=1: GO TO 1510 +1599 REM ****************************************************** +1600 LET M(x,y)=1: LET color=2: LET y=y+1 +1610 GO SUB 1030 +1620 IF psp>=30 THEN LET psp=0.05: END IF +1630 LET y=y-1: LET M(x,y)=0: RETURN +2000 LET cont=0 +2010 LET cont=cont+1 +2020 IF cont>6 THEN LET y=7: RETURN: END IF +2030 IF M(x,cont)<>0 THEN GO TO 2010: END IF +2040 LET y=cont: RETURN +2500 FOR n=1 TO 6: BEEP n*n/100,n: BEEP n/50,n: NEXT n: RETURN +2700 REM Waits for a Key press since we lack the INPUT sentence +2710 LET a$=INKEY$: IF a$="" THEN GO TO 2710: END IF +2720 RETURN +2800 GOSUB 2700: IF a$ <> "y" AND a$ <> "m" THEN GOTO 2800: END IF +2810 RETURN +3000 IF color=1 THEN INK 7: END IF +3005 IF color=2 THEN INK 2: END IF +3010 LET xx=((xp*2)+1)*8: LET yy=((yp*2)+3)*8 +3020 FOR n=1 TO 7: CIRCLE xx,yy,n: NEXT n: INK 7 +3030 RETURN +3500 PRINT INK 2;" \{vi}\ \::\::\ \::\ \ \ \ \::\::\::\ \ \ \:: \:: \.'\::\ \::\ \ \ \::\::\::\::\:: \::\:: \::\:: \::\::\:: \::\::\:: \:: \:: \::\.' \:: \:: \::\::\::\::\::\ \::\::\:: \::\:: \::\::\:: \:: \:: \:: \::\:: \::\ \::\ \::\::\::\::\:: \::\::\:: \::\::\:: \:: \:: \:: \::\:: \::\ \ \ \{vn}": GO TO 3600 +3550 PRINT INK 2;"\::\::\:: \::\ \:: \::\::\:: \::\::\:: \::\'.\ \:: \::\::\:: \::\::\::\ \ \ \::\ \ \::\ \::\ \ \ \::\ \ \ \::\ \::\ \::\ \'.\::\ \::\ \::\ \'.\..\ \ \ \ \::\ \ \:: \:: \:: \:: \::\::\::\ \::\ \ \::\ \::\::\::\ \ \ \'. \:: \::\::\::\ \ \ \::\::\::\ \::\ \::\ \::\ \ \::\ \::\ \::\ \::\::\::" +3600 PRINT "Play Again? (y/n)": GOSUB 2700: IF a$="y" THEN GO TO 6: END IF: IF a$<>"n" THEN GOTO 3600: END IF +``` From 6adcfb6ca2950bf9e708fe3fb8e8355e513c419f Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 00:04:26 +0200 Subject: [PATCH 011/139] Add Sample Programs page --- doc/docs/sample_programs.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 doc/docs/sample_programs.md diff --git a/doc/docs/sample_programs.md b/doc/docs/sample_programs.md new file mode 100644 index 000000000..e0c68519f --- /dev/null +++ b/doc/docs/sample_programs.md @@ -0,0 +1,36 @@ +#Sample Programs + +##Examples + +Tutorials and examples are the fastest way (in my opinion) to learn a new language. +Well, ZX BASIC is not so _new_ if you are used to Sinclair BASIC. +The following is a list of examples, some of them already bundled with +the ZX BASIC distribution in the `examples/` directory: + +* [CIRCLE.BAS](circle.bas.md) +
Draws a circle pixel by pixel using [PLOT](plot.md) primitive +* [CLOCK.BAS](clock.bas.md) +
Sample clock which uses the FRAMES variable (taken from the ZX Spectrum 48K user manual) +* [CLOCK2.BAS](clock2.bas.md) +
Like above, but a bit improved. +* [COLORS.BAS](colors.bas.md) +
Colors example from the ZX Spectrum user manual +* [LINES.BAS](lines.bas.md) +
Random color lines example from the ZX Spectrum 48K user manual. +* [FACT.BAS](fact.bas.md) +
Factorial ''recursive'' test. +* [FREREGUSTAV.BAS](freregustav.bas.md) +
A sound demo (taken from the ZX Spectrum 48K user manual) +* [FLAG.BAS](flag.bas.md) +
UK Flag drawing (taken from the ZX Spectrum 48K / 128K user manual) +* [FRACTAL.BAS](fractal.bas.md) +
Mandelbrot fractal by [Britlion](user
britlion.md) + +###Games +* [SNAKE.BAS](snake.bas.md)
+The snake game by Federico J. Álvarez Valero (2003-02-05) (English version) + +* [4INAROW.BAS](4inarow.bas.md)
+A _4 in a Row_ program with A.I. that plays against you and fit in just 16Kb. Published on the 80's in the Spanish [MicroHobby magazine, issue 18](http://www.microhobby.org/numero018.htm) + + From d4891df6d92cb37faa200157a3612d06348442e6 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 00:04:34 +0200 Subject: [PATCH 012/139] Add DRAW page --- doc/docs/draw.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ doc/mkdocs.yml | 3 +++ 2 files changed, 51 insertions(+) create mode 100644 doc/docs/draw.md diff --git a/doc/docs/draw.md b/doc/docs/draw.md new file mode 100644 index 000000000..0118f3556 --- /dev/null +++ b/doc/docs/draw.md @@ -0,0 +1,48 @@ +#DRAW + + +##Syntax + +``` + DRAW dx, dy [, arc] +``` + or +``` + DRAW ; dx, dy [, arc] +``` +Draws a _straight line_ starting from the current drawing coordinates (x, y) +(see [PLOT](plot.md)) to `(x + dx, y + dy)` position. Coordinate `(0, 0)` +designates bottom-left screen corner. Drawing coordinates are updated +to the last position. + +**DRAW** is enhanced in ZX BASIC to allow drawing on the last two screen rows (this was not possible in Sinclair BASIC). So now we have 16 lines more (192 in total). Sinclair BASIC only used top 176 scan lines. This means that in Sinclair BASIC +``` +PLOT x0, y0: DRAW x, y +``` + +is equivalent in ZX BASIC to +``` +PLOT x0, y0 + 16: DRAW x, y +``` + + +**Remark**: This primitive uses Bresenham's algorithm for faster drawing instead of ROMs implementation. + +###Drawing Arcs +When used with 3 parameters it draws arcs the same way the Sinclair BASIC version does, +but again the 192 scan-lines are available. + +``` +DRAW dx, dy, arc +``` +The above will draw an arc from the current position to (x + dx, y + dy) position, with a curve of ''arc'' radians. This routine also have some strange behaviors. High values of arc draws strange patterns. + +###Remarks + +* This function is not strictly Sinclair BASIC compatible since it uses all 192 screen lines instead of top 176. +If you translate **PLOT**, **DRAW** & **CIRCLE**, commands from Sinclair BASIC _as is_ +your drawing will be _shifted down_ 16 pixels. + +###See Also +* [PLOT](plot.md) +* [CIRCLE](circle.md) diff --git a/doc/mkdocs.yml b/doc/mkdocs.yml index 8fb87da9a..10f70bd20 100644 --- a/doc/mkdocs.yml +++ b/doc/mkdocs.yml @@ -4,3 +4,6 @@ nav: - About: about.md theme: readthedocs + +markdown_extensions: + - fenced_code From 5be3ce6cae7f8651127d0f4ac50075bb26613ee4 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 00:12:39 +0200 Subject: [PATCH 013/139] Add trigonometric functions --- doc/docs/acs.md | 32 ++++++++++++++++++++++++++++++++ doc/docs/asn.md | 33 +++++++++++++++++++++++++++++++++ doc/docs/atn.md | 31 +++++++++++++++++++++++++++++++ doc/docs/cos.md | 34 ++++++++++++++++++++++++++++++++++ doc/docs/sin.md | 30 ++++++++++++++++++++++++++++++ doc/docs/tan.md | 34 ++++++++++++++++++++++++++++++++++ doc/process_wiki.py | 2 ++ 7 files changed, 196 insertions(+) create mode 100644 doc/docs/acs.md create mode 100644 doc/docs/asn.md create mode 100644 doc/docs/atn.md create mode 100644 doc/docs/cos.md create mode 100644 doc/docs/sin.md create mode 100644 doc/docs/tan.md diff --git a/doc/docs/acs.md b/doc/docs/acs.md new file mode 100644 index 000000000..931aa6737 --- /dev/null +++ b/doc/docs/acs.md @@ -0,0 +1,32 @@ +#ACS + +##Syntax + +``` +ACS(numericExpression) +``` + + +##Description + +Returns the arc cosine value of the given argument. +Argument must be a numeric expression. Returned value type is [Float](types#float.md). + +##Examples + +``` +REM Arc cosine value +PRINT "Arc Cosine value of a is "; ACS(a) +``` + + +##Remarks + +* This function is 100% Sinclair BASIC Compatible +* If the given argument type is not float, it will be [converted](cast.md) to float before operating with it. + +##See also + +* [SIN](sin.md) and [ASN](asn.md) +* [TAN](tan.md) and [ATN](atn.md) +* [COS](cos.md) diff --git a/doc/docs/asn.md b/doc/docs/asn.md new file mode 100644 index 000000000..4ef4ed816 --- /dev/null +++ b/doc/docs/asn.md @@ -0,0 +1,33 @@ +#ASN + + +##Syntax + +``` +ASN(numericExpression) +``` + +##Description + +Returns the arc sine value of the given argument. +Argument must be a numeric expression. Returned value type is [float](types#float.md). + +##Examples + +``` +REM Arc sine value +PRINT "Arc Sine value of a is "; ASN(a) +``` + + +##Remarks + +* This function is 100% Sinclair BASIC Compatible +* If the given argument type is not float, it will be [converted](cast.md) to float before operating with it. + +##See also + +* [COS](cos.md) and [ACS](acs.md) +* [TAN](tan.md) and [ATN](atn.md) +* [SIN](sin.md) + diff --git a/doc/docs/atn.md b/doc/docs/atn.md new file mode 100644 index 000000000..486b197e0 --- /dev/null +++ b/doc/docs/atn.md @@ -0,0 +1,31 @@ +#ATN + +##Syntax + +``` +ATN(numericExpression) +``` + + +##Description + +Returns the arc tangent value of the given argument. +Argument must be a numeric expression. Returned value type is [float](types#float.md). + +##Examples + +``` +REM Arc tangent value +PRINT "Arc Tangent value of a is "; ATN(a) +``` + +##Remarks + +* This function is 100% Sinclair BASIC Compatible +* If the given argument type is not float, it will be [converted](cast.md) to float before operating with it. + +##See also + +* [COS](acs.md) and [ACS](asn.md) +* [SIN](sin.md) and [ASN](asn.md) +* [TAN](tan.md) diff --git a/doc/docs/cos.md b/doc/docs/cos.md new file mode 100644 index 000000000..08a9163ca --- /dev/null +++ b/doc/docs/cos.md @@ -0,0 +1,34 @@ +#COS + +##Syntax + +``` +COS(numericExpression) +``` + + +##Description + +Returns the cosine value of the given argument. +Argument must be a numeric expression in radians units. Returned value type is [float](types#float.md). + +##Examples + +``` +REM Cosine value +PRINT "Cosine value of a is "; COS(a) +``` + + +##Remarks + +* This function is 100% Sinclair BASIC Compatible +* If the given argument type is not float, it will be [converted](cast.md) to float before operating with it. + +##See also + +* [SIN](sin.md) and [ASN](asn.md) +* [TAN](tan.md) and [ATN](atn.md) +* [ACS](acs.md) +* Faster library option for lower accuracy trigonometry for games: [FCOS](fsin.bas.md) + diff --git a/doc/docs/sin.md b/doc/docs/sin.md new file mode 100644 index 000000000..5bdc707e9 --- /dev/null +++ b/doc/docs/sin.md @@ -0,0 +1,30 @@ +#SIN + +##Syntax + +``` +SIN(numericExpression) +``` + +##Description + +Returns the sine value of the given argument. +Argument must be a numeric expression in radians units. Returned value type is [float](types#float.md). + +##Examples + +``` +REM Sine value +PRINT "Sine value of a is "; SIN(a) +``` + +##Remarks +* This function is 100% Sinclair BASIC Compatible +* If the given argument type is not float, it will be [converted](cast.md) to float before operating with it. + +##See also + +* [COS](cos.md) and [ACS](acs.md) +* [TAN](tan.md) and [ATN](atn.md) +* [ASN](asn.md) +* Faster library option for lower accuracy trigonometry for games: [FSIN](fsin.bas.md) diff --git a/doc/docs/tan.md b/doc/docs/tan.md new file mode 100644 index 000000000..2e39a0fe2 --- /dev/null +++ b/doc/docs/tan.md @@ -0,0 +1,34 @@ +#TAN + + +##Syntax + +``` +TAN(numericExpression) +``` + + +##Description + +Returns the tangent value of the given argument. +Argument must be a numeric expression in radians units. Returned value type is [float](types#float.md). + +##Examples + +``` +REM Tangent value +PRINT "Tangent value of a is "; TAN(a) +``` + + +##Remarks + +* This function is 100% Sinclair BASIC Compatible +* If the given argument type is not float, it will be [converted](cast.md) to float before operating with it. + +##See also + +* [SIN](sin.md) and [ASN](asn.md) +* [COS](cos.md) and [ACS](acs.md) +* [ATN](atn.md) +* Faster library option for lower accuracy trigonometry for games: [FTAN](fsin.bas.md) diff --git a/doc/process_wiki.py b/doc/process_wiki.py index 12ad92f80..60a0dd8d1 100644 --- a/doc/process_wiki.py +++ b/doc/process_wiki.py @@ -86,6 +86,8 @@ def write_page(title, text, sha1, already_done): line = ''.join(lline) line = line.replace('>', '>').replace('<', '<').replace('&', '&') + if line.startswith('*') and line[:2] not in ('* ', '**'): + line = '* {}'.format(line[1:]) fout.write(prefix + line + '\n') From 5c932b5f87fc274fb9de10c2175fad35c26ad97c Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 00:14:31 +0200 Subject: [PATCH 014/139] Add fractal.bas example by Britlion --- doc/docs/fractal.bas.md | 81 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 doc/docs/fractal.bas.md diff --git a/doc/docs/fractal.bas.md b/doc/docs/fractal.bas.md new file mode 100644 index 000000000..564bb3b16 --- /dev/null +++ b/doc/docs/fractal.bas.md @@ -0,0 +1,81 @@ +#Fractal.bas + +``` +Program: fractal.bas by @Britlion +``` + + +``` +#define width 256 +#define height 192 + +DIM x,y as FIXED +DIM xstart,xstep,ystart,ystep as FIXED +DIM xend,yend as FIXED +DIM z,zi,newz,newzi as FIXED +DIM colour as byte +DIM iter as uInteger +DIM col as uInteger +DIM i,k as uByte +DIM j as uInteger +dim inset as uByte + +xstart=-1.6 +xend=0.65 +ystart=-1.15 +yend=-ystart +iter=24 + +xstep=(xend-xstart)/width +ystep=(yend-ystart)/height + +'Main loop +x=xstart +y=ystart + +border 0 +paper 0 +ink 7 +CLS + +for i=0 to ( height -1 )/2 +1 + + for j=0 to width -1 + z=0 + zi=0 + inset=1 + for k=0 to iter + ';z^2=(a+bi)*(a+bi) = a^2+2abi-b^2 + newz=(z*z)-(zi*zi)+x + newzi=2*z*zi+y + z=newz + zi=newzi + + if (z*z)+(zi*zi) > 4 then + inset=0 + colour=k + goto screen + END IF + next k + +screen: + + if NOT inset then + if colour BAND 1 THEN + plot j,i + plot j,192-i + END IF + end if + + x=x+xstep + next j + + y=y+ystep + x=xstart + +print at 23,0;CAST(uinteger,i)*200/height;"%" +next i + +BEEP 1,1 +PAUSE 0 +``` From dc80be900b7da399b7db2ead3189f0d853e6b8cc Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 00:17:24 +0200 Subject: [PATCH 015/139] Add BEEP command --- doc/docs/beep.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 doc/docs/beep.md diff --git a/doc/docs/beep.md b/doc/docs/beep.md new file mode 100644 index 000000000..31dc7238f --- /dev/null +++ b/doc/docs/beep.md @@ -0,0 +1,22 @@ +#BEEP + + +##Syntax + +``` +BEEP , +``` + +##Description + +Emits a sound using the ZX Spectrum speaker. The ''duration'' is given in seconds, and the ''pitch'' is given in semitones above middle C using negative numbers for notes below middle C. + +##Remarks + +* This function is 100% Sinclair BASIC Compatible + +##See also + +* Example of using BEEP: [FrereGustav.bas](freregustav.bas.md) + + From b541ff6f2a0cd38c17eb7a6fdb772715a6eecfef Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 00:39:21 +0200 Subject: [PATCH 016/139] Add Syntax for the language Also adds it to the Nav Bar --- doc/docs/syntax.md | 174 ++++++++++++++++++++++++++++++++++++++++++++ doc/mkdocs.yml | 1 + doc/process_wiki.py | 1 + 3 files changed, 176 insertions(+) create mode 100644 doc/docs/syntax.md diff --git a/doc/docs/syntax.md b/doc/docs/syntax.md new file mode 100644 index 000000000..5c4b68330 --- /dev/null +++ b/doc/docs/syntax.md @@ -0,0 +1,174 @@ +#Syntax + +##Introduction + +This page is about the ZX BASIC language syntax. It is part of the Language Reference Guide. +ZX BASIC aims to be a modern BASIC dialect but tries to keep some (many) of the original Sinclair BASIC features for the nostalgic. So you can use it in both ways. + +The BASIC dialect is mainly based in [FreeBasic](http://www.zxbasic.net/wiki/). Many of the language specifications have been taken from there. + +##ZX BASIC syntax overview + +If you have ever programmed in legacy BASIC (either Sinclair BASIC or any other flavour) you will already know that BASIC languages are **line oriented**. Each sentence or group of sentences are separated in lines (ended with a carriage return). + +Nowadays this is not necessary, but ZX BASIC allows you to use lines and line numbers for compatibility (and nostalgic!) reasons: + +``` +10 REM This is a comment. +20 PRINT "Hello world!" +``` + + +Other than that, line numbers are ignored (well, not exactly: line numbers are treated as [labels](labels.md)). +So the previous BASIC program could be also written this way: + +``` +REM This is a comment. +PRINT "Hello world!" +``` + + +###Lines and sentences + +Since ZX BASIC is **line oriented** this implies that the ''end of line'' (also known as ''carriage return'' or '''') is taken into account during syntax checking, and you cannot break lines in the middle of a sentence: + +``` +REM The following line has a syntax error +PRINT + "Hello world!" +``` + + +Other languages (like C or Pascal) allows this because they're not line oriented. If you need to break a line, use the +underline character (**_**) at the end of line to tell the compiler the current line continues in the next one: + +``` +REM The following line is broken into two, but it's ok +PRINT _ + "Hello world!" +``` +(Notice the **_** character at the end of the second line). + +###Sentences and block of sentences + +A sentence is the simplest BASIC instruction (e.g. **[PRINT](print.md)**). Sentences might contain ''arguments'' and can be separated by a ''colon'' (:) as in Sinclair BASIC or by ''end of line''. A ''block of sentences'' are just a group of sentences one after another. Usually the reserved word **END** denotes the end of such block. E.g. + +``` +IF a > b THEN + PRINT "A is greater than B" + PRINT "and that's all" +END IF +``` + +In the previous example, everything between **[THEN](if.md)** and **[END IF](if.md)** conforms a ''block of sentences''. Some sentences (like the shown **[IF](if.md)**) works with sentences block. They are called ''compound sentences''. + +###Identifiers + +[Identifiers](identifier.md) are used to denote variables, labels, sentences and functions. Some identifiers are +_reserved_ for ZX BASIC statements (e.g. **[PRINT](print.md)**) or predefined functions (e.g. **[COS](cos.md)**). +Proceed to the [identifiers](identifier.md) page for a list of _reserved words_. + +###Numbers + +Decimal numbers should be entered as one would normally expect. The compiler also accepts hexadecimal and binary numbers. + +* For hexadecimal numbers, use either a trailing h (e.g. `9Ch`) or a leading dollar symbol (`$9C`). +* For binary numbers, use either a trailing b (e.g. `11001001b`) or a leading percent symbol (`%11001001`) + +``` + Note: Take care of using a trailing h for hexadecimals starting with a letter. + E.g. C9h is an identifier! +``` +When writing an hexadecimal number with a trailing h, if the number begins with a letter (e.g. C9h), prefix it with a 0 digit. +So, `C9` hex should be written as `0C9h` or `$C9`. + +###Comments + +As shown in the previous examples, the ''reserved word'' **REM** is used for comments and ''remarks''. However, you can also use the single quote (') character for comments instead of **REM**: + +``` +10 REM This is a comment +20 'This is also a comment +30 PRINT "Hello world!" +``` + +You can also comment a block of lines, and even comment _broken_ lines. +Read [comments](comments.md) article for more information. + +### Graphic characters + +The ZX Spectrum had two types of graphics characters; block graphics and user-defined graphics (UDG). +The method for entering them into ZX BASIC is the same as that found in the .bas file format created by Paul Dunn +for his BASin BASIC IDE. + +UDG can be entered into the code with an escape before the letter that corresponds to the udg. +For the first udg, for example, use \A + +Block graphics characters can be entered into code with a similar escape sequence. +The \ is used to escape the characters and a combination of the characters `:` (colon), `'` (apostrophe) and `.` (dot) +are used to represent the blocks. So a full solid block would be `\::` An "L" shaped block would be `\:.` and an "r" +shaped one would be `\:'`. The system is fairly intuitive when you see how it works. +To put it another way, a block graphic is an escape ( \ ) followed by two characters. +The `:` represents both top and bottom as ink; `'` represents top only, and `.` represents bottom only. +A blank space represents both blocks blank or paper. The complete list of possibilities is this: + +``` + \·· (Space, Space) CHR$(128) + \·' (Space, Apostrophe) CHR$(129) + \'· (Apostrophe, Space) CHR$(130) + \'' (Apostrophe, Apostrophe) CHR$(131) + \·. (Space, Period) CHR$(132) + \·: (Space, Colon) CHR$(133) + \'. (Apostrophe, Period) CHR$(134) + \': (Apostrophe, Period) CHR$(135) + \.· (Period, Space) CHR$(136) + \.' (Period, Apostrophe) CHR$(137) + \:· (Colon, Space) CHR$(138) + \:' (Colon, Apostrophe) CHR$(139) + \.. (Period, Period) CHR$(140) + \.: (Period, Colon) CHR$(141) + \:. (Colon, Period) CHR$(142) + \:: (Colon, Colon) CHR$(143) +``` + + +### Other escaped characters +``` + \\ The \ backslash symbol. + \` The £ pound sterling symbol. (Just backtick ` works too) + \#nnn Any character, where nnn is a decimal number in the range 000 to 255. + \* The (C) Copyright Symbol. +``` + +### Embedded color control codes + +Sometimes, in a program, one might wish to embed colour control codes into strings for printing. This is possible using the same schema as Paul Dunn's BASIC IDE BASin. + +The escape sequences for control characters are as follows: + +* `\{iN}` Ink colour N, where N is in the range 0 to 8. +* `\{pN}` Paper colour N, where N is in the range 0 to 8. +* `\{bN}` Bright N, where N is 0 or 1. +* `\{fN}` Flash N, where N is 0 or 1. + +So, for example, an embedded control code for red ink would be `\{i2}`. +8 is used to signify "transparent" (i.e. do not change the ink/paper value in the square being printed) + +##Data types + +ZX Basic [types](types.md) ranges from 8 to 32 bits for integer formats. It also supports floating point format (the ZX ROM 40 bits floating point from the ROM FP Calculator) and ''Fixed'' for fixed point arithmetic. See [types page](types.md) for more information. + +## Inline assembly + +The Compiler supports inline assembly, starting with the ASM directive and ending with an END ASM directive. Between these two, raw z80 assembly becomes legal. This assembly data will be passed directly to the assembler as part of the compiled assembler source. + +Note that the rules for assembly change dramatically from standard ZX BASIC, and this mode is not for the unwary. + +**Of note** + +* Comments are begun with a semicolon (`;`) instead of an apostrophe (`'`). +* The assembler supports `DEFB` to define comma separated bytes, or a quote delimited string. +* The assembler supports `DEFS n,B` to shortcut a series of n bytes of value B. +* The assembler supports it's own set of #directives, including [incbin](zxbasm:incbin.md) + +A novice user of assembly would be well advised to examine code held in the [library](zx_basic:library.md) for examples and usage. diff --git a/doc/mkdocs.yml b/doc/mkdocs.yml index 10f70bd20..498feef21 100644 --- a/doc/mkdocs.yml +++ b/doc/mkdocs.yml @@ -1,6 +1,7 @@ site_name: ZX Basic Wiki nav: - Home: index.md + - Syntax: syntax.md - About: about.md theme: readthedocs diff --git a/doc/process_wiki.py b/doc/process_wiki.py index 60a0dd8d1..819d358a5 100644 --- a/doc/process_wiki.py +++ b/doc/process_wiki.py @@ -60,6 +60,7 @@ def write_page(title, text, sha1, already_done): prefix = prefix + '#' line = line.replace("'''", '**') + line = line.replace("''", '_') line = RE_CODE.sub(repl='```\n', string=line) line = line.replace('', '_').replace('', '_') From 9587b0873047fa598b6ef91135174d703f011a04 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 00:42:31 +0200 Subject: [PATCH 017/139] Fix 4 en raya Link --- doc/docs/sample_programs.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/docs/sample_programs.md b/doc/docs/sample_programs.md index e0c68519f..b13e30314 100644 --- a/doc/docs/sample_programs.md +++ b/doc/docs/sample_programs.md @@ -31,6 +31,6 @@ the ZX BASIC distribution in the `examples/` directory: The snake game by Federico J. Álvarez Valero (2003-02-05) (English version) * [4INAROW.BAS](4inarow.bas.md)
-A _4 in a Row_ program with A.I. that plays against you and fit in just 16Kb. Published on the 80's in the Spanish [MicroHobby magazine, issue 18](http://www.microhobby.org/numero018.htm) - - +A _4 in a Row_ program with A.I. that plays against you and fit +in just 16Kb. Published on the 80's in the Spanish +[MicroHobby magazine, issue 18](https://microhobby.speccy.cz/mhforever/numero018.htm) From 21b48071a0f7fb02d3a25cd4ce2e1c4db51f096d Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 10:40:12 +0200 Subject: [PATCH 018/139] Add FOR .. NEXT instruction --- doc/docs/for.md | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 doc/docs/for.md diff --git a/doc/docs/for.md b/doc/docs/for.md new file mode 100644 index 000000000..5ca688e46 --- /dev/null +++ b/doc/docs/for.md @@ -0,0 +1,54 @@ +#FOR ... NEXT + +##Syntax + +``` + FOR iterator = startvalue TO endvalue [ STEP stepvalue ] + [ sentences ] + NEXT [ iterator ] +``` +##Parameters + +* _iterator_: a variable identifier that is used to iterate from an initial value to an end value. +* _datatype_: If specified, the variable iterator will automatically be declared with the type datatype. +* _startvalue_: an expression that denotes the starting value of the iterator. +* _endvalue_: an expression used to compare with the value of the iterator. +* _stepvalue_: an expression that is added to the iterator after every iteration. + +##Description + +A **For...Next** loop initializes _iterator_ to _startvalue_, then executes the _sentences_, incrementing _iterator_ by _stepvalue_ until it reaches or exceeds _endvalue_. If _stepvalue_ is not explicitly given it will set to 1. + +##Examples + +``` +FOR i = 1 TO 10: PRINT i: NEXT +``` + +##Differences From Sinclair Basic +* The variable name after the NEXT statement is not required. + +* Note that variable types can cause issues with ZX Basic For...Next Loops. If the upper limit of the iterator exceeds the upper limit of the variable type, the loop may not complete. +For example: +``` +DIM i as UByte + +FOR i = 1 to 300 + PRINT i +NEXT i +``` + +Clearly, since the largest value a byte can hold is 255, it's not possible for i in the above example to exceed 300. +The variable will "wrap around" to 0 and as a result, the loop will not ever terminate. +This can happen in much more subtle ways when STEP is used. +There has to be "room" within the variable type for the iterator to exceed the terminator when it is being +incremented by "STEP" amounts. + +##See Also + +* [WHILE ... END WHILE](while.md) +* [DO ... LOOP](do.md) +* [IF ... END IF](if.md) +* [EXIT](exit.md) +* [CONTINUE](continue.md) +* [Sinclair Basic Manual](http://www.worldofspectrum.org/ZXBasicManual/zxmanchap4.html) From a594d316a33ee4f1eb243f06c8212ed24b87aed2 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 10:43:39 +0200 Subject: [PATCH 019/139] Add WHILE / WEND --- doc/docs/while.md | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 doc/docs/while.md diff --git a/doc/docs/while.md b/doc/docs/while.md new file mode 100644 index 000000000..b16b4e9cc --- /dev/null +++ b/doc/docs/while.md @@ -0,0 +1,50 @@ +#WHILE ... END WHILE + +**WHILE** is a _compound_ statement used to perform loops. The code within a **WHILE** statement will repeat _while_ the given condition is _true_. +If the given _condition_ is false the first time the inner _sentences_ are _never_ executed. + +##Syntax +``` + WHILE expression + sentences + END WHILE +``` +or + +``` + WHILE expression + sentences + WEND +``` +The first form is preferred. + +##Examples +``` +While a < b + Let a = a + 1 + Poke a, 0 +End While +``` + + +An infinite loop: +``` +While 1 + REM An infinite loop. This will issue a warning + Print "Hello world!" +End While +``` + + +**Note**: For infinite loops use [DO ... LOOP](do.md) + +##Remarks +* This statement does not exist in Sinclair Basic. +* **WHILE** can also be used with [DO ... LOOP](do.md). + +##See Also +* [IF ... END IF](if.md) +* [DO ... LOOP](do.md) +* [FOR ... NEXT](for.md) +* [EXIT](exit.md) +* [CONTINUE](continue.md) From e0dc6bf007c71ed6874c1861e5c1aaa75362e6a2 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 10:46:36 +0200 Subject: [PATCH 020/139] Add IF sentence --- doc/docs/if.md | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 doc/docs/if.md diff --git a/doc/docs/if.md b/doc/docs/if.md new file mode 100644 index 000000000..56fdb1234 --- /dev/null +++ b/doc/docs/if.md @@ -0,0 +1,83 @@ +#IF ... END IF + +**IF** is a very powerful control flow sentence that allows you to _make decisions_ under specified contitions. + +##Syntax +``` + IF expression [THEN] sentences [: END IF] + +``` +or + +``` + IF expression [THEN] + sentences + [ELSEIF expression [THEN] sentences] + [ELSEIF expression [THEN] sentences] + ... + [ELSE sentences] + END IF + +``` +###Examples +``` +IF a < 5 THEN PRINT "A is less than five" ELSE PRINT "A is greater than five" +``` + + +Sentences might be in multiple lines: + +``` +If a < 5 Then + Print "A is less than five" + a = a + 5 +Else + Print "A is greater than five" +End If +``` + + +Since **IF** is a _sentence_, it can be nested; however, remember that _every_ **IF** _must be closed with_ **END IF** when the line is splitted after **THEN** (mutiline **IF**): +``` +If a < 5 Then + Print "A is less than five" + If a > 2 Then + Print "A is less than five but greater than 2" + End If +Else If a < 7 Then + Print "A is greater or equal to five, but lower than 7" + Else + Print "A is greater than five" + End If +End If +``` + + +##Using ELSEIF +In the example above, you see that nesting an **IF** inside another one could be somewhat verbose and error prone. It's better to use +the **ELSEIF** construct. So the previous example could be rewritten as: + +``` +If a < 5 Then + Print "A is less than five" + If a > 2 Then + Print "A is less than five but greater than 2" + End If +ElseIf a < 7 Then + Print "A is greater or equal to five, but lower than 7" +Else + Print "A is greater than five" +End If +``` + + +##Remarks +* This sentence is **extended** allowing now multiline IFs and also compatible with the Sinclair BASIC version. +* Starting from version 1.8 onwards the trailing **END IF** is not mandatory for single-line IFs, for compatibility with Sinclair BASIC +* The **THEN** keyword can be omitted, but keep in mind this might reduce code legibility. + +##See Also +* [WHILE ... END WHILE](while.md) +* [DO ... LOOP](do.md) +* [FOR ... NEXT](for.md) + From d08906d1fe00b2a87cdb5029212afb26568043b3 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 10:58:00 +0200 Subject: [PATCH 021/139] Add DO...LOOP --- doc/docs/do.md | 91 +++++++++++++++++++++++++++++++++++++++++++++ doc/process_wiki.py | 4 +- 2 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 doc/docs/do.md diff --git a/doc/docs/do.md b/doc/docs/do.md new file mode 100644 index 000000000..2a3e64478 --- /dev/null +++ b/doc/docs/do.md @@ -0,0 +1,91 @@ +#DO ... LOOP + +**DO** ... **LOOP** is a _compound_ statement used to perform loops. The code within the **DO ... LOOP** statement will be repeated if the given condition is _true_. The loop is executed at less once when the loop condition is written at the end, even if the given _condition_ is false at the first iteration. + +##Syntax +The **DO** ... **LOOP** construct is a very powerful sentence and can be used in up to 5 different ways: + +###Infinite loops +Sometimes we want a loop to repeat forever, no matter what, because we need to exit the loop when an external event happens. For example, we want to repeat forever waiting for a key press. Traditionally we use GOTO for this in Sinclair BASIC. Other languages use WHILE (1), etc. The best way to do this in ZX BASIC is this one: + +``` +DO + [] +LOOP: REM This loop repeats forever. +``` + +This form **loops forever**. It's better to use this form instead of using **STEP** 0 in a **FOR** loop, or a **WHILE** 1 condition loop. The generated code is more efficient. + +###Looping UNTIL + +``` +DO + [] +LOOP UNTIL +``` + + +This form repeats _until_ the given condition is met. The loop is guaranteed to execute at least once regardless of loop exit condition - it is only evaluated at the end of the first loop. + +You can also put the condition at the beginning, this way: + +``` +DO UNTIL + [] +LOOP +``` + + +In this case, the condition is checked first, and the program won't enter to the inner _sentences_ if the condition is not satisfied at first. + +####Example using UNTIL +Example: _Loop until the user press a Key_ + +``` +REM in a single line! +DO LOOP UNTIL INKEY$ <> "" +``` + + +###Looping WHILE + +``` +DO + [] +LOOP WHILE +``` + + +This form repeats _while_ the given condition is true. +The difference with the [WHILE](while.md) sentence is the latter won't execute the inner sentences if _condition_ is false at the start. Remember: **DO**...**LOOP** will execute _sentences_ at least once regardless of the condition upon entry to the loop - it is only evaluated at the end of the first loop. + +You can also put the condition at the beginning, this way: + +``` +DO WHILE + [] +LOOP +``` + + +In this case, the condition is checked first, and the program won't enter to the inner _sentences_ if the condition is not satisfied at first. + +####Example using WHILE +Example: _Loop while there is no key pressed_ + +``` +REM in a single line! +DO LOOP WHILE INKEY$ = "" +``` + + +##Remarks +* This statement does not exist in Sinclair Basic. +* **WHILE** can also be used with [WHILE ... END WHILE](while.md) loops. + +##See Also +* [IF ... END IF](if.md) +* [WHILE ... END WHILE](while.md) +* [FOR ... NEXT](for.md) +* [EXIT](exit.md) +* [CONTINUE](continue.md) diff --git a/doc/process_wiki.py b/doc/process_wiki.py index 819d358a5..095ea0f10 100644 --- a/doc/process_wiki.py +++ b/doc/process_wiki.py @@ -51,7 +51,7 @@ def write_page(title, text, sha1, already_done): fout.write('```\n') verbatim = True elif line and not line.startswith(' '): - fout.write('```\n') + fout.write('\n```') verbatim = False if not verbatim: @@ -61,7 +61,7 @@ def write_page(title, text, sha1, already_done): line = line.replace("'''", '**') line = line.replace("''", '_') - line = RE_CODE.sub(repl='```\n', string=line) + line = RE_CODE.sub(repl='\n```\n', string=line) line = line.replace('', '_').replace('', '_') while True: From 24b7959d0da6da6db1be0d9efd3cdafe999dd40e Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 10:59:50 +0200 Subject: [PATCH 022/139] Add AT document --- doc/docs/at.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 doc/docs/at.md diff --git a/doc/docs/at.md b/doc/docs/at.md new file mode 100644 index 000000000..52471ba1e --- /dev/null +++ b/doc/docs/at.md @@ -0,0 +1,19 @@ +#AT + + +##Description + +**AT** is not a statement, but a _modifier_. +It can be used both as a [PRINT modifier](print#modifiers.md) and a [variable declaration modifier](dim.md). + +##Remarks + +* This identifier is compatible with Sinclair BASIC (see [PRINT](print.md)), but _expands_ it, since it allows positioning at rows 22 and 23 (all 24 rows are available to the programmer). Traditionally, Sinclair BASIC only allows to print at rows 0..21. +* This identifier _expands_ the Sinclair BASIC version when used with [DIM](dim.md) + +##See also + +* [PRINT](print.md) +* [DIM](dim.md) - Variable Declarations +* [POS](pos.md) +* [CSRLIN](csrlin.md) From 94c57fac9c2a6f6c8f75c5fbd83679b8bda42762 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 11:02:17 +0200 Subject: [PATCH 023/139] Add ALIGN asm primitive --- doc/docs/asm/align.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 doc/docs/asm/align.md diff --git a/doc/docs/asm/align.md b/doc/docs/asm/align.md new file mode 100644 index 000000000..0cde3970e --- /dev/null +++ b/doc/docs/asm/align.md @@ -0,0 +1,34 @@ +#ALIGN + + +## Syntax + +``` +ASM +ALIGN +END ASM +``` + +## Description + +This works inside the ASM context, and is an assembler directive. +Moves assembling position forward so the next line begins assembling aligned with a multiple of the given parameter. Useful for aligning data with address and page boundaries. Be aware that this can in theory waste n-1 bytes of memory, as the assembled code can only be moved forwards. Use with caution. + +## Examples + +``` +ASM + ALIGN 256 + DEFB 0,0,0,0,0,0 +END ASM + +ASM + ALIGN 16384 + DEFS 256,0 +END ASM +``` + +The first example will move compilation forward to match the next multiple of 256 bytes. This is useful in machine code routines as it matches a new "high byte" position in memory. That is to say that the data can be addressed by address ??00 - the low byte will be zero. This is often a key optimization for data tables and screen addressing routines. + +Aligning to a 16K (16384) boundary might be useful in 128K programming. + From 63965697b6fa63fb542db57a5f454dfc8f55475c Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 11:04:14 +0200 Subject: [PATCH 024/139] Add BORDER statement --- doc/docs/border.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 doc/docs/border.md diff --git a/doc/docs/border.md b/doc/docs/border.md new file mode 100644 index 000000000..9aecfb7f4 --- /dev/null +++ b/doc/docs/border.md @@ -0,0 +1,39 @@ +#BORDER + +##Syntax +``` +BORDER +``` +This can be used to change the border colour. + +``` +BORDER n +``` +where n is a number between 0 and 7. + + +As the ZX Spectrum manual states: + +``` +0 - black +1 - blue +2 - red +3 - purple, technically called magenta +4 - green +5 - pale blue, technically called cyan +6 - yellow +7 - white +``` + +##Remarks +* This function is 100% Sinclair BASIC compatible. + +##See also +* [PRINT](print.md) +* [PAPER](paper.md) +* [INK](ink.md) +* [BOLD](bold.md) +* [INVERSE](inverse.md) +* [ITALIC](italic.md) +* [OVER](over.md) + From 6d3df40197c7930e2f390322c8e365c0db3d4d11 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 14 Sep 2019 11:52:38 +0200 Subject: [PATCH 025/139] Add RESTORE command --- doc/docs/restore.md | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 doc/docs/restore.md diff --git a/doc/docs/restore.md b/doc/docs/restore.md new file mode 100644 index 000000000..cc0302b7e --- /dev/null +++ b/doc/docs/restore.md @@ -0,0 +1,46 @@ +#RESTORE + + +##Syntax +``` +RESTORE [