1
0
Fork 0

basic syntax, types

This commit is contained in:
Sean Sube 2022-06-20 18:09:43 -05:00
commit 79cfefc9f4
25 changed files with 2373 additions and 0 deletions

14
.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
.awcache/
.licenses/
.nyc_output/
node_modules/
out/
temp/
# types
*.bak
*.swp
*.tmp
package-lock.json
yarn-error.log

5
Makefile Executable file
View File

@ -0,0 +1,5 @@
# resolve the makefile's path and directory, from https://stackoverflow.com/a/18137056
export MAKE_PATH ?= $(abspath $(firstword $(MAKEFILE_LIST)))
export ROOT_PATH ?= $(dir $(MAKE_PATH))
include $(shell find $(ROOT_PATH) -name '*.mk' | grep -v node_modules)

39
config/api-extractor.json Normal file
View File

@ -0,0 +1,39 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"projectFolder": "..",
"mainEntryPointFilePath": "<projectFolder>/out/src/index.d.ts",
"apiReport": {
"enabled": true,
"reportFolder": "<projectFolder>/docs/",
"reportTempFolder": "<projectFolder>/out/tmp/"
},
"docModel": {
"enabled": true,
"apiJsonFilePath": "<projectFolder>/out/api/<unscopedPackageName>.api.json"
},
"dtsRollup": {
"enabled": true,
"untrimmedFilePath": "<projectFolder>/out/index.d.ts",
"betaTrimmedFilePath": "<projectFolder>/out/index-beta.d.ts",
"publicTrimmedFilePath": "<projectFolder>/out/index-public.d.ts"
},
"tsdocMetadata": {
},
"messages": {
"compilerMessageReporting": {
"default": {
"logLevel": "warning"
}
},
"extractorMessageReporting": {
"default": {
"logLevel": "warning"
}
},
"tsdocMessageReporting": {
"default": {
"logLevel": "warning"
}
}
}
}

92
config/common.mk Normal file
View File

@ -0,0 +1,92 @@
SHELL := bash
# Git
export GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD)
export GIT_COMMIT ?= $(shell git rev-parse HEAD)
export GIT_OPTIONS ?=
export GIT_REMOTES ?= $(shell git remote -v | awk '{ print $1; }' | sort | uniq)
export GIT_TAG ?= $(shell git tag -l --points-at HEAD | head -1)
# Paths
# resolve the makefile's path and directory, from https://stackoverflow.com/a/18137056
export MAKE_PATH ?= $(abspath $(firstword $(MAKEFILE_LIST)))
export ROOT_PATH ?= $(dir $(MAKE_PATH))
export CONFIG_PATH ?= $(ROOT_PATH)/config
export DOCS_PATH ?= $(ROOT_PATH)/docs
export SCRIPT_PATH ?= $(ROOT_PATH)/scripts
export SOURCE_PATH ?= $(ROOT_PATH)/src
export TARGET_PATH ?= $(ROOT_PATH)/out
export TARGET_LOG ?= $(TARGET_PATH)/make.log
export TARGET_MAIN ?= $(TARGET_PATH)/index.js
export TEST_PATH ?= $(ROOT_PATH)/test
export VENDOR_PATH ?= $(ROOT_PATH)/vendor
# CI
export CI_COMMIT_REF_SLUG ?= $(GIT_BRANCH)
export CI_COMMIT_SHA ?= $(GIT_COMMIT)
export CI_COMMIT_TAG ?= $(GIT_TAG)
export CI_ENVIRONMENT_SLUG ?= local
export CI_JOB_ID ?= 0
export CI_PROJECT_PATH ?= $(shell ROOT_PATH=$(ROOT_PATH) ${SCRIPT_PATH}/ci-project-path.sh)
export CI_RUNNER_DESCRIPTION ?= $(shell hostname)
export CI_RUNNER_ID ?= $(shell hostname)
export CI_RUNNER_VERSION ?= 0.0.0
.PHONY: all ci clean clean-target configure help release release-dry todo
# Targets that must be provided by other files: bundle, build, cover, docs, clean-deps
all: lint build cover docs ## builds, bundles, and tests the application
@echo Success!
clean: ## clean up everything added by the default target
clean: clean-deps clean-target
clean-target: ## clean up the target directory
rm -rf out/
configure: ## create the target directory and other files not in git
mkdir -p $(TARGET_PATH)
# from https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
help: ## print this help
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort \
| sed 's/^.*\/\(.*\)/\1/' \
| awk 'BEGIN {FS = ":[^:]*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
RELEASE_ARGS ?= --commit-all --sign
release: ## tag and push a release
release: node_modules
if [[ "$(GIT_BRANCH)" != master ]]; \
then \
echo "Please merge to master before releasing."; \
exit 1; \
fi
yarn standard-version $(RELEASE_ARGS)
GIT_ARGS=--follow-tags $(MAKE) push
release-dry: ## test creating a release
RELEASE_ARGS="$(RELEASE_ARGS) --dry-run" make release
todo:
@echo "Remaining tasks:"
@echo ""
@grep -i "todo" -r docs/ src/ test/ || true
@echo ""
@echo "Pending tests:"
@echo ""
@grep "[[:space:]]xit" -r test/ || true
@echo ""
@echo "Casts to any:"
@echo ""
@grep "as any" -r src/ test/ || true
@echo ""
@echo "Uses of null:"
@echo ""
@grep -P -e "null(?!able)" -r src/ test/ || true
@echo ""
@echo "Uses of ==:"
@echo ""
@grep -e "[^=!]==[^=]" -r src/ test/ || true
@echo ""

21
config/esbuild.mjs Normal file
View File

@ -0,0 +1,21 @@
import { build } from 'esbuild';
import { join } from 'path';
const root = process.cwd();
build({
bundle: true,
entryPoints: [
join(root, 'out/src/index.js'),
],
format: 'cjs',
keepNames: true,
outdir: 'out/bundle/',
outExtension: {
'.js': '.cjs',
},
platform: 'node',
}).catch((err) => {
console.error(err);
process.exit(1);
});

12
config/git.mk Normal file
View File

@ -0,0 +1,12 @@
.PHONY: push git-stats git-push
push: git-push
# from https://gist.github.com/amitchhajer/4461043#gistcomment-2349917
git-stats: ## print git contributor line counts (approx, for fun)
git ls-files | while read f; do git blame -w -M -C -C --line-porcelain "$$f" |\
grep -I '^author '; done | sort -f | uniq -ic | sort -n
git-push: ## push to both github and gitlab
git push $(GIT_ARGS) github $(GIT_BRANCH)
git push $(GIT_ARGS) gitlab $(GIT_BRANCH)

