Jump to content
IGNORED

Asking for Basic++ beta testing


thorfdbg

Recommended Posts

Hi folks,

 

currently working on a new release of Atari++, the Linux Atari emulator. This release will feature (amongst others) an updated Os++ operating system and also a built-in Atari-basic compatible basic dialect, named "Basic++". I'm attaching both the new Os++ release and the Basic++ binary plus sources (note it's an 8K cartridge image!). I'm kindly asking for testing. Also, there are still around 300 bytes free in Basic++ that could be utilized for something "small and useful". I could use it to unroll some of the loops (improving performance, maybe) or I could use it from some small Turbo Basic compatible extensions. Note that I'm not trying to create a new Basic dialect here, compatibility is one one of the goals.

 

basic++.zipos++.zip

 

From the README of Basic++:


This is based on Atari Basic, as developed by Paul Laughton and Kathleen O'Brien,
Shepardson Microsystems, as found in: The Atari BASIC SOURCE BOOK by
Bill Wilkinson, Compute! Publications (1983)

Basic++ fixes a couple of known Atari Basic bugs and includes a couple of improvmenents
without impacting compatibility with existing basic code. It does not attempt to
extend the Atari Basic dialect beyond its current syntax. If you are interested in a
more powerful Atari Basic, get TurboBasic, Basic XL or Basic XE. Basic++ is a
"best efford" to squeeze as many useful Basic features into the 8K cartridge ROM space
as possible.

Basic++ sources are based on Rev.A Atari Basic, as published in the Compute! book
cited above, with many improvements and refinements. Source code was completely reviewed
and refined, and was made more concise to the original leaving headroom for some new
features.

At this time, the following Atari Basic bugs have been fixed:

- The parser allowed INPUT without any parameters. Now it needs to take at least one
variable.
- A Ctrl-U as last component of a string argument to PRINT worked as if the PRINT
statement included a semicolon.
- It was possible to DIM two-dimensional arrays overrunning the available memory
because any type of overflow check was missing.
- A downwards block move of an exact multiple of 256 bytes moved the wrong memory.
- Basic Rev. A crashed on cascaded versions of multiple unary operators, in particular
PRINT NOT NOT A or PRINT ++2 or PRINT --X crashed. Atari "resolved" this issue in
Rev.B by not parsing such expressions, Basic++ allows then and implements them
correctly.
- LOCATE apparently did not restore the input buffer pointer correctly and could have
caused errors if followed by a VAL() that required the pointer to be seated
correctly. Basic++ fixes VAL.

The following improvements have been made:

- The SQR function in Atari Basic was unbearably slow and unprecise as it uses the
ancient Heron method. Numerical inaccuracies of the math pack division pile up and
resulted in loss of accuracy. The new code uses a "digit by digit" algorithm that
is not only faster, but precise up to the last digit ("one ulp" precision).
- The power function ("^" operator) was implemented in a very naive way and resulted
in precision loss. Atari "fixed" that in Rev.B by rounding results, Basic++ uses a
"divide and conquer" method by first computing the integer part and splitting off
the fractional part when necessary. This improves precision and stability and
ensures correct results for integer arguments.
- Atari Basic stored line numbers and offsets as return address for FOR-NEXT loops and
GOSUB expressions and hence required a complete line-search to return to the
previous statement. Similar to TurboBasic, Basic++ stores in addition an absolute
address and continues from this address directly bypassing the search if it can
ensure that the source code has not been modified in between.
- Atari Basic used a very ugly and hacky method of temporarily fiddling an EOL into
strings used as file specifications when interfacing to CIO. Basic++ avoids touching
the user program or code and copies the string before modifying it.
- Basic++ allows an empty second argument to LIST to list up to the end of the source,
i.e. "LIST 100," lists all lines from line 100 on.
- Basic++ handles denormalized floating point numbers now correclty, especially when
comparing numbers and testing numbers for zero.
- Basic++ "string variable splicing" now also allows empty splices. In particular,
if "A$="HELLO"", then A$(6) is valid and returns the empty string. Similarly,
A$(4,3) is the empty string. This avoids some pointless boundary checks when splicing
strings.
- If RESET was pressed in the middle of a line or variable insertion, Atari Basic might
have left an unusable program that crashed the system on a LIST. Basic++ will detect
such cases and will clean up its program areas in such a case.

  • Like 10
