Powered by SmartDoc

綾織言語リファレンス

式と文

綾織では,変数・定数・関数などを演算子で結んだものを式と呼びます.代表的な式は,下のようになります.

a * b + 10

式の終わりに;(セミコロン)を付けたものを文と呼びます.式はセミコロンが付いて始めて文になるので,物理的に複数の行にまたがった式を書くことが可能です.

c = a * b + 10; //これと
c = a *
b + 10; //これは同じものになる.

アクション

綾織は,キャラクターの一連の挙動とその実行条件を一緒に記述する「アクション」を定義できます.

定義

アクションの定義は次のとおりです.起動条件が満たされる時,{}内に記述された処理が実行されます.起動条件はboolean型の式で記述します.

action アクション名@( 起動条件 )
{
    そのアクションの処理;
}

起動条件チェック

起動条件のチェックは,すべてのアクションについて1秒に一回チェックされており,その条件が満たされた(真:trueになった)時点でアクションが起動します.ただし,毎秒連続して条件が真となったままのアクションは,最初の一回のみ起動されます.(毎秒,毎回起動することはできない)

アクションの例

アクションの例
action HourUpdate@( Minute() == 0 && Second() == 0)
{
    if( 4 <= Hour() && Hour() <= 10 )
        Talk("おはようございます,"+GetProperty("\\User\\LastName") +"." );
    else if( 11 <= Hour() && Hour() <= 16 )
        Talk( "こんにちは," + GetProperty( "\\User\\LastName" ) + "." );
    else
        Talk( "こんばんは," + GetProperty( "\\User\\LastName" ) + "." );
}

上の例は毎時0分0秒に起動され,そのときの時刻によっておはようございます/こんにちは/こんばんはを切り替えて話しかけるアクションです.Hour()は現在の時刻,Minute()は現在の分,Second()は現在の秒を返す標準関数で,GetProperty( "\\User\\LastName" )では,プロパティのユーザ情報から「ユーザの名字」をstring型で取り出しています.キャラリナの起動時(StartUp),終了時(ShutDown),マウスの左クリック時(MouseUpL),データの更新時(ScriptUpdated)といったタイミングでは,それぞれの名前をもつ「標準アクション」が優先的に起動されます.起動時や終了時のあいさつ,キャラクターを左クリックしたときの挙動などは,これらの標準アクション内に記述することで実現できます.

起動条件チェックの順序

ある時点で同時に実行されるアクションは一つだけです.アクションが実行されている間,前述の起動条件のチェックは行われません.したがって,アクション実行中に他のアクションの起動条件が成立したとしても,そのアクションは実行されません.標準アクションも同様ですが,ShutDownアクション,ScriptUpdatedアクション,ScriptUpdatingアクションは例外的に処理されます.

起動条件チェックの例外

ShutDownアクション,ScriptUpdatedアクション,ScriptUpdatingアクションは,通常の起動条件チェックの順序に従わず,次に示すように処理されます.

ShutDown標準アクション

現在実行中のアクションを強制的に終了させ,ShutDownを実行します.

ScriptUpdated標準アクション

内部的に専用のフラグで処理され,データのダウンロードが終了してから「アクションが一つも実行していない状態」になった時点で起動されます.

ScriptUpdating標準アクション

「更新」を行い,回線が確立されて実際にデータの転送が開始された時点で起動されますが,その時点で他のアクションが実行されていた場合には起動されません.

但し,ScriptUpdatingアクション内でGetHTTP関数を実行している場合,特例としてGetHTTP関数の処理が終了(正常終了またはタイムアウト等のエラーによる終了)するまで回線は保持されます.[1.01?]

関数

関数は,「引数」を介して複数の値を受取り,内部である処理を行い,その処理結果を返り値で返すことが可能な処理単位です.

定義

関数の定義は次のとおりです.引数が複数ある場合は半角コンマ(,)で区切って定義します.

関数データ型 関数名( 引数データ型 引数名 [,引数データ型 引数名].... )
{
    関数で行う処理;
}
関数定義の例
int Zettaichi( int x )
{
    if( x < 0 )
        return -x;
    else
        return x;
}

この例では,「int型の引数を渡すと,int型の返り値を返す,Zettaichiという名前の関数」を定義しています.渡した値xがマイナスの値なら,それにマイナスの符号をつけてプラスに戻し,プラスの値ならそのまま返すことで,xの絶対値を返すという処理を行います.

