The language seems to be a bit of a mix of Pascal and BASIC. From BASIC it keeps easy string operations, though the syntax for sub-strings is completely different, PRINT syntax, editing via line numbers and the overall interpretive approach. From Pascal it gains the assignment syntax, multi-line IF, REPEAT..UNTIL, WHILE.. functions and procedures and maybe CASE? though it doesn't copy the block structure as such - there is no BEGIN .. END or {} as in C. Clearly 6502 BBC BASIC had already started down a similar path with FN/PROC and REPEAT..UNTIL.
I am not sure to what extent it is limited to the implementation for BBC Micro, but this does syntax checking at line entry so providing immediate feedback on at least some errors and, when an error does occur, it places a ^ character at the point it thinks the error is - more friendly than BASIC. For example: The error here is that integer variables in COMAL have a # suffix, not %.
So while messing around with it, I thought I'd implement the primes by trial division algorithm. There are loads of these already on the typewritten software site, some of which we have run in various languages before, but none in COMAL so I wrote one based on the Pascal version:
or as text:
Code: Select all
10 t#:=TIME
20 numprimes:=1000
30 DIM primes(numprimes)
40 found:=0
50 cnt:=2
60 WHILEfound < numprimes DO
70 found:+1
80 primes(found):=cnt
90 PRINT cnt
100 cnt:+1
110 index:=1
120 REPEAT
130 IF cnt MOD primes(index) = 0 THEN
140 cnt:+1
150 index:=0
160 END IF
170 index:+1
180 UNTIL index > found
190 END WHILE
200 t#:=TIME-t#
210 PRINT"Completed in ";t#/100;"s"
Code: Select all
10 DIM primes(100)
20 index=1
30 count=2
40 found=1
50 primes(index)=count
60 PRINT primes(index)
70 REPEAT
80 count=count+1
90 REPEAT
100 v=(count MOD primes(index))
110 index=index+1
120 UNTIL v=0 OR index>found
130 IF v=0 THEN GOTO 170
140 PRINT count
150 primes(index)=count
160 found=found+1
170 index=1
180 UNTIL found=100
What about performance? Using B-Em, no tube, BASIC 2, the BASIC version completed in 48.68s. The COMAL version, same setup, original (low) COMAL ROM, completed in 60.62s. I also translated CLOCKSP into COMAL:
Code: Select all
10 //> ComalSP
20 PRINT"COMAL Timing Program"
30 PRINT"Equivalent to BBC BASIC ClockSP"
40 setup
50 p(41000,realrpt)
60 p(23900,intrpt)
70 p(51200,realfor)
80 p(17800,intfor)
90 p(68800,triglog)
100 p(80500,proced)
110 p(72750,string)
120 tm:=tm/(78/10)
130 PRINT"Combined average ";tm DIV 100;".";tm MOD 100;"Mhz, ";tc;"cs";CHR$(8)
140 END
150 PROC setup
160 a#:=0
170 t#:=TIME
180 REPEAT
190 a#:=a#+1
200 UNTIL TIME>t#+50
210 z:=0
220 z#:=0
230 b:=1
240 b#:=1
250 f:=1/10
260 c:=100
270 c#:=100
280 d:=510
290 d#:=510
300 f#:=3
310 REPEAT
320 c:=c*10
330 c#:=c#*10
340 d:=d*10
350 d#:=d#*10
360 f#:=f#*10
370 f:=f*10
380 a#:=a# DIV 10
390 UNTIL a#<50
400 tm:=0
410 tc:=0
420 END PROC setup
430 FUNC realrpt
440 PRINT"Real REPEAT loop ";
450 t#:=TIME
460 a:=z
470 REPEAT
480 a:=a+b
490 UNTIL a>c
500 RETURN TIME-t#
510 END FUNC realrpt
520 FUNC intrpt
530 PRINT"Integer REPEAT loop ";
540 t#:=TIME
550 a#:=z#
560 REPEAT
570 a#:=a#+b#
580 UNTIL a#>c#
590 RETURN TIME-t#
600 END FUNC intrpt
610 FUNC realfor
620 PRINT"Real FOR loop ";
630 t#:=TIME
640 FOR a:=z TO d STEP b DO
650 NEXT a
660 RETURN TIME-t#
670 END FUNC realfor
680 FUNC intfor
690 PRINT"Integer FOR loop ";
700 t#:=TIME
710 FOR a#:=z# TO d# STEP b# DO
720 NEXT a#
730 RETURN TIME-t#
740 END FUNC intfor
750 FUNC triglog
760 PRINT"Trig/Log test ";
770 t#:=TIME
780 FOR j#:=1 TO f# DO
790 a:=TAN(ATN(EXP(LN(SQR(a*a)))))+1
800 NEXT j#
810 RETURN TIME-t#
820 END FUNC triglog
830 FUNC string
840 PRINT"String manipulation ";
850 DIM a$ OF 160
860 t#:=TIME
870 a$:="STRINGMANIPULATIONTEST"
880 FOR a#:=0 TO f#*4 DO
890 a$:=(a$(LEN (a$)/4:LEN (a$)/4+1)+a$(LEN (a$)/4:)+a$(LEN (a$)/2:2)+a$(1:LEN (a$)/4)+a$(LEN (a$)/4:LEN (a$)/4+1))(:20)
900 NEXT a#
910 RETURN TIME-t#
920 END FUNC string
930 FUNC proced
940 PRINT"Procedure call ";
950 t#:=TIME
960 FOR a#:=z# TO d# DO
970 tproc
980 NEXT a#
990 RETURN TIME-t#
1000 END FUNC proced
1010 PROC tproc
1020 END PROC tproc
1030 PROC p(s,t)
1040 m:=f*s/t
1050 tm:+m
1060 tc:+t
1070 PRINT m DIV 100;".";m MOD 100;"Mhz, ";t;"cs";CHR$(8)
1080 END PROC p
I don't think there is anything inherent in the COMAL language that makes it slower to interpret than BASIC but maybe this particular COMAL has used more ROM space on parsing the text as it is entered and friendly error reporting that the execution part doesn't have space for faster algorithms? Maybe, if I get more chance/enthusiasm to work on the disassembly this may become clear.
But if you don't mind the lack of speed, it seems like a nice language.