Link to comment
Share on other sites

Compatibility issues (using XL/XE OS ver. 2):

 

SETCOLOR 1,256,10 throws an error. This breaks NAZZ.BAS (attached).

ASC("") now throws an error.

PRINT -0 prints "-<8".

ATN(-0) throws an error.

INPUT #256;A$ throws an error.

--1 is parsed as 36 36 0E 40 01 00 00 00 00, which Atari BASIC executes incorrectly. Atari BASIC parses --1 as 36 0E C0 01 00 00 00 00, which does execute correctly.

 

Possible bugs:

DIM A$(10):A$(11)="X" executes without an error.

 

NAZZ.bas

Link to comment
Share on other sites

Well,

 

how about a DIR command ? And errrm, a XEX fileversion would still be nice to have... ;-)

Yes, "DIR" is also on the top of my wish-list. However, if you look at the TurboBasic tokens, it's so far back in the token list that I would need to include a lot of other stuff as well to keep it compatible with TurboBasic - for which I simply don't have the ROM space, so I afraid it will not be included likely.

 

However, there is a way out: The os++ support disk (see the atari++ home page) includes Diskio++, which gives you DIR (amongst a lot of other nice things), and the best part is, it only costs a minimum number of bytes because Diskio++ is aware of the Os++ overlay manager, so it can place itself behind the basic ROM.

Link to comment
Share on other sites

Compatibility issues (using XL/XE OS ver. 2):

 

SETCOLOR 1,256,10 throws an error. This breaks NAZZ.BAS (attached).

ASC("") now throws an error.

PRINT -0 prints "-<8".

ATN(-0) throws an error.

INPUT #256;A$ throws an error.

--1 is parsed as 36 36 0E 40 01 00 00 00 00, which Atari BASIC executes incorrectly. Atari BASIC parses --1 as 36 0E C0 01 00 00 00 00, which does execute correctly.

 

Possible bugs:

DIM A$(10):A$(11)="X" executes without an error.

 

 

SetColor and I believe lots of other functions use now strict range checking. I also had this in SOUND, namely: If the argument should be between 0 and 255 because it is really really a byte. For SOUND, I reverted this because apparently just too many programs are broken and use improper arguments for the frequency and the volume, and that's currently all that is allowed. Not sure I'll keep it like this, but it makes sense.

 

That ASC("") throws an error is intentional, and that it did not is a bug in Atari basic. What is it that it takes the ASC from in first place, after all?

 

Print -0 prints 0 here. The problem is that you're likely using the original math pack, and the original math pack is also buggy. It cannot handle signed zeros (amongst others), but Atari basic can generate one. The above *could* be worked around by parsing "-0" as a single token, and not as a sequence of two tokens. However, this would still allow constructions like "A=0:A=-A:PRINT A", and then I would have to add code into the "unary minus". Actually, I would like to have signed zeros, they make a lot of sense for numerics. IOW, please use a fixed math pack.

 

Same with ATN(-0). That gives me simply a zero here. Not sure what goes wrong in the original math pack, but apparently something does. Same reason. It cannot handle signed zeros.

 

INPUT #256;A$ throws an error, and rightfully so. There are only IOCBs from 0 to 7. Everything else is illegal, and correctly so. See also my comment on SETCOLOR. It's the same proper range checking that is in place.

 

As for "--1", yes, that's indeed parsed as two unary minus operators, which Basic++ can handle correctly. Actually, how that is parsed depends on the Basic revision. Rev. A parses it as Basic++, but crashes when trying to execute. In Rev.B and on Atari added a "hotfix" simply by disallowing cascaced unary operators - instead of fixing the priority table of the unary operators, which is really the cause of the problem. Thus, they fixed the bug in the wrong place. I'll check whether it would be possible to parse this in a different way for optimal compatibility (this should not be too hard), but it is as said really revision dependent. So thanks!

 

That A$(11) executes without error is pretty much intentional. I actually removed this check here because it makes a lot of sense to handle this as an "empty string" case as it avoids some border checks in programs. Similarly, A$(4,3) executes without error and gives you the empty string.

 

