def p_if_end(p):
    '''
    if_end :
    '''
    label_index = codegen.pop_label_stack()
    l1          = Factor(Scope.LOCAL, val=f"if.end.{label_index}")
    
    codegen.push_code(llvmcodes.LLVMCodeBrUncond(l1))
    codegen.push_code(llvmcodes.LLVMCodeRegisterLabel(f"if.end.{label_index}"))
def p_while_init(p):
    '''
    while_init :
    '''
    label_index = codegen.label_index()
    l_init      = Factor(Scope.LOCAL, val=f"while.init.{label_index}")
    
    codegen.push_code(llvmcodes.LLVMCodeBrUncond(l_init))
    codegen.push_code(llvmcodes.LLVMCodeRegisterLabel(f"while.init.{label_index}"))
def p_for_end(p):
    '''
    for_end :
    '''
    # statement 終了後は強制的に for.condition に戻して n < range_to を評価する
    label_index = codegen.pop_label_stack()
    l_cond      = Factor(Scope.LOCAL, val=f"for.condition.{label_index}")
    
    codegen.push_code(llvmcodes.LLVMCodeBrUncond(l_cond))
    codegen.push_code(llvmcodes.LLVMCodeRegisterLabel(f"for.end.{label_index}"))
def p_for_init(p):
    '''
    for_init :
    '''

    # for n:= 2 to 100
    # ↓
    # for ident := range_from to range_to

    ident       = latest_id_name(p)
    range_to    = codegen.pop_factor()
    range_from  = codegen.pop_factor()
    var         = parse_variable(ident)
    label_index = codegen.label_index()

    # n := 2
    codegen.push_code(llvmcodes.LLVMCodeStore(range_from, var))
    # 初期化時は無条件で statement に移動
    l_body = Factor(Scope.LOCAL, val=f"for.body.{label_index}")
    codegen.push_code(llvmcodes.LLVMCodeBrUncond(l_body))
    # statement が終わったあとに戻ってくる for.condition のポイントを作成
    codegen.push_code(llvmcodes.LLVMCodeRegisterLabel(f"for.condition.{label_index}"))

    # n++ 
    ## n をレジスタに読み込み
    reg_ident = Factor(Scope.LOCAL, val=codegen.register())
    codegen.push_code(llvmcodes.LLVMCodeLoad(reg_ident, var))
    ## n + 1
    one = Factor(Scope.CONSTANT, val=1)
    reg_ident_increased = Factor(Scope.LOCAL, val=codegen.register())
    codegen.push_code(llvmcodes.LLVMCodeAdd(reg_ident, one, reg_ident_increased))
    ## レジスタの内容を n に戻す
    codegen.push_code(llvmcodes.LLVMCodeStore(reg_ident_increased, var))

    # n が range_from に到達したかのチェック
    ## n <= range_to
    cond = Factor(Scope.LOCAL, val=codegen.register())
    codegen.push_code(llvmcodes.LLVMCodeIcmp(llvmcodes.CmpType.SLE, reg_ident_increased, range_to, cond))
    l_end = Factor(Scope.LOCAL, val=f"for.end.{label_index}")
    
    codegen.push_code(llvmcodes.LLVMCodeBrCond(cond, l_body, l_end))
    codegen.push_code(llvmcodes.LLVMCodeRegisterLabel(f"for.body.{label_index}"))
def p_if_condition(p):
    '''
    if_condition :
    '''
    label_index = codegen.label_index()
    cond        = codegen.pop_factor()
    
    l1 = Factor(Scope.LOCAL, val=f"if.true.{label_index}")
    l2 = Factor(Scope.LOCAL, val=f"if.else.{label_index}")
    
    codegen.push_code(llvmcodes.LLVMCodeBrCond(cond, l1, l2))
    codegen.push_code(llvmcodes.LLVMCodeRegisterLabel(f"if.true.{label_index}"))
def p_while_condition(p):
    '''
    while_condition :
    '''
    label_index = codegen.pop_label_stack(keep=True)
    cond        = codegen.pop_factor()

    l1 = Factor(Scope.LOCAL, val=f"while.body.{label_index}")
    l2 = Factor(Scope.LOCAL, val=f"while.end.{label_index}")

    codegen.push_code(llvmcodes.LLVMCodeBrCond(cond, l1, l2))
    codegen.push_code(llvmcodes.LLVMCodeRegisterLabel(f"while.body.{label_index}"))