gen::add_generator "Python 2.x" gen_py::generate
gen::add_generator "Python 3.x" gen_py::generate3

namespace eval gen_py {

variable g_callbacks

variable keywords {
and       del       from      not       while
as        elif      global    or        with
assert    else      if        pass      yield
break     except    import    print
class     exec      in        raise
continue  finally   is        return 
def       for       lambda    try
True      False
}

# Autogenerated with DRAKON Editor 1.31

proc assign { variable value } {
    #item 572
    return "$variable = $value"
}

proc bad_case { switch_var select_icon_number } {
    #item 676
    if {[ string compare -nocase $switch_var "select" ] == 0} {
        #item 682
        return "raise Exception\(\"Condition was not detected.\"\)"
    } else {
        #item 681
        return "raise Exception\(\"Not expected:  \" + str\($switch_var\)\)"
    }
}

proc block_close { output depth } {
    
}

proc build_handler { gdb name states message params_str params machine } {
    #item 937
    set in "    "
    set in2 "        "
    #item 928
    set lines {}
    #item 952
    lappend lines \
     "${in}def $message\($params_str\):"
    #item 929
    lappend lines \
    "${in2}_state_ = self.state"
    #item 935
    set keyword "if"
    foreach state $states {
        #item 954
        set method "${state}_${message}"
        #item 932
        if {[sma::is_in_handlers $machine $method]} {
            #item 945
            lappend lines \
            "${in2}$keyword _state_ == \"$state\":"
            #item 943
            lappend lines \
            "${in2}    return self.${method}($params\)"
            #item 946
            set keyword "elif"
        } else {
            #item 955
            set method "${state}_default"
            #item 957
            if {[sma::is_in_handlers $machine $method]} {
                #item 945
                lappend lines \
                "${in2}$keyword _state_ == \"$state\":"
                #item 943
                lappend lines \
                "${in2}    return self.${method}($params\)"
                #item 946
                set keyword "elif"
            } else {
                
            }
        }
    }
    #item 936
    lappend lines "${in2}return None"
    #item 947
    lappend lines ""
    #item 951
    return $lines
}

proc change_state { next_state machine_name returns } {
    #item 806
    if {$next_state == ""} {
        #item 810
        set change "self.state = None"
    } else {
        #item 809
        set change "self.state = \"${next_state}\""
    }
    #item 811
    if {$returns == ""} {
        #item 814
        return $change
    } else {
        #item 816
        set output [ lindex $returns 1 ]
        #item 815
        return "$change\n$output"
    }
}

proc commentator { line } {
    #item 45
    return "#$line"
}

proc compare { variable constant } {
    #item 581
    return "$variable == $constant"
}

proc else_start { } {
    #item 582
    return "else:"
}

proc elseif_start { } {
    #item 583
    return "elif "
}

proc extract_signature { text name } {
    #item 150
    set lines [ gen::separate_from_comments $text ]
    #item 152
    if {[ llength $lines ] == 0} {
        #item 404
        return [ list {} \
            [ gen::create_signature procedure public {} "" ] ]
    } else {
        #item 151
        set first_line [ lindex $lines 0 ]
        set first [ lindex $first_line 0 ]
        #item 1560001
        if {$first == "#method"} {
            #item 168
            set type method
            set start 1
            #item 175
            set parameters {}
            set count [ llength $lines ]
            #item 1780001
            set i $start
            while { 1 } {
                #item 1780002
                if {$i < $count} {
                    
                } else {
                    break
                }
                #item 177
                set current [ lindex $lines $i ]
                set left [ lindex $current 0 ]
                #item 917
                if {$left == "private"} {
                    
                } else {
                    #item 920
                    if {$left == "state machine"} {
                        #item 922
                        lappend parameters "self"
                    } else {
                        #item 916
                        lappend parameters $current
                    }
                }
                #item 1780003
                incr i
            }
            #item 179
            return [ list {} \
                [ gen::create_signature $type public $parameters "" ] ]
        } else {
            #item 1560002
            if {$first == "#comment"} {
                #item 171
                return [ list {} \
                    [ gen::create_signature "comment" {} {} {} ]]
            } else {
                #item 169
                set type procedure
                set start 0
                #item 175
                set parameters {}
                set count [ llength $lines ]
                #item 1780001
                set i $start
                while { 1 } {
                    #item 1780002
                    if {$i < $count} {
                        
                    } else {
                        break
                    }
                    #item 177
                    set current [ lindex $lines $i ]
                    set left [ lindex $current 0 ]
                    #item 917
                    if {$left == "private"} {
                        
                    } else {
                        #item 920
                        if {$left == "state machine"} {
                            #item 922
                            lappend parameters "self"
                        } else {
                            #item 916
                            lappend parameters $current
                        }
                    }
                    #item 1780003
                    incr i
                }
                #item 179
                return [ list {} \
                    [ gen::create_signature $type public $parameters "" ] ]
            }
        }
    }
}

proc foreach_check { item_id first second } {
    #item 26
    set go_var "_go$item_id"
    
    return $go_var
}

proc foreach_current { item_id first second } {
    #item 38
    return ""
}

proc foreach_declare { item_id first second } {
    #item 664
    return ""
}

proc foreach_incr { item_id first second } {
    #item 32
    set iter_var "_it$item_id"
    set go_var "_go$item_id"
    
    set lines [ list \
    "try:" \
    "    $first = $iter_var.next\(\)" \
    "    $go_var = True" \
    "except StopIteration:" \
    "    $go_var = False" ]
    
    return [ join $lines "\n" ]
}

proc foreach_incr3 { item_id first second } {
    #item 387
    set iter_var "_it$item_id"
    set go_var "_go$item_id"
    
    set lines [ list \
    "try:" \
    "    $first = next\($iter_var\)" \
    "    $go_var = True" \
    "except StopIteration:" \
    "    $go_var = False" ]
    
    return [ join $lines "\n" ]
}

proc foreach_init { item_id first second } {
    #item 19
    set iter_var "_it$item_id"
    set go_var "_go$item_id"
    
    set lines [ list \
    "$iter_var = iter\($second\)" \
    "try:" \
    "    $first = $iter_var.next\(\)" \
    "    $go_var = True" \
    "except StopIteration:" \
    "    $go_var = False" ]
    
    return [ join $lines "\n" ]
}

proc foreach_init3 { item_id first second } {
    #item 381
    set iter_var "_it$item_id"
    set go_var "_go$item_id"
    
    set lines [ list \
    "$iter_var = iter\($second\)" \
    "try:" \
    "    $first = next\($iter_var\)" \
    "    $go_var = True" \
    "except StopIteration:" \
    "    $go_var = False" ]
    
    return [ join $lines "\n" ]
}

proc generate { db gdb filename } {
    #item 388
    p.generate $db $gdb $filename 2
}

proc generate3 { db gdb filename } {
    #item 394
    p.generate $db $gdb $filename 3
}

proc generate_body { gdb diagram_id start_item node_list items incoming } {
    #item 590
    variable g_callbacks
    #item 591
    return [ cbody::generate_body $gdb $diagram_id $start_item $node_list \
    $items $incoming $g_callbacks ]
}

proc highlight { tokens } {
    #item 698
    set result {}
    #item 699
    set state "idle"
    #item 739
    variable keywords
    foreach token $tokens {
        #item 787
        lassign $token type text
        #item 7000001
        if {$state == "idle"} {
            #item 7150001
            if {$text == "\""} {
                #item 740
                lappend result \
                  $colors::syntax_string
                #item 722
                set state "string"
            } else {
                #item 7150002
                if {$text == "'"} {
                    #item 741
                    lappend result \
                      $colors::syntax_string
                    #item 724
                    set state "atom"
                } else {
                    #item 7150003
                    if {$text == "#"} {
                        #item 781
                        lappend result \
                          $colors::syntax_comment
                        #item 780
                        set state "comment"
                    } else {
                        #item 7250001
                        if {$type == "op"} {
                            #item 733
                            lappend result \
                              $colors::syntax_operator
                        } else {
                            #item 7250002
                            if {$type == "number"} {
                                #item 732
                                lappend result \
                                  $colors::syntax_number
                            } else {
                                #item 7250003
                                if {($type == "token") && ([contains $keywords $text])} {
                                    #item 737
                                    lappend result \
                                      $colors::syntax_keyword
                                } else {
                                    #item 734
                                    lappend result \
                                      $colors::syntax_identifier
                                }
                            }
                        }
                    }
                }
            }
        } else {
            #item 7000002
            if {$state == "string"} {
                #item 7420001
                if {$text == "\""} {
                    #item 749
                    lappend result \
                      $colors::syntax_string
                    #item 750
                    set state "idle"
                } else {
                    #item 7420002
                    if {$text == "\\"} {
                        #item 788
                        lappend result \
                          $colors::syntax_string
                        #item 751
                        set state "escaping"
                    } else {
                        #item 7420003
                        if {$text == "\n"} {
                            #item 789
                            lappend result \
                              $colors::syntax_string
                            #item 754
                            set state "idle"
                        } else {
                            #item 7420004
                            if {$text == "~"} {
                                #item 793
                                lappend result \
                                  $colors::syntax_operator
                            } else {
                                #item 790
                                lappend result \
                                  $colors::syntax_string
                            }
                        }
                    }
                }
            } else {
                #item 7000003
                if {$state == "escaping"} {
                    #item 756
                    lappend result $colors::syntax_string
                    #item 772
                    if {$text == "\n"} {
                        #item 774
                        set state "idle"
                    } else {
                        #item 755
                        set state "string"
                    }
                } else {
                    #item 7000004
                    if {$state == "atom"} {
                        #item 764
                        lappend result $colors::syntax_string
                        #item 7570001
                        if {$text == "'"} {
                            #item 765
                            set state "idle"
                        } else {
                            #item 7570002
                            if {$text == "\\"} {
                                #item 766
                                set state "atom escaping"
                            } else {
                                #item 7570003
                                if {$text == "\n"} {
                                    #item 769
                                    set state "idle"
                                } else {
                                    
                                }
                            }
                        }
                    } else {
                        #item 7000005
                        if {$state == "atom escaping"} {
                            #item 771
                            lappend result \
                             $colors::syntax_string
                            #item 775
                            if {$text == "\n"} {
                                #item 777
                                set state "idle"
                            } else {
                                #item 770
                                set state "atom"
                            }
                        } else {
                            #item 7000006
                            if {$state == "comment"} {
                                
                            } else {
                                #item 7000007
                                error "Unexpected switch value: $state"
                            }
                            #item 782
                            lappend result \
                              $colors::syntax_comment
                            #item 783
                            if {$text == "\n"} {
                                #item 785
                                set state "idle"
                            } else {
                                
                            }
                        }
                    }
                }
            }
        }
    }
    #item 697
    return $result
}

proc if_end { } {
    #item 584
    return ":"
}

proc if_start { } {
    #item 585
    return "if "
}

proc make_callbacks { version } {
    #item 641
    set callbacks {}
    
    gen::put_callback callbacks assign			gen_py::assign
    gen::put_callback callbacks compare			gen_py::compare
    gen::put_callback callbacks compare2		gen_py::compare
    gen::put_callback callbacks while_start 	gen_py::while_start
    gen::put_callback callbacks if_start		gen_py::if_start
    gen::put_callback callbacks elseif_start	gen_py::elseif_start
    gen::put_callback callbacks if_end			gen_py::if_end
    gen::put_callback callbacks else_start		gen_py::else_start
    gen::put_callback callbacks pass			gen_py::pass
    gen::put_callback callbacks continue		gen_py::p.continue
    gen::put_callback callbacks return_none		gen_py::return_none
    gen::put_callback callbacks block_close		gen_py::block_close
    gen::put_callback callbacks comment			gen_py::commentator
    gen::put_callback callbacks bad_case		gen_py::bad_case	
    gen::put_callback callbacks for_check		gen_py::foreach_check
    gen::put_callback callbacks for_current		gen_py::foreach_current	
    gen::put_callback callbacks body			gen_py::generate_body
    gen::put_callback callbacks signature		gen_py::extract_signature
    gen::put_callback callbacks and				gen_py::p.and
    gen::put_callback callbacks or				gen_py::p.or
    gen::put_callback callbacks not				gen_py::p.not
    gen::put_callback callbacks break			"break"
    gen::put_callback callbacks declare		gen_py::p.declare
    gen::put_callback callbacks for_declare gen_py::foreach_declare
    gen::put_callback callbacks shelf gen_py::shelf
    gen::put_callback callbacks native_foreach gen_py::native_foreach
    #item 800
    gen::put_callback callbacks change_state 	gen_py::change_state
    gen::put_callback callbacks shutdown ""
    gen::put_callback callbacks fsm_merge   0
    #item 6420001
    if {$version == 2} {
        #item 648
        gen::put_callback callbacks for_init		gen_py::foreach_init
        gen::put_callback callbacks for_incr		gen_py::foreach_incr
    } else {
        #item 6420002
        if {$version == 3} {
            
        } else {
            #item 6420003
            error "Unexpected switch value: $version"
        }
        #item 649
        gen::put_callback callbacks for_init		gen_py::foreach_init3
        gen::put_callback callbacks for_incr		gen_py::foreach_incr3
    }
    #item 650
    return $callbacks
}

proc native_foreach { for_it for_var } {
    #item 799
    return "for $for_it in $for_var:"
}

proc p.and { left right } {
    #item 621
    return "($left) and ($right)"
}

proc p.build_declaration { name signature } {
    #item 103
    lassign $signature type access parameters returns
    set param_names {}
    foreach parameter $parameters {
        #item 104
        set pname [ lindex $parameter 0 ]
        lappend param_names $pname
    }
    #item 107
    set param_string [ join $param_names ", " ]
    return "def $name\($param_string\):"
}

proc p.continue { } {
    #item 586
    return "continue"
}

proc p.declare { type name value } {
    #item 656
    return ""
}

proc p.generate { db gdb filename pversion } {
    #item 651
    variable g_callbacks
    #item 337
    set g_callbacks [ make_callbacks $pversion ]
    #item 818
    set machines [ sma::extract_many_machines \
     $gdb $g_callbacks ]
    #item 349
    gen::fix_graph $gdb $g_callbacks 0
    lassign [ gen::scan_file_description $db { header footer class } ] header footer class
    set functions [ gen::generate_functions $db $gdb $g_callbacks 1 ]
    #item 338
    if {[ graph::errors_occured ]} {
        
    } else {
        #item 823
        set machines [ sma::add_handlers $gdb $machines \
         $functions ]
        #item 358
        set procedures {}
        set methods {}
        foreach function $functions {
            #item 362
            set signature [ lindex $function 2 ]
            set type [ lindex $signature 0 ]
            #item 5920001
            if {$type == "procedure"} {
                #item 826
                if {[sma::is_machine_proc $gdb $function]} {
                    
                } else {
                    #item 363
                    lappend procedures $function
                }
            } else {
                #item 5920002
                if {$type == "comment"} {
                    
                } else {
                    #item 5920003
                    if {$type == "method"} {
                        
                    } else {
                        #item 5920004
                        error "Unexpected switch value: $type"
                    }
                    #item 365
                    if {$class == ""} {
                        #item 368
                        set name [ lindex $function 1 ]
                        set lines [ list "The file does not have a class. " \
                        "Nowhere to put method '$name'." ]
                        error [ join $lines "" ]
                        break
                    } else {
                        
                    }
                    #item 364
                    lappend methods $function
                }
            }
        }
        #item 339
        set hfile [ replace_extension $filename "py" ]
        set fhandle [ open_output_file $hfile ]
        catch {
        	p.print_to_file $gdb $fhandle $procedures \
                             $class $methods  \
        		     $header $footer  \
                             $machines
        } error_message
        
        catch { close $fhandle }
        #item 340
        if {$error_message == ""} {
            
        } else {
            #item 341
            error $error_message
        }
    }
}

proc p.not { operand } {
    #item 633
    return "not ($operand)"
}

proc p.or { left right } {
    #item 652
    return "($left) or ($right)"
}

proc p.print_proc { fhandle procedure depth } {
    #item 97
    lassign $procedure diagram_id name signature body
    #item 66
    set declaration [ p.build_declaration $name $signature ]
    set indent [ gen::make_indent $depth ]
    #item 67
    set body_depth [ expr { $depth + 1 } ]
    set lines [ gen::indent $body $body_depth ]
    #item 598
    if {$lines == ""} {
        #item 600
        set lines "$indent    pass"
    } else {
        
    }
    #item 96
    puts $fhandle ""
    puts $fhandle "$indent$declaration"
    puts $fhandle $lines
    puts $fhandle ""
}

proc p.print_to_file { gdb fhandle procs class methods header footer machines } {
    #item 401
    if {$header == ""} {
        
    } else {
        #item 68
        puts $fhandle $header
    }
    #item 400
    set version [ version_string ]
    puts $fhandle \
        "# Autogenerated with DRAKON Editor $version"
    foreach procedure $procs {
        #item 72
        p.print_proc $fhandle $procedure 0
    }
    #item 906
    print_machines $gdb $fhandle $machines
    #item 69
    if {$class == ""} {
        
    } else {
        #item 77
        puts $fhandle $class
        #item 80
        if {[ llength $methods ] == 0} {
            #item 615
            if {[ line_count $class ] < 2} {
                #item 81
                puts $fhandle "    pass"
            } else {
                
            }
        } else {
            foreach procedure $methods {
                #item 75
                p.print_proc $fhandle $procedure 1
            }
        }
    }
    #item 76
    puts $fhandle $footer
}

proc pass { } {
    #item 587
    return "pass"
}

proc print_machine { gdb fhandle machine } {
    #item 838
    if {$machine == {}} {
        
    } else {
        #item 841
        set parameters [ dict get $machine "parameters" ]
        set param_names [ dict get $machine "param_names" ]
        set last [ dict get $machine "last" ]
        set boiler [ dict get $machine "boiler" ]
        set messages [ dict get $machine "messages" ]
        set states [ dict get $machine "states" ]
        set name [ dict get $machine "name" ]
        set handlers [ dict get $machine "handlers" ]
        set comments [ dict get $machine "comments" ]
        #item 844
        puts $fhandle ""
        puts $fhandle "class $name:"
        #item 865
        set real_params [ lrange $parameters 1 end ]
        set wself [ concat "self" $real_params ]
        set params [ join $real_params ", " ]
        set wparams [ join $wself ", " ]
        #item 857
        set first [ lindex $states 0 ]
        #item 856
        puts $fhandle "    def __init__\(self\):"
        puts $fhandle "        self.state = \"$first\""
        #item 889
        puts $fhandle ""
        foreach message $messages {
            #item 949
            set hlines \
            [build_handler \
            	$gdb \
            	$name \
            	$states \
            	$message \
            	$wparams $params $machine]
            #item 950
            puts $fhandle [ join $hlines "\n" ]
        }
    }
    foreach procedure $handlers {
        #item 874
        lassign $procedure _ proc_name
        #item 873
        p.print_proc $fhandle $procedure 1
    }
    #item 845
    puts $fhandle ""
}

proc print_machines { gdb fhandle machines } {
    foreach machine $machines {
        #item 905
        print_machine $gdb $fhandle $machine
    }
}

proc return_none { } {
    #item 588
    return "return None"
}

proc shelf { primary secondary } {
    #item 670
    return "$secondary = $primary"
}

proc while_start { } {
    #item 589
    return "while True:"
}

}
