新構文使用例 - stuncloud/UWSCR GitHub Wiki
- 三項演算子
- 代入演算子
- 複合代入演算子
- 無名関数
- 高階関数
- クロージャ
- ビルトイン関数のエイリアス
- UObject
- CLASS
- Enum
- タスク
- 真偽性の評価
- 論理演算子・ビット演算子
- 演算子の特殊な使い方
- 構造体定義
- 引数の型指定
- INI関数のfid利用
- 連想配列一括定義
- call文のURL対応
- for-else-endfor
0.0.1 より
式 ? 真で返す式 : 偽で返す式式を評価しその真偽により値を返します
単行のIF文に似ていますが、こちらは式なので値を返します
a = FALSE
print a ? "a is TRUE": "a is FALSE"入れ子もできる
// fizzbuzz
for i = 1 to 100
    print i mod 15 ? i mod 5 ? i mod 3 ? i : "fizz" : "buzz" : "fizzbuzz"
next文は書けないのでこういうのはダメ
// printは文なのでエラーになる
hoge ? print "hoge is truthy" : print "hoge is falsy"0.1.5より
変数 := 式:=を使うことで式の中で変数への代入が行なえます
また、代入した値を返す式として機能します
// 条件式での代入
select name := GetSomeName() // 関数の戻り値を代入し、その値を条件とする
    case "foo", "bar", "baz"
        print "you got <#name>"
    default
        print "<#name> is not a valid name"
selend
// 複数の変数に同じ値を代入
a = b := c := 10
print a // 10
print b // 10
print c // 10
// a := b := c := 10 でも可0.0.2 より
変数 += 式  // 変数 = 変数 + 式 と同等
変数 -= 式  // 変数 = 変数 - 式 と同等
変数 *= 式  // 変数 = 変数 * 式 と同等
変数 /= 式  // 変数 = 変数 / 式 と同等左辺の値と右辺の値で演算を行い、それを左辺の変数に代入します
a = 10
a += 10
print a // 20
a -= 10
print a // 10
a *= 2
print a // 20
a /= 10
print a // 20.0.1 より
※ procedureは0.0.2から
変数 = function()
    result = 戻り値
fend
変数 = procedure()
fend変数に関数を代入できます
print2 = function(a, b)
    result = a + " " + b
fend
print print2("hello", "world!")通常の関数定義と異なり、代入処理を行う際に関数が評価されます
そのため以下のような記述はNGです
print hoge()
hoge = function()
    result = "これは未定義エラーになる"
fend0.0.1 より
関数の引数に関数を指定できます
print Math(10, 5, Add)      // 15
print Math(10, 5, Multiply) // 50
subtract = function(n, m)
    result = n - m
fend
print Math(10, 5, subtract) // 5
function Math(n, m, func)
    result = func(n, m)
fend
function Add(n, m)
    result = n + m
fend
function Multiply(n, m)
    result = n * m
fend0.0.3 より
クロージャが使えます
hoge = test(5)
print hoge(3)    // 8
print hoge(7)    // 12
print hoge("あ") // 5あ
function test(n)
    result = function(m)
        result = n + m
    fend
fendビルトイン関数も変数に代入できるので別名をつけて実行できます
public rp = replace
print rp("あいうえお", "い", "イ")0.1.7より
json互換オブジェクト
jsonを@で括ることでUObjectを生成できます
obj = @{
    "a": 1,
    "b": [1,2,3],
    "c": {
        "d": 10,
        "e": 20
    }
}@
print obj.a // 1
print obj.b[1] // 2
print obj.c.d // 10
print obj["c"]["d"] // 10
arr = @[1, [2, 3]]@
print arr[0] // 1
print arr[1][0] // 2変数展開を行います
foo = '文字列を展開'
bar = 123
textblock baz
,
"baz":{
    "qux": "なんでも書き込める"
}
endtextblock
obj = @{
    "foo": "<#foo>",
    "bar": <#bar>
    <#baz>
}@
print obj.foo     // 文字列を展開
print obj.bar     // 123
print obj.baz.qux // なんでも書き込める
json = ToJson(obj) // UObjectからjson文字列に変換
obj = FromJson(json) // json文字列からUObjectに変換0.1.3 より
UWSCの
CLASSとは機能が異なります
UWSCのCLASSと同等の機能が必要な場合はMODULEを使ってください
クラス名と同名のプロシージャ(コンストラクタ)を定義する必要があります
また_クラス名_()というプロシージャはデストラクタとなります
デストラクタは必須ではありません
class MyClass
    procedure MyClass() // コンストラクタ (必須)
    fend
    procedure _MyClass_() // デストラクタ (オプション)
    fend
endclassコンストラクタ()を実行するとインスタンスを返します
ins1 = MyClass(10)
print ins1.GetN() // 10
ins2 = MyClass(20)
print ins2.GetN() // 20
class MyClass
    dim n
    procedure MyClass(n)
        this.n = n
    fend
    function GetN()
        result = n
    fend
