haven/nexgb/xgbgen/field.go

222 lines
4.2 KiB
Go
Raw Normal View History

package main
import (
"fmt"
"log"
)
type Field interface {
Initialize(p *Protocol)
SrcName() string
XmlName() string
2012-05-01 07:08:03 +02:00
SrcType() string
Size() Size
Define(c *Context)
Read(c *Context)
Write(c *Context)
}
func (pad *PadField) Initialize(p *Protocol) {}
type PadField struct {
Bytes uint
}
func (p *PadField) SrcName() string {
panic("illegal to take source name of a pad field")
}
func (p *PadField) XmlName() string {
panic("illegal to take XML name of a pad field")
}
2012-05-01 07:08:03 +02:00
func (f *PadField) SrcType() string {
panic("it is illegal to call SrcType on a SwitchField field")
}
func (p *PadField) Size() Size {
return newFixedSize(p.Bytes)
}
type SingleField struct {
srcName string
xmlName string
2012-04-30 08:44:31 +02:00
Type Type
}
func (f *SingleField) Initialize(p *Protocol) {
f.srcName = SrcName(f.XmlName())
f.Type = f.Type.(*Translation).RealType(p)
}
func (f *SingleField) SrcName() string {
return f.srcName
}
func (f *SingleField) XmlName() string {
return f.xmlName
}
2012-05-01 07:08:03 +02:00
func (f *SingleField) SrcType() string {
return f.Type.SrcName()
}
func (f *SingleField) Size() Size {
return f.Type.Size()
}
type ListField struct {
2012-04-30 08:44:31 +02:00
srcName string
xmlName string
Type Type
LengthExpr Expression
}
func (f *ListField) SrcName() string {
return f.srcName
}
func (f *ListField) XmlName() string {
return f.xmlName
}
2012-05-01 07:08:03 +02:00
func (f *ListField) SrcType() string {
return fmt.Sprintf("[]%s", f.Type.SrcName())
}
func (f *ListField) Size() Size {
simpleLen := &Function{
Name: "pad",
Expr: newBinaryOp("*", f.LengthExpr, f.Type.Size().Expression),
}
switch f.Type.(type) {
case *Struct:
sizeFun := &Function{
Name: fmt.Sprintf("%sListSize", f.Type.SrcName()),
Expr: &FieldRef{Name: f.SrcName()},
}
return newExpressionSize(sizeFun)
case *Base:
return newExpressionSize(simpleLen)
case *Resource:
return newExpressionSize(simpleLen)
case *TypeDef:
return newExpressionSize(simpleLen)
default:
log.Panicf("Cannot compute list size with type '%T'.", f.Type)
}
panic("unreachable")
}
func (f *ListField) Initialize(p *Protocol) {
f.srcName = SrcName(f.XmlName())
f.Type = f.Type.(*Translation).RealType(p)
if f.LengthExpr != nil {
f.LengthExpr.Initialize(p)
}
}
type LocalField struct {
*SingleField
}
type ExprField struct {
srcName string
xmlName string
2012-04-30 08:44:31 +02:00
Type Type
Expr Expression
}
func (f *ExprField) SrcName() string {
return f.srcName
}
func (f *ExprField) XmlName() string {
return f.xmlName
}
2012-05-01 07:08:03 +02:00
func (f *ExprField) SrcType() string {
return f.Type.SrcName()
}
func (f *ExprField) Size() Size {
return f.Type.Size()
}
func (f *ExprField) Initialize(p *Protocol) {
f.srcName = SrcName(f.XmlName())
f.Type = f.Type.(*Translation).RealType(p)
f.Expr.Initialize(p)
}
type ValueField struct {
MaskType Type
MaskName string
ListName string
}
func (f *ValueField) SrcName() string {
panic("it is illegal to call SrcName on a ValueField field")
}
func (f *ValueField) XmlName() string {
panic("it is illegal to call XmlName on a ValueField field")
}
2012-05-01 07:08:03 +02:00
func (f *ValueField) SrcType() string {
return f.MaskType.SrcName()
}
func (f *ValueField) Size() Size {
return f.MaskType.Size()
}
func (f *ValueField) Initialize(p *Protocol) {
f.MaskType = f.MaskType.(*Translation).RealType(p)
f.MaskName = SrcName(f.MaskName)
f.ListName = SrcName(f.ListName)
}
type SwitchField struct {
2012-04-30 08:44:31 +02:00
Name string
Expr Expression
Bitcases []*Bitcase
}
func (f *SwitchField) SrcName() string {
panic("it is illegal to call SrcName on a SwitchField field")
}
func (f *SwitchField) XmlName() string {
panic("it is illegal to call XmlName on a SwitchField field")
}
2012-05-01 07:08:03 +02:00
func (f *SwitchField) SrcType() string {
panic("it is illegal to call SrcType on a SwitchField field")
}
// XXX: This is a bit tricky. The size has to be represented as a non-concrete
// expression that finds *which* bitcase fields are included, and sums the
// sizes of those fields.
func (f *SwitchField) Size() Size {
return newFixedSize(0)
}
func (f *SwitchField) Initialize(p *Protocol) {
f.Name = SrcName(f.Name)
f.Expr.Initialize(p)
for _, bitcase := range f.Bitcases {
bitcase.Expr.Initialize(p)
for _, field := range bitcase.Fields {
field.Initialize(p)
}
}
}
type Bitcase struct {
Fields []Field
2012-04-30 08:44:31 +02:00
Expr Expression
}