func defaultNodeAdd(self Node, other types.FuObject) (types.FuObject, error) { otherlist := other.List() values := make([]types.FuObject, 0, 1+len(otherlist)) values = append(values, self) values = append(values, otherlist...) return types.MakeFuList(values...), nil }
func (self *ListNode) Add(other types.FuObject) (types.FuObject, error) { values := self.List() otherlist := other.List() result := make([]types.FuObject, len(values)+len(otherlist)) for i, obj := range values { result[i] = obj } j := len(values) for i, obj := range otherlist { if _, ok := obj.(Node); !ok { return types.UnsupportedAdd( self, other, "second operand contains "+obj.Typename()) } result[j+i] = obj } return newListNode(result...), nil }
func Test_BuildRule_setLocals(t *testing.T) { targets := []dag.Node{dag.NewStubNode("foo")} sources := []dag.Node{dag.NewStubNode("bar"), dag.NewStubNode("qux")} ns := types.NewValueMap() rule := NewBuildRule(nil, targets, sources) rule.setLocals(ns) var val types.FuObject var ok bool val, ok = ns.Lookup("whatever") assert.False(t, ok) val, ok = ns.Lookup("target") assert.False(t, ok) val, ok = ns.Lookup("targets") assert.False(t, ok) val, ok = ns.Lookup("TARGET") assert.True(t, ok) assert.Equal(t, "foo", val.ValueString()) assert.Equal(t, "foo", val.(*dag.StubNode).Name()) val, ok = ns.Lookup("SOURCE") assert.True(t, ok) assert.Equal(t, "bar", val.ValueString()) assert.Equal(t, "bar", val.(*dag.StubNode).Name()) val, ok = ns.Lookup("TARGETS") assert.True(t, ok) assert.Equal(t, 1, len(val.List())) assert.Equal(t, `["foo"]`, val.String()) val, ok = ns.Lookup("SOURCES") assert.True(t, ok) assert.Equal(t, 2, len(val.List())) assert.Equal(t, `["bar", "qux"]`, val.String()) }
// Convert a single FuObject (possibly a FuList) to a list of Nodes and // add them to the DAG. func (self *Runtime) nodify(values types.FuObject) []dag.Node { // Blecchh: specially handling every type here limits the // extensibility of the type system. But I don't want each type to // know how it becomes a node, because then the 'types' package // depends on 'dag', which seems backwards to me. Hmmmm. var result []dag.Node switch values := values.(type) { case types.FuString: result = []dag.Node{dag.MakeFileNode(self.dag, values.ValueString())} case types.FuList: result = make([]dag.Node, 0, len(values.List())) for _, val := range values.List() { result = append(result, self.nodify(val)...) } case *dag.ListNode: result = values.Nodes() for i, node := range result { result[i] = self.dag.AddNode(node) } case dag.Node: result = []dag.Node{self.dag.AddNode(values)} } return result }