From ce18aa76b54517513ab633739da8cd0215574c7c Mon Sep 17 00:00:00 2001 From: Luxferre Date: Sat, 4 Jul 2026 09:23:54 +0300 Subject: [PATCH] added consistent _main --- README.md | 11 +++++------ clyx-python/clyx/clyx.py | 15 ++++++++++++++- clyx_manual.md | 5 +++++ main.go | 25 ++++++++++++++++++++++++- 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index acc32e4..d84fa19 100644 --- a/README.md +++ b/README.md @@ -84,13 +84,12 @@ This will build the `clyx` executable. Note: this section describes how to run the interpreter itself. For the language manual, refer to [Clyx Reference Manual](clyx_manual.md). -All core implementations must accept a `.clx` file to run (either via command line or via library call parameter). The REPL is implemented in Clyx itself and resides in the [clyx_repl.clx](clyx_repl.clx) file. +All core implementations must accept one or more `.clx` files to run (either via command line or via library call parameter). If multiple files are passed, they are executed in sequence. If a `_main` word is defined in the workspace after running all source files, it is automatically executed as the entry point. The REPL is implemented in Clyx itself and resides in the [clyx_repl.clx](clyx_repl.clx) file. ### Running the reference Python implementation +If Clyx is installed as a PyPi package, use `clyx [prog1.clx prog2.clx ...]` to run the REPL or one or more programs. -If Clyx is installed as a PyPi package, just use `clyx [prog.clx]` to run the REPL or a program. - -Otherwise, to run the REPL, run `[micro]python clyx.py` command from the directory created by `./dist-python.sh`. Pass a `.clx` file additionally to run a Clyx program directly. +Otherwise, to run the REPL, run `[micro]python clyx.py` command from the directory created by `./dist-python.sh`. Pass one or more `.clx` files additionally to run them directly. ### Running as a T-DeckARD applet @@ -114,10 +113,10 @@ To run the REPL, execute the compiled `clyx` binary without arguments: ./clyx ``` -To run a program directly, pass the path to the `.clx` file as an argument: +To run programs directly, pass the path to the `.clx` files as arguments: ```sh -./clyx path/to/program.clx +./clyx path/to/program1.clx path/to/program2.clx ``` ### Self-contained Packaging (Compilation) diff --git a/clyx-python/clyx/clyx.py b/clyx-python/clyx/clyx.py index 5020652..aa148bf 100755 --- a/clyx-python/clyx/clyx.py +++ b/clyx-python/clyx/clyx.py @@ -127,6 +127,19 @@ def clyx(f): except Exception as e: (sys.stderr.write(f'Error executing {f}: {e}\n'), sys.exit(1)) repl = lambda: clyx(replpath) -def main(): clyx(sys.argv[1] if len(sys.argv) > 1 else replpath) +def main(): + if len(sys.argv) > 1: + c = Clyx() + for f in sys.argv[1:]: + try: + with open(f) as file: + c.run(file.read()) + except Exception as e: + sys.stderr.write(f'Error executing {f}: {e}\n') + sys.exit(1) + if '_main' in c._words: + c.run('_main') + else: + repl() if __name__ == '__main__': main() diff --git a/clyx_manual.md b/clyx_manual.md index 22cfd55..4921b12 100644 --- a/clyx_manual.md +++ b/clyx_manual.md @@ -8,6 +8,11 @@ The Clyx runtime itself allows the programmer to redefine any already defined wo The conventional source file suffix for Clyx code is `.clx`. +### Execution and Entry Point +The Clyx interpreter accepts one or more `.clx` source files as command-line arguments. If multiple files are specified, the interpreter executes them in the order they are passed. + +After running all specified source files, the interpreter checks if a word named `_main` is defined in the workspace. If `_main` is present, it is automatically executed as the program's entry point. If no arguments are passed, it runs the standard interactive REPL. + With the reference implementation installed in a POSIX-compatible environment, Clyx program sources may be made executable if they start with a `#!/usr/bin/env clyx` shebang. --- diff --git a/main.go b/main.go index d6b3a51..6a09bef 100644 --- a/main.go +++ b/main.go @@ -82,13 +82,36 @@ func detectAndRunZip() bool { return true } +func runFiles(files []string) { + defer func() { + if r := recover(); r != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", r) + os.Exit(1) + } + }() + + c := clyx.NewClyx("", defaultLibCode) + for _, filePath := range files { + content, err := os.ReadFile(filePath) + if err != nil { + fmt.Fprintf(os.Stderr, "Error executing %s: %v\n", filePath, err) + os.Exit(1) + } + c.Run(string(content)) + } + + if c.HasWord("_main") { + c.Run("_main") + } +} + func main() { if detectAndRunZip() { return } if len(os.Args) > 1 { - clyx.RunFile(os.Args[1], defaultLibCode) + runFiles(os.Args[1:]) } else { defer func() { if r := recover(); r != nil {