スクリプト構文 - stuncloud/UWSCR Wiki

変数定義

変数名には英数字、一部記号、全角文字列が使えます
英字の大文字小文字は区別しません

dim

対応バージョン: 0.0.3

ローカル変数を定義します

dim hoge     // 変数 hoge を定義
dim fuga = 1 // 値の代入も同時に行える
piyo = 1     // 未宣言変数への代入式で新たな変数が定義される(dim省略)

public

対応バージョン: 0.0.3

グローバル変数を定義します

public hoge = 1
hoge() // 1
hoge = 2
hoge() // 2

procedure fuag()
    print hoge
fend

const

対応バージョン: 0.0.3

定数を定義します
再代入ができません

const hoge = 1
hoge = 2 // これはダメ

一括定義

対応バージョン: 0.0.5

,区切りで変数を一括定義できます

dim a = 1, b = 2, c, d[3], e[] = 1,2,3,4,5
public f = 1, g = 2
const h = 1, i = 2

UWSCではエラーになっていたconstの一括定義も可能

以下はダメ (UWSCでもダメ)

dim foo[] = 1,2,3 , a = 1 // a = 1 は定義できない

配列

対応バージョン: 0.0.1

配列を定義はdimを使った方法と、配列リテラル(※)を使う方法があります
※ 新機能

dim hoge[] = 1, 2, 3 // 従来の配列定義
print hoge[0]

fuga = [1, 2, 3]     // 配列リテラル
print fuga[0]

print [4, 5, 6][0]   // 配列リテラルにインデックスを指定することも可能

+演算子による要素の追加

対応バージョン: 0.1.6

+演算子で配列の末尾に要素を追加できます

print [1, 2, 3] + 4
// [1, 2, 3, 4]
dim arr = [5, 6, 7]
arr += 8
print arr
// [5, 6, 7, 8]

多次元配列

対応バージョン: 0.1.7

// 2次元
dim 配列名[要素数][要素数] = 値, 値, 値, 値 ...
// 3次元
dim 配列名[要素数][要素数][要素数] = 値, 値, 値, 値 ...

// 以下の書式も可能
dim 配列名[要素数, 要素数] = 値, 値, 値, 値 ...
dim 配列名[要素数, 要素数, 要素数] = 値, 値, 値, 値 ...

// 一番左の要素数のみ省略可能
dim 配列名[][要素数][要素数] = 値, 値, 値, 値 ...
dim 配列名[, 要素数, 要素数] = 値, 値, 値, 値 ...

// 呼び出しは次元数分だけ[]をつける

print 配列名[0][0][0] // 3次元配列の1つ目の要素
// 不足分はEMPTYで埋められる
dim sample1[2][1] = 0, 1, 2, 3
print sample1 // [[0, 1], [2, 3], [, ]]

// 超過分は捨てられる
dim sample2[1, 1] = 0, 1, 2, 3, 4, 5
print sample2 // [[0, 1], [2, 3]]

// 要素数省略
dim sample3[][1] = 1,2,3,4,5,6,7,8
print sample3 // [[1,2] ,[3,4], [5,6], [7,8]]

// 一番左以外は省略不可
dim bad_sample[][][1] // エラー

配列リテラルを使って多次元配列を作ることもできます

dim sample4[] = [1,2], [3,4], [5,6], [7,8]
sample5 = [[1,2] ,[3,4], [5,6], [7,8]]

連想配列

対応バージョン: 0.1.5

hashtbl 連想配列変数                              // 連想配列を宣言
hashtbl 連想配列変数 = HASH_CASECARE              // キーの大文字小文字を区別
hashtbl 連想配列変数 = HASH_SORT                  // キーでソート(※1)
hashtbl 連想配列変数 = HASH_CASECARE or HASH_SORT // 大小文字区別かつソート

連想配列変数[キー] = 値                  // 任意のキー名で値を代入、数値のキーは文字列に変換される
値 = 連想配列変数[キー]                  // キー名で値を読み出す、キーがない場合はEMPTY
真偽値 = 連想配列変数[キー, HASH_EXISTS] // キーが存在するかどうか ※2
真偽値 = 連想配列変数[キー, HASH_REMOVE] // キーを削除、成功時はTRUE
キー = 連想配列変数[i, HASH_KEY]         // i番目の要素のキーを取得 ※3
値 = 連想配列変数[i, HASH_VAL]           // i番目の要素の値を取得 ※3

連想配列変数 = HASH_REMOVEALL  // 要素をすべて消す

// カンマ区切りで一括定義可能、オプションも指定できる
hashtbl 変数1, 変数2 = HASH_CASECARE, 変数3 = HASH_SORT
hashtbl hoge
hoge["foo"] = 100
print hoge["foo"] // 100
hoge["FOO"] = 200
print hoge["foo"] // 200 大小文字区別がないため上書きされた
hoge["bar"] = 400
hoge["baz"] = 600

for i = 0 to length(hoge) - 1
    print hoge[i, HASH_KEY] // foo, bar, baz の順で表示される
    print hoge[i, HASH_VAL] // 200, 400, 600
next

print hoge["bar", HASH_EXISTS] // true
print hoge["qux", HASH_EXISTS] // false
hoge["bar", HASH_REMOVE] // 変数で受けなくてもOK
print hoge["bar", HASH_EXISTS] // false

hashtbl fuga = HASH_CASECARE
fuga["foo"] = 1
fuga["Foo"] = 2
fuga["FOO"] = 3
print fuga // {"foo": 1, "Foo": 2, "FOO": 3}

hashtbl piyo = HASH_SORT
piyo["b"] = ""
piyo["z"] = ""
piyo["a"] = ""
print piyo // {"A": , "B": , "Z": }

enum

対応バージョン: 0.1.7

