forked from glen/fostr
chore: Switch to this repository from predecessor
This commit is contained in:
parent
9ecfa63f58
commit
7b00b01856
63
.drone.yml
Normal file
63
.drone.yml
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: examples
|
||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: maven
|
||||||
|
volumes:
|
||||||
|
- name: lib
|
||||||
|
path: /drone/lib
|
||||||
|
- name: m2
|
||||||
|
path: /root/.m2
|
||||||
|
commands:
|
||||||
|
- mvn -ntp verify
|
||||||
|
- cd /drone/lib
|
||||||
|
- git clone https://github.com/metaborg/spt.git
|
||||||
|
- cd spt/org.metaborg.spt.cmd
|
||||||
|
- mvn -ntp package
|
||||||
|
- name: run_spt
|
||||||
|
image: maven
|
||||||
|
volumes:
|
||||||
|
- name: lib
|
||||||
|
path: /drone/lib
|
||||||
|
- name: m2
|
||||||
|
path: /root/.m2
|
||||||
|
commands:
|
||||||
|
- cd /drone/lib/spt/org.metaborg.meta.lang.spt
|
||||||
|
- mvn -ntp verify
|
||||||
|
- cd /drone/src
|
||||||
|
- java -jar /drone/lib/spt/org.metaborg.spt.cmd/target/org.metaborg.spt.cmd* -l . -s /drone/lib/spt/org.metaborg.meta.lang.spt -t tests
|
||||||
|
- mkdir -p lib
|
||||||
|
- curl -o lib/sunshine.jar -L 'http://artifacts.metaborg.org/service/local/artifact/maven/redirect?r=snapshots&g=org.metaborg&a=org.metaborg.sunshine2&v=LATEST'
|
||||||
|
- bin/fosgen tests/emit_sum.fos
|
||||||
|
- name: extract_tests
|
||||||
|
image: xonsh/xonsh
|
||||||
|
commands:
|
||||||
|
- xonsh bin/extract_tests.xsh
|
||||||
|
- name: generate_tests
|
||||||
|
image: maven
|
||||||
|
volumes:
|
||||||
|
- name: lib
|
||||||
|
path: /drone/lib
|
||||||
|
- name: m2
|
||||||
|
path: /root/.m2
|
||||||
|
commands:
|
||||||
|
- bin/generate_test_code
|
||||||
|
- name: python_tests
|
||||||
|
image: python:slim
|
||||||
|
commands:
|
||||||
|
- bin/run_tests python py
|
||||||
|
- name: javascript_tests
|
||||||
|
image: node
|
||||||
|
commands:
|
||||||
|
- bin/run_tests node js
|
||||||
|
- name: haskell_tests
|
||||||
|
image: haskell
|
||||||
|
commands:
|
||||||
|
- bin/run_tests runghc hs
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: lib
|
||||||
|
temp: {}
|
||||||
|
- name: m2
|
||||||
|
temp: {}
|
9
.gitignore
vendored
9
.gitignore
vendored
@ -1,5 +1,5 @@
|
|||||||
/.cache
|
/.cache
|
||||||
/bin
|
/lib
|
||||||
/src-gen
|
/src-gen
|
||||||
/target
|
/target
|
||||||
|
|
||||||
@ -9,3 +9,10 @@
|
|||||||
/.factorypath
|
/.factorypath
|
||||||
|
|
||||||
/.polyglot.metaborg.yaml
|
/.polyglot.metaborg.yaml
|
||||||
|
|
||||||
|
*.aterm
|
||||||
|
/site
|
||||||
|
tests/extracted/*
|
||||||
|
tests/*.js
|
||||||
|
tests/*.py
|
||||||
|
tests/*.hs
|
||||||
|
208
LICENSE
Normal file
208
LICENSE
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
Apache License
|
||||||
|
|
||||||
|
Version 2.0, January 2004
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION,
|
||||||
|
AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction, and distribution
|
||||||
|
as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
||||||
|
owner that is granting the License.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||||
|
that control, are controlled by, or are under common control with that entity.
|
||||||
|
For the purposes of this definition, "control" means (i) the power, direct
|
||||||
|
or indirect, to cause the direction or management of such entity, whether
|
||||||
|
by contract or otherwise, or (ii) ownership of fifty percent (50%) or more
|
||||||
|
of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions
|
||||||
|
granted by this License.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications, including
|
||||||
|
but not limited to software source code, documentation source, and configuration
|
||||||
|
files.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical transformation
|
||||||
|
or translation of a Source form, including but not limited to compiled object
|
||||||
|
code, generated documentation, and conversions to other media types.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or Object form,
|
||||||
|
made available under the License, as indicated by a copyright notice that
|
||||||
|
is included in or attached to the work (an example is provided in the Appendix
|
||||||
|
below).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object form,
|
||||||
|
that is based on (or derived from) the Work and for which the editorial revisions,
|
||||||
|
annotations, elaborations, or other modifications represent, as a whole, an
|
||||||
|
original work of authorship. For the purposes of this License, Derivative
|
||||||
|
Works shall not include works that remain separable from, or merely link (or
|
||||||
|
bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including the original version
|
||||||
|
of the Work and any modifications or additions to that Work or Derivative
|
||||||
|
Works thereof, that is intentionally submitted to Licensor for inclusion in
|
||||||
|
the Work by the copyright owner or by an individual or Legal Entity authorized
|
||||||
|
to submit on behalf of the copyright owner. For the purposes of this definition,
|
||||||
|
"submitted" means any form of electronic, verbal, or written communication
|
||||||
|
sent to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems, and
|
||||||
|
issue tracking systems that are managed by, or on behalf of, the Licensor
|
||||||
|
for the purpose of discussing and improving the Work, but excluding communication
|
||||||
|
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||||
|
owner as "Not a Contribution."
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||||
|
of whom a Contribution has been received by Licensor and subsequently incorporated
|
||||||
|
within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of this
|
||||||
|
License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||||
|
no-charge, royalty-free, irrevocable copyright license to reproduce, prepare
|
||||||
|
Derivative Works of, publicly display, publicly perform, sublicense, and distribute
|
||||||
|
the Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of this License,
|
||||||
|
each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||||
|
no-charge, royalty-free, irrevocable (except as stated in this section) patent
|
||||||
|
license to make, have made, use, offer to sell, sell, import, and otherwise
|
||||||
|
transfer the Work, where such license applies only to those patent claims
|
||||||
|
licensable by such Contributor that are necessarily infringed by their Contribution(s)
|
||||||
|
alone or by combination of their Contribution(s) with the Work to which such
|
||||||
|
Contribution(s) was submitted. If You institute patent litigation against
|
||||||
|
any entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||||
|
that the Work or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses granted to You
|
||||||
|
under this License for that Work shall terminate as of the date such litigation
|
||||||
|
is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the Work or
|
||||||
|
Derivative Works thereof in any medium, with or without modifications, and
|
||||||
|
in Source or Object form, provided that You meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or Derivative Works a copy
|
||||||
|
of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices stating that
|
||||||
|
You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works that You distribute,
|
||||||
|
all copyright, patent, trademark, and attribution notices from the Source
|
||||||
|
form of the Work, excluding those notices that do not pertain to any part
|
||||||
|
of the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its distribution,
|
||||||
|
then any Derivative Works that You distribute must include a readable copy
|
||||||
|
of the attribution notices contained within such NOTICE file, excluding those
|
||||||
|
notices that do not pertain to any part of the Derivative Works, in at least
|
||||||
|
one of the following places: within a NOTICE text file distributed as part
|
||||||
|
of the Derivative Works; within the Source form or documentation, if provided
|
||||||
|
along with the Derivative Works; or, within a display generated by the Derivative
|
||||||
|
Works, if and wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and do not modify the
|
||||||
|
License. You may add Your own attribution notices within Derivative Works
|
||||||
|
that You distribute, alongside or as an addendum to the NOTICE text from the
|
||||||
|
Work, provided that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and may provide
|
||||||
|
additional or different license terms and conditions for use, reproduction,
|
||||||
|
or distribution of Your modifications, or for any such Derivative Works as
|
||||||
|
a whole, provided Your use, reproduction, and distribution of the Work otherwise
|
||||||
|
complies with the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise, any
|
||||||
|
Contribution intentionally submitted for inclusion in the Work by You to the
|
||||||
|
Licensor shall be under the terms and conditions of this License, without
|
||||||
|
any additional terms or conditions. Notwithstanding the above, nothing herein
|
||||||
|
shall supersede or modify the terms of any separate license agreement you
|
||||||
|
may have executed with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade names,
|
||||||
|
trademarks, service marks, or product names of the Licensor, except as required
|
||||||
|
for reasonable and customary use in describing the origin of the Work and
|
||||||
|
reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or agreed to
|
||||||
|
in writing, Licensor provides the Work (and each Contributor provides its
|
||||||
|
Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied, including, without limitation, any warranties
|
||||||
|
or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness
|
||||||
|
of using or redistributing the Work and assume any risks associated with Your
|
||||||
|
exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory, whether
|
||||||
|
in tort (including negligence), contract, or otherwise, unless required by
|
||||||
|
applicable law (such as deliberate and grossly negligent acts) or agreed to
|
||||||
|
in writing, shall any Contributor be liable to You for damages, including
|
||||||
|
any direct, indirect, special, incidental, or consequential damages of any
|
||||||
|
character arising as a result of this License or out of the use or inability
|
||||||
|
to use the Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all other commercial
|
||||||
|
damages or losses), even if such Contributor has been advised of the possibility
|
||||||
|
of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing the Work
|
||||||
|
or Derivative Works thereof, You may choose to offer, and charge a fee for,
|
||||||
|
acceptance of support, warranty, indemnity, or other liability obligations
|
||||||
|
and/or rights consistent with this License. However, in accepting such obligations,
|
||||||
|
You may act only on Your own behalf and on Your sole responsibility, not on
|
||||||
|
behalf of any other Contributor, and only if You agree to indemnify, defend,
|
||||||
|
and hold each Contributor harmless for any liability incurred by, or claims
|
||||||
|
asserted against, such Contributor by reason of your accepting any such warranty
|
||||||
|
or additional liability. END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following boilerplate
|
||||||
|
notice, with the fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
information. (Don't include the brackets!) The text should be enclosed in
|
||||||
|
the appropriate comment syntax for the file format. We also recommend that
|
||||||
|
a file or class name and description of purpose be included on the same "printed
|
||||||
|
page" as the copyright notice for easier identification within third-party
|
||||||
|
archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
|
||||||
|
limitations under the License.
|
48
README.md
48
README.md
@ -1,18 +1,40 @@
|
|||||||
# fostr Language Specification
|
# The fostr programming language
|
||||||
|
|
||||||
## Using Statix for multi-file analysis
|
I don't really like to write code, but I do like the things that coding can
|
||||||
|
build for me: accounting systems for non-profits I care about, spreadsheets
|
||||||
|
that have a reasonable calculation language for cell contents, geometric
|
||||||
|
visualizations that really help to understand three (and maybe even four!)
|
||||||
|
dimensions.
|
||||||
|
|
||||||
By default the project is configured to analyze all files of your language in
|
So I embarked on this project to see if I could produce as comfortable a
|
||||||
isolation -- single-file analysis. It is also possible to configure the project
|
language as possible to work in, given that I inevitably will be doing a
|
||||||
such that all files are analyzed together, and files can refer to each other --
|
bunch of coding. The language will be
|
||||||
multi-file analysis.
|
organized around (unary) ++f++unctions, (binary) ++o++perators, and
|
||||||
|
(nullary) ++str++eams, hence the name "fostr".
|
||||||
|
|
||||||
To enable multi-file analysis, do the following:
|
Other guiding principles:
|
||||||
1. Uncomment the `(multifile)` option in `editor/Analysis.esv`
|
|
||||||
2. Uncomment the multi-file definition, and comment the single-file version, of
|
|
||||||
`editor-analyze` in `trans/analysis.str`.
|
|
||||||
|
|
||||||
NB. When working in an IDE such as Eclipse, it is necessary to _restart the IDE_
|
* Maximize signal to noise ratio in code, which means minimizing the number
|
||||||
after switching from single-file to multi-file analysis or vice versa. Failure to
|
of symbols that have to be there just for the syntax; reducing punctuation;
|
||||||
do so will result in exceptions during analysis.
|
seeking brief syntax that is not too terse; etc.
|
||||||
|
|
||||||
|
* Since code is always structurally indented anyway, make use of that and
|
||||||
|
don't repeat information that's in the whitespace. This principle meshes
|
||||||
|
well with the previous one, and if whitespace significance is baked into
|
||||||
|
the language design from the ground up, it can be kept both effective and
|
||||||
|
natural.
|
||||||
|
|
||||||
|
* Code uses functions all the time. So needless to say, functions should be
|
||||||
|
first-class entities that are exceptionally easy to create, pass around,
|
||||||
|
etc.
|
||||||
|
|
||||||
|
* And true to the name, operators and streams should be just as easy to handle.
|
||||||
|
|
||||||
|
* Try to keep the constructs available as simple to reason about as possible,
|
||||||
|
and practical to use. So side effects are OK, and it should be clear when
|
||||||
|
they occur and in what order. And if possible, fostr will consist **only**
|
||||||
|
of expressions, no other syntactic constructs. Everything has a value.
|
||||||
|
|
||||||
|
<!-- /md -->
|
||||||
|
Like just about every other language, this documentation begins with a
|
||||||
|
[whirlwind tour](http::/studioinfinity.org/fostr/basic).
|
||||||
|
36
bin/extract_tests.xsh
Normal file
36
bin/extract_tests.xsh
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env xonsh
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
#### Set Parameters
|
||||||
|
# Should be a list of Path objects:
|
||||||
|
TEST_LIST = pg`tests/*.spt`
|
||||||
|
|
||||||
|
# Should be the top-level directory for all extracted tests:
|
||||||
|
# (there will be one subdirectory per item in TEST_LIST)
|
||||||
|
DESTINATION = 'tests/extracted'
|
||||||
|
|
||||||
|
# Extension for extracted files:
|
||||||
|
EXT = 'fos'
|
||||||
|
|
||||||
|
# Extension for expectations:
|
||||||
|
EXP = 'expect'
|
||||||
|
|
||||||
|
for path in TEST_LIST:
|
||||||
|
destdir = pf"{DESTINATION}/{path.stem}"
|
||||||
|
mkdir -p @(destdir)
|
||||||
|
contents = path.read_text()
|
||||||
|
tests = re.split(r'test\s*(.+?)\s*\[\[.*?\n', contents)[1:]
|
||||||
|
testit = iter(tests)
|
||||||
|
for name, details in zip(testit, testit):
|
||||||
|
em = re.search(r'\n\s*\]\]', details)
|
||||||
|
if not em: continue
|
||||||
|
example = details[:em.start()+1]
|
||||||
|
expath = destdir / f"{name}.{EXT}"
|
||||||
|
expath.write_text(example)
|
||||||
|
echo Wrote @(expath)
|
||||||
|
xm = re.search(r'/\*\*\s+writes.*?\n([\s\S]*?)\*\*/', details[em.end():])
|
||||||
|
if xm:
|
||||||
|
xpath = destdir / f"{name}.{EXP}"
|
||||||
|
xpath.write_text(xm[1])
|
||||||
|
echo " ...and" @(xpath)
|
71
bin/fosgen
Executable file
71
bin/fosgen
Executable file
@ -0,0 +1,71 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
##### Convenience:
|
||||||
|
erro() { printf "%s\n" "$*" >&2; }
|
||||||
|
|
||||||
|
##### Set defaults:
|
||||||
|
SUPPRESS_ERR=YES
|
||||||
|
LANGUAGE=Python
|
||||||
|
|
||||||
|
##### Extract command line options:
|
||||||
|
while [[ $1 = -* ]]
|
||||||
|
do
|
||||||
|
case $1 in
|
||||||
|
-h|--help)
|
||||||
|
echo
|
||||||
|
echo "Usage:"
|
||||||
|
echo " fosgen [-d] [-l LANGUAGE] FILE"
|
||||||
|
echo
|
||||||
|
echo "Writes to standard output the code generated from the fostr"
|
||||||
|
echo "program in FILE, targeting the specified LANGUAGE (which"
|
||||||
|
echo "defaults to Python)."
|
||||||
|
echo
|
||||||
|
echo "The -d option writes diagnostic output to standard error."
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
-d)
|
||||||
|
SUPPRESS_ERR=''
|
||||||
|
;;
|
||||||
|
-l)
|
||||||
|
shift
|
||||||
|
LANGUAGE="$1"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
##### Get positional arguments:
|
||||||
|
PROGRAM=$1
|
||||||
|
|
||||||
|
##### Corral resources:
|
||||||
|
BINDIR=$(dirname $BASH_SOURCE)
|
||||||
|
SUNJAR="$BINDIR/../lib/sunshine.jar"
|
||||||
|
PROJDIR="$BINDIR/.."
|
||||||
|
|
||||||
|
if [[ ! -f $SUNJAR ]]; then
|
||||||
|
erro "Please download the Spoofax Sunshine jar to the lib directory."
|
||||||
|
erro "Recommended command:"
|
||||||
|
erro " curl -o lib/sunshine.jar -L 'http://artifacts.metaborg.org/service/local/artifact/maven/redirect?r=snapshots&g=org.metaborg&a=org.metaborg.sunshine2&v=LATEST'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! $MVN_REPO ]]; then
|
||||||
|
MVN_REPO="$HOME/.m2/repository"
|
||||||
|
fi
|
||||||
|
if [[ ! -d $MVN_REPO ]]; then
|
||||||
|
MVN_REPO="/root/.m2/repository"
|
||||||
|
fi
|
||||||
|
if [[ ! -d $MVN_REPO ]]; then
|
||||||
|
erro "Cannot find your Maven repository. Please set environment variable"
|
||||||
|
erro "MVN_REPO to its full path and re-run."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
##### Perform the code generation:
|
||||||
|
if [[ $SUPPRESS_ERR ]]
|
||||||
|
then
|
||||||
|
exec 2>/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
java -jar $SUNJAR transform -p $PROJDIR -l $PROJDIR -l $MVN_REPO -n $LANGUAGE -i $PROGRAM
|
||||||
|
exit $?
|
19
bin/generate_test_code
Executable file
19
bin/generate_test_code
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
failed=0
|
||||||
|
|
||||||
|
for dir in tests/extracted/*; do
|
||||||
|
for file in $dir/*.fos; do
|
||||||
|
for language in Python Javascript Haskell; do
|
||||||
|
echo bin/fosgen -l ${language%.*} $file ...
|
||||||
|
bin/fosgen -l $language $file
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo ' ... Failed.'
|
||||||
|
((failed++))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Code generation completed with $failed failures."
|
||||||
|
exit $failed
|
33
bin/run_tests
Executable file
33
bin/run_tests
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
command=$1
|
||||||
|
ext=$2
|
||||||
|
total=0
|
||||||
|
failed=0
|
||||||
|
diffed=0
|
||||||
|
|
||||||
|
for dir in tests/extracted/*; do
|
||||||
|
for file in $dir/*.$ext; do
|
||||||
|
((total++))
|
||||||
|
$command $file > $file.out
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo ERROR: $command $file failed.
|
||||||
|
((failed++))
|
||||||
|
else
|
||||||
|
if [[ -f ${file%.*}.expect ]]; then
|
||||||
|
echo ---- diff ${file%.*}.expect $file.out ----
|
||||||
|
diff ${file%.*}.expect $file.out
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
((diffed++))
|
||||||
|
fi
|
||||||
|
echo -------------------------------
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Ran $total tests: $failed failures, $diffed runs differed."
|
||||||
|
if [[ $failed -gt 0 ]] || [[ $diffed -gt 0 ]]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
exit 0
|
16
docs/implementation.md
Normal file
16
docs/implementation.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
## Using Statix for multi-file analysis
|
||||||
|
|
||||||
|
By default the project is configured to analyze all files of your language in
|
||||||
|
isolation -- single-file analysis. It is also possible to configure the project
|
||||||
|
such that all files are analyzed together, and files can refer to each other --
|
||||||
|
multi-file analysis.
|
||||||
|
|
||||||
|
To enable multi-file analysis, do the following:
|
||||||
|
1. Uncomment the `(multifile)` option in `editor/Analysis.esv`
|
||||||
|
2. Uncomment the multi-file definition, and comment the single-file version, of
|
||||||
|
`editor-analyze` in `trans/analysis.str`.
|
||||||
|
|
||||||
|
NB. When working in an IDE such as Eclipse, it is necessary to _restart the IDE_
|
||||||
|
after switching from single-file to multi-file analysis or vice versa. Failure to
|
||||||
|
do so will result in exceptions during analysis.
|
||||||
|
|
@ -6,7 +6,7 @@ imports
|
|||||||
|
|
||||||
language
|
language
|
||||||
|
|
||||||
// see README.md for details on how to switch to multi-file analysis
|
// see docs/implementation.md for details on how to switch to multi-file analysis
|
||||||
|
|
||||||
observer : editor-analyze (constraint) // (multifile)
|
observer : editor-analyze (constraint) // (multifile)
|
||||||
|
|
||||||
|
6
editor/Generation.esv
Normal file
6
editor/Generation.esv
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module Generation
|
||||||
|
menus
|
||||||
|
menu: "Generation" (openeditor)
|
||||||
|
action: "Python" = to-python
|
||||||
|
action: "Javascript" = to-javascript
|
||||||
|
action: "Haskell" = to-haskell
|
@ -4,6 +4,7 @@ imports
|
|||||||
|
|
||||||
Syntax
|
Syntax
|
||||||
Analysis
|
Analysis
|
||||||
|
Generation
|
||||||
|
|
||||||
language
|
language
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ imports
|
|||||||
language
|
language
|
||||||
|
|
||||||
table : target/metaborg/sdf.tbl
|
table : target/metaborg/sdf.tbl
|
||||||
start symbols : Start
|
start symbols : Ex
|
||||||
|
|
||||||
line comment : "//"
|
line comment : "//"
|
||||||
block comment : "/*" * "*/"
|
block comment : "/*" * "*/"
|
||||||
|
22
mkdocs.yml
Normal file
22
mkdocs.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
site_name: fostr language
|
||||||
|
nav:
|
||||||
|
- README.md
|
||||||
|
- tests/basic.md
|
||||||
|
- implementation.md
|
||||||
|
|
||||||
|
plugins:
|
||||||
|
- search
|
||||||
|
- semiliterate:
|
||||||
|
ignore_folders: [target]
|
||||||
|
exclude_extensions: ['.o', '.hi']
|
||||||
|
extract_standard_markdown:
|
||||||
|
terminate: <!-- /md -->
|
||||||
|
theme:
|
||||||
|
name: readthedocs
|
||||||
|
markdown_extensions:
|
||||||
|
- attr_list
|
||||||
|
- markdown-del-ins
|
||||||
|
- pymdownx.superfences
|
||||||
|
- pymdownx.highlight:
|
||||||
|
use_pygments: true
|
||||||
|
- smarty
|
@ -6,12 +6,27 @@ imports
|
|||||||
|
|
||||||
context-free start-symbols
|
context-free start-symbols
|
||||||
|
|
||||||
Start
|
Ex
|
||||||
|
|
||||||
context-free sorts
|
context-free sorts
|
||||||
|
|
||||||
Start
|
Ex
|
||||||
|
|
||||||
context-free syntax
|
context-free syntax
|
||||||
|
|
||||||
Start.Empty = <>
|
Ex.Int = INT
|
||||||
|
Ex.Stdio = <stdio>
|
||||||
|
Ex.Sum = {Ex "+"}+
|
||||||
|
Ex.Receives = [[Ex] << [Ex]] {left}
|
||||||
|
|
||||||
|
context-free priorities
|
||||||
|
|
||||||
|
Ex.Sum
|
||||||
|
> Ex.Receives,
|
||||||
|
|
||||||
|
// prevent cycle: no singletons
|
||||||
|
Ex.Sum <0> .> {Ex "+"}+ = Ex,
|
||||||
|
|
||||||
|
// flat: no Sum immediately in Sum:
|
||||||
|
{Ex "+"}+ = Ex <0> .> Ex.Sum,
|
||||||
|
{Ex "+"}+ = {Ex "+"}+ "+" Ex <2> .> Ex.Sum
|
||||||
|
74
tests/basic.spt
Normal file
74
tests/basic.spt
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
module basic
|
||||||
|
language fostr
|
||||||
|
|
||||||
|
/** md
|
||||||
|
Title: A whirlwind tour of fostr
|
||||||
|
|
||||||
|
## Whirlwind tour
|
||||||
|
|
||||||
|
fostr is just in its infancy, so it's not yet even ready for
|
||||||
|
Hello, World. The best we can offer now is this little snippet
|
||||||
|
that writes the sum of the ASCII codes for 'H', 'W', and '!' to standard output:
|
||||||
|
```fostr
|
||||||
|
**/
|
||||||
|
|
||||||
|
/** md */ test emit_sum [[
|
||||||
|
stdio << 72 + 87 + 33
|
||||||
|
]]/* **/ parse to Receives(Stdio(), Sum([Int("72"), Int("87"), Int("33")]))
|
||||||
|
/** writes
|
||||||
|
192**/
|
||||||
|
|
||||||
|
/** md
|
||||||
|
```
|
||||||
|
|
||||||
|
At the moment, there are only two ways to run a file containing fostr code
|
||||||
|
(you can find the above in `tests/emit_sum.fos`). They both start by
|
||||||
|
cloning this fostr project. Then, either:
|
||||||
|
|
||||||
|
1. Open the project in Eclipse and build it, visit your program file,
|
||||||
|
generate code from it in your preferred target language (among
|
||||||
|
the options available in the "Spoofax > Generate" menu), and execute the
|
||||||
|
resulting code.
|
||||||
|
|
||||||
|
1. Use the `bin/fosgen` bash script to generate code in a target language,
|
||||||
|
and execute the resulting code.
|
||||||
|
|
||||||
|
For example, this snippet generates the following Python:
|
||||||
|
```python
|
||||||
|
{! ../examples/emit_sum.py extract:
|
||||||
|
start: 'Stdio\s='
|
||||||
|
!}
|
||||||
|
```
|
||||||
|
(which writes "192" to standard output), or this non-idiomatic, inefficient, but
|
||||||
|
working Javascript:
|
||||||
|
```javascript
|
||||||
|
{! ../examples/emit_sum.js extract:
|
||||||
|
start: '^}'
|
||||||
|
!}
|
||||||
|
```
|
||||||
|
In either case, there's also a preamble defining Stdio that's generated.
|
||||||
|
(Haskell code generation is also currently supported.)
|
||||||
|
|
||||||
|
### Everything has a value
|
||||||
|
|
||||||
|
As mentioned in the [Introduction](../README.md), everything in a fostr
|
||||||
|
program (including the entire program itself) is an expression and has
|
||||||
|
a value. So what's the value of that expression above? Well, `stdio` is our
|
||||||
|
first example of a stream, and for convenience, the value of a stream
|
||||||
|
receiving an item is just the stream back again. The `<<` operator is also
|
||||||
|
left-associative, so that way we can chain insertions into a stream:
|
||||||
|
```fostr
|
||||||
|
**/
|
||||||
|
|
||||||
|
/** md */ test emit_twice [[
|
||||||
|
stdio << 72 + 87 + 33 << 291
|
||||||
|
]]/* **/ parse to Receives(
|
||||||
|
Receives(Stdio(), Sum([Int("72"), Int("87"), Int("33")])),
|
||||||
|
Int("291"))
|
||||||
|
/** writes
|
||||||
|
192291**/
|
||||||
|
|
||||||
|
/** md
|
||||||
|
```
|
||||||
|
Running this program produces a nice palindromic output: "192291".
|
||||||
|
**/
|
1
tests/emit_sum.fos
Normal file
1
tests/emit_sum.fos
Normal file
@ -0,0 +1 @@
|
|||||||
|
stdio << 72 + 87 + 33
|
@ -15,12 +15,12 @@ rules // Analysis
|
|||||||
// single-file analysis
|
// single-file analysis
|
||||||
editor-analyze = stx-editor-analyze(pre-analyze, post-analyze|"statics", "programOk")
|
editor-analyze = stx-editor-analyze(pre-analyze, post-analyze|"statics", "programOk")
|
||||||
|
|
||||||
// see README.md for details on how to switch to multi-file analysis
|
// see docs/implementation.md for details on how to switch to multi-file analysis
|
||||||
// multi-file analysis
|
// multi-file analysis
|
||||||
// editor-analyze = stx-editor-analyze(pre-analyze, post-analyze|"statics", "projectOk", "fileOk")
|
// editor-analyze = stx-editor-analyze(pre-analyze, post-analyze|"statics", "projectOk", "fileOk")
|
||||||
|
|
||||||
pre-analyze = origin-track-forced(explicate-injections-fostr-Start)
|
pre-analyze = origin-track-forced(explicate-injections-fostr-Ex)
|
||||||
post-analyze = origin-track-forced(implicate-injections-fostr-Start)
|
post-analyze = origin-track-forced(implicate-injections-fostr-Ex)
|
||||||
|
|
||||||
rules // Editor Services
|
rules // Editor Services
|
||||||
|
|
||||||
|
@ -6,6 +6,9 @@ imports
|
|||||||
pp
|
pp
|
||||||
outline
|
outline
|
||||||
analysis
|
analysis
|
||||||
|
haskell
|
||||||
|
javascript
|
||||||
|
python
|
||||||
|
|
||||||
rules // Debugging
|
rules // Debugging
|
||||||
|
|
||||||
|
41
trans/haskell.str
Normal file
41
trans/haskell.str
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
module haskell
|
||||||
|
imports libstrategolib signatures/-
|
||||||
|
|
||||||
|
signature
|
||||||
|
constructors
|
||||||
|
TopLevel: Ex -> Ex
|
||||||
|
|
||||||
|
rules
|
||||||
|
hs: TopLevel(x) -> $[import System.IO
|
||||||
|
data IOStream = StdIO
|
||||||
|
|
||||||
|
stdio :: IO IOStream
|
||||||
|
stdio = return StdIO
|
||||||
|
|
||||||
|
receives :: Show b => IO a -> b -> IO a
|
||||||
|
receives s d = do
|
||||||
|
temp <- s
|
||||||
|
putStr(show d)
|
||||||
|
return temp
|
||||||
|
|
||||||
|
main = do
|
||||||
|
[<hs>x]]
|
||||||
|
|
||||||
|
hs: Stdio() -> $[stdio]
|
||||||
|
hs: Int(x) -> x
|
||||||
|
hs: Sum(x) -> $[sum [<hs>x]]
|
||||||
|
hs: Receives(x, y) -> $[[<hs>x] `receives` [<hs>y]]
|
||||||
|
hs: [] -> $<[]>
|
||||||
|
hs: [x | xs] -> $<[<<hs>x><<hstail>xs>]>
|
||||||
|
|
||||||
|
strategies
|
||||||
|
// wrap expression in a toplevel and then apply code generation
|
||||||
|
haskell = !TopLevel(<id>); hs
|
||||||
|
|
||||||
|
// translate each element of a list, prepending each with ',', and concatenate
|
||||||
|
hstail = foldr(!"", \ (x,y) -> $<, <<hs>x><y>> \)
|
||||||
|
|
||||||
|
// Interface haskell code generation with editor services and file system
|
||||||
|
to-haskell: (selected, _, _, path, project-path) -> (filename, result)
|
||||||
|
with filename := <guarantee-extension(|"hs")> path
|
||||||
|
; result := <haskell> selected
|
31
trans/javascript.str
Normal file
31
trans/javascript.str
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
module javascript
|
||||||
|
imports libstrategolib signatures/-
|
||||||
|
|
||||||
|
signature
|
||||||
|
constructors
|
||||||
|
TopLevel: Ex -> Ex
|
||||||
|
|
||||||
|
rules
|
||||||
|
js: TopLevel(x) -> $[const Stdio = {
|
||||||
|
receives: v => { process.stdout.write(String(v)); return Stdio; }
|
||||||
|
}
|
||||||
|
[<js>x]]
|
||||||
|
|
||||||
|
js: Stdio() -> $[Stdio]
|
||||||
|
js: Int(x) -> x
|
||||||
|
js: Sum(x) -> $[[<js>x].reduce((v,w) => v+w)]
|
||||||
|
js: Receives(x, y) -> $[[<js>x].receives([<js>y])]
|
||||||
|
js: [] -> $<[]>
|
||||||
|
js: [x | xs] -> $<[<<js>x><<jstail>xs>]>
|
||||||
|
|
||||||
|
strategies
|
||||||
|
// wrap expression in a toplevel and then apply code generation
|
||||||
|
javascript = !TopLevel(<id>); js
|
||||||
|
|
||||||
|
// translate each element of a list, prepending each with ',', and concatenate
|
||||||
|
jstail = foldr(!"", \ (x,y) -> $<, <<js>x><y>> \)
|
||||||
|
|
||||||
|
// Interface javascript code generation with editor services and file system
|
||||||
|
to-javascript: (selected, _, _, path, project-path) -> (filename, result)
|
||||||
|
with filename := <guarantee-extension(|"js")> path
|
||||||
|
; result := <javascript> selected
|
34
trans/python.str
Normal file
34
trans/python.str
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
module python
|
||||||
|
imports libstrategolib signatures/-
|
||||||
|
|
||||||
|
signature
|
||||||
|
constructors
|
||||||
|
TopLevel: Ex -> Ex
|
||||||
|
|
||||||
|
rules
|
||||||
|
py: TopLevel(x) -> $[import sys
|
||||||
|
class StdioC:
|
||||||
|
def receives(self, v):
|
||||||
|
print(v, file=sys.stdout, end='')
|
||||||
|
return self
|
||||||
|
Stdio = StdioC()
|
||||||
|
[<py>x]]
|
||||||
|
|
||||||
|
py: Stdio() -> $[Stdio]
|
||||||
|
py: Int(x) -> x
|
||||||
|
py: Sum(x) -> $[sum([<py>x])]
|
||||||
|
py: Receives(x, y) -> $[[<py>x].receives([<py>y])]
|
||||||
|
py: [] -> $<[]>
|
||||||
|
py: [x | xs] -> $<[<<py>x><<pytail>xs>]>
|
||||||
|
|
||||||
|
strategies
|
||||||
|
// wrap expression in a toplevel and then apply code generation
|
||||||
|
python = !TopLevel(<id>); py
|
||||||
|
|
||||||
|
// translate each element of a list, prepending each with ',', and concatenate
|
||||||
|
pytail = foldr(!"", \ (x,y) -> $[, [<py>x][y]] \)
|
||||||
|
|
||||||
|
// Interface python code generation with editor services and file system
|
||||||
|
to-python: (selected, _, _, path, project-path) -> (filename, result)
|
||||||
|
with filename := <guarantee-extension(|"py")> path
|
||||||
|
; result := <python> selected
|
@ -1,12 +1,15 @@
|
|||||||
module statics
|
module statics
|
||||||
|
|
||||||
// see README.md for details on how to switch to multi-file analysis
|
imports signatures/fostr-sig
|
||||||
|
|
||||||
|
// see docs/implementation.md for details on how to switch to multi-file analysis
|
||||||
|
|
||||||
rules // single-file entry point
|
rules // single-file entry point
|
||||||
|
|
||||||
programOk : Start
|
programOk : Ex
|
||||||
|
|
||||||
programOk(Empty()).
|
programOk(Sum(_)).
|
||||||
|
programOk(Receives(_,_)).
|
||||||
|
|
||||||
rules // multi-file entry point
|
rules // multi-file entry point
|
||||||
|
|
||||||
@ -14,11 +17,6 @@ rules // multi-file entry point
|
|||||||
|
|
||||||
projectOk(s).
|
projectOk(s).
|
||||||
|
|
||||||
fileOk : scope * Start
|
fileOk : scope * Ex
|
||||||
|
|
||||||
fileOk(s, Empty()).
|
fileOk(s, Receives(_,_)).
|
||||||
|
|
||||||
signature
|
|
||||||
|
|
||||||
sorts Start constructors
|
|
||||||
Empty : Start
|
|
||||||
|
Loading…
Reference in New Issue
Block a user