東京工業大学大学院理工学研究科基礎物理学専攻中村研究室メンバー

ホームページおぼえがき > kumac

kumac

PAWのマクロであるkumacの書き方おぼえがき。kumacの文法的なものを書きたい。kumacはANAPAWでも使える。

(壊れかけのおぼえがき。)

マクロの実行

kumac_name.kumacという名のマクロを実行するには、exec kumac_nameとする。execコマンドの引数はファイル名を指定する。ファイル名の拡張子が.kumacのときは、.kumacを省略しても良い。逆にファイル名の拡張子が.kumac以外のときは、拡張子を省略できない。

ファイル名: kumac_name.kumac
macro kumac_name
  mes 'Hello, world!'
return
実行結果
PAW > exec kumac_name
 Hello, world!
PAW > exec kumac_name.kumac
 Hello, world!

マクロファイルはPAWを実行したディレクトに置いておく。ほかのディレクトリに置いたマクロファイルを実行するには、execコマンドの引数にファイルの相対パス/絶対パスを指定する。

ファイルパス: /home/username/kumac/test.kumac
macro test
  mes 'Hello, world!'
return
端末で実行
$ cd       # ホームディレクトリ/home/username に移動。
$ ls kumac # ホームディレクトリにあるkumacディレクトリの中身を表示。
test.kumac
$ paw
PAW > exec kumac/test
 Hello, world!
PAW > exec /home/username/kumac/test
 Hello, world!
PAW > exec ~/kumac/test
 Hello, world!

コーディング

基本的にkumacの文法は、FORTRANの文法に近い。

■ 大文字/小文字

FORTRANと同じく、kumacに大文字/小文字の区別はない。

■ コメント

コメントは行の最初に *, | を書くか、行末に | を書く。

|     ここはコメント
*     ここはコメント
mes 'aa'      | ここもコメント

■ 行頭

行頭はFORTARNのように6文字分のスペースを開ける必要はない。しかし、開けてもかまわない。すなわち、字下げを行いプログラムを見やすくできる。

mes 'aa'
  mes 'bb'
    mes 'cc'

■ 継続行を書く&コマンドをまとめて実行する

マクロの一行が長くなる場合は、_ を用いて継続行を表すことができる。また、複数のコマンドを一行でまとめて実行するには、; を用いる。
mes 'aaaaaaaaaa_
aaaaaaaaaa'
mes 'bb'; mes 'cc'; mes 'dd'
実行結果
 aaaaaaaaaaaaaaaaaaaa
 bb
 cc
 dd

■ マクロの始まりと終わり

マクロはmacro kumac_nameで始まり、returnで終わる。しかし、macro kumac_nameの部分は省略しても良い。ひとつのファイルに複数のmacroを書くこともできる。途中でマクロを抜けるには、exitm文を用いる(下記参照)。

ファイル名: kumac_name.kumac
macro kumac_name
  mes 'aa'
  exec subkumac_name
return

macro subkumac_name
  mes 'bb'
return
実行結果
PAW > exec kumac_name
 aa
 bb
ファイル名: kumac_name2.kumac
  mes 'aa'
  mes 'bb'
実行結果
PAW > exec kumac_name2
 aa
 bb

変数

kumac内では、型の宣言なしに変数が使える。

■ 代入

= を用いて、変数に整数、実数、文字列を代入できる。

para1 = 1
para2 = 1.1
para3 = 'aa'

vectorの値を変数に代入することも可能。

vec/cre par(3) r 0.1 0.2 0.3         | 一次元ベクトル作成
vec/cre par2(2,2) r 1.1 1.2 1.3 1.4  | 二次元ベクトル作成

val1 = par(1)         | ベクトルの値代入
val2 = $eval(par(3))  | ベクトルの値を参照して代入?

val3 = par(1,1)
val4 = $eval(par(2,1))

mes [val1] [val2] [val3] [val4] | 0.1 0.3 1.1 1.2 が表示される。

■ 参照

変数に代入された値を参照するには、変数を[ ]で囲む。

para1 = 'aa'
mes [para1] | aa が表示される。

