mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-01-10 21:30:30 +00:00
added "!for VAR in ITERABLE { BLOCK }" possibility.
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@306 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
cc82e17cda
commit
c9d148d345
@ -457,11 +457,17 @@ Examples: ; this was taken from <6502/std.a>:
|
|||||||
|
|
||||||
|
|
||||||
Call: !for SYMBOL, START, END { BLOCK }
|
Call: !for SYMBOL, START, END { BLOCK }
|
||||||
|
or: !for SYMBOL in ITERABLE { BLOCK }
|
||||||
Purpose: Looping assembly. The block of statements will be
|
Purpose: Looping assembly. The block of statements will be
|
||||||
parsed a fixed number of times, as specified by the
|
parsed a fixed number of times, as specified by the
|
||||||
values of START and END. For more flexible
|
arguments:
|
||||||
possibilities, have a look at "!do" and "!while"
|
When using the first syntax, SYMBOL will simply count
|
||||||
below.
|
from START to END.
|
||||||
|
When using the second syntax, SYMBOL will iterate over
|
||||||
|
the contents of the ITERABLE, which must be a string
|
||||||
|
or a list.
|
||||||
|
For more flexible loop constructs, have a look at
|
||||||
|
"!do" and "!while" below.
|
||||||
Parameters: SYMBOL: Any valid symbol name.
|
Parameters: SYMBOL: Any valid symbol name.
|
||||||
START: Any formula the value parser accepts, but it
|
START: Any formula the value parser accepts, but it
|
||||||
must be solvable even in the first pass. SYMBOL will
|
must be solvable even in the first pass. SYMBOL will
|
||||||
@ -469,6 +475,15 @@ Parameters: SYMBOL: Any valid symbol name.
|
|||||||
END: Any formula the value parser accepts, but it must
|
END: Any formula the value parser accepts, but it must
|
||||||
be solvable even in the first pass. SYMBOL will have
|
be solvable even in the first pass. SYMBOL will have
|
||||||
this value during the last loop cycle.
|
this value during the last loop cycle.
|
||||||
|
ITERABLE: This must be a string or a list, but its
|
||||||
|
length must be defined even in the first pass (and of
|
||||||
|
course it should stay the same during all subsequent
|
||||||
|
passes).
|
||||||
|
If ITERABLE is a list, its _items_ are allowed
|
||||||
|
to be undefined.
|
||||||
|
If ITERABLE is a string, SYMBOL will be set to
|
||||||
|
each of its character codes in turn, using the
|
||||||
|
currently chosen conversion table.
|
||||||
BLOCK: A block of assembler statements.
|
BLOCK: A block of assembler statements.
|
||||||
If START or END are floats, they will be converted to
|
If START or END are floats, they will be converted to
|
||||||
integers (never use floats for loop counters). If
|
integers (never use floats for loop counters). If
|
||||||
@ -508,8 +523,25 @@ Examples:
|
|||||||
sta $0400 + i
|
sta $0400 + i
|
||||||
}
|
}
|
||||||
|
|
||||||
Miscellaneous: The old syntax ("!for SYMBOL, END { BLOCK }" where
|
split_table_lo ; generate two tables from one list
|
||||||
START was always implied to be 1) is still fully
|
!for h in my_handler_list {
|
||||||
|
!by <h
|
||||||
|
}
|
||||||
|
split_table_hi
|
||||||
|
!for h in my_handler_list {
|
||||||
|
!by >h
|
||||||
|
}
|
||||||
|
|
||||||
|
hidden_string ; "encrypt" a string by XORing with address
|
||||||
|
!ct scr { ; use screen codes
|
||||||
|
!for c in "very secret message" {
|
||||||
|
!by c XOR <*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Miscellaneous: The old syntax
|
||||||
|
!for SYMBOL, END { BLOCK }
|
||||||
|
where START was always implied to be 1 is still fully
|
||||||
supported, but gives a warning to get people to change
|
supported, but gives a warning to get people to change
|
||||||
to the new syntax.
|
to the new syntax.
|
||||||
You can disable this warning using the "--dialect" or
|
You can disable this warning using the "--dialect" or
|
||||||
@ -778,6 +810,11 @@ or type (call-by-value vs. call-by-reference). So
|
|||||||
!macro process_bytes b1, b2, ~b3 {...whatever...}
|
!macro process_bytes b1, b2, ~b3 {...whatever...}
|
||||||
can *all* be used at the same time without any name clash.
|
can *all* be used at the same time without any name clash.
|
||||||
|
|
||||||
|
Since release 0.97, lists are supported. This is useful for macros if
|
||||||
|
you want an arbitrary number of arguments: Just define the macro with
|
||||||
|
a single argument, then pass a list and have the macro iterate over
|
||||||
|
its contents.
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
Section: Segment assembly
|
Section: Segment assembly
|
||||||
|
@ -264,6 +264,12 @@ File name quotes not found ("" or <>).
|
|||||||
File names have to be given in quotes. Either "" quoting for files
|
File names have to be given in quotes. Either "" quoting for files
|
||||||
located in the current directory or <> quoting for library files.
|
located in the current directory or <> quoting for library files.
|
||||||
|
|
||||||
|
Force bits can only be given to counters, not when iterating over string/list contents.
|
||||||
|
You used a force bit with a "!for" loop counter, but then used the
|
||||||
|
"iterate over string/list contents" syntax. This does not work,
|
||||||
|
because lists could contain other lists, and then a force bit does
|
||||||
|
not make any sense.
|
||||||
|
|
||||||
Force bits can only be given to numbers.
|
Force bits can only be given to numbers.
|
||||||
You tried to give a force bit to a symbol and then assign a string
|
You tried to give a force bit to a symbol and then assign a string
|
||||||
or list to it.
|
or list to it.
|
||||||
@ -276,6 +282,10 @@ Garbage data at end of statement (unexpected 'CHAR').
|
|||||||
There are still arguments when there should not be any more. The
|
There are still arguments when there should not be any more. The
|
||||||
given character is the one where end-of-line was expected.
|
given character is the one where end-of-line was expected.
|
||||||
|
|
||||||
|
Given object is not iterable.
|
||||||
|
You used "!for VAR in ITERABLE", but the iterable was neither a
|
||||||
|
string nor a list (likely a number).
|
||||||
|
|
||||||
Hex digits are not given in pairs.
|
Hex digits are not given in pairs.
|
||||||
The two digits of a hex byte are separated by another character,
|
The two digits of a hex byte are separated by another character,
|
||||||
or there is an odd number of digits.
|
or there is an odd number of digits.
|
||||||
@ -289,6 +299,12 @@ Index is undefined.
|
|||||||
Index out of range.
|
Index out of range.
|
||||||
The value for an indexing operation wasn't in the allowed range.
|
The value for an indexing operation wasn't in the allowed range.
|
||||||
|
|
||||||
|
Loop var must be followed by either "in" keyword or comma.
|
||||||
|
You made a syntax error when using "!for": After the loop counter
|
||||||
|
symbol there can either be a comma (for a simple counting loop) or
|
||||||
|
the "in" keyword (when iterating over string or list contents).
|
||||||
|
Anything else will give this error.
|
||||||
|
|
||||||
Macro already defined.
|
Macro already defined.
|
||||||
Macros can only be defined once. If you define a macro twice, ACME
|
Macros can only be defined once. If you define a macro twice, ACME
|
||||||
will help you find the definitions by giving a warning for the
|
will help you find the definitions by giving a warning for the
|
||||||
@ -554,6 +570,9 @@ IllegalImmediateMode
|
|||||||
IllegalInputSource
|
IllegalInputSource
|
||||||
Input is taken neither from a file nor from a RAM block.
|
Input is taken neither from a file nor from a RAM block.
|
||||||
|
|
||||||
|
IllegalLoopAlgo
|
||||||
|
The "!for" function was told to use an unknown algorithm.
|
||||||
|
|
||||||
IllegalNumberTypeX
|
IllegalNumberTypeX
|
||||||
A number was neither INT nor FLOAT nor UNDEFINED.
|
A number was neither INT nor FLOAT nor UNDEFINED.
|
||||||
|
|
||||||
|
74
src/flow.c
74
src/flow.c
@ -63,24 +63,11 @@ static void parse_ram_block(struct block *block)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// back end function for "!for" pseudo opcode
|
// function for "!for" with counter variable
|
||||||
void flow_forloop(struct for_loop *loop)
|
static void counting_for(struct for_loop *loop)
|
||||||
{
|
{
|
||||||
struct input loop_input,
|
|
||||||
*outer_input;
|
|
||||||
struct object loop_var;
|
struct object loop_var;
|
||||||
|
|
||||||
// switching input makes us lose GotByte. But we know it's '}' anyway!
|
|
||||||
// set up new input
|
|
||||||
loop_input = *Input_now; // copy current input structure into new
|
|
||||||
loop_input.source = INPUTSRC_RAM; // set new byte source
|
|
||||||
// remember old input
|
|
||||||
outer_input = Input_now;
|
|
||||||
// activate new input
|
|
||||||
// (not yet useable; pointer and line number are still missing)
|
|
||||||
Input_now = &loop_input;
|
|
||||||
// fix line number (not for block, but in case symbol handling throws errors)
|
|
||||||
Input_now->line_number = loop->block.start;
|
|
||||||
// init counter
|
// init counter
|
||||||
loop_var.type = &type_number;
|
loop_var.type = &type_number;
|
||||||
loop_var.u.number.ntype = NUMTYPE_INT;
|
loop_var.u.number.ntype = NUMTYPE_INT;
|
||||||
@ -98,12 +85,11 @@ void flow_forloop(struct for_loop *loop)
|
|||||||
// cases like !set N=N+1 worked, because the force bit was
|
// cases like !set N=N+1 worked, because the force bit was
|
||||||
// taken from result.
|
// taken from result.
|
||||||
// maybe support this behaviour via --dialect?
|
// maybe support this behaviour via --dialect?
|
||||||
if (loop->force_bit)
|
if (loop->u.counter.force_bit)
|
||||||
symbol_set_force_bit(loop->symbol, loop->force_bit);
|
symbol_set_force_bit(loop->symbol, loop->u.counter.force_bit);
|
||||||
loop_var = loop->symbol->object; // update local copy with force bit
|
loop_var = loop->symbol->object; // update local copy with force bit
|
||||||
loop->symbol->has_been_read = TRUE; // lock force bit
|
loop->symbol->has_been_read = TRUE; // lock force bit
|
||||||
loop_var.u.number.val.intval = loop->u.counter.first; // SEE ABOVE - this may be nonzero, but has not yet been copied to user symbol!
|
loop_var.u.number.val.intval = loop->u.counter.first; // SEE ABOVE - this may be nonzero, but has not yet been copied to user symbol!
|
||||||
|
|
||||||
while (loop->iterations_left) {
|
while (loop->iterations_left) {
|
||||||
loop->symbol->object = loop_var; // overwrite whole struct, in case some joker has re-assigned loop counter var
|
loop->symbol->object = loop_var; // overwrite whole struct, in case some joker has re-assigned loop counter var
|
||||||
parse_ram_block(&loop->block);
|
parse_ram_block(&loop->block);
|
||||||
@ -111,15 +97,53 @@ void flow_forloop(struct for_loop *loop)
|
|||||||
loop->iterations_left--;
|
loop->iterations_left--;
|
||||||
}
|
}
|
||||||
// new algo wants illegal value in loop counter after block:
|
// new algo wants illegal value in loop counter after block:
|
||||||
if (loop->algorithm == FORALGO_NEW)
|
if (loop->algorithm == FORALGO_NEWCOUNT)
|
||||||
loop->symbol->object = loop_var; // overwrite whole struct, in case some joker has re-assigned loop counter var
|
loop->symbol->object = loop_var; // overwrite whole struct, in case some joker has re-assigned loop counter var
|
||||||
|
}
|
||||||
|
|
||||||
// case FORALGO_ITER: // iterate over string/list contents:
|
// function for "!for" with iterating variable
|
||||||
// FIXME
|
static void iterating_for(struct for_loop *loop)
|
||||||
// break;
|
{
|
||||||
// default:
|
intval_t index = 0;
|
||||||
// Bug_found("IllegalLoopAlgo", loop->algorithm); // FIXME - add to docs!
|
struct object obj;
|
||||||
// }
|
|
||||||
|
while (loop->iterations_left) {
|
||||||
|
loop->u.iter.obj.type->at(&loop->u.iter.obj, &obj, index++);
|
||||||
|
symbol_set_object(loop->symbol, &obj, POWER_CHANGE_VALUE | POWER_CHANGE_OBJTYPE);
|
||||||
|
parse_ram_block(&loop->block);
|
||||||
|
loop->iterations_left--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// back end function for "!for" pseudo opcode
|
||||||
|
void flow_forloop(struct for_loop *loop)
|
||||||
|
{
|
||||||
|
struct input loop_input,
|
||||||
|
*outer_input;
|
||||||
|
|
||||||
|
// switching input makes us lose GotByte. But we know it's '}' anyway!
|
||||||
|
// set up new input
|
||||||
|
loop_input = *Input_now; // copy current input structure into new
|
||||||
|
loop_input.source = INPUTSRC_RAM; // set new byte source
|
||||||
|
// remember old input
|
||||||
|
outer_input = Input_now;
|
||||||
|
// activate new input
|
||||||
|
// (not yet useable; pointer and line number are still missing)
|
||||||
|
Input_now = &loop_input;
|
||||||
|
// fix line number (not for block, but in case symbol handling throws errors)
|
||||||
|
Input_now->line_number = loop->block.start;
|
||||||
|
switch (loop->algorithm) {
|
||||||
|
case FORALGO_OLDCOUNT:
|
||||||
|
case FORALGO_NEWCOUNT:
|
||||||
|
counting_for(loop);
|
||||||
|
break;
|
||||||
|
case FORALGO_ITERATE:
|
||||||
|
iterating_for(loop);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Bug_found("IllegalLoopAlgo", loop->algorithm);
|
||||||
|
}
|
||||||
// restore previous input:
|
// restore previous input:
|
||||||
Input_now = outer_input;
|
Input_now = outer_input;
|
||||||
}
|
}
|
||||||
|
16
src/flow.h
16
src/flow.h
@ -18,26 +18,24 @@ struct block {
|
|||||||
|
|
||||||
// struct to pass "!for" loop stuff from pseudoopcodes.c to flow.c
|
// struct to pass "!for" loop stuff from pseudoopcodes.c to flow.c
|
||||||
enum foralgo {
|
enum foralgo {
|
||||||
FORALGO_OLD, // block can be skipped by passing zero, counter keeps value after block
|
FORALGO_OLDCOUNT, // block can be skipped by passing zero, counter keeps value after block
|
||||||
FORALGO_NEW, // first and last value are given, counter is out of range after block
|
FORALGO_NEWCOUNT, // first and last value are given, counter is out of range after block
|
||||||
//FORALGO_ITER, // iterate over string/list contents (old algo could be changed to use this!)
|
FORALGO_ITERATE // iterate over string/list contents
|
||||||
};
|
};
|
||||||
struct for_loop {
|
struct for_loop {
|
||||||
struct symbol *symbol;
|
struct symbol *symbol;
|
||||||
enum foralgo algorithm;
|
enum foralgo algorithm;
|
||||||
bits force_bit; // TODO - move to counter struct? illegal for iter algo!
|
|
||||||
intval_t iterations_left;
|
intval_t iterations_left;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
intval_t first,
|
intval_t first,
|
||||||
increment; // 1 or -1
|
increment; // 1 or -1
|
||||||
|
bits force_bit;
|
||||||
int addr_refs; // address reference count
|
int addr_refs; // address reference count
|
||||||
} counter;
|
} counter;
|
||||||
/* struct {
|
struct {
|
||||||
struct symbol *iterable;
|
struct object obj; // string or list
|
||||||
int index;
|
} iter;
|
||||||
add a "last" value here? or check len() in every iteration?
|
|
||||||
} iter;*/
|
|
||||||
} u;
|
} u;
|
||||||
struct block block;
|
struct block block;
|
||||||
};
|
};
|
||||||
|
@ -1009,12 +1009,13 @@ static enum eos po_ifndef(void) // now GotByte = illegal char
|
|||||||
|
|
||||||
|
|
||||||
// looping assembly ("!for"). has to be re-entrant.
|
// looping assembly ("!for"). has to be re-entrant.
|
||||||
// old syntax: !for VAR, END { BLOCK } VAR counts from 1 to END
|
// old counter syntax: !for VAR, END { BLOCK } VAR counts from 1 to END
|
||||||
// new syntax: !for VAR, START, END { BLOCK } VAR counts from START to END
|
// new counter syntax: !for VAR, START, END { BLOCK } VAR counts from START to END
|
||||||
// maybe future alternative: !for VAR in ITERABLE { BLOCK } VAR iterates over string/list contents
|
// iterating syntax: !for VAR in ITERABLE { BLOCK } VAR iterates over string/list contents
|
||||||
static enum eos po_for(void) // now GotByte = illegal char
|
static enum eos po_for(void) // now GotByte = illegal char
|
||||||
{
|
{
|
||||||
scope_t scope;
|
scope_t scope;
|
||||||
|
bits force_bit;
|
||||||
struct for_loop loop;
|
struct for_loop loop;
|
||||||
struct number intresult;
|
struct number intresult;
|
||||||
|
|
||||||
@ -1022,63 +1023,80 @@ static enum eos po_for(void) // now GotByte = illegal char
|
|||||||
return SKIP_REMAINDER; // zero length
|
return SKIP_REMAINDER; // zero length
|
||||||
|
|
||||||
// now GotByte = illegal char
|
// now GotByte = illegal char
|
||||||
loop.force_bit = Input_get_force_bit(); // skips spaces after
|
force_bit = Input_get_force_bit(); // skips spaces after
|
||||||
loop.symbol = symbol_find(scope); // if not number, error will be reported on first assignment
|
loop.symbol = symbol_find(scope); // if not number, error will be reported on first assignment
|
||||||
if (!Input_accept_comma()) {
|
|
||||||
#if 1
|
|
||||||
Throw_error(exception_syntax);
|
|
||||||
return SKIP_REMAINDER;
|
|
||||||
#else
|
|
||||||
// check for "in" keyword
|
|
||||||
if (Input_read_and_lower_keyword() == 0)
|
|
||||||
return SKIP_REMAINDER;
|
|
||||||
|
|
||||||
if (strcmp(GlobalDynaBuf->buffer, "in") != 0) {
|
|
||||||
Throw_error("Loop var must be followed by either \"in\" keyword or comma."); // TODO - add to docs!
|
|
||||||
return SKIP_REMAINDER;
|
|
||||||
}
|
|
||||||
if (loop.force_bit) {
|
|
||||||
Throw_error("Force bits can only be given to counters, not when iterating over string/list contents."); // TODO - add to docs!
|
|
||||||
return SKIP_REMAINDER;
|
|
||||||
}
|
|
||||||
loop.algorithm = FORALGO_ITER;
|
|
||||||
FIXME
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
ALU_defined_int(&intresult); // read first argument
|
|
||||||
loop.u.counter.addr_refs = intresult.addr_refs;
|
|
||||||
if (Input_accept_comma()) {
|
if (Input_accept_comma()) {
|
||||||
// new format - yay!
|
// counter syntax (old or new)
|
||||||
loop.algorithm = FORALGO_NEW;
|
loop.u.counter.force_bit = force_bit;
|
||||||
if (config.wanted_version < VER_NEWFORSYNTAX)
|
ALU_defined_int(&intresult); // read first argument
|
||||||
Throw_first_pass_warning("Found new \"!for\" syntax.");
|
loop.u.counter.addr_refs = intresult.addr_refs;
|
||||||
loop.u.counter.first = intresult.val.intval; // use first argument
|
if (Input_accept_comma()) {
|
||||||
ALU_defined_int(&intresult); // read second argument
|
// new counter syntax
|
||||||
// compare addr_ref counts and complain if not equal!
|
loop.algorithm = FORALGO_NEWCOUNT;
|
||||||
if (config.warn_on_type_mismatch
|
if (config.wanted_version < VER_NEWFORSYNTAX)
|
||||||
&& (intresult.addr_refs != loop.u.counter.addr_refs)) {
|
Throw_first_pass_warning("Found new \"!for\" syntax.");
|
||||||
Throw_first_pass_warning("Wrong type for loop's END value - must match type of START value.");
|
loop.u.counter.first = intresult.val.intval; // use first argument
|
||||||
}
|
ALU_defined_int(&intresult); // read second argument
|
||||||
// setup direction and total
|
// compare addr_ref counts and complain if not equal!
|
||||||
if (loop.u.counter.first <= intresult.val.intval) {
|
if (config.warn_on_type_mismatch
|
||||||
loop.iterations_left = 1 + intresult.val.intval - loop.u.counter.first;
|
&& (intresult.addr_refs != loop.u.counter.addr_refs)) {
|
||||||
loop.u.counter.increment = 1;
|
Throw_first_pass_warning("Wrong type for loop's END value - must match type of START value.");
|
||||||
|
}
|
||||||
|
// setup direction and total
|
||||||
|
if (loop.u.counter.first <= intresult.val.intval) {
|
||||||
|
// count up
|
||||||
|
loop.iterations_left = 1 + intresult.val.intval - loop.u.counter.first;
|
||||||
|
loop.u.counter.increment = 1;
|
||||||
|
} else {
|
||||||
|
// count down
|
||||||
|
loop.iterations_left = 1 + loop.u.counter.first - intresult.val.intval;
|
||||||
|
loop.u.counter.increment = -1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
loop.iterations_left = 1 + loop.u.counter.first - intresult.val.intval;
|
// old counter syntax
|
||||||
loop.u.counter.increment = -1;
|
loop.algorithm = FORALGO_OLDCOUNT;
|
||||||
|
if (config.wanted_version >= VER_NEWFORSYNTAX)
|
||||||
|
Throw_first_pass_warning("Found old \"!for\" syntax.");
|
||||||
|
if (intresult.val.intval < 0)
|
||||||
|
Throw_serious_error("Loop count is negative.");
|
||||||
|
// count up
|
||||||
|
loop.u.counter.first = 1;
|
||||||
|
loop.iterations_left = intresult.val.intval; // use given argument
|
||||||
|
loop.u.counter.increment = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// old format - booo!
|
// iterator syntax
|
||||||
loop.algorithm = FORALGO_OLD;
|
loop.algorithm = FORALGO_ITERATE;
|
||||||
if (config.wanted_version >= VER_NEWFORSYNTAX)
|
// check for "in" keyword
|
||||||
Throw_first_pass_warning("Found old \"!for\" syntax.");
|
if ((GotByte != 'i') && (GotByte != 'I')) {
|
||||||
if (intresult.val.intval < 0)
|
Throw_error(exception_syntax);
|
||||||
Throw_serious_error("Loop count is negative.");
|
return SKIP_REMAINDER; // FIXME - this ignores '{' and will then complain about '}'
|
||||||
loop.u.counter.first = 1;
|
}
|
||||||
loop.iterations_left = intresult.val.intval; // use given argument
|
/* checking for the first character explicitly here looks dumb, but actually
|
||||||
loop.u.counter.increment = 1;
|
solves a purpose: we're here because the check for comma failed, but maybe that
|
||||||
|
was just a typo. if the current byte is '.' or '-' or whatever, then trying to
|
||||||
|
read a keyword will result in "No string given" - which is confusing for the
|
||||||
|
user if they did not even want to put a string there.
|
||||||
|
so if the current byte is not the start of "in" we just throw a syntax error.
|
||||||
|
knowing there is an "i" also makes sure that Input_read_and_lower_keyword()
|
||||||
|
does not fail. */
|
||||||
|
Input_read_and_lower_keyword();
|
||||||
|
if (strcmp(GlobalDynaBuf->buffer, "in") != 0) {
|
||||||
|
Throw_error("Loop var must be followed by either \"in\" keyword or comma.");
|
||||||
|
return SKIP_REMAINDER; // FIXME - this ignores '{' and will then complain about '}'
|
||||||
|
}
|
||||||
|
if (force_bit) {
|
||||||
|
Throw_error("Force bits can only be given to counters, not when iterating over string/list contents.");
|
||||||
|
return SKIP_REMAINDER; // FIXME - this ignores '{' and will then complain about '}'
|
||||||
|
}
|
||||||
|
ALU_any_result(&loop.u.iter.obj); // get iterable
|
||||||
|
loop.iterations_left = loop.u.iter.obj.type->length(&loop.u.iter.obj);
|
||||||
|
if (loop.iterations_left < 0) {
|
||||||
|
Throw_error("Given object is not iterable.");
|
||||||
|
return SKIP_REMAINDER; // FIXME - this ignores '{' and will then complain about '}'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GotByte != CHAR_SOB)
|
if (GotByte != CHAR_SOB)
|
||||||
Throw_serious_error(exception_no_left_brace);
|
Throw_serious_error(exception_no_left_brace);
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#define RELEASE "0.97" // update before release FIXME
|
#define RELEASE "0.97" // update before release FIXME
|
||||||
#define CODENAME "Zem" // update before release
|
#define CODENAME "Zem" // update before release
|
||||||
#define CHANGE_DATE "23 Oct" // update before release FIXME
|
#define CHANGE_DATE "24 Oct" // update before release FIXME
|
||||||
#define CHANGE_YEAR "2020" // update before release
|
#define CHANGE_YEAR "2020" // update before release
|
||||||
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
|
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
|
||||||
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
||||||
|
Loading…
x
Reference in New Issue
Block a user