parse imports with fixed paths before running all the code

This commit is contained in:
2024-02-23 21:50:53 +00:00
parent 7f86d345ae
commit b3a07d7f63
6 changed files with 134 additions and 68 deletions

View File

@@ -7,6 +7,7 @@ import (
)
var imported = make(map[string]ArObject)
var translatedImports = make(map[string]translatedImport)
var importing = make(map[string]bool)
const modules_folder = "argon_modules"
@@ -41,7 +42,58 @@ func readFile(path string) ([]UNPARSEcode, error) {
return output, nil
}
func importMod(realpath string, origin string, main bool, global ArObject) (ArObject, ArErr) {
type translatedImport struct {
translated []any
p string
path string
ex string
exc string
origin string
}
var runTranslatedImport func(translatedImport, ArObject) (ArObject, ArErr)
func init() {
runTranslatedImport = __runTranslatedImport
}
func __runTranslatedImport(translatedImport translatedImport, global ArObject) (ArObject, ArErr) {
if _, ok := imported[translatedImport.p]; ok {
return imported[translatedImport.p], ArErr{}
}
ArgsArArray := []any{}
withoutarfile := []string{}
if len(Args) > 1 {
withoutarfile = Args[1:]
}
for _, arg := range withoutarfile {
ArgsArArray = append(ArgsArArray, arg)
}
local := newscope()
localvars := Map(anymap{
"program": Map(anymap{
"args": ArArray(ArgsArArray),
"origin": ArString(translatedImport.origin),
"cwd": ArString(translatedImport.ex),
"exc": ArString(translatedImport.exc),
"file": Map(anymap{
"name": ArString(filepath.Base(translatedImport.p)),
"path": ArString(translatedImport.p),
}),
"main": main,
}),
})
_, runimeErr := run(translatedImport.translated, stack{global, localvars, local})
if runimeErr.EXISTS {
return ArObject{}, runimeErr
}
imported[translatedImport.p] = local
return local, ArErr{}
}
func translateImport(realpath string, origin string, main bool) (translatedImport, ArErr) {
extention := filepath.Ext(realpath)
path := realpath
if extention == "" {
@@ -49,11 +101,11 @@ func importMod(realpath string, origin string, main bool, global ArObject) (ArOb
}
ex, err := os.Getwd()
if err != nil {
return ArObject{}, ArErr{TYPE: "Import Error", message: "Could not get working directory", EXISTS: true}
return translatedImport{}, ArErr{TYPE: "Import Error", message: "Could not get working directory", EXISTS: true}
}
exc, err := os.Executable()
if err != nil {
return ArObject{}, ArErr{TYPE: "Import Error", message: "Could not get executable", EXISTS: true}
return translatedImport{}, ArErr{TYPE: "Import Error", message: "Could not get executable", EXISTS: true}
}
executable := filepath.Dir(exc)
isABS := filepath.IsAbs(path)
@@ -86,58 +138,26 @@ func importMod(realpath string, origin string, main bool, global ArObject) (ArOb
}
if !found {
return ArObject{}, ArErr{TYPE: "Import Error", message: "File does not exist: " + path, EXISTS: true}
return translatedImport{}, ArErr{TYPE: "Import Error", message: "File does not exist: " + path, EXISTS: true}
} else if importing[p] {
return ArObject{}, ArErr{TYPE: "Import Error", message: "Circular import: " + path, EXISTS: true}
} else if _, ok := imported[p]; ok {
return imported[p], ArErr{}
return translatedImport{}, ArErr{TYPE: "Import Error", message: "Circular import: " + path, EXISTS: true}
} else if _, ok := translatedImports[p]; ok {
return translatedImports[p], ArErr{}
}
importing[p] = true
codelines, err := readFile(p)
if err != nil {
return ArObject{}, ArErr{TYPE: "Import Error", message: "Could not read file: " + path, EXISTS: true}
return translatedImport{}, ArErr{TYPE: "Import Error", message: "Could not read file: " + path, EXISTS: true}
}
importing[p] = true
translated, translationerr := translate(codelines)
importing[p] = false
if translationerr.EXISTS {
return ArObject{}, translationerr
return translatedImport{}, translationerr
}
ArgsArArray := []any{}
withoutarfile := []string{}
if len(Args) > 1 {
withoutarfile = Args[1:]
}
for _, arg := range withoutarfile {
ArgsArArray = append(ArgsArArray, arg)
}
local := newscope()
localvars := Map(anymap{
"program": Map(anymap{
"args": ArArray(ArgsArArray),
"origin": ArString(origin),
"import": builtinFunc{"import", func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{"Import Error", "Invalid number of arguments", 0, realpath, "", true}
}
if _, ok := args[0].(string); !ok {
return nil, ArErr{"Import Error", "Invalid argument type", 0, realpath, "", true}
}
return importMod(args[0].(string), filepath.Dir(filepath.ToSlash(p)), false, global)
}},
"cwd": ArString(ex),
"exc": ArString(exc),
"file": Map(anymap{
"name": ArString(filepath.Base(p)),
"path": ArString(p),
}),
"main": main,
}),
})
_, runimeErr := run(translated, stack{global, localvars, local})
importing[p] = false
if runimeErr.EXISTS {
return ArObject{}, runimeErr
}
imported[p] = local
return local, ArErr{}
translatedImports[p] = translatedImport{translated, p, path, ex, exc, origin}
return translatedImports[p], ArErr{}
}