呼び出し

関数を実際に使うには,

関数名( 引数1, 引数2, ... 引数n );

の書式で関数を呼び出します.関数の返り値を演算や別の関数の引数に用いることも出来ます(出来ないデータ型もあります).

呼び出す関数と呼び出される関数は,ともに同じモジュール(モジュール=.exaファイルに相当.後述)で定義してあれば,特別な宣言なく使用できます.他のモジュールで宣言された関数を使用するには,後述のプロトタイプ宣言が必要です.

関数呼び出しの例
int a = -10;
Talk( "aの絶対値は" + itoa( Zettaiti( a ) ) + "です." );

上の例のように呼び出したしたときの出力は次のとおりです.

関数呼び出し例の実行結果
aの絶対値は10です.

引数,返り値の型

関数の引数や返り値には,変数と同様に,型の区別が存在します.string型の関数の返り値を,直接int型変数に代入したり,string型を渡す必要があるTalk()関数などに,直接int型やdouble型変数を渡すことはできません.

この場合,itoa()やatoi(),ftoa()などの型変換関数を使います.

string a = "20";
string b = "5";
string c = a + b;
int count = atoi( a ) + atoi( b );
int count2 = atoi( c );

このとき,変数countには整数の25が入り,count2には整数の205が入ります.string型の定数は""で囲みます.上の例のとおり,string型変数/定数に対する+演算子は文字列の結合として扱われ,int型に対する+演算子は加算として扱われます.

データ型ついて

綾織の変数のデータ型には,int,double,char,string,booleanの5種類が存在します.

データ型 解説
int 整数型.-2147483648?0?2147483647までの整数を扱える.4バイト.
double 浮動小数点型.8バイト.
char 文字型.1バイト文字一文字のみを扱える.1バイト.
string 文字列型."HogeHoge"のように,ダブルクォーテーションで囲った文字列を扱える.文字数には特に制限はない.
boolean 論理値.trueとfalseの二つの値をもつ.boolean型のみ,if文などの条件式に変数一個のみで記述できる

変数と定数について

宣言

変数は利用に先立って,あらかじめ型宣言しておかなければなりません.

宣言文 解説
int i; int型変数の宣言
int i; int型変数の宣言
int j = 0; 初期値付きの宣言
string a = "abced"; string型の定数は""で囲みます
char c = 'A'; char型の定数は''で囲みます
boolean b = true; boolean型はtrueとfalseのどちらかの値を持ちます
extern int i; 異なるモジュールで宣言されたグローバル変数iを宣言する

変数名

変数の名前には,A-Z,a-z,0-9,_(アンダーバー)の文字が使えます.ただし,数字から始まる変数名は使用できません.変数名の大文字と小文字は区別されます.たとえば,Addressとaddressは別の変数として扱われます.

グローバル変数とローカル変数

変数は,宣言される場所によってグローバル変数かローカル変数に分類できます.

グローバル変数

関数やアクションの外側で宣言された変数です.同一モジュール(同じexaファイル)で定義された関数から,自由にアクセスできます.グローバル変数が持つ値はキャラクターの実行終了時に失われます.異なるモジュールで定義されたグローバル変数にアクセスするには,extern宣言を使用します.

ローカル変数

関数やアクションの内側で宣言された変数です.宣言されたスコープ内で自由にアクセスできます.スコープ外からはアクセスできません.ローカル変数が持つ値は,関数,アクション,スコープの終了と同時に失われます.

スコープ

ローカル変数には「スコープ」の概念が適用されます.関数(アクション)宣言の{}内で宣言された変数は「ローカル変数」と呼ばれ,その関数(アクション)の中だけでアクセスできます.他の関数やアクションから,その変数を読み書きすることはできません.

また,後述のif文やfor文,AddItem構文の{}内で宣言された変数も,同様にその{}内(ブロック内)だけでのローカル変数となります.

string global = 20;

action input@( false )
{
    string local = "10";
}

action StartUp@( false )
{
    Call( input );
    Talk( "local=" + local );
    Talk( "global=" + global );
}

上記の場合,string型の変数localはinputアクション内でのみ扱えるローカル変数となるため,StartUpアクションからは参照できません.コンパイルすると,「StartUpで使用している変数localは宣言されていない」のエラーとなります.変数globalは,すべてのアクション・関数宣言の外で宣言されているグローバル変数のため,input,StartUp両アクションからアクセスできます.グローバル変数を宣言と同時に初期化しておいた場合,起動およびキャラクター切り替え時に自動的に初期化されます.

