From b34470a97d5983abe24f8c63d4983a269da91ccc Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Thu, 18 Jul 2024 18:08:30 +0200 Subject: [PATCH] Implemented package imports --- examples/factorial/factorial.q | 4 +- examples/fibonacci/fibonacci.q | 4 +- examples/hello/hello.q | 8 +- lib/sys/linux.q | 55 ++++++ src/build/config/gc.go | 7 - src/build/config/init.go | 53 ++++++ src/build/core/CompileCall.go | 10 +- src/build/keyword/Keyword.go | 2 + src/build/scanner/Scan.go | 280 ++-------------------------- src/build/scanner/Scanner.go | 14 ++ src/build/scanner/queue.go | 21 +++ src/build/scanner/queueDirectory.go | 24 +++ src/build/scanner/queueFile.go | 15 ++ src/build/scanner/scanFile.go | 238 +++++++++++++++++++++++ tests/programs/branch-and.q | 22 +-- tests/programs/branch-both.q | 26 ++- tests/programs/branch-or.q | 14 +- tests/programs/branch.q | 40 ++-- tests/programs/chained-calls.q | 8 +- tests/programs/jump-near.q | 10 +- tests/programs/nested-calls.q | 8 +- 21 files changed, 510 insertions(+), 353 deletions(-) create mode 100644 lib/sys/linux.q delete mode 100644 src/build/config/gc.go create mode 100644 src/build/config/init.go create mode 100644 src/build/scanner/Scanner.go create mode 100644 src/build/scanner/queue.go create mode 100644 src/build/scanner/queueDirectory.go create mode 100644 src/build/scanner/queueFile.go create mode 100644 src/build/scanner/scanFile.go diff --git a/examples/factorial/factorial.q b/examples/factorial/factorial.q index f198ec1..30315ec 100644 --- a/examples/factorial/factorial.q +++ b/examples/factorial/factorial.q @@ -1,5 +1,7 @@ +import sys + main() { - syscall(60, factorial(5)) + sys.exit(factorial(5)) } factorial(x) { diff --git a/examples/fibonacci/fibonacci.q b/examples/fibonacci/fibonacci.q index e02a15c..505bf26 100644 --- a/examples/fibonacci/fibonacci.q +++ b/examples/fibonacci/fibonacci.q @@ -1,5 +1,7 @@ +import sys + main() { - syscall(60, fibonacci(10)) + sys.exit(fibonacci(10)) } fibonacci(x) { diff --git a/examples/hello/hello.q b/examples/hello/hello.q index 85aa05c..6adfc54 100644 --- a/examples/hello/hello.q +++ b/examples/hello/hello.q @@ -1,11 +1,9 @@ +import sys + main() { print("Hello", 5) } print(address, length) { - write(1, address, length) -} - -write(fd, address, length) { - syscall(1, fd, address, length) + sys.write(1, address, length) } \ No newline at end of file diff --git a/lib/sys/linux.q b/lib/sys/linux.q new file mode 100644 index 0000000..9c44037 --- /dev/null +++ b/lib/sys/linux.q @@ -0,0 +1,55 @@ +read(fd, address, length) { + return syscall(0, fd, address, length) +} + +write(fd, address, length) { + syscall(1, fd, address, length) +} + +open(file, flags, mode) { + return syscall(2, file, flags, mode) +} + +close(fd) { + return syscall(3, fd) +} + +mmap(address, length, protection, flags) { + return syscall(9, address, length, protection, flags) +} + +munmap(address, length) { + return syscall(11, address, length) +} + +clone(flags, stack) { + return syscall(56, flags, stack) +} + +exit(code) { + syscall(60, code) +} + +getcwd(buffer, length) { + return syscall(79, buffer, length) +} + +chdir(path) { + return syscall(80, path) +} + +rename(old, new) { + return syscall(82, old, new) +} + +mkdir(path, mode) { + return syscall(83, path, mode) +} + +rmdir(path) { + return syscall(84, path) +} + +unlink(file) { + return syscall(87, file) +} diff --git a/src/build/config/gc.go b/src/build/config/gc.go deleted file mode 100644 index 522ae07..0000000 --- a/src/build/config/gc.go +++ /dev/null @@ -1,7 +0,0 @@ -package config - -import "runtime/debug" - -func init() { - debug.SetGCPercent(-1) -} diff --git a/src/build/config/init.go b/src/build/config/init.go new file mode 100644 index 0000000..31732e8 --- /dev/null +++ b/src/build/config/init.go @@ -0,0 +1,53 @@ +package config + +import ( + "os" + "path" + "path/filepath" + "runtime/debug" +) + +var ( + Executable string + Root string + Library string +) + +func init() { + debug.SetGCPercent(-1) + executable, err := os.Executable() + + if err != nil { + panic(err) + } + + Executable = executable + Root = filepath.Dir(executable) + Library = filepath.Join(Root, "lib") + stat, err := os.Stat(Library) + + if !os.IsNotExist(err) && stat != nil && stat.IsDir() { + return + } + + dir, err := os.Getwd() + + if err != nil { + panic(err) + } + + for { + Library = path.Join(dir, "lib") + stat, err := os.Stat(Library) + + if !os.IsNotExist(err) && stat != nil && stat.IsDir() { + return + } + + if dir == "/" { + panic("standard library not found") + } + + dir = filepath.Dir(dir) + } +} diff --git a/src/build/core/CompileCall.go b/src/build/core/CompileCall.go index ae04215..53250d9 100644 --- a/src/build/core/CompileCall.go +++ b/src/build/core/CompileCall.go @@ -11,7 +11,15 @@ import ( // Registers that are in use must be saved if they are modified by the function. // After the function call, they must be restored in reverse order. func (f *Function) CompileCall(root *expression.Expression) error { - funcName := root.Children[0].Token.Text() + funcNameRoot := root.Children[0] + funcName := "" + + if funcNameRoot.IsLeaf() { + funcName = funcNameRoot.Token.Text() + } else { + funcName = funcNameRoot.Children[0].Token.Text() + funcNameRoot.Token.Text() + funcNameRoot.Children[1].Token.Text() + } + isSyscall := funcName == "syscall" if !isSyscall { diff --git a/src/build/keyword/Keyword.go b/src/build/keyword/Keyword.go index d744384..ef62575 100644 --- a/src/build/keyword/Keyword.go +++ b/src/build/keyword/Keyword.go @@ -2,6 +2,7 @@ package keyword const ( If = "if" + Import = "import" Loop = "loop" Return = "return" ) @@ -9,6 +10,7 @@ const ( // Map is a map of all keywords used in the language. var Map = map[string][]byte{ If: []byte(If), + Import: []byte(Import), Loop: []byte(Loop), Return: []byte(Return), } diff --git a/src/build/scanner/Scan.go b/src/build/scanner/Scan.go index eb3e760..b79d04f 100644 --- a/src/build/scanner/Scan.go +++ b/src/build/scanner/Scan.go @@ -1,278 +1,20 @@ package scanner -import ( - "os" - "path/filepath" - "strings" - "sync" +import "git.akyoto.dev/cli/q/src/build/core" - "git.akyoto.dev/cli/q/src/build/arch/x64" - "git.akyoto.dev/cli/q/src/build/core" - "git.akyoto.dev/cli/q/src/build/errors" - "git.akyoto.dev/cli/q/src/build/expression" - "git.akyoto.dev/cli/q/src/build/fs" - "git.akyoto.dev/cli/q/src/build/token" -) - -// Scan scans the directory. +// Scan scans the list of files. func Scan(files []string) (<-chan *core.Function, <-chan error) { - functions := make(chan *core.Function) - errors := make(chan error) + scanner := Scanner{ + functions: make(chan *core.Function), + errors: make(chan error), + } go func() { - scanFiles(files, functions, errors) - close(functions) - close(errors) + scanner.queue(files...) + scanner.group.Wait() + close(scanner.functions) + close(scanner.errors) }() - return functions, errors -} - -// scanFiles scans the list of files without channel allocations. -func scanFiles(files []string, functions chan<- *core.Function, errors chan<- error) { - wg := sync.WaitGroup{} - - for _, file := range files { - stat, err := os.Stat(file) - - if err != nil { - errors <- err - return - } - - if stat.IsDir() { - err = fs.Walk(file, func(name string) { - if !strings.HasSuffix(name, ".q") { - return - } - - fullPath := filepath.Join(file, name) - wg.Add(1) - - go func() { - defer wg.Done() - err := scanFile(fullPath, functions) - - if err != nil { - errors <- err - } - }() - }) - - if err != nil { - errors <- err - } - } else { - wg.Add(1) - - go func() { - defer wg.Done() - err := scanFile(file, functions) - - if err != nil { - errors <- err - } - }() - } - } - - wg.Wait() -} - -// scanFile scans a single file. -func scanFile(path string, functions chan<- *core.Function) error { - contents, err := os.ReadFile(path) - - if err != nil { - return err - } - - tokens := token.Tokenize(contents) - - file := &fs.File{ - Tokens: tokens, - Path: path, - } - - var ( - i = 0 - groupLevel = 0 - blockLevel = 0 - nameStart = -1 - paramsStart = -1 - paramsEnd = -1 - bodyStart = -1 - ) - - for { - // Function name - for i < len(tokens) { - if tokens[i].Kind == token.Identifier { - nameStart = i - i++ - break - } - - if tokens[i].Kind == token.NewLine || tokens[i].Kind == token.Comment { - i++ - continue - } - - if tokens[i].Kind == token.Invalid { - return errors.New(&errors.InvalidCharacter{Character: tokens[i].Text()}, file, tokens[i].Position) - } - - if tokens[i].Kind == token.EOF { - return nil - } - - return errors.New(errors.ExpectedFunctionName, file, tokens[i].Position) - } - - // Function parameters - for i < len(tokens) { - if tokens[i].Kind == token.GroupStart { - groupLevel++ - i++ - - if groupLevel == 1 { - paramsStart = i - } - - continue - } - - if tokens[i].Kind == token.GroupEnd { - groupLevel-- - - if groupLevel < 0 { - return errors.New(errors.MissingGroupStart, file, tokens[i].Position) - } - - if groupLevel == 0 { - paramsEnd = i - i++ - break - } - - i++ - continue - } - - if tokens[i].Kind == token.Invalid { - return errors.New(&errors.InvalidCharacter{Character: tokens[i].Text()}, file, tokens[i].Position) - } - - if tokens[i].Kind == token.EOF { - if groupLevel > 0 { - return errors.New(errors.MissingGroupEnd, file, tokens[i].Position) - } - - if paramsStart == -1 { - return errors.New(errors.ExpectedFunctionParameters, file, tokens[i].Position) - } - - return nil - } - - if groupLevel > 0 { - i++ - continue - } - - return errors.New(errors.ExpectedFunctionParameters, file, tokens[i].Position) - } - - // Function definition - for i < len(tokens) { - if tokens[i].Kind == token.BlockStart { - blockLevel++ - i++ - - if blockLevel == 1 { - bodyStart = i - } - - continue - } - - if tokens[i].Kind == token.BlockEnd { - blockLevel-- - - if blockLevel < 0 { - return errors.New(errors.MissingBlockStart, file, tokens[i].Position) - } - - if blockLevel == 0 { - break - } - - i++ - continue - } - - if tokens[i].Kind == token.Invalid { - return errors.New(&errors.InvalidCharacter{Character: tokens[i].Text()}, file, tokens[i].Position) - } - - if tokens[i].Kind == token.EOF { - if blockLevel > 0 { - return errors.New(errors.MissingBlockEnd, file, tokens[i].Position) - } - - if bodyStart == -1 { - return errors.New(errors.ExpectedFunctionDefinition, file, tokens[i].Position) - } - - return nil - } - - if blockLevel > 0 { - i++ - continue - } - - return errors.New(errors.ExpectedFunctionDefinition, file, tokens[i].Position) - } - - name := tokens[nameStart].Text() - body := tokens[bodyStart:i] - function := core.NewFunction(name, file, body) - parameters := tokens[paramsStart:paramsEnd] - count := 0 - - err := expression.EachParameter(parameters, func(tokens token.List) error { - if len(tokens) != 1 { - return errors.New(errors.NotImplemented, file, tokens[0].Position) - } - - name := tokens[0].Text() - register := x64.CallRegisters[count] - uses := token.Count(function.Body, token.Identifier, name) - - if uses == 0 { - return errors.New(&errors.UnusedVariable{Name: name}, file, tokens[0].Position) - } - - variable := &core.Variable{ - Name: name, - Register: register, - Alive: uses, - } - - function.AddVariable(variable) - count++ - return nil - }) - - if err != nil { - return err - } - - functions <- function - nameStart = -1 - paramsStart = -1 - bodyStart = -1 - i++ - } + return scanner.functions, scanner.errors } diff --git a/src/build/scanner/Scanner.go b/src/build/scanner/Scanner.go new file mode 100644 index 0000000..9725e3b --- /dev/null +++ b/src/build/scanner/Scanner.go @@ -0,0 +1,14 @@ +package scanner + +import ( + "sync" + + "git.akyoto.dev/cli/q/src/build/core" +) + +// Scanner is used to scan files before the actual compilation step. +type Scanner struct { + functions chan *core.Function + errors chan error + group sync.WaitGroup +} diff --git a/src/build/scanner/queue.go b/src/build/scanner/queue.go new file mode 100644 index 0000000..6ccfc15 --- /dev/null +++ b/src/build/scanner/queue.go @@ -0,0 +1,21 @@ +package scanner + +import "os" + +// queue scans the list of files. +func (s *Scanner) queue(files ...string) { + for _, file := range files { + stat, err := os.Stat(file) + + if err != nil { + s.errors <- err + return + } + + if stat.IsDir() { + s.queueDirectory(file, "") + } else { + s.queueFile(file, "") + } + } +} diff --git a/src/build/scanner/queueDirectory.go b/src/build/scanner/queueDirectory.go new file mode 100644 index 0000000..21b32e8 --- /dev/null +++ b/src/build/scanner/queueDirectory.go @@ -0,0 +1,24 @@ +package scanner + +import ( + "path/filepath" + "strings" + + "git.akyoto.dev/cli/q/src/build/fs" +) + +// queueDirectory queues an entire directory to be scanned. +func (s *Scanner) queueDirectory(directory string, pkg string) { + err := fs.Walk(directory, func(name string) { + if !strings.HasSuffix(name, ".q") { + return + } + + fullPath := filepath.Join(directory, name) + s.queueFile(fullPath, pkg) + }) + + if err != nil { + s.errors <- err + } +} diff --git a/src/build/scanner/queueFile.go b/src/build/scanner/queueFile.go new file mode 100644 index 0000000..6981f7a --- /dev/null +++ b/src/build/scanner/queueFile.go @@ -0,0 +1,15 @@ +package scanner + +// queueFile queues a single file to be scanned. +func (s *Scanner) queueFile(file string, pkg string) { + s.group.Add(1) + + go func() { + defer s.group.Done() + err := s.scanFile(file, pkg) + + if err != nil { + s.errors <- err + } + }() +} diff --git a/src/build/scanner/scanFile.go b/src/build/scanner/scanFile.go new file mode 100644 index 0000000..7407bd7 --- /dev/null +++ b/src/build/scanner/scanFile.go @@ -0,0 +1,238 @@ +package scanner + +import ( + "fmt" + "os" + "path/filepath" + + "git.akyoto.dev/cli/q/src/build/arch/x64" + "git.akyoto.dev/cli/q/src/build/config" + "git.akyoto.dev/cli/q/src/build/core" + "git.akyoto.dev/cli/q/src/build/errors" + "git.akyoto.dev/cli/q/src/build/expression" + "git.akyoto.dev/cli/q/src/build/fs" + "git.akyoto.dev/cli/q/src/build/keyword" + "git.akyoto.dev/cli/q/src/build/token" +) + +// scanFile scans a single file. +func (s *Scanner) scanFile(path string, pkg string) error { + contents, err := os.ReadFile(path) + + if err != nil { + return err + } + + tokens := token.Tokenize(contents) + + file := &fs.File{ + Tokens: tokens, + Path: path, + } + + var ( + i = 0 + groupLevel = 0 + blockLevel = 0 + nameStart = -1 + paramsStart = -1 + paramsEnd = -1 + bodyStart = -1 + ) + + for { + for i < len(tokens) && tokens[i].Kind == token.Keyword && tokens[i].Text() == keyword.Import { + i++ + + if tokens[i].Kind != token.Identifier { + panic("expected package name") + } + + packageName := tokens[i].Text() + s.queueDirectory(filepath.Join(config.Library, packageName), packageName) + + i++ + + if tokens[i].Kind != token.NewLine && tokens[i].Kind != token.EOF { + panic("expected newline or eof") + } + + i++ + } + + // Function name + for i < len(tokens) { + if tokens[i].Kind == token.Identifier { + nameStart = i + i++ + break + } + + if tokens[i].Kind == token.NewLine || tokens[i].Kind == token.Comment { + i++ + continue + } + + if tokens[i].Kind == token.Invalid { + return errors.New(&errors.InvalidCharacter{Character: tokens[i].Text()}, file, tokens[i].Position) + } + + if tokens[i].Kind == token.EOF { + return nil + } + + return errors.New(errors.ExpectedFunctionName, file, tokens[i].Position) + } + + // Function parameters + for i < len(tokens) { + if tokens[i].Kind == token.GroupStart { + groupLevel++ + i++ + + if groupLevel == 1 { + paramsStart = i + } + + continue + } + + if tokens[i].Kind == token.GroupEnd { + groupLevel-- + + if groupLevel < 0 { + return errors.New(errors.MissingGroupStart, file, tokens[i].Position) + } + + if groupLevel == 0 { + paramsEnd = i + i++ + break + } + + i++ + continue + } + + if tokens[i].Kind == token.Invalid { + return errors.New(&errors.InvalidCharacter{Character: tokens[i].Text()}, file, tokens[i].Position) + } + + if tokens[i].Kind == token.EOF { + if groupLevel > 0 { + return errors.New(errors.MissingGroupEnd, file, tokens[i].Position) + } + + if paramsStart == -1 { + return errors.New(errors.ExpectedFunctionParameters, file, tokens[i].Position) + } + + return nil + } + + if groupLevel > 0 { + i++ + continue + } + + return errors.New(errors.ExpectedFunctionParameters, file, tokens[i].Position) + } + + // Function definition + for i < len(tokens) { + if tokens[i].Kind == token.BlockStart { + blockLevel++ + i++ + + if blockLevel == 1 { + bodyStart = i + } + + continue + } + + if tokens[i].Kind == token.BlockEnd { + blockLevel-- + + if blockLevel < 0 { + return errors.New(errors.MissingBlockStart, file, tokens[i].Position) + } + + if blockLevel == 0 { + break + } + + i++ + continue + } + + if tokens[i].Kind == token.Invalid { + return errors.New(&errors.InvalidCharacter{Character: tokens[i].Text()}, file, tokens[i].Position) + } + + if tokens[i].Kind == token.EOF { + if blockLevel > 0 { + return errors.New(errors.MissingBlockEnd, file, tokens[i].Position) + } + + if bodyStart == -1 { + return errors.New(errors.ExpectedFunctionDefinition, file, tokens[i].Position) + } + + return nil + } + + if blockLevel > 0 { + i++ + continue + } + + return errors.New(errors.ExpectedFunctionDefinition, file, tokens[i].Position) + } + + name := tokens[nameStart].Text() + body := tokens[bodyStart:i] + + if pkg != "" { + name = fmt.Sprintf("%s.%s", pkg, name) + } + + function := core.NewFunction(name, file, body) + parameters := tokens[paramsStart:paramsEnd] + count := 0 + + err := expression.EachParameter(parameters, func(tokens token.List) error { + if len(tokens) != 1 { + return errors.New(errors.NotImplemented, file, tokens[0].Position) + } + + name := tokens[0].Text() + register := x64.CallRegisters[count] + uses := token.Count(function.Body, token.Identifier, name) + + if uses == 0 { + return errors.New(&errors.UnusedVariable{Name: name}, file, tokens[0].Position) + } + + variable := &core.Variable{ + Name: name, + Register: register, + Alive: uses, + } + + function.AddVariable(variable) + count++ + return nil + }) + + if err != nil { + return err + } + + s.functions <- function + nameStart = -1 + paramsStart = -1 + bodyStart = -1 + i++ + } +} diff --git a/tests/programs/branch-and.q b/tests/programs/branch-and.q index 6761f1e..9995b34 100644 --- a/tests/programs/branch-and.q +++ b/tests/programs/branch-and.q @@ -1,37 +1,35 @@ +import sys + main() { x := 0 if x != x && x != x { - exit(1) + sys.exit(1) } if x == x && x != x { - exit(1) + sys.exit(1) } if x != x && x == x { - exit(1) + sys.exit(1) } if x == x && x != x && x != x { - exit(1) + sys.exit(1) } if x != x && x == x && x != x { - exit(1) + sys.exit(1) } if x != x && x != x && x == x { - exit(1) + sys.exit(1) } if x == x && x == x && x == x { - exit(0) + sys.exit(0) } - exit(1) -} - -exit(x) { - syscall(60, x) + sys.exit(1) } \ No newline at end of file diff --git a/tests/programs/branch-both.q b/tests/programs/branch-both.q index b8e7029..ef35461 100644 --- a/tests/programs/branch-both.q +++ b/tests/programs/branch-both.q @@ -1,47 +1,45 @@ +import sys + main() { x := 0 if x == x && x != x || x != x && x != x { - exit(1) + sys.exit(1) } if x != x && x == x || x != x && x != x { - exit(1) + sys.exit(1) } if x != x && x != x || x == x && x != x { - exit(1) + sys.exit(1) } if x != x && x != x || x != x && x == x { - exit(1) + sys.exit(1) } if (x == x || x != x) && (x != x || x != x) { - exit(1) + sys.exit(1) } if (x != x || x == x) && (x != x || x != x) { - exit(1) + sys.exit(1) } if (x != x || x != x) && (x == x || x != x) { - exit(1) + sys.exit(1) } if (x != x || x != x) && (x != x || x == x) { - exit(1) + sys.exit(1) } if (x == x && x != x || x == x && x == x) && (x == x && x == x || x == x && x != x) { if (x != x || x == x) && (x != x || x != x) || (x == x || x != x) && (x != x || x == x) { - exit(0) + sys.exit(0) } } - exit(1) -} - -exit(x) { - syscall(60, x) + sys.exit(1) } \ No newline at end of file diff --git a/tests/programs/branch-or.q b/tests/programs/branch-or.q index da340a8..814f5b0 100644 --- a/tests/programs/branch-or.q +++ b/tests/programs/branch-or.q @@ -1,12 +1,14 @@ +import sys + main() { x := 0 if x != x || x != x { - exit(1) + sys.exit(1) } if x != x || x != x || x != x { - exit(1) + sys.exit(1) } if x == x || x != x { @@ -14,16 +16,12 @@ main() { if x == x || x != x || x != x { if x != x || x == x || x != x { if x != x || x != x || x == x { - exit(0) + sys.exit(0) } } } } } - exit(1) -} - -exit(x) { - syscall(60, x) + sys.exit(1) } \ No newline at end of file diff --git a/tests/programs/branch.q b/tests/programs/branch.q index 8887013..aaa393f 100644 --- a/tests/programs/branch.q +++ b/tests/programs/branch.q @@ -1,75 +1,73 @@ +import sys + main() { x := 0 if x != 0 { - exit(1) + sys.exit(1) } if x > 0 { - exit(1) + sys.exit(1) } if x < 0 { - exit(1) + sys.exit(1) } if 0 != x { - exit(1) + sys.exit(1) } if 0 > x { - exit(1) + sys.exit(1) } if 0 < x { - exit(1) + sys.exit(1) } if x >= 1 { - exit(1) + sys.exit(1) } if 1 <= x { - exit(1) + sys.exit(1) } if x + 1 != x + 1 { - exit(1) + sys.exit(1) } if x + 1 != inc(x) { - exit(1) + sys.exit(1) } if x - 1 != dec(x) { - exit(1) + sys.exit(1) } if inc(x) != x + 1 { - exit(1) + sys.exit(1) } if dec(x) != x - 1 { - exit(1) + sys.exit(1) } if x != inc(dec(x)) { - exit(1) + sys.exit(1) } if inc(dec(x)) != x { - exit(1) + sys.exit(1) } if x == 0 { - exit(0) + sys.exit(0) } - exit(1) -} - -exit(x) { - syscall(60, x) + sys.exit(1) } inc(x) { diff --git a/tests/programs/chained-calls.q b/tests/programs/chained-calls.q index 95cb219..49ddb84 100644 --- a/tests/programs/chained-calls.q +++ b/tests/programs/chained-calls.q @@ -1,9 +1,7 @@ -main() { - exit(f(1) + f(2) + f(3)) -} +import sys -exit(code) { - syscall(60, code) +main() { + sys.exit(f(1) + f(2) + f(3)) } f(x) { diff --git a/tests/programs/jump-near.q b/tests/programs/jump-near.q index 7af145d..af48760 100644 --- a/tests/programs/jump-near.q +++ b/tests/programs/jump-near.q @@ -1,3 +1,5 @@ +import sys + main() { x := 10 @@ -175,13 +177,13 @@ main() { fail() } - exit(0) + success() } fail() { - exit(1) + sys.exit(1) } -exit(code) { - syscall(60, code) +success() { + sys.exit(0) } \ No newline at end of file diff --git a/tests/programs/nested-calls.q b/tests/programs/nested-calls.q index 8844729..f226bcb 100644 --- a/tests/programs/nested-calls.q +++ b/tests/programs/nested-calls.q @@ -1,9 +1,7 @@ -main() { - exit(f(f(f(1)))) -} +import sys -exit(code) { - syscall(60, code) +main() { + sys.exit(f(f(f(1)))) } f(x) {