列挙体を定義します
グローバルスコープの定数として定義されます

// 定義
enum 定数名
    メンバ名
    メンバ名 [ = 数値]
endenum

// 呼び出し
定数名.メンバ名

メンバには上から順に数値が割り当てられます (0から)
メンバ名 = 数値とすることで任意の値を割り当てられます
ただし前のメンバより大きな値のみ有効です

// 0から順に割り当てられる
enum E
    foo // 0
    bar // 1
    baz // 2
endenum

// 呼び出しは定数名.メンバ名
print E.foo // 0
print E.bar // 1
print E.baz // 2

// 数値を指定
enum E
    foo = 10 // 10
    bar = 20 // 20
endenum

// 一箇所指定するとそれ以降はその値から加算されていく
enum E
    foo = 10 // 10
    bar      // 11 (上の10 に +1される)
    baz      // 12
endenum

// 途中も可
enum E
    foo      // 0
    bar = 10 // 10
    baz      // 11
endenum
enum E
    foo = 100    // 100
    bar          // 101
    baz = 200    // 200
    qux          // 201
endenum

// 以下はNG

enum E
    foo
    foo // 同じ名前はダメ
endenum

// 前の数値より大きくないとダメ
enum E
    foo // 0
    bar // 1
    baz = 1 // 2以上じゃないとダメ
endenum
enum E
    foo = 50
    bar = 1 // 51以上じゃないとダメ
endenum

関数定義

関数名には英数字、一部記号、全角文字列が使えます
英字の大文字小文字は区別しません

procedure

function

対応バージョン: 0.1.2

procedure 関数名([引数, 引数, …])
    処理
fend

function 関数名([引数, 引数, …])
    [result = 戻り値]
fend

procedureは戻り値がありません
functionresult変数の値が戻り値となります
resultの初期値はEMPTYです resultの記述がない場合はEMPTYを返します

hoge(1,2,3) // 6
print fuga(1,2,3) // 6

procedure hoge(a, b, c)
    print a + b + c
fend
function fuga(a, b, c)
    result = a + b + c
fend

関数定義の入れ子はダメ

// エラーになる
procedure p()
    procedure q()
    fend
fend

特殊な引数

参照渡し

引数の前に var または ref キーワードをつけることで参照渡しが可能な引数になります
引数に変数を渡すとその変数に関数実行中の変更が反映されます
変数以外の式を渡した場合は通常の引数と同様に振る舞います

a = 2
print a // 2
p(a)
print a // 6
q(a)
print a // 16

procedure p(ref r)
    r *= 3
fend

procedure q(var v)
    v += 10
fend
配列表記

引数[] とすることで配列変数または連想配列変数を受ける引数にできます
変数以外が渡されるとエラーになります (互換性のため配列ではない変数も渡せる)

dim a[] = 1,2,3
p(a) // 3

// 配列ではない変数も受けられる
b = 12345
p(b) // 5

p("abc") // 変数じゃないのでダメ

procedure p(arr[])
    print length(arr)
fend
デフォルト値

引数 = 値 とすることで引数のデフォルト値を指定できます
値を省略した場合はEMPTYがデフォルト値になります
呼び出し時に引数を渡さなかった場合デフォルト値が適用されます

print f(2)    // 0
print f(2, 3) // 6

function f(n, m = 0)
    result = n * m
fend

// デフォルト値を省略した場合はEMPTYが入る
procedure p(arg = )
    print arg == EMPTY // True
fend

デフォルト値を持つ引数のあとに別の種類の引数は指定できません

procedure p(a = 1, b = 2, c = 3) // ok 
fend
procedure q(a = 1, b, c = 3)     // エラー 
fend
procedure r(a, b = 2, c = 3)     // 前ならok 
fend
可変長引数

引数の前に args または prms キーワードをつけることで可変長の引数を受けられるようになります
関数内ではその引数が配列になります
可変長引数は最後の引数でなくてはいけません

print f(1)         // 1
print f(1,2,3,4,5) // 5

function f(args v)
    result = length(v)
fend

可変長引数のあとに引数があるとエラーになります

procedure p(prms a, b)    // エラー
fend
procedure q(a, b, prms c) // ok
fend
特殊な引数の組み合わせ

原則として組み合わせられません
配列表記の参照渡しのみOK

procedure p(ref foo[]) // これはOK

// こういうのはダメ
procedure p(ref foo = 1) // 参照 + デフォルト値
procedure p(ref params bar) // 参照 + 可変長
procedure p(params bar = 1) // 可変長 + デフォルト値

module

対応バージョン: 0.1.0

機能のモジュール化
モジュール名.メンバ名で各機能を利用可能にします

module モジュール名
    const 定数名 = 式      // モジュール名.定数名 で外部からアクセス可
    public 変数名[ = 式]   // モジュール名.変数名 で外部からアクセス可
    dim 変数名[ = 式]      // 外部からアクセス不可
    procedure モジュール名 // コンストラクタ、module定義の評価直後に実行される
    procedure 関数名()     // モジュール名.関数名() で外部からアクセス可
    function 関数名()      // モジュール名.関数名() で外部からアクセス可
    textblock 定数名       // モジュール名.定数名 で外部からアクセス可
endmodule

module関数内でのみ使える特殊な書式

module sample
    dim d = 1
    public p = 2
    const c = 3

    function f1()
        // 各メンバーには以下のようにアクセス可能
        print d
        print this.d
        print sample.d

        print p
        print this.p
        print sample.p

        print c
        print this.c
        print sample.c

        print f2()
        print this.f2()
        print sample.f2()
    fend

    function f2()
        result = 4
    fend

    function f3()
        print this.f4()   // in   メンバ関数が呼ばれる
        print global.f4() // out  module外の関数が呼ばれる
        print f4()        // in   メンバ関数が呼ばれる
    fend

    function f4()
        result = "in"
    fend
