lang: Edges should allow lists of strings
This continues the earlier patch that allowed resource names to be lists of strings so that edges can now allow the same. This also includes a new fancy test!
This commit is contained in:
18
lang/interpret_test/TestAstFunc2/empty-edge-list-0.output
Normal file
18
lang/interpret_test/TestAstFunc2/empty-edge-list-0.output
Normal file
@@ -0,0 +1,18 @@
|
||||
Edge: test[hey] -> test[amazing] # test[hey] -> test[amazing]
|
||||
Edge: test[hey] -> test[cool] # test[hey] -> test[cool]
|
||||
Edge: test[hey] -> test[hello] # test[hey] -> test[hello]
|
||||
Edge: test[hey] -> test[world] # test[hey] -> test[world]
|
||||
Edge: test[hey] -> test[wow] # test[hey] -> test[wow]
|
||||
Edge: test[there] -> test[amazing] # test[there] -> test[amazing]
|
||||
Edge: test[there] -> test[cool] # test[there] -> test[cool]
|
||||
Edge: test[there] -> test[hello] # test[there] -> test[hello]
|
||||
Edge: test[there] -> test[world] # test[there] -> test[world]
|
||||
Edge: test[there] -> test[wow] # test[there] -> test[wow]
|
||||
Vertex: test[amazing]
|
||||
Vertex: test[cool]
|
||||
Vertex: test[hello]
|
||||
Vertex: test[hey]
|
||||
Vertex: test[name]
|
||||
Vertex: test[there]
|
||||
Vertex: test[world]
|
||||
Vertex: test[wow]
|
||||
18
lang/interpret_test/TestAstFunc2/empty-edge-list-0/main.mcl
Normal file
18
lang/interpret_test/TestAstFunc2/empty-edge-list-0/main.mcl
Normal file
@@ -0,0 +1,18 @@
|
||||
# this must pass type unification and generate output
|
||||
|
||||
# single resource
|
||||
test "name" {}
|
||||
|
||||
# single resource, defined by list variable
|
||||
$names = ["hey", "there",]
|
||||
test $names {}
|
||||
|
||||
# multiples resources, defined by list
|
||||
test ["hello", "world",] {
|
||||
Depend => Test[$names],
|
||||
}
|
||||
|
||||
$morenames = ["wow", "cool", "amazing",]
|
||||
test $morenames {}
|
||||
|
||||
Test[$names] -> Test[$morenames]
|
||||
@@ -531,12 +531,32 @@ func (obj *StmtRes) edges(resName string) ([]*interfaces.Edge, error) {
|
||||
}
|
||||
}
|
||||
|
||||
v, err := x.EdgeHalf.Name.Value()
|
||||
nameValue, err := x.EdgeHalf.Name.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name := v.Str() // must not panic
|
||||
|
||||
// the edge name can be a single string or a list of strings...
|
||||
|
||||
names := []string{} // list of names to build
|
||||
switch {
|
||||
case types.TypeStr.Cmp(nameValue.Type()) == nil:
|
||||
name := nameValue.Str() // must not panic
|
||||
names = append(names, name)
|
||||
|
||||
case types.NewType("[]str").Cmp(nameValue.Type()) == nil:
|
||||
for _, x := range nameValue.List() { // must not panic
|
||||
name := x.Str() // must not panic
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
default:
|
||||
// programming error
|
||||
return nil, fmt.Errorf("unhandled resource name type: %+v", nameValue.Type())
|
||||
}
|
||||
|
||||
kind := x.EdgeHalf.Kind
|
||||
for _, name := range names {
|
||||
var notify bool
|
||||
|
||||
switch p := x.Property; p {
|
||||
@@ -572,6 +592,7 @@ func (obj *StmtRes) edges(resName string) ([]*interfaces.Edge, error) {
|
||||
return nil, fmt.Errorf("unknown property: %s", p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: we could detect simple loops here (if `from` and `to` have the
|
||||
// same entry) but we can leave this to the proper dag checker later on
|
||||
@@ -1434,14 +1455,50 @@ func (obj *StmtEdge) Output() (*interfaces.Output, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name1 := nameValue1.Str() // must not panic
|
||||
|
||||
// the edge name can be a single string or a list of strings...
|
||||
|
||||
names1 := []string{} // list of names to build
|
||||
switch {
|
||||
case types.TypeStr.Cmp(nameValue1.Type()) == nil:
|
||||
name := nameValue1.Str() // must not panic
|
||||
names1 = append(names1, name)
|
||||
|
||||
case types.NewType("[]str").Cmp(nameValue1.Type()) == nil:
|
||||
for _, x := range nameValue1.List() { // must not panic
|
||||
name := x.Str() // must not panic
|
||||
names1 = append(names1, name)
|
||||
}
|
||||
|
||||
default:
|
||||
// programming error
|
||||
return nil, fmt.Errorf("unhandled resource name type: %+v", nameValue1.Type())
|
||||
}
|
||||
|
||||
nameValue2, err := obj.EdgeHalfList[i+1].Name.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name2 := nameValue2.Str() // must not panic
|
||||
|
||||
names2 := []string{} // list of names to build
|
||||
switch {
|
||||
case types.TypeStr.Cmp(nameValue2.Type()) == nil:
|
||||
name := nameValue2.Str() // must not panic
|
||||
names2 = append(names2, name)
|
||||
|
||||
case types.NewType("[]str").Cmp(nameValue2.Type()) == nil:
|
||||
for _, x := range nameValue2.List() { // must not panic
|
||||
name := x.Str() // must not panic
|
||||
names2 = append(names2, name)
|
||||
}
|
||||
|
||||
default:
|
||||
// programming error
|
||||
return nil, fmt.Errorf("unhandled resource name type: %+v", nameValue2.Type())
|
||||
}
|
||||
|
||||
for _, name1 := range names1 {
|
||||
for _, name2 := range names2 {
|
||||
edge := &interfaces.Edge{
|
||||
Kind1: obj.EdgeHalfList[i].Kind,
|
||||
Name1: name1,
|
||||
@@ -1455,6 +1512,8 @@ func (obj *StmtEdge) Output() (*interfaces.Output, error) {
|
||||
}
|
||||
edges = append(edges, edge)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &interfaces.Output{
|
||||
Edges: edges,
|
||||
@@ -1531,11 +1590,24 @@ func (obj *StmtEdgeHalf) Unify() ([]interfaces.Invariant, error) {
|
||||
}
|
||||
invariants = append(invariants, invars...)
|
||||
|
||||
// name must be a string
|
||||
invar := &unification.EqualsInvariant{
|
||||
// name must be a string or a list
|
||||
ors := []interfaces.Invariant{}
|
||||
|
||||
invarStr := &unification.EqualsInvariant{
|
||||
Expr: obj.Name,
|
||||
Type: types.TypeStr,
|
||||
}
|
||||
ors = append(ors, invarStr)
|
||||
|
||||
invarListStr := &unification.EqualsInvariant{
|
||||
Expr: obj.Name,
|
||||
Type: types.NewType("[]str"),
|
||||
}
|
||||
ors = append(ors, invarListStr)
|
||||
|
||||
invar := &unification.ExclusiveInvariant{
|
||||
Invariants: ors, // one and only one of these should be true
|
||||
}
|
||||
invariants = append(invariants, invar)
|
||||
|
||||
return invariants, nil
|
||||
|
||||
Reference in New Issue
Block a user