On my way, I found a couple of other bugs, A couple of interesting stuff really. Due to a bug in the ABML, STATUS, POINT and NOTE are allowed to take arrays as arguments, i.e. things like STATUS #1,A(0) is parsed correctly. However, neither the implementation of STATUS nor of NOTE can actually take an array here. Instead, they just create nonsense and damage the array structure. Thus, I fixed the ABML for STATUS and NOTE. GET and INPUT have the same problem that they cannot take arrays, and I'll check whether there is enough room left to add this as an additional case.

 

POINT was not allowed to take anything but numeric variables and arrays, which is strange because the command actually takes arbitrary expressions. So I fixed this and allow now the more generic syntax.

 

And there is more funky stuff: The expression CHR$(a) = CHR$(b) always returned true, no matter what a and b are. This is because Basic built a temporary string in page 5 and passes its pointer around. Unfortunately, it always builds the string in the same place, so the second CHR$ overwrites the string of the first. The same problem applies for STR$(), so STR$(a) = STR$(b) was always true if the number of digits in a was identical to the number of digits in b (wierdo!).

 

Both of these bugs got fixed.

 

Here's the result of yesterday's bug fixing session:

basic++.zip

 

I'll probably check for changing the parsing priority of unary operators and numbers (this should be relatively easy) and reconsider SETCOLOR (though I really like the current range checks in place!). A somewhat harder task would be to allow arrays for INPUT, GET, STATUS, NOTE and LOCATE. It's a really anoying limitation.

Link to comment
Share on other sites

Yes, "DIR" is also on the top of my wish-list. However, if you look at the TurboBasic tokens, it's so far back in the token list that I would need to include a lot of other stuff as well to keep it compatible with TurboBasic - for which I simply don't have the ROM space, so I afraid it will not be included likely.

 

However, there is a way out: The os++ support disk (see the atari++ home page) includes Diskio++, which gives you DIR (amongst a lot of other nice things), and the best part is, it only costs a minimum number of bytes because Diskio++ is aware of the Os++ overlay manager, so it can place itself behind the basic ROM.

 

Hmmm,

 

as phaeron told me in the Altirra topic, the DIR token of Basic XL/Basic XE/Altirra Basic (and maybe others?) is not compatible with the DIR token of TB XL. Thus, if you cannot make the DIR token of Basic++ compatible with TB XL, maybe you can still implement the DIR token and make it compatible with Basic XL/XE/Altirra Basic ?!? Just a thought...

Link to comment
Share on other sites

Hi!

 

Print -0 prints 0 here. The problem is that you're likely using the original math pack, and the original math pack is also buggy. It cannot handle signed zeros (amongst others), but Atari basic can generate one. The above *could* be worked around by parsing "-0" as a single token, and not as a sequence of two tokens. However, this would still allow constructions like "A=0:A=-A:PRINT A", and then I would have to add code into the "unary minus". Actually, I would like to have signed zeros, they make a lot of sense for numerics. IOW, please use a fixed math pack.

Oh, I think that you are opening a can of worms there. This is because in BASIC, as the only data type is floating point, we need to use "-0" in multiple integer contexts, so we need that -0 acts like 0.

 

To properly support this, you would need:

-> 0 == -0 in comparisons. This works.

-> -0 * 1 = -0, -0 * -1 = 0. This does not work.

-> poke -0, ARRAY(-0), etc. This does not work.

 

I personally dislike that negative zeros were added to IEEE-754 :)

Link to comment
Share on other sites

Print -0 prints 0 here. The problem is that you're likely using the original math pack, and the original math pack is also buggy. It cannot handle signed zeros (amongst others), but Atari basic can generate one. The above *could* be worked around by parsing "-0" as a single token, and not as a sequence of two tokens. However, this would still allow constructions like "A=0:A=-A:PRINT A", and then I would have to add code into the "unary minus". Actually, I would like to have signed zeros, they make a lot of sense for numerics. IOW, please use a fixed math pack.

 

Same with ATN(-0). That gives me simply a zero here. Not sure what goes wrong in the original math pack, but apparently something does. Same reason. It cannot handle signed zeros.

 

Um... this is a really bad idea. Negative zero not only isn't a valid Atari floating-point value, it is explicitly excluded by the definition of the format on page 129, Section 8 of the Atari OS Manual:

 

 

Zero is represented by a zero mantissa and a zero exponent. To test for a result from any of the standard routines, test either the exponent or the first mantissa byte for zero.

 

