No description
Find a file
2026-04-11 17:25:21 -05:00
.tangled/workflows Actually fix benchmark_compilers.yaml 2026-04-04 16:40:57 -05:00
benchmark Remove some old comments 2026-04-04 20:13:50 -05:00
doc Fix a memory error in strings.join and lists.del 2026-04-06 15:10:58 -05:00
include Add pup_vm.use_jmpbuf so that setjmp/longjmp is optional 2026-04-06 03:56:41 -05:00
sample Fix a memory error in strings.join and lists.del 2026-04-06 15:10:58 -05:00
scripts Fix some memory errors 2026-04-06 03:32:37 -05:00
src Add sys.getenv 2026-04-11 17:25:21 -05:00
std Add lists.of, lists.merge, clone (builtin), fix a bug with returns, microoptimise hashing a little bit, clean up suite scripts 2026-04-04 15:53:23 -05:00
test Fix non-returning functions not implicitly returning nil and fix parsing to allow empty parameter lists 2026-03-28 13:41:26 -05:00
.gitattributes Fix comment lexing. Add guide.md and .gitattributes 2026-02-06 12:33:24 -06:00
.gitignore Micro-optimisations 2026-03-28 03:10:06 -05:00
license I forgot to license puppy until just now... 2026-02-24 12:24:02 -06:00
readme Update readme 2026-04-05 20:35:26 -05:00
run.sh Fix build/static and add more install/* scripts 2026-02-24 17:56:09 -06:00

puppy
=====

A minimalistic scripting language for embedding.

  greet(whom: str) =
    print("Hello, ", whom.name, "!");

  main {
    let names = ["Gandalf", "Bilbo", "Frodo"];
    for name in names {
      greet(name);
    }
  }

install
-------

Dependencies: sh, a c99 compiler, git

  git clone https://tangled.org/emmeline.girlkisser.top/puppy
  cd puppy
  sh run.sh "build/standalone release" install/by-cp
  # puppy's executable will be copied to ~/.local/bin/puppy.

You can also use `install/by-ln` to install via a symlink
instead, if you prefer.

To install development headers and the shared library:

  sh run.sh "build/shared release" install/headers install/shared

To perform a full system-wide install (i.e, headers, shared
library, and executable):

  sh run.sh "build/standalone release" "build/shared release"

  # Make sure to delete previously installed headers as the
  # script does not do this automatically:
  sudo rm -rf /usr/local/include/puppy/

  sudo sh run.sh install/headers install/shared "install/by-cp /usr/local/bin/"

develop
-------

Build dependencies: sh, a c99 compiler, git
Optional dependencies: valgrind, gdb, ccache

Build+run:
  sh run.sh build/standalone "run ./sample/hello.pup"

I highly recommend using Valgrind or GDB when running:
  sh run.sh build/standalone "run/valgrind ./sample/hello.pup"
  sh run.sh build/standalone "run/gdb ./sample/hello.pup"

Depending on your distro, you may get `vgcore` files in the
cwd when running Valgrind. You can use the `clean/vgcore`
script to clean these. Additionally, `clean` will clean all
core dumps along with other binaries and test outputs.

For now, Windows users will likely need to use MinGW or WSL
to compile Puppy. I use a handful of POSIX functions for
file interactions.

To test Puppy, use the `test` script. You can also test a
specific group with `test/{samples,tests}`. Results are
stored in `results/{samples,tests}/` as plaintext files
containing the stdout and stderr of the test. Generally,
I test with the following command:
  sh run.sh clean build/standalone test

Globally install the headers and shared library:
  sh run.sh clean build/shared install/shared install/headers

Copy headers and static library to another directory:
  export DEST=~/Projects/my-puppy-project/
  mkdir -p $DEST/include/
  sh run.sh clean build/static "install/static $DEST" "install/headers $DEST/include/"

Build with verbose logging enabled:
  ADD_CFLAGS="-DPUP_VERBOSE=1" sh run.sh build/standalone

Build with Clang (or any other C compiler):
  CC="clang" sh run.sh build/standalone

Profiling with Callgrind:
  ADD_CFLAGS="-g" sh run.sh "build/standalone release" "run/callgrind benchmark/one_million_iterations/bench.pup"
  # See callgrind.out.$PID

Profiling with Gprof:
  sh run.sh "build/standalone release/gprof" "run/gprof benchmark/one_million_iterations/bench.pup"
  # See gprof-output.txt

Benchmark local Puppy build against other languages:
  sh run.sh "build/standalone release" "benchmark/languages benchmark/one_million_iterations/"

Benchmark Puppy built with assorted compilers and flags:
  # Build with GCC, Clang, and TCC. Each with different performance options. This may take a bit to finish.
  sh run.sh "build/standalone-suite compilers"
  # Run the provided Puppy file with each build and pipe the results to reuslts/compiler-comparison.txt.
  sh run.sh "benchmark/suite benchmark/one_million_iterations/bench.pup" > results/compiler-comparison.txt 2>&1

todo
----

. Change VM/framestacks to hold variables in a single hash
table instead of many small hash tables. In theory, this
should provide a substantial performance improvement to
variable lookups. The problem with this is doing it in a
way that still allows variable shadowing.
x Improve syntax+thrown errors and completely change how
errors are handled in the C API. exit() should be seldom
used.
x Document API and clean up source
. Optimise memory layout to keep memory more contiguous.
I'm thinking that I could allocate a large arena at the
start of the program and allocate anything that'll stick
around inside that. Dynamic objects like the stack might be
more tedious since they're likely to move around in memory
as the program runs for longer periods of time. Maybe I
could make the "main" part of the stack live in the arena
and then separate out the "extra" (less commonly accessed)
part elsewhere in memory as needed. Basically a "chunked
dynamic list" of some kind. Resizing hash tables would be
more tedious, but I'm sure there's an optimization I could
implement.
x String interning
. Update _strfind to use a more optimal implementation.