18
config/image.mk Normal file
View File

@ -0,0 +1,18 @@
.PHONY: image image-build image-run
image: ## build the docker image
docker build $(DOCKER_ARGS) -f Dockerfile -t $(DOCKER_IMAGE) .
image-build: ## build a docker image
$(SCRIPT_PATH)/docker-build.sh --push
image-run: ## run the development image
image-run:
podman run --rm -it \
-e SSH_AUTH_SOCK=${SSH_AUTH_SOCK} \
-v /run/user/$(shell id -u)/:/run/user/$(shell id -u)/:ro \
-v $(shell dirname ${SSH_AUTH_SOCK}):$(shell dirname ${SSH_AUTH_SOCK}):rw \
-v ${HOME}/.gnupg/:/root/.gnupg/:rw \
-v $(ROOT_PATH):$(ROOT_PATH):rw \
-w $(ROOT_PATH) \
docker.artifacts.apextoaster.com/apextoaster/node:16.6 bash

4
config/mocha.json Executable file
View File

@ -0,0 +1,4 @@
{
"reporter": ["json"],
"ui": ["bdd"]
}

85
config/node.mk Normal file
View File

@ -0,0 +1,85 @@
export NODE_VERSION := $(shell node -v 2>/dev/null || echo "none")
export PACKAGE_NAME := $(shell jq -r '.name' package.json 2>/dev/null || echo "unknown")
export PACKAGE_VERSION := $(shell jq -r '.version' package.json 2>/dev/null || echo "unknown")
export RUNNER_VERSION := $(CI_RUNNER_VERSION)
# Debug
export DEBUG_BIND ?= 127.0.0.1
export DEBUG_PORT ?= 9229
# Node options
NODE_CMD ?= $(shell env node)
NODE_DEBUG ?= --inspect-brk=$(DEBUG_BIND):$(DEBUG_PORT) --nolazy
.PHONY: build bundle ci clean-deps cover deps docs lint test yarn-global yarn-upgrade
# directory targets
node_modules: deps
out: build
# phony targets
build: ## build the app
build: node_modules
yarn tsc
cat $(TARGET_PATH)/src/version.js | envsubst > $(TARGET_PATH)/src/version-out.js
mv $(TARGET_PATH)/src/version-out.js $(TARGET_PATH)/src/version.js
bundle: build
node config/esbuild.mjs
bundle-shebang: bundle
sed -i '1s;^;#! /usr/bin/env node\n\n;' $(TARGET_PATH)/bundle/index.cjs
chmod ug+x $(TARGET_PATH)/bundle/index.cjs
ci: clean-target lint build bundle bundle-shebang cover docs
clean-deps: ## clean up the node_modules directory
rm -rf node_modules/
COVER_ARGS := --all \
--check-coverage \
--exclude ".eslintrc.js" \
--exclude "bundle/**" \
--exclude "config/**" \
--exclude "docs/**" \
--exclude "examples/**" \
--exclude "out/bundle/**" \
--exclude "out/coverage/**" \
--exclude "vendor/**" \
--reporter=text-summary \
--reporter=lcov \
--report-dir=out/coverage
cover: ## run tests with coverage
cover: node_modules out
yarn c8 $(COVER_ARGS) yarn mocha $(MOCHA_ARGS) "out/**/Test*.js"
deps:
yarn
docs:
yarn api-extractor run -c config/api-extractor.json
yarn api-documenter markdown -i out/api -o docs/api
lint: ## run eslint
lint: node_modules
yarn eslint src/ --ext .ts,.tsx
MOCHA_ARGS := --async-only \
--check-leaks \
--forbid-only \
--require source-map-support \
--require out/test/setup.js \
--recursive \
--sort
test: ## run tests
test: node_modules out
yarn mocha $(MOCHA_ARGS) "out/**/Test*.js"
yarn-global: ## install bundle as a global tool
yarn global add file:$(ROOT_PATH)
yarn-upgrade: ## check yarn for potential upgrades
yarn upgrade-interactive --latest

35
config/project.mk Normal file
View File

@ -0,0 +1,35 @@
.PHONY: cover-fixup
IMAGE_OPTIONS ?=
cover-fixup: ## run mocha unit tests with coverage reports
cover-fixup: cover
sed -i $(TARGET_PATH)/coverage/lcov.info \
-e '/external ".*"$$/,/end_of_record/d' \
-e '/ sync$$/,/end_of_record/d' \
-e '/test sync/,/end_of_record/d' \
-e '/node_modules/,/end_of_record/d' \
-e '/bootstrap$$/,/end_of_record/d' \
-e '/universalModuleDefinition/,/end_of_record/d'
sed -n '/^SF/,$$p' -i $(TARGET_PATH)/coverage/lcov.info
sed '1s;^;TN:\n;' -i $(TARGET_PATH)/coverage/lcov.info
full: ## ultra thorough build (looong)
$(MAKE) clean-target ci
$(MAKE) clean-target local-alpine local-chown-leaks
$(MAKE) clean-target local-stretch local-chown-leaks
$(MAKE) clean-target
@echo "Full build (CI, alpine, stretch) succeeded!"
# run targets
run: run-app
run-app: ## run the app
@node out/src/index.js
run-debug: ## run the app and wait for an inspector to connect
@node --inspect-brk --inspect-port=0.0.0.0:9229 out/src/index.js
upload-climate:
cc-test-reporter format-coverage -t lcov -o $(TARGET_PATH)/coverage/codeclimate.json -p $(ROOT_PATH) $(TARGET_PATH)/coverage/lcov.info
cc-test-reporter upload-coverage --debug -i $(TARGET_PATH)/coverage/codeclimate.json -r "$(shell echo "${CODECLIMATE_SECRET}" | base64 -d)"

45
config/tsconfig.json Executable file
View File

@ -0,0 +1,45 @@
{
"compileOnSave": false,
"compilerOptions": {
"allowJs": false,
"allowSyntheticDefaultImports": true,
"declaration": true,
"declarationMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"jsx": "react",
"lib": [
"es2017",
"esnext.asynciterable"
],
"module": "esnext",
"moduleResolution": "node",
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"outDir": "../out",
"sourceMap": true,
"strict": true,
"strictNullChecks": true,
"target": "es2017",
"types": [
"chai-as-promised",
"mocha",
"node",
"sinon-chai"
],
"typeRoots": [
"../node_modules/@types",
"../node_modules",
"../vendor"
]
},
"exclude": [
"../node_modules"
],
"include": [
"../src/**/*",
"../test/**/*"
]
}