endclassインスタンス変数にNOTHINGを代入するとインスタンスを明示的に破棄できます
その際にデストラクタが(定義してあれば)実行されます
インスタンス変数はインスタンスの参照なので別の変数に代入していた場合いずれもNOTHINGになります
ins1 = MyClass("hoge")
ins2 = ins1
ins1 = NOTHING // "hogeが破棄されました" がprintされる
print ins1 // NOTHING
print ins2 // NOTHING ※ ins1と同じインスタンスを参照しているのでこちらもNOTHINGになる
class MyClass
    dim name
    procedure MyClass(name)
        this.name = name
    fend
    procedure _MyClass_()
        print "<#name>が破棄されました"
    fend
endclass明示的に破棄を行わなかった場合は、インスタンスが作成されたスコープから抜ける際にすべてのインスタンスが自動的に破棄されます
ただし、public変数やresultなどスコープ外にインスタンスが作られる場合は例外です
withでインスタンスを作成した場合はendwithで破毀されます
public pub
ins1 = MyClass("in main script")
ins2 = f() // 関数の戻り値がインスタンスの場合、このスコープの終わりに破棄される
MyClass("no variable").PrintName() // 変数にインスタンスを代入しない場合もスコープ終了時に破棄される
with MyClass("with")
    .PrintName()
endwith // ここで破棄される
print "end of main script"
function f()
    ins = MyClass("in function") // 関数fのスコープ内で作成されたので関数の終わりに破棄される
    pub = MyClass("public") // public変数のため関数スコープでは破棄されない
    result = MyClass("result") // resultのため関数スコープでは破棄されない
    print "end of function"
fend
class MyClass
    dim name
    procedure MyClass(name)
        this.name = name
    fend
    procedure PrintName()
        print "nameは<#name>です"
    fend
    procedure _MyClass_()
        print "<#name>が破棄されました"
    fend
endclass実行結果
end of function
in functionが破棄されました
nameはno variableです
nameはwithです
withが破棄されました
end of main script
in main scriptが破棄されました
resultが破棄されました
no variableが破棄されました
publicが破棄されました0.1.7 より
シンプルな列挙体
enum定数として定義され、値は数値のみです
enum E
    foo
    bar
    baz
endenum
print E.foo // 0
print E.bar // 1
print E.baz // 2
enum E2
    foo = 100
    bar
    baz = 200
    qux
endenum
print E.foo // 100
print E.bar // 101
print E.baz // 200
print E.qux // 201任意の関数を非同期に実行する仕組みです
タスク利用の流れ
- タスク関数を使う
- async/awaitを使う
- async宣言した関数をawaitして呼ぶ
 
- asyncとWaitTask
- async宣言した関数を実行しタスクを得る
- WaitTask関数でタスクの終了を待ち非同期実行した関数の戻り値を得る
 
function MyTask()
    // 時間のかかる処理
    result = somevalue
fend
t = Task(MyTask) // タスクを作る
// タスク終了を待つ間別の処理を行う
DoSomething()
r = WaitTask(t) // somevalueを得る上記は以下のようにも書けます
// async宣言
async function MyTask()
    // 時間のかかる処理
    result = somevalue
fend
t = MyTask() // async宣言した関数はタスクを返す
DoSomething()
r = WaitTask(t)async宣言した関数はawaitで呼ぶことで完了を待ち戻り値を得られます
async function MyTask()
    // 時間のかかる処理
    result = somevalue
fend
r = await MyTask() // 実行をブロックして関数の終了を待つ以下では真偽性が評価されます
- ifの条件式 (if 条件式 then ...)
- elseifの条件式 (elseif 条件式 then ...)
- 三項演算子の条件式 (条件式 ? ...)
- whileの条件式 (while 条件式 ...)
- untilの条件式 (... until 条件式)
- 論理演算子の両辺 (左辺 andL 右辺)
以下は偽(falsy)と判定されます
- FALSE
- 0
- EMPTY
- 
NOTHING- 破棄されたインスタンスを含む
 
- 
""(空の文字列)
- 
[](空の配列)
それ以外は真(truthy)です
if FALSE then
elseif
    print "FALSEが偽"
endif
print NOTHING ? '' : 'NOTHINGは偽'
while ""
    print "空文字列は偽なのでこの文字列はprintされません"
wend
repeat
    print "空でない文字列は真なのでこのループは一周で終了します"
until "ループを抜けます"AND、OR、XORは両辺により論理演算またはビット演算が行われていましたが
それとは別に以下が追加されました
- 論理演算のみを行う演算子 (末尾がL)
- 演算結果がbool値
 
- ビット演算のみを行う演算子 (末尾がB)
- 演算結果が数値
 
