Initial commit
This commit is contained in:
commit
7781cf26b5
21
Makefile
Normal file
21
Makefile
Normal file
@ -0,0 +1,21 @@
|
||||
GO_MODULE_IMPORT := go.datafortress.dev/pkg/central-arch-spec-models
|
||||
GO_MODELS_PKG := spec
|
||||
|
||||
SPEC_XML_NS := https://datafortress.dev/xml/central-arch-specification
|
||||
SPEC_SCHEMA_DIR := ../central-arch-spec-schema
|
||||
SPEC_SCHEMA_FILE := specification.xsd
|
||||
|
||||
.PHONY: all
|
||||
all: tests
|
||||
|
||||
.PHONY: tests
|
||||
tests:
|
||||
go test $(shell find . -type f -name '*_test.go' -print)
|
||||
|
||||
.PHONY: deps
|
||||
deps:
|
||||
go install github.com/gocomply/xsd2go/cli/gocomply_xsd2go@latest
|
||||
|
||||
.PHONY: generate
|
||||
generate:
|
||||
gocomply_xsd2go convert --xmlns-override=${SPEC_XML_NS}=${GO_MODELS_PKG} ${SPEC_SCHEMA_DIR}/${SPEC_SCHEMA_FILE} ${GO_MODULE_IMPORT} .
|
||||
9
README.md
Normal file
9
README.md
Normal file
@ -0,0 +1,9 @@
|
||||
# Central Arch: XML Specification Models
|
||||
## Install GoComply Xsd2Go
|
||||
```bash
|
||||
make deps
|
||||
```
|
||||
## Regenerate data model from XSD
|
||||
```bash
|
||||
make models
|
||||
```
|
||||
11
go.mod
Normal file
11
go.mod
Normal file
@ -0,0 +1,11 @@
|
||||
module go.datafortress.dev/pkg/central-arch-spec-models
|
||||
|
||||
go 1.23.2
|
||||
|
||||
require github.com/stretchr/testify v1.11.1
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
10
go.sum
Normal file
10
go.sum
Normal file
@ -0,0 +1,10 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
116
query/indexer.go
Normal file
116
query/indexer.go
Normal file
@ -0,0 +1,116 @@
|
||||
package query
|
||||
|
||||
import "fmt"
|
||||
|
||||
type IndexedElement struct {
|
||||
Name string
|
||||
DisplayName *string
|
||||
ReferencedData any
|
||||
Parent *IndexedContainer
|
||||
Containers []*IndexedContainer
|
||||
}
|
||||
|
||||
func (e *IndexedElement) Init() {
|
||||
for _, container := range e.Containers {
|
||||
container.Parent = e
|
||||
container.Init()
|
||||
}
|
||||
}
|
||||
|
||||
func (e *IndexedElement) String() string {
|
||||
if e.Parent == nil {
|
||||
panic("IndexedElement has no parent!")
|
||||
}
|
||||
return fmt.Sprintf("%s:%s", e.Parent.Parent, e.Name)
|
||||
}
|
||||
|
||||
func (e *IndexedElement) PrintableName() string {
|
||||
var result = e.Name
|
||||
if e.DisplayName != nil {
|
||||
result = *e.DisplayName
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (e *IndexedElement) Find(c *Container) QueryResult {
|
||||
return findInContainers(c, e.Containers)
|
||||
}
|
||||
|
||||
type IndexedContainer struct {
|
||||
Name string
|
||||
Parent *IndexedElement
|
||||
Elements []*IndexedElement
|
||||
}
|
||||
|
||||
func (c *IndexedContainer) Init() {
|
||||
for _, element := range c.Elements {
|
||||
element.Parent = c
|
||||
element.Init()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *IndexedContainer) String() string {
|
||||
var parentStr = ""
|
||||
|
||||
if c.Parent != nil {
|
||||
parentStr = c.Parent.String()
|
||||
}
|
||||
return fmt.Sprintf("%s%s", parentStr, c.Name)
|
||||
}
|
||||
|
||||
func (c *IndexedContainer) PrintableName() string {
|
||||
return c.Name
|
||||
}
|
||||
|
||||
func (c *IndexedContainer) Find(e *Element) QueryResult {
|
||||
for _, element := range c.Elements {
|
||||
if e.Name == element.Name {
|
||||
if e.NextContainer != nil {
|
||||
// If the element is found but the query expression continues
|
||||
// with a container query, delegate the search to the element
|
||||
return element.Find(e.NextContainer)
|
||||
} else {
|
||||
// If not, return the found element
|
||||
return QueryResult{element}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return an empty list if the element is not found
|
||||
return make(QueryResult, 0)
|
||||
}
|
||||
|
||||
// A query tree is a bipartite graph composed of containers and elements.
|
||||
// Only elements can be queried.
|
||||
type IndexedRoot struct {
|
||||
Containers []*IndexedContainer
|
||||
}
|
||||
|
||||
func (r *IndexedRoot) Find(q *Query) QueryResult {
|
||||
return findInContainers(&q.Container, r.Containers)
|
||||
}
|
||||
|
||||
func (r *IndexedRoot) FindByRef(ref Reference) (QueryResult, error) {
|
||||
var query, err = ref.Parse()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r.Find(query), nil
|
||||
}
|
||||
|
||||
func findInContainers(queried *Container, containers []*IndexedContainer) QueryResult {
|
||||
for _, container := range containers {
|
||||
if queried.Name == container.Name {
|
||||
if queried.NextElement != nil {
|
||||
// If the container is found but the query expression continues
|
||||
// with an element query, delegate the search to the container
|
||||
return container.Find(queried.NextElement)
|
||||
} else {
|
||||
// If not, return all the elements in the found container
|
||||
return container.Elements
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return an empty list if the container is not found
|
||||
return make(QueryResult, 0)
|
||||
}
|
||||
229
query/ref.go
Normal file
229
query/ref.go
Normal file
@ -0,0 +1,229 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
/*
|
||||
A reference is composed of one or more matchers separated by periods.
|
||||
A matcher can be composed by a single container name or by both a
|
||||
container name and an element identifier.
|
||||
A matcher only composed of a container name can only appear as the last
|
||||
matcher of a reference.
|
||||
|
||||
A reference the last matcher of which is composed of both a container
|
||||
name and an element identifier is a fully qualified reference.
|
||||
|
||||
A reference the last matcher of which is only composed of a container
|
||||
returns all elements inside the container or an empty list.
|
||||
A reference the last matcher of which is composed of both a container
|
||||
name and an element identifier returns only the referenced element or
|
||||
an empty list.
|
||||
|
||||
Example, given the following query tree:
|
||||
|
||||
(with "r:" meaning "root", "c:" container and "e:" element).
|
||||
|
||||
<r: />-+--<c: format>-+--<e: T1>
|
||||
| |--<e: T2>
|
||||
|
|
||||
+--<c: instr>--+--<e: BKPT>-+--<c: binding>
|
||||
|
||||
Ref: "format"
|
||||
Returns: [T1, T2]
|
||||
|
||||
Ref: "format:T1"
|
||||
Returns: [T1]
|
||||
|
||||
Ref: "instr:BKPT"
|
||||
Returns: [BKPT]
|
||||
|
||||
Ref: "instr:BKPT.binding"
|
||||
Returns: []
|
||||
|
||||
Ref: "instr:BKPT.binding:base"
|
||||
Returns: []
|
||||
|
||||
Ref: "instr.binding"
|
||||
Returns: Error
|
||||
=> Container-only matcher can only be used as the last matcher in a reference.
|
||||
*/
|
||||
type Reference string
|
||||
|
||||
func (ref *Reference) Parse() (*Query, error) {
|
||||
var container, err = parseContainerComponent(*ref, 0)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Query{Container: *container}, nil
|
||||
}
|
||||
|
||||
func (ref *Reference) IsValid() bool {
|
||||
var _, err = ref.Parse()
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (ref *Reference) IsFullyQualified() bool {
|
||||
var query, err = ref.Parse()
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return query.IsFullyQualified()
|
||||
}
|
||||
|
||||
type RefParseError struct {
|
||||
Ref Reference
|
||||
Index int
|
||||
Msg string
|
||||
}
|
||||
|
||||
func (err *RefParseError) Error() string {
|
||||
var error_fmt = `Parsing error at character %d in the following query reference:
|
||||
"%s"
|
||||
%s^
|
||||
Error: %s`
|
||||
|
||||
return fmt.Sprintf(error_fmt, err.Index+1, err.Ref, strings.Repeat(" ", err.Index), err.Msg)
|
||||
}
|
||||
|
||||
func isValidNameChar(r rune) bool {
|
||||
return unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '-'
|
||||
}
|
||||
|
||||
func isMatcherSeparator(r rune) bool {
|
||||
return r == '.'
|
||||
}
|
||||
|
||||
func isElementIdSeparator(r rune) bool {
|
||||
return r == ':'
|
||||
}
|
||||
|
||||
func parseContainerComponent(ref Reference, index int) (*Container, error) {
|
||||
var currentName = ""
|
||||
|
||||
if index >= len(ref) {
|
||||
return nil, &RefParseError{
|
||||
Ref: ref,
|
||||
Index: index,
|
||||
Msg: "Expected a container name but reached end of reference",
|
||||
}
|
||||
}
|
||||
|
||||
for i, w := index, 0; i < len(ref); i += w {
|
||||
var runeValue, width = utf8.DecodeRuneInString(string(ref[i:]))
|
||||
w = width
|
||||
|
||||
if isElementIdSeparator(runeValue) {
|
||||
if len(currentName) > 0 {
|
||||
var e, err = parseElementComponent(ref, index)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Container{Name: currentName, NextElement: e}, nil
|
||||
} else {
|
||||
return nil, &RefParseError{
|
||||
Ref: ref,
|
||||
Index: index,
|
||||
Msg: "Expected a container name before an element identifier",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if isMatcherSeparator(runeValue) {
|
||||
if len(currentName) > 0 {
|
||||
return nil, &RefParseError{
|
||||
Ref: ref,
|
||||
Index: index,
|
||||
Msg: "Expected an element identifier before another container name",
|
||||
}
|
||||
} else {
|
||||
return nil, &RefParseError{
|
||||
Ref: ref,
|
||||
Index: index,
|
||||
Msg: "Expected both a container name and an element identifier before another container name",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if isValidNameChar(runeValue) {
|
||||
currentName += string(runeValue)
|
||||
} else {
|
||||
return nil, &RefParseError{
|
||||
Ref: ref,
|
||||
Index: index,
|
||||
Msg: fmt.Sprintf("Character '%c' is not permitted in a container name", runeValue),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &Container{Name: currentName, NextElement: nil}, nil
|
||||
}
|
||||
|
||||
func parseElementComponent(ref Reference, index int) (*Element, error) {
|
||||
var currentName = ""
|
||||
|
||||
if index >= len(ref) {
|
||||
return nil, &RefParseError{
|
||||
Ref: ref,
|
||||
Index: index,
|
||||
Msg: "Expected an element identifier but reached end of reference",
|
||||
}
|
||||
}
|
||||
|
||||
for i, w := index, 0; i < len(ref); i += w {
|
||||
var runeValue, width = utf8.DecodeRuneInString(string(ref[i:]))
|
||||
w = width
|
||||
|
||||
if isElementIdSeparator(runeValue) {
|
||||
if len(currentName) > 0 {
|
||||
return nil, &RefParseError{
|
||||
Ref: ref,
|
||||
Index: index,
|
||||
Msg: "Expected a container name before another element identifier",
|
||||
}
|
||||
} else {
|
||||
return nil, &RefParseError{
|
||||
Ref: ref,
|
||||
Index: index,
|
||||
Msg: "Expected both a container name and an element identifier before another element identifier",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if isMatcherSeparator(runeValue) {
|
||||
if len(currentName) > 0 {
|
||||
var e, err = parseContainerComponent(ref, index)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Element{Name: currentName, NextContainer: e}, nil
|
||||
} else {
|
||||
return nil, &RefParseError{
|
||||
Ref: ref,
|
||||
Index: index,
|
||||
Msg: "Expected an element identifier before a container name",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if isValidNameChar(runeValue) {
|
||||
currentName += string(runeValue)
|
||||
} else {
|
||||
return nil, &RefParseError{
|
||||
Ref: ref,
|
||||
Index: index,
|
||||
Msg: fmt.Sprintf("Character '%c' is not permitted in an element identifier", runeValue),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &Element{Name: currentName, NextContainer: nil}, nil
|
||||
}
|
||||
31
query/ref_test.go
Normal file
31
query/ref_test.go
Normal file
@ -0,0 +1,31 @@
|
||||
package query_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.datafortress.dev/pkg/central-arch-spec-models/query"
|
||||
)
|
||||
|
||||
const (
|
||||
MULTIPLE_LEVELS_QUERY_REF = "instruction:LDR_Base_Offset.binding:base"
|
||||
FULLY_QUALIFIED_QUERY_REF = "c1:e1.c2:e2"
|
||||
NOT_FULLY_QUALIFIED_QUERY_REF = "c1:e1.c2"
|
||||
)
|
||||
|
||||
func TestRefParsing(t *testing.T) {
|
||||
var ref query.Reference = MULTIPLE_LEVELS_QUERY_REF
|
||||
var query, err = ref.Parse()
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
var instrContainer = query.Container
|
||||
require.Equal(t, "instruction", instrContainer.Name)
|
||||
require.NotNil(t, instrContainer.NextElement)
|
||||
|
||||
var instrElement = instrContainer.NextElement
|
||||
require.Equal(t, "LDR_Base_Offset", instrElement.Name)
|
||||
require.NotNil(t, instrElement.NextContainer)
|
||||
|
||||
// TODO Continue testing
|
||||
}
|
||||
61
query/tree.go
Normal file
61
query/tree.go
Normal file
@ -0,0 +1,61 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type QueryResult []*IndexedElement
|
||||
|
||||
type Element struct {
|
||||
Name string
|
||||
NextContainer *Container
|
||||
}
|
||||
|
||||
func (e *Element) String() string {
|
||||
var containerStr = ""
|
||||
|
||||
if e.NextContainer != nil {
|
||||
containerStr = fmt.Sprintf(".%s", e.NextContainer)
|
||||
}
|
||||
return fmt.Sprintf("%s%s", e.Name, containerStr)
|
||||
}
|
||||
|
||||
type Container struct {
|
||||
Name string
|
||||
NextElement *Element
|
||||
}
|
||||
|
||||
func (c *Container) String() string {
|
||||
var elementStr = ""
|
||||
|
||||
if c.NextElement != nil {
|
||||
elementStr = fmt.Sprintf(":%s", c.NextElement)
|
||||
}
|
||||
return fmt.Sprintf("%s%s", c.Name, elementStr)
|
||||
}
|
||||
|
||||
type Query struct {
|
||||
Container Container
|
||||
}
|
||||
|
||||
func (q *Query) String() string {
|
||||
return q.Container.String()
|
||||
}
|
||||
|
||||
func (q *Query) IsFullyQualified() bool {
|
||||
var container *Container = &q.Container
|
||||
|
||||
for container != nil {
|
||||
if container.NextElement == nil {
|
||||
// Current container has no next element, so the query ended on a container.
|
||||
// Thus, it is not fully qualified.
|
||||
return false
|
||||
} else {
|
||||
container = container.NextElement.NextContainer
|
||||
}
|
||||
}
|
||||
|
||||
// Next container is nil, so the query ended on an element.
|
||||
// Thus, it is fully qualified.
|
||||
return true
|
||||
}
|
||||
307
spec/models.go
Normal file
307
spec/models.go
Normal file
@ -0,0 +1,307 @@
|
||||
// Code generated by https://github.com/gocomply/xsd2go; DO NOT EDIT.
|
||||
// Models for https://datafortress.dev/xml/central-arch-specification
|
||||
package spec
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
)
|
||||
|
||||
// Element
|
||||
type Specification struct {
|
||||
XMLName xml.Name `xml:"specification"`
|
||||
|
||||
Exceptions ExceptionList `xml:"exceptions"`
|
||||
|
||||
Formats FormatList `xml:"formats"`
|
||||
|
||||
Instructions InstructionList `xml:"instructions"`
|
||||
}
|
||||
|
||||
// XSD ComplexType declarations
|
||||
|
||||
// SpecificationType: Central Architecture CPU XML Specification file.
|
||||
type SpecificationType struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Exceptions ExceptionList `xml:"exceptions"`
|
||||
|
||||
Formats FormatList `xml:"formats"`
|
||||
|
||||
Instructions InstructionList `xml:"instructions"`
|
||||
}
|
||||
|
||||
// FormatList: Supported instruction encoding formats.
|
||||
type FormatList struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Format []Format `xml:",any"`
|
||||
}
|
||||
|
||||
// InstructionList: Supported instructions.
|
||||
type InstructionList struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Instruction []Instruction `xml:",any"`
|
||||
}
|
||||
|
||||
// ExceptionList: Supported exceptions.
|
||||
type ExceptionList struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Exception []Exception `xml:",any"`
|
||||
}
|
||||
|
||||
// DocText: Documentation text.
|
||||
type DocText struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Ref []RefText `xml:"ref"`
|
||||
|
||||
Todo []TodoText `xml:"todo"`
|
||||
|
||||
InnerXml string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
// RefText: A reference to an element.
|
||||
type RefText struct {
|
||||
XMLName xml.Name
|
||||
|
||||
// Type: Reference type. Used to set a specific styling to the reference text. Can also generate a link to a reference in the documentation.
|
||||
Type string `xml:"type,attr"`
|
||||
|
||||
Text string `xml:",chardata"`
|
||||
}
|
||||
|
||||
// TodoText: A TODO annotation.
|
||||
type TodoText struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Text string `xml:",chardata"`
|
||||
}
|
||||
|
||||
// Exception: The specification of an exception.
|
||||
type Exception struct {
|
||||
XMLName xml.Name
|
||||
|
||||
// Id: The unique identifier of this exception.
|
||||
Id string `xml:"id,attr"`
|
||||
|
||||
// DisplayName: The name of the exception that will be displayed in the documentation.
|
||||
DisplayName string `xml:"display-name"`
|
||||
|
||||
// Brief: A brief description of this exception.
|
||||
Brief DocText `xml:"brief"`
|
||||
|
||||
// Details: Details about this exception. Used to give info about where the exception handler PSW is stored and what are the info given to it by the system.
|
||||
Details DocText `xml:"details"`
|
||||
}
|
||||
|
||||
// Format: The specification of an instruction encoding format.
|
||||
type Format struct {
|
||||
XMLName xml.Name
|
||||
|
||||
// Id: The unique identifier of an instruction encoding format.
|
||||
Id string `xml:"id,attr"`
|
||||
|
||||
// DisplayName: The name of the instruction encoding format as it will be displayed in the documentation.
|
||||
DisplayName string `xml:"display-name"`
|
||||
|
||||
Description DocText `xml:"description"`
|
||||
|
||||
Fields FormatFieldList `xml:"fields"`
|
||||
}
|
||||
|
||||
// FormatFieldList: The fields used in this instruction encoding format.
|
||||
type FormatFieldList struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Field []FormatField `xml:",any"`
|
||||
}
|
||||
|
||||
// FormatField: Description of a field in this instruction encoding format.
|
||||
type FormatField struct {
|
||||
XMLName xml.Name
|
||||
|
||||
// Bits: Field length, in bits.
|
||||
Bits int64 `xml:"bits,attr"`
|
||||
|
||||
Type FormatFieldType `xml:"type,attr"`
|
||||
|
||||
// Name: Field name. Ignored for opcode and condition fields.
|
||||
Name string `xml:"name,attr,omitempty"`
|
||||
}
|
||||
|
||||
// Instruction: The specification of an instruction.
|
||||
type Instruction struct {
|
||||
XMLName xml.Name
|
||||
|
||||
// Id: The unique identifier of this instruction.
|
||||
Id string `xml:"id,attr"`
|
||||
|
||||
// Opcode: The opcode of this instruction.
|
||||
Opcode uint8 `xml:"opcode,attr"`
|
||||
|
||||
// Format: The encoding format of the instruction.
|
||||
Format string `xml:"format,attr"`
|
||||
|
||||
// DisplayName: The name of the instruction as it will be displayed in the documentation.
|
||||
DisplayName string `xml:"display-name"`
|
||||
|
||||
// Description: The description of this instruction.
|
||||
Description DocText `xml:"description"`
|
||||
|
||||
Syntax Syntax `xml:"syntax"`
|
||||
|
||||
Examples ExampleList `xml:"examples"`
|
||||
|
||||
Bindings BindingList `xml:"bindings"`
|
||||
|
||||
Operation Operation `xml:"operation"`
|
||||
|
||||
Exceptions InstructionExceptionList `xml:"exceptions"`
|
||||
}
|
||||
|
||||
// Syntax: The assembler syntax of the instruction.
|
||||
type Syntax struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Mnemonic Mnemonic `xml:",any"`
|
||||
}
|
||||
|
||||
// MnemonicArgRegister: A register passed as an argument of the instruction.
|
||||
type MnemonicArgRegister struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Binding BindingName `xml:"binding,attr"`
|
||||
|
||||
Ref []RefText `xml:"ref"`
|
||||
|
||||
Todo []TodoText `xml:"todo"`
|
||||
}
|
||||
|
||||
// MnemonicArgImmediate: An immediate value passed as an argument of the instruction.
|
||||
type MnemonicArgImmediate struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Ref BindingName `xml:"ref,attr"`
|
||||
|
||||
RefElm []RefText `xml:"ref"`
|
||||
|
||||
Todo []TodoText `xml:"todo"`
|
||||
}
|
||||
|
||||
// MnemonicArgGroup: A group of both registers and immediate values passed as arguments of the instruction.
|
||||
type MnemonicArgGroup struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Register []MnemonicArgRegister `xml:"register"`
|
||||
|
||||
Immediate []MnemonicArgImmediate `xml:"immediate"`
|
||||
}
|
||||
|
||||
// ExampleList: Instruction syntax examples.
|
||||
type ExampleList struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Example []Example `xml:",any"`
|
||||
}
|
||||
|
||||
// Example: An example of the instruction syntax.
|
||||
type Example struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Code Code `xml:"code"`
|
||||
|
||||
Comment CodeComment `xml:"comment"`
|
||||
}
|
||||
|
||||
// CodeComment: Comment about the assembly code of the example.
|
||||
type CodeComment struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Ref []RefText `xml:"ref"`
|
||||
|
||||
Todo []TodoText `xml:"todo"`
|
||||
}
|
||||
|
||||
// BindingList: Value bindings to instruction fields.
|
||||
type BindingList struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Binding []Binding `xml:",any"`
|
||||
}
|
||||
|
||||
// Binding: A value binding to an instruction field.
|
||||
type Binding struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Name BindingName `xml:"name,attr"`
|
||||
|
||||
// Field: Reference to the instruction field to bind the value to.
|
||||
Field string `xml:"field,attr"`
|
||||
|
||||
// Aligned: Optional immediate value alignement, must be a power of 2. Dictates how the value is encoded: an alignment of 2 means that the value is bitshifted right by one bit, an alignment of 4 means that it is bitshifted right by two bits, etc... Defaults to 1, i.e. no bitshifting is involved.
|
||||
Aligned uint64 `xml:"aligned,attr"`
|
||||
|
||||
// MinusOne: Specifies whether the value is "-1 encoded". As an example, if an 8-bits value is -1 encoded then it means that one can use values in the range 1..256 and it will be encoded in the range 0..255. Defaults to false.
|
||||
MinusOne bool `xml:"minus-one,attr"`
|
||||
|
||||
// Signed: Indicate whether the immediate value is signed. Defaults to false.
|
||||
Signed bool `xml:"signed,attr"`
|
||||
}
|
||||
|
||||
// InstructionExceptionList: The exceptions that can be generated during execution of this instruction.
|
||||
type InstructionExceptionList struct {
|
||||
XMLName xml.Name
|
||||
|
||||
Exception []InstructionException `xml:",any"`
|
||||
}
|
||||
|
||||
// InstructionException: An exception that can be generated during the execution of this instruction.
|
||||
type InstructionException struct {
|
||||
XMLName xml.Name
|
||||
|
||||
// Ref: The unique identifier of the exception.
|
||||
Ref string `xml:"ref,attr"`
|
||||
|
||||
RefElm []RefText `xml:"ref"`
|
||||
|
||||
Todo []TodoText `xml:"todo"`
|
||||
}
|
||||
|
||||
// XSD SimpleType declarations
|
||||
|
||||
// FormatFieldType: Field type.
|
||||
type FormatFieldType string
|
||||
|
||||
const FormatFieldTypeOpcode FormatFieldType = "opcode"
|
||||
|
||||
const FormatFieldTypeRegister FormatFieldType = "register"
|
||||
|
||||
const FormatFieldTypeRegisterSrc FormatFieldType = "register.src"
|
||||
|
||||
const FormatFieldTypeRegisterDest FormatFieldType = "register.dest"
|
||||
|
||||
const FormatFieldTypeRegisterOffset FormatFieldType = "register.offset"
|
||||
|
||||
const FormatFieldTypeImmediate FormatFieldType = "immediate"
|
||||
|
||||
const FormatFieldTypeImmediateOffset FormatFieldType = "immediate.offset"
|
||||
|
||||
const FormatFieldTypeCondition FormatFieldType = "condition"
|
||||
|
||||
const FormatFieldTypeFlag FormatFieldType = "flag"
|
||||
|
||||
const FormatFieldTypeUnused FormatFieldType = "unused"
|
||||
|
||||
// Mnemonic: Instruction mnemonic.
|
||||
type Mnemonic string
|
||||
|
||||
// Code: Single-line assembly code of the example.
|
||||
type Code string
|
||||
|
||||
// BindingName: The name of the value binding.
|
||||
type BindingName string
|
||||
|
||||
// Operation: Instruction microcoded operation.
|
||||
type Operation string
|
||||
5
spec/visitor.go
Normal file
5
spec/visitor.go
Normal file
@ -0,0 +1,5 @@
|
||||
package spec
|
||||
|
||||
type SpecVisitor interface {
|
||||
VisitSpecification(node *Specification)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user