From bfad2775eee1c37267bdd260ace6db4eb4c8be86 Mon Sep 17 00:00:00 2001 From: Ugric Date: Sat, 25 Mar 2023 18:19:48 +0000 Subject: [PATCH] impliment garbage collection and move init --- src/array.go | 10 +++++----- src/built-ins.go | 6 +++--- src/garbageCollect.go | 15 +++++++++++++++ src/import.go | 8 ++++---- src/main.go | 13 ++++++++----- src/parseImport.go | 2 +- src/random.go | 2 +- src/shell.go | 6 +++--- src/thread.go | 4 ++-- src/translate.go | 21 ++++++++++++++------- tests/memoryLeakTest.ar | 8 ++++++++ 11 files changed, 64 insertions(+), 31 deletions(-) create mode 100644 src/garbageCollect.go create mode 100644 tests/memoryLeakTest.ar diff --git a/src/array.go b/src/array.go index 49f693b..dd68af2 100644 --- a/src/array.go +++ b/src/array.go @@ -351,7 +351,7 @@ func ArArray(arr []any) ArObject { return runCall(call{ args[1], []any{a}, "", 0, "", - }, stack{vars, newscope()}, 0) + }, stack{}, 0) }) if err.EXISTS { return nil, err @@ -400,7 +400,7 @@ func ArArray(arr []any) ArObject { vv, err := runCall(call{ args[0], []any{v}, "", 0, "", - }, stack{vars, newscope()}, 0) + }, stack{}, 0) if err.EXISTS { return nil, err } @@ -431,7 +431,7 @@ func ArArray(arr []any) ArObject { vv, err := runCall(call{ args[0], []any{v}, "", 0, "", - }, stack{vars, newscope()}, 0) + }, stack{}, 0) if err.EXISTS { return nil, err } @@ -448,7 +448,7 @@ func ArArray(arr []any) ArObject { if len(args) != 2 { return nil, ArErr{ TYPE: "TypeError", - message: "missing argument", + message: "missing argument, expected 2 got " + fmt.Sprint(len(args)), EXISTS: true, } } @@ -472,7 +472,7 @@ func ArArray(arr []any) ArObject { v, err = runCall(call{ args[0], []any{v, vv}, "", 0, "", - }, stack{vars, newscope()}, 0) + }, stack{}, 0) if err.EXISTS { return nil, err } diff --git a/src/built-ins.go b/src/built-ins.go index ca84e70..9cc09bd 100644 --- a/src/built-ins.go +++ b/src/built-ins.go @@ -2,9 +2,8 @@ package main import "fmt" -var vars = Map(anymap{}) - -func init() { +func makeGlobal() ArObject { + var vars = Map(anymap{}) vars.obj["global"] = vars vars.obj["term"] = ArTerm vars.obj["number"] = builtinFunc{"number", ArgonNumber} @@ -150,4 +149,5 @@ func init() { return ArArray([]any{}), ArErr{} }} vars.obj["subprocess"] = builtinFunc{"subprocess", ArSubprocess} + return vars } diff --git a/src/garbageCollect.go b/src/garbageCollect.go new file mode 100644 index 0000000..14b5b07 --- /dev/null +++ b/src/garbageCollect.go @@ -0,0 +1,15 @@ +package main + +import ( + "runtime" + "time" +) + +func garbageCollect() { + go func() { + for { + time.Sleep(10 * time.Second) + runtime.GC() + } + }() +} diff --git a/src/import.go b/src/import.go index 385fe8d..9f22a96 100644 --- a/src/import.go +++ b/src/import.go @@ -47,7 +47,7 @@ func readFile(path string) []UNPARSEcode { return output } -func importMod(realpath string, origin string, main bool) (ArObject, ArErr) { +func importMod(realpath string, origin string, main bool, global ArObject) (ArObject, ArErr) { extention := filepath.Ext(realpath) path := realpath if extention == "" { @@ -114,7 +114,7 @@ func importMod(realpath string, origin string, main bool) (ArObject, ArErr) { for _, arg := range withoutarfile { ArgsArArray = append(ArgsArArray, arg) } - global := newscope() + local := newscope() localvars := Map(anymap{ "program": Map(anymap{ "args": ArArray(ArgsArArray), @@ -126,7 +126,7 @@ func importMod(realpath string, origin string, main bool) (ArObject, ArErr) { if _, ok := args[0].(string); !ok { return nil, ArErr{"Import Error", "Invalid argument type", 0, realpath, "", true} } - return importMod(args[0].(string), filepath.Dir(p), false) + return importMod(args[0].(string), filepath.Dir(p), false, global) }}, "cwd": ex, "exc": exc, @@ -138,7 +138,7 @@ func importMod(realpath string, origin string, main bool) (ArObject, ArErr) { "scope": global, }), }) - _, runimeErr := ThrowOnNonLoop(run(translated, stack{vars, localvars, global})) + _, runimeErr := ThrowOnNonLoop(run(translated, stack{global, localvars, local})) importing[p] = false if runimeErr.EXISTS { return ArObject{}, runimeErr diff --git a/src/main.go b/src/main.go index 1084ea9..2f0a21c 100644 --- a/src/main.go +++ b/src/main.go @@ -17,15 +17,18 @@ func newscope() ArObject { } func main() { + initRandom() + garbageCollect() + global := makeGlobal() + if len(Args) == 0 { + shell(global) + os.Exit(0) + } ex, e := os.Getwd() if e != nil { panic(e) } - if len(Args) == 0 { - shell() - os.Exit(0) - } - _, err := importMod(Args[0], ex, true) + _, err := importMod(Args[0], ex, true, global) if err.EXISTS { panicErr(err) os.Exit(1) diff --git a/src/parseImport.go b/src/parseImport.go index f54fa48..8c90a51 100644 --- a/src/parseImport.go +++ b/src/parseImport.go @@ -57,7 +57,7 @@ func runImport(importOBJ ArImport, stack stack, stacklevel int) (any, ArErr) { if e != nil { return nil, ArErr{"File Error", "could not get current working directory", importOBJ.line, importOBJ.path, importOBJ.code, true} } - stackMap, err := importMod(path, ex, false) + stackMap, err := importMod(path, ex, false, stack[0]) if err.EXISTS { if err.line == 0 { err.line = importOBJ.line diff --git a/src/random.go b/src/random.go index 7fb6044..6af0650 100644 --- a/src/random.go +++ b/src/random.go @@ -97,7 +97,7 @@ var ArRandom = Map(anymap{ }}, }) -func init() { +func initRandom() { rand.Seed( time.Now().UnixMicro(), ) diff --git a/src/shell.go b/src/shell.go index f3d23be..7ce72a9 100644 --- a/src/shell.go +++ b/src/shell.go @@ -6,8 +6,8 @@ import ( "os/signal" ) -func shell() { - global := stack{vars, newscope()} +func shell(global ArObject) { + stack := stack{global, newscope()} c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) go func() { @@ -41,7 +41,7 @@ func shell() { if translationerr.EXISTS { panicErr(translationerr) } - output, runimeErr := ThrowOnNonLoop(run(translated, global)) + output, runimeErr := ThrowOnNonLoop(run(translated, stack)) output = openReturn(output) if runimeErr.EXISTS { diff --git a/src/thread.go b/src/thread.go index 1e8b8c0..d9a8fba 100644 --- a/src/thread.go +++ b/src/thread.go @@ -23,7 +23,7 @@ func ArThread(args ...any) (any, ArErr) { } var resp any var err ArErr - currentscope := stack{vars, newscope()} + hasrun := false joined := false var wg sync.WaitGroup @@ -38,7 +38,7 @@ func ArThread(args ...any) (any, ArErr) { hasrun = true wg.Add(1) go func() { - resp, err = runCall(call{tocall, []any{}, "", 0, ""}, currentscope, 0) + resp, err = runCall(call{tocall, []any{}, "", 0, ""}, nil, 0) wg.Done() }() return nil, ArErr{} diff --git a/src/translate.go b/src/translate.go index ba69431..0964483 100644 --- a/src/translate.go +++ b/src/translate.go @@ -62,7 +62,8 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i if worked { return resp, worked, err, i } - } else if isnot(code) { + } + if isnot(code) { return parseNot(code, index, codelines, isLine) } if isSetVariable(code) { @@ -76,7 +77,8 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i if worked { return resp, worked, err, i } - } else if isNumber(code) { + } + if isNumber(code) { return parseNumber(code) } else if isNegative(code) { return parseNegative(code, index, codelines) @@ -86,21 +88,26 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i return parseSquareroot(code, index, codelines) } else if isFactorial(code) { return parseFactorial(code, index, codelines) - } else if isCall(code) { + } + if isCall(code) { resp, worked, err, i = parseCall(code, index, codelines) if worked { return resp, worked, err, i } - } else if isVariable(code) { + } + if isVariable(code) { return parseVariable(code) - } else if isArray(code) { + } + if isArray(code) { resp, worked, err, i = parseArray(code, index, codelines) if worked { return resp, worked, err, i } - } else if isMapGet(code) { + } + if isMapGet(code) { return mapGetParse(code, index, codelines) - } else if isIndexGet(code) { + } + if isIndexGet(code) { resp, worked, err, i = indexGetParse(code, index, codelines) if worked { return resp, worked, err, i diff --git a/tests/memoryLeakTest.ar b/tests/memoryLeakTest.ar new file mode 100644 index 0000000..00ecb63 --- /dev/null +++ b/tests/memoryLeakTest.ar @@ -0,0 +1,8 @@ +f() = do + a = [] + for (i from 0 to 10000000) a.append(i) + +term.log("start") +f() +term.log("end") +time.snooze(100000000) \ No newline at end of file