定義済み定数について

綾織では,以下の3種類の定義済み定数が存在します.

定数名 説明
true boolean "真"(条件が満たされた)
false boolean "偽"(条件が満たされない)
NULL (string) 値がない

NULLは,主に文字列関数などで値が取れない場合に返り値として返されます.NULLと長さ0の文字列""は区別されます.if( NULL == "" )は偽です(NULLと""は同じではない).

演算子

優先順位

綾織の演算子には,大まかに分けて算術演算子,代入演算子,関係演算子,論理演算子の4種類があります.各演算子の優先順位は次のとおりです.

優先順位 演算子
1(高) ()
2 []
3 ! - ++ -- lengthof dimof emptyof
4 * / %
5 + -
6 < > <= >=
7 == !=
8 &&
9 ||
10(低) = += -= *= /= %=

インクリメント(デクリメント)演算子

演算子 機能
X++ 後置インクリメント演算
X-- 後置デクリメント演算
++X 前置インクリメント演算
--X 前置デクリメント演算

インクリメント演算子(++)は,変数に1を加算する演算子です.変数の前に置くと前置インクリメント演算子,後ろに置くと後置インクリメント演算子と呼びます.

前置インクリメント演算子は,その変数を演算に使用する前に1を加算します.後置インクリメント演算子は,その変数を演算に使用した後に1を加算します.

前置インクリメント演算子の例
int a;
a = 1;
if( ++a == 1 ){ ... }
else{...}

上の例は"++a == 1"を評価する前に,前置インクリメント演算子の働きによりaに1が加算されます.そのためif文を評価する時点でaの値は2になり条件を満たさないので,else節が実行されます.

後置インクリメント演算子の例
int a;
a = 1;
if( a++ == 1 ){ ... }
else{...}

上の例では,はじめにif文を評価します.この時点でaの値は1なので条件を満たします.次に後置インクリメント演算子の働きによってaに1が加算されます.if文の条件を満たしたので,then節を実行します.then節を実行する時点のaの値は2です.

デクリメント演算子は,変数から1を減算する以外はインクリメント演算子と同じです.

インクリメント演算子,デクリメント演算子はint型変数に対して使用可能です.その他のデータ型には使用できません.

算術演算子

演算子 機能
- 負記号
* 乗算
/ 除算
% modulo(余り)
+ 加算または文字列の連結
- 減算

算術演算子には優先順位があります.これは,たとえば1 + 5 * 6という式があったとき,*は+よりも優先順位が高いので,まず5 * 6が評価され,その結果に1が+されて結果は31となります.余り(モジュロ)は,7 % 3という式があったときに,7 / 3の余りである1を求めます.

%演算子はint型の変数・定数に対してのみ使えます.+演算子をstring型変数や文字列定数に使用すると,文字列を連結できます.

関係演算子

演算子 機能
> 大きい
>= 大きいか等しい
< 小さい
<= 小さいか等しい
== 等しい
!= 等しくない

論理演算子

演算子 機能
! 否定(not)
&& かつ(and)
|| または(or)

論理演算子は,関係演算子などの条件判断を組み合わせて使う場合に用います.

論理演算子の例
a < b && b > c // bがaとcよりも大きいとき
b == 15 || a < b && b > c // bが15か,bがaとcよりも大きいとき

代入演算子

演算子 機能
= 代入
+= 加算の結果を代入
-= 減算の結果を代入
*= 積算の結果を代入
/= 除算の結果を代入
%= moduloの結果を代入

代入演算子には,四則演算およびmoduloと結合した複合演算子があります.これらの演算子は左辺と右辺の演算結果を左辺に代入します.演算子をop,左辺式をX,右辺式をYとしたとき,

X op= Y

上の複合演算子を使った記述は下の式と同じ働きをします.

X = X op Y

制御構造

制御構造はプログラムに条件判断に基づく分岐や反復を取り入れるもので,綾織には判断(if-else),前判定反復(while),所定回反復(for),飛び越し(break),選択分岐(AddItem-Choice)などがあります.

if-else(判断)

