Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

制御フロー

point/warpto文

WapLで最も基本となる制御フローはpoint/warpto文です。これは多くの言語でのgoto文に近い概念で非常に自由度の高い処理が書けます。pointでラベルをつけてブロックを作り、warptoでそこまでジャンプします。warpto

fn main():i32{
    warpto(skip);
    point skipped;
        println("この行は飛ばされるよ");
        warpto(skip);
    point skip;
    
    println("skipに飛んだよ");
    return 0s;
}
skipに飛んだよ

これではskippedskipというラベルでブロックを作り、warpto(skip)skipに飛びます。すべてのブロックがreturnwarpto/warptoifのどれかで終わる必要があります。

warptoif文

warptoifwarptoに条件を付けて真のときと偽のときで飛ぶ先を選択するものでwarptoif(条件, 真のとき, 偽のとき)となります。

fn main():i32{
    #=(cond, true, bool);
    warptoif(cond, then, else);
    point then;
        println("then");
        warpto(end);
    point else;
        println("else");
        warpto(end);
    point end;
    return 0s;
}

このようにして条件分岐を作ることもできますし、後述するloopifも内部ではpoint/warpto/warptoifと同じようなことがされています。

loopif文

loopifは他の多くの言語で存在するwhileのようなもので、名前を付けたりwarpto/warptoifにも対応しています。

fn main():i32{
    #=(i,0,i64);
    loopif:(<(i,10)){
        println(format("%d",i))
        =(i,+(i,1));
    }

    =(i,0)
    loopif:LOOP1(<(i,10)){
        println(format("LOOP1:%d",i))
        =(i,+(i,1));
        warptoif(<(i,5),continue-LOOP1,break-LOOP1);
    }

    return 0s
}
0
1
2
3
4
5
6
7
8
9
LOOP1:0
LOOP1:1
LOOP1:2
LOOP1:3
LOOP1:4

このようにloopifは名前ありでも名前なしでも作ることができ、ループを抜けたいときはbreak-名前に飛ぶことで抜けることができ、以下の処理をせずに条件の評価に戻りたいときはcontinue-名前に飛ぶことでできる。

if文(0.1.13以降)

多くの言語で見られるif文。言語によってはif文とif式は同じ文法で記述できるものもありますが、WapLでは異なるキーワードを使っています。

if文は以下のように使うことができます

fn main():i32{

    if (true){
        println("True");
    }
    if (false){
        println("False");
    }
    return 0s;
}
True

このようにifのあとの()の中にbool型で条件を書き、trueのときには{}の中の処理が実行されます。

elifとelse

if文で前の条件がfalseであるときにfalse側でも処理をしたいときに毎回ifで前の条件がfalseであるときを指定するのはめんどくさいです。そこで使えるのがelifelseです。

fn main():i32{
    #=(x, 7, i64);
    if (>(x, 10)){
        println(format("%lld > 10",x));
    }elif (>(x, 5)){
        println(format("5 < %lld <= 10",x));
    }else{
        println(format("%lld <= 5",x));
    }
    return 0s;
}
5 < 7 <= 10

このように前の条件がfalseであることを前提にして条件を書いたり、その他の場合を記述できます。

?演算子

これはif式に相当する演算子です。中には文は書けないのでもし文を書きたい場合は関数を作ってその関数を呼ぶようにしてください。

fn main():i32{
    #=(x, ?(false,10,5), i64);
    println(format("x = %lld", x));
    return 0s;
}
x = 5

このように第1引数に条件を書き、続けてtrueのときの値、falseのときの値を書きます。このとき値の型は一致していてさらにvoidであってはいけません。

fn Hello(){
    println("Hello");
}
fn Bye(){
    println("Bye");
}

fn main():i32{
    ?(true,Hello(),Bye());
    return 0s;
}
src/main.ll:56:1: error: expected instruction opcode
   56 | if.merge:                                         ; No predecessors!
      | ^
1 error generated.

このようにvoidの場合エラーが出ます。これを回避するためには以下のようにして意味がなくとも戻り値を持たせる必要があります。

fn Hello():i32{
    println("Hello");
    return 0s;
}
fn Bye():i32{
    println("Bye");
    return 0s;
}

fn main():i32{
    ?(true,Hello(),Bye());
    return 0s;
}
Hello

choose

?演算と似たようなものとしてchooseがあります。違いとしては?は片方しか評価しない一方chooseは両方を評価してから条件に合う値を返します。先ほどのHelloとByeの?chooseに書き変えて試してみましょう。

fn Hello():i32{
    println("Hello");
    return 0s;
}
fn Bye():i32{
    println("Bye");
    return 0s;
}

fn main():i32{
    choose(true,Hello(),Bye());
    return 0s;
}
Hello
Bye

このようにHello/Byeともに実行されたことが確認できます。