endmodule

function f4()
    result = "out"
fend

プライベート関数

無名関数を用いたプライベート関数の実装例

Sample.Private() // エラー
Sample.Func()    // OK

module Sample
    function Func()
        result = Private()
    fend

    dim Private = function()
        result = "OK"
    fend
endmodule

class

対応バージョン: 0.1.3

classを定義します
class名()を実行することによりインスタンスを作成します
※ 注意: UWSCのclassとは互換性がありません

class class名
    procedure class名()    // コンストラクタ (必須)
    procedure _class名_()  // デストラクタ (オプション)
    const 定数名 = 式      // classインスタンス.定数名 で呼び出し可
    public 変数名[ = 式]   // classインスタンス.変数名 で呼び出し可
    dim 変数名[ = 式]      // class内からのみ呼び出し可
    procedure 関数名()     // classインスタンス.関数名() で呼び出し可
    function 関数名()      // classインスタンス.関数名() で呼び出し可
    textblock 定数名       // classインスタンス.定数名 で呼び出し可
endclass

h1 = hoge(3, 5)
print h1.Total() // 8

h2 = hoge(8, 10)
print h2.Total() // 18

print hoge(11, 22).Total() // 33

class hoge
    dim a = 1, b = 2
    procedure hoge(a, b)
        this.a = a
        this.b = b
    fend
    function Total()
        result = this.a + this.b
    fend
endclass

moduleと異なりclass名から直接メンバにアクセスすることはできません

print hoge.p() // エラー

インスタンスの破棄およびデストラクタについて

デストラクタはインスタンスが破棄される際に実行される関数です
_class名_() で命名された関数がデストラクタとして定義されます
デストラクタに引数は指定できません
(デストラクタが定義されていればインスタンス破棄の直前に実行されます)

インスタンスが破棄されるタイミングは

※ 明示的な破棄を行わなかったインスタンスのみが対象です

破毀されたインスタンスはNOTHINGになります

UObject

対応バージョン: 0.1.7

json互換のオブジェクト

オブジェクトの作成

  1. UObjectリテラル: jsonを@で括る
  2. FROMJSON関数
obj = @{
    "foo": "fooooo",
    "bar": {
        "baz": true
    },
    "qux": [
        {"quux": 1},
        {"quux": 2},
        {"quux": 3}
    ]
}@

arr = @[1, 2, 3]@

有効な値は

値の呼び出し、変更

print obj.foo // fooooo
obj.foo = "FOOOOO"
print obj.foo // FOOOOO
print obj["foo"] // 配列の添字にしてもOK

print obj.bar.baz ? "baz is true!": "baz is fasle!" // baz is true!

obj.qux[1].quux = 5
print obj.qux[1].quux // 5

obj.qux[2] = "overwrite!"
print obj.qux[2] // overwrite!

obj.corge = 1 // エラー、追加はできない

// オブジェクトを作って代入ならOK
obj.foo = fromjson('{"hoge": 1, "fuga": 2}')
print obj.foo


無名関数

対応バージョン: 0.1.0

変数 = function([引数, ...])
    [result = 戻り値]
fend
変数 = procedure([引数, ...])
fend

変数に関数を代入できます

hoge = function(x, y)
    result = x + y
fend

print hoge(2, 3) // 5

変数への代入は可能ですが即時関数のようなことはできません

// こういうのは無理
print (function(n)
    result = n * 2
fend)(5)

無名関数の中でpublic/constを宣言した場合は実行時に初めて評価されます

print x // エラー

proc = procedure()
    public x = 5
fend

print x // エラー

proc()

print x // 5

通常の関数と同様に特殊な引数も定義できます

f = function(a, b[], var c, d = 0)
fend
p = procedure(args e)
fend

簡易関数式

対応バージョン: 0.1.6

無名関数を単行の式で記述できます
通常の無名関数と異なり処理部に文は書けません(式のみ)
その代わりに即時関数として利用できます

関数 = | 引数 [, 引数, …] => 式 [; 式; …] |

引数は,区切りで複数指定可能
resultは省略可能です

func = | a, b => a + b |
print func(1, 2) // 3

式は ; 区切りで複数書けます
この場合一番最後の式が戻り値となります

func = | a, b => a *= 2; b *= 3; a + b |
print func(1, 2) // 8

即時関数

print | n, m => n * m |(7, 6) // 42
// 値だけ返す
print |=> 42|() // 42

// 関数の引数にする
function f(fn)
    result = fn("world!")
fend
print f(| s => "hello " + s |) // hello world!

特殊な引数にも対応

print | args a => length(a) |(1,2,3,4,5,6) // 6

評価の順序

対応バージョン: 0.1.0

グローバル変数や定数、関数定義は実行より先に評価されます

  1. public, const, textblockを記述順に評価
  2. function, procedure, moduleを記述順に評価
    • 関数内で宣言されているpublicやconstも評価
  3. 残りの構文を評価/実行する

スコープ

対応バージョン: 0.1.0

スコープは大きくわけて

で分かれています
変数にはローカルとグローバルという区分があり、

という特徴があります

public global1 = "グローバル変数1"
dim local = "本文ローカル"

print global1 // ok
print global2 // ok
print local // ok
print proc_local // ng
print func() // ok

procedure proc()
    public global2 = "グローバル変数2"
    dim proc_local = "関数ローカル"
    print global1 // ok
    print global2 // ok
    print local // ng
    print proc_local // ok
    print func() // ok
fend

function func()
    result = "関数"
fend

無名関数のスコープ

無名関数の中はスコープが分かれていません
ローカル変数がそのまま使えます

dim local = 1
dim func = function(n)
    result = local + n
fend

print func(1) // 2

moduleのスコープ

moduleメンバに関しては独自のスコープを持ちます
module関数内で定義したpublic, const, function/procedureはグローバル空間には置かれず、
moduleメンバのみがアクセスできるmoduleローカル空間に配置されます

これらはmodule名.メンバ名でアクセスできます

文字列

対応バージョン: 0.1.1

文字列リテラルは""または''で括ります
" で括った文字列では特殊文字が展開されます
' で括った文字列では特殊文字が展開されません

str = "文字列"
str = '文字列'

文字列の結合は+演算子を使います

str = "文字列" + "の" + "結合"
print str // 文字列の結合

特殊文字の展開

" で括った文字列中にある以下の特殊文字は、それぞれ該当する別の文字に変換されます

print "hoge<#CR>fuga<#CR>piyo"
// hoge
// fuga
// piyo
print "hoge<#TAB>fuga<#TAB>piyo"
// hoge    fuga    piyo
print "<#DBL>hoge<#DBL>"
// "hoge"

dim a = 123
print "a is <#a>"
// a is 123
print "b is <#b>" // 変数が存在しない場合は展開されない
// b is <#b>
print "length of a is <#length(a)>" // 式はダメ、変数のみ展開される
// length of a is <#length(a)>

print 'a is <#a>' // シングルクォーテーション文字列は展開しない
// a is <#a>

ホワイトスペース

はホワイトスペース扱いです
式と式の区切りとして機能します

改行(CRLF、CR、LF)は行末扱いです

演算子

対応バージョン: 0.1.9

演算子 処理
+ 数値の加算、文字列の結合、配列要素の追加
+= +演算して代入
- 数値の減算
-= 減算して代入
* 数値の乗算
*= 乗算して代入
/ 数値の除算 ※ 0で割ると0を返す
/= 除算して代入
mod 数値の剰余演算 (割った余りを返す)
! 論理否定
?: 三項演算子 b ? t : f
:= 代入 (代入した値を返す)
= 代入、等価演算
== 等価演算
<> != 不等価演算
and 数値のAND演算(ビット演算)、真偽値の論理演算
or 数値のOR演算(ビット演算)、真偽値の論理演算
xor 数値のXOR演算(ビット演算)、真偽値の論理演算
andL 論理演算 (両辺の真偽性評価を行う)
orL 論理演算 (両辺の真偽性評価を行う)
xorL 論理演算 (両辺の真偽性評価を行う)
andB ビット演算 (両辺を数値とみなし評価を行う)
orB ビット演算 (両辺を数値とみなし評価を行う)
xorB ビット演算 (両辺を数値とみなし評価を行う)
< 小なり
<= 小なりイコール
> 大なり
>= 大なりイコール
. moduleやオブジェクトのメンバへのアクセス

演算式の優先順位

対応バージョン: 0.1.9

優先順位の高いものから先に演算を行います

  1. ()
  2. .
  3. !
  4. * / mod
  5. + -
  6. =(等価比較) == <> !=
  7. and (L,Bを含む)
  8. or xor (L,Bを含む)
  9. ?:
  10. :=

代入系演算子は順位判定とは別に代入処理判定を行っています

// 2つ目の = は代入ではなく比較になるので a にはboolが入る
a = b = c

// こういうのはダメ、演算中に代入はしない
a + b + c += d 

例外として:=による代入があります
:=による代入は式であり、変数に代入された値を返します

print n := 1               // 1 (代入した値が返る)
print n                    // 1
print 1 + 2 + (n := 3) + 4 // 10 (代入した値が返り、その値で計算が行われる)
print n                    // 3

真偽判定

対応バージョン: 0.1.9

真偽性の評価が行われる場合(ifの条件式など)に

は偽となります
それ以外は真です

print NOTHING ? '真' : '偽' // 偽
print "" ? '真' : '偽' // 偽
print "空ではない文字列" ? '真' : '偽' // 真
print [1,2,3] ? '真' : '偽' // 真
print [] ? '真' : '偽' // 偽

コメント

// 以降は行末までコメントです (構文解析されない)
// があった時点で行末扱いになります

a = 1
// a = a + 1
print a // 1 が出力される

行結合

対応バージョン: 0.1.3

行末に _ を記述することで次の行と結合させます

a = 1 + 2 + _
3 + 4

print a // 10

マルチステートメント

対応バージョン: 未定

; をつけることで複数の文を1行に記述できます

a = 1; a = a + 1; print a // 2

組み込み定数

対応バージョン: 0.1.6

NaNについて

NaNNaN自身を含めあらゆる値と等価ではありません
またNaNとの大小の比較結果も必ず偽です

print NaN == NaN // False
print n   == NaN // False (nは何かしらの値)
print NaN != NaN // True 
print NaN <  n   // False 
print NaN <= n   // False 
print NaN >  n   // False 
print NaN >= n   // False 

16進数

対応バージョン: 0.0.1

16進数リテラル表記は $ を使います

print $FF // 255

起動時パラメータ

対応バージョン: 0.1.2

スクリプトにパラメータを付与した場合にそれらがPARAM_STR[]に格納されます

OPTION

対応バージョン: 0.1.7

// bool値指定は省略可能で、省略時はtrueになります
// 例:
// OPTION EXPLICIT // explicit設定をtrueにする
// もともと設定がtrueになっているものをfalseに設定したい場合に値指定を使う
// OPTION SHORTCIRCUIT=FALSE // デフォルトtrueなのでfalseにする

// コメントアウトされているものは非対応か現時点では動作しないものです

