mirror of
https://github.com/Open-Argon/argon-v3.git
synced 2025-12-06 00:46:07 +00:00
parse imports with fixed paths before running all the code
This commit is contained in:
114
src/import.go
114
src/import.go
@@ -7,6 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var imported = make(map[string]ArObject)
|
var imported = make(map[string]ArObject)
|
||||||
|
var translatedImports = make(map[string]translatedImport)
|
||||||
var importing = make(map[string]bool)
|
var importing = make(map[string]bool)
|
||||||
|
|
||||||
const modules_folder = "argon_modules"
|
const modules_folder = "argon_modules"
|
||||||
@@ -41,7 +42,58 @@ func readFile(path string) ([]UNPARSEcode, error) {
|
|||||||
return output, nil
|
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)
|
extention := filepath.Ext(realpath)
|
||||||
path := realpath
|
path := realpath
|
||||||
if extention == "" {
|
if extention == "" {
|
||||||
@@ -49,11 +101,11 @@ func importMod(realpath string, origin string, main bool, global ArObject) (ArOb
|
|||||||
}
|
}
|
||||||
ex, err := os.Getwd()
|
ex, err := os.Getwd()
|
||||||
if err != nil {
|
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()
|
exc, err := os.Executable()
|
||||||
if err != nil {
|
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)
|
executable := filepath.Dir(exc)
|
||||||
isABS := filepath.IsAbs(path)
|
isABS := filepath.IsAbs(path)
|
||||||
@@ -86,58 +138,26 @@ func importMod(realpath string, origin string, main bool, global ArObject) (ArOb
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
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] {
|
} else if importing[p] {
|
||||||
return ArObject{}, ArErr{TYPE: "Import Error", message: "Circular import: " + path, EXISTS: true}
|
return translatedImport{}, ArErr{TYPE: "Import Error", message: "Circular import: " + path, EXISTS: true}
|
||||||
} else if _, ok := imported[p]; ok {
|
} else if _, ok := translatedImports[p]; ok {
|
||||||
return imported[p], ArErr{}
|
return translatedImports[p], ArErr{}
|
||||||
}
|
}
|
||||||
importing[p] = true
|
importing[p] = true
|
||||||
codelines, err := readFile(p)
|
codelines, err := readFile(p)
|
||||||
if err != nil {
|
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)
|
translated, translationerr := translate(codelines)
|
||||||
|
importing[p] = false
|
||||||
|
|
||||||
if translationerr.EXISTS {
|
if translationerr.EXISTS {
|
||||||
return ArObject{}, translationerr
|
return translatedImport{}, translationerr
|
||||||
}
|
}
|
||||||
ArgsArArray := []any{}
|
|
||||||
withoutarfile := []string{}
|
translatedImports[p] = translatedImport{translated, p, path, ex, exc, origin}
|
||||||
if len(Args) > 1 {
|
return translatedImports[p], ArErr{}
|
||||||
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{}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,11 +61,16 @@ func main() {
|
|||||||
if e != nil {
|
if e != nil {
|
||||||
panic(e)
|
panic(e)
|
||||||
}
|
}
|
||||||
_, err := importMod(Args[0], ex, true, global)
|
translated, err := translateImport(Args[0], ex, true)
|
||||||
if err.EXISTS {
|
if err.EXISTS {
|
||||||
panicErr(err)
|
panicErr(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
_, runimeErr := runTranslatedImport(translated, global)
|
||||||
|
if runimeErr.EXISTS {
|
||||||
|
panicErr(runimeErr)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
if threadCount > 0 {
|
if threadCount > 0 {
|
||||||
<-threadChan
|
<-threadChan
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ import (
|
|||||||
var genericImportCompiled = makeRegex(`import( )+(.|\n)+(( )+as( )+([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*)?( *)`)
|
var genericImportCompiled = makeRegex(`import( )+(.|\n)+(( )+as( )+([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*)?( *)`)
|
||||||
|
|
||||||
type ArImport struct {
|
type ArImport struct {
|
||||||
FilePath any
|
pretranslated bool
|
||||||
Values any
|
translated translatedImport
|
||||||
Code string
|
FilePath any
|
||||||
Line int
|
Values any
|
||||||
Path string
|
Code string
|
||||||
|
Line int
|
||||||
|
Path string
|
||||||
}
|
}
|
||||||
|
|
||||||
func isGenericImport(code UNPARSEcode) bool {
|
func isGenericImport(code UNPARSEcode) bool {
|
||||||
@@ -67,27 +69,64 @@ func parseGenericImport(code UNPARSEcode, index int, codeline []UNPARSEcode) (Ar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ArImport{
|
importOBJ := ArImport{
|
||||||
|
false,
|
||||||
|
translatedImport{},
|
||||||
toImport,
|
toImport,
|
||||||
asStr,
|
asStr,
|
||||||
code.realcode,
|
code.realcode,
|
||||||
code.line,
|
code.line,
|
||||||
code.path,
|
code.path,
|
||||||
}, true, ArErr{}, i
|
}
|
||||||
|
|
||||||
|
if str, ok := toImport.(string); ok {
|
||||||
|
importOBJ.pretranslated = true
|
||||||
|
var err ArErr
|
||||||
|
importOBJ.translated, err = translateImport(str, filepath.Dir(filepath.ToSlash(code.path)), false)
|
||||||
|
if err.EXISTS {
|
||||||
|
if err.line == 0 {
|
||||||
|
err.line = importOBJ.Line
|
||||||
|
}
|
||||||
|
if err.path == "" {
|
||||||
|
err.path = importOBJ.Path
|
||||||
|
}
|
||||||
|
if err.code == "" {
|
||||||
|
err.code = importOBJ.Code
|
||||||
|
}
|
||||||
|
return importOBJ, false, err, i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return importOBJ, true, ArErr{}, i
|
||||||
}
|
}
|
||||||
|
|
||||||
func runImport(importOBJ ArImport, stack stack, stacklevel int) (any, ArErr) {
|
func runImport(importOBJ ArImport, stack stack, stacklevel int) (any, ArErr) {
|
||||||
val, err := runVal(importOBJ.FilePath, stack, stacklevel+1)
|
var translated = importOBJ.translated
|
||||||
val = ArValidToAny(val)
|
if !importOBJ.pretranslated {
|
||||||
if err.EXISTS {
|
val, err := runVal(importOBJ.FilePath, stack, stacklevel+1)
|
||||||
return nil, err
|
val = ArValidToAny(val)
|
||||||
|
if err.EXISTS {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if typeof(val) != "string" {
|
||||||
|
return nil, ArErr{"Type Error", "import requires a string, got type '" + typeof(val) + "'", importOBJ.Line, importOBJ.Path, importOBJ.Code, true}
|
||||||
|
}
|
||||||
|
parent := filepath.Dir(filepath.ToSlash(importOBJ.Path))
|
||||||
|
translated, err = translateImport(val.(string), parent, false)
|
||||||
|
if err.EXISTS {
|
||||||
|
if err.line == 0 {
|
||||||
|
err.line = importOBJ.Line
|
||||||
|
}
|
||||||
|
if err.path == "" {
|
||||||
|
err.path = importOBJ.Path
|
||||||
|
}
|
||||||
|
if err.code == "" {
|
||||||
|
err.code = importOBJ.Code
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if typeof(val) != "string" {
|
stackMap, err := runTranslatedImport(translated, stack[0])
|
||||||
return nil, ArErr{"Type Error", "import requires a string, got type '" + typeof(val) + "'", importOBJ.Line, importOBJ.Path, importOBJ.Code, true}
|
|
||||||
}
|
|
||||||
path := val.(string)
|
|
||||||
parent := filepath.Dir(filepath.ToSlash(importOBJ.Path))
|
|
||||||
stackMap, err := importMod(path, parent, false, stack[0])
|
|
||||||
if err.EXISTS {
|
if err.EXISTS {
|
||||||
if err.line == 0 {
|
if err.line == 0 {
|
||||||
err.line = importOBJ.Line
|
err.line = importOBJ.Line
|
||||||
@@ -116,7 +155,7 @@ func runImport(importOBJ ArImport, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
for _, v := range x {
|
for _, v := range x {
|
||||||
val, ok := stackMap.obj[v]
|
val, ok := stackMap.obj[v]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, ArErr{"Import Error", "could not find value " + anyToArgon(v, true, false, 3, 0, false, 0) + " in module " + anyToArgon(path, true, false, 3, 0, false, 0), importOBJ.Line, importOBJ.Path, importOBJ.Code, true}
|
return nil, ArErr{"Import Error", "could not find value " + anyToArgon(v, true, false, 3, 0, false, 0) + " in module " + anyToArgon(translated.path, true, false, 3, 0, false, 0), importOBJ.Line, importOBJ.Path, importOBJ.Code, true}
|
||||||
}
|
}
|
||||||
builtinCall(setindex, []any{v, val})
|
builtinCall(setindex, []any{v, val})
|
||||||
}
|
}
|
||||||
|
|||||||
1
tests/circular_import.ar
Normal file
1
tests/circular_import.ar
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import "circular_test"
|
||||||
1
tests/circular_test.ar
Normal file
1
tests/circular_test.ar
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import "circular_import"
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
let zero = 1e-1000
|
let h = 1e-1000
|
||||||
let diff(f) = (x) = (f(x + zero) - f(x)) / zero
|
let diff(f) = (x) = (f(x + h) - f(x)) / h
|
||||||
|
|
||||||
|
|
||||||
let f(x) = x^10+x^9+x^8+x^7+x^6+x^5+x^4+x^3+x^2+x+1
|
let f(x) = x^10+x^9+x^8+x^7+x^6+x^5+x^4+x^3+x^2+x+1
|
||||||
|
|||||||
Reference in New Issue
Block a user