feat: Improve DSL function UX #1295

This commit is contained in:
forgedhallpass 2021-11-26 17:14:25 +02:00
parent dfe284664c
commit c61ec5f673
2 changed files with 353 additions and 344 deletions

View File

@ -15,6 +15,7 @@ import (
"math/rand" "math/rand"
"net/url" "net/url"
"regexp" "regexp"
"strconv"
"strings" "strings"
"time" "time"
@ -28,104 +29,65 @@ import (
const ( const (
numbers = "1234567890" numbers = "1234567890"
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
withCutSetArgsSize = 2
withBaseRandArgsSize = 3
withMaxRandArgsSize = withCutSetArgsSize
) )
var ErrDSLArguments = errors.New("invalid arguments provided to dsl") var invalidDslFunctionError = errors.New("invalid DSL function signature")
var invalidDslFunctionMessageTemplate = "correct method signature '%s'. %w"
var functions = map[string]govaluate.ExpressionFunction{ var dslFunctions map[string]dslFunction
"len": func(args ...interface{}) (interface{}, error) {
if len(args) != 1 { type dslFunction struct {
return nil, ErrDSLArguments signature string
} expressFunc govaluate.ExpressionFunction
}
func init() {
tempDslFunctions := map[string]func(string) dslFunction{
"len": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
length := len(types.ToString(args[0])) length := len(types.ToString(args[0]))
return float64(length), nil return float64(length), nil
}, }),
"toupper": func(args ...interface{}) (interface{}, error) { "toupper": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
if len(args) != 1 {
return nil, ErrDSLArguments
}
return strings.ToUpper(types.ToString(args[0])), nil return strings.ToUpper(types.ToString(args[0])), nil
}, }),
"tolower": func(args ...interface{}) (interface{}, error) { "tolower": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
if len(args) != 1 {
return nil, ErrDSLArguments
}
return strings.ToLower(types.ToString(args[0])), nil return strings.ToLower(types.ToString(args[0])), nil
}, }),
"replace": func(args ...interface{}) (interface{}, error) { "replace": makeDslFunction(3, func(args ...interface{}) (interface{}, error) {
if len(args) != 3 {
return nil, ErrDSLArguments
}
return strings.ReplaceAll(types.ToString(args[0]), types.ToString(args[1]), types.ToString(args[2])), nil return strings.ReplaceAll(types.ToString(args[0]), types.ToString(args[1]), types.ToString(args[2])), nil
}, }),
"replace_regex": func(args ...interface{}) (interface{}, error) { "replace_regex": makeDslFunction(3, func(args ...interface{}) (interface{}, error) {
if len(args) != 3 {
return nil, ErrDSLArguments
}
compiled, err := regexp.Compile(types.ToString(args[1])) compiled, err := regexp.Compile(types.ToString(args[1]))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return compiled.ReplaceAllString(types.ToString(args[0]), types.ToString(args[2])), nil return compiled.ReplaceAllString(types.ToString(args[0]), types.ToString(args[2])), nil
}, }),
"trim": func(args ...interface{}) (interface{}, error) { "trim": makeDslFunction(2, func(args ...interface{}) (interface{}, error) {
if len(args) != 2 {
return nil, ErrDSLArguments
}
return strings.Trim(types.ToString(args[0]), types.ToString(args[1])), nil return strings.Trim(types.ToString(args[0]), types.ToString(args[1])), nil
}, }),
"trimleft": func(args ...interface{}) (interface{}, error) { "trimleft": makeDslFunction(2, func(args ...interface{}) (interface{}, error) {
if len(args) != 2 {
return nil, ErrDSLArguments
}
return strings.TrimLeft(types.ToString(args[0]), types.ToString(args[1])), nil return strings.TrimLeft(types.ToString(args[0]), types.ToString(args[1])), nil
}, }),
"trimright": func(args ...interface{}) (interface{}, error) { "trimright": makeDslFunction(2, func(args ...interface{}) (interface{}, error) {
if len(args) != 2 {
return nil, ErrDSLArguments
}
return strings.TrimRight(types.ToString(args[0]), types.ToString(args[1])), nil return strings.TrimRight(types.ToString(args[0]), types.ToString(args[1])), nil
}, }),
"trimspace": func(args ...interface{}) (interface{}, error) { "trimspace": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
if len(args) != 1 {
return nil, ErrDSLArguments
}
return strings.TrimSpace(types.ToString(args[0])), nil return strings.TrimSpace(types.ToString(args[0])), nil
}, }),
"trimprefix": func(args ...interface{}) (interface{}, error) { "trimprefix": makeDslFunction(2, func(args ...interface{}) (interface{}, error) {
if len(args) != 2 {
return nil, ErrDSLArguments
}
return strings.TrimPrefix(types.ToString(args[0]), types.ToString(args[1])), nil return strings.TrimPrefix(types.ToString(args[0]), types.ToString(args[1])), nil
}, }),
"trimsuffix": func(args ...interface{}) (interface{}, error) { "trimsuffix": makeDslFunction(2, func(args ...interface{}) (interface{}, error) {
if len(args) != 2 {
return nil, ErrDSLArguments
}
return strings.TrimSuffix(types.ToString(args[0]), types.ToString(args[1])), nil return strings.TrimSuffix(types.ToString(args[0]), types.ToString(args[1])), nil
}, }),
"reverse": func(args ...interface{}) (interface{}, error) { "reverse": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
if len(args) != 1 {
return nil, ErrDSLArguments
}
return reverseString(types.ToString(args[0])), nil return reverseString(types.ToString(args[0])), nil
}, }),
// encoding "base64": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
"base64": func(args ...interface{}) (interface{}, error) { return base64.StdEncoding.EncodeToString([]byte(types.ToString(args[0]))), nil
if len(args) != 1 { }),
return nil, ErrDSLArguments "gzip": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
}
sEnc := base64.StdEncoding.EncodeToString([]byte(types.ToString(args[0])))
return sEnc, nil
},
"gzip": func(args ...interface{}) (interface{}, error) {
if len(args) != 1 {
return nil, ErrDSLArguments
}
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
writer := gzip.NewWriter(buffer) writer := gzip.NewWriter(buffer)
if _, err := writer.Write([]byte(args[0].(string))); err != nil { if _, err := writer.Write([]byte(args[0].(string))); err != nil {
@ -134,261 +96,309 @@ var functions = map[string]govaluate.ExpressionFunction{
_ = writer.Close() _ = writer.Close()
return buffer.String(), nil return buffer.String(), nil
}, }),
// python encodes to base64 with lines of 76 bytes terminated by new line "\n" "base64_py": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
"base64_py": func(args ...interface{}) (interface{}, error) { stdBase64 := base64.StdEncoding.EncodeToString([]byte(types.ToString(args[0])))
if len(args) != 1 { return deserialization.InsertInto(stdBase64, 76, '\n'), nil
return nil, ErrDSLArguments }),
} "base64_decode": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
sEnc := base64.StdEncoding.EncodeToString([]byte(types.ToString(args[0])))
return deserialization.InsertInto(sEnc, 76, '\n'), nil
},
"base64_decode": func(args ...interface{}) (interface{}, error) {
if len(args) != 1 {
return nil, ErrDSLArguments
}
return base64.StdEncoding.DecodeString(types.ToString(args[0])) return base64.StdEncoding.DecodeString(types.ToString(args[0]))
}, }),
"url_encode": func(args ...interface{}) (interface{}, error) { "url_encode": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
if len(args) != 1 {
return nil, ErrDSLArguments
}
return url.QueryEscape(types.ToString(args[0])), nil return url.QueryEscape(types.ToString(args[0])), nil
}, }),
"url_decode": func(args ...interface{}) (interface{}, error) { "url_decode": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
if len(args) != 1 {
return nil, ErrDSLArguments
}
return url.QueryUnescape(types.ToString(args[0])) return url.QueryUnescape(types.ToString(args[0]))
}, }),
"hex_encode": func(args ...interface{}) (interface{}, error) { "hex_encode": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
if len(args) != 1 {
return nil, ErrDSLArguments
}
return hex.EncodeToString([]byte(types.ToString(args[0]))), nil return hex.EncodeToString([]byte(types.ToString(args[0]))), nil
}, }),
"hex_decode": func(args ...interface{}) (interface{}, error) { "hex_decode": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
if len(args) != 1 { decodeString, err := hex.DecodeString(types.ToString(args[0]))
return nil, ErrDSLArguments return decodeString, err
} }),
hx, _ := hex.DecodeString(types.ToString(args[0])) "html_escape": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
return string(hx), nil
},
"html_escape": func(args ...interface{}) (interface{}, error) {
if len(args) != 1 {
return nil, ErrDSLArguments
}
return html.EscapeString(types.ToString(args[0])), nil return html.EscapeString(types.ToString(args[0])), nil
}, }),
"html_unescape": func(args ...interface{}) (interface{}, error) { "html_unescape": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
if len(args) != 1 {
return nil, ErrDSLArguments
}
return html.UnescapeString(types.ToString(args[0])), nil return html.UnescapeString(types.ToString(args[0])), nil
}, }),
// hashing "md5": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
"md5": func(args ...interface{}) (interface{}, error) {
if len(args) != 1 {
return nil, ErrDSLArguments
}
hash := md5.Sum([]byte(types.ToString(args[0]))) hash := md5.Sum([]byte(types.ToString(args[0])))
return hex.EncodeToString(hash[:]), nil return hex.EncodeToString(hash[:]), nil
}, }),
"sha256": func(args ...interface{}) (interface{}, error) { "sha256": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
if len(args) != 1 { hash := sha256.New()
return nil, ErrDSLArguments if _, err := hash.Write([]byte(types.ToString(args[0]))); err != nil {
}
h := sha256.New()
if _, err := h.Write([]byte(types.ToString(args[0]))); err != nil {
return nil, err return nil, err
} }
return hex.EncodeToString(h.Sum(nil)), nil return hex.EncodeToString(hash.Sum(nil)), nil
}, }),
"sha1": func(args ...interface{}) (interface{}, error) { "sha1": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
if len(args) != 1 { hash := sha1.New()
return nil, ErrDSLArguments if _, err := hash.Write([]byte(types.ToString(args[0]))); err != nil {
}
h := sha1.New()
if _, err := h.Write([]byte(types.ToString(args[0]))); err != nil {
return nil, err return nil, err
} }
return hex.EncodeToString(h.Sum(nil)), nil return hex.EncodeToString(hash.Sum(nil)), nil
}, }),
"mmh3": func(args ...interface{}) (interface{}, error) { "mmh3": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
if len(args) != 1 {
return nil, ErrDSLArguments
}
return fmt.Sprintf("%d", int32(murmur3.Sum32WithSeed([]byte(types.ToString(args[0])), 0))), nil return fmt.Sprintf("%d", int32(murmur3.Sum32WithSeed([]byte(types.ToString(args[0])), 0))), nil
}, }),
// search "contains": makeDslFunction(2, func(args ...interface{}) (interface{}, error) {
"contains": func(args ...interface{}) (interface{}, error) {
if len(args) != 2 {
return nil, ErrDSLArguments
}
return strings.Contains(types.ToString(args[0]), types.ToString(args[1])), nil return strings.Contains(types.ToString(args[0]), types.ToString(args[1])), nil
}, }),
"regex": func(args ...interface{}) (interface{}, error) { "regex": makeDslFunction(2, func(args ...interface{}) (interface{}, error) {
if len(args) != 2 {
return nil, ErrDSLArguments
}
compiled, err := regexp.Compile(types.ToString(args[0])) compiled, err := regexp.Compile(types.ToString(args[0]))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return compiled.MatchString(types.ToString(args[1])), nil return compiled.MatchString(types.ToString(args[1])), nil
}, }),
// random generators "rand_char": makeDslWithOptionalArgsFunction(
"rand_char": func(args ...interface{}) (interface{}, error) { "(optionalCharSet, optionalBachChars) string",
if len(args) != 2 { func(args ...interface{}) (interface{}, error) {
return nil, ErrDSLArguments charSet := letters + numbers
} badChars := ""
chars := letters + numbers
bad := ""
if len(args) >= 1 {
chars = types.ToString(args[0])
}
if len(args) >= withCutSetArgsSize {
bad = types.ToString(args[1])
}
chars = trimAll(chars, bad)
return chars[rand.Intn(len(chars))], nil
},
"rand_base": func(args ...interface{}) (interface{}, error) {
if len(args) != 3 {
return nil, ErrDSLArguments
}
l := 0
bad := ""
base := letters + numbers
if len(args) >= 1 { argSize := len(args)
l = int(args[0].(float64)) if argSize != 1 && argSize != 2 {
return nil, invalidDslFunctionError
} }
if len(args) >= withCutSetArgsSize {
bad = types.ToString(args[1])
}
if len(args) >= withBaseRandArgsSize {
base = types.ToString(args[2])
}
base = trimAll(base, bad)
return randSeq(base, l), nil
},
"rand_text_alphanumeric": func(args ...interface{}) (interface{}, error) {
if len(args) != 2 {
return nil, ErrDSLArguments
}
l := 0
bad := ""
chars := letters + numbers
if len(args) >= 1 { if argSize >= 1 {
l = int(args[0].(float64)) charSet = types.ToString(args[0])
} }
if len(args) >= withCutSetArgsSize { if argSize == 2 {
bad = types.ToString(args[1]) badChars = types.ToString(args[1])
} }
chars = trimAll(chars, bad)
return randSeq(chars, l), nil
},
"rand_text_alpha": func(args ...interface{}) (interface{}, error) {
if len(args) != 2 {
return nil, ErrDSLArguments
}
l := 0
bad := ""
chars := letters
if len(args) >= 1 { charSet = trimAll(charSet, badChars)
l = int(args[0].(float64)) return charSet[rand.Intn(len(charSet))], nil
}
if len(args) >= withCutSetArgsSize {
bad = types.ToString(args[1])
}
chars = trimAll(chars, bad)
return randSeq(chars, l), nil
}, },
"rand_text_numeric": func(args ...interface{}) (interface{}, error) { ),
if len(args) != 2 { "rand_base": makeDslWithOptionalArgsFunction(
return nil, ErrDSLArguments "(length, optionalCharSet, optionalBadChars) string",
} func(args ...interface{}) (interface{}, error) {
l := 0 var length int
bad := "" badChars := ""
chars := numbers charSet := letters + numbers
if len(args) >= 1 { argSize := len(args)
l = int(args[0].(float64)) if argSize < 1 || argSize > 3 {
return nil, invalidDslFunctionError
} }
if len(args) >= withCutSetArgsSize {
bad = types.ToString(args[1]) length = int(args[0].(float64))
if argSize >= 2 {
badChars = types.ToString(args[1])
} }
chars = trimAll(chars, bad) if argSize == 3 {
return randSeq(chars, l), nil charSet = types.ToString(args[2])
}
charSet = trimAll(charSet, badChars)
return randSeq(charSet, length), nil
}, },
"rand_int": func(args ...interface{}) (interface{}, error) { ),
if len(args) != 2 { "rand_text_alphanumeric": makeDslWithOptionalArgsFunction(
return nil, ErrDSLArguments "(length, optionalBadChars) string",
func(args ...interface{}) (interface{}, error) {
length := 0
badChars := ""
argSize := len(args)
if argSize != 1 && argSize != 2 {
return nil, invalidDslFunctionError
} }
length = int(args[0].(float64))
if argSize == 2 {
badChars = types.ToString(args[1])
}
chars := trimAll(letters+numbers, badChars)
return randSeq(chars, length), nil
},
),
"rand_text_alpha": makeDslWithOptionalArgsFunction(
"(length, optionalBadChars) string",
func(args ...interface{}) (interface{}, error) {
var length int
badChars := ""
argSize := len(args)
if argSize != 1 && argSize != 2 {
return nil, invalidDslFunctionError
}
length = int(args[0].(float64))
if argSize == 2 {
badChars = types.ToString(args[1])
}
chars := trimAll(letters, badChars)
return randSeq(chars, length), nil
},
),
"rand_text_numeric": makeDslWithOptionalArgsFunction(
"(size int, optionalBadNumbers string) string",
func(args ...interface{}) (interface{}, error) {
argSize := len(args)
if argSize != 1 && argSize != 2 {
return nil, invalidDslFunctionError
}
length := args[0].(int)
var badNumbers = ""
if argSize == 2 {
badNumbers = types.ToString(args[1])
}
chars := trimAll(numbers, badNumbers)
return randSeq(chars, length), nil
},
),
"rand_int": makeDslWithOptionalArgsFunction(
"(optionalMin, optionalMax int) int",
func(args ...interface{}) (interface{}, error) {
argSize := len(args)
if argSize >= 2 {
return nil, invalidDslFunctionError
}
min := 0 min := 0
max := math.MaxInt32 max := math.MaxInt32
if len(args) >= 1 { if argSize >= 1 {
min = int(args[0].(float64)) min = args[0].(int)
} }
if len(args) >= withMaxRandArgsSize { if argSize == 2 {
max = int(args[1].(float64)) max = args[1].(int)
} }
return rand.Intn(max-min) + min, nil return rand.Intn(max-min) + min, nil
}, },
"unixtime": func(args ...interface{}) (interface{}, error) { ),
"generate_java_gadget": makeDslFunction(3, func(args ...interface{}) (interface{}, error) {
gadget := args[0].(string)
cmd := args[1].(string)
encoding := args[2].(string)
data := deserialization.GenerateJavaGadget(gadget, cmd, encoding)
return data, nil
}),
"unixtime": makeDslWithOptionalArgsFunction(
"(optionalSeconds uint) float64",
func(args ...interface{}) (interface{}, error) {
seconds := 0 seconds := 0
if len(args) >= 1 {
seconds = int(args[0].(float64)) argSize := len(args)
if argSize != 0 && argSize != 1 {
return nil, invalidDslFunctionError
} else if argSize == 1 {
seconds = int(args[0].(uint))
} }
now := time.Now()
offset := now.Add(time.Duration(seconds) * time.Second) offset := time.Now().Add(time.Duration(seconds) * time.Second)
return float64(offset.Unix()), nil return float64(offset.Unix()), nil
}, },
// Time Functions ),
"waitfor": func(args ...interface{}) (interface{}, error) { "waitfor": makeDslWithOptionalArgsFunction(
"(seconds uint)",
func(args ...interface{}) (interface{}, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, ErrDSLArguments return nil, invalidDslFunctionError
} }
seconds := args[0].(float64) seconds := args[0].(uint)
time.Sleep(time.Duration(seconds) * time.Second) time.Sleep(time.Duration(seconds) * time.Second)
return true, nil return true, nil
}, },
// deserialization Functions ),
"generate_java_gadget": func(args ...interface{}) (interface{}, error) { "print_debug": makeDslWithOptionalArgsFunction(
if len(args) != 3 { "(args ...interface{})",
return nil, ErrDSLArguments func(args ...interface{}) (interface{}, error) {
if len(args) < 1 {
return nil, invalidDslFunctionError
} }
gadget := args[0].(string)
cmd := args[1].(string)
var encoding string
if len(args) > 2 {
encoding = args[2].(string)
}
data := deserialization.GenerateJavaGadget(gadget, cmd, encoding)
return data, nil
},
// for debug purposes
"print_debug": func(args ...interface{}) (interface{}, error) {
gologger.Info().Msgf("print_debug value: %s", fmt.Sprint(args)) gologger.Info().Msgf("print_debug value: %s", fmt.Sprint(args))
return true, nil return true, nil
}, },
),
"time_now": makeDslWithOptionalArgsFunction(
"() float64",
func(args ...interface{}) (interface{}, error) {
if len(args) == 0 {
return nil, invalidDslFunctionError
}
return float64(time.Now().Unix()), nil
},
),
}
dslFunctions = make(map[string]dslFunction, len(tempDslFunctions))
for funcName, dslFunc := range tempDslFunctions {
dslFunctions[funcName] = dslFunc(funcName)
}
}
func createSignaturePart(numberOfParameters int) string {
params := make([]string, 0, numberOfParameters)
for i := 1; i <= numberOfParameters; i++ {
params = append(params, "arg"+strconv.Itoa(i))
}
return fmt.Sprintf("(%s interface{}) interface{}", strings.Join(params, ", "))
}
func makeDslWithOptionalArgsFunction(signaturePart string, dslFunctionLogic govaluate.ExpressionFunction) func(functionName string) dslFunction {
return func(functionName string) dslFunction {
return dslFunction{
functionName + signaturePart,
dslFunctionLogic,
}
}
}
func makeDslFunction(numberOfParameters int, dslFunctionLogic govaluate.ExpressionFunction) func(functionName string) dslFunction {
return func(functionName string) dslFunction {
signature := functionName + createSignaturePart(numberOfParameters)
return dslFunction{
signature,
func(args ...interface{}) (interface{}, error) {
if len(args) != numberOfParameters {
return nil, fmt.Errorf(invalidDslFunctionMessageTemplate, signature, invalidDslFunctionError)
}
return dslFunctionLogic(args...)
},
}
}
} }
// HelperFunctions returns the dsl helper functions // HelperFunctions returns the dsl helper functions
func HelperFunctions() map[string]govaluate.ExpressionFunction { func HelperFunctions() map[string]govaluate.ExpressionFunction {
return functions helperFunctions := make(map[string]govaluate.ExpressionFunction, len(dslFunctions))
for functionName, dslFunction := range dslFunctions {
helperFunctions[functionName] = dslFunction.expressFunc
}
return helperFunctions
}
func GetDslFunctionSignatures() []string {
result := make([]string, 0, len(dslFunctions))
for _, dslFunction := range dslFunctions {
result = append(result, dslFunction.signature)
}
return result
} }
// AddHelperFunction allows creation of additional helper functions to be supported with templates // AddHelperFunction allows creation of additional helper functions to be supported with templates
func AddHelperFunction(key string, value func(args ...interface{}) (interface{}, error)) error { func AddHelperFunction(key string, value func(args ...interface{}) (interface{}, error)) error {
if _, ok := functions[key]; !ok { if _, ok := dslFunctions[key]; !ok {
functions[key] = value dslFunction := dslFunctions[key]
dslFunction.signature = "(args ...interface{}) interface{}"
dslFunction.expressFunc = value
return nil return nil
} }
return errors.New("duplicate helper function key defined") return errors.New("duplicate helper function key defined")

View File

@ -36,7 +36,6 @@ func (m *Matcher) CompileMatchers() error {
m.Part = "body" m.Part = "body"
} }
// Compile the regexes // Compile the regexes
for _, regex := range m.Regex { for _, regex := range m.Regex {
compiled, err := regexp.Compile(regex) compiled, err := regexp.Compile(regex)
@ -59,7 +58,7 @@ func (m *Matcher) CompileMatchers() error {
for _, expr := range m.DSL { for _, expr := range m.DSL {
compiled, err := govaluate.NewEvaluableExpressionWithFunctions(expr, dsl.HelperFunctions()) compiled, err := govaluate.NewEvaluableExpressionWithFunctions(expr, dsl.HelperFunctions())
if err != nil { if err != nil {
return fmt.Errorf("could not compile dsl: %s", expr) return fmt.Errorf("could not compile dsl: %s. %w", expr, err)
} }
m.dslCompiled = append(m.dslCompiled, compiled) m.dslCompiled = append(m.dslCompiled, compiled)
} }