summaryrefslogtreecommitdiff
path: root/tiger-compiler/tcsh
diff options
context:
space:
mode:
authorMartial Simon <msimon_fr@hotmail.com>2025-09-15 01:07:58 +0200
committerMartial Simon <msimon_fr@hotmail.com>2025-09-15 01:07:58 +0200
commit967be9e750221ab2ab783f95df79bb26d290a45e (patch)
tree6802900a5e975f9f68b169f0f503f040056d6952 /tiger-compiler/tcsh
add: added projectsHEADmain
Diffstat (limited to 'tiger-compiler/tcsh')
-rw-r--r--tiger-compiler/tcsh/Makefile.am5
-rw-r--r--tiger-compiler/tcsh/README-deps.txt49
-rwxr-xr-xtiger-compiler/tcsh/generate-swig-mk101
-rw-r--r--tiger-compiler/tcsh/python/Makefile.am60
-rw-r--r--tiger-compiler/tcsh/python/tc.py97
-rwxr-xr-xtiger-compiler/tcsh/python/tcsh-hir.test8
-rwxr-xr-xtiger-compiler/tcsh/python/tcsh-llvm.test8
-rw-r--r--tiger-compiler/tcsh/python/tests/ast.ipynb394
-rw-r--r--tiger-compiler/tcsh/python/tests/astclone.ipynb212
-rw-r--r--tiger-compiler/tcsh/python/tests/bind.ipynb283
-rw-r--r--tiger-compiler/tcsh/python/tests/combine.ipynb207
-rw-r--r--tiger-compiler/tcsh/python/tests/common.ipynb154
-rw-r--r--tiger-compiler/tcsh/python/tests/desugar.ipynb343
-rw-r--r--tiger-compiler/tcsh/python/tests/escapes.ipynb194
-rwxr-xr-xtiger-compiler/tcsh/python/tests/ipynbtest.py279
-rw-r--r--tiger-compiler/tcsh/python/tests/llvmtranslate.ipynb220
-rw-r--r--tiger-compiler/tcsh/python/tests/misc.ipynb358
-rw-r--r--tiger-compiler/tcsh/python/tests/object.ipynb182
-rw-r--r--tiger-compiler/tcsh/python/tests/overload.ipynb207
-rw-r--r--tiger-compiler/tcsh/python/tests/parse.ipynb150
-rw-r--r--tiger-compiler/tcsh/python/tests/tc.ipynb252
-rw-r--r--tiger-compiler/tcsh/python/tests/ti.ipynb186
-rw-r--r--tiger-compiler/tcsh/python/tests/type.ipynb228
-rwxr-xr-xtiger-compiler/tcsh/python/ti.py356
-rwxr-xr-xtiger-compiler/tcsh/run.in53
-rw-r--r--tiger-compiler/tcsh/run.mk6
-rw-r--r--tiger-compiler/tcsh/src/helper.hh16
-rw-r--r--tiger-compiler/tcsh/src/swig_real_type.hh67
-rw-r--r--tiger-compiler/tcsh/src/tiger_ast.i312
-rw-r--r--tiger-compiler/tcsh/src/tiger_astclone.i17
-rw-r--r--tiger-compiler/tcsh/src/tiger_bind.i13
-rw-r--r--tiger-compiler/tcsh/src/tiger_callgraph.i18
-rw-r--r--tiger-compiler/tcsh/src/tiger_combine.i14
-rw-r--r--tiger-compiler/tcsh/src/tiger_common.i73
-rw-r--r--tiger-compiler/tcsh/src/tiger_desugar.i30
-rw-r--r--tiger-compiler/tcsh/src/tiger_escapes.i11
-rw-r--r--tiger-compiler/tcsh/src/tiger_llvmtranslate.i39
-rw-r--r--tiger-compiler/tcsh/src/tiger_misc.i73
-rw-r--r--tiger-compiler/tcsh/src/tiger_object.i32
-rw-r--r--tiger-compiler/tcsh/src/tiger_overload.i14
-rw-r--r--tiger-compiler/tcsh/src/tiger_parse.i102
-rw-r--r--tiger-compiler/tcsh/src/tiger_type.i91
42 files changed, 5514 insertions, 0 deletions
diff --git a/tiger-compiler/tcsh/Makefile.am b/tiger-compiler/tcsh/Makefile.am
new file mode 100644
index 0000000..2c2c1f9
--- /dev/null
+++ b/tiger-compiler/tcsh/Makefile.am
@@ -0,0 +1,5 @@
+SUBDIRS = python
+
+EXTRA_DIST = README-deps.txt generate-swig-mk src
+
+check_SCRIPTS = run
diff --git a/tiger-compiler/tcsh/README-deps.txt b/tiger-compiler/tcsh/README-deps.txt
new file mode 100644
index 0000000..8e3fa60
--- /dev/null
+++ b/tiger-compiler/tcsh/README-deps.txt
@@ -0,0 +1,49 @@
+* Handling dependencies of SWIG-generated files. -*- outline -*-
+
+
+** The problem with non-Automade dependencies
+
+Sometimes, the dependencies computed by swig in tcsh/python/.deps and
+tcsh/ruby/.deps are void because of some changes in the build
+environment (e.g., SWIG has been installed somewhere else since the
+last build, and dependencies on SWIG's .swg files are no longer
+valid). Hence SWIG wrappers won't build, because of unmet
+dependencies.
+
+_build % make -C tcsh/ruby
+make: Entering directory `/home/levill_r/src/tc/_build/tcsh/ruby'
+make: *** No rule to make target `/home/levill_r/local/share/swig/1.3.29/swig.swg', needed by `tiger_misc-wrap.cc'. Stop.
+make: Leaving directory `/home/levill_r/src/tc/_build/tcsh/ruby'
+
+In the previous example, I (Roland) wasn't able to build TCSH/Ruby
+because I had updated from SWIG 1.3.29 (installed locally) to 1.3.31
+(provided by Debian).
+
+** Solution
+
+Our approach is to provide a target to reset the dependencies (i.e.,
+to set them to the initial state set by `configure'). `make
+deps-reset' provides that service, erasing dependencies generated by
+swig.
+
+_build % make -C tcsh/ruby deps-reset
+make: Entering directory `/home/levill_r/src/tc/_build/tcsh/ruby'
+make: Leaving directory `/home/levill_r/src/tc/_build/tcsh/ruby'
+
+The build can then proceed.
+
+_build % make -C tcsh/ruby
+make: Entering directory `/home/levill_r/src/tc/_build/tcsh/ruby'
+if /usr/bin/swig -c++ -ruby -I../../../lib -I../../../src -MD -MF ".deps/tiger_misc-wrap.Tcc" -o tiger_misc-wrap.cc ../../../lib/misc/tiger_misc.i; \
+ then \
+ mv -f ".deps/tiger_misc-wrap.Tcc" ".deps/tiger_misc-wrap.Pcc"; \
+ else \
+ rm -f ".deps/tiger_misc-wrap.Tcc"; exit 1; \
+ fi
+
+[...]
+
+
+Note: I don't know whether Automake is smart enough to handle this
+problem gracefully with the dependencies it already handles. If so,
+please tell us!
diff --git a/tiger-compiler/tcsh/generate-swig-mk b/tiger-compiler/tcsh/generate-swig-mk
new file mode 100755
index 0000000..200d98b
--- /dev/null
+++ b/tiger-compiler/tcsh/generate-swig-mk
@@ -0,0 +1,101 @@
+#! /bin/sh
+
+if test $# -ne 2; then
+ echo "Usage: $0 python filename" >&2
+ exit 1
+fi
+
+if test "x$1" != xpython; then
+ echo "$0: first argument must be \`python'"
+ exit 1
+fi
+
+if test -z "$top_srcdir"; then
+ echo "$0: top_srcdir undefined" >&2
+ exit 1
+fi
+
+lang=$1
+
+# Connect stdout to the output file.
+exec >$2
+
+cat <<EOF
+## Generated by $0. Do not edit by hand!
+
+AM_LDFLAGS = -avoid-version -module -shared
+AM_LIBADD = \$(top_builddir)/src/libtc.la
+tcdir = \$(top_srcdir)
+
+CLEANFILES =
+
+# The list of dependencies generated as a side-effect of running swig.
+SWIG_GENERATED_DEPS =
+
+EOF
+case $lang in
+ python) echo "nodist_python_PYTHON =" ;;
+esac
+
+# Compile swig modules.
+case $lang in
+ python) mod_dir=pyexec ;;
+esac
+for src in $(find $top_srcdir/tcsh/src -name '*.i' |
+ sed -e 's:'"$top_srcdir"':$(tcdir):')
+do
+ base=$(basename $src ".i")
+ module=$(echo $base | sed -e 's/tiger_//')
+ modulepath=$(dirname $src)
+ dest=$base-wrap.cc
+ case $lang in
+ python)
+ ltmodule=_tiger_$module
+ cleanfiles="$dest $base.py $base.pyc"
+ ;;
+ esac
+ # No $< and $@ here because NetBSD make does not like it. Two
+ # rules, because two outputs from a single input does not fit Make's
+ # model. See automake.info "Multiple Outputs".
+ cat <<EOF
+
+## Module: $module.
+${mod_dir}_LTLIBRARIES += $ltmodule.la
+nodist_${ltmodule}_la_SOURCES = $dest
+${ltmodule}_la_LIBADD = \$(AM_LIBADD)
+CLEANFILES += $cleanfiles
+$dest: $src
+ \$(AM_V_GEN)if \$(SWIG) \$(AM_SWIGFLAGS) \$(SWIGFLAGS) -MD -MF "\$(DEPDIR)/$base-wrap.Tcc" -o $dest $src; \\
+ then \\
+ mv -f "\$(DEPDIR)/$base-wrap.Tcc" "\$(DEPDIR)/$base-wrap.Pcc"; \\
+ else \\
+ rm -f "\$(DEPDIR)/$base-wrap.Tcc"; exit 1; \\
+ fi
+
+@AMDEP_TRUE@@am__include@ @am__quote@./\$(DEPDIR)/$base-wrap.Pcc@am__quote@
+
+@AMDEP_TRUE@ SWIG_GENERATED_DEPS += ./\$(DEPDIR)/$base-wrap.Pcc
+
+EOF
+ case $lang in
+ python) cat <<EOF
+nodist_python_PYTHON += $base.py
+$base.py: $src
+ \$(AM_V_GEN)\$(MAKE) \$(AM_MAKEFLAGS) $dest
+EOF
+ ;;
+ esac
+done
+cat <<EOF
+
+
+# Target \`deps-reset' re-initializes the dependencies generated as a
+# side-effect of running swig.
+.PHONY: deps-reset
+deps-reset:
+ @list='\$(SWIG_GENERATED_DEPS)'; for d in \$\$list; do \\
+ echo '# dummy' > \$\$d; \\
+ done
+
+
+EOF
diff --git a/tiger-compiler/tcsh/python/Makefile.am b/tiger-compiler/tcsh/python/Makefile.am
new file mode 100644
index 0000000..442b582
--- /dev/null
+++ b/tiger-compiler/tcsh/python/Makefile.am
@@ -0,0 +1,60 @@
+## ------------------------ ##
+## Included sub makefiles. ##
+## ------------------------ ##
+
+include $(top_srcdir)/tcsh/run.mk
+
+pyexec_LTLIBRARIES =
+
+# Build a Swig wrapper for each module.
+$(srcdir)/swig.mk: $(top_srcdir)/tcsh/generate-swig-mk
+ $(AM_V_GEN)top_srcdir="$(top_srcdir)" $< python $@.tmp
+ $(AM_V_at)mv -f $@.tmp $@
+ $(AM_V_at)chmod -w $@
+include $(srcdir)/swig.mk
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/lib -I$(top_srcdir)/src -I$(top_builddir)/src \
+ -I$(top_srcdir)/tcsh/src \
+ $(BOOST_CPPFLAGS) \
+ -I$(PYTHONINC)
+AM_SWIGFLAGS = -c++ -python -py3 -I$(top_srcdir)/lib -I$(top_srcdir)/src
+
+# Tiger Compiler module loader.
+python_PYTHON = tc.py
+# Tiger interpreter.
+python_PYTHON += ti.py
+
+
+
+## --------- ##
+## Testing. ##
+## --------- ##
+
+EXTRA_DIST = $(TESTS)
+EXTRA_DIST += $(srcdir)/tests/ipynbtest.py
+
+TESTS_ENVIRONMENT = \
+ top_srcdir="$(top_srcdir)" top_builddir="$(top_builddir)"
+# Ensure `run' is rebuilt before the tests are run.
+$(TESTS): $(srcdir)/run.stamp
+# The dependency is on `run.in' and not `run', since `run' is
+# regenerated at distribution time, and voids the time stamps (which
+# we don't want!).
+EXTRA_DIST += $(srcdir)/run.stamp
+$(srcdir)/run.stamp: $(RUN_IN)
+ $(AM_V_GEN)rm -f $@ $@.tmp
+ $(AM_V_at)touch $@.tmp
+ $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) $(RUN)
+ $(AM_V_at)mv -f $@.tmp $@
+
+TESTS =
+TESTS += tcsh-llvm.test
+
+LOG_COMPILER = $(srcdir)/../run
+TESTS += tests/tc.ipynb tests/ti.ipynb tests/misc.ipynb tests/common.ipynb \
+ tests/parse.ipynb tests/object.ipynb
+TESTS += tests/ast.ipynb
+TESTS += tests/bind.ipynb tests/escapes.ipynb
+TESTS += tests/type.ipynb tests/astclone.ipynb tests/desugar.ipynb
+TESTS += tests/combine.ipynb
diff --git a/tiger-compiler/tcsh/python/tc.py b/tiger-compiler/tcsh/python/tc.py
new file mode 100644
index 0000000..095e79c
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tc.py
@@ -0,0 +1,97 @@
+# Tiger Compiler module loader.
+
+import importlib
+
+from enum import Enum
+from typing import List, Literal
+
+
+class BackendType(Enum):
+ llvm: Literal["llvm"] = "llvm"
+ mips: Literal["mips"] = "mips"
+
+
+def try_import(prefix: str, modules: List[str]):
+ for mod in modules:
+ mod_name = prefix + mod
+ try:
+ globals()[mod] = importlib.import_module(mod_name)
+ except:
+ pass
+
+
+# Query tc for a module.
+def has(module_name: str) -> bool:
+ return module_name in globals()
+
+
+try_import(
+ "tiger_",
+ [
+ "misc",
+ "common",
+ "parse",
+ "object",
+ "ast",
+ "bind",
+ "escapes",
+ "type",
+ "combine",
+ "astclone",
+ "desugar",
+ "overload",
+ "llvmtranslate",
+ ],
+)
+
+# Shortcuts
+Cout = common.cvar.Cout
+Cerr = common.cvar.Cerr
+Ofstream = common.Ofstream
+
+# Load IPython specific support if we can.
+try:
+ # Load only if we are running IPython.
+ from IPython import get_ipython
+ from IPython.core.magic import Magics, magics_class, cell_magic
+ import os
+ import sys
+ import tempfile
+
+ import ti
+
+ @magics_class
+ class TigerMagics(Magics):
+ @cell_magic
+ def tiger(self, line, cell):
+ if not line:
+ print(self.__doc__, file=sys.stderr)
+ return
+ backend = BackendType("mips")
+ line = line.split()
+ if len(line) == 2 and line[1] in [e.value for e in BackendType]:
+ backend = BackendType(line[1])
+ elif len(line) > 1:
+ print(self.__doc__, file=sys.stderr)
+ return
+ with tempfile.NamedTemporaryFile(dir=".", suffix=".tig") as t:
+ t.write(cell.encode("utf-8"))
+ t.flush()
+ executor = ti.TiExecutor(t.name, exit_on_error=False, backend=backend)
+ executor.backend_get()
+ self.shell.user_ns[line[0]] = executor.data
+
+ TigerMagics.__doc__ = (
+ "%%tiger variable_name [backend]\n"
+ "variable_name is the name of the finale variable\n"
+ "backend is optional and must be in [{}]".format(
+ ", ".join((e.value for e in BackendType))
+ )
+ )
+
+ ip = get_ipython()
+ if ip:
+ ip.register_magics(TigerMagics)
+
+except (ImportError, NameError) as e:
+ pass
diff --git a/tiger-compiler/tcsh/python/tcsh-hir.test b/tiger-compiler/tcsh/python/tcsh-hir.test
new file mode 100755
index 0000000..b341457
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tcsh-hir.test
@@ -0,0 +1,8 @@
+#! /bin/sh
+
+set -e
+
+testsdir=$top_srcdir/tests
+run=$top_builddir/tcsh/run
+
+$run $srcdir/ti.py -b hir $testsdir/good/fact.tig
diff --git a/tiger-compiler/tcsh/python/tcsh-llvm.test b/tiger-compiler/tcsh/python/tcsh-llvm.test
new file mode 100755
index 0000000..bb72672
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tcsh-llvm.test
@@ -0,0 +1,8 @@
+#! /bin/sh
+
+set -e
+
+testsdir=$top_srcdir/tests
+run=$top_builddir/tcsh/run
+
+$run $srcdir/ti.py -b llvm $testsdir/good/fact.tig
diff --git a/tiger-compiler/tcsh/python/tests/ast.ipynb b/tiger-compiler/tcsh/python/tests/ast.ipynb
new file mode 100644
index 0000000..51f06ee
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/ast.ipynb
@@ -0,0 +1,394 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "3f7f66b6",
+ "metadata": {},
+ "source": [
+ "# Import Tiger and Ast"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9cb3bce5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "be38c5fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has(\"ast\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "9fe09a20",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import tiger_ast\n",
+ "tiger_ast == tc.ast"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3b3a7285",
+ "metadata": {},
+ "source": [
+ "# Ast Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "2be2f25d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['ArrayExp',\n",
+ " 'ArrayTy',\n",
+ " 'AssignExp',\n",
+ " 'Ast',\n",
+ " 'AstConstVisitor',\n",
+ " 'AstVisitor',\n",
+ " 'BreakExp',\n",
+ " 'CallExp',\n",
+ " 'CallbackVisitor',\n",
+ " 'CallbackVisitor_Argument',\n",
+ " 'CastExp',\n",
+ " 'ChunkInterface',\n",
+ " 'ChunkList',\n",
+ " 'ClassTy',\n",
+ " 'Dec',\n",
+ " 'Exp',\n",
+ " 'Field',\n",
+ " 'FieldInit',\n",
+ " 'FieldVar',\n",
+ " 'ForExp',\n",
+ " 'FunctionChunk',\n",
+ " 'FunctionDec',\n",
+ " 'IfExp',\n",
+ " 'IntExp',\n",
+ " 'LetExp',\n",
+ " 'MethodCallExp',\n",
+ " 'MethodChunk',\n",
+ " 'MethodDec',\n",
+ " 'NameTy',\n",
+ " 'NilExp',\n",
+ " 'ObjectExp',\n",
+ " 'OpExp',\n",
+ " 'RecordExp',\n",
+ " 'RecordTy',\n",
+ " 'SeqExp',\n",
+ " 'SimpleVar',\n",
+ " 'StringExp',\n",
+ " 'SubscriptVar',\n",
+ " 'SwigPyIterator',\n",
+ " 'Ty',\n",
+ " 'TypeChunk',\n",
+ " 'TypeDec',\n",
+ " 'Var',\n",
+ " 'VarChunk',\n",
+ " 'VarDec',\n",
+ " 'WhileExp']"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def ignore(e):\n",
+ " if e.startswith(\"_\") or not e[0] == e[0].upper():\n",
+ " return False\n",
+ " return e not in (\"Escapable\", \"Typable\", \"TypeConstructor\")\n",
+ "list(filter(ignore, dir(tc.ast)))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c2ffa10b",
+ "metadata": {},
+ "source": [
+ "# Tiger Magics and AST"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "eecfc7a6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%tiger executor\n",
+ "let\n",
+ " var b := 5\n",
+ "in\n",
+ " print_int(b)\n",
+ "end"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "2d1e6475",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_ast.ChunkList'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "ast = executor.ast\n",
+ "print(type(ast))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "89fbcdc9",
+ "metadata": {},
+ "source": [
+ "# Parse Ast\n",
+ "We use this to only parse the ast and don't run code after TC2, but use Tiger Magics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "0ee4cd72",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_ast.ChunkList'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "import tempfile\n",
+ "\n",
+ "with tempfile.NamedTemporaryFile() as f:\n",
+ " f.write(b\"let var b := 5 in print_int(b) end\")\n",
+ " f.seek(0)\n",
+ " ast = tc.ti.TiExecutor(f.name).parse()\n",
+ "print(type(ast))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "0276768a",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "primitive print(string : string)\n",
+ "primitive print_err(string : string)\n",
+ "primitive print_int(int : int)\n",
+ "primitive flush()\n",
+ "primitive getchar() : string\n",
+ "primitive ord(string : string) : int\n",
+ "primitive chr(code : int) : string\n",
+ "primitive size(string : string) : int\n",
+ "primitive streq(s1 : string, s2 : string) : int\n",
+ "primitive strcmp(s1 : string, s2 : string) : int\n",
+ "primitive substring(string : string, start : int, length : int) : string\n",
+ "primitive concat(fst : string, snd : string) : string\n",
+ "primitive not(boolean : int) : int\n",
+ "primitive exit(status : int)\n",
+ "function _main() =\n",
+ " (\n",
+ " let\n",
+ " var b := 5\n",
+ " in\n",
+ " print_int(b)\n",
+ " end;\n",
+ " ()\n",
+ " )\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(ast)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "e9856080",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_ast.FunctionChunk'>\n",
+ "<class 'tiger_ast.FunctionDec'>\n",
+ "\n",
+ "function _main() =\n",
+ " (\n",
+ " let\n",
+ " var b := 5\n",
+ " in\n",
+ " print_int(b)\n",
+ " end;\n",
+ " ()\n",
+ " )\n"
+ ]
+ }
+ ],
+ "source": [
+ "main_chunk = ast[1]\n",
+ "print(type(main_chunk))\n",
+ "main_function = main_chunk[0]\n",
+ "print(type(main_function))\n",
+ "print(str(main_function))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "51de4ce3",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_ast.SeqExp'>\n",
+ "<class 'tiger_ast.LetExp'>\n",
+ "let\n",
+ " var b := 5\n",
+ "in\n",
+ " print_int(b)\n",
+ "end\n"
+ ]
+ }
+ ],
+ "source": [
+ "main_body = main_function.body_get()\n",
+ "print(type(main_body))\n",
+ "let = main_body.exps_get()[0]\n",
+ "print(type(let))\n",
+ "print(let)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "1428a492",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_ast.VarChunk'>\n",
+ "<class 'tiger_ast.VarDec'>\n",
+ "\n",
+ "var b := 5\n",
+ "b -> 5\n"
+ ]
+ }
+ ],
+ "source": [
+ "var_chk = let.chunks_get()[0]\n",
+ "print(type(var_chk))\n",
+ "var_b = var_chk[0]\n",
+ "print(type(var_b))\n",
+ "print(var_b)\n",
+ "print(\"{} -> {}\".format(var_b.name_get(), var_b.init_get()))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "d9796c32",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_ast.CallExp'>\n",
+ "print_int(b)\n",
+ "<class 'tiger_ast.SimpleVar'>\n",
+ "b\n"
+ ]
+ }
+ ],
+ "source": [
+ "print_call = let.body_get()\n",
+ "print(type(print_call))\n",
+ "print(print_call)\n",
+ "print_arg = print_call.args_get()[0]\n",
+ "print(type(print_arg))\n",
+ "print(print_arg)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/tests/astclone.ipynb b/tiger-compiler/tcsh/python/tests/astclone.ipynb
new file mode 100644
index 0000000..924260b
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/astclone.ipynb
@@ -0,0 +1,212 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "b8caa27f",
+ "metadata": {},
+ "source": [
+ "# Import Tiger and AstClone"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9cb3bce5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "be38c5fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has(\"astclone\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "9fe09a20",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import tiger_astclone\n",
+ "tiger_astclone == tc.astclone"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3b3a7285",
+ "metadata": {},
+ "source": [
+ "# Ast Clone Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "2be2f25d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['clone']"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "list(filter(lambda e: not e.startswith(\"_\") and not e.startswith(\"tiger\"), dir(tc.astclone)))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "35825bf6",
+ "metadata": {},
+ "source": [
+ "# Clone Ast\n",
+ "We use this to only parse the ast and don't run code after TC4, but use Tiger Magics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "0ee4cd72",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_ast.ChunkList'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "import tempfile\n",
+ "\n",
+ "with tempfile.NamedTemporaryFile() as f:\n",
+ " f.write(b\"let var b := 5 in print_int(b) end\")\n",
+ " f.seek(0)\n",
+ " ast = tc.ti.TiExecutor(f.name).type()\n",
+ "print(type(ast))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "29d68680",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "False\n",
+ "True\n",
+ "<class 'tiger_ast.ChunkList'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "cloned_ast = tc.astclone.clone(ast)\n",
+ "print(ast == cloned_ast)\n",
+ "print(str(ast) == str(cloned_ast))\n",
+ "print(type(cloned_ast))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "5f1cb3e7",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "primitive print(string : string)\n",
+ "primitive print_err(string : string)\n",
+ "primitive print_int(int : int)\n",
+ "primitive flush()\n",
+ "primitive getchar() : string\n",
+ "primitive ord(string : string) : int\n",
+ "primitive chr(code : int) : string\n",
+ "primitive size(string : string) : int\n",
+ "primitive streq(s1 : string, s2 : string) : int\n",
+ "primitive strcmp(s1 : string, s2 : string) : int\n",
+ "primitive substring(string : string, start : int, length : int) : string\n",
+ "primitive concat(fst : string, snd : string) : string\n",
+ "primitive not(boolean : int) : int\n",
+ "primitive exit(status : int)\n",
+ "function _main() =\n",
+ " (\n",
+ " let\n",
+ " var b := 5\n",
+ " in\n",
+ " print_int(b)\n",
+ " end;\n",
+ " ()\n",
+ " )\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(cloned_ast)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/tests/bind.ipynb b/tiger-compiler/tcsh/python/tests/bind.ipynb
new file mode 100644
index 0000000..f2ceafe
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/bind.ipynb
@@ -0,0 +1,283 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "3f7f66b6",
+ "metadata": {},
+ "source": [
+ "# Import Tiger and bind"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9cb3bce5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "be38c5fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has(\"bind\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "9fe09a20",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import tiger_bind\n",
+ "tiger_bind == tc.bind"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3b3a7285",
+ "metadata": {},
+ "source": [
+ "# Bind Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "2be2f25d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['bind', 'rename']"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "list(filter(lambda e: not e.startswith(\"_\") and not e.startswith(\"tiger\"), dir(tc.bind)))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "35825bf6",
+ "metadata": {},
+ "source": [
+ "# Bind Ast\n",
+ "We use this to only parse the ast and don't run code after TC3, but use Tiger Magics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "0ee4cd72",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_ast.ChunkList'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "import tempfile\n",
+ "\n",
+ "with tempfile.NamedTemporaryFile() as f:\n",
+ " f.write(b\"let var b := 5 in print_int(b) end\")\n",
+ " f.seek(0)\n",
+ " ast = tc.ti.TiExecutor(f.name).bind()\n",
+ "print(type(ast))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "703bb878",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# all variables are identical to ast.ipynb \n",
+ "main_chunk = ast[1]\n",
+ "main_function = main_chunk[0]\n",
+ "main_body = main_function.body_get()\n",
+ "let = main_body.exps_get()[0]\n",
+ "var_chk = let.chunks_get()[0]\n",
+ "var_b = var_chk[0]\n",
+ "print_call = let.body_get()\n",
+ "print_arg = print_call.args_get()[0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "991c55bf",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def find_builtin(ast: tc.ast.ChunkList, name: str):\n",
+ " key = tc.misc.symbol(name)\n",
+ " for fns in ast[0]:\n",
+ " if fns.name_get() == key:\n",
+ " return fns\n",
+ " return None"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "a0fc3d00",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_ast.FunctionDec'> \n",
+ "primitive print_int(int : int)\n",
+ "True\n",
+ "True\n",
+ "False\n",
+ "False\n",
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "ref_print_int = print_call.def_get()\n",
+ "print(type(ref_print_int), str(ref_print_int))\n",
+ "\n",
+ "builtin_print_int = find_builtin(ast, \"print_int\")\n",
+ "builtin_print = find_builtin(ast, \"print\")\n",
+ "\n",
+ "print(ref_print_int == builtin_print_int)\n",
+ "print(builtin_print_int == ref_print_int)\n",
+ "print(ref_print_int == builtin_print)\n",
+ "print(builtin_print == ref_print_int)\n",
+ "\n",
+ "print(print_arg.def_get() == var_b)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3c997fb0",
+ "metadata": {},
+ "source": [
+ "# Bind Rename"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "ff0b5358",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tc.bind.rename(ast)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "fcccea94",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# all variables are identical to ast.ipynb \n",
+ "main_chunk = ast[1]\n",
+ "main_function = main_chunk[0]\n",
+ "main_body = main_function.body_get()\n",
+ "let = main_body.exps_get()[0]\n",
+ "var_chk = let.chunks_get()[0]\n",
+ "var_b = var_chk[0]\n",
+ "print_call = let.body_get()\n",
+ "print_arg = print_call.args_get()[0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "1ba1374c",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n",
+ "True\n",
+ "False\n",
+ "False\n",
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "ref_print_int = print_call.def_get()\n",
+ "builtin_print_int = find_builtin(ast, \"print_int\")\n",
+ "builtin_print = find_builtin(ast, \"print\")\n",
+ "\n",
+ "print(ref_print_int == builtin_print_int)\n",
+ "print(builtin_print_int == ref_print_int)\n",
+ "print(ref_print_int == builtin_print)\n",
+ "print(builtin_print == ref_print_int)\n",
+ "\n",
+ "print(print_arg.def_get() == var_b)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/tests/combine.ipynb b/tiger-compiler/tcsh/python/tests/combine.ipynb
new file mode 100644
index 0000000..c97c28a
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/combine.ipynb
@@ -0,0 +1,207 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "b8caa27f",
+ "metadata": {},
+ "source": [
+ "# Import Tiger and combine"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9cb3bce5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "be38c5fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has(\"combine\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "9fe09a20",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import tiger_combine\n",
+ "tiger_combine == tc.combine"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3b3a7285",
+ "metadata": {},
+ "source": [
+ "# Combine Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "2be2f25d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['combine_bind', 'combine_types_check']"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "list(filter(lambda e: not e.startswith(\"_\") and not e.startswith(\"tiger\"), dir(tc.combine)))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "35825bf6",
+ "metadata": {},
+ "source": [
+ "# Combine Ast\n",
+ "We use this to only parse the ast and don't run code after TC4, but use Tiger Magics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "0ee4cd72",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_ast.ChunkList'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "import tempfile\n",
+ "\n",
+ "with tempfile.NamedTemporaryFile() as f:\n",
+ " f.write(b\"let var b := 5 in print_int(b) end\")\n",
+ " f.seek(0)\n",
+ " ast = tc.ti.TiExecutor(f.name).type()\n",
+ "print(type(ast))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "29d68680",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tuple'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "pair = tc.combine.combine_bind(ast, True)\n",
+ "print(type(pair))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "46abfec6",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<Swig Object of type 'overload::overfun_bindings_type *' at 0x7fb2c1d50810> <class 'tiger_misc.error'>\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "overfun_bindings_get, error = pair\n",
+ "print(repr(overfun_bindings_get), type(error))\n",
+ "print(error)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "e8f0ee43",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "error = tc.combine.combine_types_check(ast, overfun_bindings_get, True)\n",
+ "print(error)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/tests/common.ipynb b/tiger-compiler/tcsh/python/tests/common.ipynb
new file mode 100644
index 0000000..a2ee8ac
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/common.ipynb
@@ -0,0 +1,154 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "3f7f66b6",
+ "metadata": {},
+ "source": [
+ "# Import Tiger and Common"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9cb3bce5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "be38c5fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has(\"common\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "9fe09a20",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import tiger_common\n",
+ "tiger_common == tc.common"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3b3a7285",
+ "metadata": {},
+ "source": [
+ "# Common Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "2be2f25d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['Ofstream', 'cvar', 'get_cerr', 'get_cout']"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "list(filter(lambda e: not e.startswith(\"_\"), dir(tc.common)))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c2ffa10b",
+ "metadata": {},
+ "source": [
+ "# Common Ofstrem"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "0ee4cd72",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<Swig Object of type 'std::ostream *' at 0x7f812c0f0750>\n"
+ ]
+ }
+ ],
+ "source": [
+ "import os\n",
+ "import tempfile\n",
+ "\n",
+ "# Create file\n",
+ "f = tempfile.NamedTemporaryFile(delete=False)\n",
+ "f.write(b\"let in end\")\n",
+ "f.close()\n",
+ "\n",
+ "# Open a C++ ostream\n",
+ "ostream = tc.common.Ofstream(f.name)\n",
+ "print(ostream.to())\n",
+ "\n",
+ "# Delete file\n",
+ "os.unlink(f.name)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.1"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/tests/desugar.ipynb b/tiger-compiler/tcsh/python/tests/desugar.ipynb
new file mode 100644
index 0000000..3e6417f
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/desugar.ipynb
@@ -0,0 +1,343 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "b8caa27f",
+ "metadata": {},
+ "source": [
+ "# Import Tiger and Desugar"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9cb3bce5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "be38c5fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has(\"desugar\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "9fe09a20",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import tiger_desugar\n",
+ "tiger_desugar == tc.desugar"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3b3a7285",
+ "metadata": {},
+ "source": [
+ "# Desugar Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "2be2f25d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['desugar', 'raw_desugar']"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "list(filter(lambda e: not e.startswith(\"_\") and not e.startswith(\"tiger\"), dir(tc.desugar)))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "35825bf6",
+ "metadata": {},
+ "source": [
+ "# Desugar Ast\n",
+ "We use this to only parse the ast and don't run code after TC4, but use Tiger Magics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "0ee4cd72",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_ast.ChunkList'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "import tempfile\n",
+ "\n",
+ "with tempfile.NamedTemporaryFile() as f:\n",
+ " f.write(b\"for i := 1 to 10 do (i; ())\")\n",
+ " f.seek(0)\n",
+ " ast = tc.ti.TiExecutor(f.name).type()\n",
+ "print(type(ast))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "d0e05897",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "primitive print(string : string)\n",
+ "primitive print_err(string : string)\n",
+ "primitive print_int(int : int)\n",
+ "primitive flush()\n",
+ "primitive getchar() : string\n",
+ "primitive ord(string : string) : int\n",
+ "primitive chr(code : int) : string\n",
+ "primitive size(string : string) : int\n",
+ "primitive streq(s1 : string, s2 : string) : int\n",
+ "primitive strcmp(s1 : string, s2 : string) : int\n",
+ "primitive substring(string : string, start : int, length : int) : string\n",
+ "primitive concat(fst : string, snd : string) : string\n",
+ "primitive not(boolean : int) : int\n",
+ "primitive exit(status : int)\n",
+ "function _main() =\n",
+ " (\n",
+ " (for i := 1 to 10 do\n",
+ " (\n",
+ " i;\n",
+ " ()\n",
+ " ));\n",
+ " ()\n",
+ " )\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(ast)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "29d68680",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "<function tiger_desugar.raw_desugar(tree: 'Ast', desugar_for: 'bool' = False, desugar_string_cmp: 'bool' = False) -> 'ast::Ast *'>"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.desugar.raw_desugar"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "04a11b99",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "primitive print(string : string)\n",
+ "primitive print_err(string : string)\n",
+ "primitive print_int(int : int)\n",
+ "primitive flush()\n",
+ "primitive getchar() : string\n",
+ "primitive ord(string : string) : int\n",
+ "primitive chr(code : int) : string\n",
+ "primitive size(string : string) : int\n",
+ "primitive streq(s1 : string, s2 : string) : int\n",
+ "primitive strcmp(s1 : string, s2 : string) : int\n",
+ "primitive substring(string : string, start : int, length : int) : string\n",
+ "primitive concat(fst : string, snd : string) : string\n",
+ "primitive not(boolean : int) : int\n",
+ "primitive exit(status : int)\n",
+ "function _main() =\n",
+ " (\n",
+ " let\n",
+ " var _lo := 1\n",
+ " var _hi := 10\n",
+ " var i := _lo\n",
+ " in\n",
+ " (if (_lo <= _hi)\n",
+ " then (while 1 do\n",
+ " (\n",
+ " (\n",
+ " i;\n",
+ " ()\n",
+ " );\n",
+ " (if (i = _hi)\n",
+ " then break\n",
+ " else ());\n",
+ " (i := (i + 1))\n",
+ " ))\n",
+ " else ())\n",
+ " end;\n",
+ " ()\n",
+ " )\n"
+ ]
+ }
+ ],
+ "source": [
+ "ast_raw = tc.desugar.raw_desugar(ast, True, True)\n",
+ "print(ast_raw)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "da86985d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "<function tiger_desugar.desugar(tree: 'Ast', desugar_for: 'bool' = False, desugar_string_cmp: 'bool' = False) -> 'ast::Ast *'>"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.desugar.desugar"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "86f1bcc7",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "primitive print(string : string)\n",
+ "primitive print_err(string : string)\n",
+ "primitive print_int(int : int)\n",
+ "primitive flush()\n",
+ "primitive getchar() : string\n",
+ "primitive ord(string : string) : int\n",
+ "primitive chr(code : int) : string\n",
+ "primitive size(string : string) : int\n",
+ "primitive streq(s1 : string, s2 : string) : int\n",
+ "primitive strcmp(s1 : string, s2 : string) : int\n",
+ "primitive substring(string : string, start : int, length : int) : string\n",
+ "primitive concat(fst : string, snd : string) : string\n",
+ "primitive not(boolean : int) : int\n",
+ "primitive exit(status : int)\n",
+ "function _main() =\n",
+ " (\n",
+ " let\n",
+ " var _lo := 1\n",
+ " var _hi := 10\n",
+ " var i := _lo\n",
+ " in\n",
+ " (if (_lo <= _hi)\n",
+ " then (while 1 do\n",
+ " (\n",
+ " (\n",
+ " i;\n",
+ " ()\n",
+ " );\n",
+ " (if (i = _hi)\n",
+ " then break\n",
+ " else ());\n",
+ " (i := (i + 1))\n",
+ " ))\n",
+ " else ())\n",
+ " end;\n",
+ " ()\n",
+ " )\n"
+ ]
+ }
+ ],
+ "source": [
+ "ast = tc.desugar.desugar(ast, True, True)\n",
+ "print(ast)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/tests/escapes.ipynb b/tiger-compiler/tcsh/python/tests/escapes.ipynb
new file mode 100644
index 0000000..ed914fb
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/escapes.ipynb
@@ -0,0 +1,194 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "3f7f66b6",
+ "metadata": {},
+ "source": [
+ "# Import Tiger and escapes"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9cb3bce5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "be38c5fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has(\"escapes\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "9fe09a20",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import tiger_escapes\n",
+ "tiger_escapes == tc.escapes"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3b3a7285",
+ "metadata": {},
+ "source": [
+ "# Escapes Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "2be2f25d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "<function tiger_escapes.escapes_compute(tree: 'ast::Ast &') -> 'void'>"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.escapes.escapes_compute"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "35825bf6",
+ "metadata": {},
+ "source": [
+ "# Escape\n",
+ "We use this to only parse and bind the ast and don't run code after TC3, but use Tiger Magics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "0ee4cd72",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_ast.ChunkList'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "import tempfile\n",
+ "\n",
+ "with tempfile.NamedTemporaryFile() as f:\n",
+ " f.write(b\"let var b := 5 in print_int(b) end\")\n",
+ " f.seek(0)\n",
+ " ast = tc.ti.TiExecutor(f.name).bind()\n",
+ "print(type(ast))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "371349e8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tc.escapes.escapes_compute(ast)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "703bb878",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# all variables are identical to ast.ipynb \n",
+ "main_chunk = ast[1]\n",
+ "main_function = main_chunk[0]\n",
+ "main_body = main_function.body_get()\n",
+ "let = main_body.exps_get()[0]\n",
+ "var_chk = let.chunks_get()[0]\n",
+ "var_b = var_chk[0]\n",
+ "print_call = let.body_get()\n",
+ "print_arg = print_call.args_get()[0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "c7ed8db8",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "False\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(var_b.escape_get())"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/tests/ipynbtest.py b/tiger-compiler/tcsh/python/tests/ipynbtest.py
new file mode 100755
index 0000000..1b7798a
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/ipynbtest.py
@@ -0,0 +1,279 @@
+#!/usr/bin/env python3
+"""
+simple example script for running and testing notebooks.
+
+Usage: `ipnbdoctest.py foo.ipynb [bar.ipynb [...]]`
+
+Each cell is submitted to the kernel, and the outputs are compared
+with those stored in the notebook.
+"""
+
+# Derived from https://gist.github.com/minrk/2620735
+# Derived from https://gitlab.lrde.epita.fr/spot/spot/-/raw/next/tests/python/ipnbdoctest.py
+
+from __future__ import print_function
+
+import os
+import sys
+import time
+import base64
+import re
+import pprint
+import random
+from difflib import unified_diff as diff
+
+from collections import defaultdict
+try:
+ from queue import Empty
+except ImportError:
+ print('Python 3.x is needed to run this script.')
+ sys.exit(77)
+
+import importlib.util
+try:
+ importlib.util.find_spec('IPython')
+except:
+ print('IPython is needed to run this script.')
+ sys.exit(77)
+
+try:
+ from jupyter_client import KernelManager
+except ImportError:
+ try:
+ from IPython.kernel import KernelManager
+ except ImportError:
+ try:
+ from IPython.zmq.blockingkernelmanager \
+ import BlockingKernelManager as KernelManager
+ except:
+ print('IPython is needed to run this script.')
+ sys.exit(77)
+
+# Until Debian Stable ships IPython >3.0, we stick to the v3 format.
+try:
+ from nbformat import v4 as nbformat
+except ImportError:
+ from IPython.nbformat import v4 as nbformat
+
+
+def canonicalize(s):
+ """sanitize a string for comparison.
+
+ fix universal newlines, strip trailing newlines, and normalize likely
+ random values (memory addresses and UUIDs)
+ """
+ if not isinstance(s, str):
+ return s
+
+ # normalize newline:
+ s = s.replace('\r\n', '\n')
+
+ # ignore trailing newlines (but not space)
+ s = s.rstrip('\n')
+
+ # remove hex addresses:
+ s = re.sub(r'at 0x[a-f0-9]+', 'at 0xadd7e5500000', s)
+
+ # remove backend lists in documentations/errors:
+ s = re.sub(r'\[((lir|hir|llvm|mips|ia32), ?)*(lir|hir|llvm|mips|ia32)\]',
+ '[]', s)
+
+ return s
+
+
+def canonical_dict(data):
+ """Neutralize gratuitous differences in a Jupyter dictionary."""
+
+ if 'text' in data:
+ data['text'] = canonicalize(data['text'])
+
+ if 'data' in data:
+ d = data['data']
+ if "text/html" in d and "text/plain" in d:
+ del d["text/plain"]
+ for k in d:
+ d[k] = canonicalize(d[k])
+
+ if ('ename' in data and
+ data['ename'] == 'SystemExit' and data['evalue'] == '77'):
+ # sys.exit(77) is used to Skip the test.
+ sys.exit(77)
+
+ if 'ename' in data and data['ename'] == 'CalledProcessError':
+ # CalledProcessError message has a final dot in Python 3.6
+ data['evalue'] = re.sub(r"(' returned non-zero exit status \d+)\.",
+ r'\1', data['evalue'])
+
+ for e in ('transient', 'execution_count', 'traceback'):
+ if e in data:
+ del data[e]
+ return data
+
+
+def compare_outputs(ref, test):
+ """Check that two lists of outputs are equivalent and report the result."""
+
+ cref = list(map(canonical_dict, ref))
+ ctest = list(map(canonical_dict, test))
+
+ ok = True
+
+ if len(cref) != len(ctest):
+ print("output length mismatch (expected {}, got {})"
+ .format(len(cref), len(ctest)))
+ ok = False
+ # There can be several outputs. For instance wnen the cell both
+ # prints a result (goes to "stdout") and displays an automaton
+ # (goes to "data").
+ exp = pprint.pformat(cref, width=132)
+ eff = pprint.pformat(ctest, width=132)
+ if exp[:-1] != '\n':
+ exp += '\n'
+ if eff[:-1] != '\n':
+ eff += '\n'
+ if exp == eff:
+ return ok
+ else:
+ print(''.join(diff(exp.splitlines(1), eff.splitlines(1),
+ fromfile='expected', tofile='effective')))
+ return False
+
+
+def _wait_for_ready_backport(kc):
+ """Backport BlockingKernelClient.wait_for_ready from IPython 3"""
+ # Wait for kernel info reply on shell channel
+ kc.kernel_info()
+ while True:
+ msg = kc.get_shell_msg(block=True, timeout=30)
+ if msg['msg_type'] == 'kernel_info_reply':
+ break
+ # Flush IOPub channel
+ while True:
+ try:
+ msg = kc.get_iopub_msg(block=True, timeout=1)
+ except Empty:
+ break
+
+
+def run_cell(kc, cell):
+ kc.execute(cell.source)
+ outs = []
+
+ while True:
+ try:
+ msg = kc.get_iopub_msg(timeout=1)
+ except Empty:
+ if not kc.is_alive():
+ raise RuntimeError("Kernel died")
+ continue
+
+ msg_type = msg['msg_type']
+ content = msg['content']
+
+ if msg_type == 'status' and content['execution_state'] == 'idle':
+ break
+ if msg_type in ('status', 'pyin', 'execute_input',
+ 'comm_open', 'comm_msg'):
+ continue
+ if msg_type == 'stream':
+ if 'Widget' in content['text']:
+ continue
+ # If the last stream had the same name, then outputs are
+ # appended.
+ if outs:
+ last = outs[-1]
+ if last['output_type'] == 'stream' and \
+ last['name'] == content['name']:
+ last['text'] += content['text']
+ continue
+ elif msg_type == 'clear_output':
+ outs = []
+ continue
+
+ content['output_type'] = msg_type
+ outs.append(content)
+ # Flush shell channel
+ while True:
+ try:
+ kc.get_shell_msg(timeout=0.1)
+ except Empty:
+ if not kc.is_alive():
+ raise RuntimeError("Kernel died")
+ break
+ return outs
+
+
+def test_notebook(ipynb):
+ with open(ipynb, encoding='utf-8') as f:
+ nb = nbformat.reads_json(f.read())
+ km = KernelManager()
+ # Do not save the history to disk, as it can yield spurious lock errors.
+ # See https://github.com/ipython/ipython/issues/2845
+ km.start_kernel(extra_arguments=['--HistoryManager.hist_file=:memory:',
+ '--quiet'])
+
+ kc = km.client()
+ kc.start_channels()
+
+ try:
+ kc.wait_for_ready(timeout=30)
+ except AttributeError:
+ _wait_for_ready_backport(kc)
+
+ successes = 0
+ failures = 0
+ errors = 0
+ for i, cell in enumerate(nb.cells):
+ if cell.cell_type == 'markdown' and cell.source.startswith("#"):
+ title = re.sub(r'^#+ ?', '', cell.source.splitlines()[0])
+ if cell.cell_type != 'code' or cell.source.startswith('#DONTCHECK'):
+ continue
+ try:
+ outs = run_cell(kc, cell)
+ except Exception as e:
+ print("failed to run cell:", repr(e))
+ print(cell.input)
+ errors += 1
+ continue
+
+ failed = not compare_outputs(cell.outputs, outs)
+ print("{: <30} {: >2}: ".format(title, i), end="")
+ if failed:
+ print("FAIL")
+ failures += 1
+ else:
+ print("OK")
+ successes += 1
+
+ print("tested notebook %s" % ipynb)
+ print(" %3i cells successfully replicated" % successes)
+ if failures:
+ print(" %3i cells mismatched output" % failures)
+ if errors:
+ print(" %3i cells failed to complete" % errors)
+ kc.stop_channels()
+ km.shutdown_kernel()
+ del km
+ if failures or errors:
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ for ipynb in sys.argv[1:]:
+ tries=3
+ while tries:
+ print("testing %s" % ipynb)
+ try:
+ test_notebook(ipynb)
+ break
+ except RuntimeError as e:
+ # If the Kernel dies, try again. It seems we have spurious
+ # failures when multiple instances of jupyter start in parallel.
+ if 'Kernel died' in str(e):
+ tries -= 1
+ if tries:
+ s = random.randint(1, 5)
+ print("trying again in", s, "seconds...")
+ time.sleep(s)
+ else:
+ raise e
diff --git a/tiger-compiler/tcsh/python/tests/llvmtranslate.ipynb b/tiger-compiler/tcsh/python/tests/llvmtranslate.ipynb
new file mode 100644
index 0000000..1e84c8f
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/llvmtranslate.ipynb
@@ -0,0 +1,220 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "b8caa27f",
+ "metadata": {},
+ "source": [
+ "# Import Tiger and LLVMTranslate"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9cb3bce5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "be38c5fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has(\"llvmtranslate\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "9fe09a20",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import tiger_llvmtranslate\n",
+ "tiger_llvmtranslate == tc.llvmtranslate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3b3a7285",
+ "metadata": {},
+ "source": [
+ "# LLVMTranslate Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "2be2f25d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['translate']"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "list(filter(lambda e: not e.startswith(\"_\") and not e.startswith(\"tiger\"), dir(tc.llvmtranslate)))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "39d05040",
+ "metadata": {},
+ "source": [
+ "# Tiger Magics and LLVMTranslate"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "b210db83",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%tiger executor llvm\n",
+ "let\n",
+ " var b := 5\n",
+ "in\n",
+ " print_int(b)\n",
+ "end"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "cd732dc4",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "; ModuleID = 'LRDE Tiger Compiler'\n",
+ "source_filename = \"LRDE Tiger Compiler\"\n"
+ ]
+ }
+ ],
+ "source": [
+ "llvm = executor.llvm\n",
+ "print(*llvm.splitlines()[0:2], sep=\"\\n\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "defafcde",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "5\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(executor.result)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "35825bf6",
+ "metadata": {},
+ "source": [
+ "# LLVMTranslate example\n",
+ "In Tiger Magics it run translate and then run clang (see tcsh/python/ti.py)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "0ee4cd72",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tempfile\n",
+ "\n",
+ "with tempfile.NamedTemporaryFile() as f:\n",
+ " f.write(b\"let var b := 5 in print_int(b) end\")\n",
+ " f.seek(0)\n",
+ " ast = tc.ti.TiExecutor(f.name).desugar()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "29d68680",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "; ModuleID = 'LRDE Tiger Compiler'\n",
+ "source_filename = \"LRDE Tiger Compiler\"\n"
+ ]
+ }
+ ],
+ "source": [
+ "llvm = tc.llvmtranslate.translate(ast)\n",
+ "print(*llvm.splitlines()[0:2], sep=\"\\n\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.1"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/tests/misc.ipynb b/tiger-compiler/tcsh/python/tests/misc.ipynb
new file mode 100644
index 0000000..8fb12a2
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/misc.ipynb
@@ -0,0 +1,358 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "3f7f66b6",
+ "metadata": {},
+ "source": [
+ "# Import Tiger and Misc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9cb3bce5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "be38c5fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has(\"misc\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "9fe09a20",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import tiger_misc\n",
+ "tiger_misc == tc.misc"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3b3a7285",
+ "metadata": {},
+ "source": [
+ "# Misc Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "2be2f25d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['error', 'file_library', 'symbol', 'symbol_fresh', 'timer']"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "list(filter(lambda e: not e.startswith(\"_\"), dir(tc.misc)))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c2ffa10b",
+ "metadata": {},
+ "source": [
+ "# Misc error"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "0ee4cd72",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0 SUCCESS\n",
+ "1 FAILURE\n",
+ "2 SCAN\n",
+ "3 PARSE\n",
+ "4 BIND\n",
+ "5 TYPE\n"
+ ]
+ }
+ ],
+ "source": [
+ "errors_messages = tc.misc.error.error_type_message()\n",
+ "for i in range(6):\n",
+ " print(i, errors_messages[i])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "bf7ee0ae",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0\n",
+ "1\n",
+ "2\n",
+ "3\n",
+ "4\n",
+ "5\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(tc.misc.error.error_type_success)\n",
+ "print(tc.misc.error.error_type_failure)\n",
+ "print(tc.misc.error.error_type_scan)\n",
+ "print(tc.misc.error.error_type_parse)\n",
+ "print(tc.misc.error.error_type_bind)\n",
+ "print(tc.misc.error.error_type_type)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "aa79fa38",
+ "metadata": {},
+ "source": [
+ "# Misc symbol"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "082ad376",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "hello = tc.misc.symbol(\"Hello\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "88a477ec",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_misc.symbol'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(type(hello))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "315f56d1",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'Hello'"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "str(hello)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "9614378d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "hello == \"Hello\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "14621e65",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "hello == tc.misc.symbol(\"Hello\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "dccec330",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "hello != tc.misc.symbol(\"world\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a8236c03",
+ "metadata": {},
+ "source": [
+ "# Misc timer"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "2f35c4c7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "my_timer = tc.misc.timer()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "70f7b6e0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "my_timer.start()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "8510ce33",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "my_timer.push('test')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "8eeb355b",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Execution times (seconds)\n",
+ "\n",
+ "Cumulated times (seconds)\n",
+ " test : -0.79 ( -79%) -0.13 ( -13%) -1.43526e+07 (-1.44e+09%) \n",
+ "\n",
+ " TOTAL (seconds) : 0 user, 0 system, 0 wall\n"
+ ]
+ }
+ ],
+ "source": [
+ "#DONTCHECK\n",
+ "my_timer.dump()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/tests/object.ipynb b/tiger-compiler/tcsh/python/tests/object.ipynb
new file mode 100644
index 0000000..69563e5
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/object.ipynb
@@ -0,0 +1,182 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "3f7f66b6",
+ "metadata": {},
+ "source": [
+ "# Import Tiger and Object"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9cb3bce5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "be38c5fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has(\"object\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "9fe09a20",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import tiger_object\n",
+ "tiger_object == tc.object"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c2ffa10b",
+ "metadata": {},
+ "source": [
+ "# Object functions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "37f1bbb8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from typing import Callable\n",
+ "def function_annotations(fn: Callable) -> str:\n",
+ " ann = fn.__annotations__\n",
+ " ret = ann.get(\"return\")\n",
+ " args = \", \".join((\"{}: '{}'\".format(a, ann[a]) for a in ann if a != \"return\"))\n",
+ " name = fn.__module__ + '.' + fn.__qualname__\n",
+ " return \"<function {name}({args}) -> '{ret}'>\".format(name=name, args=args, ret=ret)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "0ee4cd72",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<function tiger_object.bind(tree: 'Ast') -> 'misc::error'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "if tc.has(\"bind\"): # Wait TC3\n",
+ " print(function_annotations(tc.object.bind))\n",
+ "else:\n",
+ " def bind(tree: 'ast::Ast &') -> 'misc::error':\n",
+ " pass\n",
+ " bind.__module__ = \"tiger_object\"\n",
+ " print(function_annotations(bind))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "bfba3cc3",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<function tiger_object.types_check(tree: 'Ast') -> 'misc::error'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "if tc.has(\"type\"): # Wait TC4\n",
+ " print(function_annotations(tc.object.types_check))\n",
+ "else:\n",
+ " def types_check(tree: 'ast::Ast &') -> 'misc::error':\n",
+ " pass\n",
+ " types_check.__module__ = \"tiger_object\"\n",
+ " print(function_annotations(types_check))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "bd48ce57",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<function tiger_object.rename(tree: 'Ast') -> 'object::class_names_type *'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "if tc.has(\"desugar\"): # Wait TC4\n",
+ " print(function_annotations(tc.object.rename))\n",
+ "else:\n",
+ " def rename(tree: 'ast::Ast &') -> 'object::class_names_type *':\n",
+ " pass\n",
+ " rename.__module__ = \"tiger_object\"\n",
+ " print(function_annotations(rename))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/tests/overload.ipynb b/tiger-compiler/tcsh/python/tests/overload.ipynb
new file mode 100644
index 0000000..170ab9c
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/overload.ipynb
@@ -0,0 +1,207 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "b8caa27f",
+ "metadata": {},
+ "source": [
+ "# Import Tiger and Overload"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9cb3bce5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "be38c5fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has(\"overload\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "9fe09a20",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import tiger_overload\n",
+ "tiger_overload == tc.overload"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3b3a7285",
+ "metadata": {},
+ "source": [
+ "# Overload Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "2be2f25d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['bind', 'types_check']"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "list(filter(lambda e: not e.startswith(\"_\") and not e.startswith(\"tiger\"), dir(tc.overload)))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "35825bf6",
+ "metadata": {},
+ "source": [
+ "# Overload Ast\n",
+ "We use this to only parse the ast and don't run code after TC4, but use Tiger Magics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "0ee4cd72",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_ast.ChunkList'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "import tempfile\n",
+ "\n",
+ "with tempfile.NamedTemporaryFile() as f:\n",
+ " f.write(b\"let var b := 5 in print_int(b) end\")\n",
+ " f.seek(0)\n",
+ " ast = tc.ti.TiExecutor(f.name).type()\n",
+ "print(type(ast))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "29d68680",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tuple'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "pair = tc.overload.bind(ast)\n",
+ "print(type(pair))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "46abfec6",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'SwigPyObject'> <class 'tiger_misc.error'>\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "overfun_bindings_get, error = pair\n",
+ "print(type(overfun_bindings_get), type(error))\n",
+ "print(error)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "e8f0ee43",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "error = tc.overload.types_check(ast, overfun_bindings_get)\n",
+ "print(error)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/tests/parse.ipynb b/tiger-compiler/tcsh/python/tests/parse.ipynb
new file mode 100644
index 0000000..e899bc4
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/parse.ipynb
@@ -0,0 +1,150 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "3f7f66b6",
+ "metadata": {},
+ "source": [
+ "# Import Tiger and Parse"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9cb3bce5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "be38c5fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has(\"parse\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "9fe09a20",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import tiger_parse\n",
+ "tiger_parse == tc.parse"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3b3a7285",
+ "metadata": {},
+ "source": [
+ "# Parse Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "2be2f25d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['MetavarChunkList',\n",
+ " 'MetavarMap',\n",
+ " 'MetavarNameTy',\n",
+ " 'MetavarVar',\n",
+ " 'TigerParser',\n",
+ " 'YY_NULLPTR',\n",
+ " 'location',\n",
+ " 'parse',\n",
+ " 'parse_chunks',\n",
+ " 'parse_unit',\n",
+ " 'position']"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "list(filter(lambda e: not e.startswith(\"_\") and not e.endswith(\"Tweast\") and not e.startswith(\"tiger\"), dir(tc.parse)))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c2ffa10b",
+ "metadata": {},
+ "source": [
+ "# Parse parse"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "0ee4cd72",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tempfile\n",
+ "\n",
+ "if tc.has(\"misc\"):\n",
+ " with tempfile.NamedTemporaryFile() as f:\n",
+ " f.write(b\"let in end\")\n",
+ " f.seek(0)\n",
+ " ast = tc.parse.parse(\"builtin\", f.name, tc.misc.file_library())\n",
+ " # do not use ast before tc2"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.1"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/tests/tc.ipynb b/tiger-compiler/tcsh/python/tests/tc.ipynb
new file mode 100644
index 0000000..58cfa3f
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/tc.ipynb
@@ -0,0 +1,252 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "cefa08c9",
+ "metadata": {},
+ "source": [
+ "# Import tc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "989c2dff",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tc"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "37e62513",
+ "metadata": {},
+ "source": [
+ "# Tiger Magics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "38583076",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "%%tiger variable_name [backend]\n",
+ "variable_name is the name of the finale variable\n",
+ "backend is optional and must be in [llvm, hir, lir, mips, ia32]\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(tc.TigerMagics.__doc__)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "0e93343f",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "UsageError: %%tiger is a cell magic, but the cell body is empty.\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%tiger"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "d2d30487",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "UsageError: %%tiger is a cell magic, but the cell body is empty.\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%tiger execution"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "c5ce6c25",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "%%tiger variable_name [backend]\n",
+ "variable_name is the name of the finale variable\n",
+ "backend is optional and must be in [llvm, hir, lir, mips, ia32]\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%tiger\n",
+ "let in end"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "05856612",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%tiger execution\n",
+ "let in end"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "326e35de",
+ "metadata": {},
+ "source": [
+ "# tc Variables and Functions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "97e995a8",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "<Swig Object of type 'std::ostream *' at 0x7fd40876a430>"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.Cout"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "ad4ebd05",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "<Swig Object of type 'std::ostream *' at 0x7fd40876a610>"
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.Cerr"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "6790e6ee",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "<enum 'BackendType'>"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.BackendType"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "34ebeb8c",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "<function tc.has(module_name: str) -> bool>"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "fc67329d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has(\"common\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.1"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/tests/ti.ipynb b/tiger-compiler/tcsh/python/tests/ti.ipynb
new file mode 100644
index 0000000..dfa5399
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/ti.ipynb
@@ -0,0 +1,186 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "7415e928",
+ "metadata": {},
+ "source": [
+ "The ti module is used to easily perform all the steps in the tc module and in the command line."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "cefa08c9",
+ "metadata": {},
+ "source": [
+ "# Import ti"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "989c2dff",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import ti"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "37e62513",
+ "metadata": {},
+ "source": [
+ "# ti Process File"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "d293f4f2",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "<function ti.process_file(filename: 'str', backend: 'tc.BackendType' = <BackendType.mips: 'mips'>, **kwargs) -> 'None'>"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "ti.process_file"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "fefa7505",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Hello World!\n"
+ ]
+ }
+ ],
+ "source": [
+ "import tempfile\n",
+ "\n",
+ "with tempfile.NamedTemporaryFile() as f:\n",
+ " f.write(b'let in print(\"Hello World!\\n\") end')\n",
+ " f.seek(0)\n",
+ " \n",
+ " if not ti.tc.has(\"llvmtranslate\"): # Simulate result before TCL\n",
+ " print(\"Hello World!\")\n",
+ " else:\n",
+ " ti.process_file(f.name, 'llvm')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3a6c23a4",
+ "metadata": {},
+ "source": [
+ "# ti TiExecutor"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "bd177f77",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "<function ti.TiExecutor.__init__(self, filename: 'str', backend: 'tc.BackendType' = <BackendType.mips: 'mips'>, exit_on_error: 'bool' = True, get_result: 'bool' = False, rename: 'bool' = True, desugar: 'bool' = True, object_enabled: 'bool' = True, debug: 'bool' = False)>"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "ti.TiExecutor.__init__"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "64c47c73",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "ast: None\n",
+ "error: None\n",
+ "fragments: None\n",
+ "lir_fragments: None\n",
+ "llvm: None\n",
+ "result: None\n",
+ "target: None\n",
+ "tempmap: None\n",
+ "\n",
+ "Hello World!\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "import tempfile\n",
+ "\n",
+ "with tempfile.NamedTemporaryFile() as f:\n",
+ " # Create File\n",
+ " f.write(b'let in print(\"Hello World!\\n\") end')\n",
+ " f.seek(0)\n",
+ " \n",
+ " # Create Executor\n",
+ " \n",
+ " if ti.tc.has(\"llvmtranslate\"):\n",
+ " e = ti.TiExecutor(f.name, backend=\"llvm\", rename=False, desugar=False, exit_on_error=False, get_result=True)\n",
+ " else:\n",
+ " e = ti.TiExecutor(f.name, rename=False, desugar=False, exit_on_error=False, get_result=True)\n",
+ " \n",
+ " # All data are empty before execution\n",
+ " print(e.data)\n",
+ " e.backend_exec()\n",
+ " \n",
+ " if not ti.tc.has(\"llvmtranslate\"): # Simulate result before TCL\n",
+ " e.data.result = \"Hello World!\\n\"\n",
+ " \n",
+ " # Result is stored when get_result=True\n",
+ " print(e.data.result)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/tests/type.ipynb b/tiger-compiler/tcsh/python/tests/type.ipynb
new file mode 100644
index 0000000..5daab36
--- /dev/null
+++ b/tiger-compiler/tcsh/python/tests/type.ipynb
@@ -0,0 +1,228 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "81a0b85e",
+ "metadata": {},
+ "source": [
+ "# Import Tiger and type"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9cb3bce5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "be38c5fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tc.has(\"type\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "9fe09a20",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import tiger_type\n",
+ "tiger_type == tc.type"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3b3a7285",
+ "metadata": {},
+ "source": [
+ "# Type Library"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "2be2f25d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['Array',\n",
+ " 'Class',\n",
+ " 'Class_object_instance',\n",
+ " 'Field',\n",
+ " 'Function',\n",
+ " 'Int',\n",
+ " 'Method',\n",
+ " 'Named',\n",
+ " 'Nil',\n",
+ " 'Record',\n",
+ " 'String',\n",
+ " 'Type',\n",
+ " 'Void',\n",
+ " 'cvar',\n",
+ " 'hide_actual_types',\n",
+ " 'types_check']"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "list(filter(lambda e: not e.startswith(\"_\") and not e.startswith(\"tiger\"), dir(tc.type)))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "35825bf6",
+ "metadata": {},
+ "source": [
+ "# Type Ast\n",
+ "We use this to only parse the ast and don't run code after TC4, but use Tiger Magics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "0ee4cd72",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_ast.ChunkList'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "import tempfile\n",
+ "\n",
+ "with tempfile.NamedTemporaryFile() as f:\n",
+ " f.write(b\"let var b := 5 in print_int(b) end\")\n",
+ " f.seek(0)\n",
+ " ast = tc.ti.TiExecutor(f.name).type()\n",
+ "print(type(ast))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "703bb878",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# all variables are identical to ast.ipynb \n",
+ "main_chunk = ast[1]\n",
+ "main_function = main_chunk[0]\n",
+ "main_body = main_function.body_get()\n",
+ "let = main_body.exps_get()[0]\n",
+ "var_chk = let.chunks_get()[0]\n",
+ "var_b = var_chk[0]\n",
+ "print_call = let.body_get()\n",
+ "print_arg = print_call.args_get()[0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "40ad7839",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'tiger_type.Int'>\n",
+ "int\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(type(var_b.type_get()))\n",
+ "print(str(var_b.type_get()))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "be462b0c",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "main_function: \n",
+ "{\n",
+ "} -> void\n",
+ "main_body: void\n",
+ "let: void\n",
+ "var_b: int\n",
+ "print_call: void\n",
+ "print_arg: int\n"
+ ]
+ }
+ ],
+ "source": [
+ "for e in (\"main_function\", \"main_body\", \"let\", \"var_b\", \"print_call\", \"print_arg\"):\n",
+ " if hasattr(globals()[e], \"type_get\"):\n",
+ " print(e, globals()[e].type_get(), sep=\": \")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tiger-compiler/tcsh/python/ti.py b/tiger-compiler/tcsh/python/ti.py
new file mode 100755
index 0000000..a7df479
--- /dev/null
+++ b/tiger-compiler/tcsh/python/ti.py
@@ -0,0 +1,356 @@
+#! /usr/bin/env python3
+
+# Tiger interpreter.
+
+# Execute a Tiger program, using the Tiger Compiler through
+# TCSH/Python and a supporting back-end environment (HAVM, Nolimips,
+# or an IA-32 environment).
+#
+# This script needs a complete, dynamically-compiled Tiger compiler
+# (with all its modules) to work. The Tree back-end needs a `havm'
+# binary to be available in the PATH; the MIPS back-end, a `nolimips'
+# binary; and the IA-32 back-end, an IA-32 execution environment.
+
+from __future__ import annotations
+from collections.abc import Callable
+from typing import List, Optional, Tuple, TypeVar, Union
+
+import optparse
+import tempfile
+import subprocess
+
+import os
+import sys
+import re
+
+import tc
+
+
+# Subclass to redefine error method (for exit code to be 1).
+class TiOptionParser(optparse.OptionParser):
+ def error(self, msg: str) -> None:
+ self.print_usage(sys.stderr)
+ self.exit(1, "%s: error: %s\n" % (self.get_prog_name(), msg))
+
+
+T = TypeVar("T")
+
+
+def wrap_step(
+ modules: List[str] = [],
+ require: Optional[str] = None,
+ backend: Optional[tc.BackendType] = None,
+) -> Callable[[Callable[[TiExecutor], T]], Callable[[TiExecutor], Optional[T]]]:
+ """
+ Decorator for steps of TiExecutor, execute the require step if needed
+ """
+
+ def check_wrap_step(
+ f: Callable[[TiExecutor], T]
+ ) -> Callable[[TiExecutor], Optional[T]]:
+ def new_f(self: TiExecutor) -> Optional[T]:
+ if self.debug:
+ print(f"CALL {f.__name__} [{self.backend}]")
+ if backend and self.backend != backend:
+ self.backend = backend
+ if hasattr(self, "__step"):
+ delattr(self, "__step")
+ self._rm_asm()
+ self._rm_llvm()
+ self.data = TiExecutor.TiExecution()
+ if require and not hasattr(self, require):
+ raise RuntimeError(require + " step must exist")
+ if self.data.error:
+ return None
+ hasstep = hasattr(self, "__step")
+ if require and (not hasstep or hasstep and not self.__step == require):
+ getattr(self, require)()
+ if self.data.error:
+ return None
+ for mod in modules:
+ if not tc.has(mod):
+ msg = f"Module {mod} is not available to execute {f.__name__} step\nCheck your install of tc"
+ self.data.error = (-1, msg)
+ print(msg, file=sys.stderr)
+ if self.exit_on_error:
+ sys.exit(1)
+ return None
+ if self.debug:
+ print(f"ENTER {f.__name__} [{self.backend}]")
+ res = f(self)
+ if self.debug:
+ print(f"EXIT {f.__name__} [{self.backend}]")
+ self.__step = f.__name__
+ return res
+
+ new_f.__doc__ = f"Ast {f.__name__} step"
+ if require:
+ new_f.__doc__ += f"\nRequire {require} step, execute it otherwise"
+ if modules and len(modules):
+ new_f.__doc__ += "\nRequire {} tc modules".format(", ".join(modules))
+ new_f.__name__ = f.__name__
+ return new_f
+
+ return check_wrap_step
+
+
+class TiExecutor:
+ class TiExecution:
+ ast: Optional[tc.ast.ChunkList] = None
+ error: Optional[Tuple[int, str]] = None
+ fragments: Optional[tc.tree.Fragments] = None
+ lir_fragments: Optional[tc.assem.Fragments] = None
+ target: Optional[Union[tc.target.Ia32Target, tc.target.MipsTarget]] = None
+ tempmap: Optional[tc.temp.TempMap] = None
+ result: Optional[str] = None
+ llvm: Optional[str] = None
+
+ def __str__(self) -> str:
+ res = ""
+
+ def truncate(msg: str) -> str:
+ return msg if not msg or len(msg) < 100 else msg[:100] + "..."
+
+ for e in dir(self):
+ if not e.startswith("_"):
+ res += e + ": " + truncate(repr(getattr(self, e))) + "\n"
+ return res
+
+ def __init__(
+ self,
+ filename: str,
+ backend: tc.BackendType = tc.BackendType.mips,
+ exit_on_error: bool = True,
+ get_result: bool = False,
+ rename: bool = True,
+ desugar: bool = True,
+ object_enabled: bool = True,
+ debug: bool = False,
+ ):
+ self.filename = filename
+ self.backend = tc.BackendType(backend)
+ self.exit_on_error = exit_on_error
+ self.get = get_result
+ self.rename_enabled = rename
+ self.desugar_enabled = desugar
+ self.object_enabled = object_enabled
+ self.debug = debug
+ self.data = TiExecutor.TiExecution()
+
+ def error_message(self) -> str:
+ if not self.data.error:
+ return ""
+ status, message = self.data.error
+ statusMessage = tc.misc.error.error_type_message()[status]
+ if re.match(r"(.*/)?tmp\w{8}\.tig$", self.filename):
+ if message.startswith(self.filename + ":"):
+ message = message.replace(self.filename + ":", "")
+ message = " " + message
+ else:
+ message = "\n" + message
+ return str(status) + " " + statusMessage + ":" + message
+
+ def throw_error(self, e: Exception) -> None:
+ self.__step = "error"
+ self.data.error = e.args
+ status, message = e.args
+ if self.exit_on_error:
+ print(message, file=sys.stderr)
+ sys.exit(status)
+ else:
+ print(self.error_message(), end="", file=sys.stderr)
+
+ def _rm_attribute_file(self, arg: str) -> None:
+ if hasattr(self, arg):
+ os.unlink(getattr(self, arg))
+ delattr(self, arg)
+
+ def _rm_attribute_dir(self, arg: str) -> None:
+ if hasattr(self, arg):
+ os.rmdir(getattr(self, arg))
+ delattr(self, arg)
+
+ def _rm_attribute_temp(self, arg: str) -> None:
+ if hasattr(self, arg):
+ os.unlink(getattr(self, arg).name)
+ delattr(self, arg)
+
+ def _run_cmd(self, *cmd: str) -> Optional[str]:
+ if self.get:
+ proc = subprocess.run(cmd, capture_output=True)
+ self.data.result = proc.stdout.decode("utf-8")
+ else:
+ os.system(" ".join(cmd))
+ self.data.result = None
+ return self.data.result
+
+ @wrap_step(["misc", "parse"])
+ def parse(self) -> Optional[tc.ast.ChunkList]:
+ lib = tc.misc.file_library()
+ try:
+ self.data.ast = tc.parse.parse("builtin", self.filename, lib)
+ except Exception as e:
+ return self.throw_error(e)
+ return self.data.ast
+
+ @wrap_step(["bind"], "parse")
+ def bind(self) -> Optional[tc.ast.ChunkList]:
+ try:
+ if self.object_enabled and tc.has("object"):
+ tc.object.bind(self.data.ast).exit_on_error()
+ else:
+ tc.bind.bind(self.data.ast).exit_on_error()
+ except Exception as e:
+ return self.throw_error(e)
+ return self.data.ast
+
+ @wrap_step([], "bind")
+ def rename(self) -> Optional[tc.ast.ChunkList]:
+ if (
+ self.rename_enabled
+ and tc.has("bind")
+ and not self.object_enabled
+ and not tc.has("object")
+ ):
+ tc.bind.rename(self.data.ast)
+ return self.data.ast
+
+ @wrap_step(["type"], "rename")
+ def type(self) -> Optional[tc.ast.ChunkList]:
+ try:
+ if self.object_enabled and tc.has("object"):
+ tc.object.types_check(self.data.ast).exit_on_error()
+ else:
+ tc.type.types_check(self.data.ast).exit_on_error()
+ except Exception as e:
+ return self.throw_error(e)
+ return self.data.ast
+
+ @wrap_step([], "type")
+ def object_desugar(self) -> Optional[tc.ast.ChunkList]:
+ if self.object_enabled and tc.has("object"):
+ class_names = tc.object.rename(self.data.ast)
+ self.data.ast = tc.object.desugar(self.data.ast, class_names)
+ return self.data.ast
+
+ @wrap_step([], "object_desugar")
+ def desugar(self) -> Optional[tc.ast.ChunkList]:
+ if self.desugar_enabled and tc.has("desugar"):
+ self.data.ast = tc.desugar.desugar(self.data.ast, True, True)
+ return self.data.ast
+
+ @wrap_step(["llvmtranslate"], "desugar")
+ def llvm_file(self) -> str:
+ self.data.llvm = tc.llvmtranslate.translate(self.data.ast)
+
+ self._rm_llvm()
+ self.llvm_temp_dir = tempfile.mkdtemp()
+ # Dump assembly code output into a temporary file.
+ self.llvm_output = os.path.join(self.llvm_temp_dir, "llvm.ll")
+ with open(self.llvm_output, "w") as f:
+ f.write(str(self.data.llvm))
+ return self.llvm_output
+
+ def _rm_llvm(self) -> None:
+ self._rm_attribute_file("llvm_output")
+ self._rm_attribute_file("llvm_binary")
+ self._rm_attribute_dir("llvm_temp_dir")
+
+ @wrap_step([], "llvm_file")
+ def llvm_bin(self) -> str:
+ self._rm_attribute_file("llvm_binary")
+ self.llvm_binary = os.path.join(self.llvm_temp_dir, "bin")
+ os.system(f"clang -m32 {self.llvm_output} -o {self.llvm_binary}")
+ return self.llvm_binary
+
+ @wrap_step([], "llvm_bin", tc.BackendType.llvm)
+ def llvm(self) -> Optional[str]:
+ self._run_cmd(self.llvm_binary)
+ self._rm_llvm()
+ return self.data.result
+
+ def frontend_run(self) -> None:
+ """Run parse, bind and type depending of TC step"""
+ self.parse()
+
+ self.bind()
+ self.rename()
+ self.type()
+ self.object_desugar()
+ self.desugar()
+ return None
+
+ def backend_exec(self) -> Optional[str]:
+ """execute backends: llvm, hir, lir, mips and ia32"""
+ self.frontend_run()
+ if self.backend == tc.BackendType.llvm:
+ return self.llvm()
+ return None
+
+ def backend_run(self) -> None:
+ self.get = False
+ self.backend_exec()
+
+ def backend_get(self) -> Optional[str]:
+ self.get = True
+ return self.backend_exec()
+
+
+def process_file(
+ filename: str, backend: tc.BackendType = tc.BackendType.mips, **kwargs
+) -> None:
+ executor = TiExecutor(filename, backend=backend, **kwargs)
+ executor.backend_run()
+
+
+if __name__ == "__main__":
+ # Parser creation.
+ parser = TiOptionParser(
+ """%prog [options] file.tig
+ Execute a Tiger program, using a given back-end."""
+ )
+ parser.add_option(
+ "-b",
+ "--back-end",
+ metavar="BACKEND",
+ dest="backend",
+ default=tc.BackendType.mips,
+ help="use BACKEND as back-end. Can be either "
+ f"`{tc.BackendType.llvm.value}' (LLVM), "
+ f"`{tc.BackendType.mips.value}' (MIPS assembly language) "
+ "[default: %default]",
+ )
+ parser.add_option(
+ "-d",
+ "--debug",
+ action="store_true",
+ dest="debug",
+ default=False,
+ help="print debug call trace",
+ )
+
+ # Options parsing.
+ (options, args) = parser.parse_args()
+
+ # Invalid argument.
+ me = os.path.basename(sys.argv[0])
+ error = False
+ if len(args) != 1:
+ print(f"{me}: not enough arguments")
+ error = True
+
+ if options.backend not in [e.value for e in tc.BackendType]:
+ print(f"{me}: select a valid backend")
+ error = True
+
+ if error:
+ parser.print_help()
+ sys.exit(1)
+
+ # Get filename from arguments.
+ filename = args[-1]
+ process_file(filename, **vars(options))
+
+# Local Variables:
+# mode: python
+# End:
diff --git a/tiger-compiler/tcsh/run.in b/tiger-compiler/tcsh/run.in
new file mode 100755
index 0000000..1a12070
--- /dev/null
+++ b/tiger-compiler/tcsh/run.in
@@ -0,0 +1,53 @@
+#! /bin/sh
+# Copyright (C) 2003, 2004, 2006, 2013 Laboratoire d'Informatique de
+# Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
+# Université Pierre et Marie Curie.
+#
+# This file is part of Spot, a model checking library.
+#
+# Spot is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Spot is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Spot; see the file COPYING. If not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+
+# If we are running from make check (srcdir is set) and VERBOSE is
+# unset, be quiet.
+test -n "$srcdir" && test -z "$VERBOSE" && exec >/dev/null 2>&1
+
+# Darwin needs some help in figuring out where non-installed libtool
+# libraries are (on this platform libtool encodes the expected final
+# path of dependent libraries in each library).
+modpath='.libs:@abs_top_builddir@/src/.libs'
+
+# `@abs_builddir@/python' and `@abs_srcdir@/python' are for the *.py
+# files, and `@abs_builddir@/python/.libs' for the *.so files. We
+# used to rely on a module called `ltihooks' to teach the `import'
+# statement how to load a Libtool library, but it started to cause
+# issues with Python 2.6.
+pypath='@abs_builddir@/python:@abs_builddir@/python/.libs:@abs_srcdir@/python':"$PYTHONPATH"
+
+case $1 in
+ export)
+ # use export to get variables
+ echo "PYTHONPATH='$pypath' DYLD_LIBRARY_PATH='$modpath'";;
+ *.py)
+ PYTHONPATH=$pypath DYLD_LIBRARY_PATH=$modpath exec @PYTHON@ "$@";;
+ *.test)
+ exec sh -x "$@";;
+ *.ipynb)
+ PYTHONPATH=$pypath DYLD_LIBRARY_PATH=$modpath exec @abs_srcdir@/python/tests/ipynbtest.py "$@";;
+ *)
+ echo "Unknown extension" >&2
+ exit 2;;
+esac
diff --git a/tiger-compiler/tcsh/run.mk b/tiger-compiler/tcsh/run.mk
new file mode 100644
index 0000000..bfc00e9
--- /dev/null
+++ b/tiger-compiler/tcsh/run.mk
@@ -0,0 +1,6 @@
+# A test/script wrapper.
+
+RUN = $(top_builddir)/tcsh/run
+RUN_IN = $(top_srcdir)/tcsh/run.in
+$(RUN): $(RUN_IN)
+ cd $(top_builddir)/tcsh && $(MAKE) $(AM_MAKEFLAGS) run
diff --git a/tiger-compiler/tcsh/src/helper.hh b/tiger-compiler/tcsh/src/helper.hh
new file mode 100644
index 0000000..cdbf760
--- /dev/null
+++ b/tiger-compiler/tcsh/src/helper.hh
@@ -0,0 +1,16 @@
+#ifndef SWIG_HELPER_H
+#define SWIG_HELPER_H
+
+#define STCONVERT(TYPE, TYPENAME) \
+void operator()(const TYPE & e) override \
+{ \
+ result = SWIG_NewPointerObj(SWIG_as_voidptr(&e), SWIGTYPE_ ## TYPENAME, 0); \
+}
+
+#define IFTYPECONVERT(TYPE, TYPENAME) \
+if (const TYPE* d = dynamic_cast<const TYPE*>(&e); d != nullptr) \
+{ \
+ result = SWIG_NewPointerObj(SWIG_as_voidptr(&e), SWIGTYPE_ ## TYPENAME, 0); \
+}
+
+#endif /* ! SWIG_HELPER_H */
diff --git a/tiger-compiler/tcsh/src/swig_real_type.hh b/tiger-compiler/tcsh/src/swig_real_type.hh
new file mode 100644
index 0000000..9420bf9
--- /dev/null
+++ b/tiger-compiler/tcsh/src/swig_real_type.hh
@@ -0,0 +1,67 @@
+#ifndef SWIG_REAL_TYPE_HH
+#define SWIG_REAL_TYPE_HH
+
+#include "helper.hh"
+
+namespace {
+ using namespace ast;
+ class SwigAstTypeVisitor : public ConstVisitor
+ {
+ public:
+ PyObject *result;
+ SwigAstTypeVisitor() : GenVisitor<misc::constify_traits>() {}
+ ~SwigAstTypeVisitor() {}
+
+#define STHELPER(TYPE) STCONVERT(TYPE, p_ast__ ## TYPE)
+ STHELPER(ArrayExp)
+ STHELPER(ArrayTy)
+ STHELPER(AssignExp)
+ STHELPER(Ast)
+ STHELPER(BreakExp)
+ STHELPER(CallExp)
+ STHELPER(CastExp)
+ STHELPER(ChunkList)
+ STHELPER(ClassTy)
+ STHELPER(Field)
+ STHELPER(FieldInit)
+ STHELPER(FieldVar)
+ STHELPER(ForExp)
+ STHELPER(FunctionDec)
+ STHELPER(IfExp)
+ STHELPER(IntExp)
+ STHELPER(LetExp)
+ STHELPER(MethodCallExp)
+ STHELPER(MethodDec)
+ STHELPER(NameTy)
+ STHELPER(NilExp)
+ STHELPER(ObjectExp)
+ STHELPER(OpExp)
+ STHELPER(RecordExp)
+ STHELPER(RecordTy)
+ STHELPER(SeqExp)
+ STHELPER(SimpleVar)
+ STHELPER(StringExp)
+ STHELPER(SubscriptVar)
+ STHELPER(TypeDec)
+ STHELPER(VarDec)
+ STHELPER(WhileExp)
+#undef STHELPER
+
+#define STCHUNKHELPER(TYPE) \
+ STCONVERT(TYPE ## Chunk, p_ast__ChunkT_ast__ ## TYPE ## Dec_t)
+ STCHUNKHELPER(Function)
+ STCHUNKHELPER(Method)
+ STCHUNKHELPER(Type)
+ STCHUNKHELPER(Var)
+#undef STCHUNKHELPER
+ };
+} // namespace
+
+PyObject *get_swig_real_ast_type(const ast::Ast& e)
+{
+ SwigAstTypeVisitor stv;
+ e.accept(stv);
+ return stv.result;
+}
+
+#endif /* ! SWIG_REAL_TYPE_HH */
diff --git a/tiger-compiler/tcsh/src/tiger_ast.i b/tiger-compiler/tcsh/src/tiger_ast.i
new file mode 100644
index 0000000..685100f
--- /dev/null
+++ b/tiger-compiler/tcsh/src/tiger_ast.i
@@ -0,0 +1,312 @@
+// -*- C++ -*-
+
+%module tiger_ast
+
+%include "std_string.i"
+%include "std_vector.i"
+%include "std_list.i"
+%include "std_except.i"
+
+%{
+ #include "helper.hh"
+ #include <sstream>
+ #include <fstream>
+ #include <ast/visitor.hh>
+ #include <ast/object-visitor.hh>
+ #include <ast/default-visitor.hh>
+ #include <ast/all.hh>
+ #include <ast/libast.hh>
+ #include <common.hh>
+%}
+
+%typemap(ret) ast::Ast* {
+ $result = get_swig_real_ast_type(*$1);
+}
+%apply ast::Ast* { ast::ChunkInterface*, ast::Exp*, ast::Dec*, ast::Ty*, ast::Var* }
+%apply ast::Ast* { ast::Ast&, ast::ChunkInterface&, ast::Exp&, ast::Dec&, ast::Ty&, ast::Var& }
+
+%include "common.hh"
+%include "ast/fwd.hh"
+
+%include "ast/location.hh"
+
+%include "ast/ast.hh"
+
+%extend ast::Ast
+{
+ std::string __str__() const
+ {
+ std::ostringstream o;
+ o << *$self;
+ return o.str();
+ }
+ bool operator==(const ast::Ast& o) const
+ {
+ return $self == &o;
+ }
+}
+
+%extend ast::OpExp {
+ %pythoncode %{
+ def oper_str_get(self) -> "std::string":
+ return _tiger_ast.str(self.oper_get())
+
+ @staticmethod
+ def oper_names():
+ return { getattr(_tiger_ast, t): t[len("OpExp_Oper_"):] for t in dir(_tiger_ast) if t.startswith("OpExp_Oper_") }
+
+ def oper_name_get(self) -> "std::string":
+ return OpExp.oper_names()[self.oper_get()]
+ %}
+}
+
+%extend ast::Typable
+{
+ %pythoncode %{
+ def type_get(self) -> "type::Type const *":
+ import tiger_type
+ return tiger_type._get_swig_real_type_type(_tiger_ast.Typable_type_get(self))
+ %}
+}
+
+// Visitors.
+%include "ast/visitor.hh"
+%template(AstConstVisitor) ast::GenVisitor<misc::constify_traits>;
+%template(AstVisitor) ast::GenVisitor<misc::id_traits>;
+%warnfilter(401);
+
+%{
+#include "swig_real_type.hh"
+%}
+
+%define HELPER(TYPE, SUPER_TYPE)
+ void operator()(const ast::##TYPE & e) override
+ {
+ CallbackVisitor_Argument arg{++id_, #TYPE, &e};
+ auto obj = make_argument_dict(arg);
+ call_callback(parent_obj_, obj);
+
+ auto save_arg = parent_arg_;
+ auto save_obj = parent_obj_;
+ parent_arg_ = arg;
+ parent_obj_ = obj;
+ SUPER_TYPE##::operator()(e);
+ parent_arg_ = save_arg;
+ parent_obj_ = save_obj;
+ }
+%enddef
+
+%warnfilter(451) CallbackVisitor_Argument::name;
+%inline
+{
+ ast::Ast* ast_upcast(ast::ChunkList* a)
+ {
+ return static_cast<ast::Ast *>(a);
+ }
+
+#ifdef SWIGPYTHON
+
+ struct CallbackVisitor_Argument
+ {
+ int id{};
+ const char* name{};
+ const ast::Ast* ast{};
+ };
+
+ class CallbackVisitor
+ : public ast::DefaultConstVisitor
+ , public ast::ObjectConstVisitor
+ {
+ public:
+ using super_type = ast::DefaultVisitor;
+
+ CallbackVisitor(PyObject* pyfunc)
+ : GenVisitor<misc::constify_traits>()
+ {
+ Py_XINCREF(pyfunc);
+ this->callback_ = pyfunc;
+ }
+ ~CallbackVisitor() {}
+
+ PyObject* make_argument_dict(const CallbackVisitor_Argument& a)
+ {
+ std::ostringstream o;
+ if (a.ast) o << *a.ast;
+ std::string name(a.name);
+ std::string dec_name;
+ if (auto dec = dynamic_cast<const ast::Dec*>(a.ast))
+ dec_name = std::string(dec->name_get());
+ auto s = o.str();
+ PyObject *obj = get_swig_real_ast_type(*a.ast);
+ return Py_BuildValue("{s:i,s:s,s:s,s:s,s:O}",
+ "id", a.id,
+ "name", name.c_str(),
+ "string", s.c_str(),
+ "dec", dec_name.c_str(),
+ "ast", obj);
+ }
+
+ PyObject* call_callback(PyObject* from, PyObject* to) const
+ {
+ auto arglist = Py_BuildValue("(OO)", from ? from : Py_None, to ? to : Py_None);
+ auto result = PyObject_CallObject(this->callback_, arglist);
+ Py_DECREF(arglist);
+ return result;
+ }
+
+ HELPER(ArrayExp, ast::DefaultConstVisitor)
+ HELPER(ArrayTy, ast::DefaultConstVisitor)
+ HELPER(AssignExp, ast::DefaultConstVisitor)
+ HELPER(Ast, ast::DefaultConstVisitor)
+ HELPER(BreakExp, ast::DefaultConstVisitor)
+ HELPER(CallExp, ast::DefaultConstVisitor)
+ HELPER(CastExp, ast::DefaultConstVisitor)
+ HELPER(ChunkList, ast::DefaultConstVisitor)
+ HELPER(Field, ast::DefaultConstVisitor)
+ HELPER(FieldInit, ast::DefaultConstVisitor)
+ HELPER(FieldVar, ast::DefaultConstVisitor)
+ HELPER(ForExp, ast::DefaultConstVisitor)
+ HELPER(FunctionChunk, ast::DefaultConstVisitor)
+ HELPER(FunctionDec, ast::DefaultConstVisitor)
+ HELPER(IfExp, ast::DefaultConstVisitor)
+ HELPER(IntExp, ast::DefaultConstVisitor)
+ HELPER(LetExp, ast::DefaultConstVisitor)
+ HELPER(NameTy, ast::DefaultConstVisitor)
+ HELPER(NilExp, ast::DefaultConstVisitor)
+ HELPER(OpExp, ast::DefaultConstVisitor)
+ HELPER(RecordExp, ast::DefaultConstVisitor)
+ HELPER(RecordTy, ast::DefaultConstVisitor)
+ HELPER(SeqExp, ast::DefaultConstVisitor)
+ HELPER(SimpleVar, ast::DefaultConstVisitor)
+ HELPER(StringExp, ast::DefaultConstVisitor)
+ HELPER(SubscriptVar, ast::DefaultConstVisitor)
+ HELPER(TypeChunk, ast::DefaultConstVisitor)
+ HELPER(TypeDec, ast::DefaultConstVisitor)
+ HELPER(VarChunk, ast::DefaultConstVisitor)
+ HELPER(VarDec, ast::DefaultConstVisitor)
+ HELPER(WhileExp, ast::DefaultConstVisitor)
+
+ HELPER(ClassTy, ast::ObjectConstVisitor)
+ HELPER(MethodChunk, ast::ObjectConstVisitor)
+ HELPER(MethodCallExp, ast::ObjectConstVisitor)
+ HELPER(MethodDec, ast::ObjectConstVisitor)
+ HELPER(ObjectExp, ast::ObjectConstVisitor)
+
+ private:
+ PyObject* callback_{};
+
+ int id_{};
+ CallbackVisitor_Argument parent_arg_{};
+ PyObject* parent_obj_{};
+ };
+
+ ast::ConstVisitor* get_callback_visitor(PyObject* pyfunc)
+ {
+ if (!PyCallable_Check(pyfunc)) {
+ PyErr_SetString(PyExc_TypeError, "Need a callable object!");
+ return NULL;
+ }
+
+ return new CallbackVisitor(pyfunc);
+ }
+
+#endif
+}
+
+// Types.
+%include "ast/escapable.hh"
+%include "ast/typable.hh"
+%include "ast/type-constructor.hh"
+
+%include "ast/field.hh"
+%include "ast/field-init.hh"
+
+// Exps.
+%include "ast/exp.hh"
+%include "ast/array-exp.hh"
+%include "ast/assign-exp.hh"
+%include "ast/break-exp.hh"
+%include "ast/call-exp.hh"
+%include "ast/cast-exp.hh"
+%include "ast/for-exp.hh"
+%include "ast/if-exp.hh"
+%include "ast/int-exp.hh"
+%include "ast/let-exp.hh"
+%include "ast/method-call-exp.hh"
+%include "ast/nil-exp.hh"
+%include "ast/object-exp.hh"
+%include "ast/op-exp.hh"
+%include "ast/record-exp.hh"
+%include "ast/seq-exp.hh"
+%include "ast/string-exp.hh"
+%include "ast/while-exp.hh"
+
+// Vars.
+%include "ast/var.hh"
+%include "ast/simple-var.hh"
+%include "ast/field-var.hh"
+%include "ast/subscript-var.hh"
+
+// Tys.
+%include "ast/ty.hh"
+%include "ast/name-ty.hh"
+%include "ast/record-ty.hh"
+%include "ast/array-ty.hh"
+%include "ast/class-ty.hh"
+
+// ChunkInterface.
+%ignore ast::Chunk::operator[];
+%include "ast/chunk-interface.hh"
+%include "ast/dec.hh"
+%include "ast/function-dec.hh"
+%include "ast/method-dec.hh"
+%include "ast/var-dec.hh"
+%include "ast/type-dec.hh"
+%include "ast/chunk-list.hh"
+%include "ast/chunk.hh"
+
+%extend ast::Chunk
+{
+ int __len__()
+ {
+ return std::distance((*$self).begin(), (*$self).end());
+ }
+
+ D* __getitem__(int pos) throw(std::out_of_range)
+ {
+ int size = std::distance((*$self).begin(), (*$self).end());
+ if (pos >= size || pos < -size)
+ throw std::out_of_range("trying to access chunk item");
+ auto front = (*$self).begin();
+ std::advance(front, pos >= 0 ? pos : size + pos);
+ return *front;
+ }
+}
+
+%template(FunctionChunk) ast::Chunk<ast::FunctionDec>;
+%template(MethodChunk) ast::Chunk<ast::MethodDec>;
+%template(TypeChunk) ast::Chunk<ast::TypeDec>;
+%template(VarChunk) ast::Chunk<ast::VarDec>;
+%template(exps_type)std::vector<ast::Exp*>;
+%template(fieldinits_type) std::vector<ast::FieldInit*>;
+%template(fields_type) std::vector<ast::Field*>;
+
+%extend ast::ChunkList
+{
+ int __len__()
+ {
+ return std::distance((*$self).begin(), (*$self).end());
+ }
+
+ ast::ChunkInterface* __getitem__(int pos)
+ {
+ int size = std::distance((*$self).begin(), (*$self).end());
+ if (pos >= size || pos < -size)
+ throw std::out_of_range("trying to access chunk item");
+ auto front = (*$self).begin();
+ std::advance(front, pos >= 0 ? pos : size + pos);
+ return *front;
+ }
+}
+
+%include "ast/libast.hh"
diff --git a/tiger-compiler/tcsh/src/tiger_astclone.i b/tiger-compiler/tcsh/src/tiger_astclone.i
new file mode 100644
index 0000000..ca8438a
--- /dev/null
+++ b/tiger-compiler/tcsh/src/tiger_astclone.i
@@ -0,0 +1,17 @@
+// -*- C++ -*-
+
+%module tiger_astclone
+
+%import "tiger_ast.i"
+
+%{
+ #include <astclone/libastclone.hh>
+ #include "swig_real_type.hh"
+%}
+%inline
+{
+ ast::Ast* clone(const ast::Ast& tree)
+ {
+ return astclone::clone<ast::Ast>(tree);
+ }
+}
diff --git a/tiger-compiler/tcsh/src/tiger_bind.i b/tiger-compiler/tcsh/src/tiger_bind.i
new file mode 100644
index 0000000..00034cf
--- /dev/null
+++ b/tiger-compiler/tcsh/src/tiger_bind.i
@@ -0,0 +1,13 @@
+// -*- C++ -*-
+
+%module tiger_bind
+
+%import "tiger_misc.i"
+
+%include "std_string.i"
+
+%{
+ #include <bind/libbind.hh>
+%}
+
+%include "bind/libbind.hh"
diff --git a/tiger-compiler/tcsh/src/tiger_callgraph.i b/tiger-compiler/tcsh/src/tiger_callgraph.i
new file mode 100644
index 0000000..429c451
--- /dev/null
+++ b/tiger-compiler/tcsh/src/tiger_callgraph.i
@@ -0,0 +1,18 @@
+// -*- C++ -*-
+
+%module tiger_callgraph
+
+%include "std_string.i"
+
+%{
+ #include <callgraph/fundec-graph.hh>
+ #include <callgraph/libcallgraph.hh>
+%}
+
+namespace callgraph
+{
+ class FundecGraph;
+ using CallGraph = FundecGraph;
+}
+
+%include "callgraph/libcallgraph.hh"
diff --git a/tiger-compiler/tcsh/src/tiger_combine.i b/tiger-compiler/tcsh/src/tiger_combine.i
new file mode 100644
index 0000000..5ac5278
--- /dev/null
+++ b/tiger-compiler/tcsh/src/tiger_combine.i
@@ -0,0 +1,14 @@
+// -*- C++ -*-
+
+%module tiger_combine
+
+%include "std_pair.i"
+
+%{
+ #include <combine/libcombine.hh>
+ using namespace combine;
+%}
+
+%template() std::pair<overload::overfun_bindings_type, misc::error>;
+
+%include "combine/libcombine.hh"
diff --git a/tiger-compiler/tcsh/src/tiger_common.i b/tiger-compiler/tcsh/src/tiger_common.i
new file mode 100644
index 0000000..ff43652
--- /dev/null
+++ b/tiger-compiler/tcsh/src/tiger_common.i
@@ -0,0 +1,73 @@
+// -*- C++ -*-
+
+%module tiger_common
+
+%include std_string.i
+
+%{
+ #include <fstream>
+ #include <sstream>
+ #include <iostream>
+ #include <cassert>
+ #include <string>
+ #include <misc/timer.hh>
+%}
+
+// Warning 454: Setting a pointer/reference variable may leak memory.
+%warnfilter(454) Cout;
+%warnfilter(454) Cerr;
+%warnfilter(454) Clog;
+
+// Ofstream.
+%inline %{
+ struct Ofstream
+ {
+ Ofstream (const std::string& filename) : closed_ (false)
+ {
+ stream_ = new std::ofstream (filename.c_str ());
+ }
+
+ ~Ofstream ()
+ {
+ if (!closed_)
+ close ();
+ }
+
+ std::ostream&
+ to ()
+ {
+ assert (stream_);
+ return *stream_;
+ }
+
+ void
+ close ()
+ {
+ assert (stream_);
+ stream_->close ();
+ delete stream_;
+ closed_ = true;
+ }
+
+ std::ofstream* stream_;
+ bool closed_;
+ };
+
+ std::ostream&
+ get_cout()
+ {
+ return std::cout;
+ }
+
+ std::ostream&
+ get_cerr()
+ {
+ return std::cerr;
+ }
+
+ std::ostream* Cout = &std::cout;
+ std::ostream* Cerr = &std::cerr;
+ std::ostream* Clog = &std::clog;
+
+ misc::timer timer;
+%}
diff --git a/tiger-compiler/tcsh/src/tiger_desugar.i b/tiger-compiler/tcsh/src/tiger_desugar.i
new file mode 100644
index 0000000..94f6b82
--- /dev/null
+++ b/tiger-compiler/tcsh/src/tiger_desugar.i
@@ -0,0 +1,30 @@
+// -*- C++ -*-
+
+%module tiger_desugar
+
+%import "tiger_ast.i"
+
+%{
+ #include <desugar/libdesugar.hh>
+ #include <ast/all.hh>
+ #include "swig_real_type.hh"
+%}
+
+%rename(desugar) ast_desugar;
+%rename(raw_desugar) ast_raw_desugar;
+
+%inline {
+ast::Ast* ast_desugar(const ast::Ast& tree,
+ bool desugar_for = false,
+ bool desugar_string_cmp = false)
+{
+ return desugar::desugar<ast::Ast>(tree, desugar_for, desugar_string_cmp);
+}
+ast::Ast* ast_raw_desugar(const ast::Ast& tree,
+ bool desugar_for = false,
+ bool desugar_string_cmp = false)
+{
+ return desugar::raw_desugar<ast::Ast>(tree, desugar_for, desugar_string_cmp);
+}
+}
+
diff --git a/tiger-compiler/tcsh/src/tiger_escapes.i b/tiger-compiler/tcsh/src/tiger_escapes.i
new file mode 100644
index 0000000..b176790
--- /dev/null
+++ b/tiger-compiler/tcsh/src/tiger_escapes.i
@@ -0,0 +1,11 @@
+// -*- C++ -*-
+
+%module tiger_escapes
+
+%include "std_string.i"
+
+%{
+ #include <escapes/libescapes.hh>
+%}
+
+%include "escapes/libescapes.hh"
diff --git a/tiger-compiler/tcsh/src/tiger_llvmtranslate.i b/tiger-compiler/tcsh/src/tiger_llvmtranslate.i
new file mode 100644
index 0000000..70fade9
--- /dev/null
+++ b/tiger-compiler/tcsh/src/tiger_llvmtranslate.i
@@ -0,0 +1,39 @@
+// -*- C++ -*-
+
+%module tiger_llvmtranslate
+
+%include "std_string.i"
+
+%{
+ #include <llvmtranslate/libllvmtranslate.hh>
+ #include <llvmtranslate/tasks.hh>
+ #include <llvm/IR/IRPrintingPasses.h>
+ #include <llvm/Linker/Linker.h>
+ #include <llvm/IR/Module.h>
+%}
+
+%inline
+{
+ std::string translate(const ast::Ast& tree)
+ {
+ auto module = llvmtranslate::translate(tree);
+ auto runtime = llvmtranslate::runtime_get(*module.first);
+#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 7
+ auto link = llvm::Linker::LinkModules(module.second.get(), runtime.get());
+#else
+ auto link = llvm::Linker::linkModules(*module.second, std::move(runtime));
+#endif
+ postcondition(!link); // Returns true on error
+
+ std::string str;
+ llvm::raw_string_ostream out(str);
+ llvm::PrintModulePass printer{out};
+#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 8
+ printer.run(*module.second);
+#else
+ llvm::ModuleAnalysisManager dummy_mam;
+ printer.run(*module.second, dummy_mam);
+#endif
+ return out.str();
+ }
+}
diff --git a/tiger-compiler/tcsh/src/tiger_misc.i b/tiger-compiler/tcsh/src/tiger_misc.i
new file mode 100644
index 0000000..7e1470f
--- /dev/null
+++ b/tiger-compiler/tcsh/src/tiger_misc.i
@@ -0,0 +1,73 @@
+// -*- C++ -*-
+
+%module tiger_misc
+
+%include "std_string.i"
+
+%{
+ #include <sstream>
+
+ #include <misc/file-library.hh>
+ #include <misc/symbol.hh>
+ #include <misc/error.hh>
+ // The need for this using directive seems to be a SWIG bug. It is
+ // needed by the _wrap_error___lshift____SWIG_5 in the C++ wrapper
+ // generated by swig (tiger_bind-wrap.cc).
+ using misc::error;
+
+ #include <misc/timer.hh>
+%}
+
+%exception {
+ try {
+ $function
+ } catch (const misc::error& e)
+ {
+ std::ostringstream o;
+ o << e;
+ PyObject *err = Py_BuildValue("is", e.status_get_value(), o.str().c_str());
+ PyErr_SetObject(PyExc_RuntimeError, err);
+ SWIG_fail;
+ }
+}
+
+%include "misc/file-library.hh"
+
+// Save some warnings from SWIG.
+%ignore misc::error::operator=;
+%ignore misc::error::operator bool;
+
+// SWIG has trouble wrapping some of misc::error's operator<<'s; ignore them.
+%ignore misc::error::operator<<;
+
+%include "misc/error.hh"
+
+// Wrap misc::error::operator<<.
+%extend misc::error
+{
+ std::string __str__() const
+ {
+ std::ostringstream o;
+ o << *$self;
+ return o.str();
+ }
+
+ %pythoncode %{
+ @staticmethod
+ def error_type_message() -> dict[int, str]:
+ return { getattr(_tiger_misc, t): t[len("error_error_type_"):].upper() for t in dir(_tiger_misc) if t.startswith("error_error_type_") }
+ %}
+}
+
+%ignore misc::symbol::operator=;
+%ignore misc::symbol::operator<<;
+%include "misc/symbol.hh"
+%extend misc::symbol
+{
+ std::string __str__() const
+ {
+ return ($self)->get();
+ }
+}
+
+%include "misc/timer.hh"
diff --git a/tiger-compiler/tcsh/src/tiger_object.i b/tiger-compiler/tcsh/src/tiger_object.i
new file mode 100644
index 0000000..cd81eec
--- /dev/null
+++ b/tiger-compiler/tcsh/src/tiger_object.i
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+
+%module tiger_object
+
+%import "tiger_ast.i"
+
+%{
+ #include <object/libobject.hh>
+ #include <ast/all.hh>
+ #include "swig_real_type.hh"
+%}
+
+%import "tiger_misc.i"
+
+%rename(desugar) object_desugar;
+%rename(raw_desugar) object_raw_desugar;
+
+%inline {
+ast::Ast* object_desugar(const ast::Ast& tree,
+ const object::class_names_type& class_names)
+{
+ return object::desugar<ast::Ast>(tree, class_names);
+}
+ast::Ast* object_raw_desugar(const ast::Ast& tree,
+ const object::class_names_type& class_names)
+{
+ return object::raw_desugar<ast::Ast>(tree, class_names);
+}
+}
+
+%include "object/fwd.hh"
+%include "object/libobject.hh"
diff --git a/tiger-compiler/tcsh/src/tiger_overload.i b/tiger-compiler/tcsh/src/tiger_overload.i
new file mode 100644
index 0000000..7a9090c
--- /dev/null
+++ b/tiger-compiler/tcsh/src/tiger_overload.i
@@ -0,0 +1,14 @@
+// -*- C++ -*-
+
+%module tiger_overload
+
+%include "std_pair.i"
+
+%{
+ #include <overload/liboverload.hh>
+ using namespace overload;
+%}
+
+%template() std::pair<overfun_bindings_type, misc::error>;
+
+%include "overload/liboverload.hh"
diff --git a/tiger-compiler/tcsh/src/tiger_parse.i b/tiger-compiler/tcsh/src/tiger_parse.i
new file mode 100644
index 0000000..1d62bd8
--- /dev/null
+++ b/tiger-compiler/tcsh/src/tiger_parse.i
@@ -0,0 +1,102 @@
+// -*- C++ -*-
+
+%module tiger_parse
+
+%include "std_string.i"
+%include "std_pair.i"
+
+%{
+ #include <sstream>
+ #include <misc/error.hh>
+ #include <parse/location.hh>
+ #include <parse/tiger-driver.hh>
+ #include <parse/libparse.hh>
+%}
+
+%import "tiger_misc.i"
+
+%include "parse/fwd.hh"
+
+// Explicit instantiation of MetavarMap's.
+%include "parse/metavar-map.hh"
+%template(MetavarMap) parse::MetavarMap<ast::Exp>;
+%template(MetavarVar) parse::MetavarMap<ast::Var>;
+%template(MetavarNameTy) parse::MetavarMap<ast::NameTy>;
+%template(MetavarChunkList) parse::MetavarMap<ast::ChunkList>;
+%template(MetavarTweast) parse::MetavarMap<parse::Tweast>;
+
+/*------------------.
+| parse::position. |
+`------------------*/
+
+// Replace parse::position's ctor and ignore parse::position::initialize,
+// as Python is unable to parse the literal `1u' used as default value
+// of two of their arguments.
+%extend parse::position
+{
+ // External ctor. For more information, see
+ // http://www.nabble.com/Java---adding-code-to-a-constructor-td20210601.html
+ position (const std::string* f = nullptr,
+ unsigned int l = 1, unsigned int c = 1)
+ {
+ return new parse::position(f, l, c);
+ }
+}
+%ignore parse::position::position;
+%ignore parse::position::initialize;
+%extend parse::position
+{
+ std::string
+ __str__ () const
+ {
+ std::ostringstream o;
+ o << *$self;
+ return o.str ();
+ }
+}
+
+/*------------------.
+| parse::location. |
+`------------------*/
+
+// Ignore parse::location::initialize, as Python is unable to
+// parse the literal `1u' used as default value of two of its
+// arguments.
+%ignore parse::location::initialize;
+%include "parse/location.hh"
+%extend parse::location
+{
+ std::string
+ __str__ () const
+ {
+ std::ostringstream o;
+ o << *$self;
+ return o.str ();
+ }
+}
+
+/*-----------.
+| libparse. |
+`-----------*/
+
+%import "parse/tweast.hh"
+%include "parse/tiger-driver.hh"
+%inline
+{
+ namespace parse
+ {
+ // Parse a Tiger file, return the corresponding abstract syntax.
+ ast::ChunkList*
+ parse (const std::string& prelude, const std::string& fname,
+ misc::file_library& library)
+ {
+ std::pair<ast::ChunkList*, misc::error> res =
+ parse (prelude, fname, library, false, false, true);
+ res.second.exit_on_error();
+ return res.first;
+ }
+ }
+
+}
+
+%include "parse/libparse.hh"
diff --git a/tiger-compiler/tcsh/src/tiger_type.i b/tiger-compiler/tcsh/src/tiger_type.i
new file mode 100644
index 0000000..5679873
--- /dev/null
+++ b/tiger-compiler/tcsh/src/tiger_type.i
@@ -0,0 +1,91 @@
+// -*- C++ -*-
+
+%module tiger_type
+
+%include "std_string.i"
+
+%include "misc/singleton.hh"
+
+%{
+ #include "helper.hh"
+ #include <type/libtype.hh>
+ #include <misc/singleton.hh>
+
+ #include <type/fwd.hh>
+ #include <type/type.hh>
+ #include <type/array.hh>
+ #include <type/builtin-types.hh>
+ #include <type/class.hh>
+ #include <type/field.hh>
+ #include <type/function.hh>
+ #include <type/method.hh>
+ #include <type/named.hh>
+ #include <type/nil.hh>
+ #include <type/record.hh>
+
+ #include <type/visitor.hh>
+ #include <type/pretty-printer.hh>
+%}
+
+%typemap(ret) type::Type* {
+ $result = _get_swig_real_type_type(*$1);
+}
+
+%warnfilter(401);
+
+%include "type/fwd.hh"
+%include "type/type.hh"
+
+%extend type::Type
+{
+ std::string __str__() const
+ {
+ std::ostringstream o;
+ o << *$self;
+ return o.str();
+ }
+}
+%{
+namespace {
+ using namespace type;
+ class SwigTypeVisitor : public ConstVisitor
+ {
+ public:
+ PyObject *result;
+
+#define STHELPER(TYPE) STCONVERT(TYPE, p_type__ ## TYPE)
+ STHELPER(Array)
+ STHELPER(Class)
+ STHELPER(Function)
+ STHELPER(Int)
+ STHELPER(Method)
+ STHELPER(Named)
+ STHELPER(Nil)
+ STHELPER(Record)
+ STHELPER(String)
+ STHELPER(Void)
+#undef STHELPER
+ };
+} // namespace
+%}
+%inline %{
+PyObject *_get_swig_real_type_type(const type::Type& e)
+{
+ SwigTypeVisitor stv;
+ e.accept(stv);
+ return stv.result;
+}
+%}
+
+
+%include "type/array.hh"
+%include "type/builtin-types.hh"
+%include "type/class.hh"
+%include "type/field.hh"
+%include "type/function.hh"
+%include "type/method.hh"
+%include "type/named.hh"
+%include "type/nil.hh"
+%include "type/record.hh"
+
+%include "type/libtype.hh"