19
package.json Normal file
View File

@ -0,0 +1,19 @@
{
"name": "ssrp",
"version": "1.0.0",
"type": "module",
"main": "index.js",
"author": "Sean Sube <seansube@gmail.com>",
"license": "MIT",
"dependencies": {
"typescript": "^4.7.4"
},
"devDependencies": {
"@types/chai-as-promised": "^7.1.5",
"@types/mocha": "^9.1.1",
"@types/node": "^18.0.0",
"@types/sinon-chai": "^3.2.8",
"mocha": "^10.0.0",
"sinon-chai": "^3.7.0"
}
}

7
scripts/ci-project-path.sh Executable file
View File

@ -0,0 +1,7 @@
#! /bin/sh
PROJECT="${ROOT_PATH}"
PARENT="$(dirname "${PROJECT}")"
PROJECT_PATH="$(basename "${PARENT}")/$(basename "${PROJECT}")"
echo "${PROJECT_PATH}"

27
scripts/docker-build.sh Executable file
View File

@ -0,0 +1,27 @@
#! /bin/bash
IMAGE_PUSH="${1:---skip}"
IMAGE_DEFAULT="${2:---skip}"
IMAGE_NAME="${CI_PROJECT_PATH}"
IMAGE_TAG="$(echo "${CI_COMMIT_TAG:-${CI_COMMIT_REF_SLUG}}" | sed -r 's/[^-_a-zA-Z0-9\\.]/-/g')"
IMAGE_SHORT="${IMAGE_NAME}:${IMAGE_TAG}"
IMAGE_FULL="${IMAGE_NAME}:${IMAGE_TAG}-${IMAGE_ARCH}"
echo "Building image: ${IMAGE_FULL}"
docker build -f "Dockerfile.${IMAGE_ARCH}" -t "${IMAGE_FULL}" . || (echo "Failed to build image!" && exit 1)
if [[ "${IMAGE_PUSH}" == "--push" ]];
then
echo "Pushing image: ${IMAGE_FULL}"
docker push "${IMAGE_FULL}" || (echo "Failed to push image!" && exit 1)
fi
if [[ "${IMAGE_DEFAULT}" == "--default" ]];
then
echo "Pushing image (default architecture): ${IMAGE_SHORT}"
docker tag "${IMAGE_FULL}" "${IMAGE_SHORT}"
docker push "${IMAGE_SHORT}" || (echo "Failed to push image!" && exit 1)
fi

234
scripts/git-commit-template.sh Executable file
View File

