{{$clang_style := "{BasedOnStyle: Google, AccessModifierOffset: -4, ColumnLimit: 200, ContinuationIndentWidth: 8, IndentWidth: 4, AlignOperands: true, CommentPragmas: '.*'}"}}
{{Global "clang-format" (Strings "clang-format" "-style" $clang_style)}}


{{/*
-------------------------------------------------------------------------------
  Emits the C translation for the specified type.
-------------------------------------------------------------------------------
*/}}
{{define "Type.Class"      }}{{if GetAnnotation $.Type "internal"}}struct {{end}}{{Macro "StructName" $.Type}}{{end}}
{{define "Type.Pseudonym"  }}{{$.Type.Name}}{{end}}
{{define "Type.Enum"       }}{{$.Type.Name}}{{end}}
{{define "Type.StaticArray"}}{{Node "Type" $.Type.ValueType}}{{end}}
{{define "Type.Pointer"    }}{{if $.Type.Const}}{{Node "ConstType" $.Type.To}}{{else}}{{Node "Type" $.Type.To}}{{end}}*{{end}}
{{define "Type.Slice"      }}{{Log "%T %+v" $.Node $.Node}}{{Node "Type" $.Type.To}}*{{end}}
{{define "Type#bool"       }}bool{{end}}
{{define "Type#int"        }}int{{end}}
{{define "Type#uint"       }}unsigned int{{end}}
{{define "Type#s8"         }}int8_t{{end}}
{{define "Type#u8"         }}uint8_t{{end}}
{{define "Type#s16"        }}int16_t{{end}}
{{define "Type#u16"        }}uint16_t{{end}}
{{define "Type#s32"        }}int32_t{{end}}
{{define "Type#u32"        }}uint32_t{{end}}
{{define "Type#f32"        }}float{{end}}
{{define "Type#s64"        }}int64_t{{end}}
{{define "Type#u64"        }}uint64_t{{end}}
{{define "Type#f64"        }}double{{end}}
{{define "Type#void"       }}void{{end}}
{{define "Type#char"       }}char{{end}}

{{define "ConstType_Default"}}const {{Node "Type" $.Type}}{{end}}
{{define "ConstType.Pointer"}}{{Node "Type" $.Type}} const{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits the C translation for the specified documentation block (string array).
-------------------------------------------------------------------------------
*/}}
{{define "Docs"}}
  {{if $}}// {{$ | JoinWith "\n// "}}{{end}}
{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits the name of a bitfield entry.
-------------------------------------------------------------------------------
*/}}
{{define "BitfieldEntryName"}}
  {{AssertType $ "EnumEntry"}}

  {{Macro "EnumEntry" $}}
{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits the name of an enum type.
-------------------------------------------------------------------------------
*/}}
{{define "EnumName"}}{{AssertType $ "Enum"}}{{$.Name}}{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits the name of an enum entry.
-------------------------------------------------------------------------------
*/}}
{{define "EnumEntry"}}
  {{AssertType $.Owner "Enum"}}
  {{AssertType $.Name "string"}}

  {{$.Name}}
{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits the name of the first entry of an enum.
-------------------------------------------------------------------------------
*/}}
{{define "EnumFirstEntry"}}
  {{AssertType $ "Enum"}}

  {{range $i, $e := $.Entries}}
    {{if not $i}}{{$e.Name}}{{end}}
  {{end}}
{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits the name of the last entry of an enum.
-------------------------------------------------------------------------------
*/}}{{define "EnumLastEntry"}}
  {{AssertType $ "Enum"}}

  {{range $i, $e := $.Entries}}
    {{if not (HasMore $i $.Entries)}}{{$e.Name}}{{end}}
  {{end}}
{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits the name of a struct (class) type.
-------------------------------------------------------------------------------
*/}}
{{define "StructName"}}{{AssertType $ "Class"}}{{$.Name}}{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits the name of a function.
-------------------------------------------------------------------------------
*/}}
{{define "FunctionName"}}{{AssertType $ "Function"}}{{$.Name}}{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits the fixed-size-array postfix for pseudonym types annotated with @array
-------------------------------------------------------------------------------
*/}}
{{define "ArrayPostfix"}}{{Node "ArrayPostfix" $}}{{end}}
{{define "ArrayPostfix.StaticArray"}}[{{$.Type.Size}}]{{end}}
{{define "ArrayPostfix_Default"}}{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits a C type and name for the given parameter
-------------------------------------------------------------------------------
*/}}
{{define "Parameter"}}
  {{AssertType $ "Parameter"}}

  {{if GetAnnotation $ "readonly"}}const {{end}}{{Macro "ParameterType" $}} {{$.Name}}{{Macro "ArrayPostfix" $}}
{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits a C name for the given parameter
-------------------------------------------------------------------------------
*/}}
{{define "ParameterName"}}
  {{AssertType $ "Parameter"}}

  {{$.Name}}
{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits a C type for the given parameter
-------------------------------------------------------------------------------
*/}}
{{define "ParameterType"}}{{AssertType $ "Parameter"}}{{Node "Type" $}}{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits a comma-separated list of C type-name paired parameters for the given
  command.
-------------------------------------------------------------------------------
*/}}
{{define "Parameters"}}
  {{AssertType $ "Function"}}

  {{ForEach $.CallParameters "Parameter" | JoinWith ", "}}
  {{if not $.CallParameters}}void{{end}}
{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits the C function pointer name for the specified command.
-------------------------------------------------------------------------------
*/}}
{{define "FunctionPtrName"}}
  {{AssertType $ "Function"}}

  PFN_{{$.Name}}
{{end}}


{{/*
-------------------------------------------------------------------------------
  Parses const variables as text Globals.
-------------------------------------------------------------------------------
*/}}
{{define "DefineGlobals"}}
  {{AssertType $ "API"}}

  {{range $d := $.Definitions}}
    {{Global $d.Name $d.Expression}}
  {{end}}
{{end}}


{{/*
-------------------------------------------------------------------------------
  Given a function, return "Global", "Instance", or "Device" depending on which
  dispatch table the function belongs to.
-------------------------------------------------------------------------------
*/}}
{{define "Vtbl#VkInstance"      }}Instance{{end}}
{{define "Vtbl#VkPhysicalDevice"}}Instance{{end}}
{{define "Vtbl#VkDevice"        }}Device{{end}}
{{define "Vtbl#VkQueue"         }}Device{{end}}
{{define "Vtbl#VkCommandBuffer" }}Device{{end}}
{{define "Vtbl_Default"         }}Global{{end}}
{{define "Vtbl"}}
  {{AssertType $ "Function"}}

  {{if gt (len $.CallParameters) 0}}
    {{Node "Vtbl" (index $.CallParameters 0)}}
  {{else}}Global
  {{end}}
{{end}}