新構文使用例 - stuncloud/UWSCR Wiki

目次

三項演算子

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("あいうえお", "い", "イ")

UObject

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 // なんでも書き込める

UObject <-> json 変換

json = ToJson(obj) // UObjectからjson文字列に変換
obj = FromJson(json) // json文字列からUObjectに変換

CLASS

0.1.3 より

UWSCのCLASSとは機能が異なります
UWSCのCLASSと同等の機能が必要な場合はMODULEを使ってください

CLASS定義

クラス名と同名のプロシージャ(コンストラクタ)を定義する必要があります
また_クラス名_()というプロシージャはデストラクタとなります
デストラクタは必須ではありません

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が破棄されました

Enum

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

タスク

任意の関数を非同期に実行する仕組みです

タスク利用の流れ

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() // 実行をブロックして関数の終了を待つ

真偽性の評価

以下では真偽性が評価されます

以下は偽(falsy)と判定されます

それ以外は真(truthy)です

if FALSE then
elseif
    print "FALSEが偽"
endif

print NOTHING ? '' : 'NOTHINGは偽'

while ""
    print "空文字列は偽なのでこの文字列はprintされません"
wend

repeat
    print "空でない文字列は真なのでこのループは一周で終了します"
until "ループを抜けます"

論理演算子・ビット演算子

AND、OR、XORは両辺により論理演算またはビット演算が行われていましたが
それとは別に以下が追加されました

// 論理演算子
// 両辺の真偽性を評価してから演算を行う
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

構造体定義

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]