para2 = 10
para3 = 20
para4 = [para2] + [para3]
mes [para4] | 30 が表示される。

マクロ内の[ ]で囲まれた変数を含む行は、変数の参照を行ってから実行されている?むしろ、変数を一度評価してから、実行している?

para1 = 'aa'
[para1] = 10
mes [aa] | 10 が表示される。

para2 = 'bb'
para3 = 'cc'
para4 = 'dd'
[para2] = [para3][para4]ee
mess [bb] | ccddee が表示される。

参照[ ]は入れ子にすることも可能。参照[ ]の中の入れ子は98重まで可能。

bb = 'aa'
cc = 'bb'
mes [[cc]] | aa が表示される。
dd=cc
mess [[[dd]]] | aaが表示される。これを2重の入れ子とすると、98重まで可能。

■ 計算

変数同士は四則演算ができる。複雑な計算をする場合は、$sigmaを用いる。

a = 1.0
b = 2.0
c = 3.0
d = 4.0
e = ([a] + [b]) * [c] / [d]
mes [e]             | 2.25と表示される。

f=$sigma( sqrt([d]) + [a])
mes [f] | 3 と表示される。

g=$sigma( exp(log([d]) + sin([c])) + cos([c])**[b] )
mes [g] |  5.58634 と表示される。

pi=3.14159
h=$sigma( cos([pi]) )
mes [h] |  -1 と表示される。

■ 文字列の結合

文字列は // を用いて結合することができる。たまに使う。大抵は、文字列同士をただ並べるだけで結合される。

str1 = aa
str2 = bb
mess [str1]//[str2]//'cc' | aabbcc と表示される 
mess [str1][str2]cc       | aabbcc と表示される

■ シングルクオート

文字列としてシングルクオートを用いる場合は、シングルクオートを重ねる。

str1 = 'aa''bb''cc'
mess [str1] | aa'bb'cc と表示される 

■ スコープ

変数の参照は、通常その変数が宣言されたマクロ内でのみ有効である。すなわち、変数はローカル変数として宣言される。静的ローカル変数はむりかも?また、マクロを入れ子にした場合、入れ子から外側のローカル変数は参照できない。

macro main
  par='aa'
  mes [par]
  exec sub
return

macro sub
  mess [par]
return
実行結果
 aa
 [par]

マクロや、マクロの入れ子から外側の変数を参照するには、変数をグローバル変数として宣言し、インポート(?)する。

macro main
  global/create par
  global/create str
  par=3
  str='aa'
  exec sub
return

macro sub
  import par str | グローバル変数: par, str をインポート
  mess [par]
  mess [str]
return
上記マクロの別記
macro main
  global/create par 3
  global/create str 'aa'
  exec sub
return

macro sub
  import * | すべてのグローバル変数をインポート
  mess [par]
  mess [str]
return
実行結果
 3
 aa

■ 配列もどき

変数名として( )が使える様なので、配列もどきを作ることができる。

do i = 1, 5
  a([i]) = [i]*2
enddo

mes [a(1)] [a(2)] [a(3)] [a(4)] [a(5)] | 2 4 6 8 10 が表示される。
j=3
mes [a([j])]  | 6 が表示される。

■ 特殊な値