The absolute value of floating point numbers must be greater than 10**-98 and less than 10**-98, or be equal to zero. There is perfect symmetry between positive and negative numbers with the exception that negative zero is never generated.

 

Signed zero is a standard concept in modern math libraries, but it is not supported by the math pack. If you want to add support in your interpreter for negative zero, that's fine, but if your interpreter writes out BASIC programs that have this constant embedded, it is not compatible with Atari BASIC, and if it does not run correctly with the standard math pack built into the Atari OS ROM, it isn't an Atari program. You can't call the math pack with a floating-point representation that is documented as prohibited and claim that the math pack is broken.

  • Like 2
Link to comment
Share on other sites

Is there a single case in the real world where negative zero has any meaning other than zero?

 

0*0=0

-0*0=0

-0*-0=0

 

How can there even be such a number?

 

I'm expecting a reply from a "higher math" type, which is welcome, but please read the first sentence where I specify "real world" before you reply. :)

 

Maybe that's the math AlGore's buddies used to come up with their (completely debunked and laughable) "hockey stick".

  • Like 1
Link to comment
Share on other sites

Yes. In IEEE 754, negative zero is defined as equal to zero for comparison purposes, but it exists so that the sign can be preserved in certain sequences of operations. It's great fun for those who are doing floating-point representation hacks and discover that their fast floor-to-int routine converts -0 to -1. It's a perfectly fine and well accepted phenomenon in numeric computation, but it just isn't supported by the Atari math pack.

  • Like 1
Link to comment
Share on other sites

OK, if it is equal to zero, then why not just let it be equal to zero? Zero has no sign, + or -. Maybe -0.000000000000000001 would round to -0, but, in reality, who cares?

 

Please forgive me, but I process data as it pertains to reality, I really don't care what the IEEE says about -0. Is this really important in the scope of Atari BASIC?

 

I'm not trying to be disagreeable, I want to know the real reason behind this, not the IEEE reason, but the real reason.

Link to comment
Share on other sites

Hi!

 

 

Oh, I think that you are opening a can of worms there. This is because in BASIC, as the only data type is floating point, we need to use "-0" in multiple integer contexts, so we need that -0 acts like 0.

 

To properly support this, you would need:

-> 0 == -0 in comparisons. This works.

-> -0 * 1 = -0, -0 * -1 = 0. This does not work.

-> poke -0, ARRAY(-0), etc. This does not work.

 

I personally dislike that negative zeros were added to IEEE-754 :)

Sorry, but from that I see that you haven't actually tried. In fact, -0*1 equals 0 (or -0), and that's one part of the fixes Basic++ includes. Namely, to make the math functions aware of denormalized numbers and signed zeros...

Link to comment
Share on other sites

 

Um... this is a really bad idea. Negative zero not only isn't a valid Atari floating-point value, it is explicitly excluded by the definition of the format on page 129, Section 8 of the Atari OS Manual:

 

Now they are. Quite simple. It's an extension. Same goes for denormalized numbers. That the original math pack claims that numbers must be larger than 1E-98 in absolute value to be non-zero is a similar mis-definition, and shows that the authors had really no clue about numerics. Even more so as the original code actually generates such numbers in some cases - and then falls off when trying to normalize them....

 

So for example, try this:

 

? SQR(1E-60*1E-60)

 

This gives the correct answer, 1E-60, even though the intermediate result is denormalized, denormalized numbers still allow you to carry around the intermediate result correctly.

 

Of course, if you try to print them, they give you a zero.

A=1E-60

?A*A

0

 

But they are not zero:

 

?A*A=0

0

Link to comment
Share on other sites

OK, if it is equal to zero, then why not just let it be equal to zero? Zero has no sign, + or -. Maybe -0.000000000000000001 would round to -0, but, in reality, who cares?

 

Please forgive me, but I process data as it pertains to reality, I really don't care what the IEEE says about -0. Is this really important in the scope of Atari BASIC?

 

I'm not trying to be disagreeable, I want to know the real reason behind this, not the IEEE reason, but the real reason.

A pretty good and quite useful source for all this floating point stuff is the following:

 

http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

 

It also gives a good argument why the choice of the base of 100 for the floating point representation was a particularly bad one.

Link to comment
Share on other sites

Ok, so this is a short update with some additional fixes. I still wasn't happy with CHR$ and STR$, despite being simple, these functions create some fun when used twice in the same expression. I hope this is fine now.

 