// 論理演算子
// 両辺の真偽性を評価してから演算を行う
print true andl false // false
print true andl NOTHING // false
print NULL andl 'a' // true
print 1 xorl [1,2] // false
// ビット演算子
// 両辺を数値として評価してから演算を行う
print 3 andb 5 // 1
print 3 orb 5 // 7
print 3 xorb 5 // 6
print 1 andb '1' // 1
print 1 andb true // 1文字列 * 数値 で数値分文字列を繰り返します
print 'a' * 6 // aaaaaa
print 'abc' * 3 // abcabcabc
a = 'a'
a *= 3
print a // aaa
// NULLは chr(0) 相当
buf = NULL * 260
print buf         // 
print length(buf) // 260文字列にNULL文字を追加できます
hoge = "hoge" + NULL
print hoge         // hoge
print length(hoge) // 5struct-endstruct 構文で定義した構造体をDLL関数に渡すことができます
def_dllで定義する際に struct を指定します
var struct で渡した構造体に値を受け取れます
def_dll SetWindowPlacement(hwnd, struct):bool:user32.dll
def_dll GetWindowPlacement(hwnd, var struct):bool:user32.dll
struct WindowPlacement
    length  : uint
    flags   : uint
    showCmd : uint
    min_x   : long
    min_y   : long
    max_x   : long
    max_y   : long
    left    : long
    top     : long
    right   : long
    bottom  : long
endstruct
// 構造体のインスタンスを作る
wp = WindowPlacement()
// 値をセット
wp.length = length(WindowPlacement) // 構造体サイズはlengthで得られる
// wp.length = length(wp) // これでもOK
wp.showCmd = 1
wp.left    = 200
wp.top     = 200
wp.right   = 600
wp.bottom  = 600
id = exec('notepad', false, 0, 0, 300, 300)
print id
h = idtohnd(id)
print '1秒後にSetWindowPlacement'
sleep(1)
print SetWindowPlacement(h, wp)
print '1秒後にacwでサイズ変更しGetWindowPlacement'
acw(id, 300, 300, 500, 500, 1000)
print GetWindowPlacement(h, wp)
print 'GetWindowPlacement ' + [wp.top, wp.top, wp.right, wp.bottom]ユーザー定義関数の引数定義にデータ型を併記することで受ける型を限定できます
引数名: 型名 で定義します
- 通常の引数
- 引数名: 型名
 
- 参照渡し
- var 引数名: 型名
- ref 引数名: 型名
 
- デフォルト値
- 引数名: 型名 = デフォルト値
 
- 文字列
- 
stringfunction f(s: string) fend f("展開可能文字列") f('文字列') 
 
- 
- 数値
- 
numberfunction f(n: number) fend f(123) f($FF) 
 
- 
- 真偽値 (TRUE/FALSE)
- 
boolfunction f(b: bool) fend f(TRUE) f(FALSE) 
 
- 
- 配列
- 
arrayfunction f(a: array) fend f([1,2,3]) arr[] = 4,5,6 f(arr) 
 
- 
- 連想配列
- 
hashfunction f(h: hash) fend hashtbl h h[1] = 1 f(h) 
 
- 
- 関数 (ユーザー定義関数, 無名関数)
- 
funcfunction f1(f: func) fend function f2() fend f3 = function() fend f1(f2) f1(f3) f1(|=>1|) 
 
- 
- UObject
- 
uobjectfunction f(o: uobject) fend f(@{"a": 1}@) o = @{ "foo": 1, "bar": 2 }@ f(o) 
 
- 
- クラスオブジェクトインスタンス
- クラス名
function f(c: Hoge) fend class Hoge() procedure Hoge fend endclass class Fuga() procedure Fuga fend endclass hoge = Hoge() fuga = Fuga() f(hoge) // OK f(fuga) // エラー 
 
- クラス名
readini/writeini/deleteiniのファイルパスの代わりにfopenして得たfidを渡せるようになりました
fid = fopen(path, F_READ)
readini(section, key1, fid)
readini(section, key2, fid)
readini(section, key3, fid)
fclose(fid)
fid = fopen(path, F_READ or F_WRITE)
writeini(section, key1, value, fid)
deleteini(section, key3, fid)
fclose(fid) // 書き込みが反映される
// iniの読み書きに排他制御を入れる
fid = fopen(path, F_READ or F_WRITE or F_EXCLUSIVE)
writeini(section, key3, value, fid)
fclose(fid)hash-endhash文を使うことで連想配列定義と同時にキーと値も定義できます
hash foobar
    foo = 1
    bar = 2
endhash
print foobar['foo'] // 1
print foobar['bar'] // 2
// publicやオプション指定する場合
hash public pub
endhash
hash with_option = HASH_SORT or HASH_CASECARE
endhashweb上のスクリプトをcallできます
call url[http://example.com/mymodule.uws]
print MyModule.Do()forループをbreakしなかった場合にelseを実行します
for i = 0 to length(items) - 1
    if items[i] == target then
        // 要素のいずれかがtargetと一致した場合break
        target_found()
        break
    endif
else
    // いずれの要素もtargetと一致しない場合はbreakしないのでこちらが実行される
    target_not_found()
endfor
// for-inにも対応
for item in items
    if item == target then
        target_found()
        break
    endif
else
    target_not_found()
endfor
// ループ内の処理が行われない場合でもelseが実行される
for i = 0 to -1
    print 1 // 実行されないため表示もされない
else
    print 2 // 2と表示される
endfor
for a in []
    print 1 // 実行されない
else
    print 2 // 2と表示される
endfor