if-else文はまず(条件式1)を評価し,その式が真(条件が満たされている)ならば文1を実行します.条件式1が偽(条件が満たされていない)で,条件式2が真ならば,文2を実行します.条件式1,2がすべて偽であった場合,文3が実行されます.文1や文2が一つの文からなるときは(;が一個しかない),{ }は省略できます.また,else節に置く文がなければ,else節は省略できます.逆に,最初のif節と最後のelse節の間には,else if節を複数個置くことができます.

if( 条件式1 )
{
    文1
}
else if( 条件式2 )
{
    文2
}
else
{
    文3
}

while(前判定反復)

while文では,まず条件式が評価され,それが真なら{ }の中の文が実行されます.そして再度条件式を評価し,それがまだ真なら繰り返し{ }の中の文を実行します.条件式が偽になるまではずっと繰り返し実行を続けます.

while( 条件式 )
{
    文
}

for(所定回反復)

for文では,まずfor文に入る前に一度だけ式1が実行され,条件の初期化を行います.次に式2が評価され,この式が真であれば{ }の中の文が実行されます.文を一度実行するたびに式3が実行され,条件の再初期化を行います.

for( 式1;式2;式3 )
{
    文
}
forの使用例
for( i = 0; i < 5; i = i + 1 )
{
    Talk( "現在の変数iの値は," + itoa( i ) + "です.\n" );
}

上の例では,iを0から始めて中のTalk関数を実行するごとに+1していき,iが5になった時点でループを抜けます.このときの表示結果は,

forの実行例
現在の変数iの値は,0です.
現在の変数iの値は,1です.
現在の変数iの値は,2です.
現在の変数iの値は,3です.
現在の変数iの値は,4です.

のようになります.

switch-case(多方向分岐)

switch-caseは,変数fooが持つ可能性がある値をcase:部に列挙し,その場合に行う処理を記述することができます.switchのカッコ内に記述できるのはint型やその演算のみで,case節には整数定数のみ記述可能です.

int foo = Day();
switch( foo )
{
    case 0:
        Talk( "Sunday" );
        break;
    case 1:
        Talk( "Monday" );
        break;
    …
    …
    default:
        Talk( "未指定" );
        break;
}

break(飛び越し)

break文を実行すると,while文・for文・switch文のいずれかの制御構造から外へ出ることができます.これらの制御構造が多重になっていても,1つの制御構造からしか脱出できません.

AddItem-Choice(ユーザ選択分岐)

AddItem( string 選択肢1 )
{
    文1;
}
AddItem( string 選択肢2 )
{
    文2;
}
AddCancelItem
{
    キャンセル時の文;
}
Choice;

Additem-Choice文は,キャラリナのメッセージウィンドウ(吹き出し)に( )内に指定した文字列を選択肢として表示し,ユーザが選んだ文字列とペアで指定した{ }内の文を実行します.綾織の処理系には,これらの選択肢文字列と処理内容をおさめる選択肢バッファが存在し,そこにAddItem文で選択肢を追加します.Choice文を実行した時点で,バッファに納められた選択肢を表示します.その時点で,選択肢バッファの内容はクリアされます.また,選択肢の文字列にはTalk,Message内で使用する\fc等の文字色指定等が使えます.選択肢の表示では,文字列上でマウスの右クリックをすることでキャンセル(どれも選択しない)が可能です.このとき,AddCancelItem節が記述してあると,それを実行します.AddCancelItem節は一つのAddItem-Choice構文に一つしか指定できず,二つ以上指定するとコンパイルエラーとなります.

AddItemの回数に特に制限はありませんが,表示できる選択肢の数はメッセージウィンドウの行数に依存します.行数を越えたAddItemは,表示時に無視されます.一度AddItemされた選択肢は,Choice;されるまではバッファに残っています.AddItem文をif文で囲んで,条件判断によって選択肢を追加したりしなかったりすることが可能です.

AddItemのブロック内({}内)で,そのAddItem-Choiceを含む制御構造から脱出するためにbreakを使用しないでください.ブロック外の不定の位置にジャンプすることになります.

配列

変数が変数1個につき一つの整数または文字列を代入できるのに対し,配列は添字という「何件目のデータ」を表す数字を付けることで,複数の整数または文字列を代入するものです.たとえば,10個の整数を入れる配列を宣言するには,

int hairetsu[10];

とします.こうして宣言することで,hairetsu[0],hairetsu[1],hairetsu[2],…hairetsu[9]までの10個の配列要素が用意されます.hairetsu[10]という要素は用意されないことに注意します.この時の[i]のiを添字といいます.

