diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1bd6ad7bf4..59957f02db 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,5 +1,9 @@ name: Build and Test +permissions: + contents: read + packages: write + on: push: {} pull_request: {} @@ -12,32 +16,46 @@ on: jobs: get-matrix: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 outputs: - do-linux: ${{ steps.get-matrix-step.outputs.do-linux }} + do-linux: ${{ steps.get-matrix-step.outputs.do_linux }} matrix-linux: ${{ steps.get-matrix-step.outputs.linux }} - do-macos: ${{ steps.get-matrix-step.outputs.do-macos }} + do-macos: ${{ steps.get-matrix-step.outputs.do_macos }} matrix-macos: ${{ steps.get-matrix-step.outputs.macos }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - id: files if: ${{ github.event_name != 'workflow_dispatch' }} - uses: kanaka/get-changed-files@v1 + uses: kanaka/get-changed-files@v2 + with: + default_base: master - id: get-matrix-step run: | export OVERRIDE_IMPLS="${{ github.event.inputs.impls }}" # " echo "OVERRIDE_IMPLS: ${OVERRIDE_IMPLS}" - ./get-ci-matrix.py ${{ steps.files.outputs.all }} + ./get-ci-matrix.py ${{ steps.files.outputs.all }} > "${GITHUB_OUTPUT}" linux: needs: get-matrix if: ${{ needs.get-matrix.outputs.do-linux == 'true' }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: ${{ fromJson(needs.get-matrix.outputs.matrix-linux) }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Need full history for voom like versions + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Docker Build/Push + run: | + export ${{ matrix.IMPL }} + ./ci.sh docker-build-push ${IMPL} - name: Build run: | export ${{ matrix.IMPL }} @@ -55,9 +73,9 @@ jobs: export ${{ matrix.IMPL }} ./ci.sh perf ${IMPL} - name: Archive logs and debug output - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: - name: logs + name: logs.${{ matrix.IMPL }} path: | *.log *.debug @@ -65,12 +83,12 @@ jobs: macos: needs: get-matrix if: ${{ needs.get-matrix.outputs.do-macos == 'true' }} - runs-on: macos-10.15 + runs-on: macos-12 strategy: fail-fast: false matrix: ${{ fromJson(needs.get-matrix.outputs.matrix-macos) }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Build run: | export ${{ matrix.IMPL }} @@ -88,9 +106,9 @@ jobs: export ${{ matrix.IMPL }} ./ci.sh perf ${IMPL} - name: Archive logs and debug output - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: - name: logs + name: logs.${{ matrix.IMPL }} path: | *.log *.debug diff --git a/Makefile b/Makefile index 7d47ad44fb..ff1cd7a643 100644 --- a/Makefile +++ b/Makefile @@ -126,7 +126,7 @@ STEP_TEST_FILES = $(strip $(wildcard \ # DOCKERIZE utility functions lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$1)))))))))))))))))))))))))) -impl_to_image = kanaka/mal-test-$(call lc,$(1)) +impl_to_image = ghcr.io/kanaka/mal-test-$(call lc,$(1)):$(shell ./voom-like-version.sh impls/$(1)/Dockerfile) actual_impl = $(if $(filter mal,$(1)),$(patsubst %-mal,%,$(MAL_IMPL)),$(1)) @@ -143,7 +143,7 @@ get_build_command = $(strip $(foreach mode,$(1)_MODE, \ $(if $(strip $($(mode))),-e $(mode)=$($(mode)),) \ $(if $(filter factor,$(1)),-e FACTOR_ROOTS=$(FACTOR_ROOTS),) \ $(call impl_to_image,$(1)) \ - $(MAKE) $(if $(strip $($(mode))),$(mode)=$($(mode)),) \ + make $(if $(strip $($(mode))),$(mode)=$($(mode)),) \ ,\ $(MAKE) $(if $(strip $($(mode))),$(mode)=$($(mode)),) -C impls/$(impl)))) diff --git a/README.md b/README.md index 3fa1c13df2..e58e828921 100644 --- a/README.md +++ b/README.md @@ -35,9 +35,8 @@ Here is the final diagram for [step A](process/guide.md#stepA): ![stepA_mal architecture](process/stepA_mal.png) If you are interested in creating a mal implementation (or just -interested in using mal for something), you are welcome to to join our -[Discord](https://discord.gg/CKgnNbJBpF) or join #mal on -[libera.chat](https://libera.chat/). In addition to the [make-a-lisp +interested in using mal for something) you are welcome to to join our +[Discord](https://discord.gg/CKgnNbJBpF). In addition to the [make-a-lisp process guide](process/guide.md) there is also a [mal/make-a-lisp FAQ](docs/FAQ.md) where I attempt to answer some common questions. @@ -1452,7 +1451,7 @@ make "docker-build^IMPL" **Notes**: -* Docker images are named *"kanaka/mal-test-IMPL"* +* Docker images are named *"ghcr.io/kanaka/mal-test-IMPL"* * JVM-based language implementations (Groovy, Java, Clojure, Scala): you will probably need to run this command once manually first `make DOCKERIZE=1 "repl^IMPL"` before you can run tests because diff --git a/ci.sh b/ci.sh index 400045fbeb..f8c98135f9 100755 --- a/ci.sh +++ b/ci.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex @@ -24,11 +24,30 @@ mode_var=${raw_mode_var/-/__} mode_var=${mode_var/./__} mode_val=${!mode_var} -MAKE="make ${mode_val:+${mode_var}=${mode_val}}" - log_prefix="${ACTION}${REGRESS:+-regress}-${IMPL}${mode_val:+-${mode_val}}${MAL_IMPL:+-${MAL_IMPL}}" TEST_OPTS="${TEST_OPTS} --debug-file ../../${log_prefix}.debug" +step_summary() { + echo "${*}" + if [ "${GITHUB_STEP_SUMMARY}" ]; then + echo "${*}" >> "${GITHUB_STEP_SUMMARY}" + fi +} + +img_base="${MAL_IMPL:-${IMPL}}" +img_impl="${img_base%%-mal}" +img_name="mal-test-$(echo "${img_impl}" | tr '[:upper:]' '[:lower:]')" +img_ver=$(./voom-like-version.sh impls/${img_impl}/Dockerfile) +IMAGE="ghcr.io/kanaka/${img_name}:${img_ver}" + +# If NO_DOCKER is blank then run make in a docker image +MAKE="make ${mode_val:+${mode_var}=${mode_val}}" +if [ -z "${NO_DOCKER}" ]; then + # We could just use make DOCKERIZE=1 instead but that does add + # non-trivial startup overhead for each step. + MAKE="docker run -i -u $(id -u) -v `pwd`:/mal ${IMAGE} ${MAKE}" +fi + # Log everything below this point: exec &> >(tee ./${log_prefix}.log) @@ -47,17 +66,21 @@ echo "IMPL: ${IMPL}" echo "BUILD_IMPL: ${BUILD_IMPL}" echo "MAL_IMPL: ${MAL_IMPL}" echo "TEST_OPTS: ${TEST_OPTS}" - -# If NO_DOCKER is blank then launch use a docker image, otherwise use -# the Travis/Github Actions image/tools directly. -if [ -z "${NO_DOCKER}" ]; then - img_impl=$(echo "${MAL_IMPL:-${IMPL}}" | tr '[:upper:]' '[:lower:]') - # We could just use make DOCKERIZE=1 instead but that does add - # non-trivial startup overhead for each step. - MAKE="docker run -i -u $(id -u) -v `pwd`:/mal kanaka/mal-test-${img_impl%%-mal} ${MAKE}" -fi +echo "IMAGE: ${IMAGE}" +echo "MAKE: ${MAKE}" case "${ACTION}" in +docker-build-push) + if ! docker pull ${IMAGE}; then + step_summary "${MAL_IMPL:-${IMPL}} - building ${IMAGE}" + make "docker-build^${MAL_IMPL:-${IMPL}}" + step_summary "${MAL_IMPL:-${IMPL}} - built ${IMAGE}" + if [ "${GITHUB_REF}" = "refs/heads/main" ]; then + docker push ${IMAGE} + step_summary "${MAL_IMPL:-${IMPL}} - pushed ${IMAGE}" + fi + fi + ;; build) # rpython often fails on step9 in compute_vars_longevity # so build step9, then continue with the full build diff --git a/docs/FAQ.md b/docs/FAQ.md index 49af1d7eee..b045de0867 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -154,11 +154,57 @@ into the main repository: `time-ms` function which is needed to run the micro-benchmark tests). * Create a `Dockerfile` in your directory that installs all the - packages necessary to build and run your implementation. Refer to other - implementations for examples of what the Dockerfile should contain. - Build your docker image and tag it `kanaka/mal-test-[IMPL_NAME]`. - The top-level Makefile has support for building/testing within - docker with the `DOCKERIZE` flag: + packages necessary to build and run your implementation. In order to + integrate fully with the Github Actions CI workflow, the + `Dockerfile` needs to include the following boilerplate (with your + name, email, and implementation filled in): + ``` + MAINTAINER Your Name + LABEL org.opencontainers.image.source=https://github.com/kanaka/mal + LABEL org.opencontainers.image.description="mal test container: Your_Implementation" + ``` + + In addition, the docker image should provide python3 (with a python + symlink to it) to enable running tests using the image. Here is the + typical `Dockerfile` template you should use if your + implementation does not require a special base distro: + + ``` + FROM ubuntu:24.04 + MAINTAINER Your Name + LABEL org.opencontainers.image.source=https://github.com/kanaka/mal + LABEL org.opencontainers.image.description="mal test container: Your_Implementation" + ########################################################## + # General requirements for testing or common across many + # implementations + ########################################################## + + RUN apt-get -y update + + # Required for running tests + RUN apt-get -y install make python3 + RUN ln -sf /usr/bin/python3 /usr/bin/python + + # Some typical implementation and test requirements + RUN apt-get -y install curl libreadline-dev libedit-dev + + RUN mkdir -p /mal + WORKDIR /mal + + ########################################################## + # Specific implementation requirements + ########################################################## + + ... Your packages ... + ``` + +* Build and tag your docker image. The image tag will have the + form `ghcr.io/kanaka/mal-test-[IMPL_NAME]:[VOOM_VERSION]`. + ``` + make "docker-build^[IMPL_NAME]" + +* The top-level Makefile has support for building/testing using + the docker image with the `DOCKERIZE` flag: ```bash make DOCKERIZE=1 "test^[IMPL_NAME]" make DOCKERIZE=1 MAL_IMPL=[IMPL_NAME] "test^mal" @@ -170,6 +216,9 @@ into the main repository: ./ci.sh test [IMPL_NAME] ``` +* Push your code to a branch and make sure that the automated Github + Actions CI passes for your implementation. + * If you are creating a new implementation for an existing implementation (or somebody beats you to the punch while you are working on it), there is still a chance I will merge your diff --git a/get-ci-matrix.py b/get-ci-matrix.py index debcb172f3..1840df0c42 100755 --- a/get-ci-matrix.py +++ b/get-ci-matrix.py @@ -12,6 +12,9 @@ OVERRIDE_IMPLS = os.environ.get('OVERRIDE_IMPLS', '').split() +def eprint(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + def impl_text(impl): s = "IMPL=%s" % impl['IMPL'] for k, v in impl.items(): @@ -37,11 +40,11 @@ def impl_text(impl): do_full = True -print("OVERRIDE_IMPLS: %s" % OVERRIDE_IMPLS) -print("code_changes: %s (%d)" % (code_changes, len(code_changes))) -print("impl_changes: %s (%d)" % (impl_changes, len(impl_changes))) -print("run_impls: %s (%d)" % (run_impls, len(run_impls))) -print("do_full: %s" % do_full) +eprint("OVERRIDE_IMPLS: %s" % OVERRIDE_IMPLS) +eprint("code_changes: %s (%d)" % (code_changes, len(code_changes))) +eprint("impl_changes: %s (%d)" % (impl_changes, len(impl_changes))) +eprint("run_impls: %s (%d)" % (run_impls, len(run_impls))) +eprint("do_full: %s" % do_full) # Load the full implementation description file all_impls = yaml.safe_load(open(IMPLS_FILE)) @@ -60,7 +63,7 @@ def impl_text(impl): elif do_full: targ.append(impl_text(impl)) -print("::set-output name=do-linux::%s" % json.dumps(len(linux_impls)>0)) -print("::set-output name=do-macos::%s" % json.dumps(len(macos_impls)>0)) -print("::set-output name=linux::{\"IMPL\":%s}" % json.dumps(linux_impls)) -print("::set-output name=macos::{\"IMPL\":%s}" % json.dumps(macos_impls)) +print("do_linux=%s" % json.dumps(len(linux_impls)>0)) +print("do_macos=%s" % json.dumps(len(macos_impls)>0)) +print("linux={\"IMPL\":%s}" % json.dumps(linux_impls)) +print("macos={\"IMPL\":%s}" % json.dumps(macos_impls)) diff --git a/impls/ada/Dockerfile b/impls/ada/Dockerfile index 5eb272abe0..392e20fd83 100755 --- a/impls/ada/Dockerfile +++ b/impls/ada/Dockerfile @@ -1,5 +1,7 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin +LABEL org.opencontainers.image.source=https://github.com/kanaka/mal +LABEL org.opencontainers.image.description="mal test container: ada" ########################################################## # General requirements for testing or common across many diff --git a/impls/awk/Dockerfile b/impls/awk/Dockerfile index 9d0e12cee1..46b05567a9 100644 --- a/impls/awk/Dockerfile +++ b/impls/awk/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## diff --git a/impls/bash/Dockerfile b/impls/bash/Dockerfile index 71720eb5e5..81eba8836a 100644 --- a/impls/bash/Dockerfile +++ b/impls/bash/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## diff --git a/impls/c.2/Dockerfile b/impls/c.2/Dockerfile index 79bab2ecad..2795e538d2 100644 --- a/impls/c.2/Dockerfile +++ b/impls/c.2/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:bionic +FROM ubuntu:24.04 MAINTAINER Duncan Watts ########################################################## @@ -9,10 +9,8 @@ MAINTAINER Duncan Watts RUN apt-get -y update # Required for running tests -RUN apt-get -y install make python - -# Some typical implementation and test requirements -#RUN apt-get -y install curl +RUN apt-get -y install make python3 +RUN ln -fs /usr/bin/python3 /usr/local/bin/python RUN mkdir -p /mal WORKDIR /mal diff --git a/impls/common-lisp/Dockerfile b/impls/common-lisp/Dockerfile index 447f413bbb..7b43e47f02 100644 --- a/impls/common-lisp/Dockerfile +++ b/impls/common-lisp/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## diff --git a/impls/cs/Dockerfile b/impls/cs/Dockerfile index f5f133484d..a95c31ce18 100644 --- a/impls/cs/Dockerfile +++ b/impls/cs/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## @@ -22,4 +22,4 @@ WORKDIR /mal ########################################################## # Deps for Mono-based languages (C#, VB.Net) -RUN apt-get -y install mono-runtime mono-mcs mono-vbnc mono-devel +RUN apt-get -y install tzdata mono-runtime mono-mcs mono-vbnc mono-devel diff --git a/impls/forth/Dockerfile b/impls/forth/Dockerfile index c84caec2c4..4a0be33d86 100644 --- a/impls/forth/Dockerfile +++ b/impls/forth/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## diff --git a/impls/fsharp/Dockerfile b/impls/fsharp/Dockerfile index 01cf8044c7..67ca2243b1 100644 --- a/impls/fsharp/Dockerfile +++ b/impls/fsharp/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## @@ -22,6 +22,6 @@ WORKDIR /mal ########################################################## # Deps for Mono-based languages (C#, VB.Net) -RUN apt-get -y install mono-runtime mono-mcs mono-vbnc mono-devel +RUN apt-get -y install tzdata mono-runtime mono-mcs mono-vbnc mono-devel RUN apt-get -y install fsharp diff --git a/impls/groovy/Dockerfile b/impls/groovy/Dockerfile index 196698ab78..938f5aa0c0 100644 --- a/impls/groovy/Dockerfile +++ b/impls/groovy/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## @@ -22,7 +22,7 @@ WORKDIR /mal ########################################################## # Java and Groovy -RUN apt-get -y install openjdk-7-jdk +RUN apt-get -y install openjdk-8-jdk #RUN apt-get -y install maven2 #ENV MAVEN_OPTS -Duser.home=/mal RUN apt-get -y install ant diff --git a/impls/io/Dockerfile b/impls/io/Dockerfile index e93a326434..beeb46b03c 100644 --- a/impls/io/Dockerfile +++ b/impls/io/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## diff --git a/impls/kotlin/Dockerfile b/impls/kotlin/Dockerfile index dfb83bb887..86857b2ce1 100644 --- a/impls/kotlin/Dockerfile +++ b/impls/kotlin/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## @@ -22,7 +22,7 @@ WORKDIR /mal ########################################################## # Java and Zip -RUN apt-get -y install openjdk-7-jdk +RUN apt-get -y install openjdk-8-jdk RUN apt-get -y install unzip RUN curl -O -J -L https://github.com/JetBrains/kotlin/releases/download/v1.0.6/kotlin-compiler-1.0.6.zip diff --git a/impls/make/Dockerfile b/impls/make/Dockerfile index 5f61062ee3..0890fa83de 100644 --- a/impls/make/Dockerfile +++ b/impls/make/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:24.04 MAINTAINER Joel Martin ########################################################## @@ -9,7 +9,8 @@ MAINTAINER Joel Martin RUN apt-get -y update # Required for running tests -RUN apt-get -y install make python +RUN apt-get -y install make python3 +RUN ln -fs /usr/bin/python3 /usr/local/bin/python # Some typical implementation and test requirements RUN apt-get -y install curl libreadline-dev libedit-dev diff --git a/impls/miniMAL/Dockerfile b/impls/miniMAL/Dockerfile index fa54933ccb..87a5dcfb3f 100644 --- a/impls/miniMAL/Dockerfile +++ b/impls/miniMAL/Dockerfile @@ -1,5 +1,7 @@ -FROM ubuntu:18.04 +FROM ubuntu:24.04 MAINTAINER Joel Martin +LABEL org.opencontainers.image.source=https://github.com/kanaka/mal +LABEL org.opencontainers.image.description="mal test container: miniMAL" ########################################################## # General requirements for testing or common across many @@ -9,7 +11,8 @@ MAINTAINER Joel Martin RUN apt-get -y update # Required for running tests -RUN apt-get -y install make python +RUN apt-get -y install make python3 +RUN ln -sf /usr/bin/python3 /usr/bin/python # Some typical implementation and test requirements RUN apt-get -y install curl libreadline-dev libedit-dev @@ -24,14 +27,9 @@ WORKDIR /mal # For building node modules RUN apt-get -y install g++ -# Add nodesource apt repo config for 10.x stable -RUN apt-get -y install gnupg -RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - - -# Install nodejs -RUN apt-get -y install nodejs +RUN apt-get -y install nodejs npm ENV NPM_CONFIG_CACHE /mal/.npm # install miniMAL -RUN npm install -g minimal-lisp +RUN npm install -g minimal-lisp@1.2.2 diff --git a/impls/miniMAL/core.json b/impls/miniMAL/core.json index d80efad732..3ad9bd0926 100644 --- a/impls/miniMAL/core.json +++ b/impls/miniMAL/core.json @@ -10,6 +10,12 @@ ["and", ["string?", "s"], ["not", ["=", ["`", "\u029e"], ["get", "s", 0]]]]]], +["def", "_function?", ["fn", ["a"], + ["isa", "a", "Function"]]], + +["def", "_number?", ["fn", ["a"], + ["=", ["`", "[object Number]"], ["classOf", "a"]]]], + ["def", "div", ["fn", ["a", "b"], ["parseInt", ["/", "a", "b"]]]], ["def", "time-ms", ["fn", [], @@ -121,9 +127,9 @@ ["`", "symbol?"], "symbol?", ["`", "keyword"], "keyword", ["`", "keyword?"], "keyword?", - ["`", "number?"], "number?", + ["`", "number?"], "_number?", ["`", "fn?"], ["fn", ["a"], - ["or", ["function?", "a"], + ["or", ["_function?", "a"], ["and", ["malfunc?", "a"], ["not", ["get", "a", ["`", "macro?"]]]]]], ["`", "macro?"], ["fn", ["a"], diff --git a/impls/miniMAL/miniMAL-core.json b/impls/miniMAL/miniMAL-core.json index cc3379f0e7..d430c1fdae 100644 --- a/impls/miniMAL/miniMAL-core.json +++ b/impls/miniMAL/miniMAL-core.json @@ -1,124 +1,5 @@ ["do", -["def", "new", ["fn", ["a", "&", "b"], - [".", "Reflect", ["`", "construct"], "a", "b"]]], -["def", "del", ["fn", ["a", "b"], - [".", "Reflect", ["`", "deleteProperty"], "a", "b"]]], -["def", "map", ["fn", ["a", "b"], - [".", "b", ["`", "map"], ["fn", ["x"], ["a", "x"]]]]], -["def", "list", ["fn", ["&", "a"], "a"]], -["def", ">=", ["fn", ["a", "b"], - ["if", ["<", "a", "b"], false, true]]], -["def", ">", ["fn", ["a", "b"], - ["if", [">=", "a", "b"], - ["if", ["=", "a", "b"], false, true], - false]]], -["def", "<=", ["fn", ["a", "b"], - ["if", [">", "a", "b"], false, true]]], - -["def", "classOf", ["fn", ["a"], - [".", [".-", [".-", "Object", ["`", "prototype"]], ["`", "toString"]], - ["`", "call"], "a"]]], - -["def", "not", ["fn", ["a"], ["if", "a", false, true]]], - -["def", "null?", ["fn", ["a"], ["=", null, "a"]]], -["def", "true?", ["fn", ["a"], ["=", true, "a"]]], -["def", "false?", ["fn", ["a"], ["=", false, "a"]]], -["def", "string?", ["fn", ["a"], - ["if", ["=", "a", null], - false, - ["=", ["`", "String"], - [".-", [".-", "a", ["`", "constructor"]], - ["`", "name"]]]]]], -["def", "number?", ["fn", ["a"], - ["=", ["`", "[object Number]"], ["classOf", "a"]]]], -["def", "function?", ["fn", ["a"], - ["isa", "a", "Function"]]], - -["def", "pr-list*", ["fn", ["a", "b", "c"], - [".", ["map", ["fn", ["x"], - ["if", "c", - [".", "JSON", ["`", "stringify"], "x"], - ["if", ["string?", "x"], - "x", - [".", "JSON", ["`", "stringify"], "x"]]]], - "a"], - ["`", "join"], "b"]]], -["def", "pr-str", ["fn", ["&", "a"], - ["pr-list*", "a", ["`", " "], true]]], -["def", "str", ["fn", ["&", "a"], - ["pr-list*", "a", ["`", ""], false]]], -["def", "prn", ["fn", ["&", "a"], - ["do", [".", "console", ["`", "log"], - ["pr-list*", "a", ["`", " "], true]], null]]], -["def", "println", ["fn", ["&", "a"], - ["do", [".", "console", ["`", "log"], - ["pr-list*", "a", ["`", " "], false]], null]]], - -["def", "list?", ["fn", ["a"], - [".", "Array", ["`", "isArray"], "a"]]], -["def", "contains?", ["fn", ["a", "b"], - [".", "a", ["`", "hasOwnProperty"], "b"]]], -["def", "get", ["fn", ["a", "b"], - ["if", ["contains?", "a", "b"], [".-", "a", "b"], null]]], -["def", "set", ["fn", ["a", "b", "c"], - ["do", [".-", "a", "b", "c"], "a"]]], -["def", "keys", ["fn", ["a"], - [".", "Object", ["`", "keys"], "a"]]], -["def", "vals", ["fn", ["a"], - ["map",["fn", ["k"], ["get", "a", "k"]], ["keys", "a"]]]], - -["def", "cons", ["fn", ["a", "b"], - [".", ["`", []], - ["`", "concat"], ["list", "a"], "b"]]], -["def", "concat", ["fn", ["&", "a"], - [".", [".-", ["list"], ["`", "concat"]], - ["`", "apply"], ["list"], "a"]]], -["def", "nth", "get"], -["def", "first", ["fn", ["a"], - ["if", [">", [".-", "a", ["`", "length"]], 0], - ["nth", "a", 0], - null]]], -["def", "last", ["fn", ["a"], - ["nth", "a", ["-", [".-", "a", ["`", "length"]], 1]]]], -["def", "count", ["fn", ["a"], - [".-", "a", ["`", "length"]]]], -["def", "empty?", ["fn", ["a"], - ["if", ["list?", "a"], - ["if", ["=", 0, [".-", "a", ["`", "length"]]], true, false], - ["=", "a", null]]]], -["def", "slice", ["fn", ["a", "b", "&", "end"], - [".", "a", ["`", "slice"], "b", - ["if", [">", ["count", "end"], 0], - ["get", "end", 0], - [".-", "a", ["`", "length"]]]]]], -["def", "rest", ["fn", ["a"], ["slice", "a", 1]]], - -["def", "apply", ["fn", ["f", "&", "b"], - [".", "f", ["`", "apply"], "f", - ["concat", ["slice", "b", 0, -1], ["last", "b"]]]]], - -["def", "and", ["~", ["fn", ["&", "xs"], - ["if", ["empty?", "xs"], - true, - ["if", ["=", 1, ["count", "xs"]], - ["first", "xs"], - ["list", ["`", "let"], ["list", ["`", "and_FIXME"], ["first", "xs"]], - ["list", ["`", "if"], ["`", "and_FIXME"], - ["concat", ["`", ["and"]], ["rest", "xs"]], - ["`", "and_FIXME"]]]]]]]], - -["def", "or", ["~", ["fn", ["&", "xs"], - ["if", ["empty?", "xs"], - null, - ["if", ["=", 1, ["count", "xs"]], - ["first", "xs"], - ["list", ["`", "let"], ["list", ["`", "or_FIXME"], ["first", "xs"]], - ["list", ["`", "if"], ["`", "or_FIXME"], - ["`", "or_FIXME"], - ["concat", ["`", ["or"]], ["rest", "xs"]]]]]]]]], - ["def", "repl", ["fn",["prompt", "rep"], ["let", ["readline", ["require", ["`", "readline"]], "opts", ["new", "Object"], diff --git a/impls/miniMAL/package.json b/impls/miniMAL/package.json index bd9e2cf659..99f902b20e 100644 --- a/impls/miniMAL/package.json +++ b/impls/miniMAL/package.json @@ -4,6 +4,6 @@ "description": "Make a Lisp (mal) language implemented in miniMAL", "dependencies": { "minimal-lisp": "1.0.2", - "ffi-napi": "2.4.x" + "ffi-napi": "4.0.3" } } diff --git a/impls/miniMAL/step6_file.json b/impls/miniMAL/step6_file.json index 214a83cfc3..1e954c740c 100644 --- a/impls/miniMAL/step6_file.json +++ b/impls/miniMAL/step6_file.json @@ -100,14 +100,14 @@ ["env-set", "repl-env", ["symbol", ["`", "eval"]], ["fn", ["ast"], ["EVAL", "ast", "repl-env"]]], ["env-set", "repl-env", ["symbol", ["`", "*ARGV*"]], - ["slice", "ARGS", 1]], + ["slice", "argv", 1]], ["`", "core.mal: defined using mal itself"], ["rep", ["`", "(def! not (fn* (a) (if a false true)))"]], ["rep", ["`", "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))"]], -["if", ["not", ["empty?", "ARGS"]], - ["rep", ["str", ["`", "(load-file \""], ["get", "ARGS", 0], ["`", "\")"]]], +["if", ["not", ["empty?", "argv"]], + ["rep", ["str", ["`", "(load-file \""], ["get", "argv", 0], ["`", "\")"]]], ["repl", ["`", "user> "], "rep"]], null diff --git a/impls/miniMAL/step7_quote.json b/impls/miniMAL/step7_quote.json index 44baaacc37..e11f1d7fce 100644 --- a/impls/miniMAL/step7_quote.json +++ b/impls/miniMAL/step7_quote.json @@ -131,14 +131,14 @@ ["env-set", "repl-env", ["symbol", ["`", "eval"]], ["fn", ["ast"], ["EVAL", "ast", "repl-env"]]], ["env-set", "repl-env", ["symbol", ["`", "*ARGV*"]], - ["slice", "ARGS", 1]], + ["slice", "argv", 1]], ["`", "core.mal: defined using mal itself"], ["rep", ["`", "(def! not (fn* (a) (if a false true)))"]], ["rep", ["`", "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))"]], -["if", ["not", ["empty?", "ARGS"]], - ["rep", ["str", ["`", "(load-file \""], ["get", "ARGS", 0], ["`", "\")"]]], +["if", ["not", ["empty?", "argv"]], + ["rep", ["str", ["`", "(load-file \""], ["get", "argv", 0], ["`", "\")"]]], ["repl", ["`", "user> "], "rep"]], null diff --git a/impls/miniMAL/step8_macros.json b/impls/miniMAL/step8_macros.json index cafceb3f5d..d4b54576c1 100644 --- a/impls/miniMAL/step8_macros.json +++ b/impls/miniMAL/step8_macros.json @@ -137,15 +137,15 @@ ["env-set", "repl-env", ["symbol", ["`", "eval"]], ["fn", ["ast"], ["EVAL", "ast", "repl-env"]]], ["env-set", "repl-env", ["symbol", ["`", "*ARGV*"]], - ["slice", "ARGS", 1]], + ["slice", "argv", 1]], ["`", "core.mal: defined using mal itself"], ["rep", ["`", "(def! not (fn* (a) (if a false true)))"]], ["rep", ["`", "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))"]], ["rep", ["`", "(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))"]], -["if", ["not", ["empty?", "ARGS"]], - ["rep", ["str", ["`", "(load-file \""], ["get", "ARGS", 0], ["`", "\")"]]], +["if", ["not", ["empty?", "argv"]], + ["rep", ["str", ["`", "(load-file \""], ["get", "argv", 0], ["`", "\")"]]], ["repl", ["`", "user> "], "rep"]], null diff --git a/impls/miniMAL/step9_try.json b/impls/miniMAL/step9_try.json index f9140b71f8..05090ab9f8 100644 --- a/impls/miniMAL/step9_try.json +++ b/impls/miniMAL/step9_try.json @@ -150,15 +150,15 @@ ["env-set", "repl-env", ["symbol", ["`", "eval"]], ["fn", ["ast"], ["EVAL", "ast", "repl-env"]]], ["env-set", "repl-env", ["symbol", ["`", "*ARGV*"]], - ["slice", "ARGS", 1]], + ["slice", "argv", 1]], ["`", "core.mal: defined using mal itself"], ["rep", ["`", "(def! not (fn* (a) (if a false true)))"]], ["rep", ["`", "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))"]], ["rep", ["`", "(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))"]], -["if", ["not", ["empty?", "ARGS"]], - ["rep", ["str", ["`", "(load-file \""], ["get", "ARGS", 0], ["`", "\")"]]], +["if", ["not", ["empty?", "argv"]], + ["rep", ["str", ["`", "(load-file \""], ["get", "argv", 0], ["`", "\")"]]], ["repl", ["`", "user> "], "rep"]], null diff --git a/impls/miniMAL/stepA_mal.json b/impls/miniMAL/stepA_mal.json index f7eec832bc..0f068a4e2a 100644 --- a/impls/miniMAL/stepA_mal.json +++ b/impls/miniMAL/stepA_mal.json @@ -150,7 +150,7 @@ ["env-set", "repl-env", ["symbol", ["`", "eval"]], ["fn", ["ast"], ["EVAL", "ast", "repl-env"]]], ["env-set", "repl-env", ["symbol", ["`", "*ARGV*"]], - ["slice", "ARGS", 1]], + ["slice", "argv", 1]], ["`", "core.mal: defined using mal itself"], ["rep", ["`", "(def! *host-language* \"miniMAL\")"]], @@ -158,8 +158,8 @@ ["rep", ["`", "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))"]], ["rep", ["`", "(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))"]], -["if", ["not", ["empty?", "ARGS"]], - ["rep", ["str", ["`", "(load-file \""], ["get", "ARGS", 0], ["`", "\")"]]], +["if", ["not", ["empty?", "argv"]], + ["rep", ["str", ["`", "(load-file \""], ["get", "argv", 0], ["`", "\")"]]], ["do", ["rep", ["`", "(println (str \"Mal [\" *host-language* \"]\"))"]], ["repl", ["`", "user> "], "rep"]]], diff --git a/impls/objpascal/Dockerfile b/impls/objpascal/Dockerfile index 31bb193b10..743ec8bbea 100644 --- a/impls/objpascal/Dockerfile +++ b/impls/objpascal/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:24.04 MAINTAINER Joel Martin ########################################################## @@ -9,7 +9,8 @@ MAINTAINER Joel Martin RUN apt-get -y update # Required for running tests -RUN apt-get -y install make python +RUN apt-get -y install make python3 +RUN ln -fs /usr/bin/python3 /usr/local/bin/python # Some typical implementation and test requirements RUN apt-get -y install curl libreadline-dev libedit-dev diff --git a/impls/ocaml/Dockerfile b/impls/ocaml/Dockerfile index 399553dbc3..4f7392ab3b 100644 --- a/impls/ocaml/Dockerfile +++ b/impls/ocaml/Dockerfile @@ -1,4 +1,4 @@ -[FROM ubuntu:vivid +FROM ubuntu:24.04 MAINTAINER Joel Martin ########################################################## @@ -9,7 +9,8 @@ MAINTAINER Joel Martin RUN apt-get -y update # Required for running tests -RUN apt-get -y install make python +RUN apt-get -y install make python3 +RUN ln -fs /usr/bin/python3 /usr/local/bin/python # Some typical implementation and test requirements RUN apt-get -y install curl libreadline-dev libedit-dev diff --git a/impls/perl/Dockerfile b/impls/perl/Dockerfile index b36833e072..24fd51c4c1 100644 --- a/impls/perl/Dockerfile +++ b/impls/perl/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## diff --git a/impls/perl6/Dockerfile b/impls/perl6/Dockerfile index ea081e882a..d77ab0de62 100644 --- a/impls/perl6/Dockerfile +++ b/impls/perl6/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:24.04 MAINTAINER Joel Martin ########################################################## @@ -9,10 +9,8 @@ MAINTAINER Joel Martin RUN apt-get -y update # Required for running tests -RUN apt-get -y install make python - -# Some typical implementation and test requirements -RUN apt-get -y install curl libreadline-dev libedit-dev +RUN apt-get -y install make python3 +RUN ln -fs /usr/bin/python3 /usr/local/bin/python RUN mkdir -p /mal WORKDIR /mal @@ -22,13 +20,4 @@ WORKDIR /mal ########################################################## # Perl6 build deps -RUN apt-get -y install libfile-copy-recursive-perl build-essential git - -RUN curl -O http://rakudo.org/downloads/star/rakudo-star-2016.07.tar.gz && \ - tar xzf rakudo-star-2016.07.tar.gz && \ - cd rakudo-star-2016.07 && \ - perl Configure.pl --prefix=/usr --gen-moar --gen-nqp --backends=moar && \ - make && \ - make install && \ - cd .. && \ - rm -rf rakudo-star-2016.07* +RUN apt-get -y install rakudo diff --git a/impls/php/Dockerfile b/impls/php/Dockerfile index 87709d4d9a..140e560177 100644 --- a/impls/php/Dockerfile +++ b/impls/php/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## @@ -21,4 +21,4 @@ WORKDIR /mal # Specific implementation requirements ########################################################## -RUN apt-get -y install php5-cli +RUN apt-get -y install php7.0-cli diff --git a/impls/powershell/reader.psm1 b/impls/powershell/reader.psm1 index bd7f95c34b..06ac18bdd4 100644 --- a/impls/powershell/reader.psm1 +++ b/impls/powershell/reader.psm1 @@ -40,7 +40,7 @@ function read_atom([Reader] $rdr) { return $s } elseif ($token -match "^`".*") { throw "expected '`"', got EOF" - } elseif ($token -match ":.*") { + } elseif ($token -match "^:.*") { return "$([char]0x29e)$($token.substring(1))" } elseif ($token -eq "true") { return $true diff --git a/impls/prolog/reader.pl b/impls/prolog/reader.pl index 515f67c69d..63846c5a22 100644 --- a/impls/prolog/reader.pl +++ b/impls/prolog/reader.pl @@ -63,3 +63,4 @@ symcode(0'?). symcode(0'_). symcode(0'|). +symcode(0':). diff --git a/impls/ps/Dockerfile b/impls/ps/Dockerfile index d91f68e1ea..a57b968803 100644 --- a/impls/ps/Dockerfile +++ b/impls/ps/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## diff --git a/impls/python/Dockerfile b/impls/python/Dockerfile index 3e64cc116c..623eb4c9cb 100644 --- a/impls/python/Dockerfile +++ b/impls/python/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## diff --git a/impls/r/Dockerfile b/impls/r/Dockerfile index 42611aeca2..0d19cecbe8 100644 --- a/impls/r/Dockerfile +++ b/impls/r/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## diff --git a/impls/racket/Dockerfile b/impls/racket/Dockerfile index 1b05ee258b..cb97d4656b 100644 --- a/impls/racket/Dockerfile +++ b/impls/racket/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## diff --git a/impls/ruby/Dockerfile b/impls/ruby/Dockerfile index 3bda3bf706..a50818b687 100644 --- a/impls/ruby/Dockerfile +++ b/impls/ruby/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## diff --git a/impls/ruby/step6_file.rb b/impls/ruby/step6_file.rb index a4828e8640..c639926836 100644 --- a/impls/ruby/step6_file.rb +++ b/impls/ruby/step6_file.rb @@ -108,6 +108,6 @@ def PRINT(exp) puts REP[line] rescue Exception => e puts "Error: #{e}" - puts "\t#{e.backtrace.join("\n\t")}" + puts "\t#{e.backtrace[0..100].join("\n\t")}" end end diff --git a/impls/ruby/step7_quote.rb b/impls/ruby/step7_quote.rb index 19d0fe7574..a9a4e33ca5 100644 --- a/impls/ruby/step7_quote.rb +++ b/impls/ruby/step7_quote.rb @@ -143,6 +143,6 @@ def PRINT(exp) puts REP[line] rescue Exception => e puts "Error: #{e}" - puts "\t#{e.backtrace.join("\n\t")}" + puts "\t#{e.backtrace[0..100].join("\n\t")}" end end diff --git a/impls/ruby/step8_macros.rb b/impls/ruby/step8_macros.rb index 3b6873ccc8..01150de4c2 100644 --- a/impls/ruby/step8_macros.rb +++ b/impls/ruby/step8_macros.rb @@ -152,6 +152,6 @@ def PRINT(exp) puts REP[line] rescue Exception => e puts "Error: #{e}" - puts "\t#{e.backtrace.join("\n\t")}" + puts "\t#{e.backtrace[0..100].join("\n\t")}" end end diff --git a/impls/ruby/step9_try.rb b/impls/ruby/step9_try.rb index 2ddb775234..84357f46cf 100644 --- a/impls/ruby/step9_try.rb +++ b/impls/ruby/step9_try.rb @@ -171,6 +171,6 @@ def PRINT(exp) else puts "Error: #{e}" end - puts "\t#{e.backtrace.join("\n\t")}" + puts "\t#{e.backtrace[0..100].join("\n\t")}" end end diff --git a/impls/ruby/stepA_mal.rb b/impls/ruby/stepA_mal.rb index 34cc005eee..787fb578f0 100644 --- a/impls/ruby/stepA_mal.rb +++ b/impls/ruby/stepA_mal.rb @@ -179,6 +179,6 @@ def PRINT(exp) else puts "Error: #{e}" end - puts "\t#{e.backtrace.join("\n\t")}" + puts "\t#{e.backtrace[0..100].join("\n\t")}" end end diff --git a/impls/swift5/Sources/core/Reader.swift b/impls/swift5/Sources/core/Reader.swift index 32f70c4093..287cfe83d0 100644 --- a/impls/swift5/Sources/core/Reader.swift +++ b/impls/swift5/Sources/core/Reader.swift @@ -84,7 +84,7 @@ private extension Parsers { // MARK: - Symbol static let symbolHead = char(excluding: "0123456789^`'\"#~@:%()[]{} \n\r\t,") - static let symbolRest = oneOf(symbolHead, char(from: "0123456789.")) + static let symbolRest = oneOf(symbolHead, char(from: "0123456789.:")) static let name = (symbolHead <*> symbolRest.zeroOrMore).map { String($0) + String($1) } static let symbol = name.map(Expr.symbol) diff --git a/impls/tcl/Dockerfile b/impls/tcl/Dockerfile index 2ad3f330c3..337d63c7c5 100644 --- a/impls/tcl/Dockerfile +++ b/impls/tcl/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## diff --git a/impls/tests/step1_read_print.mal b/impls/tests/step1_read_print.mal index 403af6b49f..4afd4bfeba 100644 --- a/impls/tests/step1_read_print.mal +++ b/impls/tests/step1_read_print.mal @@ -233,6 +233,10 @@ false @a ;=>(deref a) +;; Colon character inside a symbol +a: +;=>a: + ;>>> soft=True ;>>> optional=True ;; diff --git a/impls/vb/Dockerfile b/impls/vb/Dockerfile index f5f133484d..a95c31ce18 100644 --- a/impls/vb/Dockerfile +++ b/impls/vb/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:xenial MAINTAINER Joel Martin ########################################################## @@ -22,4 +22,4 @@ WORKDIR /mal ########################################################## # Deps for Mono-based languages (C#, VB.Net) -RUN apt-get -y install mono-runtime mono-mcs mono-vbnc mono-devel +RUN apt-get -y install tzdata mono-runtime mono-mcs mono-vbnc mono-devel diff --git a/process/guide.md b/process/guide.md index 415ce23605..7fa072339f 100644 --- a/process/guide.md +++ b/process/guide.md @@ -1216,7 +1216,7 @@ Mal borrows most of its syntax and feature-set). then `ast`. - Else return `ast` unchanged. Such forms are not affected by evaluation, so you may quote them - as in the previous case if implementation is easyer. + as in the previous case if implementation is easier. * Add the `quasiquote` special form. @@ -1715,9 +1715,7 @@ implementation. ### Next Steps -* Join the #mal IRC channel. It's fairly quiet but there are bursts of - interesting conversation related to mal, Lisps, esoteric programming - languages, etc. +* Join our [Discord](https://discord.gg/CKgnNbJBpF) channel. * If you have created an implementation for a new target language (or a unique and interesting variant of an existing implementation), consider sending a pull request to add it into the main mal diff --git a/voom-like-version.sh b/voom-like-version.sh new file mode 100755 index 0000000000..9e85e92770 --- /dev/null +++ b/voom-like-version.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env sh + +echo $(TZ=UTC git log -1 --pretty=%ad-g%h --date=format-local:"%Y%m%d_%H%M%S" -- "$@")$(test -z "$(git status --short -- "$@")" || echo _DIRTY)