CompileIt! はC言語を使っている方にも便利なツールです。なんたって HyperTalk でプログラムを組めます。C言語の煩わしさから開放された壮快感は、HyperTalk をネイティブな言語とする人ならきっと分かって貰えると思います。


○ HyperCard 内で全てが完結する
CompileIt! は良くも悪くも「 HyperCard スタック」です。HyperCard 以外のアプリを立ち上げる必要がなく、ターゲットスタックを開いたままで、ソースの編集、コンパイル、インストール、テスト、そしてソース修正の一連の作業が、HyperCard の上で行えます。

○ XCMD に特化している
いわゆる main 関数はなく、普通の HyperTalk のハンドラを書くのと同じようにソースを書くことが出来ます。引数や返値も普通のハンドラと全く同じに書けます。受け取った引数は自動的に必要な型に変換され、HyperCard に値を返す時は CompileIt! が自動的にC文字列を作ります。

○ 変数宣言がない
HyperTalk ですから変数宣言はありません。変数の型は CompileIt! が最適なものを推測して割り当てます。これは諸刃の剣ですが、私にとっては実に快適な環境です。CompileIt! が変数にどのような型を割り当てたのかは、コンパイル後に確認することが出来ます。

CompileIt! では 、HyperTalk から ToolBox にアクセスするために以下のような工夫がなされています。


○ ToolBox
CompileIt! では、.h ファイル、.o ファイルに相当するものを、スタックである CompileIt! 自身がカードやリソースとして持っています。 void型の関数はコマンドとして、関数型のコールは関数として、普通の HyperTalk のように書くことが出来ます。新しい関数はカードを追加するという形でインストールされます。

○ コールバック
CompileIt! ではコールバックを意識することがほとんどありません。例えば StrToLong を使わずとも、文字列変数をそのまま足し算に用いることが出来ます。変数や定数を式の中で使うとき、あるいは ToolBoxルーチンに渡す時、CompileIt! が自動的にコンバート作業をしてくれます。ただしそのままでは効率が悪いので、多少の最適化をほどこしてやる必要がある場合があります。

○ Pascal構文によるアクセス
参照、逆参照、配列など、HyperTalk に無い構文については、Pascal構文が取り入れられています。もともと変数の型そのものが無いために、配列アクセスでは要素の型を指定して読み書きします。
  逆参照オペレータ ... ptr@ handle@@
  参照オペレータ  ... @var @filter
  構造体メンバー  ... structRec.member  structPtr@.member
  配列       ... ptr@.varType[ n ]


UDI's XCMD Lib. には、私が CompileIt! で作ったXがたくさんあります。全てソース付きですから、ダウンロードして眺めてみて下さい。

参考として UxGetInputLevel のCのソースと、全く同じものの CompileIt! 版を載せます。私のCのソースはちょっとクセがあって読みにくいかも知れません(実力の程が知れますね(^^;)が、CompileIt! のソースのシンプルさは感動ものですよね。


------------------- THINK C 版 -------------------

// --------------------------------
// UxGetInputLevel 1.0(TC)
//	1998.8.30
//	for THINK C 7.1J	Osaka10  tab4
// --------------------------------

#include	"HyperXCmd.h"
#include	Sound.h
#include	SoundInput.h

typedef struct {
	short   status;
	short   volume;
} LevelMeterRec;

void setMyGlobal( XCmdPtr paramPtr, long theValue );
long getMyGlobal(  XCmdPtr paramPtr );


/* ---------- main ---------- */

pascal void  main( XCmdPtr paramPtr ) {
	Str255			theStr;
	OSErr			err;
	char			levelMeterOn = 1;
	long			inRefNum;
	LevelMeterRec	levelMeter;
	
	ZeroToPas( paramPtr, *paramPtr->params[0], theStr );
	
	if ( theStr[1] == '?' ){
		paramPtr->returnValue = PasToZero( paramPtr, "\pUxGetInputLevel() -- get volume   /   UxGetInputLevel(-1) -- close" );
		return;
	}
	if ( theStr[1] == '!' ){
		paramPtr->returnValue = PasToZero( paramPtr, "\pUxGetInputLevel(TC) XFCN v1.0  1998 UDI" );
		return;
	}
		
	
	if ( StrToNum( paramPtr, theStr ) == -1 ){
		inRefNum = getMyGlobal( paramPtr );
		if ( inRefNum != 0 ){
			err = SPBCloseDevice( inRefNum );
		}
		setMyGlobal( paramPtr, 0 );
		
	} else {
	
		inRefNum = getMyGlobal( paramPtr );
		if ( inRefNum == 0 ){
			err = SPBOpenDevice( "\p", siWritePermission, &inRefNum );
			if ( err ){
				paramPtr->returnValue = PasToZero( paramPtr, "\pError : Can't Open Sound device" );
				return;
			}
			err = SPBSetDeviceInfo( inRefNum, siLevelMeterOnOff, &levelMeterOn );
			setMyGlobal( paramPtr, inRefNum );
		}
			
		 err = SPBGetDeviceInfo( inRefNum, siLevelMeterOnOff, ( Ptr)&levelMeter );
		NumToStr( paramPtr, levelMeter.volume, theStr );
		paramPtr->returnValue = PasToZero( paramPtr, theStr );

	}
}

void setMyGlobal( XCmdPtr paramPtr, long theValue ){
	Str255		theStr;
	
	NumToStr( paramPtr, theValue, theStr );
	SetGlobal( paramPtr, "\pgUxGetInputVol", PasToZero( paramPtr, theStr ) );
 }
 
 long getMyGlobal(  XCmdPtr paramPtr ){
 	Str255		theStr;
 	Handle		valueHand;
 	
 	valueHand = GetGlobal( paramPtr, "\pgUxGetInputVol" );
 	ZeroToPas( paramPtr, *valueHand, theStr );
 	DisposHandle( valueHand );
 	return( StrToNum( paramPtr, theStr ) );
 }


------------------- CompileIt! 版 -------------------


-- CompileIt! script

-- UxGetInputLevel 1.0(Cit)
-- 1998.9.05
-- for CompileIt! 2.6

global uData: L -- shared variable

function UxGetInputLevel x
  global gUxGetInputVol -- HyperCard's global
  
  if x is "?" then
    return "UxGetInputLevel() -- get volume   /   UxGetInputLevel(-1) -- close"
  end if
  if x is "!" then
    return "UxGetInputLevel(Cit) XFCN v1.0cit  1998 UDI"
  end if
  
  if x = -1 then
    put gUxGetInputVol into myInRefNum
    if myInRefNum <> 0 then
      get SPBCloseDevice( myInRefNum )
    end if
    put 0 into gUxGetInputVol
    return empty
  end if
  
  put gUxGetInputVol into myInRefNum
  if myInRefNum = 0 then
    get SPBOpenDevice( "", siWritePermission, myInRefNum )
    if it <> 0 then return "Error : Can't Open Sound device"
    get SPBSetDeviceInfo( myInRefNum, siLevelMeterOnOff, 1 )
    put myInRefNum into gUxGetInputVol
  end if
  
  get SPBGetDeviceInfo( myInRefNum, siLevelMeterOnOff, @uData )
  put uData.integerType[2] into theResult
  return theResult
end UxGetInputLevel
inserted by FC2 system


CompileIt! Lab.

UDI's HomePage