grammar JSON::PIR is TGE::Grammar;

transform result (ROOT) {
    .local pmc pir
    .local string result

    $S0 = tree.'get'('pir', node, 'value')

    pir = new 'StringBuilder'
    appendln(pir, '.sub anon :anon')
    appendln(pir, $S0)
    result = node['ret']
    $S0 = 'sprintf'('     .return (%Ss)', result)
    appendln(pir, $S0)
    appendln(pir, '.end')

   .return(pir)
}

transform pir (value) {

    .local pmc sub_node, transform_result
    .local pmc pir, result
    .local string value, type

    type = 'string'
    sub_node = node[type]
    unless null sub_node goto got_type

    type = 'number'
    sub_node = node[type]
    unless null sub_node goto got_type

    type = 'object'
    sub_node = node[type]
    unless null sub_node goto got_type

    type = 'array'
    sub_node = node[type]
    unless null sub_node goto got_type

    value = node
    if value == 'true'  goto got_true
    if value == 'false' goto got_false
    if value == 'null'  goto got_null

    .return ('') # should never reach this.

  got_type:
    pir = tree.'get'('pir', sub_node, type)
    $S0 = sub_node['ret']
    node['ret'] = $S0
    .return (pir)

  got_true:
    pir = new 'StringBuilder'
    result = unique_pmc_reg()
    $S0 = 'sprintf'("    %Ss = new 'Boolean', 1", result)
    appendln(pir, $S0)
    node['ret'] = result
    .return(pir)

  got_false:
    pir = new 'StringBuilder'
    result = unique_pmc_reg()
    $S0 = 'sprintf'("    %Ss = new 'Boolean', 0", result)
    appendln(pir, $S0)
    node['ret'] = result
    .return(pir)

  got_null:
    pir = new 'StringBuilder'
    result = unique_pmc_reg()
    $S0 = 'sprintf'('    null %Ss', result)
    appendln(pir, $S0)
    node['ret'] = result
    .return(pir)
}

transform pir (object) {
    .local pmc pir
    pir = new 'StringBuilder'
    .local string result, child_result, key_result
    result = unique_pmc_reg()
    $S0 = 'sprintf'("    %Ss = new 'Hash'", result)
    appendln(pir, $S0)

    .local pmc items

    items = node['members']
    if null items goto end

    items = items[0]

    .local pmc keys
    keys  = items['string']
    items = items['value']

    .local pmc it, key_iter, child, key
    key_iter = iter keys
    it       = iter items

    # the two iters should be in lockstep as a result of the PGE grammar
loop:
    unless it goto end
    child = shift it
    $P0 = tree.'get'('pir', child, 'value')
    $S0 = $P0
    push pir, $S0
    child_result = child['ret']

    key   = shift key_iter
    $P0 = tree.'get'('pir', key, 'string')
    $S0 = $P0
    push pir, $S0
    key_result = key['ret']

    $S0 = 'sprintf'('    %Ss[%Ss] = %Ss', result, key_result, child_result)
    appendln(pir, $S0)


    goto loop
end:
    node['ret'] = result

   .return (pir)
}

transform pir (array) {
    .local pmc pir
    pir = new 'StringBuilder'
    .local string result, child_result
    result = unique_pmc_reg()
    $S0 = 'sprintf'("    %Ss = new 'ResizablePMCArray'", result)
    appendln(pir, $S0)

    .local pmc items


    items = node['elements']
    if null items goto end

    items = items['value']

    .local pmc it, child
    it = iter items
loop:
    unless it goto end
    child = shift it
    $P0 = tree.'get'('pir', child, 'value')
    $S0 = $P0
    push pir, $S0

    child_result = child['ret']
    $S0 = 'sprintf'('    push %Ss, %Ss', result, child_result)
    appendln(pir, $S0)
    goto loop
end:
    node['ret'] = result

   .return (pir)
}

transform pir (string) {
    .local pmc pir, result, children, it, child
    .local string tmp
    tmp = ''
    pir = new 'StringBuilder'
    children = node['char']
    if null children goto loop_end
    it = iter children
  loop:
    push_eh loop_end
      child = shift it
    pop_eh
    unless child goto loop_end
    $S0 = child
    $I0 = length $S0
    if $I0 == 1 goto char
    if $I0 == 2 goto escape
  unicode:
    $P1 = new 'String'
    $S1 = substr $S0, 2, 4
    $P1 = $S1
    $I0 = $P1.'to_int'(16)
    $S0 = chr $I0
    goto char
  escape:
    $P0 = get_root_global ['parrot'; 'data_json'], '$escapes'
    $S0 = $P0[$S0]
  char:
    tmp .= $S0
    goto loop
  loop_end:

    result = unique_pmc_reg()
    $S0 = 'sprintf'("    %Ss = new 'String'", result)
    appendln(pir, $S0)
    $P0 = get_root_global ['parrot';'PGE';'Util'], 'pir_str_escape'
    tmp = $P0(tmp)
    $S0 = 'sprintf'('    %Ss = %Ss', result, tmp)
    appendln(pir, $S0)
    node['ret'] = result
   .return(pir)
}

transform pir (number) {
    .local pmc pir, result
    pir = new 'StringBuilder'
    result = unique_pmc_reg()
    $S0 = 'sprintf'("    %Ss = new 'Integer'", result)
    appendln(pir, $S0)
    $S0 = 'sprintf'('    %Ss = %Ss', result, node)
    appendln(pir, $S0)
    node['ret'] = result
   .return(pir)
}
