<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">

  <Type Name="lua_TValue">
    <DisplayString Condition="tt == lua_Type::LUA_TNIL">nil</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TBOOLEAN">{(bool)value.b}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TLIGHTUSERDATA">lightuserdata {(uintptr_t)value.p,h} tag: {extra[0]}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TNUMBER">number = {value.n}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TVECTOR">vector = {value.v[0]}, {value.v[1]}, {*(float*)&amp;extra}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TSTRING">{value.gc->ts}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TTABLE">{value.gc->h}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TFUNCTION">function {value.gc->cl,view(short)}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TUSERDATA">userdata {value.gc->u}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TTHREAD">thread {value.gc->th}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TBUFFER">buffer {value.gc->buf} size={value.gc->buf.len}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TPROTO">proto {value.gc->p}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TUPVAL">upvalue {value.gc->uv}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TDEADKEY">deadkey</DisplayString>
    <DisplayString>empty</DisplayString>
    <Expand>
      <Item Name="[lightuserdata]" Condition="tt == lua_Type::LUA_TLIGHTUSERDATA">value.p</Item>
      <Item Name="[string]" Condition="tt == lua_Type::LUA_TSTRING">value.gc->ts</Item>
      <Item Name="[table]" Condition="tt == lua_Type::LUA_TTABLE">value.gc->h</Item>
      <Item Name="[C function]" Condition="tt == lua_Type::LUA_TFUNCTION &amp;&amp; value.gc-&gt;cl.isC">value.gc->cl</Item>
      <Item Name="[Lua function]" Condition="tt == lua_Type::LUA_TFUNCTION &amp;&amp; !value.gc-&gt;cl.isC">value.gc->cl</Item>
      <Item Name="[userdata]" Condition="tt == lua_Type::LUA_TUSERDATA">value.gc->u</Item>
      <Item Name="[thread]" Condition="tt == lua_Type::LUA_TTHREAD">value.gc->th</Item>
      <Item Name="[buffer]" Condition="tt == lua_Type::LUA_TBUFFER">value.gc->buf</Item>
      <Item Name="[proto]" Condition="tt == lua_Type::LUA_TPROTO">value.gc->p</Item>
      <Item Name="[upvalue]" Condition="tt == lua_Type::LUA_TUPVAL">value.gc->uv</Item>
      <Item Name="[tag]" Condition="tt == lua_Type::LUA_TLIGHTUSERDATA">extra[0]</Item>
      <Synthetic Name="[gc]" Condition="tt >= lua_Type::LUA_TSTRING">
        <DisplayString Condition="value.gc-&gt;gch.marked &amp; 8">fixed ({(int)value.gc-&gt;gch.marked})</DisplayString>
        <DisplayString Condition="value.gc-&gt;gch.marked &amp; 4">black ({(int)value.gc-&gt;gch.marked})</DisplayString>
        <DisplayString Condition="value.gc-&gt;gch.marked &amp; 1">white ({(int)value.gc-&gt;gch.marked})</DisplayString>
        <DisplayString Condition="value.gc-&gt;gch.marked &amp; 2">white ({(int)value.gc-&gt;gch.marked})</DisplayString>
        <DisplayString Condition="(value.gc-&gt;gch.marked &amp; 3) == 0">gray ({(int)value.gc-&gt;gch.marked})</DisplayString>
      </Synthetic>
    </Expand>
  </Type>

  <Type Name="TKey">
    <DisplayString Condition="tt == lua_Type::LUA_TNIL">nil</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TBOOLEAN">{(bool)value.b}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TLIGHTUSERDATA">lightuserdata {(uintptr_t)value.p,h} tag: {extra[0]}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TNUMBER">number = {value.n}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TVECTOR">vector = {value.v[0]}, {value.v[1]}, {*(float*)&amp;extra}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TSTRING">{value.gc->ts}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TTABLE">{value.gc->h}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TFUNCTION">function {value.gc->cl,view(short)}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TUSERDATA">userdata {value.gc->u}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TTHREAD">thread {value.gc->th}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TBUFFER">buffer {value.gc->buf} size={value.gc->buf.len}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TPROTO">proto {value.gc->p}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TUPVAL">upvalue {value.gc->uv}</DisplayString>
    <DisplayString Condition="tt == lua_Type::LUA_TDEADKEY">deadkey</DisplayString>
    <DisplayString>empty</DisplayString>
    <Expand>
      <Item Name="[lightuserdata]" Condition="tt == lua_Type::LUA_TLIGHTUSERDATA">(void**)value.p</Item>
      <Item Name="[string]" Condition="tt == lua_Type::LUA_TSTRING">value.gc->ts</Item>
      <Item Name="[table]" Condition="tt == lua_Type::LUA_TTABLE">value.gc->h</Item>
      <Item Name="[C function]" Condition="tt == lua_Type::LUA_TFUNCTION &amp;&amp; value.gc-&gt;cl.isC">value.gc->cl</Item>
      <Item Name="[Lua function]" Condition="tt == lua_Type::LUA_TFUNCTION &amp;&amp; !value.gc-&gt;cl.isC">value.gc->cl</Item>
      <Item Name="[userdata]" Condition="tt == lua_Type::LUA_TUSERDATA">value.gc->u</Item>
      <Item Name="[thread]" Condition="tt == lua_Type::LUA_TTHREAD">value.gc->th</Item>
      <Item Name="[buffer]" Condition="tt == lua_Type::LUA_TBUFFER">value.gc->buf</Item>
      <Item Name="[proto]" Condition="tt == lua_Type::LUA_TPROTO">value.gc->p</Item>
      <Item Name="[upvalue]" Condition="tt == lua_Type::LUA_TUPVAL">value.gc->uv</Item>

      <Item Name="[tag]" Condition="tt == lua_Type::LUA_TLIGHTUSERDATA">extra[0]</Item>
      <Item Name="[next]">next</Item>
    </Expand>
  </Type>

  <Type Name="LuaNode">
    <DisplayString Condition="key.tt != lua_Type::LUA_TNIL || val.tt != lua_Type::LUA_TNIL">{key,na} = {val}</DisplayString>
    <DisplayString Condition="key.tt == lua_Type::LUA_TNIL &amp;&amp; val.tt == 0">---</DisplayString>
  </Type>

  <Type Name="LuaTable">
    <DisplayString>table</DisplayString>
    <Expand>
      <Item Name="metatable" Condition="metatable">metatable</Item>

      <Synthetic Name="hash">
        <DisplayString>[size] {1&lt;&lt;lsizenode}</DisplayString>
        <Expand>
          <IndexListItems>
            <Size>1&lt;&lt;lsizenode</Size>
            <ValueNode>node[$i]</ValueNode>
          </IndexListItems>
        </Expand>
      </Synthetic>
      <Synthetic Name="array">
        <DisplayString>[size] {sizearray}</DisplayString>
        <Expand>
          <IndexListItems>
            <Size>sizearray</Size>
            <ValueNode>array[$i]</ValueNode>
          </IndexListItems>
        </Expand>
      </Synthetic>
    </Expand>
  </Type>

  <Type Name="Udata">
    <Expand>
      <CustomListItems>
        <Variable Name="count" InitialValue="1&lt;&lt;metatable->lsizenode" />
        <Variable Name="i" InitialValue="0" />

        <Size>1</Size>
        <Loop>
          <Break Condition="i &gt;= count" />
          <If Condition="metatable->node[i].key.tt == lua_Type::LUA_TSTRING">
            <If Condition="strcmp(metatable-&gt;node[i].key.value.gc->ts.data, &quot;__type&quot;) == 0">
              <Item Name="[type]">metatable-&gt;node[i].val</Item>
            <Break/>
            </If>
          </If>
          <Exec>i = i + 1</Exec>
        </Loop>
        <If Condition="i == count">
          <Item Name="[type]">"unknown",sb</Item>
        </If>
      </CustomListItems>
      <Item Name="tag">tag</Item>
      <Item Name="len">len</Item>
      <Item Name="metatable">metatable</Item>
      <Item Name="data">data</Item>
    </Expand>
  </Type>

  <Type Name="Closure">
    <DisplayString Condition="isC == 1" IncludeView="short">{c.f,na}</DisplayString>
    <DisplayString Condition="isC == 0" IncludeView="short">{l.p,na}</DisplayString>
    <DisplayString Condition="isC == 1" ExcludeView="short">{c}</DisplayString>
    <DisplayString Condition="isC == 0" ExcludeView="short">{l}</DisplayString>
    <DisplayString>invalid</DisplayString>
  </Type>

  <Type Name="TString">
    <DisplayString>{data,s}</DisplayString>
  </Type>

  <Type Name="CallInfo">
    <Intrinsic Name="cl" Category="Property" Expression="func->value.gc->cl"/>
    <Intrinsic Name="isC" Category="Property" Expression="cl().isC"/>
    <Intrinsic Name="proto" Category="Property" Expression="cl().l.p"/>
    <Intrinsic Name="pcRel" Category="Property" Expression="savedpc ? savedpc - proto()->code - 1 : 0"/>
    <Intrinsic Name="line" Category="Property" Expression="proto()->abslineinfo[pcRel() >> proto()->linegaplog2] + proto()->lineinfo[pcRel()]"/>

    <!-- Special frames -->
    <DisplayString Condition="!func">empty</DisplayString>
    <DisplayString Condition="func->tt != lua_Type::LUA_TFUNCTION">none</DisplayString>

    <!-- Lua functions-->
    <DisplayString Condition="!isC() &amp;&amp; proto()->debugname">{proto()->source->data,sb}:{line()} function {proto()->debugname->data,sb}()</DisplayString>
    <DisplayString Condition="!isC()">{proto()->source->data,sb}:{line()} function()</DisplayString>

    <!-- C functions-->
    <DisplayString Condition="isC() &amp;&amp; cl().c.debugname">=[C] function {cl().c.debugname,sb}() {cl().c.f,na}</DisplayString>
    <DisplayString Condition="isC()">=[C] {cl().c.f,na}</DisplayString>
  </Type>

  <Type Name ="lua_State">
    <DisplayString Condition="ci">{ci,na}</DisplayString>
    <DisplayString>thread</DisplayString>
    <Expand>
      <Synthetic Name="[call stack]">
        <DisplayString>{ci-base_ci} frames</DisplayString>
        <Expand>
          <IndexListItems>
            <Size>ci-base_ci</Size>
            <!-- the +1 is omitted here to avoid some issues with a blank call -->
            <ValueNode>
              base_ci[ci-base_ci - $i]
            </ValueNode>
          </IndexListItems>
        </Expand>
      </Synthetic>
      <Synthetic Name="[top frame stack]">
        <DisplayString>{top-base} values</DisplayString>
        <Expand>
          <ArrayItems>
            <Size>top-base</Size>
            <ValuePointer>base</ValuePointer>
          </ArrayItems>
        </Expand>
      </Synthetic>
      <Synthetic Name="[stack]">
        <DisplayString>{top-stack} values</DisplayString>
        <Expand>
          <ArrayItems>
            <Size>top-stack</Size>
            <ValuePointer>stack</ValuePointer>
          </ArrayItems>
        </Expand>
      </Synthetic>
      <Synthetic Name="[open upvals]" Condition="openupval != 0">
        <Expand>
          <LinkedListItems>
            <HeadPointer>openupval</HeadPointer>
            <NextPointer>u.open.threadnext</NextPointer>
            <ValueNode>this</ValueNode>
          </LinkedListItems>
        </Expand>
      </Synthetic>
      <Item Name="globals">gt</Item>
      <Item Name="userdata">userdata</Item>
    </Expand>
  </Type>

  <Type Name="Proto">
    <DisplayString Condition="debugname">{source->data,sb}:{linedefined} function {debugname->data,sb} [{(int)numparams} arg, {(int)nups} upval]</DisplayString>
    <DisplayString Condition="!debugname">{source->data,sb}:{linedefined} [{(int)numparams} arg, {(int)nups} upval]</DisplayString>
    <Expand>
      <Item Name="debugname">debugname</Item>
      <Synthetic Name="[constants]">
        <DisplayString>constants</DisplayString>
        <Expand>
          <IndexListItems>
            <Size>sizek</Size>
            <ValueNode>k[$i]</ValueNode>
          </IndexListItems>
        </Expand>
      </Synthetic>
      <Synthetic Name="[locals]">
        <DisplayString>locals</DisplayString>
        <Expand>
          <IndexListItems>
            <Size>sizelocvars</Size>
            <ValueNode>locvars[$i]</ValueNode>
          </IndexListItems>
        </Expand>
      </Synthetic>
      <Synthetic Name="[bytecode]">
        <DisplayString>bytecode</DisplayString>
        <Expand>
          <IndexListItems>
            <Size>sizecode</Size>
            <ValueNode>code[$i]</ValueNode>
          </IndexListItems>
        </Expand>
      </Synthetic>
      <Synthetic Name="[functions]">
        <DisplayString>functions</DisplayString>
        <Expand>
          <IndexListItems>
            <Size>sizep</Size>
            <ValueNode>p[$i]</ValueNode>
          </IndexListItems>
        </Expand>
      </Synthetic>
      <Synthetic Name="[upvals]">
        <DisplayString>upvals</DisplayString>
        <Expand>
          <IndexListItems>
            <Size>sizeupvalues</Size>
            <ValueNode>upvalues[$i]</ValueNode>
          </IndexListItems>
        </Expand>
      </Synthetic>

      <Item Name="source">source</Item>
    </Expand>
  </Type>

  <Type Name="GCheader">
    <Expand>
      <Synthetic Name="[type]">
        <DisplayString>{(lua_Type)tt}</DisplayString>
      </Synthetic>
      <Synthetic Name="[gc]">
        <DisplayString Condition="marked &amp; 8">fixed ({(int)marked})</DisplayString>
        <DisplayString Condition="marked &amp; 4">black ({(int)marked})</DisplayString>
        <DisplayString Condition="marked &amp; 1">white ({(int)marked})</DisplayString>
        <DisplayString Condition="marked &amp; 2">white ({(int)marked})</DisplayString>
        <DisplayString Condition="(marked &amp; 3) == 0">gray ({(int)marked})</DisplayString>
        <DisplayString>unknown</DisplayString>
      </Synthetic>
      <Item Name="memcat">memcat</Item>
    </Expand>
  </Type>

</AutoVisualizer>