配列の宣言は,一般に以下のようになります.

型 配列名[要素の数]( [要素の数] …);

配列には,最初の例のような一次元配列以外にも,添字が複数ある多次元配列を宣言することができます.縦横10個の要素を持つ2次元整数配列の場合,その宣言は

int nijigen[10][10];

となります.この2次元配列に対し,nijigen[0][0] = 256;やnijigen[5][9] = 32;というようにアクセスできます.配列をアクセスする際の添字には,変数や式が使用可能です.つまり,

int i;
for( i = 0; i <= 9; i = i + 1 )
{
    hairetsu[i] = 0;
}

とすることで,hairetsu[0]?hairetsu[9]までのすべてに,0を代入できます.添字が宣言した配列の範囲を越えることがないように注意します.逆に,配列の宣言時の添字には,式や変数を使うことはできません.

int dim[5]; // OK
int i = 20;  
int dim2[i]; //宣言時に変数を使っているので不可
int dim3[2 + 3]; //宣言時に式を使っているので不可

綾織では関数の引数は,変数は値渡し,配列は参照渡しになることに注意します.

エスケープシーケンス

通常,キーボードからソースプログラム中に入力できない文字や,特別の意味をもつ記号そのものを記述する際にエスケープシーケンスを利用します.

\n (改行コード0x0a)

\\ \記号

\" "記号

Talk( "GetProcesserType=\"" + GetProcesserType( ) + "\"\n" );

→「"586"」などと表示される

string line;
string mes = GetHTTP( "http://(掲示板のログファイルを指定)" );
while( ( line = StrToken( mes, "\n", i ) ) != NULL )
    Talk( line + "\n" );

コメント

行の間に,//(スラッシュ2個)を入れると,その行の//以下の文字はコメントとして扱われます.また,/*から始まり*/で終わるまでの範囲をコメントとして扱うこともできます.

action StartUp@( 0 )
{
    // StartUpは標準アクションなので,起動条件と関係なく起動されます.
    string mes = "おはようございます"; // ここからコメント
    Talk( mes + "\n" );
    /* Sample Program 
    for TEST (ここはコメントです) */ 
}

プリプロセッサ制御文#import

#import "ファイル名.aya"

#importは綾織の言語仕様ではなく,プリプロセッサayapの制御文です.ソースファイルのその位置に他のソースファイルを読み込むことができます.ファイル名の指定は,この#importを書いたソースファイルからの相対パスで指定し,また,#importされるファイルからさらに他のファイルを#importする(importのネスト)も可能です.行の最後にセミコロンが付かないことに注意してください.

#importされたファイルは,コンパイル時には読み込まれてimportしたファイルと結合され,一つのファイルとしてコンパイルされます.

分割コンパイルとextern指定

綾織ソースファイルをayacで

>ayac foo.aya

とコンパイルすると,foo.exaというファイルが生成されます.キャラリナは,キャラクターデータディレクトリに存在する複数の.exaファイルをすべて読み込もうとします.具体的には,3つに分割されて,#importによる結合も行われていないソースファイルがあるときに,それらをそれぞれ個別にコンパイルして利用できます.

このとき,.exaファイルをまたがったアクションや変数の呼び出し・アクセスを行う際,それを呼び出そうとする側の綾織ソースファイルで,あらかじめ

extern 変数型 変数名; (変数の場合:外部変数宣言)
extern action アクション名; (アクションの場合:外部アクション宣言)
関数データ型 関数名( 引数型 引数名, ... ); (ユーザ定義関数の場合:関数プロトタイプ宣言)

という宣言を行っておく必要があります.

プロトタイプ宣言

extern指定はアクションと変数,配列について適用されます.同様に関数について外部モジュールのものを参照する場合,プロトタイプ宣言を行います.また,persona.exeの標準関数を使用する際にも,プロトタイプ宣言が必要であることに注意します.これはPDK付属のサンプルに記述例が含まれています.

 
関数データ型 関数名( 引数型 引数名, ... );

Critical修飾子について

アクション/関数の実行優先度を指定するために,"Critical"修飾子を用意しています.Criticalの優先度を持ったアクション/関数(ここでは仮にc-actionとする)は,起動された時点でノーマルのアクション/関数(n-action)が動作していればそのn-actionの実行をキャンセルし,自身を優先的に実行します.ただし動作中のc-actionは,c-actionでもキャンセルすることはできません.