GOTO and GOSUB now try to avoid backwards searches when possible, so that helps to improve speed, sometimes a lot.

 

Number parsing still had one bug in os++, namely "-" and "+" where considered valid representations of zero (which they are not), and basic++ parses now negative numbers as one token, not two. Thus, "-0" is parsed as 0E 80 00 00 00 00 00 and not as "unary minus" "zero". This helps to avoid some compatibility issues with Rev.B basic which also parses "--1" as two tokens, not one, same as Basic++.

 

I still had a bug in sqrt by forgetting to re-load the exponent value in some cases giving wrong results, so that got fixed. The BCDToInt function in the math pack still had one race condition, which also got fixed.

 

Last but not least, I also looked into the possibility of extending INPUT, LOCATE, GET, STATUS and NOTE to accept arrays, but not this time. This requires a bit more care than I thought due to the way how Basic evaluates expressions. For for curiosity,

 

A(1) = 5

 

is not evaluated "as you might have guessed" by first taking the address of A(1) and then evaluating the right side and assigning the result as a side effect of the "=" operator, but rather the right hand side is evaluated first, the "=" operator rather sets a flag, and the assignment happens as a side-effect of the opening bracket once the arguments are parsed. Hence, it is not "=" which does the work, but "(" does. This makes re-using some of the code (remember we're tight of ROM space!) a bit harder than I thought.

 

os++.zipbasic++.zip

 

Link to comment
Share on other sites

Ok, so this is a short update with some additional fixes. I still wasn't happy with CHR$ and STR$, despite being simple, these functions create some fun when used twice in the same expression. I hope this is fine now.

GOTO and GOSUB now try to avoid backwards searches when possible, so that helps to improve speed, sometimes a lot.

Number parsing still had one bug in os++, namely "-" and "+" where considered valid representations of zero (which they are not), and basic++ parses now negative numbers as one token, not two. Thus, "-0" is parsed as 0E 80 00 00 00 00 00 and not as "unary minus" "zero". This helps to avoid some compatibility issues with Rev.B basic which also parses "--1" as two tokens, not one, same as Basic++.

I still had a bug in sqrt by forgetting to re-load the exponent value in some cases giving wrong results, so that got fixed. The BCDToInt function in the math pack still had one race condition, which also got fixed.

 

I'm now again allowing SETCOLOR with arguments >255, though I'm really not happy about that. Maybe this should really fail.

 

IOCBs larger than 7 are now explicitly filtered out, and IOCB #0 is also consistently disallowed. Specifically, PRINT #0 and INPUT #0 now both fail, very much like all their other counterparts that work on devices. Before, they were the only exception of allowing IOCB #0 there probably due to an oversight. No, if you believe that INPUT #0 would have spared you the question mark on the console, you are wrong. INPUT #0,A does exactly the same as INPUT A, so no advantage could be gained anyhow.

 

Last but not least, I also looked into the possibility of extending INPUT, LOCATE, GET, STATUS and NOTE to accept arrays, but not this time. This requires a bit more care than I thought due to the way how Basic evaluates expressions. For for curiosity,

A(1) = 5

is not evaluated "as you might have guessed" by first taking the address of A(1) and then evaluating the right side and assigning the result as a side effect of the "=" operator, but that is not the case. Rather the right hand side is evaluated first, the "=" operator sets a flag, and the assignment happens as a side-effect of the opening bracket once the arguments are parsed. Hence, it is not "=" which does the work, but "(" does. This makes re-using some of the code (remember we're tight of ROM space!) a bit harder than I thought.

 

os++.zip basic++.zip

 

Link to comment
Share on other sites

as phaeron told me in the Altirra topic, the DIR token of Basic XL/Basic XE/Altirra Basic (and maybe others?) is not compatible with the DIR token of TB XL. Thus, if you cannot make the DIR token of Basic++ compatible with TB XL, maybe you can still implement the DIR token and make it compatible with Basic XL/XE/Altirra Basic ?!? Just a thought...

Yes, though I haven't checked where Basic XL/XE place DIR in the token list. Unless it is really the next available token, it is getting quite hard to add it, with a lot of unorthogonal checks I would had to add. One way or another, I do not like the idea of creating too much of a new dialect here. TurboBasic became somewhat the gold standard and the most accepted dialect, so if all possible, I want to keep as much compatible to it as I possibly can.

 

And as said, there is a really simple way of getting "DIR". Did I say "DiskIO"? (-:

Link to comment
Share on other sites

IOCBs larger than 7 are now explicitly filtered out, and IOCB #0 is also consistently disallowed. Specifically, PRINT #0 and INPUT #0 now both fail, very much like all their other counterparts that work on devices. Before, they were the only exception of allowing IOCB #0 there probably due to an oversight. No, if you believe that INPUT #0 would have spared you the question mark on the console, you are wrong. INPUT #0,A does exactly the same as INPUT A, so no advantage could be gained anyhow.

 

You probably won't be happy about this... but there are programs that abuse a related bug in Atari BASIC to avoid that prompt by requesting IOCB #16. I was made aware of this when people were testing my BASIC interpreter. It's bogus, but it's the price of compatibility.

 

Last but not least, I also looked into the possibility of extending INPUT, LOCATE, GET, STATUS and NOTE to accept arrays, but not this time. This requires a bit more care than I thought due to the way how Basic evaluates expressions. For for curiosity,

 

A(1) = 5

 

is not evaluated "as you might have guessed" by first taking the address of A(1) and then evaluating the right side and assigning the result as a side effect of the "=" operator, but that is not the case. Rather the right hand side is evaluated first, the "=" operator sets a flag, and the assignment happens as a side-effect of the opening bracket once the arguments are parsed. Hence, it is not "=" which does the work, but "(" does. This makes re-using some of the code (remember we're tight of ROM space!) a bit harder than I thought.

 

Interesting, so they shifted the left hand side and deferred it until after the right hand side. The way I handled this in my BASIC interpreter was to set a flag going into the expression evaluator and store the pointer to the lvalue whenever the lvalue was placed at the bottom of the argument stack. This solution partly arose because the rules for checking string subscripts are different for the outermost subscript on the left hand side than in any other case. In particular, if LEN(A$)=3, A$(5) is valid on the left but invalid on the right, and A$(LEN(A$(5))) is also invalid. It also avoided the need to store the variable token on the stack.

 

  • Like 1
Link to comment
Share on other sites

I didn't even realize INPUT #16 relied on a bug, but it's described here:

 

http://www.page6.org/archive/issue_32/page_12.htm

 

Definitely in common use for as long as I can recall, though.

Actually, the bug is that the code in Rev.A through C only test the IOCB for zero, but then upshift the channel number by four, shifting out and ignoring the upper nibble completely. Thus, #16 is really a Basic bug and should not work. After all, there are only eight channels (#0 through #7). If you want an INPUT without a question mark, the right strategy is to open a channel to the editor and input from there.

Link to comment
Share on other sites

I thought that's basically what the Page 6 article said (upper nybble shifted out). In any case, fixing bugs is laudable, but I guess the CTRL+U behaviour was left in TBXL for the same reason (optionally, IIRC), since simply fixing it would break existing software.

Actually, this specific bug in PRINT was left in TurboBasic because Frank just copied that from Rev.A without further thinking about. Probably from the same source where I found a documented ROM listing. The bug was already fixed in Rev.B and Rev.C by Atari. So no, I'm certainly not undoing this specific bugfix. About the IOCB issue, I'm probably thinking allowing #16 as only exception.

Link to comment
Share on other sites

At this point, only one fix for the mathpack, a pretty embarrasing bug which I had the "BCDtoInt" conversion (yes, really) I don't want to leave like this.

 

os++.zip

 

I also have a prototypical implementation for input,get,note,locate,get and status with arrays running, but I believe I should first make a couple of more serious tests with what I did.

 

The cool thing is that you can now do something like

 

INPUT A,C(A)

 

which first reads the array index, and then fills the array at the given index at the same spot.

 

I finally understand why Shepardson did not include all this in their version of Basic. The modifications required some hairpulling, but in the end, also helped to make the code better. Unfortunately, Atari basic does not have a very clear interface design, so which function uses which RAM locations and updates which other data is not consistent, and comparable functions sometimes work quite different. As said, the array assignment is really rough, and from the code you can tell that Shepardson already tried to squeeze out every byte. The same function is used for array dimensioning, array assignment and array evaluation, just depending on the AssignFlag. It's quite hacky.

 

 

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...