can Since the program can't know when it has ended (although it know when it hasn't), you must assure that the programs terminate at the right time. 5.3 PRINTing And Simple Assignment (LET) The This group of programs examines the ability of the implementation to print strings and numbers correctly. Both constants and variables are tested as print-items. variables, of course, have to be given a value before they are printed, and this is done with the LET statement. PRINT is among the most semantically complex statements in BASIC. Furthermore, the PRINT statement is the outstanding case of a feature whose operation cannot be checked internally. The consequence is that this group calls for the most sophisticated user interpretation of any in the test sequence. Please read carefully the specifications in the programs, section 12 of the ANSI standard, and this documentation; the interpretation of test results should then be reasonably clear. The emphasis in this group is on the correct representation of numeric and string values. There is some testing that TAB, comma, and semi-colon perform their functions, but a challenging exercise of these features is deferred until group 14.6 because of the other features needed to test them. be since there are no The PRINTing of strings is fairly straightforward and should relatively easy to check, implementation-defined features which affect the printing. The only possible problem is the margin width. The program assumes a margin of at least 60 characters with at least 4 print zones. your implementation supports only a shorter margin, you must make due allowance for it. The standard does not prescribe a minimum margin. The string overflow test requires careful interpretation. Your implementation must have a defined maximum string length, and the fatal exception should occur on the assignment corresponding to that documented length. If the implementation supports at least 58 characters in the string, overflow should not occur. Be sure, if there is no overflow exception report, that the processor has indeed not lost data. Do this by checking that the output has not been truncated. A processor that loses string data without reporting overflow definitely fails. just follow Checking for a TAB exception is simple enough; the conditional pass/fail messages closely. Note that one section of the test should not generate an exception since, even though the argument itself is less than one, its value becomes one after rounding. 5.3.2 Numeric Constants And Variables In the following discussion, the terms "significand", "exrad", "explicit point", "implicit point", and "scaled" are used in accordance with the meaning ascribed them in the ANSI standard. in The rules for printing numeric values are fairly elaborate, and, moreover, are heavily implementation-dependent; accordingly conscientious scrutiny is in order. There are two rules to keep mind. First, the expected output format depends on the value of the print-item, not its source format. In particular, integer values should print as integers as long as the significand-width can accommodate them, fractional values should print in explicit point unscaled format where no loss of accuracy results, and the rest should print in explicit point scaled format. For example "PRINT 2.1E2" should produce "210" because the item has an integer value, even though it is written in source code in explicit point scaled format. Second, leading zeros in the exrad and trailing zeros in the significand may be omitted. Thus, for an implementation with a significand-width of 8 and an exrad-width of 3, the value 1,230,000,000 could print as "1.2300000E+009" at one extreme or "1.23E+9" at the other. The tests generally display the expected output in the latter form, but it should be understood that extra zeros can be tacked on to the the actual output, up to the widths specified for implementation. The tests in general are oriented toward the minimum requirements of six decimal digits of accuracy, a significand length of six and an exrad-width of two. You must apply standard requirements in terms of your own implementation's widths, however. the 5.4 Control Statements And REM This group checks that the simple control structures all work when used in a simple way. Some of the same facilities are checked more rigorously in later groups. As with PRINT, END and STOP, these features must come early in the test sequence, since a BASIC program cannot do much of consequence without them. If any of these tests fail, the validity of much of the rest of the test sequence is doubtful, since following tests rely heavily on GOTO, GOSUB, and IF. Note especially that trailing blanks should be significant in comparing strings, e.g. "ABC" <> "ABC Subsequent tests which rely on this property of IF will give false results if the implementation doesn't comparison properly. process the to The tests for GOTO and GOSUB exercise a variety of transfers make sure the processor handles control correctly. If everything works, you should get intelligible, self-consistent output. If the output looks scrambled, the test has failed. There are no helpful diagnostics for failures since it is impossible to anticipate exactly how a processor might misinterpret transfers of control. Look carefully at the sample output for the GOTO and GOSUB programs in Volume 2, to know what to expect. the The IF...THEN tests use a somewhat complex algorithm, so pay attention to REM statements if you are trying to understand the logic. On the other hand, these tests are easy to use because they are completely self-checking. You need only look for the pass/fail messages to see if they worked. It is worth noting that the IF...THEN test for numeric values depends on the validity of the IF...THEN test for strings, which comes just before. The error tests are understandable in light of the general rules for interpretation of error programs given earlier. The first of these programs simply checks that the set of valid names is as guaranteed by the standard. In particular, A, AO, and A$ are all distinct. There are no diagnostics for failure, since we expect failures to be rare and it is simple enough to isolate the misinterpretation by modifying the program, if that proves necessary. A later test in group 8.1 tests that the implementation fulfills the requirements for array names. Default initialization of variables is one of the most important aspects of semantics left to implementation definition. Implementations may treat this however they want to, but it must be documented, and you should check that the documentation agrees with the behavior of the program. Thus this is not merely an informative test; the processor must have correct documentation for its behavior in order to conform. 5.6 Numeric Constants, Variables, And Operations 5.6.1 Standard Capabilities the use of numeric arithmetic The most This group of programs introduces expressions, specifically those formed with the operations (+, /, ^) provided in BASIC. troublesome aspect of these tests is the explicit disavowal in the standard of any criterion of accuracy for the result operations. Thus it becomes somewhat difficult to say at what to implement a given operation. We point a processor fails. finally decided to require exact results only for integer arithmetic, and, in the case of non-integral operands, to apply an extremely loose criterion of accuracy such that if an implementation failed to meet it, one could reasonably conclude either that the precedence rules had been violated or that the operation had not been implemented at all. Although the standard does not mandate accuracy for expressions, it does require that individual numbers be accurate to at least six significant decimal digits. This requirement is tested by assuring that values which differ by 1 in the 6th digit actually compare in the proper order, using the IF statement. The rationale for the accuracy test is best explained with an example: suppose we write the constant "333.333" somewhere in the program. For six digits of accuracy to be maintained, it must evaluate internally to some value between 333.3325 and 333.3335, since six digits of accuracy implies an error less than 5 in the 7th place. By the same reasoning, "333.334" must evaluate between 333.3335 and 333.3345. Since the allowable ranges do not overlap, the standard requires that 333.333 compare as strictly less than 333.334. Of course this same reasoning would apply to any two numbers which differed by 1 in sixth digit. The accuracy test not only assures that these minimal requirements are met, but also attempts to measure how much accuracy the implementation actually provides. It does this both by comparing some numbers in the manner described above for 7, 8, and 9 decimal digits, and also by using an algorithm to compute any reasonable internal accuracy. Since such an algorithm is highly sensitive to the peculiarities of the system's implementation of arithmetic, this last test is informative only. 5.6.2 Exceptions The standard specifies a variety of exceptions for numeric expressions. All the mandatory non-fatal exceptions occur when machine infinity is exceeded and they all call for the implementation to supply machine infinity as the result and continue execution. The tests ensure that machine infinity is at least as great as the guaranteed minimum of 1E38, but since machine infinity is implementation-defined, you must assure that the value actually supplied is accurately documented. It is worth repeating here the general guidance that the timing of exception reports is not specified by the standard. The wording is intentionally imprecise to allow implementations to anticipate exceptions, if they desire. Such anticipation may well occur for overflow and underflow of numeric constants; that is, an implementation may issue the exception report before execution of the program begins. Note that the recovery procedure, substitution of machine infinity for overflow, remains in effect. 3 " Underflow, whether for expressions or constants, is only recommended as an exception, but, in any case, zero must be supplied when the magnitude of the result is below the minimum representable by the implementation. Note that this is required in the semantics sections (7.4 and 5.4) of the standard, not exception sections (7.5 and 5.5). the 5.6.3 Errors involution These programs try out the effect of various constructions which represent either common programming errors (missing parentheses) or common enhancements (** as the operator) or a blend of the two (adjacent operators). No special interpretation rules apply to these tests beyond those normally associated with error programs. 5.6.4 Accuracy Tests - Informative Although the standard mandates no particular accuracy for expression evaluation, such accuracy is nonetheless an important measure of the quality of language implementation, and is of interest a large proportion of language users. Accordingly, these tests apply a criterion of accuracy for the arithmetic operations which is suggested by the standard's requirement that individual numeric values be represented accurate to significant decimal digits. Note, however, that these tests are informative, not only because there is no strict accuracy requirement, but also because there is no generally valid way for a computer to measure precisely the accuracy of its operations. Such a measurement involves calculations which must use the very facilities being measured. six own The criterion for passing or failing is based on the concept that an implementation should be at least as accurate as a reasonable hypothetical implementation which uses the least It is accurate numeric representation allowed by the standard. best explained by first considering accuracy for functions of a single variable, and then generalizing to operations, which may be thought of as functions of two variables. Given an internal precision of at least d decimal digits, we simply require that the computed value for f(x) (hereinafter denoted by "cf(x)") be some value actually taken on by the function within the domain [x-e,x+e], where e = 10 ^ (int (log10 (abs (x))) + 1 - d) For example, suppose we want to test the value returned by sin (29.1234) and we specify that d=6. Then: A e = 10 (int (log10 (29.1234)) + 1 - 6) = 10 (int (1.464) - 5) |