github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/environment/generate-wrappers/main.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "fmt" 6 "go/format" 7 "os" 8 "path/filepath" 9 "strings" 10 ) 11 12 const header = `// AUTO-GENERATED BY %s. DO NOT MODIFY. 13 14 package environment 15 16 import ( 17 "github.com/onflow/flow-go/fvm/errors" 18 "github.com/onflow/flow-go/fvm/storage/state" 19 "github.com/onflow/flow-go/module/trace" 20 ) 21 22 func parseRestricted( 23 txnState state.NestedTransactionPreparer, 24 spanName trace.SpanName, 25 ) error { 26 if txnState.IsParseRestricted() { 27 return errors.NewParseRestrictedModeInvalidAccessFailure(spanName) 28 } 29 30 return nil 31 } 32 33 // Utility functions used for checking unexpected operation access while 34 // cadence is parsing programs. 35 // 36 // The generic functions are of the form 37 // parseRestrict<x>Arg<y>Ret(txnState, spanName, callback, arg1, ..., argX) 38 // where the callback expects <x> number of arguments, and <y> number of 39 // return values (not counting error). If the callback expects no argument, 40 // <x>Arg is omitted, and similarly for return value.` 41 42 func generateWrapper(numArgs int, numRets int, content *FileContent) { 43 l := content.Line 44 push := content.PushIndent 45 pop := content.PopIndent 46 47 argsFuncSuffix := "" 48 if numArgs > 0 { 49 argsFuncSuffix = fmt.Sprintf("%dArg", numArgs) 50 } 51 52 argTypes := []string{} 53 argNames := []string{} 54 for i := 0; i < numArgs; i++ { 55 argTypes = append(argTypes, fmt.Sprintf("Arg%dT", i)) 56 argNames = append(argNames, fmt.Sprintf("arg%d", i)) 57 } 58 59 retsFuncSuffix := "" 60 if numRets > 0 { 61 retsFuncSuffix = fmt.Sprintf("%dRet", numRets) 62 } 63 64 retTypes := []string{} 65 retNames := []string{} 66 for i := 0; i < numRets; i++ { 67 retTypes = append(retTypes, fmt.Sprintf("Ret%dT", i)) 68 retNames = append(retNames, fmt.Sprintf("value%d", i)) 69 } 70 71 // 72 // Generate function signature 73 // 74 75 l("") 76 l("func parseRestrict%s%s[", argsFuncSuffix, retsFuncSuffix) 77 push() 78 79 for _, typeName := range append(argTypes, retTypes...) { 80 l("%s any,", typeName) 81 } 82 83 pop() 84 l("](") 85 push() 86 87 l("txnState state.NestedTransactionPreparer,") 88 l("spanName trace.SpanName,") 89 90 callbackRet := "error" 91 if numRets > 0 { 92 callbackRet = "(" + strings.Join(append(retTypes, "error"), ", ") + ")" 93 } 94 95 l("callback func(%s) %s,", strings.Join(argTypes, ", "), callbackRet) 96 97 for i, argType := range argTypes { 98 l("%s %s,", argNames[i], argType) 99 } 100 101 pop() 102 if numRets == 0 { 103 l(") error {") 104 } else { 105 l(") (") 106 push() 107 108 for _, retType := range retTypes { 109 l("%s,", retType) 110 } 111 l("error,") 112 113 pop() 114 l(") {") 115 } 116 push() 117 118 // 119 // Generate parse restrict check 120 // 121 122 l("err := parseRestricted(txnState, spanName)") 123 l("if err != nil {") 124 push() 125 126 for i, retType := range retTypes { 127 l("var %s %s", retNames[i], retType) 128 } 129 130 l("return %s", strings.Join(append(retNames, "err"), ", ")) 131 132 pop() 133 l("}") 134 135 // 136 // Generate callback invocation 137 // 138 139 l("") 140 l("return callback(%s)", strings.Join(argNames, ", ")) 141 142 pop() 143 l("}") 144 } 145 146 func main() { 147 if len(os.Args) != 2 { 148 fmt.Printf("USAGE: %s <output file>\n", filepath.Base(os.Args[0])) 149 os.Exit(1) 150 } 151 152 cmd := append([]string{filepath.Base(os.Args[0])}, os.Args[1:]...) 153 154 content := NewFileContent() 155 content.Section(header, strings.Join(cmd, " ")) 156 157 for numArgs := 1; numArgs < 4; numArgs++ { 158 generateWrapper(numArgs, 0, content) 159 } 160 161 for _, numArgs := range []int{0, 1, 2, 3, 4, 6} { 162 generateWrapper(numArgs, 1, content) 163 } 164 165 generateWrapper(1, 2, content) 166 167 buffer := &bytes.Buffer{} 168 _, err := content.WriteTo(buffer) 169 if err != nil { 170 panic(err) // This should never happen 171 } 172 173 source, formatErr := format.Source(buffer.Bytes()) 174 175 // NOTE: formatting error can occur if the generated code has syntax 176 // errors. We still want to write out the unformatted source for debugging 177 // purpose. 178 if formatErr != nil { 179 source = buffer.Bytes() 180 } 181 182 writeErr := os.WriteFile(os.Args[1], source, 0644) 183 if writeErr != nil { 184 panic(writeErr) 185 } 186 187 if formatErr != nil { 188 panic(formatErr) 189 } 190 }