actionから他のactionをCall関数で呼び出すような場合,それらの優先度は,基底状態(何等のアクション・関数も起動していない待機状態)から最初に呼びだされた一個目のactionの優先度を継承します.すなわち,c-actionからサブルーチン的に呼び出されたn-actionはc-actionの優先度を持ち,逆にn-actionから呼び出されたc-actionはn-actionの優先度を持つため,キャンセルされる場合があります.

予約語"Critical"はactionと関数宣言(void, int, string, double, boolean)に指定する事ができます.但し,標準アクションに対してCriticalは適用できず,記述しても無視されます.

Critical修飾子の記述例
Critical action Urgent@( Timer_Set == Time() )
{
    Talk( "お時間です." );
}

CriticalSectionについて

上記のCritical修飾子と違い,関数・アクション内の特定部分のみをcritical化するものがCriticalSectionです.具体的には,

CriticalSectionの記述例
int HogeHoge( int n )
{
    通常優先度の処理;
    CriticalSection{
        優先度の高い処理;
    }
    通常優先度の処理;
}

と,通常の関数やアクション記述内に{}のブロックで指定します.CriticalSection内から呼び出された関数やアクションは,その優先度にかかわらずcriticalの優先度を持ちます.

CriticalSectionは,標準アクション内や,標準アクションから呼び出される関数,アクション内でも指定可能です.

import, exportについて[1.50]

1.50からは,プラグインとの連携用にimport,exportが新設されました.プラグインの関数を呼び出すときは,予めimportをつけて関数の宣言する必要があります.

importの記述例
import void LF_SNTPCLIENT_SetServer(string server);
import int  LF_SNTPCLIENT_AccessAndAdjust();

// time-a.timefreq.bldrdoc.gov のサーバを見て時計をあわせる.
void AdjsutClock()
{
    LF_SNTPCLIENT_SetServer("time-a.timefreq.bldrdoc.gov");
    LF_SNTPCLIENT_AccessAndAdjust();
}

また,プラグインから呼び出される関数にはexportをつけて宣言する必要があります.

exportの記述例
// この関数は,時計あわせプラグインが定期的な時計あわせを行うと呼ばれる.
export void LF_SNTPCLIENT_cAccessAndAdjust( int errorcode, int offset, int \
    delay )
{
    if ( errorcode == 0 )
        Talk("時計をあわせました.\n");
}

可変長配列[2.00]

宣言時に配列の要素数の指定が不要で,代入,読み込み時に指定される添字の大きさに従って自動的に要素数が拡張される配列です.

宣言

"データ型配列名[];"を基本形とし,必要な次元の数だけ[]をつけて宣言します.指定可能なデータ型はchar,int,double,stringです.

1次元可変長配列 int a[];
2次元可変長配列 int a[][];

初期値

可変長配列の宣言と初期化を同時に行うことはできません.

要素数

宣言直後の可変長配列の要素数は0です.

拡張

配列にアクセスする際に指定されたインデックスが,その時点における配列の最大要素数を超えていた場合,可変長配列は拡張されます.拡張後の配列の要素数は,指定されたインデックス+1になります.拡張された要素は,データ型に応じて下記の初期値で初期化されます.

データ型 初期値
char 0
int 0
double 0.0
string null
配列 長さ0の配列(多次元配列の2次元目以降)
可変長配列のアクセス例
int a[][];

assert( lengthof a == 0 );          //宣言直後の要素数は0
a[10][5] = 1;                       //a[0]->a[10], a[10][0]->a[10][5]に
//それぞれ拡張される
assert( lengthof a == 11 );         //aはa[0]?a[10]まで拡張されて11個の要素をもつ
assert( lengthof a[10] == 6 ); //a[10]はa[10][0]?a[10][5]まで拡張されて6個の要素をもつ
assert( lengthof a[0] == 0 );       //a[0]はアクセスがないので拡張されない

演算子

可変長配列に対して次の演算子が定義されています.

dimof

次元数を取得する演算子です.配列名を与えて使います.

dimof演算子の使用例
    
int a[][];
assert( dimof a == 2 );     //aは2次元配列なので演算結果は2

lengthof

要素数を取得する演算子です.配列名とインデックスを与えて使います.