[0],[1],[2],[3],...と、[#],[*],[@]は特別な値を表す。詳しくは、Paw Reference Manual/MACRO/SYNTAX/Variables/Special の項目を参照。

特殊な値
意味
[0] 実行されたマクロファイル名を格納する。
[1],[2],[3],... マクロに渡される引数を参照する。
[#] マクロに渡される引数の数をあらわす。引数がないときは0。
[*] すべての引数をあらわす。引数同士は空白で区切られる。for文で用いると便利。
[@] 最後に実行されたマクロの返し値(exitm 文または return 文で指定)を格納する。

[0],[1],...,[*],[#]の例

ファイル名: spe_test.kumac
macro spe_test
  mes [1]
  mes [2]
  mes [3]
  mes [*]
  mes [#]
  mes [0]
return
実行結果
PAW > exec spe_test aa bb cc
 aa
 bb
 cc
 aa bb cc
 3
 spe_test.kumac#spe_test

[@]の例

ファイル名: spe_test2.kumac
macro spe_test2
  mes [@]
  exe sub
  mes [@]
return

macro sub
return aa
実行結果
PAW > exec spe_test2
 0
 aa

マクロの呼び出し、引数、返し値

一つのマクロファイルに複数のマクロを書くこともできる。それらのマクロは、同一マクロファイル内や、PAWのコマンドラインから呼び出すことができる。また、マクロは引数をとることもできる。また、マクロは引数をとったり、返し値を指定することもできる。すなわち、マクロを関数のように扱うこともできる。

■ マクロの呼び出し

PAWのコマンドラインから、マクロファイル内の複数のマクロのうちの一つを実行するには、マクロファイル名#マクロ名とする。

ファイル名: macro_test.kumac
macro main_macro
  mes main
return

macro sub_macro_1
  mes sub_1
return

macro sub_macro_2
  mes sub_2
return
実行結果
PAW > exec macro_test
 main
PAW > exec macro_test#main_macro
 main
PAW > exec macro_test#sub_macro_2
 sub_2

マクロファイル内で別のマクロを呼び出すこともできる。同一ファイル内のマクロは、exec マクロ名とすれば実行される。

ファイル名: macro_test2.kumac
macro main_macro2
  exec sub_macro_1
  exec sub_macro_2
return

macro sub_macro_1
  mes sub_1
return

macro sub_macro_2
  mes sub_2
return
実行結果
PAW > exec macro_test2
 sub_1
 sub_2

■ マクロに値を渡す(その1)

以下の例では、マクロ内の変数aa, bb, cc にマクロの引数として値 1, dd, 0.1 を渡している。マクロ中の"aa bb cc"の部分は"aa= bb= cc="、または"[aa] [bb] [cc]"と書いても良い。

ファイル名: arg_test.kumac
macro arg_test aa bb cc
  mes [aa]
  mes [bb]
  mes [cc]
return
実行結果
PAW > exec arg_test 1 dd 0.1
 1
 dd
 0.1

■ マクロに値を渡す(その2)

マクロのはじめ(macro文)で変数を指定しなくても、マクロ実行時の引数はマクロ内で[1],[2],[3],...を用いて参照できる。

ファイル名: arg_test2.kumac
macro arg_test2
  mes [1]
  mes [2]
  mes [3]
  mes [4]
return
実行結果
PAW > exec arg_test2 aa 'bb' 0.1 5
 aa
 bb
 0.1
 5

■ 引数すべてに対して処理をする

マクロに渡される引数の数は、[#]に格納される。これを用いれば、引数の数が不定でもすべての引数に対して処理をすることができる。

ファイル名: arg_test3.kumac
macro arg_test3
  do i =1,[#]
    mes [[i]] | この [[i]] は、[%i]と書いても良い
  enddo
return
実行結果
PAW > exec arg_test3 aa 'bb' 0.1 5
 aa
 bb
 0.1
 5

SHIFT文を用いても、上記のような処理をすることができる。

ファイル名: arg_test3.1.kumac
macro arg_test3.1
  while [1] <> ' ' do
    mes [1]
    shift
  endwhile
return
実行結果
PAW > exec arg_test3.1 aa 'bb' 0.1 5
 aa
 bb
 0.1
 5

■ デフォルトの値を指定

マクロ呼び出し時に引数を指定しなかった場合の為に、変数にデフォルトの値を設定したいときは、macro文のマクロ名の後に変数名=デフォルト値とする。引数が設定されると、デフォルト値は上書きされる。

ファイル名: arg_test4.kumac
macro arg_test3 aa=10 bb=test cc=0.1
  mes [aa]
  mes [bb]
  mes [cc]
return
実行結果
PAW > exec arg_test4
 10
 test
 0.1
PAW > exec arg_test3 20 val 0.2
 20
 val
 0.2

■ デフォルトの値を使ったり使わなかったりする

マクロのある変数には値を渡したいけれど、別の変数ではデフォルト値を使用したという場合は、マクロ呼び出し時に引数として ! を指定するか、引数として変数名と値のセットを指定する(変数名=値のように指定する)。

ファイル名: arg_test5.kumac
macro arg_test3 aa=10 bb=test cc=0.1
  mes [aa]
  mes [bb]
  mes [cc]
return
実行結果
PAW > exec arg_test5 val ! 0.2
 val
 test
 0.2
PAW > exec arg_test5 cc=0.2 aa=val
 val
 test
 0.2

■ マクロに返し値を指定する

マクロに返し値を指定するには、retrun の後に値を指定する。返し値を参照するには、$EXEC('macro名')とする。$で始まる変数は特別な意味を持ち、これを使いこなすととても便利。Paw Reference Manual/KUIP/FUNCTIONSの項目にいろいろ書いてある。

ファイル名: return_test.kumac
macro return_test
  mess aa
return bb
実行結果
PAW > exec return_test | 普通に実行
 aa
PAW > mess $exec('return_test') | マクロを実行後、返し値を表示
 aa
 bb

返し値は、マクロ内でも$exec('マクロ名')を用いて参照可能。

ファイル名: return_test2.kumac
macro return_test2
  mes $exec('mes_macro')
return

macro mes_macro
  str = aa
return [str]
実行結果
PAW > exec return_test2
 aa

■ 関数もどき

$exec()は引数をとることもできる。すなわち、$exec('マクロ名 引数1 引数2')と引数を指定することもできる。これを用いて、マクロを関数のように扱うこともできる。

ファイル名: func_test.kumac
macro func_test
  sum = $exec('sum_func 3 2')
  mes [sum]
return

macro sum_func
  val = [1] + [2]
return [val]
実行結果
PAW > exec func_test
 5

マクロの途中で値を返したいときは、exitm 文を用いて値を返す。

ファイル名: func_test2.kumac
macro func_test2
  str = $exec('func 5')
  mes [str]
return

macro func
  if [1] = 5 then
    str = five
	exitm [str]
  else
    str = not_five
    exitm [str]
  endif
  mess aa
return
実行結果
PAW > exec func_test2
 five

■ 変数を関数もどきの引数にする

変数を関数もどきの引数にするには、$exec()内にて変数を[]で参照すればよい。

ファイル名: func_test3.kumac
macro func_test3 aa bb
  sum = $exec('sum_func [aa] [bb]')
  mes [sum]
return

macro sum_func
  val = [1] + [2]
return [val]
実行結果
PAW > exec func_test3 2 3
 5

制御文

kumac内では、if文やdo文などの制御文が使える。文というよりコマンド?書式はFORTRANとほぼ同じ。

■ if文

条件分岐をするには、if文を用いる。書式は以下のとおり。

書式
IF expression THEN
 statements
ELSEIF expression THEN
 statements
...
ELSEIF expression THEN
 statements
ELSE
 statements
ENDIF

例) 変数paraの値によって表示するメッセージを変更する。

para = 5
if ([para] = 0) then
  mes 'aa'
elseif ([para] = 1) then
  mes 'bb'
elseif ([para] = 2) then
 mes 'cc'
else
 mes 'dd'
endif

例) ELSEIFやELSEは書かなくても良い。

para = 5
if ([para] > 0) then
  mes 'aa'
endif

■ case文

条件分岐には、case文もある。書式は以下のとおり。

書式
CASE expression IN
 (label) statement [statements]
  ...
 (label) statement [statements]
ENDCASE

例) 変数paraの値によって表示するメッセージを変更する。

para = 1
case [para] in
  (1)  mess 'aa'
  (2)  mess 'bb'
  (cc) mess 3
  (*)  mess 'other'
endcase

■ do文

繰り返し処理を行うにはdo文を用いる。

書式
DO loop = start_expr, finish_expr [,step_expr]
 statements
ENDDO

例) 1から10の値を表示する。

do i = 1,10
  mes [i]
enddo

例) 1から9まで2おきに表示する。

do i = 1,10,2
  mes [i]
enddo

■ for文

異なる値それぞれに対して、同じ処理をするにはfor文を用いる。

書式
FOR name IN expr_1 [ expr_2 ... expr_n ]
  statements
ENDFOR

例) 文字列を順に表示する。