@ -0,0 +1,234 @@
#! /bin/bash
###
# This script will add conventional commit fields to commit messages based on the staged files, branch name,
# and any fields provided in the message.
#
# Can be used as a prepare-commit-msg hook. Committing with -m will run the hook without giving you a
# chance to review the results, omitting -m will launch your $EDITOR. Prefixing the message with ~ will skip
# the template altogether.
#
# TODO: support globs in aliases
# TODO: combine shared prefixes (src/foo/bar and src/foo/bin share src/foo)
#
# Project-specific settings:
#
# - SCOPE_ALIAS: list of path and scope replacements
# - SCOPE_ALLOW: list of allowed scopes (after ALIAS replacement)
###
declare -A SCOPE_ALIAS
SCOPE_ALIAS=(
['README.md']='docs' # with extension matches raw filename, pre-filter
['README']='docs' # without extension matches subdir or filename post-filter
# build
['.codeclimate.yml']='build'
['.eslintrc.json']='build'
['.github']='build'
['.gitlab']='build'
['.gitlab-ci.yml']='build'
['.mdlrc']='build'
['.npmignore']='build'
['.npmrc']='build'
['Makefile']='build'
['renovate.json']='build'
['tsconfig.json']='build'
# deps
['package.json']='deps'
['yarn.lock']='deps'
['vendor']='deps'
# docs
['LICENSE.md']='docs'
# image
['.dockerignore']='image'
['Dockerfile.alpine']='image'
['Dockerfile.stretch']='image'
)
SCOPE_ALLOW=(
# aliases
'build'
'deps'
'image'
# dirs
'docs'
'rules'
'scripts'
'test'
# src subdirs
'config'
'parser'
'reporter'
'rule'
'visitor'
# misc
'lint'
)
function filter_scope() {
local scope="${1}"
local allowed="${2:-FALSE}"
for alias in "${!SCOPE_ALIAS[@]}"
do
# debug_log "alias: ${alias}"
if [[ "${alias}" == "${scope}" ]];
then
scope="${SCOPE_ALIAS[$alias]}"
fi
done
for allow in "${SCOPE_ALLOW[@]}"
do
# debug_log "allow: ${allow}"
if [[ "${allow}" == "${scope}" ]];
then
allowed=TRUE
fi
done
if [[ ${allowed} == TRUE ]];
then
printf '%s' "${scope}"
fi
}
function debug_log() {
if [[ ! -z "${DEBUG:-}" ]];
then
printf '%s\n' "${@}"
fi
}
function head_path() {
local IFS=/
local parts
set -f # Disable glob expansion
parts=( $@ ) # Deliberately unquoted
set +f
if [[ ${#parts[@]} -gt 3 ]];
then
printf '%s/' "${parts[@]:1:2}"
elif [[ ${#parts[@]} -gt 2 ]];
then
printf '%s/' "${parts[@]:1:1}"
elif [[ ${#parts[@]} -gt 1 ]];
then
printf '%s/' "${parts[@]:0:1}"
else
printf '%s' "${parts[0]%%.*}"
fi
}
MESSAGE_FILE="$1"
MESSAGE_SOURCE="$2"
debug_log "$(printf 'message file: %s\n' "$MESSAGE_FILE")"
MESSAGE_BODY=""
MESSAGE_TYPE=""
if [[ "${MESSAGE_FILE}" == "-" ]];
then
printf 'message body: '
read -e MESSAGE_BODY
else
MESSAGE_BODY="$(cat ${MESSAGE_FILE})"
fi
# split up the existing message into segments, if any are present
if [[ "${MESSAGE_BODY}" =~ [a-z]+\([a-z\/]+\)\:[\ ]+[-a-zA-Z0-9\.\(\)]+ ]];
then
debug_log "message is already conventional"
exit 0
elif [[ "${MESSAGE_BODY}" =~ [a-z]+(\(\))*\:[\ ]+[-a-zA-Z0-9\.\(\)]+ ]];
then
debug_log "message is missing scope"
MESSAGE_TYPE="$(echo "${MESSAGE_BODY}" | sed 's/:.*$//' | sed 's/()//')"
MESSAGE_BODY="$(echo "${MESSAGE_BODY}" | sed 's/^.*://' | sed 's/^[ ]*//')"
debug_log "message type: ${MESSAGE_TYPE}"
debug_log "message body: ${MESSAGE_BODY}"
elif [[ "${MESSAGE_BODY}" =~ \~.+ ]];
then
debug_log "unconventional message marker found"
if [[ "${MESSAGE_FILE}" != "-" ]];
then
sed -i '0,/./s/^.//' "${MESSAGE_FILE}"
debug_log "removed marker"
fi
exit 0
fi
# git ls-files -m for modified but unstaged
MODIFIED_FILES="$(git diff --name-only --cached)"
if [[ -z "${MODIFIED_FILES}" ]];
then
debug_log "no staged files"
exit 0
fi
MODIFIED_PATHS=()
while IFS= read -r file
do
# pre-filter the raw path with filename
file="$(filter_scope "$file" TRUE)"
# reduce filenames to <= 2 segments
path="$(head_path "$file")"
path="${path%/}"
debug_log "$(printf 'prefile: %s\n' "$path")"
# post-filter truncated paths
path="$(filter_scope "$path")"
MODIFIED_PATHS+=("$path")
debug_log "$(printf 'file: %s\n' "$file")"
debug_log "$(printf 'path: %s\n' "$path")"
done <<< "${MODIFIED_FILES}"
debug_log "$(printf 'paths: %d\n' "${#MODIFIED_PATHS[@]}")"
readarray -t UNIQUE_SCOPES < <(printf '%s\n' "${MODIFIED_PATHS[@]}" | sort | uniq)
debug_log "$(printf 'unique scopes: %s\n' "${UNIQUE_SCOPES[@]}")"
# git prefix
GIT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
GIT_PREFIX="$(printf '%s\n' "${GIT_BRANCH}" | sed 's:/.*$::g')"
COMMIT_TYPE="${MESSAGE_TYPE:-${GIT_PREFIX}}"
COMMIT_MESSAGE=""
debug_log "branch: $GIT_BRANCH"
debug_log "prefix: $COMMIT_TYPE"
if [[ ${#UNIQUE_SCOPES[@]} -gt 1 ]];
then
debug_log "many scopes"
COMMIT_MESSAGE="${COMMIT_TYPE}: ${MESSAGE_BODY}"
else
if [[ -z "${UNIQUE_SCOPES[0]}" ]];
then
debug_log "empty scope"
COMMIT_MESSAGE="${COMMIT_TYPE}(???): ${MESSAGE_BODY}"
else
debug_log "single scope"
COMMIT_MESSAGE="${COMMIT_TYPE}(${UNIQUE_SCOPES[0]}): ${MESSAGE_BODY}"
fi
fi
debug_log "message: $COMMIT_MESSAGE"
if [[ "${MESSAGE_FILE}" == "-" ]];
then
printf '%s\n' "${COMMIT_MESSAGE}"
else
printf '%s' "${COMMIT_MESSAGE}" > "${MESSAGE_FILE}"
fi

19
scripts/github-status.sh Executable file
View File

@ -0,0 +1,19 @@
#! /bin/sh
STATUS="${1}"
CI_COMMIT_SHA="${CI_COMMIT_SHA:-$(git rev-parse HEAD)}"
STATUS_BODY="$(cat <<EOF
{
"state": "${STATUS}",
"target_url": "${CI_PIPELINE_URL}",
"description": "CI pipeline ${STATUS}!",
"context": "gitlab/build"
}
EOF
)"
printf "Reporting status for %s...\n%s" "${CI_COMMIT_SHA}" "${STATUS_BODY}"
printf "%s" "${STATUS_BODY}" | curl -d @- \
-H "Authorization: token $(printf "%s" "${GITHUB_SECRET}" | base64 -d)" \
-i "https://api.github.com/repos/${CI_PROJECT_PATH}/statuses/${CI_COMMIT_SHA}"

68
scripts/test-examples.sh Executable file
View File

@ -0,0 +1,68 @@
#! /bin/sh
mkdir -p ./out/test/examples
EXAMPLES="$(find ./test/examples -name '*.yml')"
for example in ${EXAMPLES};
do
echo "Testing: ${example}"
USE_RULES="$(grep '# test rules' "${example}" | sed 's/# test rules \(.*\)/\1/')"
[ -z "${USE_RULES}" ] && echo "Test example must have '# test rules' pragma" && exit 1
USE_TAGS="$(grep '# test tags' "${example}" | sed 's/# test tags \(.*\)/\1/')"
[ -z "${USE_TAGS}" ] && echo "Test example must have '# test tags' pragma" && exit 1
EXPECTED_STATUS="$(grep '# test exit-status' "${example}" | sed 's/# test exit-status \([0-9]*\)/\1/')"
[ -z "${EXPECTED_STATUS}" ] && EXPECTED_STATUS=0
echo "Using rules: ${USE_RULES}"
echo "Using tags: ${USE_TAGS}"
echo "Expected status: ${EXPECTED_STATUS}"
STDOUT_PATH=./out/${example}-stdout.log
STDERR_PATH=./out/${example}-stderr.log
node out/src/index.js \
--config-path ./docs \
--config-name config-stderr.yml \
--count \
--rules "rules/${USE_RULES}.yml" \
--tag "${USE_TAGS}" \
--source "${example}" \
1> ${STDOUT_PATH} \
2> ${STDERR_PATH}
ACTUAL_STATUS=$?
echo "Test status: ${ACTUAL_STATUS}"
if [ -s ${STDOUT_PATH} ];
then
echo "Test output:"
echo "==="
echo ""
tail -n5 "${STDOUT_PATH}" | yarn bunyan
echo ""
echo "==="
fi
if [ -s ${STDERR_PATH} ];
then
echo "Test errors:"
echo "==="
echo ""
tail -n5 "${STDERR_PATH}" | yarn bunyan
echo ""
echo "==="
fi
if [ "${ACTUAL_STATUS}" != "${EXPECTED_STATUS}" ];
then
echo "Exit status does not match! (expected ${EXPECTED_STATUS}, got ${ACTUAL_STATUS})"
echo "Failed in: ${example}"
exit 1
fi
done
echo "All examples passed."

3
src/examples/loop.ssrp Normal file
View File

@ -0,0 +1,3 @@
add r1, 1
push r1
call 0

199
src/index.ts Normal file
View File

@ -0,0 +1,199 @@
// @ts-ignore
import parser from './parser.cjs';
const { parse } = parser;
type Address = number;
type Counter = number;
type Register = number; // int32, specifically
enum OpCode {
// flow
COMPARE = 'cmp',
JUMP = 'jmp',
CALL = 'call',
// stack
PEEK = 'peek',
PEEK_STACK = 'peekstack',
POP = 'pop',
POP_STACK = 'popstack',
PUSH = 'push',
PUSH_STACK = 'pushstack',
// math
ADD = 'add',
SUB = 'sub',
MUL = 'mul',
DIV = 'div',
EXP = 'exp',
}
interface FreeInstruction {
code: OpCode;
}
interface SingleInstruction extends FreeInstruction {
first: RegisterName;
}
interface DoubleInstruction extends SingleInstruction {
second: RegisterName;
}
type Instruction = FreeInstruction | SingleInstruction | DoubleInstruction;
interface ProgramRegisters {
// address
PC: Address;
RA: Address;
EH: Address;
IH: Address;
// value
R1: Register;
R2: Register;
R3: Register;
R4: Register;
}
type RegisterName = keyof ProgramRegisters;
interface Table<TEntry> {
names: Array<[string, Address]>;
entries: Array<TEntry>;
}
interface FunctionEntry {
instructions: Array<Instruction>;
}
interface GlobalEntry {
value: unknown;
}
interface ProgramModule {
functions: Table<FunctionEntry>;
globals: Table<GlobalEntry>;
}
interface ProgramStack {
counter: number;
values: Array<number>;
}
interface Program {
registers: ProgramRegisters;
runtime: ProgramModule;
program: ProgramModule;
modules: Array<ProgramModule>;
stack: ProgramStack;
}
/**
* Load a module from compiled source.
*/
function load(data: string): ProgramModule {
const ast = parse(data) as Array<Instruction>;
console.log(ast);
return {
functions: {
names: [['main', 0]],
entries: [{
instructions: ast,
}],
},
globals: {
names: [],
entries: [],
},
};
}
/**
* Prepare the memory for a program module to run.
*/
function prep(runtime: ProgramModule, program: ProgramModule): Program {
return {
registers: {
PC: 0,
RA: 0,
EH: 0,
IH: 0,
R1: 0,
R2: 2, // increment by
R3: 0,
R4: 10, // increment until
},
runtime,
program,
modules: [],
stack: {
counter: 0,
values: [],
},
};
}
/**
* Step the program and execute one command.
*/
function step(state: Program): void {
const instruction = state.program.functions.entries[0].instructions[state.registers.PC];
console.log('step', state.registers.PC, instruction);
const steps = stepInstruction(instruction, state.registers, state.stack);
state.registers.PC += steps;
console.log('post', state.registers.PC, steps);
}
function stepInstruction(instruction: Instruction, registers: ProgramRegisters, stack: ProgramStack): number {
const single = instruction as SingleInstruction;
const double = instruction as DoubleInstruction;
switch (instruction.code) {
case OpCode.CALL:
console.log('CALL', single.first, registers[single.first]);
registers.PC = registers[single.first];
return 0;
case OpCode.PUSH:
stack.values.push(registers[single.first]);
break;
case OpCode.POP:
registers[single.first] = stack.values.pop() || 0;
break;
case OpCode.PEEK:
registers[single.first] = stack.values[stack.values.length - 1] || 0;
break;
case OpCode.ADD:
{
const val = (registers[double.first] + registers[double.second]) % 256;
console.log('ADD', double, registers, val);
stack.values.push(val);
}
break;
case OpCode.COMPARE:
console.log('COMPARE', double, registers);
if (registers[double.first] === registers[double.second]) {
return 2;
}
}
return 1;
}
/**
* Step the program until the function has been exhausted.
*/
function runProgram(data: string): ProgramStack {
const main = load(data);
const state = prep(main, main);
while (state.registers.PC < state.program.functions.entries[0].instructions.length) {
step(state);
}
return state.stack;
}
const stack = runProgram(`add R1, R2
peek R1
cmp R1, R4
call R3
`);
console.log('stack', stack);

806
src/parser.cjs Normal file
View File

@ -0,0 +1,806 @@
module.exports = /*
* Generated by PEG.js 0.10.0.
*
* http://pegjs.org/
*/
(function() {
"use strict";
function peg$subclass(child, parent) {
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
child.prototype = new ctor();
}
function peg$SyntaxError(message, expected, found, location) {
this.message = message;
this.expected = expected;
this.found = found;
this.location = location;
this.name = "SyntaxError";
if (typeof Error.captureStackTrace === "function") {
Error.captureStackTrace(this, peg$SyntaxError);
}
}
peg$subclass(peg$SyntaxError, Error);
peg$SyntaxError.buildMessage = function(expected, found) {
var DESCRIBE_EXPECTATION_FNS = {
literal: function(expectation) {
return "\"" + literalEscape(expectation.text) + "\"";
},
"class": function(expectation) {
var escapedParts = "",
i;
for (i = 0; i < expectation.parts.length; i++) {
escapedParts += expectation.parts[i] instanceof Array
? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1])
: classEscape(expectation.parts[i]);
}
return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]";
},
any: function(expectation) {
return "any character";
},
end: function(expectation) {
return "end of input";
},
other: function(expectation) {
return expectation.description;
}
};
function hex(ch) {
return ch.charCodeAt(0).toString(16).toUpperCase();
}
function literalEscape(s) {
return s
.replace(/\\/g, '\\\\')
.replace(/"/g, '\\"')
.replace(/\0/g, '\\0')
.replace(/\t/g, '\\t')
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r')
.replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
.replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); });
}
function classEscape(s) {
return s
.replace(/\\/g, '\\\\')
.replace(/\]/g, '\\]')
.replace(/\^/g, '\\^')
.replace(/-/g, '\\-')
.replace(/\0/g, '\\0')
.replace(/\t/g, '\\t')
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r')
.replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
.replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); });
}
function describeExpectation(expectation) {
return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
}
function describeExpected(expected) {
var descriptions = new Array(expected.length),
i, j;
for (i = 0; i < expected.length; i++) {
descriptions[i] = describeExpectation(expected[i]);
}
descriptions.sort();
if (descriptions.length > 0) {
for (i = 1, j = 1; i < descriptions.length; i++) {
if (descriptions[i - 1] !== descriptions[i]) {
descriptions[j] = descriptions[i];
j++;
}
}
descriptions.length = j;
}
switch (descriptions.length) {
case 1:
return descriptions[0];
case 2:
return descriptions[0] + " or " + descriptions[1];
default:
return descriptions.slice(0, -1).join(", ")
+ ", or "
+ descriptions[descriptions.length - 1];
}
}
function describeFound(found) {
return found ? "\"" + literalEscape(found) + "\"" : "end of input";
}
return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
};
function peg$parse(input, options) {
options = options !== void 0 ? options : {};
var peg$FAILED = {},
peg$startRuleFunctions = { Program: peg$parseProgram },
peg$startRuleFunction = peg$parseProgram,
peg$c0 = function(code) { return { code }; },
peg$c1 = function(code, first) { return { code, first }; },
peg$c2 = ",",
peg$c3 = peg$literalExpectation(",", false),
peg$c4 = function(code, first, second) { return { code, first, second }; },
peg$c5 = "RA",
peg$c6 = peg$literalExpectation("RA", false),
peg$c7 = "PC",
peg$c8 = peg$literalExpectation("PC", false),
peg$c9 = "IH",
peg$c10 = peg$literalExpectation("IH", false),
peg$c11 = "EH",
peg$c12 = peg$literalExpectation("EH", false),
peg$c13 = "R",
peg$c14 = peg$literalExpectation("R", false),
peg$c15 = /^[0-4]/,
peg$c16 = peg$classExpectation([["0", "4"]], false, false),
peg$c17 = function() { return text(); },
peg$c18 = /^[0-9]/,
peg$c19 = peg$classExpectation([["0", "9"]], false, false),
peg$c20 = function() { return parseInt(text(), 10); },
peg$c21 = "cmp",
peg$c22 = peg$literalExpectation("cmp", false),
peg$c23 = "add",
peg$c24 = peg$literalExpectation("add", false),
peg$c25 = "call",
peg$c26 = peg$literalExpectation("call", false),
peg$c27 = "push",
peg$c28 = peg$literalExpectation("push", false),
peg$c29 = "peek",
peg$c30 = peg$literalExpectation("peek", false),
peg$c31 = ";",
peg$c32 = peg$literalExpectation(";", false),
peg$c33 = /^[ a-z]/,
peg$c34 = peg$classExpectation([" ", ["a", "z"]], false, false),
peg$c35 = /^[\n\r]/,
peg$c36 = peg$classExpectation(["\n", "\r"], false, false),
peg$c37 = peg$otherExpectation("whitespace"),
peg$c38 = /^[ \t]/,
peg$c39 = peg$classExpectation([" ", "\t"], false, false),
peg$currPos = 0,
peg$savedPos = 0,
peg$posDetailsCache = [{ line: 1, column: 1 }],
peg$maxFailPos = 0,
peg$maxFailExpected = [],
peg$silentFails = 0,
peg$result;
if ("startRule" in options) {
if (!(options.startRule in peg$startRuleFunctions)) {
throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
}
peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
}
function text() {
return input.substring(peg$savedPos, peg$currPos);
}
function location() {
return peg$computeLocation(peg$savedPos, peg$currPos);
}
function expected(description, location) {
location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)
throw peg$buildStructuredError(
[peg$otherExpectation(description)],
input.substring(peg$savedPos, peg$currPos),
location
);
}
function error(message, location) {
location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)
throw peg$buildSimpleError(message, location);
}
function peg$literalExpectation(text, ignoreCase) {
return { type: "literal", text: text, ignoreCase: ignoreCase };
}
function peg$classExpectation(parts, inverted, ignoreCase) {
return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase };
}
function peg$anyExpectation() {
return { type: "any" };
}
function peg$endExpectation() {
return { type: "end" };
}
function peg$otherExpectation(description) {
return { type: "other", description: description };
}
function peg$computePosDetails(pos) {
var details = peg$posDetailsCache[pos], p;
if (details) {
return details;
} else {
p = pos - 1;
while (!peg$posDetailsCache[p]) {
p--;
}
details = peg$posDetailsCache[p];
details = {
line: details.line,
column: details.column
};
while (p < pos) {
if (input.charCodeAt(p) === 10) {
details.line++;
details.column = 1;
} else {
details.column++;
}
p++;
}
peg$posDetailsCache[pos] = details;
return details;
}
}
function peg$computeLocation(startPos, endPos) {
var startPosDetails = peg$computePosDetails(startPos),
endPosDetails = peg$computePosDetails(endPos);
return {
start: {
offset: startPos,
line: startPosDetails.line,
column: startPosDetails.column
},
end: {
offset: endPos,
line: endPosDetails.line,
column: endPosDetails.column
}
};
}
function peg$fail(expected) {
if (peg$currPos < peg$maxFailPos) { return; }
if (peg$currPos > peg$maxFailPos) {
peg$maxFailPos = peg$currPos;
peg$maxFailExpected = [];
}
peg$maxFailExpected.push(expected);
}
function peg$buildSimpleError(message, location) {
return new peg$SyntaxError(message, null, null, location);
}
function peg$buildStructuredError(expected, found, location) {
return new peg$SyntaxError(
peg$SyntaxError.buildMessage(expected, found),
expected,
found,
location
);
}
function peg$parseProgram() {
var s0, s1;
s0 = [];
s1 = peg$parseInstruction();
if (s1 !== peg$FAILED) {
while (s1 !== peg$FAILED) {
s0.push(s1);
s1 = peg$parseInstruction();
}
} else {
s0 = peg$FAILED;
}
return s0;
}
function peg$parseInstruction() {
var s0;
s0 = peg$parseFreeInstruction();
if (s0 === peg$FAILED) {
s0 = peg$parseSingleInstruction();
if (s0 === peg$FAILED) {
s0 = peg$parseDoubleInstruction();
}
}
return s0;
}
function peg$parseFreeInstruction() {
var s0, s1, s2, s3;
s0 = peg$currPos;
s1 = peg$parseOpCode();
if (s1 !== peg$FAILED) {
s2 = peg$parseComment();
if (s2 === peg$FAILED) {
s2 = null;
}
if (s2 !== peg$FAILED) {
s3 = peg$parseBreak();
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
s1 = peg$c0(s1);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
return s0;
}
function peg$parseSingleInstruction() {
var s0, s1, s2, s3, s4, s5;
s0 = peg$currPos;
s1 = peg$parseOpCode();
if (s1 !== peg$FAILED) {
s2 = peg$parse_();
if (s2 !== peg$FAILED) {
s3 = peg$parseValue();
if (s3 !== peg$FAILED) {
s4 = peg$parseComment();
if (s4 === peg$FAILED) {
s4 = null;
}
if (s4 !== peg$FAILED) {
s5 = peg$parseBreak();
if (s5 !== peg$FAILED) {
peg$savedPos = s0;
s1 = peg$c1(s1, s3);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
return s0;
}
function peg$parseDoubleInstruction() {
var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
s0 = peg$currPos;
s1 = peg$parseOpCode();
if (s1 !== peg$FAILED) {
s2 = peg$parse_();
if (s2 !== peg$FAILED) {
s3 = peg$parseValue();
if (s3 !== peg$FAILED) {
s4 = peg$parse_();
if (s4 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 44) {
s5 = peg$c2;
peg$currPos++;
} else {
s5 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c3); }
}
if (s5 !== peg$FAILED) {
s6 = peg$parse_();
if (s6 !== peg$FAILED) {
s7 = peg$parseValue();
if (s7 !== peg$FAILED) {
s8 = peg$parseComment();
if (s8 === peg$FAILED) {
s8 = null;
}
if (s8 !== peg$FAILED) {
s9 = peg$parseBreak();
if (s9 !== peg$FAILED) {
peg$savedPos = s0;
s1 = peg$c4(s1, s3, s7);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
return s0;
}
function peg$parseValue() {
var s0;
s0 = peg$parseRegister();
if (s0 === peg$FAILED) {
s0 = peg$parseInteger();
}
return s0;
}
function peg$parseRegister() {
var s0, s1, s2;
if (input.substr(peg$currPos, 2) === peg$c5) {
s0 = peg$c5;
peg$currPos += 2;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c6); }
}
if (s0 === peg$FAILED) {
if (input.substr(peg$currPos, 2) === peg$c7) {
s0 = peg$c7;
peg$currPos += 2;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c8); }
}
if (s0 === peg$FAILED) {
if (input.substr(peg$currPos, 2) === peg$c9) {
s0 = peg$c9;
peg$currPos += 2;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c10); }
}
if (s0 === peg$FAILED) {
if (input.substr(peg$currPos, 2) === peg$c11) {
s0 = peg$c11;
peg$currPos += 2;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c12); }
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 82) {
s1 = peg$c13;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c14); }
}
if (s1 !== peg$FAILED) {
if (peg$c15.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c16); }
}
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
s1 = peg$c17();
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
}
}
}
}
return s0;
}
function peg$parseInteger() {
var s0, s1, s2, s3;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
s2 = [];
if (peg$c18.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c19); }
}
if (s3 !== peg$FAILED) {
while (s3 !== peg$FAILED) {
s2.push(s3);
if (peg$c18.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c19); }
}
}
} else {
s2 = peg$FAILED;
}
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
s1 = peg$c20();
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
return s0;
}
function peg$parseOpCode() {
var s0;
if (input.substr(peg$currPos, 3) === peg$c21) {
s0 = peg$c21;
peg$currPos += 3;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c22); }
}
if (s0 === peg$FAILED) {
if (input.substr(peg$currPos, 3) === peg$c23) {
s0 = peg$c23;
peg$currPos += 3;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c24); }
}
if (s0 === peg$FAILED) {
if (input.substr(peg$currPos, 4) === peg$c25) {
s0 = peg$c25;
peg$currPos += 4;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c26); }
}
if (s0 === peg$FAILED) {
if (input.substr(peg$currPos, 4) === peg$c27) {
s0 = peg$c27;
peg$currPos += 4;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c28); }
}
if (s0 === peg$FAILED) {
if (input.substr(peg$currPos, 4) === peg$c29) {
s0 = peg$c29;
peg$currPos += 4;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c30); }
}
}
}
}
}
return s0;
}
function peg$parseComment() {
var s0, s1, s2, s3;
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 59) {
s1 = peg$c31;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c32); }
}
if (s1 !== peg$FAILED) {
s2 = [];
if (peg$c33.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c34); }
}
while (s3 !== peg$FAILED) {
s2.push(s3);
if (peg$c33.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c34); }
}
}
if (s2 !== peg$FAILED) {
s1 = [s1, s2];
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
return s0;
}
function peg$parseBreak() {
var s0, s1;
s0 = [];
if (peg$c35.test(input.charAt(peg$currPos))) {
s1 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c36); }
}
if (s1 !== peg$FAILED) {
while (s1 !== peg$FAILED) {
s0.push(s1);
if (peg$c35.test(input.charAt(peg$currPos))) {
s1 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c36); }
}
}
} else {
s0 = peg$FAILED;
}
return s0;
}
function peg$parse_() {
var s0, s1;
peg$silentFails++;
s0 = [];
if (peg$c38.test(input.charAt(peg$currPos))) {
s1 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c39); }
}
while (s1 !== peg$FAILED) {
s0.push(s1);
if (peg$c38.test(input.charAt(peg$currPos))) {
s1 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c39); }
}
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c37); }
}
return s0;
}
peg$result = peg$startRuleFunction();
if (peg$result !== peg$FAILED && peg$currPos === input.length) {
return peg$result;
} else {
if (peg$result !== peg$FAILED && peg$currPos < input.length) {
peg$fail(peg$endExpectation());
}
throw peg$buildStructuredError(
peg$maxFailExpected,
peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,
peg$maxFailPos < input.length
? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1)
: peg$computeLocation(peg$maxFailPos, peg$maxFailPos)
);
}
}
return {
SyntaxError: peg$SyntaxError,
parse: peg$parse
};
})();