lengthof演算子の使用例
int a[][];
a[0][0] = 10;
a[1][2] = 11;

//aは2次元配列なので,0?1個のインデックスを指定できる
assert( lengthof a == 2 );          //aの要素数は2
assert( lengthof a[0] == 1 );       //a[0]の要素数は1
assert( lengthof a[1] == 3 );       //a[0]の要素数は2

emptyof

要素数を0にする演算子です.配列名とインデックスを与えて使用します.指定された配列に格納されている要素は全て破棄されます.破棄する範囲をインデックスで指定できます.n次元配列に対し,0からn-1個のインデックスを指定します.

emptyof演算子の使用例
int a[][];
a[0][0] = 10;
a[1][2] = 11;

//aは2次元配列なので,0?1個のインデックスを指定できる
emptyof a[1];                   //a[1][0]?a[1][2]の要素が破棄される
assert( lengthof a[1] == 0 );   //破棄されて,a[1]の要素数が0になった
emptyof a;                      //aのすべての要素が破棄される
assert( lengthof a == 0 );      //破棄されて,aの要素数が0になった

関数の引数

可変長配列を引数に取る関数は次のように宣言します.

可変長配列を引数にするときの記述例
void f( int b[] ){ ... }    //1次元可変長配列を受け取るとき
void g( int c[][] ){ ... }  //2次元可変長配列を受け取るとき
    :                                  :
    :                                  :

関数呼び出し時の引数

可変長配列を引数に指定して関数を呼び出す場合は,次のように指定します.N次元可変長配列にn個のインデックスを指定して関数を呼び出すと,呼び出された関数ではN-n次元可変長配列になります.

関数に可変長配列を渡すときの記述例
void f( int b[] ){ ... };
void g( int c[][] ){ ... };
void main{
    int a[][];
    a[3][6] = 10;

    f( a[1] );      //1次元可変長配列としてfに渡す
    g( a );         //2次元可変長配列としてgに渡す
}

割り込み[2.00]

割り込みとは

割り込みは,現在実行中の処理を一時中断して,別の処理を行う機構です.キャラクターの実行状態に関わらず,外部からのトリガによって処理を実行します.

割り込み処理の記述

割り込み処理は関数で記述します.割り込みで実行される処理の最小単位は関数一つです.

割り込みトリガ

割り込み処理を実行するトリガには,GUI系のイベントや通信,マルチメディア系の処理があります.トリガと関数を対応付けて綾織関数でを登録することで,割り込み処理を可能にします.

優先順位

処理単位と禁止区間の優先順位は次のとおりです.

ある処理(又は禁止区間)を実行中は,それより優先順位の低い処理は実行されません.

優先順位 処理内容






割り込み禁止区間(Uninterrupted{...})
割り込み
クリティカルセクション(CriticalSection{...})
クリティカルアクション
通常アクション

割り込み禁止区間

割り込みを禁止する区間を定義できます.割り込み禁止中は,割り込み,クリティカルアクションの実行,通常アクションの実行が禁止されます.

割り込み禁止区間はUninterrupted{...}で定義します.{}の中に割り込みされたくない処理を記述します.{}中から呼び出される関数の実行中も同様に禁止されます.

割り込み

基底状態,通常アクション,クリティカルアクション,クリティカルセクション実行中に,外部からのトリガによって実行されます.

クリティカルセクション

クリティカルアクションの実行を禁止する区間です.通常アクション中に記述した場合に有効です.クリティカルセクション中の処理を実行中は,クリティカルアクションによるアクションの中断を禁止します.

クリティカルアクション

基底状態または通常アクション実行中,起動条件が真となったときに実行されるアクションです.通常アクション実行中であれば強制的に基底状態に状態遷移させた後に,クリティカルアクションの処理を実行します.クリティカルアクション実行中は,通常アクション及び他のクリティカルアクションは実行されることはありません.クリティカルアクション実行中に割り込みが発生すると処理が中断され,割り込み処理が実行されます.割り込みの完了後にクリティカルアクションの処理が再開されます.割り込み禁止区間の定義により,この割り込みを禁止できます.

通常アクション

優先順位の最も低いアクションです.基底状態の下で起動条件が真となった場合に実行されます.クリティカルアクションによる中断及び割り込み機構による割り込みが有り得ます.クリティカルアクションの禁止にはクリティカルセクション区間の定義が,割り込みの禁止には割り込み禁止区間の定義が必要です.