for str in 'aa' 'bb' 'cc'
  mes [str]
endfor
実行結果
 aa
 bb
 cc

■ while文

繰り返し処理はwhile文を用いてもよい。do文でも同じことができる。

書式
WHILE expression DO
 statements
ENDWHILE

例) iが10よりも小さい間、iを1ずつ増やす。

i = 0
while ([i] < 10) do
  mes [i]
  i = [i] + 1
endwhile

■ repeat文

繰り返しの処理には、repeat文を用いてもよい。

書式
REPEAT
 statements
UNTIL expression

■ breakl文

ループを途中で抜けるには、breakl文を用いる。多重のループもlevelを指定することで一気に抜ける。levelを省略すれば、一重のループを抜ける。

書式
BREAKL [ level ]

例) do文を途中で抜ける。

do i = 1,10
  mes [i]
  if ([i] > 5) then
    breakl
  endif
enddo
mes 'aa'

例) 二重のdo文を抜ける。

do i = 1,10
  do j =1,10
    mes [i] [j]
    if ([i] > 5 .and. [j] > 5) then
      breakl 2  | breakl level で、level重のループを抜ける。
    endif
  enddo
enddo
mes 'aa'

■ nextl文

ループの途中でストップし、次のループに進むには、nextl文を用いる。levelを指定すれば、どのループの始まりに戻るかを決められる。