18
src/parser.peg Normal file
View File

@ -0,0 +1,18 @@
Program = Instruction+
Instruction = FreeInstruction / SingleInstruction / DoubleInstruction
FreeInstruction = code:OpCode Comment? Break { return { code }; }
SingleInstruction = code:OpCode _ first:Value Comment? Break { return { code, first }; }
DoubleInstruction = code:OpCode _ first:Value _ "," _ second:Value Comment? Break { return { code, first, second }; }
Value = Register / Constant
Register = "R" [0-4] { return text(); }
Constant = Integer
Integer
= _ [0-9]+ { return parseInt(text(), 10); }
OpCode = "cmp" / "add" / "call" / "push"
Comment = ";" [ a-z]*
Break = [\n\r]+
_ "whitespace"
= [ \t]*

16
src/version.ts Normal file
View File

@ -0,0 +1,16 @@
/* eslint-disable no-template-curly-in-string */
export const VERSION_INFO = {
build: {
job: '${BUILD_JOB}',
node: '${NODE_VERSION}',
runner: '${BUILD_RUNNER}',
},
git: {
branch: '${GIT_BRANCH}',
commit: '${GIT_COMMIT}',
},
package: {
name: '${PACKAGE_NAME}',
version: '${PACKAGE_VERSION}',
},
};

