/
semantic.go
95 lines (87 loc) · 2.52 KB
/
semantic.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
package transforms
import (
"sort"
"github.com/anz-bank/sysl/pkg/eval"
"github.com/anz-bank/sysl/pkg/sysl"
"github.com/anz-bank/sysl/pkg/syslutil"
)
type semantic struct {
base
filenames *sysl.View
}
// valid args are
// app <: sysl.App and
// type <: sysl.Type
// typeName <: string
// module <: sysl.Module
func (t *semantic) Apply(mod *sysl.Module, appNames ...string) map[string]*sysl.Value {
output := map[string]*sysl.Value{}
for _, name := range appNames {
filenamesData := createScope(t.filenames, mod, mod.Apps[name])
outputData := createScope(t.view, mod, mod.Apps[name])
var result, filenames *sysl.Value
if tp := outputData.tp; tp != nil {
types := mod.Apps[name].Types
filenames = eval.MakeValueList()
result = eval.MakeValueList()
var tNames []string
for tName := range types {
tNames = append(tNames, tName)
}
sort.Strings(tNames)
for _, tName := range tNames {
outputData.scope[tp.name] = eval.MakeValueString(tName)
outputData.scope[tp.t] = eval.TypeToValue(types[tName])
eval.AppendItemToValueList(filenames.GetList(), t.eval(t.filenames, outputData.scope))
eval.AppendItemToValueList(result.GetList(), t.eval(t.view, outputData.scope))
}
} else {
result = t.eval(t.view, outputData.scope)
filenames = t.eval(t.filenames, filenamesData.scope)
}
// filename should either be a map with a single key:"filename", or a list of the same length as the result value
switch {
case filenames.GetMap() != nil:
filename := filenames.GetMap().Items["filename"].GetS()
output[filename] = result
case filenames.GetList() != nil && result.GetList() != nil:
fileValues := filenames.GetList().Value
for i, v := range result.GetList().Value {
filename := fileValues[i].GetMap().Items["filename"].GetS()
output[filename] = v
}
}
}
return output
}
type typeParams struct {
t string
name string
}
type transformData struct {
scope eval.Scope
tp *typeParams
}
func createScope(view *sysl.View, mod *sysl.Module, app *sysl.Application) transformData {
res := transformData{
scope: eval.Scope{},
}
tp := typeParams{}
for _, param := range view.Param {
_, detail := syslutil.GetTypeDetail(param.Type)
switch detail {
case "sysl.App", "sysl.Application":
res.scope.AddApp(param.Name, app)
case "sysl.Module":
res.scope.AddModule(param.Name, mod)
case "sysl.Type":
tp.t = param.Name
case "STRING": // Assuming it must be the type name
tp.name = param.Name
}
}
if tp.name != "" && tp.t != "" {
res.tp = &tp
}
return res
}