func fn_build(argsource types.ArgSource) (types.FuObject, []error) { rt := argsource.(RuntimeArgs).runtime args := argsource.Args() targets := rt.nodify(args[0]) sources := rt.nodify(args[1]) actionobj := args[2] fmt.Printf( "fn_build():\n"+ " targets: %T %v\n"+ " sources: %T %v\n"+ " actions: %T %v\n", targets, targets, sources, sources, actionobj, actionobj) var errs []error var action Action if actionstr, ok := actionobj.(types.FuString); ok { action = NewCommandAction(actionstr) } else { errs = append(errs, errors.New("build(): only command strings supported as actions right now, sorry")) } rule := NewBuildRule(rt, targets, sources) rule.action = action return rule, errs }
func meth_FinderNode_prune(args types.ArgSource) (types.FuObject, []error) { robj := args.Receiver().(*FinderNode) for _, arg := range args.Args() { robj.Prune(arg.String()) } return nil, nil }
func logFunctionCall(callable types.FuCallable, args types.ArgSource) { argstrings := make([]string, len(args.Args())) for i, arg := range args.Args() { argstrings[i] = arg.String() } log.Info("%s(%s)", callable.Name(), strings.Join(argstrings, ", ")) }
func fn_remove(argsource types.ArgSource) (types.FuObject, []error) { errs := make([]error, 0) for _, name := range argsource.Args() { err := os.RemoveAll(name.ValueString()) if err != nil { errs = append(errs, err) } } return nil, errs }
func fn_println(argsource types.ArgSource) (types.FuObject, []error) { for i, val := range argsource.Args() { if i > 0 { os.Stdout.WriteString(" ") } var s string if val == nil { s = "(nil)" } else { s = val.ValueString() } _, err := os.Stdout.WriteString(s) if err != nil { // this shouldn't happen, so bail immediately return nil, []error{err} } } os.Stdout.WriteString("\n") return nil, nil }
func (self PythonCallable) callPython(argsource types.ArgSource) (types.FuObject, []error) { args := argsource.Args() // build a slice of strings, which will then be converted to // Python strings in C (this way we only copy the bytes once, at // the cost of C code knowing the internals of Go slices and // strings) sargs := make([]string, len(args)) for i, arg := range args { switch arg.(type) { case types.FuString: sargs[i] = arg.ValueString() default: err := fmt.Errorf( "bad argument type: all arguments must be strings, "+ "but argument %d is %s %s", i+1, arg.Typename(), arg.String()) return nil, []error{err} } } var cerror *C.char var cresult *C.char var result types.FuObject cresult = C.call_python(self.callable, unsafe.Pointer(&sargs), &cerror) if cerror != nil { err := C.GoString(cerror) return nil, []error{errors.New(err)} } if cresult != nil { result = types.MakeFuString(C.GoString(cresult)) } return result, nil }
func fn_ActionNode(argsource types.ArgSource) (types.FuObject, []error) { basename := argsource.Args()[0].ValueString() graph := argsource.(RuntimeArgs).Graph() return dag.MakeActionNode(graph, basename+":action"), nil }
func fn_FileNode(argsource types.ArgSource) (types.FuObject, []error) { name := argsource.Args()[0].ValueString() graph := argsource.(RuntimeArgs).Graph() return dag.MakeFileNode(graph, name), nil }
func Test_evaluateCall_method(t *testing.T) { // construct AST for "a.b.c(x)" astargs := []dsl.ASTExpression{dsl.NewASTName("x")} astcall := dsl.NewASTFunctionCall( dsl.NewASTSelection( dsl.NewASTSelection(dsl.NewASTName("a"), "b"), "c"), astargs) // make sure a is an object with attributes, and b is one of them // (N.B. having FileNodes be attributes of one another is weird // and would never happen in a real Fubsy script, but it's a // convenient way to setup this method call) aobj := dag.NewFileNode("a.txt") bobj := dag.NewFileNode("b.txt") aobj.ValueMap = types.NewValueMap() aobj.Assign("b", bobj) // make sure a.b.c is a method calls := make([]string, 0) // list of function names var meth_c types.FuCode meth_c = func(argsource types.ArgSource) (types.FuObject, []error) { args := argsource.Args() if len(args) != 1 { panic("c() called with wrong number of args") } calls = append(calls, "c") robj := argsource.Receiver() return nil, []error{ fmt.Errorf("c failed: receiver: %s %v, arg: %s %v", robj.Typename(), robj, args[0].Typename(), args[0])} } bobj.ValueMap = types.NewValueMap() bobj.Assign("c", types.NewFixedFunction("c", 1, meth_c)) rt := minimalRuntime() ns := rt.Namespace() ns.Assign("a", aobj) ns.Assign("x", types.MakeFuString("hello")) // what the hell, let's test the precall feature too var precalledCallable types.FuCallable var precalledArgs types.ArgSource precall := func(callable types.FuCallable, argsource types.ArgSource) { precalledCallable = callable precalledArgs = argsource } callable, args, errs := rt.prepareCall(astcall) assert.Equal(t, "c", callable.(*types.FuFunction).Name()) assert.True(t, args.Receiver() == bobj) assert.Equal(t, 0, len(errs)) result, errs := rt.evaluateCall(callable, args, precall) assert.Equal(t, precalledCallable, callable) assert.Equal(t, precalledArgs.Args(), types.MakeStringList("hello").List()) assert.Nil(t, result) if len(errs) == 1 { assert.Equal(t, "c failed: receiver: FileNode \"b.txt\", arg: string \"hello\"", errs[0].Error()) } else { t.Errorf("expected exactly 1 error, but got: %v", errs) } }