@ -2,18 +2,24 @@ package AST
import "fmt"
const anonName = "#anonymous"
type TransformNode struct {
* ScopeNode
Parameters [ ] string
parent * ReferenceNode
inlined bool
anonymous bool
}
func NewTransformNode ( name string , parameters [ ] string , transformBlock * ScopeNode ) * TransformNode {
transformBlock . SetName ( name )
func NewTransformNode ( name string , parameters [ ] string , scope * ScopeNode ) * TransformNode {
scope . SetName ( name )
tn := & TransformNode {
transformBlock ,
scope ,
parameters ,
NewReferenceNode ( "#parent" ) ,
false ,
false ,
}
for _ , childTrans := range tn . transforms {
@ -23,9 +29,20 @@ func NewTransformNode(name string, parameters []string, transformBlock *ScopeNod
return tn
}
func NewIdentNode ( name string , scope * ScopeNode ) * TransformNode {
scope . SetName ( name )
return NewTransformNode ( name , [ ] string { } , scope )
func NewInlineTransformNode ( name string , parameters [ ] string , scope * ScopeNode ) * TransformNode {
transform := NewTransformNode ( name , parameters , scope )
transform . inlined = true
return transform
}
func NewImmediateTransformNode ( parameters [ ] string , scope * ScopeNode ) * TransformNode {
transform := NewInlineTransformNode ( anonName , [ ] string { } , scope )
transform . anonymous = true
return transform
}
func NewIdentityNode ( scope * ScopeNode ) * TransformNode {
return NewImmediateTransformNode ( [ ] string { } , scope )
}
func ( tn * TransformNode ) AddChild ( node Unique ) error {
@ -35,35 +52,88 @@ func (tn *TransformNode) AddChild(node Unique) error {
return tn . ScopeNode . AddChild ( node )
}
func ( tn * TransformNode ) FindTransByName ( name string ) ( * TransformNode , error ) {
for _ , trans := range tn . transforms {
if trans . Name ( ) == name {
return trans , nil
func ( tn * TransformNode ) Inlined ( ) bool {
return tn . inlined
}
func ( tn * TransformNode ) Inline ( ) {
tn . inlined = true
}
func ( tn * TransformNode ) resolveRef ( ref * ReferenceNode ) ( * TransformNode , bool ) {
if len ( ref . Path ( ) ) == 1 {
if tn . Name ( ) == ref . BaseName ( ) {
return tn , true
}
for _ , childTrans := range tn . transforms {
if childTrans . Name ( ) == ref . BaseName ( ) {
return childTrans , true
}
}
if tn . HasParent ( ) {
//tn only has parent if the reference is resolved.
//As parent reference is only set by SetParents this is always a TransformNode
return tn . parent . destination . ( * TransformNode ) . resolveRef ( ref )
}
} else {
root , found := tn . findRoot ( ref )
if ! found {
return nil , found
}
for _ , childTrans := range root . transforms {
childRef , err := ref . ChildReference ( )
if err != nil {
panic ( fmt . Sprintf ( "Reached unreachable statement. Maybe this helps: %v" , err ) )
}
trans , found := childTrans . resolveRef ( childRef )
if found {
return trans , found
}
}
}
return nil , false
}
func ( tn * TransformNode ) findRoot ( ref * ReferenceNode ) ( trans * TransformNode , found bool ) {
trans = nil
found = false
parent , err := tn . Parent ( ) ; if err != nil { return nil , fmt . Errorf ( "Could not find transform with name %v" , name ) }
for _ , childTrans := range tn . transforms {
if childTrans . Name ( ) == ref . Root ( ) {
trans = childTrans
found = true
return
}
}
tr , err := parent . FindTransByName ( name )
return tr , err
if tn . HasParent ( ) {
//tn only has parent if the reference is resolved.
//As parent reference is only set by SetParents this is always a TransformNode
trans , found = tn . parent . destination . ( * TransformNode ) . findRoot ( ref )
}
return
}
func ( tn * TransformNode ) ResolveRefs ( ) error {
if ! tn . ParentsSet ( ) {
return fmt . Errorf ( "%v can only resolve references when all children know their parents" , tn . Name ( ) )
}
for _ , variable := range tn . variables {
transRef := variable . Transform
if ! transRef . IsResolved ( ) {
trans , err := tn . FindTransByName ( transRef . ReferenceName ) ; if err != nil { return fmt . Errorf ( "Ref %v for %v can not be resolved" , transRef . ReferenceName , variable . Name ( ) ) }
variable . Transform . Resolve ( trans )
}
}
for _ , childTrans := range tn . transforms {
childTrans . ResolveRefs ( )
}
for _ , variable := range tn . variables {
transRef := variable . Transform
if ! transRef . IsResolved ( ) {
dest , found := tn . resolveRef ( transRef )
if found {
transRef . Resolve ( dest )
}
}
}
return nil
}
@ -101,3 +171,8 @@ func (tn *TransformNode) ParentsSet() bool {
}
return true
}
func ( tn * TransformNode ) SetName ( name string ) {
tn . ScopeNode . SetName ( name )
tn . anonymous = false
}