OPTION EXPLICIT[=bool]             // ローカル変数初期化時にdim宣言が必須かどうか (初期値:false)
// OPTION SAMESTR[=bool]           // 文字列の比較等で大文字小文字を区別するかどうか (初期値:false)
// OPTION OPTPUBLIC[=bool]         // public変数の重複定義を禁止するかどうか (初期値:false)
OPTION OPTFINALLY[=bool]           // tryで強制終了時にfinally部を実行するかどうか (初期値:false)
// OPTION SPECIALCHAR[=bool]       // 互換性のため設定は可能ですが機能しません ※1
// OPTION SHORTCIRCUIT[=bool]      // 論理演算で短絡評価を行うかどうか (初期値:true)
// OPTION NOSTOPHOTKEY[=bool]      // 停止ホットキーを無効にするかどうか (初期値:false)
// OPTION TOPSTOPFORM[=bool]       // 停止ボタン実装の予定がありません
// OPTION FIXBALLOON[=bool]        // 吹き出しを仮想デスクトップにも表示するかどうか (初期値:false)
// OPTION DEFAULTFONT="name,n"     // ダイアログ等のフォント指定  (初期値:"MS Gothic,12")
// OPTION POSITION=x,y             // メインGUIの座標指定 (初期値:0, 0)
OPTION LOGPATH="path"              // ログ保存フォルダを指定 ※2 (初期値:スクリプトのあるフォルダ)
// OPTION LOGLINES=n               // ログファイルの最大行数を指定 (初期値:400)
OPTION LOGFILE=n                   // ログファイルの出力方法 ※3 (初期値:1)
// OPTION DLGTITLE="title"         // ダイアログのタイトル (初期値:"UWSCR - スクリプト名")

// ※1 '文字列'を使ってください
// ※2 存在するディレクトリを指定するとそこに`uwscr.log`を出力
//     それ以外はファイルパスとして扱われます
// ※3 現時点では細かい設定ができません
//     1: ログ出力なし
//     2: ログ出力あり
//     3: ログ出力あり
//     4: ログ出力あり
//     それ以外: ログ出力なし

def_dll

対応バージョン: 0.1.9

DLL関数 (Win32 APIなど) を呼び出せるようにします
32bit版UWSCRでは32bitのDLL、64bit版では64bitのDLLに対応します

def_dll 関数名(型, 型, ...): 戻り型: DLLパス
def_dll 関数名(型, 型, ...): DLLパス // 戻り値がvoidの場合省略できる

型定義について

以下の型を指定できます
一部の型はx86/x64でサイズが変わります
一部の型は引数定義、または戻り値定義でのみ指定可能です

型名 サイズ 詳細 対応する値型 引数 戻り値 備考
int, long, bool 4 符号あり32ビット整数 数値
uint, dword 4 符号なし32ビット整数 数値
hwnd 4 / 8 ウィンドウハンドル 数値
float 4 単精度浮動小数点数 数値(小数)
double 8 倍精度浮動小数点数 数値(小数) UWSCRの標準数値型
word, wchar 2 符号なし16ビット整数 数値
byte, char, boolean 1 符号なし8ビット整数 数値
longlong 8 符号あり64ビット整数 数値
string 4 / 8 ANSI文字列のポインタ 文字列, NULL OSの現在のANSIコードによる
pchar 4 / 8 ANSI文字列のポインタ 文字列, NULL NULL含む
wstring 4 / 8 ワイド文字列のポインタ 文字列, NULL Unicode文字列
pwchar 4 / 8 ワイド文字列のポインタ 文字列, NULL NULL含む
pointer 4 / 8 ポインタを示す数値(符号なし) 数値 新規
struct 4 / 8 ユーザー定義構造体のポインタ 構造体インスタンス 新規 struct-endstructで定義
callback 4 / 8 コールバック関数のポインタ 新規 動作未定義
safearray SafeArray型 SafeArray 動作未定義
void 型がないことを示す

特殊な型定義

参照渡し

var 型 で参照渡しになります
DLL関数により引数が書き換えられる場合にvarを付与することにより変更後の値を渡した変数で受けられる

注意 ポインタになるわけではありません (内部処理により元の変数の値を書き換える)

配列の定義

型[] で配列変数を受ける型になります
varの有無に関わらずDLL関数により値が変更される場合があります
配列変数はポインタになるためサイズは4または8です

構造体の定義

{型, 型, ...} で構造体を定義します
構造体定義内ではvarの有無に関わらずDLL関数により値が変更される場合があります
構造体定義はポインタになるためサイズは4または8です

構造体定義のネストはできません
平の定義に展開されます

def_dll hoge({long, {long, long}}):hoge:dll
// ↑同じ↓
def_dll hoge({long, long, long}):hoge:dll

DLL関数定義例

// Win32のA関数ではstringかpcharを使う
def_dll MessageBoxA(hwnd, string, string, uint):int:user32.dll
// Win32のW関数ではwstringかpwcharを使う
def_dll MessageBoxW(hwnd, wstring, wstring, uint):int:user32.dll

// 構造体定義は{}
def_dll SetWindowPlacement(hwnd, {uint, uint, uint, long, long, long, long, long, long, long, long}):bool:user32.dll

// 参照渡し
def_dll GetPrivateProfileStringA(string, string, string, var pchar, dword, string):dword:kernel32

// 構造体で実行後の値を受ける場合にvarは不要
def_dll GetCursorPos({long, long}):bool:user32.dll
// 構造体はそのサイズに合う配列でも代用可能
def_dll GetCursorPos(long[]):bool:user32.dll

DLL関数定義例およびその呼び出し方

// Win32のA関数ではstringかpcharを使う
def_dll MessageBoxA(hwnd, string, pchar, uint):int:user32.dll
// Win32のW関数ではwstringかpwcharを使う
def_dll MessageBoxW(hwnd, wstring, pwchar, uint):int:user32.dll

