diff --git a/lang/gapi.go b/lang/gapi.go index 09350af9..440dd38e 100644 --- a/lang/gapi.go +++ b/lang/gapi.go @@ -234,8 +234,10 @@ func (obj *GAPI) Cli(cliInfo *gapi.CliInfo) (*gapi.Deploy, error) { logf("init...") // init and validate the structure of the AST data := &interfaces.Data{ - Fs: localFs, // the local fs! - Base: output.Base, // base dir (absolute path) that this is rooted in + // TODO: add missing fields here if/when needed + Fs: localFs, // the local fs! + FsURI: localFs.URI(), // TODO: is this right? + Base: output.Base, // base dir (absolute path) that this is rooted in Files: output.Files, Imports: importVertex, Metadata: output.Metadata, @@ -415,6 +417,7 @@ func (obj *GAPI) LangInit() error { obj.lang = &Lang{ Fs: fs, + FsURI: obj.InputURI, Input: input, Hostname: obj.data.Hostname, @@ -671,8 +674,10 @@ func (obj *GAPI) Get(getInfo *gapi.GetInfo) error { logf("init...") // init and validate the structure of the AST data := &interfaces.Data{ - Fs: localFs, // the local fs! - Base: output.Base, // base dir (absolute path) that this is rooted in + // TODO: add missing fields here if/when needed + Fs: localFs, // the local fs! + FsURI: localFs.URI(), // TODO: is this right? + Base: output.Base, // base dir (absolute path) that this is rooted in Files: output.Files, Imports: importVertex, Metadata: output.Metadata, diff --git a/lang/interfaces/ast.go b/lang/interfaces/ast.go index 587b12db..a498c74a 100644 --- a/lang/interfaces/ast.go +++ b/lang/interfaces/ast.go @@ -142,6 +142,10 @@ type Data struct { // system to manage file resources or other aspects. Fs engine.Fs + // FsURI is the fs URI of the active filesystem. This is useful to pass + // to the engine.World API for further consumption. + FsURI string + // Base directory (absolute path) that the running code is in. If an // import is found, that's a recursive addition, and naturally for that // run, this value would be different in the recursion. diff --git a/lang/interfaces/func.go b/lang/interfaces/func.go index 948c49bb..6cf67889 100644 --- a/lang/interfaces/func.go +++ b/lang/interfaces/func.go @@ -115,6 +115,16 @@ type NamedArgsFunc interface { // TODO: Consider combining this with the existing Data struct or more of it... // TODO: Do we want to add line/col/file values here, and generalize this? type FuncData struct { + // Fs represents a handle to the filesystem that we're running on. This + // is necessary for opening files if needed by import statements. The + // file() paths used to get templates or other files from our deploys + // come from here, this is *not* used to interact with the host file + // system to manage file resources or other aspects. + Fs engine.Fs + + // FsURI is the fs URI of the active filesystem. This is useful to pass + // to the engine.World API for further consumption. + FsURI string // Base directory (absolute path) that the running code is in. This is a // copy of the value from the Expr and Stmt Data struct for Init. diff --git a/lang/interpolate_test.go b/lang/interpolate_test.go index 4a3398fe..6084d71b 100644 --- a/lang/interpolate_test.go +++ b/lang/interpolate_test.go @@ -389,6 +389,7 @@ func TestInterpolateBasicStmt(t *testing.T) { ast, fail, exp := tc.ast, tc.fail, tc.exp data := &interfaces.Data{ + // TODO: add missing fields here if/when needed Debug: testing.Verbose(), // set via the -test.v flag to `go test` Logf: func(format string, v ...interface{}) { t.Logf("ast: "+format, v...) @@ -711,6 +712,7 @@ func TestInterpolateBasicExpr(t *testing.T) { ast, fail, exp := tc.ast, tc.fail, tc.exp data := &interfaces.Data{ + // TODO: add missing fields here if/when needed Debug: testing.Verbose(), // set via the -test.v flag to `go test` Logf: func(format string, v ...interface{}) { t.Logf("ast: "+format, v...) diff --git a/lang/interpret_test.go b/lang/interpret_test.go index 8419e783..8fee3456 100644 --- a/lang/interpret_test.go +++ b/lang/interpret_test.go @@ -441,6 +441,7 @@ func TestAstFunc0(t *testing.T) { t.Logf("test #%d: AST: %+v", index, ast) data := &interfaces.Data{ + // TODO: add missing fields here if/when needed Debug: testing.Verbose(), // set via the -test.v flag to `go test` Logf: func(format string, v ...interface{}) { t.Logf("ast: "+format, v...) @@ -790,7 +791,9 @@ func TestAstFunc1(t *testing.T) { importGraph.AddVertex(importVertex) data := &interfaces.Data{ + // TODO: add missing fields here if/when needed Fs: fs, + FsURI: fs.URI(), // TODO: is this right? Base: output.Base, // base dir (absolute path) the metadata file is in Files: output.Files, // no really needed here afaict Imports: importVertex, @@ -1232,9 +1235,11 @@ func TestAstFunc2(t *testing.T) { importGraph.AddVertex(importVertex) data := &interfaces.Data{ + // TODO: add missing fields here if/when needed Fs: fs, - Base: output.Base, // base dir (absolute path) the metadata file is in - Files: output.Files, // no really needed here afaict + FsURI: "memmapfs:///", // we're in standalone mode + Base: output.Base, // base dir (absolute path) the metadata file is in + Files: output.Files, // no really needed here afaict Imports: importVertex, Metadata: output.Metadata, Modules: "/" + interfaces.ModuleDirectory, // not really needed here afaict @@ -1676,6 +1681,7 @@ func TestAstInterpret0(t *testing.T) { t.Logf("test #%d: AST: %+v", index, ast) data := &interfaces.Data{ + // TODO: add missing fields here if/when needed Debug: testing.Verbose(), // set via the -test.v flag to `go test` Logf: func(format string, v ...interface{}) { t.Logf("ast: "+format, v...) diff --git a/lang/lang.go b/lang/lang.go index 422720a0..b81f259a 100644 --- a/lang/lang.go +++ b/lang/lang.go @@ -41,7 +41,9 @@ const ( // Lang is the main language lexer/parser object. type Lang struct { - Fs engine.Fs // connected fs where input dir or metadata exists + Fs engine.Fs // connected fs where input dir or metadata exists + FsURI string + // Input is a string which specifies what the lang should run. It can // accept values in several different forms. If is passed a single dash // (-), then it will use `os.Stdin`. If it is passed a single .mcl file, @@ -133,7 +135,9 @@ func (obj *Lang) Init() error { obj.Logf("init...") // init and validate the structure of the AST data := &interfaces.Data{ + // TODO: add missing fields here if/when needed Fs: obj.Fs, + FsURI: obj.FsURI, Base: output.Base, // base dir (absolute path) the metadata file is in Files: output.Files, Imports: importVertex, diff --git a/lang/structs.go b/lang/structs.go index eb82641d..dfc2e45e 100644 --- a/lang/structs.go +++ b/lang/structs.go @@ -3241,7 +3241,9 @@ func (obj *StmtProg) importScopeWithInputs(s string, scope *interfaces.Scope, pa logf("init...") // init and validate the structure of the AST data := &interfaces.Data{ + // TODO: add missing fields here if/when needed Fs: obj.data.Fs, + FsURI: obj.data.FsURI, Base: output.Base, // new base dir (absolute path) Files: files, Imports: parentVertex, // the parent vertex that imported me @@ -6690,7 +6692,9 @@ func (obj *ExprFunc) Init(data *interfaces.Data) error { // TODO: do we want to pass in the full obj.data instead ? if dataFunc, ok := obj.function.(interfaces.DataFunc); ok { dataFunc.SetData(&interfaces.FuncData{ - Base: obj.data.Base, + Fs: obj.data.Fs, + FsURI: obj.data.FsURI, + Base: obj.data.Base, }) } } @@ -6776,7 +6780,9 @@ func (obj *ExprFunc) Copy() (interfaces.Expr, error) { // TODO: do we want to pass in the full obj.data instead ? if dataFunc, ok := function.(interfaces.DataFunc); ok { dataFunc.SetData(&interfaces.FuncData{ - Base: obj.data.Base, + Fs: obj.data.Fs, + FsURI: obj.data.FsURI, + Base: obj.data.Base, }) } copied = true diff --git a/lang/unification_test.go b/lang/unification_test.go index aa02a094..0450235a 100644 --- a/lang/unification_test.go +++ b/lang/unification_test.go @@ -836,6 +836,7 @@ func TestUnification1(t *testing.T) { t.Logf("\n\ntest #%d: AST (before): %+v\n", index, ast) data := &interfaces.Data{ + // TODO: add missing fields here if/when needed Debug: testing.Verbose(), // set via the -test.v flag to `go test` Logf: func(format string, v ...interface{}) { t.Logf(fmt.Sprintf("test #%d", index)+": ast: "+format, v...)