Full BASIC assumes the program has been compiled when the execution starts. Thus no program that rewrites itself can be executed.
We free Decimal BASIC from this restriction by writing out a program to a file and executing a CHAIN or EXECUTE statement.
Example.
A program that plots a graph of a function that is entered in syntax of BASIC.
100 REM Enter a function of x to plot the graph within the range of -8 to 8. 110 DATA "SET POINT STYLE 1" 120 DATA "SET WINDOW -8,8,-8,8" 130 DATA "DRAW GRID" 140 DATA "FOR x=-8 TO 8 STEP 0.0004" 150 DATA " WHEN EXCEPTION IN" 160 DATA " PLOT POINTS:x,f(x)" 170 DATA " USE" 180 DATA " END WHEN" 190 DATA "NEXT x" 200 DATA "FILE DELETE ""temp.bas""" ! clear away 210 DATA "END" 220 INPUT PROMPT "f(x)=":s$ ! Enter the expression of the function 230 OPEN #1:NAME "temp.bas" ! Write out a BASIC program 240 ERASE #1 250 PRINT #1:"DEF f(x)=";s$ 260 DO 270 READ IF MISSING THEN EXIT DO: s$ 280 PRINT #1:s$ 290 LOOP 300 CLOSE #1 310 CHAIN "temp.bas" ! Execute the program 320 END
Deleting the file "temp.bas" is a job of temp.bas, so, if temp.bas has syntax error and is not exccuted, the file "temp.bas" remains not to be removed. Thus we should run the program again until no syntax error is reported.
If this is the problem, use an EXECUTE statement but a CHAIN statment, write a FILE DELETE statement following the EXECUTE statment.
100 REM Enter a function of x to plot the graph within the range of -8 to 8. 110 DATA "SET POINT STYLE 1" 120 DATA "SET WINDOW -8,8,-8,8" 130 DATA "DRAW GRID" 140 DATA "FOR x=-8 TO 8 STEP 0.0004" 150 DATA " WHEN EXCEPTION IN" 160 DATA " PLOT POINTS:x,f(x)" 170 DATA " USE" 180 DATA " END WHEN" 190 DATA "NEXT x" 200 DATA "GSAVE ""TEMP.BMP"",""4bit""" ! save the graph into a file to finish 210 DATA "END" 220 INPUT PROMPT "f(x)=":s$ ! Enter the expression of the function 230 OPEN #1:NAME "temp.bas" ! Write out a BASIC program 240 ERASE #1 250 PRINT #1:"DEF f(x)=";s$ 260 DO 270 READ IF MISSING THEN EXIT DO: s$ 280 PRINT #1:s$ 290 LOOP 300 CLOSE #1 310 EXECUTE "temp.bas" ! Execute the wriiten out program 320 FILE DELETE "temp.bas" ! clear away 330 WHEN EXCEPTION IN 340 GLOAD "TEMP.BMP" ! recieve the result 350 FILE DELETE "TEMP.BMP" ! clear away 360 USE 370 END WHEN 380 END
In practical use, the written out program elements should be held on a file.
An EXECUTE statment can be used for launching an EXE-file. The parameters for the EXE-file can be designated on the WITH clause of the EXECUTE statement.
Example.
Write out temp.txt and open it with Notepad.
10 DATA "Hello" 20 OPEN #1:NAME "A:temp.txt" 30 ERASE #1 40 READ s$ 50 PRINT #1:s$ 60 CLOSE #1 70 EXECUTE "NOTEPAD.EXE" WITH ("A:temp.txt") 80 END
When the extension ".txt" is associated with Notepad, the line 70 in the above can be replaces with the following.
70 EXECUTE "A:temp.txt"
In general, we can entrust a job to some program that can has a file name as a run paramater.
For example, if another BASIC than Decimal BASIC can deal with a job, with which Decimal BASIC cannot deals, we make a program written in the syntax of that BASIC, write out it into a file and hand it to that BASIC.
If some program sends a mail on launched with a name of the file that contains the an addressee and contents ing name, we can send a mail in an execution of a BASIC program.
When we write
OPTION CHARACTER BYTE
at the beginning of a program, all bytes becomes characters, so that
for any integer from 0 to 255
PRINT #1:chr$(n);
appends a byte at the tail of the file. Note that a semicolon is needed at the end.
That is to say, if we know the format of the files, we can make any binary file.
For example, if we know the format of the sound files, we can compose a sound file so that we play the file. In general, if a program transacts a file indicated as a run-parameter, we can do any task by making a file of demanded format.
Note that the scope of OPTION CHARACTER BYTE is the program unit. If a program has external functions or external subprograms, they may have to have OPTION CHARACTER BYTE.
WAVファイルフォーマットに関する情報は,
WAV ファイルフォーマット があります。
十進BASIC掲示板に実際の作例が掲載されました。たかしさんからの情報ですが,実際の作者は別の方のようです。
なお,プログラムのはじめに
OPTION CHARACTER BYTE
を書いておけば,オプションメニューでの前操作は不要です。
REM testwave.bas 十進BASICによる音声ファイル生成プログラム REM (L:1KHz -10dB 正弦波、R: 振幅 -10dB {パワーは-11.76dB} 白色雑音) REM chr$関数の引数として全ての1バイト整数が許される様に、オプションメニューの REM 「互換性」「動作」で「文字列処理の単位」を「バイト」に設定して実行すること LET d=10 !継続時間(秒) LET f0=1000 !正弦波周波数(Hz) LET db=-10 !生成波形の最大値(±32767を0dBとする) LET fs=44100 !標本化周波数(Hz) LET bps=fs*4 !1秒当りのデータ量(ステレオ16ビット量子化) LET dsize=d*fs*4 !オーディオデータサイズ LET fsize=dsize+36 !ファイルサイズ(先頭8Bを除く) LET fmtsize=16 !フォーマットサイズ LET channel=2^17+1 !ステレオPCMデータの指定 LET reso=2^20+4 !16ビットの指定 LET a=10^(db/20) OPEN #6 : NAME "test.wav" !ファイルを開き、この名前のファイルが ERASE #6 !既に存在していた場合には上書きを指定 LET t0=TIME PRINT #6 : "RIFF"; !以下、wavファイルのヘッダーを作成 CALL out4(fsize) ! PRINT #6 : "WAVEfmt "; ! CALL out4(fmtsize) ! CALL out4(channel) ! CALL out4(fs) ! CALL out4(bps) ! CALL out4(reso) ! PRINT #6 : "data"; ! CALL out4(dsize) !ここまでがヘッダー用の出力 LET al=a*32767 !左チャネル係数 LET ar=a*65535 !右チャネル係数 LET k=f0/fs*PI*2 !引数の刻み LET audio$="" !オーディオデータバッファを初期化 LET count=0 !カウンタをリセット FOR i=1 TO d*fs LET lch=INT(SIN(i*k)*al+0.5) !左チャネルは1kHz正弦波 IF lch<0 THEN LET lch=lch+65536 !負の数は補数表現 LET rch=INT((RND-0.5)*ar+0.5) !右チャネルは白色雑音 IF rch<0 THEN LET rch=rch+65536 !負の数は補数表現 LET audio$=audio$&CHR$(MOD(lch,256))&CHR$(INT(lch/256))&CHR$(MOD(rch,256))&CHR$(INT(rch/256)) LET count=count+1 IF count=64 THEN !バッファデータが所定の長さ(64サンプル256Bがほぼ最適)に達したら PRINT #6 : audio$; !データをファイルに出力して LET audio$="" !バッファを初期化し LET count=0 !カウンタをリセット END IF NEXT i PRINT #6 : audio$; !バッファに残ったデータを出力して CLOSE #6 !ファイルを閉じる PRINT "elapsed time = ";TIME-t0;"seconds" SUB out4(i4) !4バイト整数の出力(little endian) LET j4=i4 FOR m=0 TO 3 PRINT #6 : CHR$(MOD(j4,256)); LET j4=INT(j4/256) NEXT m END SUB END
なお,Windows版十進BASICでは,この後,
PLAYSOUND "test.wav" END
を実行すれば,音が聞けます。
ファイル名を引数として指定して起動したとき,それをどう処理するかは,相手のEXEファイル次第です。
<参照>ver 5.4.0でのCHAIN文,EXECUTE文の動作の変更