// 呼び出す際は単に文字列を渡すだけで良い
print MessageBoxA(0, 'メッセージ', 'タイトル', 0)
print MessageBoxW(0, 'メッセージ', 'タイトル', 0)

// 構造体定義は{}
def_dll SetWindowPlacement(hwnd, {uint, uint, uint, long, long, long, long, long, long, long, long}):bool:user32.dll
id = getid("メモ帳")
h = idtohnd(id)
// 構造体を渡すときは定義した型の数だけ値を並べる
SetWindowPlacement(h, 44, 0, 1, 0, 0, 0, 0, 200, 200, 600, 600)

// 参照渡し
def_dll GetPrivateProfileStringA(string, string, string, var pchar, dword, string):dword:kernel32
buffer = '                                                     '
// bufferがpcharなのでNULLを含んだ文字列が返ってくる
print GetPrivateProfileStringA(NULL, NULL, "default", buffer, length(buffer), "test.ini")
print buffer
def_dll GetPrivateProfileStringA(string, string, string, var string, dword, string):dword:kernel32
buffer = '                                                     '
// bufferをstringにすると最初のNULL以前の文字列のみ返ってくる
print GetPrivateProfileStringA(NULL, NULL, "default", buffer, length(buffer), "test.ini")
print buffer

// 構造体で値を受ける
// varは不要
def_dll GetCursorPos({long, long}):bool:user32.dll
dim x, y
print GetCursorPos(x, y)
print [x, y]

// 構造体はそのサイズに合う配列でも代用可能
// varは不要
def_dll GetCursorPos(long[]):bool:user32.dll
dim point = [0, 0] // long, long
print GetCursorPos(point)
print point

// 戻り値の型の制限
def_dll PathAddBackslashW(var string):string:ShlwApi.dll
path = "d:\hoge"
print PathAddBackslashW(path)
print path
// このような場合UWSCでは戻り値も文字列になりましたが、UWSCRでは安全のためこれをサポートしません
// この場合ポインタ(の数値)が返ります (その際警告文が標準出力されます)

構造体定義

対応バージョン: 0.1.9

def_dllのstruct型に渡す構造体を定義します

struct 構造体名
    メンバ名: 型
    メンバ名: 構造体名
    ︙
endstruct

はdef_dll定義で使うものと同等です(一部使用不可※)
構造体名は別に定義した構造体の名前です

構造体名()で構造体のインスタンスを作成します
インスタンス作成時に数値型は0、文字列型はNULLで初期化されます

struct Point
    x: long
    y: long
endstruct

dim p = Point()
// xとyは0で初期化されるため以下のような初期化処理は記述不要
// p.x = 0
// p.y = 0

def_dll GetCursorPos(struct):bool:user32.dll
GetCursorPos(p)
print [p.x, p.y]


struct Hoge
    id: uint
    point: Point // 構造体名を指定
endstruct

h = Hoge()
print h.id // 0
// Pointも初期化される
print h.point.x // 0
print h.point.y // 0

※ 利用可能な型

型名 サイズ 詳細 対応する値型
int, long, bool 4 符号あり32ビット整数 数値
uint, dword 4 符号なし32ビット整数 数値
hwnd 4 / 8 ウィンドウハンドル 数値
float 4 単精度浮動小数点数 数値(小数)
double 8 倍精度浮動小数点数 数値(小数)
word, wchar 2 符号なし16ビット整数 数値
byte, char, boolean 1 符号なし8ビット整数 数値
longlong 8 符号あり64ビット整数 数値
string 4 / 8 ANSI文字列のポインタ 文字列, NULL
pchar 4 / 8 ANSI文字列のポインタ 文字列, NULL
wstring 4 / 8 ワイド文字列のポインタ 文字列, NULL
pwchar 4 / 8 ワイド文字列のポインタ 文字列, NULL
pointer 4 / 8 ポインタを示す数値(符号なし) 数値

ポインタから構造体インスタンスを作る

DLL関数が作成した構造体のポインタを返す場合に、その構造体と同等の構造体を定義しておくことで値を受け取れます

struct SomeStruct
    foo: long
    bar: long
    baz: long
endstruct

// 
s = SomeStruct(pointer)
print s.foo

スレッド

thread

対応バージョン: 0.1.8

関数を別のスレッドで実行します

thread func()

タスク

対応バージョン: 0.1.8

関数を非同期実行します
threadとは異なり関数が完了し次第戻り値を受け取れます

async

タスクを返す関数を宣言します

// function宣言の前に async キーワードを付与
async function 関数名()
fend
async function MyFuncAsync(n)
    sleep(n)
    result = "<#n>秒待ちました"
fend

task = MyFuncAsync(5) // resultの値ではなくタスクを返す

// 以下と同じ結果になります
function MyFuncAsync(n)
    sleep(n)
    result = "<#n>秒待ちました"
fend

task = Task(MyFuncAsync, 5)

await

async宣言した関数の終了を待ち、resultの値を得ます

async function MyFuncAsync(n)
    sleep(n)
    result = "<#n>秒待ちました"
fend

// MyFuncAsync()の処理が終了するまで待つ
print await MyFuncAsync(5) // 5秒待ちました

with

対応バージョン: 0.1.1

.演算子の左辺(module名やオブジェクト)を省略できます

with foo
    print .bar // foo.bar
    .baz()     // foo.baz()
endwith

ネストも可

with m
    print .p // m.p
    with .f() // m.f() のwithでネスト
        print .p // m2.p
    endwith
    print .p // m.p
endwith

module m
    public p = "m.p"
    function f()
        result = m2
    fend
endmodule

module m2
    public p = "m2.p"
endmodule

textblock

対応バージョン: 0.1.1

