// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of The BSD 3-Clause License
// that can be found in the LICENSE file.

package uritemplate

import (
	
	
)

type progOpcode uint16

const (
	// match
	opRune progOpcode = iota
	opRuneClass
	opLineBegin
	opLineEnd
	// capture
	opCapStart
	opCapEnd
	// stack
	opSplit
	opJmp
	opJmpIfNotDefined
	opJmpIfNotEmpty
	opJmpIfNotFirst
	// result
	opEnd
	// fake
	opNoop
	opcodeMax
)

var opcodeNames = []string{
	// match
	"opRune",
	"opRuneClass",
	"opLineBegin",
	"opLineEnd",
	// capture
	"opCapStart",
	"opCapEnd",
	// stack
	"opSplit",
	"opJmp",
	"opJmpIfNotDefined",
	"opJmpIfNotEmpty",
	"opJmpIfNotFirst",
	// result
	"opEnd",
}

func ( progOpcode) () string {
	if  >= opcodeMax {
		return ""
	}
	return opcodeNames[]
}

type progOp struct {
	code progOpcode
	r    rune
	rc   runeClass
	i    uint32

	name string
}

func dumpProgOp( *bytes.Buffer,  *progOp) {
	.WriteString(.code.String())
	switch .code {
	case opRune:
		.WriteString("(")
		.WriteString(strconv.QuoteToASCII(string(.r)))
		.WriteString(")")
	case opRuneClass:
		.WriteString("(")
		.WriteString(.rc.String())
		.WriteString(")")
	case opCapStart, opCapEnd:
		.WriteString("(")
		.WriteString(strconv.QuoteToASCII(.name))
		.WriteString(")")
	case opSplit:
		.WriteString(" -> ")
		.WriteString(strconv.FormatInt(int64(.i), 10))
	case opJmp, opJmpIfNotFirst:
		.WriteString(" -> ")
		.WriteString(strconv.FormatInt(int64(.i), 10))
	case opJmpIfNotDefined, opJmpIfNotEmpty:
		.WriteString("(")
		.WriteString(strconv.QuoteToASCII(.name))
		.WriteString(")")
		.WriteString(" -> ")
		.WriteString(strconv.FormatInt(int64(.i), 10))
	}
}

type prog struct {
	op     []progOp
	numCap int
}

func dumpProg( *bytes.Buffer,  *prog,  uint32) {
	for  := range .op {
		 := .op[]

		 := strconv.Itoa()
		if uint32() ==  {
			 = "*" + 
		}
		.WriteString("    "[len():])
		.WriteString()

		.WriteByte('\t')
		dumpProgOp(, &)

		.WriteByte('\n')
	}
}

func ( *prog) () string {
	 := bytes.Buffer{}
	dumpProg(&, , 0)
	return .String()
}