-
Notifications
You must be signed in to change notification settings - Fork 20
/
functions.go
97 lines (84 loc) · 3.39 KB
/
functions.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package tosca_v2_0
import (
"github.com/tliron/kutil/ard"
"github.com/tliron/puccini/tosca"
"github.com/tliron/puccini/tosca/normal"
profile "github.com/tliron/puccini/tosca/profiles/implicit/v2_0"
"github.com/tliron/yamlkeys"
)
//
// Built-in functions and constraints
//
// [TOSCA-v2.0] @ ?
// [TOSCA-Simple-Profile-YAML-v1.3] @ 4
// [TOSCA-Simple-Profile-YAML-v1.2] @ 4
// [TOSCA-Simple-Profile-YAML-v1.1] @ 4
// [TOSCA-Simple-Profile-YAML-v1.0] @ 4
//
// [TOSCA-v2.0] @ ?
// [TOSCA-Simple-Profile-YAML-v1.3] @ 3.6.3
// [TOSCA-Simple-Profile-YAML-v1.2] @ 3.6.3
// [TOSCA-Simple-Profile-YAML-v1.1] @ 3.5.2
// [TOSCA-Simple-Profile-YAML-v1.0] @ 3.5.2
//
var FunctionScriptlets = map[string]string{
"tosca.function.concat": profile.Profile["/tosca/implicit/2.0/js/functions/concat.js"],
"tosca.function.join": profile.Profile["/tosca/implicit/2.0/js/functions/join.js"], // introduced in TOSCA 1.2
"tosca.function.token": profile.Profile["/tosca/implicit/2.0/js/functions/token.js"],
"tosca.function.get_input": profile.Profile["/tosca/implicit/2.0/js/functions/get_input.js"],
"tosca.function.get_property": profile.Profile["/tosca/implicit/2.0/js/functions/get_property.js"],
"tosca.function.get_attribute": profile.Profile["/tosca/implicit/2.0/js/functions/get_attribute.js"],
"tosca.function.get_operation_output": profile.Profile["/tosca/implicit/2.0/js/functions/get_operation_output.js"],
"tosca.function.get_nodes_of_type": profile.Profile["/tosca/implicit/2.0/js/functions/get_nodes_of_type.js"],
"tosca.function.get_artifact": profile.Profile["/tosca/implicit/2.0/js/functions/get_artifact.js"],
}
func ToFunctionCall(context *tosca.Context) bool {
if _, ok := context.Data.(*tosca.FunctionCall); ok {
// It's already a function call
return true
}
map_, ok := context.Data.(ard.Map)
if !ok || len(map_) != 1 {
return false
}
for key, data := range map_ {
name := yamlkeys.KeyString(key)
scriptletName := "tosca.function." + name
_, ok := context.ScriptletNamespace.Lookup(scriptletName)
if !ok {
// Not a function call, despite having the right data structure
return false
}
// Some functions accept a list of arguments, some just one argument
originalArguments, ok := data.(ard.List)
if !ok {
originalArguments = ard.List{data}
}
// Arguments may be function calls
arguments := make(ard.List, len(originalArguments))
for index, argument := range originalArguments {
argumentContext := context.Clone(argument)
ToFunctionCall(argumentContext)
arguments[index] = argumentContext.Data
}
context.Data = context.NewFunctionCall(scriptletName, arguments)
// We have only one key
return true
}
return false
}
func NormalizeFunctionCallArguments(functionCall *tosca.FunctionCall, context *tosca.Context) {
for index, argument := range functionCall.Arguments {
// Because the same constraint instance may be shared among more than one value, this
// func might be called more than once on the same arguments, so we must make sure not
// to normalize more than once
if _, ok := argument.(normal.Constrainable); !ok {
if value, ok := argument.(*Value); ok {
functionCall.Arguments[index] = value.Normalize()
} else {
// Note: this literal value will not have a $type field
functionCall.Arguments[index] = NewValue(context.ListChild(index, argument)).Normalize()
}
}
}
}