-
Notifications
You must be signed in to change notification settings - Fork 5
新構文使用例
- 三項演算子
- 代入演算子
- 複合代入演算子
- 無名関数
- 高階関数
- クロージャ
- ビルトイン関数のエイリアス
- 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 // 2
0.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 = "これは未定義エラーになる"
fend
0.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
fend
0.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) // 5
struct-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 引数名: 型名
- デフォルト値
引数名: 型名 = デフォルト値
- 文字列
-
string
function f(s: string) fend f("展開可能文字列") f('文字列')
-
- 数値
-
number
function f(n: number) fend f(123) f($FF)
-
- 真偽値 (TRUE/FALSE)
-
bool
function f(b: bool) fend f(TRUE) f(FALSE)
-
- 配列
-
array
function f(a: array) fend f([1,2,3]) arr[] = 4,5,6 f(arr)
-
- 連想配列
-
hash
function f(h: hash) fend hashtbl h h[1] = 1 f(h)
-
- 関数 (ユーザー定義関数, 無名関数)
-
func
function f1(f: func) fend function f2() fend f3 = function() fend f1(f2) f1(f3) f1(|=>1|)
-
- UObject
-
uobject
function 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
endhash
web上のスクリプトを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