書式
NEXTL [ level ]

■ goto文

処理を飛ばしたり、ループを途中で抜けるには、goto文を用いる。

書式
GOTO label
...
label:

例) 条件を満たしたら、処理を飛ばす。

i = 1
if ([i] = 1) then
  goto label_10
endif
mes 'aa'   | この文は実行されない。
label_10:
mes 'b'

上記は以下のように短縮することもできる。

i = 1
if ([i] = 1) GOTO 10
  mes 'aa'   | この文は実行されない。
10: mes 'b'

例) do文を途中で抜ける。

do i = 1,10
  mes [i]
  if ([i] > 5) then
    goto 10
  endif
enddo
10:
mes 'aa'

■ exitm文

return 文の前にマクロを終了するには、 exitm 文を用いる。

ファイル名: exitm_test.kumac
macro exitm_test
  do i = 1,10 
    if [i] = 5 then
	  exitm
    endif
    mess [i]
  enddo
return
実行結果
PAW > exec exitm_test
 1
 2
 3
 4

演算子

■ 算術演算子

変数を計算するときなどに用いる算術演算子は以下のとおり。四則演算しかできず、%や**は使えないかも?複雑な演算をしたいなら、$sigmaを用いる。

算術演算子
演算子意味
+ 足す
- 引く
* 掛ける
/ 割る

例) 変数を足したり引いたり掛けたり割ったりする。

a = 1
b = 2
c = 3
d = 4
e = ([a] + [b]) * [c] / [d]
mes [e]             | 2.25と表示される。

■ 関係演算子(比較演算子)

if文などで条件を指定するときに用いる関係演算子は以下のとおり。

関係演算子
演算子別記意味
.gt. >greater than
.ge. >=greater than / equal
.lt. <less than
.le. <=less than / equal
.eq. = equal
.ne. <>not equal

■ 論理演算子

if文などで複数の条件を指定するときに用いる論理演算子は以下のとおり。

論理演算子
演算子意味
.and. かつ
.or. または
.not. 否定

使用法は以下の様。

i = 10
j= 11
if ((i = 10) .and. (j <> 10)) then  | i が10でjが10以外ならmes 'aa'を実行
  mes 'aa'
endif

参考文献・webページ


ページ制作履歴
2008/06/15 制作開始
2008/06/15 webにアップ
2008/06/24 変数あたり追加
2010/03/14 マクロの呼び出し、引数、返し値、特殊変数、文字列の結合を追加
2010/05/29 シングルクオート追加