added hsargs, hsexit and bundler mode

This commit is contained in:
Luxferre
2026-07-04 08:52:56 +03:00
parent 10f0b39d8e
commit 4fc3ee518a
7 changed files with 116 additions and 1 deletions
+18
View File
@@ -120,6 +120,24 @@ To run a program directly, pass the path to the `.clx` file as an argument:
./clyx path/to/program.clx
```
### Self-contained Packaging (Compilation)
The Go implementation supports reading an optional ZIP archive appended directly to the end of the `clyx` binary. This allows you to package your Clyx source code into a single executable file.
To package your program:
1. Create a ZIP archive containing all your `.clx` source files.
2. Append the ZIP archive to the compiled `clyx` binary:
```sh
cat clyx my_app.zip > my_app_executable
chmod +x my_app_executable
```
When the packed executable runs:
- The interpreter automatically detects the appended ZIP archive.
- It iterates through all `.clx` files in the archive and evaluates (`src`) them.
- If a `_main` word is defined in the environment, it is executed automatically.
- If `_main` is not present, the interpreter falls back to running the standard REPL.
## FAQ
### Where does the name Clyx originate from?
+8
View File
@@ -313,6 +313,12 @@ func (c *Clyx) Eval(q any) {
}
}
func (c *Clyx) HasWord(name string) bool {
_, ok := c.words[name]
return ok
}
func printVal(v any) {
switch val := v.(type) {
case int64: fmt.Printf("%d\n", val)
@@ -420,6 +426,8 @@ func NewClyx(libfname string, libCode string) *Clyx {
c.words[".s"] = func() { printVal(c.reprStack()) }
c.words["dip"] = func() { q, y := c.pop().([]any), c.pop(); c.execQuot(q); c.stack = append(c.stack, y) }
c.words["loop"] = func() { body, cond := c.pop().([]any), c.pop().([]any); for { c.execQuot(cond); if !isTruthy(c.pop()) { break }; c.execQuot(body) } }
c.words["hsargs"] = func() { c.stack = append(c.stack, toAnySlice(os.Args)) }
c.words["hsexit"] = func() { os.Exit(int(toInt(c.pop()))) }
c.words["hseval"] = func() { fmt.Fprintln(os.Stderr, "Error: unsupported word"); os.Exit(1) }
c.words["chr"] = func() { c.stack = append(c.stack, string(rune(toInt(c.pop())))) }
c.words["asc"] = func() { s := c.pop().(string); r, _ := utf8.DecodeRuneInString(s); c.stack = append(c.stack, int64(r)) }
+2
View File
@@ -62,6 +62,8 @@ class Clyx:
'delf': lambda: os.remove(self._stack.pop()), 'maked': lambda: os.mkdir(self._stack.pop()), 'listd': lambda: self._stack.append(os.listdir(self._stack.pop())), 'deld': lambda: os.rmdir(self._stack.pop()),
'rand': lambda: self._stack.append(randrange(int(self._stack.pop()))), '.s': lambda: self._out_num(repr(self._stack)), 'dip': lambda: (lambda q, y: (self._exec_quot(q), self._stack.append(y)))(self._stack.pop(), self._stack.pop()),
'loop': lambda: (lambda body, cond: self._exec_loop(cond, body))(self._stack.pop(), self._stack.pop()),
'hsargs': lambda: self._stack.append(list(sys.argv)),
'hsexit': lambda: sys.exit(int(self._stack.pop())),
'hseval': lambda: self._stack.append(eval(self._stack.pop())),
'chr': lambda: self._stack.append(chr(int(self._stack.pop()))), 'asc': lambda: self._stack.append(ord(self._stack.pop())),
'sin': lambda: self._stack.append(math.sin(float(self._stack.pop()))), 'cos': lambda: self._stack.append(math.cos(float(self._stack.pop()))), 'atan': lambda: self._stack.append(math.atan(float(self._stack.pop()))),
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "clyx"
version = "0.1.1"
version = "0.2"
description = "Clyx programming language interpreter"
readme = "README.md"
requires-python = ">=3.7"
+8
View File
@@ -282,6 +282,14 @@ Any line fragment starting with `#` to the end of the physical source line is re
- **Stack Effect**: `( -- )`
- **Description**: Prints the current stack representation to standard output (useful for debugging).
### `hsargs` (Host Arguments)
- **Stack Effect**: `( -- [args] )`
- **Description**: Pushes a list/quotation of all passed command line arguments onto the stack.
### `hsexit` (Host Exit)
- **Stack Effect**: `( code -- )`
- **Description**: Exits the program/interpreter with the specified exit code.
### `hseval` (Host Language Evaluation)
- **Stack Effect**: `( expr -- val )`
- **Description**: Pops the string `expr` from the stack, evaluates it as an expression in the host language (e.g., Python), and pushes the resulting value back onto the stack.
+69
View File
@@ -4,9 +4,12 @@
package main
import (
"archive/zip"
_ "embed"
"fmt"
"io"
"os"
"strings"
clyx "codeberg.org/luxferre/clyx/clyx-go"
)
@@ -17,7 +20,73 @@ var defaultLibCode string
//go:embed clyx_repl.clx
var defaultReplCode string
func runZipArchive(zr *zip.Reader) error {
defer func() {
if r := recover(); r != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", r)
os.Exit(1)
}
}()
c := clyx.NewClyx("", defaultLibCode)
for _, file := range zr.File {
if !file.FileInfo().IsDir() && strings.HasSuffix(strings.ToLower(file.Name), ".clx") {
rc, err := file.Open()
if err != nil {
return fmt.Errorf("error opening %s in archive: %w", file.Name, err)
}
data, err := io.ReadAll(rc)
rc.Close()
if err != nil {
return fmt.Errorf("error reading %s in archive: %w", file.Name, err)
}
c.Run(string(data))
}
}
if c.HasWord("_main") {
c.Run("_main")
} else {
c.Run(defaultReplCode)
}
return nil
}
func detectAndRunZip() bool {
exePath, err := os.Executable()
if err != nil {
return false
}
f, err := os.Open(exePath)
if err != nil {
return false
}
defer f.Close()
info, err := f.Stat()
if err != nil {
return false
}
zr, err := zip.NewReader(f, info.Size())
if err != nil {
return false // No ZIP appended
}
// ZIP found! Run it
if err := runZipArchive(zr); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
return true
}
func main() {
if detectAndRunZip() {
return
}
if len(os.Args) > 1 {
clyx.RunFile(os.Args[1], defaultLibCode)
} else {
+10
View File
@@ -215,3 +215,13 @@ my_inline 100 = if [ " :: (inline) PASS" puts cr ] [ " :: (inline) FAIL" puts
# " hseval FAIL" puts cr
# ]
# 12. Host Arguments & Host Exit
"Testing host arguments and exit..." puts cr
hsargs isquot [ hsargs qlen 0 > ] and if [
" hsargs PASS" puts cr
] [
" hsargs FAIL" puts cr
]
0 hsexit