can now declare for loop variable on the spot

This commit is contained in:
Irmen de Jong 2018-10-06 22:54:03 +02:00
parent 1d37841575
commit 6edd5f9b30
13 changed files with 178 additions and 268 deletions

View File

@ -253,7 +253,7 @@ branch_stmt : branchcondition EOL? (statement | statement_block) EOL? else_part?
branchcondition: 'if_cs' | 'if_cc' | 'if_eq' | 'if_z' | 'if_ne' | 'if_nz' | 'if_pl' | 'if_pos' | 'if_mi' | 'if_neg' | 'if_vs' | 'if_vc' ;
forloop : 'for' (register | identifier) 'in' expression EOL? statement_block ;
forloop : 'for' datatype? (register | identifier) 'in' expression EOL? statement_block ;
whileloop: 'while' expression EOL? (statement | statement_block) ;

View File

@ -69,8 +69,7 @@
float Azy = cosb*sinc
float Azz = cosb*cosc
byte i
for i in 0 to len(xcoor)-1 {
for byte i in 0 to len(xcoor)-1 {
rotatedx[i] = Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i]
rotatedy[i] = Ayx*xcoor[i] + Ayy*ycoor[i] + Ayz*zcoor[i]
rotatedz[i] = Azx*xcoor[i] + Azy*ycoor[i] + Azz*zcoor[i]
@ -89,8 +88,7 @@
}
; draw all edges of the object
word edge
for edge in edges {
for word edge in edges {
byte e_from = msb(edge)
byte e_to = lsb(edge)
_vm_gfx_line(toscreenx(rotatedx[e_from], rotatedz[e_from]), toscreeny(rotatedy[e_from], rotatedz[e_from]),
@ -98,8 +96,7 @@
}
; accentuate the vertices a bit with small boxes
byte i
for i in 0 to len(xcoor)-1 {
for byte i in 0 to len(xcoor)-1 {
word sx = toscreenx(rotatedx[i], rotatedz[i])
word sy = toscreeny(rotatedy[i], rotatedz[i])
byte color=i+2

View File

@ -10,12 +10,10 @@
_vm_gfx_clearscr(11)
_vm_gfx_text(2, 1, 1, "Calculating Mandelbrot Fractal...")
byte pixely ; @todo allow defining loopvar INSIDE loop scope ("for byte pixely in ...")
for pixely in yoffset to yoffset+height-1 {
for byte pixely in yoffset to yoffset+height-1 {
float yy = flt((pixely-yoffset))/height/3.6+0.4
word pixelx ; @todo allow defining loopvar INSIDE loop scope ("for word pixelx in ...")
for pixelx in xoffset to xoffset+width-1 {
for word pixelx in xoffset to xoffset+width-1 {
float xx = flt((pixelx-xoffset))/width/3.0+0.2
float xsquared
float ysquared

View File

@ -11,8 +11,7 @@
_vm_write_str(name)
_vm_write_str(".\nI am thinking of a number from 1 to 100! You'll have to guess it!\n")
byte attempts_left
for attempts_left in 10 to 1 step -1 {
for byte attempts_left in 10 to 1 step -1 {
_vm_write_str("\nYou have ")
_vm_write_num(attempts_left)
_vm_write_str(" guess")

View File

@ -5,44 +5,14 @@
~ main {
sub start() {
byte x
for x in 0 to 20 {
float xx = sin(flt(x))
float yy = cos(flt(x))
; word [20] prime_numbers = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71] ; todo array_w!!!
word [20] fibonacci_numbers = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
for word fibnr in fibonacci_numbers {
_vm_write_num(fibnr)
_vm_write_char('\n')
}
while(1) {
float xx = sin(flt(x))
float yy = cos(flt(x))
}
repeat {
float xx = sin(flt(x))
float yy = cos(flt(x))
} until(1)
; for x in 0 to 30 {
; float xx = 2123.33
; float yy = 2444.55
; xx = sin(flt(x))
; yy = cos(flt(x))
; r = xx*yy
; }
;
; for x in 0 to 40 {
; float xx = 3123.33
; float yy = 3444.55
; xx = sin(flt(x))
; yy = cos(flt(x))
; r = xx*yy
; }
return
}
}

View File

@ -367,12 +367,6 @@ interface INameScope {
printNames(0, this)
}
fun removeStatement(statement: IStatement) {
// remove a statement (most likely because it is never referenced such as a subroutine)
val removed = statements.remove(statement)
if(!removed) throw AstException("node to remove wasn't found")
}
fun isEmpty() = statements.isEmpty()
}
@ -1371,6 +1365,7 @@ class BranchStatement(var condition: BranchCondition,
class ForLoop(val loopRegister: Register?,
val decltype: DataType?,
val loopVar: IdentifierReference?,
var iterable: IExpression,
var body: AnonymousScope,
@ -1379,7 +1374,7 @@ class ForLoop(val loopRegister: Register?,
override fun linkParents(parent: Node) {
this.parent=parent
loopVar?.linkParents(this)
loopVar?.linkParents(if(decltype==null) this else body)
iterable.linkParents(this)
body.linkParents(this)
}
@ -1856,10 +1851,11 @@ private fun prog8Parser.BranchconditionContext.toAst() = BranchCondition.valueOf
private fun prog8Parser.ForloopContext.toAst(): ForLoop {
val loopregister = register()?.toAst()
val datatype = datatype()?.toAst()
val loopvar = identifier()?.toAst()
val iterable = expression()!!.toAst()
val scope = AnonymousScope(statement_block().toAst(), statement_block().toPosition())
return ForLoop(loopregister, loopvar, iterable, scope, toPosition())
return ForLoop(loopregister, datatype, loopvar, iterable, scope, toPosition())
}

View File

@ -115,4 +115,29 @@ class AstIdentifiersChecker : IAstProcessor {
}
return super.process(label)
}
override fun process(forLoop: ForLoop): IStatement {
// if the for loop as a decltype, it means to declare the loopvar inside the loop body
// rather than reusing an already declared loopvar from an outer scope.
if(forLoop.loopRegister!=null && forLoop.decltype!=null) {
checkResult.add(SyntaxError("register loop variables cannot be explicitly declared with a datatype", forLoop.position))
} else {
val loopVar = forLoop.loopVar!!
val varName = loopVar.nameInSource.last()
when (forLoop.decltype) {
DataType.BYTE, DataType.WORD -> {
val existing = if(forLoop.body.isEmpty()) null else forLoop.body.lookup(loopVar.nameInSource, forLoop.body.statements.first())
if(existing==null) {
val vardecl = VarDecl(VarDeclType.VAR, forLoop.decltype, null, varName, null, loopVar.position)
vardecl.linkParents(forLoop.body)
forLoop.body.statements.add(0, vardecl)
forLoop.loopVar.parent = forLoop.body // loopvar 'is defined in the body'
}
}
null -> {}
else -> checkResult.add(SyntaxError("loop variables can only be a byte or word", forLoop.position))
}
}
return super.process(forLoop)
}
}

View File

@ -1198,6 +1198,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
DataType.ARRAY, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
null -> throw CompilerException("could not determine targetdt")
// todo: maybe if you assign byte or word to array/matrix, clear it with that value?
}
}
@ -1474,10 +1475,10 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
val assignTarget = if(loop.loopRegister!=null)
AssignTarget(loop.loopRegister, null, null, loop.position)
else
AssignTarget(null, loop.loopVar, null, loop.position)
AssignTarget(null, loop.loopVar!!.copy(), null, loop.position)
val arrayspec = ArraySpec(RegisterExpr(Register.valueOf(indexVar), loop.position), null, loop.position)
val assignLv = Assignment(assignTarget, null, ArrayIndexedExpression(loop.iterable as IdentifierReference, null, arrayspec, loop.position), loop.position)
assignLv.linkParents(loop.parent)
val assignLv = Assignment(assignTarget, null, ArrayIndexedExpression((loop.iterable as IdentifierReference).copy(), null, arrayspec, loop.position), loop.position)
assignLv.linkParents(loop.body)
translate(assignLv)
translate(loop.body)
stackvmProg.label(continueLabel)

View File

@ -1,12 +1,13 @@
// Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7
package prog8.parser;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.atn.ATNDeserializer;
import org.antlr.v4.runtime.atn.LexerATNSimulator;
import org.antlr.v4.runtime.atn.PredictionContextCache;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.misc.*;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class prog8Lexer extends Lexer {

View File

@ -1,15 +1,13 @@
// Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7
package prog8.parser;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.atn.ATNDeserializer;
import org.antlr.v4.runtime.atn.ParserATNSimulator;
import org.antlr.v4.runtime.atn.PredictionContextCache;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.*;
import org.antlr.v4.runtime.tree.*;
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class prog8Parser extends Parser {
@ -3897,6 +3895,9 @@ public class prog8Parser extends Parser {
public IdentifierContext identifier() {
return getRuleContext(IdentifierContext.class,0);
}
public DatatypeContext datatype() {
return getRuleContext(DatatypeContext.class,0);
}
public TerminalNode EOL() { return getToken(prog8Parser.EOL, 0); }
public ForloopContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
@ -3913,7 +3914,17 @@ public class prog8Parser extends Parser {
{
setState(571);
match(T__99);
setState(574);
setState(573);
_errHandler.sync(this);
_la = _input.LA(1);
if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22))) != 0)) {
{
setState(572);
datatype();
}
}
setState(577);
_errHandler.sync(this);
switch (_input.LA(1)) {
case T__64:
@ -3923,34 +3934,34 @@ public class prog8Parser extends Parser {
case T__68:
case T__69:
{
setState(572);
setState(575);
register();
}
break;
case NAME:
{
setState(573);
setState(576);
identifier();
}
break;
default:
throw new NoViableAltException(this);
}
setState(576);
match(T__100);
setState(577);
expression(0);
setState(579);
match(T__100);
setState(580);
expression(0);
setState(582);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==EOL) {
{
setState(578);
setState(581);
match(EOL);
}
}
setState(581);
setState(584);
statement_block();
}
}
@ -3989,21 +4000,21 @@ public class prog8Parser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(583);
match(T__101);
setState(584);
expression(0);
setState(586);
match(T__101);
setState(587);
expression(0);
setState(589);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==EOL) {
{
setState(585);
setState(588);
match(EOL);
}
}
setState(590);
setState(593);
_errHandler.sync(this);
switch (_input.LA(1)) {
case T__2:
@ -4055,13 +4066,13 @@ public class prog8Parser extends Parser {
case T__102:
case NAME:
{
setState(588);
setState(591);
statement();
}
break;
case T__80:
{
setState(589);
setState(592);
statement_block();
}
break;
@ -4105,9 +4116,9 @@ public class prog8Parser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(592);
match(T__102);
setState(595);
match(T__102);
setState(598);
_errHandler.sync(this);
switch (_input.LA(1)) {
case T__2:
@ -4159,32 +4170,32 @@ public class prog8Parser extends Parser {
case T__102:
case NAME:
{
setState(593);
setState(596);
statement();
}
break;
case T__80:
{
setState(594);
setState(597);
statement_block();
}
break;
default:
throw new NoViableAltException(this);
}
setState(598);
setState(601);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==EOL) {
{
setState(597);
setState(600);
match(EOL);
}
}
setState(600);
setState(603);
match(T__103);
setState(601);
setState(604);
expression(0);
}
}
@ -4237,7 +4248,7 @@ public class prog8Parser extends Parser {
}
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3v\u025e\4\2\t\2\4"+
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3v\u0261\4\2\t\2\4"+
"\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+
"\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
@ -4278,53 +4289,53 @@ public class prog8Parser extends Parser {
"\n\65\3\66\3\66\3\66\5\66\u0216\n\66\3\66\3\66\5\66\u021a\n\66\3\66\5"+
"\66\u021d\n\66\3\66\5\66\u0220\n\66\3\66\3\66\3\67\3\67\5\67\u0226\n\67"+
"\3\67\3\67\5\67\u022a\n\67\38\38\58\u022e\n8\38\38\58\u0232\n8\38\58\u0235"+
"\n8\38\58\u0238\n8\38\38\39\39\3:\3:\3:\5:\u0241\n:\3:\3:\3:\5:\u0246"+
"\n:\3:\3:\3;\3;\3;\5;\u024d\n;\3;\3;\5;\u0251\n;\3<\3<\3<\5<\u0256\n<"+
"\3<\5<\u0259\n<\3<\3<\3<\3<\2\3&=\2\4\6\b\n\f\16\20\22\24\26\30\32\34"+
"\36 \"$&(*,.\60\62\64\668:<>@BDFHJLNPRTVXZ\\^`bdfhjlnprtv\2\20\3\2\6\16"+
"\3\2\23\31\3\2\34$\3\2%&\4\2\3\3)*\3\2,/\3\2)*\3\2\60\63\3\2\64\65\3\2"+
"CH\3\2IL\3\2pr\3\2NO\3\2Ze\2\u0294\2|\3\2\2\2\4\u0083\3\2\2\2\6\u0085"+
"\3\2\2\2\b\u00a3\3\2\2\2\n\u00a5\3\2\2\2\f\u00a8\3\2\2\2\16\u00ae\3\2"+
"\2\2\20\u00bf\3\2\2\2\22\u00c1\3\2\2\2\24\u00c7\3\2\2\2\26\u00cf\3\2\2"+
"\2\30\u00d2\3\2\2\2\32\u00d5\3\2\2\2\34\u00d7\3\2\2\2\36\u00df\3\2\2\2"+
" \u00e3\3\2\2\2\"\u00eb\3\2\2\2$\u00ed\3\2\2\2&\u00ff\3\2\2\2(\u0131\3"+
"\2\2\2*\u0137\3\2\2\2,\u0141\3\2\2\2.\u0149\3\2\2\2\60\u0154\3\2\2\2\62"+
"\u0158\3\2\2\2\64\u015a\3\2\2\2\66\u015c\3\2\2\28\u015e\3\2\2\2:\u0165"+
"\3\2\2\2<\u0167\3\2\2\2>\u0169\3\2\2\2@\u016d\3\2\2\2B\u016f\3\2\2\2D"+
"\u0171\3\2\2\2F\u0185\3\2\2\2H\u0187\3\2\2\2J\u0189\3\2\2\2L\u0191\3\2"+
"\2\2N\u0193\3\2\2\2P\u0196\3\2\2\2R\u01a3\3\2\2\2T\u01a6\3\2\2\2V\u01b1"+
"\3\2\2\2X\u01bc\3\2\2\2Z\u01c0\3\2\2\2\\\u01cb\3\2\2\2^\u01e3\3\2\2\2"+
"`\u01e6\3\2\2\2b\u01f1\3\2\2\2d\u01f9\3\2\2\2f\u0201\3\2\2\2h\u020c\3"+
"\2\2\2j\u0212\3\2\2\2l\u0223\3\2\2\2n\u022b\3\2\2\2p\u023b\3\2\2\2r\u023d"+
"\3\2\2\2t\u0249\3\2\2\2v\u0252\3\2\2\2x{\5\4\3\2y{\7n\2\2zx\3\2\2\2zy"+
"\3\2\2\2{~\3\2\2\2|z\3\2\2\2|}\3\2\2\2}\177\3\2\2\2~|\3\2\2\2\177\u0080"+
"\7\2\2\3\u0080\3\3\2\2\2\u0081\u0084\5\16\b\2\u0082\u0084\5\6\4\2\u0083"+
"\u0081\3\2\2\2\u0083\u0082\3\2\2\2\u0084\5\3\2\2\2\u0085\u0086\7\3\2\2"+
"\u0086\u0088\5\66\34\2\u0087\u0089\5> \2\u0088\u0087\3\2\2\2\u0088\u0089"+
"\3\2\2\2\u0089\u008a\3\2\2\2\u008a\u008b\5T+\2\u008b\u008c\7n\2\2\u008c"+
"\7\3\2\2\2\u008d\u00a4\5\16\b\2\u008e\u00a4\5\24\13\2\u008f\u00a4\5\22"+
"\n\2\u0090\u00a4\5\26\f\2\u0091\u00a4\5\30\r\2\u0092\u00a4\5\36\20\2\u0093"+
"\u00a4\5 \21\2\u0094\u00a4\5\f\7\2\u0095\u00a4\5$\23\2\u0096\u00a4\5,"+
"\27\2\u0097\u00a4\5j\66\2\u0098\u00a4\5n8\2\u0099\u00a4\5P)\2\u009a\u00a4"+
"\5\\/\2\u009b\u00a4\5N(\2\u009c\u00a4\5\60\31\2\u009d\u00a4\5r:\2\u009e"+
"\u00a4\5t;\2\u009f\u00a4\5v<\2\u00a0\u00a4\5\62\32\2\u00a1\u00a4\5\64"+
"\33\2\u00a2\u00a4\5\n\6\2\u00a3\u008d\3\2\2\2\u00a3\u008e\3\2\2\2\u00a3"+
"\u008f\3\2\2\2\u00a3\u0090\3\2\2\2\u00a3\u0091\3\2\2\2\u00a3\u0092\3\2"+
"\2\2\u00a3\u0093\3\2\2\2\u00a3\u0094\3\2\2\2\u00a3\u0095\3\2\2\2\u00a3"+
"\u0096\3\2\2\2\u00a3\u0097\3\2\2\2\u00a3\u0098\3\2\2\2\u00a3\u0099\3\2"+
"\2\2\u00a3\u009a\3\2\2\2\u00a3\u009b\3\2\2\2\u00a3\u009c\3\2\2\2\u00a3"+
"\u009d\3\2\2\2\u00a3\u009e\3\2\2\2\u00a3\u009f\3\2\2\2\u00a3\u00a0\3\2"+
"\2\2\u00a3\u00a1\3\2\2\2\u00a3\u00a2\3\2\2\2\u00a4\t\3\2\2\2\u00a5\u00a6"+
"\5\66\34\2\u00a6\u00a7\7\4\2\2\u00a7\13\3\2\2\2\u00a8\u00ac\7\5\2\2\u00a9"+
"\u00ad\5> \2\u00aa\u00ad\5\66\34\2\u00ab\u00ad\58\35\2\u00ac\u00a9\3\2"+
"\2\2\u00ac\u00aa\3\2\2\2\u00ac\u00ab\3\2\2\2\u00ad\r\3\2\2\2\u00ae\u00ba"+
"\t\2\2\2\u00af\u00b1\5\20\t\2\u00b0\u00af\3\2\2\2\u00b0\u00b1\3\2\2\2"+
"\u00b1\u00bb\3\2\2\2\u00b2\u00b7\5\20\t\2\u00b3\u00b4\7\17\2\2\u00b4\u00b6"+
"\5\20\t\2\u00b5\u00b3\3\2\2\2\u00b6\u00b9\3\2\2\2\u00b7\u00b5\3\2\2\2"+
"\u00b7\u00b8\3\2\2\2\u00b8\u00bb\3\2\2\2\u00b9\u00b7\3\2\2\2\u00ba\u00b0"+
"\3\2\2\2\u00ba\u00b2\3\2\2\2\u00bb\17\3\2\2\2\u00bc\u00c0\5F$\2\u00bd"+
"\u00c0\5\66\34\2\u00be\u00c0\5> \2\u00bf\u00bc\3\2\2\2\u00bf\u00bd\3\2"+
"\2\2\u00bf\u00be\3\2\2\2\u00c0\21\3\2\2\2\u00c1\u00c3\5\32\16\2\u00c2"+
"\n8\38\58\u0238\n8\38\38\39\39\3:\3:\5:\u0240\n:\3:\3:\5:\u0244\n:\3:"+
"\3:\3:\5:\u0249\n:\3:\3:\3;\3;\3;\5;\u0250\n;\3;\3;\5;\u0254\n;\3<\3<"+
"\3<\5<\u0259\n<\3<\5<\u025c\n<\3<\3<\3<\3<\2\3&=\2\4\6\b\n\f\16\20\22"+
"\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@BDFHJLNPRTVXZ\\^`bdfhjlnp"+
"rtv\2\20\3\2\6\16\3\2\23\31\3\2\34$\3\2%&\4\2\3\3)*\3\2,/\3\2)*\3\2\60"+
"\63\3\2\64\65\3\2CH\3\2IL\3\2pr\3\2NO\3\2Ze\2\u0298\2|\3\2\2\2\4\u0083"+
"\3\2\2\2\6\u0085\3\2\2\2\b\u00a3\3\2\2\2\n\u00a5\3\2\2\2\f\u00a8\3\2\2"+
"\2\16\u00ae\3\2\2\2\20\u00bf\3\2\2\2\22\u00c1\3\2\2\2\24\u00c7\3\2\2\2"+
"\26\u00cf\3\2\2\2\30\u00d2\3\2\2\2\32\u00d5\3\2\2\2\34\u00d7\3\2\2\2\36"+
"\u00df\3\2\2\2 \u00e3\3\2\2\2\"\u00eb\3\2\2\2$\u00ed\3\2\2\2&\u00ff\3"+
"\2\2\2(\u0131\3\2\2\2*\u0137\3\2\2\2,\u0141\3\2\2\2.\u0149\3\2\2\2\60"+
"\u0154\3\2\2\2\62\u0158\3\2\2\2\64\u015a\3\2\2\2\66\u015c\3\2\2\28\u015e"+
"\3\2\2\2:\u0165\3\2\2\2<\u0167\3\2\2\2>\u0169\3\2\2\2@\u016d\3\2\2\2B"+
"\u016f\3\2\2\2D\u0171\3\2\2\2F\u0185\3\2\2\2H\u0187\3\2\2\2J\u0189\3\2"+
"\2\2L\u0191\3\2\2\2N\u0193\3\2\2\2P\u0196\3\2\2\2R\u01a3\3\2\2\2T\u01a6"+
"\3\2\2\2V\u01b1\3\2\2\2X\u01bc\3\2\2\2Z\u01c0\3\2\2\2\\\u01cb\3\2\2\2"+
"^\u01e3\3\2\2\2`\u01e6\3\2\2\2b\u01f1\3\2\2\2d\u01f9\3\2\2\2f\u0201\3"+
"\2\2\2h\u020c\3\2\2\2j\u0212\3\2\2\2l\u0223\3\2\2\2n\u022b\3\2\2\2p\u023b"+
"\3\2\2\2r\u023d\3\2\2\2t\u024c\3\2\2\2v\u0255\3\2\2\2x{\5\4\3\2y{\7n\2"+
"\2zx\3\2\2\2zy\3\2\2\2{~\3\2\2\2|z\3\2\2\2|}\3\2\2\2}\177\3\2\2\2~|\3"+
"\2\2\2\177\u0080\7\2\2\3\u0080\3\3\2\2\2\u0081\u0084\5\16\b\2\u0082\u0084"+
"\5\6\4\2\u0083\u0081\3\2\2\2\u0083\u0082\3\2\2\2\u0084\5\3\2\2\2\u0085"+
"\u0086\7\3\2\2\u0086\u0088\5\66\34\2\u0087\u0089\5> \2\u0088\u0087\3\2"+
"\2\2\u0088\u0089\3\2\2\2\u0089\u008a\3\2\2\2\u008a\u008b\5T+\2\u008b\u008c"+
"\7n\2\2\u008c\7\3\2\2\2\u008d\u00a4\5\16\b\2\u008e\u00a4\5\24\13\2\u008f"+
"\u00a4\5\22\n\2\u0090\u00a4\5\26\f\2\u0091\u00a4\5\30\r\2\u0092\u00a4"+
"\5\36\20\2\u0093\u00a4\5 \21\2\u0094\u00a4\5\f\7\2\u0095\u00a4\5$\23\2"+
"\u0096\u00a4\5,\27\2\u0097\u00a4\5j\66\2\u0098\u00a4\5n8\2\u0099\u00a4"+
"\5P)\2\u009a\u00a4\5\\/\2\u009b\u00a4\5N(\2\u009c\u00a4\5\60\31\2\u009d"+
"\u00a4\5r:\2\u009e\u00a4\5t;\2\u009f\u00a4\5v<\2\u00a0\u00a4\5\62\32\2"+
"\u00a1\u00a4\5\64\33\2\u00a2\u00a4\5\n\6\2\u00a3\u008d\3\2\2\2\u00a3\u008e"+
"\3\2\2\2\u00a3\u008f\3\2\2\2\u00a3\u0090\3\2\2\2\u00a3\u0091\3\2\2\2\u00a3"+
"\u0092\3\2\2\2\u00a3\u0093\3\2\2\2\u00a3\u0094\3\2\2\2\u00a3\u0095\3\2"+
"\2\2\u00a3\u0096\3\2\2\2\u00a3\u0097\3\2\2\2\u00a3\u0098\3\2\2\2\u00a3"+
"\u0099\3\2\2\2\u00a3\u009a\3\2\2\2\u00a3\u009b\3\2\2\2\u00a3\u009c\3\2"+
"\2\2\u00a3\u009d\3\2\2\2\u00a3\u009e\3\2\2\2\u00a3\u009f\3\2\2\2\u00a3"+
"\u00a0\3\2\2\2\u00a3\u00a1\3\2\2\2\u00a3\u00a2\3\2\2\2\u00a4\t\3\2\2\2"+
"\u00a5\u00a6\5\66\34\2\u00a6\u00a7\7\4\2\2\u00a7\13\3\2\2\2\u00a8\u00ac"+
"\7\5\2\2\u00a9\u00ad\5> \2\u00aa\u00ad\5\66\34\2\u00ab\u00ad\58\35\2\u00ac"+
"\u00a9\3\2\2\2\u00ac\u00aa\3\2\2\2\u00ac\u00ab\3\2\2\2\u00ad\r\3\2\2\2"+
"\u00ae\u00ba\t\2\2\2\u00af\u00b1\5\20\t\2\u00b0\u00af\3\2\2\2\u00b0\u00b1"+
"\3\2\2\2\u00b1\u00bb\3\2\2\2\u00b2\u00b7\5\20\t\2\u00b3\u00b4\7\17\2\2"+
"\u00b4\u00b6\5\20\t\2\u00b5\u00b3\3\2\2\2\u00b6\u00b9\3\2\2\2\u00b7\u00b5"+
"\3\2\2\2\u00b7\u00b8\3\2\2\2\u00b8\u00bb\3\2\2\2\u00b9\u00b7\3\2\2\2\u00ba"+
"\u00b0\3\2\2\2\u00ba\u00b2\3\2\2\2\u00bb\17\3\2\2\2\u00bc\u00c0\5F$\2"+
"\u00bd\u00c0\5\66\34\2\u00be\u00c0\5> \2\u00bf\u00bc\3\2\2\2\u00bf\u00bd"+
"\3\2\2\2\u00bf\u00be\3\2\2\2\u00c0\21\3\2\2\2\u00c1\u00c3\5\32\16\2\u00c2"+
"\u00c4\5\34\17\2\u00c3\u00c2\3\2\2\2\u00c3\u00c4\3\2\2\2\u00c4\u00c5\3"+
"\2\2\2\u00c5\u00c6\5\66\34\2\u00c6\23\3\2\2\2\u00c7\u00c9\5\32\16\2\u00c8"+
"\u00ca\5\34\17\2\u00c9\u00c8\3\2\2\2\u00c9\u00ca\3\2\2\2\u00ca\u00cb\3"+
@ -4450,22 +4461,23 @@ public class prog8Parser extends Parser {
"\u0233\3\2\2\2\u0234\u0235\3\2\2\2\u0235\u0237\3\2\2\2\u0236\u0238\5l"+
"\67\2\u0237\u0236\3\2\2\2\u0237\u0238\3\2\2\2\u0238\u0239\3\2\2\2\u0239"+
"\u023a\7n\2\2\u023ao\3\2\2\2\u023b\u023c\t\17\2\2\u023cq\3\2\2\2\u023d"+
"\u0240\7f\2\2\u023e\u0241\5:\36\2\u023f\u0241\5\66\34\2\u0240\u023e\3"+
"\2\2\2\u0240\u023f\3\2\2\2\u0241\u0242\3\2\2\2\u0242\u0243\7g\2\2\u0243"+
"\u0245\5&\24\2\u0244\u0246\7n\2\2\u0245\u0244\3\2\2\2\u0245\u0246\3\2"+
"\2\2\u0246\u0247\3\2\2\2\u0247\u0248\5T+\2\u0248s\3\2\2\2\u0249\u024a"+
"\7h\2\2\u024a\u024c\5&\24\2\u024b\u024d\7n\2\2\u024c\u024b\3\2\2\2\u024c"+
"\u024d\3\2\2\2\u024d\u0250\3\2\2\2\u024e\u0251\5\b\5\2\u024f\u0251\5T"+
"+\2\u0250\u024e\3\2\2\2\u0250\u024f\3\2\2\2\u0251u\3\2\2\2\u0252\u0255"+
"\7i\2\2\u0253\u0256\5\b\5\2\u0254\u0256\5T+\2\u0255\u0253\3\2\2\2\u0255"+
"\u0254\3\2\2\2\u0256\u0258\3\2\2\2\u0257\u0259\7n\2\2\u0258\u0257\3\2"+
"\2\2\u0258\u0259\3\2\2\2\u0259\u025a\3\2\2\2\u025a\u025b\7j\2\2\u025b"+
"\u025c\5&\24\2\u025cw\3\2\2\2Fz|\u0083\u0088\u00a3\u00ac\u00b0\u00b7\u00ba"+
"\u023f\7f\2\2\u023e\u0240\5\32\16\2\u023f\u023e\3\2\2\2\u023f\u0240\3"+
"\2\2\2\u0240\u0243\3\2\2\2\u0241\u0244\5:\36\2\u0242\u0244\5\66\34\2\u0243"+
"\u0241\3\2\2\2\u0243\u0242\3\2\2\2\u0244\u0245\3\2\2\2\u0245\u0246\7g"+
"\2\2\u0246\u0248\5&\24\2\u0247\u0249\7n\2\2\u0248\u0247\3\2\2\2\u0248"+
"\u0249\3\2\2\2\u0249\u024a\3\2\2\2\u024a\u024b\5T+\2\u024bs\3\2\2\2\u024c"+
"\u024d\7h\2\2\u024d\u024f\5&\24\2\u024e\u0250\7n\2\2\u024f\u024e\3\2\2"+
"\2\u024f\u0250\3\2\2\2\u0250\u0253\3\2\2\2\u0251\u0254\5\b\5\2\u0252\u0254"+
"\5T+\2\u0253\u0251\3\2\2\2\u0253\u0252\3\2\2\2\u0254u\3\2\2\2\u0255\u0258"+
"\7i\2\2\u0256\u0259\5\b\5\2\u0257\u0259\5T+\2\u0258\u0256\3\2\2\2\u0258"+
"\u0257\3\2\2\2\u0259\u025b\3\2\2\2\u025a\u025c\7n\2\2\u025b\u025a\3\2"+
"\2\2\u025b\u025c\3\2\2\2\u025c\u025d\3\2\2\2\u025d\u025e\7j\2\2\u025e"+
"\u025f\5&\24\2\u025fw\3\2\2\2Gz|\u0083\u0088\u00a3\u00ac\u00b0\u00b7\u00ba"+
"\u00bf\u00c3\u00c9\u00db\u00eb\u00ff\u0127\u0129\u012b\u0131\u0137\u013b"+
"\u0141\u0145\u014c\u0151\u0156\u0163\u016b\u0173\u0178\u017d\u0181\u0191"+
"\u019a\u019e\u01aa\u01ac\u01b4\u01b9\u01c3\u01c8\u01cf\u01d6\u01dc\u01e1"+
"\u01e9\u01ee\u01f7\u01fe\u0204\u0209\u0210\u0215\u0219\u021c\u021f\u0225"+
"\u0229\u022d\u0231\u0234\u0237\u0240\u0245\u024c\u0250\u0255\u0258";
"\u0229\u022d\u0231\u0234\u0237\u023f\u0243\u0248\u024f\u0253\u0258\u025b";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {

View File

@ -328,8 +328,9 @@ Loops
-----
The *for*-loop is used to let a variable (or register) iterate over a range of values. Iteration is done in steps of 1, but you can change this.
The loop variable must be declared as byte or word earlier. Floating point iteration is not supported,
if you want to loop over a floating-point array, use a loop with an integer index variable instead.
The loop variable can be declared as byte or word earlier so you can reuse it for multiple occasions,
or you can declare one directly in the for statement which will only be visible in the for loop body.
Iterating with a floating point variable is not supported. If you want to loop over a floating-point array, use a loop with an integer index variable instead.
The *while*-loop is used to repeat a piece of code while a certain condition is still true.
The *repeat--until* loop is used to repeat a piece of code until a certain condition is true.

View File

@ -450,18 +450,34 @@ Loops
for loop
^^^^^^^^
The loop variable must be a register or a byte/word variable defined in the local scope.
The loop variable must be a register or a byte/word variable. It must be defined in the local scope (to reuse
an existing variable), or you can declare it in the for loop directly to make a new one that is only visible
in the body of the for loop.
The expression that you loop over can be anything that supports iteration (such as ranges like ``0 to 100``,
array variables and strings) *except* floating-point arrays (because a floating-point loop variable is not supported).
You can use a single statement, or a statement block like in the example below::
for <loopvar> in <expression> [ step <amount> ] {
for [byte | word] <loopvar> in <expression> [ step <amount> ] {
; do something...
break ; break out of the loop
continue ; immediately enter next iteration
}
For example, this is a for loop using the existing byte variable ``i`` to loop over a certain range of numbers::
for i in 20 to 155 {
; do something
}
And this is a loop over the values of the array ``fibonacci_numbers`` where the loop variable is declared in the loop itself::
word[20] fibonacci_numbers = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
for word fibnr in fibonacci_numbers {
; do something
}
while loop
^^^^^^^^^^

View File

@ -3,112 +3,6 @@ TODO
====
IF_XX::
if[_XX] [<expression>] {
...
}
[ else {
... ; evaluated when the condition is not met
} ]
==> DESUGARING ==>
(no else:)::
if[_!XX] [<expression>] goto prog8_if_999_end ; !XX being the conditional inverse of XX
.... (true part)
prog8_if_999_end ; code continues after this
(with else)::
if[_XX] [<expression>] goto prog8_if_999
... (else part)
goto prog8_if_999_end
prog8_if_999 ... (true part)
prog8_if_999_end ; code continues after this
IF X <COMPARISON> Y
==> DESUGARING ==>::
compare X, Y
if_XX goto ....
XX based on <COMPARISON>.
While::
while[_XX] <expression> {
...
continue
break
}
==> DESUGARING ==>::
goto prog8_while_999_check ; jump to the check
prog8_while_999
... (code)
goto prog8_while_999 ;continue
goto prog8_while_999_end ;break
prog8_while_999_check
if[_XX] <expression> goto prog8_while_999 ; loop condition
prog8_while_999_end ; code continues after this
Repeat::
repeat {
...
continue
break
} until[_XX] <expressoin>
==> DESUGARING ==>::
prog8_repeat_999
... (code)
goto prog8_repeat_999 ;continue
goto prog8_repeat_999_end ;break
if[_!XX] <expression> goto prog8_repeat_999 ; loop condition via conditional inverse of XX
prog8_repeat_999_end ; code continues after this
For::
for <loopvar> = <from_expression> to <to_expression> [step <step_expression>] {
...
break
continue
}
@todo how to do signed integer loopvars?
==> DESUGARING ==>::
loopvar = <from_expression>
compare loopvar, <to_expression>
if_ge goto prog8_for_999_end ; loop condition
step = <step_expression> ; (store only if step < -1 or step > 1)
prog8_for_999
goto prog8_for_999_end ;break
goto prog8_for_999_loop ;continue
.... (code)
prog8_for_999_loop
loopvar += step ; (if step > 1 or step < -1)
loopvar++ ; (if step == 1)
loopvar-- ; (if step == -1)
goto prog8_for_999 ; continue the loop
prog8_for_999_end ; code continues after this
### Macros
@todo macros are meta-code that is executed by the compiler, in a preprecessing step