7401 - clean up support for non-Linux platforms

This commit is contained in:
Kartik Agaram 2020-12-25 12:26:05 -08:00
parent 56bfd52643
commit 47287fbf1a
10 changed files with 478 additions and 205 deletions

View File

@ -24,7 +24,8 @@ to _some_ safe and clear syntax with as few layers of translation as possible.
The emphasis is on internal consistency at any point in time rather than
compatibility with the past. ([More details.](http://akkartik.name/akkartik-convivial-20200607.pdf))
Currently Mu requires a 32-bit x86 processor and Linux kernel.
Currently Mu requires a 32-bit x86 processor. Generated programs require just
a Linux kernel and nothing else.
## Goals
@ -67,12 +68,20 @@ The Mu stack consists of:
- _bare_ SubX, a more rudimentary form of SubX without certain syntax sugar.
All Mu programs get translated through these layers into tiny zero-dependency
ELF binaries. The translators for most levels are built out of lower levels.
The translator from Mu to SubX is written in SubX, and the translator from
SubX to bare SubX is built in bare SubX.
ELF binaries that run natively on Linux. The translators for most levels are
built out of lower levels. The translator from Mu to SubX is written in SubX,
and the translator from SubX to bare SubX is built in bare SubX.
Mu programs can be run in emulated mode to emit traces, which permit time-travel
debugging. ([More details.](subx_debugging.md))
There's an emulator for running Mu binaries (more slowly) on other Unix-like
systems.
```sh
$ ./translate_mu_emulated apps/ex2.mu # emit a.elf using the emulator
$ ./bootstrap run ./a.elf # run in the emulator
$ echo $?
```
The emulator is also useful for [debugging](subx_debugging.md).
### incomplete tools

View File

@ -27,28 +27,16 @@ rudimentary but hopefully still workable toolkit:
mode (`bootstrap run`):
```
$ ./bootstrap translate input.subx -o binary
$ ./bootstrap --trace run binary arg1 arg2 2>trace
$ ./translate_subx_debug file1.subx file2.subx ... # generating a.elf
$ ./bootstrap --trace run a.elf arg1 arg2
saving trace to 'last_run'
```
The ability to generate a trace is the essential reason for the existence of
`bootstrap run` mode. It gives far better visibility into program internals than
running natively.
- As a further refinement, it is possible to render label names in the trace
by adding a second flag to the `bootstrap translate` command:
```
$ ./bootstrap --debug translate input.subx -o binary
$ ./bootstrap --trace run binary arg1 arg2 2>trace
```
`bootstrap --debug translate` emits a mapping from label to address in a file
called `labels`. `bootstrap --trace run` reads in the `labels` file if
it exists and prints out any matching label name as it traces each instruction
executed.
Here's a sample of what a trace looks like, with a few boxes highlighted:
Here's a sample of the contents of `last_run`, with a few boxes highlighted:
<img alt='trace example' src='html/trace.png'>
@ -60,10 +48,10 @@ rudimentary but hopefully still workable toolkit:
address `0x0900005e` maps to label `$loop` and presumably marks the start of
some loop. Function names get similar `run: == label` lines.
- One trick when emitting traces with labels:
- One quick trick when scanning a trace for the first time:
```
$ grep label trace
$ grep label last_run
```
This is useful for quickly showing you the control flow for the run, and the
@ -115,11 +103,21 @@ rudimentary but hopefully still workable toolkit:
`./translate_subx_debug`, and then running:
```
./bootstrap --trace --dump run a.elf test 2>&1 |grep 'label test'
grep 'label test-' |tail
```
Just read out the last test printed out before the segfault.
Even outside of tests, I can often quickly debug an error just by scanning
the end of a trace for labels:
```
$ grep label last_run |tail
```
Knowing _where_ the error occurred is often enough to put me on the right
track to debugging an error.
Hopefully these hints are enough to get you started. The main thing to
remember is to not be afraid of modifying the sources. A good debugging
session gets into a nice rhythm of generating a trace, staring at it for a

244
test_apps
View File

@ -1,180 +1,171 @@
#!/bin/sh
# Build and test all included SubX programs:
# Build and test all included SubX programs on Linux:
# translate them into ELF binaries
# compare the generated binaries with what's already in git
# run/test the ELF binaries in emulated mode (unless $NO_EMULATION)
# run/test the ELF binaries in native mode (if on Linux)
# run/test the ELF binaries in emulated mode
# run/test the ELF binaries in native mode
#
# Example usage:
# test_apps # compare generated binaries, run them in emulated and native mode
# test_apps record # run binaries in emulated and native mode
# NO_EMULATION=1 test_apps # compare generated binaries, run them in native mode
# NO_EMULATION=1 test_apps record # run binaries just in native mode
# test_apps
# test_apps record # don't compare with what's in git
set -e
cd `dirname $0`
test $NO_EMULATION || EMULATED=1
test $EMULATED && echo 'testing emulated runs'
test `uname` = 'Linux' && NATIVE=1
test $NATIVE && echo 'testing native runs'
./build
export OS=${OS:-linux}
echo "== translating and running using C++"
echo "== translating using the bootstrap C++ translator"
# example programs
echo ex1
./bootstrap translate init.$OS apps/ex1.subx -o apps/ex1
./bootstrap_bin translate init.linux apps/ex1.subx -o apps/ex1
test "$1" = 'record' || git diff --exit-code apps/ex1
test $EMULATED && {
./bootstrap run apps/ex1 || ret=$?
{
./bootstrap_bin run apps/ex1 || ret=$?
test $ret -eq 42 # life, the universe and everything
}
test $NATIVE && {
{
apps/ex1 || ret=$?
test $ret -eq 42 # life, the universe and everything
}
echo ex2
./bootstrap translate init.$OS apps/ex2.subx -o apps/ex2
./bootstrap_bin translate init.linux apps/ex2.subx -o apps/ex2
test "$1" = 'record' || git diff --exit-code apps/ex2
test $EMULATED && {
./bootstrap run apps/ex2 || ret=$?
{
./bootstrap_bin run apps/ex2 || ret=$?
test $ret -eq 7 # 3 + 4
}
test $NATIVE && {
{
apps/ex2 || ret=$?
test $ret -eq 7 # 3 + 4
}
echo ex3
./bootstrap translate init.$OS apps/ex3.subx -o apps/ex3
./bootstrap_bin translate init.linux apps/ex3.subx -o apps/ex3
test "$1" = 'record' || git diff --exit-code apps/ex3
test $EMULATED && {
./bootstrap run apps/ex3 || ret=$?
{
./bootstrap_bin run apps/ex3 || ret=$?
test $ret -eq 55 # 1 + 2 + ... + 10
}
test $NATIVE && {
{
apps/ex3 || ret=$?
test $ret -eq 55 # 1 + 2 + ... + 10
}
echo ex4
./bootstrap translate init.$OS apps/ex4.subx -o apps/ex4
./bootstrap_bin translate init.linux apps/ex4.subx -o apps/ex4
test "$1" = 'record' || git diff --exit-code apps/ex4
test $EMULATED && {
echo a | ./bootstrap run apps/ex4 >ex4.out || true
{
echo a | ./bootstrap_bin run apps/ex4 >ex4.out || true
test `cat ex4.out` = 'a'
}
test $NATIVE && {
{
echo a | apps/ex4 >ex4.out || true
test `cat ex4.out` = 'a'
}
echo ex5
./bootstrap translate init.$OS apps/ex5.subx -o apps/ex5
./bootstrap_bin translate init.linux apps/ex5.subx -o apps/ex5
test "$1" = 'record' || git diff --exit-code apps/ex5
test $EMULATED && {
echo a | ./bootstrap run apps/ex5 >ex5.out || true
{
echo a | ./bootstrap_bin run apps/ex5 >ex5.out || true
test `cat ex5.out` = 'a'
}
test $NATIVE && {
{
echo a | apps/ex5 >ex5.out || true
test `cat ex5.out` = 'a'
}
echo ex6
./bootstrap translate init.$OS apps/ex6.subx -o apps/ex6
./bootstrap_bin translate init.linux apps/ex6.subx -o apps/ex6
test "$1" = 'record' || git diff --exit-code apps/ex6
test $EMULATED && {
./bootstrap run apps/ex6 >ex6.out || true
{
./bootstrap_bin run apps/ex6 >ex6.out || true
test "`cat ex6.out`" = 'Hello, world!'
}
test $NATIVE && {
{
apps/ex6 >ex6.out || true
test "`cat ex6.out`" = 'Hello, world!'
}
echo ex7
./bootstrap translate init.$OS apps/ex7.subx -o apps/ex7
./bootstrap_bin translate init.linux apps/ex7.subx -o apps/ex7
test "$1" = 'record' || git diff --exit-code apps/ex7
test $EMULATED && {
./bootstrap run apps/ex7 || ret=$?
{
./bootstrap_bin run apps/ex7 || ret=$?
test $ret -eq 97 # 'a'
}
test $NATIVE && {
{
apps/ex7 || ret=$?
test $ret -eq 97 # 'a'
}
echo ex8
./bootstrap translate init.$OS apps/ex8.subx -o apps/ex8
./bootstrap_bin translate init.linux apps/ex8.subx -o apps/ex8
test "$1" = 'record' || git diff --exit-code apps/ex8
test $EMULATED && {
./bootstrap run apps/ex8 abcd || ret=$?
{
./bootstrap_bin run apps/ex8 abcd || ret=$?
test $ret -eq 4 # length('abcd')
}
test $NATIVE && {
{
apps/ex8 abcd || ret=$?
test $ret -eq 4 # length('abcd')
}
echo ex9
./bootstrap translate init.$OS apps/ex9.subx -o apps/ex9
./bootstrap_bin translate init.linux apps/ex9.subx -o apps/ex9
test "$1" = 'record' || git diff --exit-code apps/ex9
test $EMULATED && {
./bootstrap run apps/ex9 z x || ret=$?
{
./bootstrap_bin run apps/ex9 z x || ret=$?
test $ret -eq 2 # 'z' - 'x'
}
test $NATIVE && {
{
apps/ex9 z x || ret=$?
test $ret -eq 2 # 'z' - 'x'
}
echo ex10
./bootstrap translate init.$OS apps/ex10.subx -o apps/ex10
./bootstrap_bin translate init.linux apps/ex10.subx -o apps/ex10
test "$1" = 'record' || git diff --exit-code apps/ex10
test $EMULATED && {
./bootstrap run apps/ex10 abc abc || ret=$?
{
./bootstrap_bin run apps/ex10 abc abc || ret=$?
test $ret -eq 1 # equal
./bootstrap run apps/ex10 abc abcd # 0; not equal
./bootstrap_bin run apps/ex10 abc abcd # 0; not equal
}
test $NATIVE && {
{
apps/ex10 abc abc || ret=$?
test $ret -eq 1 # equal
apps/ex10 abc abcd # 0; not equal
}
echo ex11
./bootstrap translate init.$OS apps/ex11.subx -o apps/ex11
./bootstrap_bin translate init.linux apps/ex11.subx -o apps/ex11
test "$1" = 'record' || git diff --exit-code apps/ex11
test $EMULATED && {
./bootstrap run apps/ex11
{
./bootstrap_bin run apps/ex11
echo
}
test $NATIVE && {
{
apps/ex11
echo
}
echo ex12
./bootstrap translate init.$OS apps/ex12.subx -o apps/ex12
./bootstrap_bin translate init.linux apps/ex12.subx -o apps/ex12
test "$1" = 'record' || git diff --exit-code apps/ex12
test $EMULATED && ./bootstrap run apps/ex12 # final byte of mmap'd address is well-nigh guaranteed to be 0
test $EMULATED && ./bootstrap_bin run apps/ex12 # final byte of mmap'd address is well-nigh guaranteed to be 0
test $NATIVE && apps/ex12
echo ex13
./bootstrap translate init.$OS apps/ex13.subx -o apps/ex13
./bootstrap_bin translate init.linux apps/ex13.subx -o apps/ex13
test "$1" = 'record' || git diff --exit-code apps/ex13
test $EMULATED && {
./bootstrap run apps/ex13 || ret=$?
{
./bootstrap_bin run apps/ex13 || ret=$?
test $ret -eq 1 # 3 == 3
}
test $NATIVE && {
{
apps/ex13 || ret=$?
test $ret -eq 1 # 3 == 3
}
@ -182,15 +173,15 @@ test $NATIVE && {
# Larger apps that use the standard library.
echo factorial
./bootstrap translate init.$OS [01]*.subx apps/factorial.subx -o apps/factorial
./bootstrap_bin translate init.linux [01]*.subx apps/factorial.subx -o apps/factorial
test "$1" = 'record' || git diff --exit-code apps/factorial
test $EMULATED && {
./bootstrap run apps/factorial || ret=$?
{
./bootstrap_bin run apps/factorial || ret=$?
test $ret -eq 120 # factorial(5)
./bootstrap run apps/factorial test
./bootstrap_bin run apps/factorial test
echo
}
test $NATIVE && {
{
apps/factorial || ret=$?
test $ret -eq 120 # factorial(5)
apps/factorial test
@ -198,25 +189,25 @@ test $NATIVE && {
}
echo crenshaw2-1
./bootstrap translate init.$OS [01]*.subx apps/crenshaw2-1.subx -o apps/crenshaw2-1
./bootstrap_bin translate init.linux [01]*.subx apps/crenshaw2-1.subx -o apps/crenshaw2-1
test "$1" = 'record' || git diff --exit-code apps/crenshaw2-1
test $EMULATED && {
./bootstrap run apps/crenshaw2-1 test
{
./bootstrap_bin run apps/crenshaw2-1 test
echo
}
test $NATIVE && {
{
apps/crenshaw2-1 test
echo
}
echo crenshaw2-1b
./bootstrap translate init.$OS [01]*.subx apps/crenshaw2-1b.subx -o apps/crenshaw2-1b
./bootstrap_bin translate init.linux [01]*.subx apps/crenshaw2-1b.subx -o apps/crenshaw2-1b
test "$1" = 'record' || git diff --exit-code apps/crenshaw2-1b
test $EMULATED && {
./bootstrap run apps/crenshaw2-1b test
{
./bootstrap_bin run apps/crenshaw2-1b test
echo
}
test $NATIVE && {
{
apps/crenshaw2-1b test
echo
}
@ -226,13 +217,13 @@ test $NATIVE && {
for phase in hex survey pack assort dquotes tests
do
echo $phase
./bootstrap translate init.$OS [01]*.subx apps/subx-params.subx apps/$phase.subx -o apps/$phase
./bootstrap_bin translate init.linux [01]*.subx apps/subx-params.subx apps/$phase.subx -o apps/$phase
test "$1" = 'record' || git diff --exit-code apps/$phase
test $EMULATED && {
./bootstrap run apps/$phase test
{
./bootstrap_bin run apps/$phase test
echo
}
test $NATIVE && {
{
apps/$phase test
echo
}
@ -241,70 +232,67 @@ done
# Higher-level syntax.
# Certain phases of translation run native beyond this point. We're starting
# to go beyond functionality of the C++ bootstrap.
# to go beyond functionality of the C++ bootstrap_bin.
echo sigils
./bootstrap translate init.$OS [012]*.subx apps/subx-params.subx apps/sigils.subx -o apps/sigils
./bootstrap_bin translate init.linux [012]*.subx apps/subx-params.subx apps/sigils.subx -o apps/sigils
test "$1" = 'record' || git diff --exit-code apps/sigils
test $EMULATED && {
./bootstrap run apps/sigils test
{
./bootstrap_bin run apps/sigils test
echo
}
test $NATIVE && {
{
apps/sigils test
echo
}
test $NATIVE || { echo 'there are more tests, but you need Linux to run them'; exit 0; }
echo calls
cat init.$OS [012]*.subx apps/subx-params.subx apps/calls.subx | apps/sigils > a.sigils
./bootstrap translate a.sigils -o apps/calls
cat init.linux [012]*.subx apps/subx-params.subx apps/calls.subx | apps/sigils > a.sigils
./bootstrap_bin translate a.sigils -o apps/calls
test "$1" = 'record' || git diff --exit-code apps/calls
test $EMULATED && {
./bootstrap run apps/calls test
{
./bootstrap_bin run apps/calls test
echo
}
test $NATIVE && {
{
apps/calls test
echo
}
echo braces
cat init.$OS [012]*.subx apps/subx-params.subx apps/braces.subx | apps/calls | apps/sigils > a.sigils
./bootstrap translate a.sigils -o apps/braces
cat init.linux [012]*.subx apps/subx-params.subx apps/braces.subx | apps/calls | apps/sigils > a.sigils
./bootstrap_bin translate a.sigils -o apps/braces
test "$1" = 'record' || git diff --exit-code apps/braces
test $EMULATED && {
./bootstrap run apps/braces test
{
./bootstrap_bin run apps/braces test
echo
}
test $NATIVE && {
{
apps/braces test
echo
}
echo mu
cat init.$OS [0-2]*.subx apps/mu.subx | apps/braces | apps/calls | apps/sigils > a.sigils
./bootstrap translate a.sigils -o apps/mu
cat init.linux [0-2]*.subx apps/mu.subx | apps/braces | apps/calls | apps/sigils > a.sigils
./bootstrap_bin translate a.sigils -o apps/mu
test "$1" = 'record' || git diff --exit-code apps/mu
test $EMULATED && {
./bootstrap run apps/mu test
{
./bootstrap_bin run apps/mu test
echo
}
test $NATIVE && {
{
apps/mu test
echo
}
test $NATIVE || exit 0
echo "== translating using SubX (native only)"
echo "== translating using the self-hosted translator"
# example programs
for n in `seq 1 12`
do
echo ex$n
./translate_subx init.$OS apps/ex$n.subx
./translate_subx init.linux apps/ex$n.subx
diff apps/ex$n a.elf
done
@ -313,7 +301,7 @@ done
for app in factorial crenshaw2-1 crenshaw2-1b
do
echo $app
./translate_subx init.$OS [01]*.subx apps/$app.subx
./translate_subx init.linux [01]*.subx apps/$app.subx
diff apps/$app a.elf
done
@ -322,77 +310,77 @@ done
for app in hex survey pack assort dquotes tests
do
echo $app
./translate_subx init.$OS [01]*.subx apps/subx-params.subx apps/$app.subx
./translate_subx init.linux [01]*.subx apps/subx-params.subx apps/$app.subx
diff apps/$app a.elf
done
for app in sigils calls braces
do
echo $app
./translate_subx init.$OS [012]*.subx apps/subx-params.subx apps/$app.subx
./translate_subx init.linux [012]*.subx apps/subx-params.subx apps/$app.subx
diff apps/$app a.elf
done
# Mu translator
echo mu
./translate_subx init.$OS [0-2]*.subx apps/mu.subx
./translate_subx init.linux [0-2]*.subx apps/mu.subx
diff apps/mu a.elf
# Mu programs
echo ex1.mu
./translate_mu apps/ex1.mu
test $EMULATED && {
./bootstrap run a.elf || ret=$?
{
./bootstrap_bin run a.elf || ret=$?
test $ret -eq 42 # life, the universe and everything
}
test $NATIVE && {
{
./a.elf || ret=$?
test $ret -eq 42 # life, the universe and everything
}
echo ex2.mu
./translate_mu apps/ex2.mu
test $EMULATED && {
./bootstrap run a.elf || ret=$?
{
./bootstrap_bin run a.elf || ret=$?
test $ret -eq 7
}
test $NATIVE && {
{
./a.elf || ret=$?
test $ret -eq 7
}
echo ex3.mu
./translate_mu apps/ex3.mu
test $EMULATED && {
./bootstrap run a.elf || ret=$?
{
./bootstrap_bin run a.elf || ret=$?
test $ret -eq 55
}
test $NATIVE && {
{
./a.elf || ret=$?
test $ret -eq 55
}
echo ex3.2.mu
./translate_mu apps/ex3.2.mu
test $EMULATED && {
./bootstrap run a.elf || ret=$?
{
./bootstrap_bin run a.elf || ret=$?
test $ret -eq 55
}
test $NATIVE && {
{
./a.elf || ret=$?
test $ret -eq 55
}
echo factorial.mu
./translate_mu apps/factorial.mu
test $EMULATED && {
./bootstrap run a.elf || ret=$?
{
./bootstrap_bin run a.elf || ret=$?
test $ret -eq 120
./bootstrap run a.elf test
./bootstrap_bin run a.elf test
echo
}
test $NATIVE && {
{
./a.elf || ret=$?
test $ret -eq 120
./a.elf test

286
test_apps_emulated Executable file
View File

@ -0,0 +1,286 @@
#!/bin/sh
# Build and test all included SubX programs on non-Linux platforms:
# translate them into ELF binaries
# compare the generated binaries with what's already in git
# run/test the ELF binaries in emulated mode
#
# Example usage:
# test_apps_emulated
# test_apps_emulated record # don't compare with what's in git
#
# This script is slow. 20+ times slower than running natively on Linux.
set -e
cd `dirname $0`
./build
echo "== translating using the bootstrap C++ translator"
# example programs
echo ex1
./bootstrap_bin translate init.linux apps/ex1.subx -o apps/ex1
test "$1" = 'record' || git diff --exit-code apps/ex1
{
./bootstrap_bin run apps/ex1 || ret=$?
test $ret -eq 42 # life, the universe and everything
}
echo ex2
./bootstrap_bin translate init.linux apps/ex2.subx -o apps/ex2
test "$1" = 'record' || git diff --exit-code apps/ex2
{
./bootstrap_bin run apps/ex2 || ret=$?
test $ret -eq 7 # 3 + 4
}
echo ex3
./bootstrap_bin translate init.linux apps/ex3.subx -o apps/ex3
test "$1" = 'record' || git diff --exit-code apps/ex3
{
./bootstrap_bin run apps/ex3 || ret=$?
test $ret -eq 55 # 1 + 2 + ... + 10
}
echo ex4
./bootstrap_bin translate init.linux apps/ex4.subx -o apps/ex4
test "$1" = 'record' || git diff --exit-code apps/ex4
{
echo a | ./bootstrap_bin run apps/ex4 >ex4.out || true
test `cat ex4.out` = 'a'
}
echo ex5
./bootstrap_bin translate init.linux apps/ex5.subx -o apps/ex5
test "$1" = 'record' || git diff --exit-code apps/ex5
{
echo a | ./bootstrap_bin run apps/ex5 >ex5.out || true
test `cat ex5.out` = 'a'
}
echo ex6
./bootstrap_bin translate init.linux apps/ex6.subx -o apps/ex6
test "$1" = 'record' || git diff --exit-code apps/ex6
{
./bootstrap_bin run apps/ex6 >ex6.out || true
test "`cat ex6.out`" = 'Hello, world!'
}
echo ex7
./bootstrap_bin translate init.linux apps/ex7.subx -o apps/ex7
test "$1" = 'record' || git diff --exit-code apps/ex7
{
./bootstrap_bin run apps/ex7 || ret=$?
test $ret -eq 97 # 'a'
}
echo ex8
./bootstrap_bin translate init.linux apps/ex8.subx -o apps/ex8
test "$1" = 'record' || git diff --exit-code apps/ex8
{
./bootstrap_bin run apps/ex8 abcd || ret=$?
test $ret -eq 4 # length('abcd')
}
echo ex9
./bootstrap_bin translate init.linux apps/ex9.subx -o apps/ex9
test "$1" = 'record' || git diff --exit-code apps/ex9
{
./bootstrap_bin run apps/ex9 z x || ret=$?
test $ret -eq 2 # 'z' - 'x'
}
echo ex10
./bootstrap_bin translate init.linux apps/ex10.subx -o apps/ex10
test "$1" = 'record' || git diff --exit-code apps/ex10
{
./bootstrap_bin run apps/ex10 abc abc || ret=$?
test $ret -eq 1 # equal
./bootstrap_bin run apps/ex10 abc abcd # 0; not equal
}
echo ex11
./bootstrap_bin translate init.linux apps/ex11.subx -o apps/ex11
test "$1" = 'record' || git diff --exit-code apps/ex11
{
./bootstrap_bin run apps/ex11
echo
}
echo ex12
./bootstrap_bin translate init.linux apps/ex12.subx -o apps/ex12
test "$1" = 'record' || git diff --exit-code apps/ex12
test $EMULATED && ./bootstrap_bin run apps/ex12 # final byte of mmap'd address is well-nigh guaranteed to be 0
test $NATIVE && apps/ex12
echo ex13
./bootstrap_bin translate init.linux apps/ex13.subx -o apps/ex13
test "$1" = 'record' || git diff --exit-code apps/ex13
{
./bootstrap_bin run apps/ex13 || ret=$?
test $ret -eq 1 # 3 == 3
}
# Larger apps that use the standard library.
echo factorial
./bootstrap_bin translate init.linux [01]*.subx apps/factorial.subx -o apps/factorial
test "$1" = 'record' || git diff --exit-code apps/factorial
{
./bootstrap_bin run apps/factorial || ret=$?
test $ret -eq 120 # factorial(5)
./bootstrap_bin run apps/factorial test
echo
}
echo crenshaw2-1
./bootstrap_bin translate init.linux [01]*.subx apps/crenshaw2-1.subx -o apps/crenshaw2-1
test "$1" = 'record' || git diff --exit-code apps/crenshaw2-1
{
./bootstrap_bin run apps/crenshaw2-1 test
echo
}
echo crenshaw2-1b
./bootstrap_bin translate init.linux [01]*.subx apps/crenshaw2-1b.subx -o apps/crenshaw2-1b
test "$1" = 'record' || git diff --exit-code apps/crenshaw2-1b
{
./bootstrap_bin run apps/crenshaw2-1b test
echo
}
# Phases of the self-hosted SubX translator.
for phase in hex survey pack assort dquotes tests
do
echo $phase
./bootstrap_bin translate init.linux [01]*.subx apps/subx-params.subx apps/$phase.subx -o apps/$phase
test "$1" = 'record' || git diff --exit-code apps/$phase
{
./bootstrap_bin run apps/$phase test
echo
}
done
# Higher-level syntax.
# Certain phases of translation run native beyond this point. We're starting
# to go beyond functionality of the C++ bootstrap_bin.
echo sigils
./bootstrap_bin translate init.linux [012]*.subx apps/subx-params.subx apps/sigils.subx -o apps/sigils
test "$1" = 'record' || git diff --exit-code apps/sigils
{
./bootstrap_bin run apps/sigils test
echo
}
echo calls
cat init.linux [012]*.subx apps/subx-params.subx apps/calls.subx | ./bootstrap_bin run apps/sigils > a.sigils
./bootstrap_bin translate a.sigils -o apps/calls
test "$1" = 'record' || git diff --exit-code apps/calls
{
./bootstrap_bin run apps/calls test
echo
}
echo braces
cat init.linux [012]*.subx apps/subx-params.subx apps/braces.subx | ./bootstrap_bin run apps/calls | ./bootstrap_bin run apps/sigils > a.sigils
./bootstrap_bin translate a.sigils -o apps/braces
test "$1" = 'record' || git diff --exit-code apps/braces
{
./bootstrap_bin run apps/braces test
echo
}
echo mu
cat init.linux [0-2]*.subx apps/mu.subx | ./bootstrap_bin run apps/braces | ./bootstrap_bin run apps/calls | ./bootstrap_bin run apps/sigils > a.sigils
./bootstrap_bin translate a.sigils -o apps/mu
test "$1" = 'record' || git diff --exit-code apps/mu
{
./bootstrap_bin run apps/mu test
echo
}
echo "== translating using the self-hosted translator"
# example programs
for n in `seq 1 12`
do
echo ex$n
./translate_subx_emulated init.linux apps/ex$n.subx
diff apps/ex$n a.elf
done
# Larger apps that use the standard library.
for app in factorial crenshaw2-1 crenshaw2-1b
do
echo $app
./translate_subx_emulated init.linux [01]*.subx apps/$app.subx
diff apps/$app a.elf
done
# Phases of the self-hosted SubX translator.
for app in hex survey pack assort dquotes tests
do
echo $app
./translate_subx_emulated init.linux [01]*.subx apps/subx-params.subx apps/$app.subx
diff apps/$app a.elf
done
for app in sigils calls braces
do
echo $app
./translate_subx_emulated init.linux [012]*.subx apps/subx-params.subx apps/$app.subx
diff apps/$app a.elf
done
# Mu translator
echo mu
./translate_subx_emulated init.linux [0-2]*.subx apps/mu.subx
diff apps/mu a.elf
# Mu programs
echo ex1.mu
./translate_mu_emulated apps/ex1.mu
{
./bootstrap_bin run a.elf || ret=$?
test $ret -eq 42 # life, the universe and everything
}
echo ex2.mu
./translate_mu_emulated apps/ex2.mu
{
./bootstrap_bin run a.elf || ret=$?
test $ret -eq 7
}
echo ex3.mu
./translate_mu_emulated apps/ex3.mu
{
./bootstrap_bin run a.elf || ret=$?
test $ret -eq 55
}
echo ex3.2.mu
./translate_mu_emulated apps/ex3.2.mu
{
./bootstrap_bin run a.elf || ret=$?
test $ret -eq 55
}
echo factorial.mu
./translate_mu_emulated apps/factorial.mu
{
./bootstrap_bin run a.elf || ret=$?
test $ret -eq 120
./bootstrap_bin run a.elf test
echo
}
exit 0

View File

@ -1,6 +1,5 @@
#!/bin/sh
# Translate given Mu programs into ELF binaries.
# Linux only for now.
# Translate a given Mu program into an ELF binary on Linux.
set -e

View File

@ -1,5 +1,8 @@
#!/bin/sh
# Translate Mu programs with debug information on Linux.
# Translate given Mu files with debug information on Linux.
#
# (You _could_ do something similar on other platforms using emulation. But I
# often find that to be too slow.)
set -e

10
translate_mu_emulated Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
# Translate a Mu program using emulated mode on Linux or BSD or Mac.
set -e
./build
cat $* [0-9]*.mu |./bootstrap_bin run apps/mu > a.subx
./translate_subx_emulated init.linux [0-9]*.subx mu-init.subx a.subx

View File

@ -1,19 +1,6 @@
#!/bin/sh
# Translate SubX by running the self-hosted translator natively on Linux.
#
# Possible knobs:
# Whether to run a phase natively or in emulated mode.
# This script is for running natively.
# Whether to stop after a phase.
# This script assumes inputs are already working so doesn't easily show
# which phase an error happens in.
# Whether to trace a phase. Whether to always trace or rerun with tracing
# enabled after an error.
# Leave tracing to other scripts. We save intermediate files so it's easy
# to rerun a single phase afterwards.
# Whether to run a phase with debug information. (Need to juggle multiple
# sets of debug files.)
# Again, that's for subsequent scripts.
# Translate given SubX files by running the self-hosted translator natively on
# Linux.
set -e

View File

@ -1,28 +1,32 @@
#!/bin/sh
# Translate SubX files with debug information on Linux.
# Translate given SubX files with debug information on Linux.
#
# Mu's core tooling has a gap:
# 0. The C++ translator 'subx translate' can generate debug information on
# Linux or BSD or Mac, but doesn't support any syntax sugar.
# 1. The self-hosted translator 'translate' runs in emulated mode and can
# run on Linux or BSD or Mac. However, syntax sugar passes (sigils and
# calls) can be very slow to run emulated.
# 2. The self-hosted translator 'translate_subx' runs natively on Linux. It is
# fast, but you get no trace for runs and zero error-checking on the code
# emitted by sigils and calls. Which could still be buggy.
# Mu provides 3 canonical ways to translate unsafe SubX programs:
# 0. The C++ translator 'bootstrap translate' can generate traces for
# debugging on Linux or BSD or Mac, but doesn't support any syntax sugar.
# 1. The self-hosted translator can be run natively on Linux using
# 'translate_subx'. It is fast and supports all syntax sugar, but you get no
# trace for debugging.
# 2. The self-hosted translator can be run emulated on Linux or BSD or Mac
# using 'translate_subx_emulated'. It supports all syntax sugar. However, it
# can be slow if you generate traces.
#
# This script is a hack to get the best of all worlds. We run natively what we
# must, and leverage as much debug information as possible. This arrangement
# is snappy but requires Linux just like 'translate_subx'. You also are on your
# own to mentally map desugared instructions in traces and error messages back
# to the original sources.
# This script fills in the gap above by stitching together aspects from
# multiple approaches. It translates syntax sugar natively, but emulates lower
# levels using the C++ translator. The result is complete and relatively fast
# even when generating traces.
#
# The cost: it needs Linux. There is no script to generate traces while
# running emulated on BSD or Mac. That's often impractically slow.
set -e
./build
cat $* |apps/braces > a.braces
cat a.braces |apps/calls > a.calls
cat a.calls |apps/sigils > a.sigils
./bootstrap --debug translate a.sigils -o a.elf
./bootstrap_bin --debug translate a.sigils -o a.elf
chmod +x a.elf

View File

@ -1,20 +1,8 @@
#!/bin/sh
# Translate SubX by running the self-hosted translator in emulated mode on
# Linux or BSD or Mac.
# Translate given SubX files by running the self-hosted translator in emulated
# mode on Linux or BSD or Mac.
#
# Possible knobs:
# Whether to run a phase natively or in emulated mode.
# Just always emulate for now since we debug on non-Linux.
# Whether to stop after a phase.
# Just always run all phases, but print out phases so it's clear where an
# error happens.
# Whether to trace a phase. Whether to always trace or rerun with tracing
# enabled after an error.
# Leave tracing to other scripts. We save intermediate files so it's easy
# to rerun a single phase afterwards.
# Whether to run a phase with debug information. (Need to juggle multiple
# sets of debug files.)
# Again, that's for subsequent scripts.
# We _could_ generate traces here, but that's often extremely slow.
set -e
@ -24,9 +12,10 @@ cat $* |./bootstrap_bin run apps/braces > a.braces
cat a.braces |./bootstrap_bin run apps/calls > a.calls
cat a.calls |./bootstrap_bin run apps/sigils > a.sigils
cat a.sigils |./bootstrap_bin run apps/tests > a.tests
cat a.tests |./bootstrap_bin run apps/dquotes > a.dquotes
cat a.dquotes |./bootstrap_bin run apps/assort > a.assort
cat a.assort |./bootstrap_bin run apps/pack > a.pack
cat a.tests |./bootstrap_bin run apps/assort > a.assort
cat a.assort |./bootstrap_bin run apps/dquotes > a.dquotes
cat a.dquotes |./bootstrap_bin run apps/assort > a.assort2
cat a.assort2 |./bootstrap_bin run apps/pack > a.pack
cat a.pack |./bootstrap_bin run apps/survey > a.survey
cat a.survey |./bootstrap_bin run apps/hex > a.elf