0
test/index.ts Normal file
View File

3
tsconfig.json Executable file
View File

@ -0,0 +1,3 @@
{
"extends": "./config/tsconfig.json"
}

584
yarn.lock Normal file
View File

@ -0,0 +1,584 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@types/chai-as-promised@^7.1.5":
version "7.1.5"
resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255"
integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ==
dependencies:
"@types/chai" "*"
"@types/chai@*":
version "4.3.1"
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.1.tgz#e2c6e73e0bdeb2521d00756d099218e9f5d90a04"
integrity sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ==
"@types/mocha@^9.1.1":
version "9.1.1"
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4"
integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==
"@types/node@^18.0.0":
version "18.0.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.0.tgz#67c7b724e1bcdd7a8821ce0d5ee184d3b4dd525a"
integrity sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==
"@types/sinon-chai@^3.2.8":
version "3.2.8"
resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.8.tgz#5871d09ab50d671d8e6dd72e9073f8e738ac61dc"
integrity sha512-d4ImIQbT/rKMG8+AXpmcan5T2/PNeSjrYhvkwet6z0p8kzYtfgA32xzOBlbU0yqJfq+/0Ml805iFoODO0LP5/g==
dependencies:
"@types/chai" "*"
"@types/sinon" "*"
"@types/sinon@*":
version "10.0.11"
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.11.tgz#8245827b05d3fc57a6601bd35aee1f7ad330fc42"
integrity sha512-dmZsHlBsKUtBpHriNjlK0ndlvEh8dcb9uV9Afsbt89QIyydpC7NcR+nWlAhASfy3GHnxTl4FX/aKE7XZUt/B4g==
dependencies:
"@types/sinonjs__fake-timers" "*"
"@types/sinonjs__fake-timers@*":
version "8.1.2"
resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz#bf2e02a3dbd4aecaf95942ecd99b7402e03fad5e"
integrity sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==
"@ungap/promise-all-settled@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==
ansi-colors@4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
dependencies:
color-convert "^2.0.1"
anymatch@~3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
dependencies:
normalize-path "^3.0.0"
picomatch "^2.0.4"
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
binary-extensions@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
brace-expansion@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
dependencies:
balanced-match "^1.0.0"
braces@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
dependencies:
fill-range "^7.0.1"
browser-stdout@1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
camelcase@^6.0.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
chalk@^4.1.0:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chokidar@3.5.3:
version "3.5.3"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
dependencies:
anymatch "~3.1.2"
braces "~3.0.2"
glob-parent "~5.1.2"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.6.0"
optionalDependencies:
fsevents "~2.3.2"
cliui@^7.0.2:
version "7.0.4"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
dependencies:
string-width "^4.2.0"
strip-ansi "^6.0.0"
wrap-ansi "^7.0.0"
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
dependencies:
color-name "~1.1.4"
color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
debug@4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
decamelize@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837"
integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==
diff@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b"
integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
escalade@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
escape-string-regexp@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
dependencies:
to-regex-range "^5.0.1"
find-up@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
dependencies:
locate-path "^6.0.0"
path-exists "^4.0.0"
flat@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
get-caller-file@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
glob@7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.4"
once "^1.3.0"
path-is-absolute "^1.0.0"
has-flag@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
he@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
dependencies:
once "^1.3.0"
wrappy "1"
inherits@2:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
is-binary-path@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
dependencies:
binary-extensions "^2.0.0"
is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
is-glob@^4.0.1, is-glob@~4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
dependencies:
is-extglob "^2.1.1"
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
is-plain-obj@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
is-unicode-supported@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
js-yaml@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
dependencies:
argparse "^2.0.1"
locate-path@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
dependencies:
p-locate "^5.0.0"
log-symbols@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
dependencies:
chalk "^4.1.0"
is-unicode-supported "^0.1.0"
minimatch@5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b"
integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==
dependencies:
brace-expansion "^2.0.1"
minimatch@^3.0.4:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
dependencies:
brace-expansion "^1.1.7"
mocha@^10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.0.0.tgz#205447d8993ec755335c4b13deba3d3a13c4def9"
integrity sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==
dependencies:
"@ungap/promise-all-settled" "1.1.2"
ansi-colors "4.1.1"
browser-stdout "1.3.1"
chokidar "3.5.3"
debug "4.3.4"
diff "5.0.0"
escape-string-regexp "4.0.0"
find-up "5.0.0"
glob "7.2.0"
he "1.2.0"
js-yaml "4.1.0"
log-symbols "4.1.0"
minimatch "5.0.1"
ms "2.1.3"
nanoid "3.3.3"
serialize-javascript "6.0.0"
strip-json-comments "3.1.1"
supports-color "8.1.1"
workerpool "6.2.1"
yargs "16.2.0"
yargs-parser "20.2.4"
yargs-unparser "2.0.0"
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
ms@2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
nanoid@3.3.3:
version "3.3.3"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25"
integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==
normalize-path@^3.0.0, normalize-path@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
dependencies:
wrappy "1"
p-limit@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
dependencies:
yocto-queue "^0.1.0"
p-locate@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
dependencies:
p-limit "^3.0.2"
path-exists@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
picomatch@^2.0.4, picomatch@^2.2.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
randombytes@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
dependencies:
safe-buffer "^5.1.0"
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
dependencies:
picomatch "^2.2.1"
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
safe-buffer@^5.1.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
serialize-javascript@6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8"
integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==
dependencies:
randombytes "^2.1.0"
sinon-chai@^3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-3.7.0.tgz#cfb7dec1c50990ed18c153f1840721cf13139783"
integrity sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==
string-width@^4.1.0, string-width@^4.2.0:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-json-comments@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
supports-color@8.1.1:
version "8.1.1"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
dependencies:
has-flag "^4.0.0"
supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
dependencies:
has-flag "^4.0.0"
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
dependencies:
is-number "^7.0.0"
typescript@^4.7.4:
version "4.7.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235"
integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==
workerpool@6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343"
integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
y18n@^5.0.5:
version "5.0.8"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
yargs-parser@20.2.4:
version "20.2.4"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"
integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==
yargs-parser@^20.2.2:
version "20.2.9"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
yargs-unparser@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb"
integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==
dependencies:
camelcase "^6.0.0"
decamelize "^4.0.0"
flat "^5.0.2"
is-plain-obj "^2.1.0"
yargs@16.2.0:
version "16.2.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
dependencies:
cliui "^7.0.2"
escalade "^3.1.1"
get-caller-file "^2.0.5"
require-directory "^2.1.1"
string-width "^4.2.0"
y18n "^5.0.5"
yargs-parser "^20.2.2"
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==