複数行文字列の定数を定義します
改行は<#CR>と一致します
特殊文字(<#CR>,<#DBL>,<#TAB>)はtextblock文の評価時に展開されます

textblock [定数名]
(複数行文字列)
endtextblock

定数名が省略された場合は複数行コメントとなり、スクリプトの一部として扱われません
(構文木が作られない)

// 定数hogeが作られる
textblock hoge
foo
bar
baz
endtextblock

// 定数省略時はコメント扱い
// 値を呼び出すことができない
textblock
ここはコメントです
endtextblock

textblockex

対応バージョン: 0.1.3

変数展開が可能なtextblockです
textblockex変数の評価時に展開されます

textblockex hoge
<#fuga>
endtextblock

fuga = 123
print hoge // 123
fuga = 456
print hoge // 456

call

対応バージョン: 0.1.6

他のスクリプトを取り込みます

call hoge.uws          // 実行するスクリプトからの相対パス
call hoge              // 拡張子のないファイルもOK、見つからない場合は.uwsを付けて開く
call fuga.uws(1, 2, 3) // 引数を渡すと PARAM_STR にはboolが入る

uwslファイルの読み込み

対応バージョン: 0.1.7

uwslファイルをcallして使えます

call mylib.uwsl // 拡張子はuwslのみ (省略不可)

uwslファイルについて

構文木をバイナリとして保存したものです
以下のコマンドでバイナリファイルを生成できます
ファイルはスクリプトと同じディレクトリに作成されます
拡張子は.uwslになります

uwscr --lib path\to\script.uws

callでの呼び出しにのみ対応しており、直接実行することはできません

uwscr hoge.uwsl // ng

uwslファイル作成の流れ

  1. 指定されたスクリプトを読み出す
  2. 構文解析を行い構文木を生成する
  3. 構文木をバイナリデータとしてファイルに書き出す

使用例

  1. 多段callしているファイルをまとめてバイナリ化

    // ファイル構成例
    main.uws (mylib.uwsをcall)
    
    // 多段call、これらがすべて解析され単一ファイルになる
    mylib.uws (module1 ~ 3 をcall)
      |_ module1.uws
      |_ module2.uws (submodule1, 2 をcall)
      | |_ submodule1.uws
      | |_ submodule2.uws
      |_ module3.uws
    
    uwscr -l mylib.uws // mylib.uwslが出力される
    
  2. uwslファイルをcallして使う

    // 総ファイル数を減らせる
    main.uws
    mylib.uwsl
    
    // main.uws
    call mylib.uwsl
    
    MyLib.DoSomething()
    Module1.DoSomethingElse()
    Module2.DoSomethingWithSubmodule(Submodule1.DoSomething)
    

例外処理

対応バージョン: 0.2.1

try部で発生した実行エラーを抑制し、以下の特殊変数にエラー情報を格納します

except部はtryでエラーが発生した場合のみ実行されます
finally部は必ず実行されます
finally部ではcontinue, break, exitが使えません (構文解析エラーになる)
try-except-finally-endtry

try
    try
    except
    endtry
finally
endtry

と同等です

except例

try
    print 1
    raise("エラー") // ここでエラー
    print 2 // 実行されない
except
    print TRY_ERRMSG // 実行される
endtry

try
    // エラーが発生しない場合
except
    print 1 // 実行されない
endtry

finally例

try
    print 1
    raise("エラー") // ここでエラー
    print 2 // 実行されない
finally
    print TRY_ERRMSG // 実行される
endtry

try
    // エラーが発生しない場合
finally
    print 1 // 実行される
endtry

except-finally例

try
    print 1
    raise("エラー") // ここでエラー
    print 2 // 実行されない
except
    print TRY_ERRMSG // 実行される
finally
    print TRY_ERRMSG // 実行される
endtry

try
    // エラーが発生しない場合
except
    print 1 // 実行されない
finally
    print 2 // 実行される
endtry

制御文

説明文中のとは主に値を返す演算式や関数など
は制御文のことです
ブロック文が複数行ある状態です

if

対応バージョン: 0.0.1 ※

ififbが区別されません
どちらも同じものとして扱われます

単行if

if 式 then 文 [else 文]

if foo then bar // `foo`が真の場合`bar`が実行され、偽の場合なにもしない
if foo then bar else baz// `foo`が真の場合`bar`、偽の場合`baz`が実行される

// ifb でもエラーにならない
ifb foo then bar

複数行if

if 式 [then]
    ブロック文
[elseif 式 [then]]
    ブロック文
[else 式]    
    ブロック文
endif

elseifは複数回記述できる

if foo then
    fooが真なら実行され偽ならなにもしない()
endif

if foo then
    fooが真なら実行される()
else
    fooが偽なら実行される()
endif


if foo then
    fooが真なら実行される()
elseif bar then
    fooが偽かつbarが真なら実行される()
elseif baz then
    fooが偽かつbazが真なら実行される()
else
    foobarbazいずれも偽なら実行される()
endif

for

対応バージョン: 0.0.1

for 変数 = 式1 to 式2 [step 式3]
    ブロック文
next

式1式3はいずれも数値を返す必要があります
step 式3 が省略された場合式31として扱われます
小数が渡された場合は整数に丸められます (UWSCとは仕様が異なります)

  1. 変数式1を代入した状態でブロック文を処理
  2. 変数の値に式3を加算したものを再代入しブロック文を処理
  3. 変数式2を超える値が代入されたら終了
  4. 終了後も変数の値は維持されます
for i = 0 to 2
    print i // 順に 0 1 2 が出力される
next
print i // 3

for i = 0 to 5 step 2
    print i // 順に 0 2 4 が出力される
next
print i // 6

// stepは減算も可能
for i = 5 to 0 step -1
    print i
next

// ループ変数に代入した場合
for i = 0 to 0
    print i // 0
    i = 10
    print i // 10
next
print i     // 1

// UWSCでは小数が利用可能でしたがUWSCRでは整数値に変換されます
for i = 0.1 to 1.9 step 0.1 // 0.1 -> 0, 1.9 -> 2 に丸められます
next

for-in

対応バージョン: 0.0.1 ※

※ 配列、連想配列、文字列のみ対応

for 変数 in 式
    ブロック文
next

は以下を返す必要があります

また、に特定の組み込み関数を指定した場合に特殊配列変数を用いたループを行います

が返す値をその種類に応じて分解し、変数に代入していきます

// 文字列は1文字ずつ分解
for char in "あいうえお"
    print char // あ い う え お が順に出力される
next

// 配列は各要素
for value in ["あ", "い", "う", "え", "お"]
    print value // あ い う え お が順に出力される
next

// 連想配列はキーを返す
hashtbl hoge = HASH_SORT
hoge["b"] = 2
hoge["a"] = 1
hoge["d"] = 3
hoge["c"] = 4

for key in hoge
    print key        // a b c d の順に出力される
    print hoge[key]  // 1 2 3 4 の順に出力される
next

while

対応バージョン: 0.0.1

while 式
    ブロック文
wend

が真である限りブロック文を繰り返し処理します
(ループ中に式を偽にしない限り無限ループする)

a = TRUE
while a
    a = DoSomething() // 偽値を返せばループ終了
wend

while false
    式が偽なら何も実行されない()
wend

while TRUE
    print "無限ループ"
wend

repeat

対応バージョン: 0.0.1

repeat
    ブロック文
until 式

が偽である限りブロック文を繰り返し処理します
(ループ中に式を真にしない限り無限ループする)

a = false
repeat
    a = DoSomething() // 真値を返せばループ終了
until a

repeat
    式が真でも一度は必ず実行される()
until TRUE

repeat
    print "無限ループ"
until FALSE

continue

対応バージョン: 0.0.1

continue [式]

ループ文(for, while, repet)にてループの先頭に戻ります
は正の整数を指定します
省略した場合1として扱われます
多重ループで複数のループをcontinueしたい場合に2以上(ループの数分)を指定します

for i = 0 to 2
    print "3回出力される"
    continue
    print "出力されない"
next

a = 1
b = 1
while a < 5
    while TRUE
        a = a + 1
        continue 2
        b = b + 1
    wend
wend
print a // 5
print b // 1

break

対応バージョン: 0.0.1

break [式]

ループ文(for, while, repet)にてループを抜けます
は正の整数を指定します
省略した場合1として扱われます
多重ループで複数のループをbreakしたい場合に2以上(ループの数分)を指定します

for i = 0 to 2
    print "1回だけ出力される"
    break
    print "出力されない"
next    

a = 0
repeat
    repeat
        repeat
            break 3
            a = a + 1
        until false
        a = a + 1
    until false
    a = a + 1
until false
print a // 0

select

対応バージョン: 0.0.1

select 式
    case 式
        ブロック文
    [case 式, 式 …]
        ブロック文
    [default]
        ブロック文
selend

select式を評価し、その結果とcase式が一致した場合にそのcase以下のブロック文が処理されます
caseに,区切りで式を複数指定した場合、いずれかが一致すればそのブロック文が処理されます

  1. select式を評価し結果を得る
  2. case式を評価しselect式の結果と比較
    • 一致した場合: その下のブロック文を処理しselectを終了する
    • 不一致の場合: 次のcaseまたはdefaultに進む
  3. defaultに到達した場合必ずその下のブロック文を処理する
  4. defaultがなくいずれのcaseにも一致しない場合なにも行わない
select hoge
    case 1
        hogeが1なら実行される()
    case 2, 3
        hogeが2か3なら実行される()
    case 3
        hogeが3でも上のcaseが該当してるので実行されない()
    default
        hogeが1~3以外なら実行される()
selend

select hoge
    default
        必ず実行される()
selend

select 1
    case 2
        なにも実行されない()
selend

exit

対応バージョン: 0.0.3

hoge() // 2 は出力されない

procedure hoge()
    print 1
    exit
    print 2
fend

exitexit

対応バージョン: 0.1.5

exitexit [数値]

数値を指定した場合はUWSCRの終了コードになります
(省略時は終了コード0)

print

対応バージョン: 0.0.1 ※

※ 専用ウィンドウがないため標準出力されます

COMオブジェクト

対応バージョン: 0.2.0

書式について

COMオブジェクトのメンバへのアクセス方法

COM_ERR_IGN-COM_ERR_RET

COMエラーの発生を無視して処理を続行させることができます

COM_ERR_IGNでCOMエラーを抑制します
COM_ERR_RETでCOMエラーの抑制を解除します

COM_ERR_IGNからCOM_ERR_RETの間でCOMエラーが発生した場合
実行時エラーで終了することなく処理を続行します
その際にCOM_ERR_FLGTRUEになります

COM_ERR_FLGCOM_ERR_IGNを呼んだ際にFALSEに初期化されます
COM_ERR_RETを呼んだ場合は値がそのまま維持されます

COM_ERR_IGNによるCOMエラーの抑制はスレッド単位で有効です

// 通常はCOMエラーで動作停止する
obj = createoleobj("Some.ComObject")
obj.FireError() // COMエラー!

// COMエラーを抑制するパターン
obj = createoleobj("Some.ComObject")
// COMエラー抑制開始
COM_ERR_IGN

print COM_ERR_FLG // False
obj.FireError() // エラーになるがスクリプトは停止しない
print COM_ERR_FLG // Trueになる

// COMエラー抑制終了
COM_ERR_RET

print COM_ERR_FLG // True; COM_ERR_RETでは初期化されない

obj.FireError() // 抑制していないのでCOMエラー