Skip to content

Dynamic memory allocation - #61

Closed
jorge-leon wants to merge 66 commits into
hughbarney:masterfrom
jorge-leon:dynamic-memory-allocation
Closed

Dynamic memory allocation#61
jorge-leon wants to merge 66 commits into
hughbarney:masterfrom
jorge-leon:dynamic-memory-allocation

Conversation

@jorge-leon

Copy link
Copy Markdown
Contributor

This PR add dynamic memory allocation to the fLisp interpreter. When free space after a garbage collection cycle is not sufficient
to allocate the required space, more memory is allocated and the garbage collection cycle is restarted.

The consequences are:

  • Femto does not run out of space on more demanding applications.
  • Femto does not need to be recompiled to allow for more Lisp object space.
  • Infinite recursion will consume all available memory before exiting fatally.
  • fLisp application can be built with very little memory demand, start with about 21 kB.

Fatal exists have been introduced into the fLisp core when memory allocation fails. They exit with codes 64, 65, 66 and 67.

This PR includes also #59 and #60, see there description for included features.

Georg Lehner and others added 30 commits August 25, 2025 22:07
See test/1_dired.lsp for a demo test suite

Run `make ltest`  to execute it.
tap code is simplified: instead of appending a test to the test list it is
prepended and the list of tests is reversed before iterating over it.

This adds `reverse` and `flip` to the flisp library.
The `run` test suite runner is renamed to `test` and it got proper command
line parsing.

All test suites must be named *.test.  The first line determines if it is
to be tested by poor mans shell test runner within flips or by the Lisp implementation
tap.lsp within femto.

The first line must contain the Emacs mode string: -*- mode: _type_ -*-
where type is `sh` for flisp and `lisp` for femto.

`tap.lsp` has a simple command line parser to specifiy the test(s) to run.

For writing test scripts:

Write a function which returns a true value if the test passes.

Register the function and a test comment with tap.lsp:

`(tap-register comment function)`
Will need this for file mode operations.
Added file.h, flisp_file_primitives struct in file.c and load it in
initRootEnv() in lisp.c
Parametrized readNumberOrSymbol to compile for integer only if double
extension is not required.
Since the double extension is practically required, it must be declared
in the build of all extension files to not get the type enums wrongly
ordered.
fstat returns a property list with size, mode uid, gid and type, type as string.

It throws one of the following exceptions:
- permission-denied
- not-found
- io-error

(catch (fstat path)) can therefore be used to test for existence of files.
Duplicate "catch" code in lisp-eval() is replaced by using evalCatch.

The only interface with the interpreter is now interp->object, which
receives a catch object (error_type message object).

If error_type == nil, object is the result, otherwise object is the err'ed
object (or nil) and message a string object, message->string the error
message.
to- and fromSpace are allocated individually and resized on demand.

FLISP_MEMORY_INC_SIZE determines the size of allocation junks.

Note: While all tests pass when sufficient initial memory is given,
  gc_always still segfaults.
Must be rewritten in Lisp
…ory size

The interpreter allocates a minimal chunk of memory to boot itself on
start. After that, every time the Lisp object memory is to small, it is
increased by a specific chunk size.

Both parameters: FLISP_MIN_MEMORY and FLISP_MEMORY_INC_SIZE are defined
lisp.h.

While the approach is working well, there are problems with segfaults, when
using gc_always.  These seem to be related to wrong GC_TRACE'ing

Note: on startup the interpreter prints out, how much memory is used for
the initial startup. We round it up manually to the chunk size.
Georg Lehner and others added 27 commits September 2, 2025 23:09
Somewhere - probably in (cond) is a heisenbug causing segfaults on startup
of femto with commandline arguments.

(string-contains) showed the problem, replacing it with the (string-search)
search primitives resolves the issue.

The heisenbug is still there - and not.
Would not survive gc_always
Otherwise the interpreter pointer is hardcoded as 'interp'
If FLISP_INITIAL_MEMORY is specified, it adds to the minimum amount needed
to start the fLisp interpreter. Please note that only half of the amount is
actually available, the other half is used for garbage collection.

For femto currently 512k(256k) is enough to start up without initiating
garbage collection cycles.
Expose ungetc and getc on Lisp level, with optional stream argument.

Replace streamUngetc with ungetc and only throw exceptions where
appropriate.
Append taken from https://www.scheme.com/tspl2d/objects.html#g2052

Simple minded apply implementation: probably slow.
All done items sorted into their version section.
@jorge-leon

Copy link
Copy Markdown
Contributor Author

Superseded by #62

@jorge-leon jorge-leon closed this Nov 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant