From 03fe7d33b04b629ef7732ca861ab032a4b52c297 Mon Sep 17 00:00:00 2001 From: Martino Ferrari Date: Wed, 28 Jan 2026 17:50:49 +0100 Subject: [PATCH] added variables and producer check --- cmd/mdt/main.go | 109 +++++++++++++++++++---------- docs/CONFIGURATION_GUIDE.md | 26 +++++++ internal/builder/builder.go | 69 +++++++++++++++++- internal/index/index.go | 34 +++++++-- internal/lsp/server.go | 6 ++ internal/parser/ast.go | 18 +++++ internal/parser/lexer.go | 19 ++++- internal/parser/parser.go | 55 +++++++++++++++ internal/validator/validator.go | 119 ++++++++++++++++++++++++++++++++ test/builder_multifile_test.go | 2 +- test/integration_test.go | 4 +- 11 files changed, 413 insertions(+), 48 deletions(-) diff --git a/cmd/mdt/main.go b/cmd/mdt/main.go index 43ed4ed..dd89aa6 100644 --- a/cmd/mdt/main.go +++ b/cmd/mdt/main.go @@ -3,6 +3,8 @@ package main import ( "bytes" "os" + "path/filepath" + "strings" "github.com/marte-community/marte-dev-tools/internal/builder" "github.com/marte-community/marte-dev-tools/internal/formatter" @@ -17,10 +19,6 @@ func main() { if len(os.Args) < 2 { logger.Println("Usage: mdt [arguments]") logger.Println("Commands: lsp, build, check, fmt, init") - logger.Println(" build [-o output_file] ") - logger.Println(" check ") - logger.Println(" fmt ") - logger.Println(" init ") os.Exit(1) } @@ -47,46 +45,47 @@ func runLSP() { } func runBuild(args []string) { - if len(args) < 1 { - logger.Println("Usage: mdt build [-o output_file] ") - os.Exit(1) - } - - var outputFilePath string - var inputFiles []string + files := []string{} + overrides := make(map[string]string) + outputFile := "" for i := 0; i < len(args); i++ { - if args[i] == "-o" { + arg := args[i] + if strings.HasPrefix(arg, "-v") { + pair := arg[2:] + parts := strings.SplitN(pair, "=", 2) + if len(parts) == 2 { + overrides[parts[0]] = parts[1] + } + } else if arg == "-o" { if i+1 < len(args) { - outputFilePath = args[i+1] + outputFile = args[i+1] i++ - } else { - logger.Println("Error: -o requires a file path") - os.Exit(1) } } else { - inputFiles = append(inputFiles, args[i]) + files = append(files, arg) } } - if len(inputFiles) < 1 { - logger.Println("Usage: mdt build [-o output_file] ") + if len(files) < 1 { + logger.Println("Usage: mdt build [-o output] [-vVAR=VAL] ") os.Exit(1) } - output := os.Stdout - if outputFilePath != "" { - f, err := os.Create(outputFilePath) + b := builder.NewBuilder(files, overrides) + + var out *os.File = os.Stdout + if outputFile != "" { + f, err := os.Create(outputFile) if err != nil { - logger.Printf("Error creating output file %s: %v\n", outputFilePath, err) + logger.Printf("Error creating output file: %v\n", err) os.Exit(1) } defer f.Close() - output = f + out = f } - b := builder.NewBuilder(inputFiles) - err := b.Build(output) + err := b.Build(out) if err != nil { logger.Printf("Build failed: %v\n", err) os.Exit(1) @@ -175,24 +174,62 @@ func runInit(args []string) { } projectName := args[0] - if err := os.MkdirAll("src", 0755); err != nil { + if err := os.MkdirAll(filepath.Join(projectName, "src"), 0755); err != nil { logger.Fatalf("Error creating project directories: %v", err) } files := map[string]string{ - "Makefile": "MDT=mdt\n\nall: check build\n\ncheck:\n\t$(MDT) check src/*.marte\n\nbuild:\n\t$(MDT) build -o app.marte src/*.marte\n\nfmt:\n\t$(MDT) fmt src/*.marte\n", - ".marte_schema.cue": "package schema\n\n#Classes: {\n // Add your project-specific classes here\n}\n", - "src/app.marte": "#package " + projectName + "\n\n+App = {\n Class = RealTimeApplication\n +Data = {\n Class = ReferenceContainer\n }\n +Functions = {\n Class = ReferenceContainer\n }\n +States = {\n Class = ReferenceContainer\n }\n +Scheduler = {\n Class = GAMScheduler\n TimingDataSource = TimingDataSource\n }\n}\n", - "src/data.marte": "#package " + projectName + ".App.Data\n\n// Define your DataSources here\nDefaultDataSource = DDB\n//# Default DB\n+DDB = {\n Class=GAMDataSource\n}\n//# Timing Data Source to track threads timings\n+TimingDataSource = {\n Class = TimingDataSource\n}", - "src/functions.marte": "#package " + projectName + ".App.Functions\n\n// Define your GAMs here\n", + "Makefile": `MDT=mdt + +all: check build + +check: + $(MDT) check src/*.marte + +build: + $(MDT) build -o app.marte src/*.marte + +fmt: + $(MDT) fmt src/*.marte +`, + ".marte_schema.cue": `package schema + +#Classes: { + // Add your project-specific classes here +} +`, + "src/app.marte": `#package App + ++Main = { + Class = RealTimeApplication + +States = { + Class = ReferenceContainer + +Run = { + Class = RealTimeState + +MainThread = { + Class = RealTimeThread + Functions = {} + } + } + } + +Data = { + Class = ReferenceContainer + } +} +`, + "src/components.marte": `#package App.Data + +// Define your DataSources here +`, } for path, content := range files { - if err := os.WriteFile(path, []byte(content), 0644); err != nil { - logger.Fatalf("Error creating file %s: %v", path, err) + fullPath := filepath.Join(projectName, path) + if err := os.WriteFile(fullPath, []byte(content), 0644); err != nil { + logger.Fatalf("Error creating file %s: %v", fullPath, err) } - logger.Printf("Created %s\n", path) + logger.Printf("Created %s\n", fullPath) } logger.Printf("Project '%s' initialized successfully.\n", projectName) -} +} \ No newline at end of file diff --git a/docs/CONFIGURATION_GUIDE.md b/docs/CONFIGURATION_GUIDE.md index 73f6387..7c07216 100644 --- a/docs/CONFIGURATION_GUIDE.md +++ b/docs/CONFIGURATION_GUIDE.md @@ -76,6 +76,8 @@ GAMs declare inputs and outputs. You can refer to signals directly or alias them ### Threading Rules **Validation Rule**: A DataSource that is **not** marked as multithreaded (default) cannot be used by GAMs running in different threads within the same State. +**Ordering Rule**: For `INOUT` signals (data dependency within a thread), the Producer GAM must appear **before** the Consumer GAM in the thread's `Functions` list. This ensures correct data flow within the cycle. This rule is skipped if the DataSource is marked as `multithreaded: true`. + To allow sharing, the DataSource class in the schema must have `#meta: multithreaded: true`. ## 3. Schemas and Validation @@ -160,3 +162,27 @@ If validation is too strict, you can suppress warnings using pragmas (`//!`). Type = int32 } ``` + +## 6. Variables + +You can define variables using `#var`. The type expression supports CUE syntax. + +```marte +#var MyVar: uint32 = 100 +#var Env: "PROD" | "DEV" = "DEV" +``` + +### Usage +Reference a variable using `$`: + +```marte +Field = $MyVar +``` + +### Build Override +You can override variable values during build: + +```bash +mdt build -vMyVar=200 -vEnv="PROD" src/*.marte +``` + diff --git a/internal/builder/builder.go b/internal/builder/builder.go index 0751861..93d1580 100644 --- a/internal/builder/builder.go +++ b/internal/builder/builder.go @@ -11,11 +11,13 @@ import ( ) type Builder struct { - Files []string + Files []string + Overrides map[string]string + variables map[string]parser.Value } -func NewBuilder(files []string) *Builder { - return &Builder{Files: files} +func NewBuilder(files []string, overrides map[string]string) *Builder { + return &Builder{Files: files, Overrides: overrides, variables: make(map[string]parser.Value)} } func (b *Builder) Build(f *os.File) error { @@ -56,6 +58,22 @@ func (b *Builder) Build(f *os.File) error { tree.AddFile(file, config) } + b.collectVariables(tree) + + if expectedProject == "" { + for _, iso := range tree.IsolatedFiles { + tree.Root.Fragments = append(tree.Root.Fragments, iso.Fragments...) + for name, child := range iso.Children { + if existing, ok := tree.Root.Children[name]; ok { + b.mergeNodes(existing, child) + } else { + tree.Root.Children[name] = child + child.Parent = tree.Root + } + } + } + } + // Determine root node to print rootNode := tree.Root if expectedProject != "" { @@ -102,6 +120,8 @@ func (b *Builder) writeNodeBody(f *os.File, node *index.ProjectNode, indent int) switch d := def.(type) { case *parser.Field: b.writeDefinition(f, d, indent) + case *parser.VariableDefinition: + continue case *parser.ObjectNode: norm := index.NormalizeName(d.Name) if child, ok := node.Children[norm]; ok { @@ -150,6 +170,12 @@ func (b *Builder) formatValue(val parser.Value) string { return v.Raw case *parser.BoolValue: return fmt.Sprintf("%v", v.Value) + case *parser.VariableReferenceValue: + name := strings.TrimPrefix(v.Name, "$") + if val, ok := b.variables[name]; ok { + return b.formatValue(val) + } + return v.Name case *parser.ReferenceValue: return v.Value case *parser.ArrayValue: @@ -163,6 +189,18 @@ func (b *Builder) formatValue(val parser.Value) string { } } +func (b *Builder) mergeNodes(dest, src *index.ProjectNode) { + dest.Fragments = append(dest.Fragments, src.Fragments...) + for name, child := range src.Children { + if existing, ok := dest.Children[name]; ok { + b.mergeNodes(existing, child) + } else { + dest.Children[name] = child + child.Parent = dest + } + } +} + func hasClass(frag *index.Fragment) bool { for _, def := range frag.Definitions { if f, ok := def.(*parser.Field); ok && f.Name == "Class" { @@ -171,3 +209,28 @@ func hasClass(frag *index.Fragment) bool { } return false } + +func (b *Builder) collectVariables(tree *index.ProjectTree) { + processNode := func(n *index.ProjectNode) { + for _, frag := range n.Fragments { + for _, def := range frag.Definitions { + if vdef, ok := def.(*parser.VariableDefinition); ok { + if valStr, ok := b.Overrides[vdef.Name]; ok { + p := parser.NewParser("Temp = " + valStr) + cfg, _ := p.Parse() + if len(cfg.Definitions) > 0 { + if f, ok := cfg.Definitions[0].(*parser.Field); ok { + b.variables[vdef.Name] = f.Value + continue + } + } + } + if vdef.DefaultValue != nil { + b.variables[vdef.Name] = vdef.DefaultValue + } + } + } + } + } + tree.Walk(processNode) +} diff --git a/internal/index/index.go b/internal/index/index.go index bd985a0..3b93b5f 100644 --- a/internal/index/index.go +++ b/internal/index/index.go @@ -14,6 +14,7 @@ type ProjectTree struct { IsolatedFiles map[string]*ProjectNode GlobalPragmas map[string][]string NodeMap map[string][]*ProjectNode + Variables map[string]*parser.VariableDefinition } func (pt *ProjectTree) ScanDirectory(rootPath string) error { @@ -37,10 +38,11 @@ func (pt *ProjectTree) ScanDirectory(rootPath string) error { } type Reference struct { - Name string - Position parser.Position - File string - Target *ProjectNode // Resolved target + Name string + Position parser.Position + File string + Target *ProjectNode + TargetVariable *parser.VariableDefinition } type ProjectNode struct { @@ -72,6 +74,7 @@ func NewProjectTree() *ProjectTree { }, IsolatedFiles: make(map[string]*ProjectNode), GlobalPragmas: make(map[string][]string), + Variables: make(map[string]*parser.VariableDefinition), } } @@ -219,6 +222,9 @@ func (pt *ProjectTree) populateNode(node *ProjectNode, file string, config *pars case *parser.Field: fileFragment.Definitions = append(fileFragment.Definitions, d) pt.indexValue(file, d.Value) + case *parser.VariableDefinition: + fileFragment.Definitions = append(fileFragment.Definitions, d) + pt.Variables[d.Name] = d case *parser.ObjectNode: fileFragment.Definitions = append(fileFragment.Definitions, d) norm := NormalizeName(d.Name) @@ -274,6 +280,9 @@ func (pt *ProjectTree) addObjectFragment(node *ProjectNode, file string, obj *pa frag.Definitions = append(frag.Definitions, d) pt.indexValue(file, d.Value) pt.extractFieldMetadata(node, d) + case *parser.VariableDefinition: + frag.Definitions = append(frag.Definitions, d) + pt.Variables[d.Name] = d case *parser.ObjectNode: frag.Definitions = append(frag.Definitions, d) norm := NormalizeName(d.Name) @@ -379,6 +388,12 @@ func (pt *ProjectTree) indexValue(file string, val parser.Value) { Position: v.Position, File: file, }) + case *parser.VariableReferenceValue: + pt.References = append(pt.References, Reference{ + Name: strings.TrimPrefix(v.Name, "$"), + Position: v.Position, + File: file, + }) case *parser.ArrayValue: for _, elem := range v.Elements { pt.indexValue(file, elem) @@ -401,6 +416,12 @@ func (pt *ProjectTree) ResolveReferences() { pt.RebuildIndex() for i := range pt.References { ref := &pt.References[i] + + if v, ok := pt.Variables[ref.Name]; ok { + ref.TargetVariable = v + continue + } + if isoNode, ok := pt.IsolatedFiles[ref.File]; ok { ref.Target = pt.FindNode(isoNode, ref.Name, nil) } else { @@ -479,6 +500,7 @@ type QueryResult struct { Node *ProjectNode Field *parser.Field Reference *Reference + Variable *parser.VariableDefinition } func (pt *ProjectTree) Query(file string, line, col int) *QueryResult { @@ -528,6 +550,10 @@ func (pt *ProjectTree) queryNode(node *ProjectNode, file string, line, col int) if line == f.Position.Line && col >= f.Position.Column && col < f.Position.Column+len(f.Name) { return &QueryResult{Field: f} } + } else if v, ok := def.(*parser.VariableDefinition); ok { + if line == v.Position.Line { + return &QueryResult{Variable: v} + } } } } diff --git a/internal/lsp/server.go b/internal/lsp/server.go index 870bc82..944e9ea 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -591,6 +591,8 @@ func HandleHover(params HoverParams) *Hover { } } else if res.Field != nil { content = fmt.Sprintf("**Field**: `%s`", res.Field.Name) + } else if res.Variable != nil { + content = fmt.Sprintf("**Variable**: `%s`\nType: `%s`", res.Variable.Name, res.Variable.TypeExpr) } else if res.Reference != nil { targetName := "Unresolved" fullInfo := "" @@ -600,6 +602,10 @@ func HandleHover(params HoverParams) *Hover { targetName = res.Reference.Target.RealName targetDoc = res.Reference.Target.Doc fullInfo = formatNodeInfo(res.Reference.Target) + } else if res.Reference.TargetVariable != nil { + v := res.Reference.TargetVariable + targetName = v.Name + fullInfo = fmt.Sprintf("**Variable**: `%s`\nType: `%s`", v.Name, v.TypeExpr) } content = fmt.Sprintf("**Reference**: `%s` -> `%s`", res.Reference.Name, targetName) diff --git a/internal/parser/ast.go b/internal/parser/ast.go index fa1ca8e..2b78d21 100644 --- a/internal/parser/ast.go +++ b/internal/parser/ast.go @@ -125,3 +125,21 @@ type Pragma struct { } func (p *Pragma) Pos() Position { return p.Position } + +type VariableDefinition struct { + Position Position + Name string + TypeExpr string + DefaultValue Value +} + +func (v *VariableDefinition) Pos() Position { return v.Position } +func (v *VariableDefinition) isDefinition() {} + +type VariableReferenceValue struct { + Position Position + Name string +} + +func (v *VariableReferenceValue) Pos() Position { return v.Position } +func (v *VariableReferenceValue) isValue() {} diff --git a/internal/parser/lexer.go b/internal/parser/lexer.go index ee012c5..0ffe17d 100644 --- a/internal/parser/lexer.go +++ b/internal/parser/lexer.go @@ -23,6 +23,11 @@ const ( TokenComment TokenDocstring TokenComma + TokenColon + TokenPipe + TokenLBracket + TokenRBracket + TokenSymbol ) type Token struct { @@ -124,6 +129,16 @@ func (l *Lexer) NextToken() Token { return l.emit(TokenRBrace) case ',': return l.emit(TokenComma) + case ':': + return l.emit(TokenColon) + case '|': + return l.emit(TokenPipe) + case '[': + return l.emit(TokenLBracket) + case ']': + return l.emit(TokenRBracket) + case '&', '?', '!', '<', '>', '*', '(', ')': + return l.emit(TokenSymbol) case '"': return l.lexString() case '/': @@ -151,7 +166,7 @@ func (l *Lexer) NextToken() Token { func (l *Lexer) lexIdentifier() Token { for { r := l.next() - if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '-' || r == '.' || r == ':' { + if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '-' || r == '.' { continue } l.backup() @@ -247,7 +262,7 @@ func (l *Lexer) lexHashIdentifier() Token { // We are at '#', l.start is just before it for { r := l.next() - if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '-' || r == '.' || r == ':' || r == '#' { + if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '-' || r == '.' || r == '#' { continue } l.backup() diff --git a/internal/parser/parser.go b/internal/parser/parser.go index b6decea..2d18140 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -101,6 +101,9 @@ func (p *Parser) parseDefinition() (Definition, bool) { switch tok.Type { case TokenIdentifier: name := tok.Value + if name == "#var" { + return p.parseVariableDefinition(tok) + } if p.peek().Type != TokenEqual { p.addError(tok.Position, "expected =") return nil, false @@ -244,6 +247,8 @@ func (p *Parser) parseValue() (Value, bool) { true case TokenIdentifier: return &ReferenceValue{Position: tok.Position, Value: tok.Value}, true + case TokenObjectIdentifier: + return &VariableReferenceValue{Position: tok.Position, Name: tok.Value}, true case TokenLBrace: arr := &ArrayValue{Position: tok.Position} for { @@ -269,3 +274,53 @@ func (p *Parser) parseValue() (Value, bool) { return nil, false } } + +func (p *Parser) parseVariableDefinition(startTok Token) (Definition, bool) { + nameTok := p.next() + if nameTok.Type != TokenIdentifier { + p.addError(nameTok.Position, "expected variable name") + return nil, false + } + + if p.next().Type != TokenColon { + p.addError(nameTok.Position, "expected :") + return nil, false + } + + var typeTokens []Token + startLine := nameTok.Position.Line + + for { + t := p.peek() + if t.Position.Line > startLine || t.Type == TokenEOF { + break + } + if t.Type == TokenEqual { + break + } + typeTokens = append(typeTokens, p.next()) + } + + typeExpr := "" + for _, t := range typeTokens { + typeExpr += t.Value + " " + } + + var defVal Value + if p.peek().Type == TokenEqual { + p.next() + val, ok := p.parseValue() + if ok { + defVal = val + } else { + return nil, false + } + } + + return &VariableDefinition{ + Position: startTok.Position, + Name: nameTok.Value, + TypeExpr: strings.TrimSpace(typeExpr), + DefaultValue: defVal, + }, true +} diff --git a/internal/validator/validator.go b/internal/validator/validator.go index d2daf68..2d20b80 100644 --- a/internal/validator/validator.go +++ b/internal/validator/validator.go @@ -55,6 +55,7 @@ func (v *Validator) ValidateProject() { } v.CheckUnused() v.CheckDataSourceThreading() + v.CheckINOUTOrdering() } func (v *Validator) validateNode(node *index.ProjectNode) { @@ -884,3 +885,121 @@ func (v *Validator) isMultithreaded(ds *index.ProjectNode) bool { } return false } + +func (v *Validator) CheckINOUTOrdering() { + if v.Tree.Root == nil { + return + } + + var appNode *index.ProjectNode + findApp := func(n *index.ProjectNode) { + if cls, ok := n.Metadata["Class"]; ok && cls == "RealTimeApplication" { + appNode = n + } + } + v.Tree.Walk(findApp) + + if appNode == nil { + return + } + + var statesNode *index.ProjectNode + if s, ok := appNode.Children["States"]; ok { + statesNode = s + } else { + for _, child := range appNode.Children { + if cls, ok := child.Metadata["Class"]; ok && cls == "StateMachine" { + statesNode = child + break + } + } + } + + if statesNode == nil { + return + } + + for _, state := range statesNode.Children { + var threads []*index.ProjectNode + for _, child := range state.Children { + if child.RealName == "Threads" { + for _, t := range child.Children { + if cls, ok := t.Metadata["Class"]; ok && cls == "RealTimeThread" { + threads = append(threads, t) + } + } + } else { + if cls, ok := child.Metadata["Class"]; ok && cls == "RealTimeThread" { + threads = append(threads, child) + } + } + } + + for _, thread := range threads { + producedSignals := make(map[*index.ProjectNode]bool) + gams := v.getThreadGAMs(thread) + for _, gam := range gams { + v.processGAMSignalsForOrdering(gam, "InputSignals", producedSignals, true, thread, state) + v.processGAMSignalsForOrdering(gam, "OutputSignals", producedSignals, false, thread, state) + } + } + } +} + +func (v *Validator) processGAMSignalsForOrdering(gam *index.ProjectNode, containerName string, produced map[*index.ProjectNode]bool, isInput bool, thread, state *index.ProjectNode) { + container := gam.Children[containerName] + if container == nil { + return + } + + for _, sig := range container.Children { + if sig.Target == nil { + continue + } + + targetSig := sig.Target + if targetSig.Parent == nil || targetSig.Parent.Parent == nil { + continue + } + ds := targetSig.Parent.Parent + + if v.isMultithreaded(ds) { + continue + } + + dir := v.getDataSourceDirection(ds) + if dir != "INOUT" { + continue + } + + if isInput { + if !produced[targetSig] { + v.Diagnostics = append(v.Diagnostics, Diagnostic{ + Level: LevelError, + Message: fmt.Sprintf("INOUT Signal '%s' (DS '%s') is consumed by GAM '%s' in thread '%s' (State '%s') before being produced by any previous GAM.", targetSig.RealName, ds.RealName, gam.RealName, thread.RealName, state.RealName), + Position: v.getNodePosition(sig), + File: v.getNodeFile(sig), + }) + } + } else { + produced[targetSig] = true + } + } +} + +func (v *Validator) getDataSourceDirection(ds *index.ProjectNode) string { + cls := v.getNodeClass(ds) + if cls == "" { + return "" + } + if v.Schema == nil { + return "" + } + path := cue.ParsePath(fmt.Sprintf("#Classes.%s.#meta.direction", cls)) + val := v.Schema.Value.LookupPath(path) + if val.Err() == nil { + s, _ := val.String() + return s + } + return "" +} diff --git a/test/builder_multifile_test.go b/test/builder_multifile_test.go index 010c385..e012f86 100644 --- a/test/builder_multifile_test.go +++ b/test/builder_multifile_test.go @@ -32,7 +32,7 @@ FieldB = 20 os.WriteFile("build_multi_test/f2.marte", []byte(f2Content), 0644) // Execute Build - b := builder.NewBuilder([]string{"build_multi_test/f1.marte", "build_multi_test/f2.marte"}) + b := builder.NewBuilder([]string{"build_multi_test/f1.marte", "build_multi_test/f2.marte"}, nil) // Prepare output file // Should be +MyObj.marte (normalized MyObj.marte) - Actually checking content diff --git a/test/integration_test.go b/test/integration_test.go index 4b2cc3e..c68de85 100644 --- a/test/integration_test.go +++ b/test/integration_test.go @@ -168,7 +168,7 @@ func TestBuildCommand(t *testing.T) { // Test Merge files := []string{"integration/build_merge_1.marte", "integration/build_merge_2.marte"} - b := builder.NewBuilder(files) + b := builder.NewBuilder(files, nil) outputFile, err := os.Create("build_test/TEST.marte") if err != nil { @@ -195,7 +195,7 @@ func TestBuildCommand(t *testing.T) { // Test Order (Class First) filesOrder := []string{"integration/build_order_1.marte", "integration/build_order_2.marte"} - bOrder := builder.NewBuilder(filesOrder) + bOrder := builder.NewBuilder(filesOrder, nil) outputFileOrder, err := os.Create("build_test/ORDER.marte") if err != nil {