diff --git a/docs/language-guide.md b/docs/language-guide.md index 4ebdbae5..c2904ca5 100644 --- a/docs/language-guide.md +++ b/docs/language-guide.md @@ -227,6 +227,7 @@ file "/tmp/f1" { Meta:noop => true, Meta:delay => $b ?: 42, + Meta:autoedge => false, } ``` @@ -250,6 +251,8 @@ file "/tmp/f1" { limit => 4.2, burst => 3, sema => ["foo:1", "bar:3",], + autoedge => true, + autogroup => false, }, } ``` diff --git a/lang/interpret_test.go b/lang/interpret_test.go index 32a03488..0e1aaf68 100644 --- a/lang/interpret_test.go +++ b/lang/interpret_test.go @@ -994,8 +994,12 @@ func TestAstInterpret0(t *testing.T) { limit => 4.2, burst => 3, sema => ["foo:1", "bar:3",], + autoedge => true, + autogroup => true, }, Meta:noop => true, + Meta:autoedge => true, + Meta:autogroup => true, } `, graph: graph, diff --git a/lang/interpret_test/TestAstFunc1/metaparams0.graph b/lang/interpret_test/TestAstFunc1/metaparams0.graph index 423db1dd..a045351a 100644 --- a/lang/interpret_test/TestAstFunc1/metaparams0.graph +++ b/lang/interpret_test/TestAstFunc1/metaparams0.graph @@ -1,17 +1,23 @@ -Edge: bool(false) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3))) # noop +Edge: bool(false) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3)); autoedge: bool(true); autogroup: bool(true)) # noop +Edge: bool(true) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3)); autoedge: bool(true); autogroup: bool(true)) # autoedge +Edge: bool(true) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3)); autoedge: bool(true); autogroup: bool(true)) # autogroup Edge: bool(true) -> var(b) # b Edge: bool(true) -> var(b) # b -Edge: float(4.2) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3))) # limit -Edge: int(-1) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3))) # retry -Edge: int(0) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3))) # delay -Edge: int(3) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3))) # burst -Edge: int(5) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3))) # poll -Edge: list(str(foo:1), str(bar:3)) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3))) # sema +Edge: float(4.2) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3)); autoedge: bool(true); autogroup: bool(true)) # limit +Edge: int(-1) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3)); autoedge: bool(true); autogroup: bool(true)) # retry +Edge: int(0) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3)); autoedge: bool(true); autogroup: bool(true)) # delay +Edge: int(3) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3)); autoedge: bool(true); autogroup: bool(true)) # burst +Edge: int(5) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3)); autoedge: bool(true); autogroup: bool(true)) # poll +Edge: list(str(foo:1), str(bar:3)) -> struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3)); autoedge: bool(true); autogroup: bool(true)) # sema Edge: str(bar:3) -> list(str(foo:1), str(bar:3)) # 1 Edge: str(foo:1) -> list(str(foo:1), str(bar:3)) # 0 Edge: str(hello world) -> call:fmt.printf(str(hello world)) # a Vertex: bool(false) Vertex: bool(false) +Vertex: bool(false) +Vertex: bool(true) +Vertex: bool(true) +Vertex: bool(true) Vertex: bool(true) Vertex: bool(true) Vertex: call:fmt.printf(str(hello world)) @@ -26,6 +32,6 @@ Vertex: str(bar:3) Vertex: str(foo:1) Vertex: str(greeting) Vertex: str(hello world) -Vertex: struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3))) +Vertex: struct(noop: bool(false); retry: int(-1); delay: int(0); poll: int(5); limit: float(4.2); burst: int(3); sema: list(str(foo:1), str(bar:3)); autoedge: bool(true); autogroup: bool(true)) Vertex: var(b) Vertex: var(b) diff --git a/lang/interpret_test/TestAstFunc1/metaparams0/main.mcl b/lang/interpret_test/TestAstFunc1/metaparams0/main.mcl index 4167d674..e3f7ccbe 100644 --- a/lang/interpret_test/TestAstFunc1/metaparams0/main.mcl +++ b/lang/interpret_test/TestAstFunc1/metaparams0/main.mcl @@ -13,8 +13,12 @@ test "greeting" { limit => 4.2, burst => 3, sema => ["foo:1", "bar:3",], + autoedge => true, + autogroup => true, }, Meta:noop => false, Meta:noop => true, # duplicates allowed atm, but not recommended! Meta:poll => $b ?: 42, + Meta:autoedge => true, + Meta:autogroup => false, } diff --git a/lang/structs.go b/lang/structs.go index b4854a96..3ba22657 100644 --- a/lang/structs.go +++ b/lang/structs.go @@ -617,6 +617,15 @@ func (obj *StmtRes) edges(resName string) ([]*interfaces.Edge, error) { func (obj *StmtRes) metaparams(res engine.Res) error { meta := engine.DefaultMetaParams.Copy() // defaults + var aem *engine.AutoEdgeMeta + if r, ok := res.(engine.EdgeableRes); ok { + aem = r.AutoEdgeMeta() // get a struct with the defaults + } + var agm *engine.AutoGroupMeta + if r, ok := res.(engine.GroupableRes); ok { + agm = r.AutoGroupMeta() // get a struct with the defaults + } + for _, line := range obj.Contents { x, ok := line.(*StmtResMeta) if !ok { @@ -676,6 +685,16 @@ func (obj *StmtRes) metaparams(res engine.Res) error { } meta.Sema = values + case "autoedge": + if aem != nil { + aem.Disabled = !v.Bool() // must not panic + } + + case "autogroup": + if agm != nil { + agm.Disabled = !v.Bool() // must not panic + } + case MetaField: if val, exists := v.Struct()["noop"]; exists { meta.Noop = val.Bool() // must not panic @@ -712,6 +731,12 @@ func (obj *StmtRes) metaparams(res engine.Res) error { } meta.Sema = values } + if val, exists := v.Struct()["autoedge"]; exists && aem != nil { + aem.Disabled = !val.Bool() // must not panic + } + if val, exists := v.Struct()["autogroup"]; exists && agm != nil { + agm.Disabled = !val.Bool() // must not panic + } default: return fmt.Errorf("unknown property: %s", p) @@ -719,6 +744,13 @@ func (obj *StmtRes) metaparams(res engine.Res) error { } res.SetMetaParams(meta) // set it! + if r, ok := res.(engine.EdgeableRes); ok { + r.SetAutoEdgeMeta(aem) // set + } + if r, ok := res.(engine.GroupableRes); ok { + r.SetAutoGroupMeta(agm) // set + } + return nil } @@ -1086,6 +1118,8 @@ func (obj *StmtResMeta) Init(data *interfaces.Data) error { case "limit": case "burst": case "sema": + case "autoedge": + case "autogroup": case MetaField: default: @@ -1194,10 +1228,18 @@ func (obj *StmtResMeta) Unify(kind string) ([]interfaces.Invariant, error) { case "sema": typ = types.NewType("[]str") + case "autoedge": + typ = types.TypeBool + + case "autogroup": + typ = types.TypeBool + + // autoedge and autogroup aren't part of the `MetaRes` interface, but we + // can merge them in here for simplicity in the public user interface... case MetaField: // FIXME: allow partial subsets of this struct, and in any order // FIXME: we might need an updated unification engine to do this - typ = types.NewType("struct{noop bool; retry int; delay int; poll int; limit float; burst int; sema []str}") + typ = types.NewType("struct{noop bool; retry int; delay int; poll int; limit float; burst int; sema []str; autoedge bool; autogroup bool}") default: return nil, fmt.Errorf("unknown property: %s", p)