syntax = "proto3";

package python.ast;

option go_package = "github.com/kyleconroy/sqlc/internal/python/ast";

message Node {
  oneof node {
	ClassDef class_def = 1 [json_name="ClassDef"];
	Import import = 2 [json_name="Import"];
	ImportFrom import_from = 3 [json_name="ImportFrom"];
	Module module = 4 [json_name="Module"];
	Alias alias = 5 [json_name="Alias"];
	AnnAssign ann_assign = 6 [json_name="AnnAssign"];
	Name name = 7 [json_name="Name"];
    Subscript subscript = 8 [json_name="Subscript"];
    Attribute attribute = 9 [json_name="Attribute"];
    Constant constant = 10 [json_name="Constant"];
    Assign assign = 11 [json_name="Assign"];
    Comment comment = 12 [json_name="Comment"];
    Expr expr = 13 [json_name="Expr"];
    Call call = 14 [json_name="Call"];
    FunctionDef function_def = 15 [json_name="FunctionDef"];
    Arg arg = 16 [json_name="Arg"];
    Arguments arguments = 17 [json_name="Arguments"];
    AsyncFunctionDef async_function_def = 18 [json_name="AsyncFunctionDef"];
    Pass pass = 19 [json_name="Pass"];
    Dict dict = 20 [json_name="Dict"];
    If if = 21 [json_name="If"];
    Compare compare = 22 [json_name="Compare"];
    Return return = 23 [json_name="Return"];
    Is is = 24 [json_name="Is"];
    Keyword keyword = 25 [json_name="Keyword"];
    Yield yield = 26 [json_name="Yield"];
    For for = 27 [json_name="For"];
    Await await = 28 [json_name="Await"];
    AsyncFor async_for = 29 [json_name="AsyncFor"];
    ImportGroup import_group = 30 [json_name="ImportGroup"];
  }
}

message Alias
{
  string name = 1 [json_name="name"];
}

message Await
{
  Node value = 1 [json_name="value"];
}

message Attribute
{
  Node value = 1 [json_name="value"];
  string attr = 2 [json_name="attr"];
}

message AnnAssign
{
  Name target = 1 [json_name="target"];
  Node annotation = 2 [json_name="annotation"];
  int32 simple = 3 [json_name="simple"];
  string Comment = 4 [json_name="comment"];
}

message Arg
{
  string arg = 1 [json_name="arg"];
  Node annotation = 2 [json_name="annotation"];
}

message Arguments
{
  repeated Arg args = 1 [json_name="args"];
  repeated Arg kw_only_args = 2 [json_name="kwonlyargs"];
}

message AsyncFor
{
  Node target = 1 [json_name="target"];
  Node iter = 2 [json_name="iter"];
  repeated Node body = 3 [json_name="body"];
}

message AsyncFunctionDef
{
  string name = 1 [json_name="name"];
  Arguments Args = 2 [json_name="args"];
  repeated Node body = 3 [json_name="body"];
  Node returns = 4 [json_name="returns"];
}

message Assign
{
  repeated Node targets = 1 [json_name="targets"];
  Node value = 2 [json_name="value"];
  string Comment = 3 [json_name="comment"];
}

message Call
{
  Node func = 1 [json_name="func"];
  repeated Node args = 2 [json_name="args"];
  repeated Keyword keywords = 3 [json_name="keywords"];
}

message ClassDef
{
  string name = 1 [json_name="name"];
  repeated Node bases = 2 [json_name="bases"];
  repeated Node keywords = 3 [json_name="keywords"];
  repeated Node body = 4 [json_name="body"];
  repeated Node decorator_list = 5 [json_name="decorator_list"];
}

// The Python ast module does not parse comments. It's not clear if this is the
// best way to support them in the AST
message Comment
{
  string text = 1 [json_name="text"];
}

message Compare
{
  Node left = 1 [json_name="left"];
  repeated Node ops = 2 [json_name="ops"];
  repeated Node comparators = 3 [json_name="comparators"];
}

message Constant
{
  oneof value {
	string str = 1 [json_name="string"];
	int32 int = 2 [json_name="int"];
    bool none = 3 [json_name="none"];
  }
}

message Dict
{
  repeated Node keys = 1 [json_name="keys"];
  repeated Node values = 2 [json_name="values"];
}

message Expr
{
  Node value = 1 [json_name="value"];
}

message For
{
  Node target = 1 [json_name="target"];
  Node iter = 2 [json_name="iter"];
  repeated Node body = 3 [json_name="body"];
}

message FunctionDef
{
  string name = 1 [json_name="name"];
  Arguments Args = 2 [json_name="args"];
  repeated Node body = 3 [json_name="body"];
  Node returns = 4 [json_name="returns"];
}

message If
{
  Node test = 1 [json_name="test"];
  repeated Node body = 2 [json_name="body"];
  repeated Node or_else = 3 [json_name="orelse"];
}

message Import
{
  repeated Node names = 1 [json_name="names"];
}

message ImportFrom
{
  string module = 1 [json_name="module"];
  repeated Node names = 2 [json_name="names"];
  int32 level = 3 [json_name="level"];
}

// Imports are always put at the top of the file, just after any module
// comments and docstrings, and before module globals and constants.
// 
// Imports should be grouped in the following order:
// 
//     Standard library imports.
//     Related third party imports.
//     Local application/library specific imports.
// 
// You should put a blank line between each group of imports.
// 
// https://www.python.org/dev/peps/pep-0008/#imports
message ImportGroup
{
  repeated Node imports = 1 [json_name="imports"];
}

message Is
{
}

message Keyword
{
  string arg = 1 [json_name="arg"];
  Node value = 2 [json_name="value"];
}

message Module
{
  repeated Node body = 1 [json_name="body"];
}

message Name
{
  string id = 1 [json_name="id"];
}

message Pass
{
}

message Return
{
  Node value = 1 [json_name="value"];
}


message Subscript
{
  Name value = 1 [json_name="value"];
  Node slice = 2 [json_name="slice"];
}

message Yield
{
  Node value = 1 [json_name="value"];
}


