diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
index e6c019b0b5..4a321f00e7 100644
--- a/.github/workflows/CI.yml
+++ b/.github/workflows/CI.yml
@@ -10,7 +10,7 @@ on:
branches:
- main
env:
- MACOSX_DEPLOYMENT_TARGET: 12.0
+ MACOSX_DEPLOYMENT_TARGET: 14.0
jobs:
Build:
@@ -35,28 +35,28 @@ jobs:
key:
${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-${{ hashFiles('ci/environment.yml') }}
- - uses: conda-incubator/setup-miniconda@v2
+ - uses: mamba-org/setup-micromamba@v1.9.0
with:
- auto-update-conda: true
environment-file: ci/environment.yml
- python-version: ${{ matrix.python-version }}
- use-only-tar-bz2: true
+ create-args: >-
+ python=${{ matrix.python-version }}
+ cmake=3.30.0
- name: Install Windows Conda Packages
if: contains(matrix.os, 'windows')
shell: bash -e -l {0}
- run: conda install m2-bison=3.0.4 cmake=3.21.1
+ run: micromamba install --freeze-installed m2-bison=3.0.4 m2-filesystem
- name: Install Linux / macOS Conda Packages
if: contains(matrix.os, 'ubuntu') || contains(matrix.os, 'macos')
shell: bash -e -l {0}
- run: conda install bison=3.4
+ run: micromamba install --freeze-installed bison=3.4 nodejs=18
- name: Conda info
shell: bash -e -l {0}
run: |
- conda info
- conda list
+ micromamba info
+ micromamba list
- name: Setup Platform (Linux)
if: contains(matrix.os, 'ubuntu')
@@ -86,9 +86,9 @@ jobs:
if: contains(matrix.os, 'windows')
shell: cmd
run: |
- set CONDA_INSTALL_LOCN=C:\\Miniconda
- call %CONDA_INSTALL_LOCN%\Scripts\activate.bat
- call conda activate test
+ set MAMBA_INSTALL_LOCN=C:\\Users\runneradmin\micromamba
+ call %MAMBA_INSTALL_LOCN%\Scripts\activate.bat
+ call micromamba activate lp
set LFORTRAN_CMAKE_GENERATOR=Ninja
set WIN=1
set MACOS=0
@@ -106,9 +106,9 @@ jobs:
if: contains(matrix.os, 'windows')
shell: cmd
run: |
- set CONDA_INSTALL_LOCN=C:\\Miniconda
- call %CONDA_INSTALL_LOCN%\Scripts\activate.bat
- call conda activate test
+ set MAMBA_INSTALL_LOCN=C:\\Users\runneradmin\micromamba
+ call %MAMBA_INSTALL_LOCN%\Scripts\activate.bat
+ call micromamba activate lp
set LFORTRAN_CMAKE_GENERATOR=Ninja
set WIN=1
set MACOS=0
@@ -402,7 +402,7 @@ jobs:
create-args: >-
python=3.10
bison=3.4
- symengine=0.11.1
+ symengine=0.12.0
sympy=1.11.1
- uses: hendrikmuhs/ccache-action@main
@@ -430,8 +430,8 @@ jobs:
shell: bash -e -l {0}
run: |
cd integration_tests
- ./run_tests.py -b c_sym cpython_sym llvm_sym
- ./run_tests.py -b c_sym cpython_sym llvm_sym -f
+ ./run_tests.py -b c_sym cpython_sym llvm_sym llvm_jit
+ ./run_tests.py -b c_sym cpython_sym llvm_sym llvm_jit -f
integration_tests_cpython:
name: Run Integration tests with Python ${{ matrix.python-version }}
@@ -454,12 +454,12 @@ jobs:
create-args: >-
llvmdev=11.1.0
bison=3.4
- re2c
- zlib
- cmake
- make
+ re2c=2.2
+ zlib=1.3.1
+ cmake=3.30.0
+ make=4.3
python=${{ matrix.python-version }}
- numpy
+ numpy=1.26.4
- uses: hendrikmuhs/ccache-action@main
with:
@@ -496,6 +496,48 @@ jobs:
cd integration_tests
./run_tests.py -b cpython c_py
+ build_jupyter_kernel:
+ name: Build Jupyter Kernel
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - uses: mamba-org/setup-micromamba@v1
+ with:
+ environment-file: ci/environment.yml
+ create-args: >-
+ jupyter=1.0.0
+ python=3.10
+ bison=3.4
+
+ - uses: hendrikmuhs/ccache-action@main
+ with:
+ variant: sccache
+ key: ${{ github.job }}-${{ matrix.os }}
+
+ - name: Build LPython with Kernel
+ shell: bash -e -l {0}
+ run: |
+ ./build0.sh
+ export CXXFLAGS="-Werror"
+ cmake . -GNinja \
+ -DCMAKE_BUILD_TYPE=Debug \
+ -DWITH_LLVM=yes \
+ -DWITH_XEUS=yes \
+ -DCMAKE_PREFIX_PATH="$CONDA_PREFIX" \
+ -DCMAKE_INSTALL_PREFIX="$CONDA_PREFIX"
+
+ ninja install
+ ctest --output-on-failure
+ jupyter kernelspec list --json
+
+ - name: Test Kernel
+ shell: bash -e -l {0}
+ run: |
+ ctest --output-on-failure
+
upload_tarball:
name: Upload Tarball
runs-on: ubuntu-latest
diff --git a/.gitignore b/.gitignore
index 2e1546420b..d18b9b6284 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,6 +61,7 @@ src/libasr/wasm_visitor.h
src/libasr/pass/intrinsic_function_registry_util.h
src/libasr/config.h
share/jupyter/kernels/fortran/kernel.json
+share/jupyter/kernels/lpython/kernel.json
src/runtime/*.o.empty.c
python_ast.py
python_ast.h
@@ -234,3 +235,6 @@ integration_tests/array_02_decl
integration_tests/array_02_decl.c
integration_tests/expr_12
integration_tests/expr_12.c
+
+# Interactive Shell
+input
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9545f67832..8919bbee1f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -120,6 +120,20 @@ if (WITH_LCOMPILERS_FAST_ALLOC)
add_definitions("-DLCOMPILERS_FAST_ALLOC=1")
endif()
+# copy runtime files
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/lpython/lpython.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/lpython/lpython.py")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/cmath.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/cmath.py")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/lpython_builtin.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/lpython_builtin.py")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/lpython_intrinsic_numpy.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/lpython_intrinsic_numpy.py")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/lpython_parser.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/lpython_parser.py")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/math.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/math.py")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/os.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/os.py")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/platform.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/platform.py")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/random.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/random.py")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/statistics.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/statistics.py")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/sys.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/sys.py")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/time.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/time.py")
+
# LLVM
set(WITH_LLVM no CACHE BOOL "Build with LLVM support")
set(WITH_TARGET_AARCH64 no CACHE BOOL "Enable target AARCH64")
@@ -194,13 +208,14 @@ endif()
# XEUS (Fortran kernel)
set(WITH_XEUS no CACHE BOOL "Build with XEUS support")
if (WITH_XEUS)
- find_package(xeus 0.24.1 REQUIRED)
+ find_package(xeus 5.1.0 REQUIRED)
+ find_package(xeus-zmq 3.0.0 REQUIRED)
set(HAVE_LFORTRAN_XEUS yes)
# Generate kernel.json with correct paths
configure_file (
- "${CMAKE_CURRENT_SOURCE_DIR}/share/jupyter/kernels/fortran/kernel.json.in"
- "${CMAKE_CURRENT_BINARY_DIR}/share/jupyter/kernels/fortran/kernel.json"
+ "${CMAKE_CURRENT_SOURCE_DIR}/share/jupyter/kernels/lpython/kernel.json.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/share/jupyter/kernels/lpython/kernel.json"
)
# Configuration and data directories for Jupyter and LFortran
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index a12bb34a57..0000000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-image: Visual Studio 2017
-# List of preinstalled software in the image:
-# https://www.appveyor.com/docs/windows-images-software/
-
-build_script:
-- set CONDA_INSTALL_LOCN=C:\\Miniconda37-x64
-- call %CONDA_INSTALL_LOCN%\Scripts\activate.bat
-- call conda config --set always_yes yes --set changeps1 no
-- call conda info -a
-- call conda update -q conda
-- call conda install -c conda-forge python=3.7 re2c m2-bison xonsh llvmdev=11.1.0 jupyter xeus=1.0.1 xtl nlohmann_json cppzmq jupyter_kernel_test pytest
-- set CONDA_PREFIX=C:\\Miniconda37-x64
-- set WIN=1
-- set MACOS=0
-#- set LFORTRAN_CMAKE_GENERATOR=Visual Studio 15 2017 Win64
-- set LFORTRAN_CMAKE_GENERATOR=Ninja
-- call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd" -arch=x64
-- xonsh ci\build.xsh
-
-# Uncomment the following two lines to be able to login to the build worker. You
-# can use the `remmina` program in Ubuntu, use the login information that the
-# line below prints into the log.
-#on_finish:
-#- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
diff --git a/build_to_wasm.sh b/build_to_wasm.sh
index dc8f1e1435..2d11afb250 100755
--- a/build_to_wasm.sh
+++ b/build_to_wasm.sh
@@ -9,8 +9,9 @@ cp -r src/runtime/lpython src/bin/asset_dir
./build0.sh
emcmake cmake \
- -DCMAKE_BUILD_TYPE=Debug \
+ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS_DEBUG="-Wall -Wextra -fexceptions" \
+ -DCMAKE_CXX_FLAGS_RELEASE="-Wall -Wextra -fexceptions" \
-DWITH_LLVM=no \
-DLPYTHON_BUILD_ALL=yes \
-DLPYTHON_BUILD_TO_WASM=yes \
diff --git a/ci/azure_install_macos.sh b/ci/azure_install_macos.sh
deleted file mode 100755
index 5012f14ae7..0000000000
--- a/ci/azure_install_macos.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-
-conda config --set always_yes yes --set changeps1 no
-conda info -a
-conda update -q conda
-conda install -c conda-forge python=3.8 re2c bison=3.4 m4 xonsh llvmdev=11.0.1 toml cmake=3.17.0 jupyter pytest xeus=1.0.1 xtl nlohmann_json cppzmq jupyter_kernel_test
-export MACOSX_DEPLOYMENT_TARGET="10.12"
-export CONDA_PREFIX=/usr/local/miniconda
-export LFORTRAN_CMAKE_GENERATOR="Unix Makefiles"
-export WIN=0
-export MACOS=1
-xonsh ci/build.xsh
diff --git a/ci/environment.yml b/ci/environment.yml
index b9b7fd715f..db5ded2261 100644
--- a/ci/environment.yml
+++ b/ci/environment.yml
@@ -4,19 +4,19 @@ channels:
- defaults
dependencies:
- llvmdev=11.1.0
- - toml
- - pytest
- - jupyter
- - xeus=1.0.1
- - xtl
- - nlohmann_json
- - cppzmq
- - jupyter_kernel_test
- - xonsh
- - re2c
- - numpy
- - zlib
- - ninja
- - rapidjson
+ - toml=0.10.2
+ - pytest=7.2.0
+ - jupyter=1.0.0
+ - xeus=5.1.0
+ - xeus-zmq=3.0.0
+ - nlohmann_json=3.11.3
+ - jupyter_kernel_test=0.4.4
+ - xonsh=0.13.3
+ - re2c=2.2
+ - numpy=1.26.4
+ - zlib=1.3.1
+ - zstd=1.5.6
+ - ninja=1.11.0
+ - rapidjson=1.1.0
# - bison=3.4 [not win]
# - m2-bison=3.4 [win]
diff --git a/doc/src/built-in functions.md b/doc/src/built-in functions.md
new file mode 100644
index 0000000000..b9804b5c28
--- /dev/null
+++ b/doc/src/built-in functions.md
@@ -0,0 +1,147 @@
+# Built-in Functions
+
+LPython has a variety of functions and types built into it that are always available.
+
+### abs(x)
+
+- **Parameter**
+ - x : integer (i8, i16, i32, i64), floating point number (f32, f64), complex number (c32, c64) or bool
+- **Returns** : integer (i8, i16, i32, i64), floating point number (f32, f64)
+
+Returns the absolute value of a number. If the argument is a complex number, its magnitude is returned.
+
+
+### bin(n)
+
+- **Parameters**
+ - n : integer (i32)
+- **Returns** : str
+
+Returns the binary representation of n as a '0b' prefixed string.
+
+
+### complex(x=0, y=0)
+
+- **Parameters**
+ - x : integer (i32, i64) or floating point number (f32, f64)
+ - y : integer (i32, i64) or floating point number (f32, f64)
+- **Returns** : complex number (c32, c64)
+
+Returns a complex number with the provided real and imaginary parts. Both x and y should be of the same type. However, using both the 32-bit and 64-bit versions of the same type together is allowed. In that case, the returned complex number is of 64-bit type.
+
+Example:
+
+```python
+real: i32 = 10
+imag: i64 = 22
+c: c64 = complex(real, imag)
+```
+
+### divmod(x, y)
+
+- **Parameters**
+ - x : integer (i32)
+ - y : integer (i32)
+- **Returns** : tuple[i32, i32]
+
+Returns the tuple (x // y, x % y).
+
+
+### exp(x)
+
+- ****Parameter****
+ - x : floating point number (f32, f64)
+- **Returns** : floating point number (f32, f64) between [0.0, inf]
+
+Returns the base-e exponential of x (ex), where e is the Euler's number (2.71828). For a very large output, the function returns **inf** indicating overflow.
+
+
+### hex(n)
+
+- **Parameters**
+ - n : integer (i32)
+- **Returns** : str
+
+Returns the hexadecimal representation of n as a '0x' prefixed string.
+
+
+### len(s)
+
+- **Parameters**
+ - s : sequence (such as string, tuple, list or range) or collection (such as a dictionary or set)
+- **Returns** : integer (i32)
+
+Returns the number of items present in an object.
+
+
+### max(x, y)
+
+- **Parameters**
+ - x : integer (i32) or floating point number (f64)
+ - y : integer (i32) or floating point number (f64)
+- **Returns** : integer (i32) or floating point number (f64)
+
+Returns the greater value between x and y. Both x and y should be of the same type.
+
+
+### min(x, y)
+
+- **Parameters**
+ - x : integer (i32) or floating point number (f64)
+ - y : integer (i32) or floating point number (f64)
+- **Returns** : integer (i32) or floating point number (f64)
+
+Returns the smaller value between x and y. Both x and y should be of the same type.
+
+
+### mod(x, y)
+
+- **Parameters**
+ - x : integer (i32, i64) or floating point number (f32, f64)
+ - y : integer (i32, i64) or floating point number (f32, f64)
+- **Returns** : integer (i32, i64) or floating point number (f32, f64)
+
+Returns the remainder of x / y, or x when x is smaller than y. Both x and y should be of the same type.
+
+
+### pow(x, y)
+
+- **Parameters**
+ - x : integer (i32, i64), floating point number (f32, f64), complex number (c32) or bool
+ - y: integer (i32, i64), floating point number (f32, f64) or bool
+- **Returns** : integer (i32), floating point number (f32, f64) or a complex number
+
+Returns xy. When x is of type bool, y must also be of the same type. If x is 32-bit complex number (c32), y can only be a 32-bit integer (i32).
+
+**Note** : `x ** y` is the recommended method for doing the above calculation.
+
+
+### round(x)
+
+- **Parameters**
+ - x : integer (i8, i16, i32, i64), floating point number (f32, f64) or bool
+- **Returns** : integer (i8, i16, i32, i64)
+
+Returns the integer nearest to x.
+
+
+### sum(arr)
+
+- **Parameters**
+ - arr : list of integers (list[i32], list[i64]) or floating point numbers (list[i32], list[f64])
+- **Returns** : integer (i32, i64) or floating point number (f32, f64)
+
+Returns the sum of all elements present in the list.
+
+
+### oct(n)
+
+- **Parameters**
+ - n : integer (i32)
+- **Returns** : str
+
+Returns the octal representation of n as a '0o' prefixed string.
+
+
+
+
diff --git a/doc/src/developers_example.ipynb b/doc/src/developers_example.ipynb
new file mode 100644
index 0000000000..c63754c8f0
--- /dev/null
+++ b/doc/src/developers_example.ipynb
@@ -0,0 +1,67 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c86338ac-53ca-4115-8c5a-8bf8a5c7113e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%showast\n",
+ "def add(x: i32, y: i32) -> i32:\n",
+ " return x + y"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "23834b08-2f3f-45e7-a1ce-21a9fd4e5117",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%showasr\n",
+ "def add(x: i32, y: i32) -> i32:\n",
+ " return x + y"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ec7426b4-e2e5-416c-bcae-9bb9c8926c9b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%showllvm\n",
+ "def sub(x: i32, y: i32) -> i32:\n",
+ " return add(x, -y)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "716c56ef-8210-4daf-aa23-96b385801014",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%showasm\n",
+ "def mul(x: i32, y: i32) -> i32:\n",
+ " return x * y"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "LPython",
+ "language": "python",
+ "name": "lpython"
+ },
+ "language_info": {
+ "file_extension": ".f90",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "version": "2018"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/doc/src/installation.md b/doc/src/installation.md
index bc02241cab..dff2027ff7 100644
--- a/doc/src/installation.md
+++ b/doc/src/installation.md
@@ -185,6 +185,38 @@ You can run the following examples manually in a terminal:
./src/bin/lpython --show-c examples/expr2.py
```
+## Enabling the Jupyter Kernel
+
+To install the Jupyter kernel, install the following Conda packages also:
+```
+conda install xeus=5.1.0 xeus-zmq=3.0.0 nlohmann_json
+```
+and enable the kernel by `-DWITH_XEUS=yes` and install into `$CONDA_PREFIX`. For
+example:
+```
+cmake . -GNinja \
+ -DCMAKE_BUILD_TYPE=Debug \
+ -DWITH_LLVM=yes \
+ -DWITH_XEUS=yes \
+ -DCMAKE_PREFIX_PATH="$CONDA_PREFIX" \
+ -DCMAKE_INSTALL_PREFIX="$CONDA_PREFIX"
+ .
+ninja install
+```
+To use it, install Jupyter (`conda install jupyter`) and test that the LPython
+kernel was found:
+```
+jupyter kernelspec list --json
+```
+Then launch a Jupyter notebook as follows:
+```
+jupyter notebook
+```
+Click `New->LPython`. To launch a terminal jupyter LPython console:
+```
+jupyter console --kernel=lpython
+```
+
## Found a bug?
Please report any bugs you find at our issue tracker [here](https://github.com/lcompilers/lpython/issues). Or, even better, fork the repository on GitHub and create a Pull Request (PR).
diff --git a/examples/example_notebook.ipynb b/examples/example_notebook.ipynb
new file mode 100644
index 0000000000..17ce1ba2db
--- /dev/null
+++ b/examples/example_notebook.ipynb
@@ -0,0 +1,134 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "e87300c2-64ed-4636-8448-591f36faba29",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Hello, LPython\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(\"Hello, LPython\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "dfcac851-7b49-4065-8c64-4a31658249f7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def add(x: i32, y: i32) -> i32:\n",
+ " return x + y"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "09213386-84d5-4e7c-83ba-c3b027f765dd",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def sub(x: i32, y: i32) -> i32:\n",
+ " return x - y"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "a4b49fd3-bf17-4287-9d5e-60f14ebc9a0f",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "5"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "add(2, 3)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "d6f4961f-7f0c-45a6-9bf8-e549e97098b0",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "-1"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "sub(2, 3)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "398fd4be-d7cc-4912-8aa1-880aa58b37ab",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "@dataclass\n",
+ "class MyClass:\n",
+ " x: i32\n",
+ " y: f64\n",
+ " z: str"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "628f0b7d-09a6-49de-a0e6-2f6c664f2ba2",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "12 2.45000000000000000e+01 LPython\n"
+ ]
+ }
+ ],
+ "source": [
+ "x: MyClass = MyClass(12, 24.5, \"LPython\")\n",
+ "print(x)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "LPython",
+ "language": "python",
+ "name": "lpython"
+ },
+ "language_info": {
+ "file_extension": ".f90",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "version": "2018"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/expr b/expr
deleted file mode 100755
index 82c85f86ee..0000000000
Binary files a/expr and /dev/null differ
diff --git a/grammar/Python.asdl b/grammar/Python.asdl
index a5ca1c672e..ade97a49a0 100644
--- a/grammar/Python.asdl
+++ b/grammar/Python.asdl
@@ -73,6 +73,7 @@ module LPython
-- need sequences for compare to distinguish between
-- x < 4 < 3 and (x < 4) < 3
| Compare(expr left, cmpop ops, expr* comparators)
+ | Membership(expr left, membershipop op, expr right)
| Call(expr func, expr* args, keyword* keywords)
| FormattedValue(expr value, int conversion, expr? format_spec)
| JoinedStr(expr* values)
@@ -110,7 +111,9 @@ module LPython
unaryop = Invert | Not | UAdd | USub
- cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
+ cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot
+
+ membershipop = In | NotIn
comprehension = (expr target, expr iter, expr* ifs, int is_async)
diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt
index e5f6ff3aa8..4632194e50 100644
--- a/integration_tests/CMakeLists.txt
+++ b/integration_tests/CMakeLists.txt
@@ -107,6 +107,16 @@ macro(RUN_UTIL RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_EXTRAFILES RUN_NOM
if (${fail})
set_tests_properties(${name} PROPERTIES WILL_FAIL TRUE)
endif()
+ elseif (KIND STREQUAL "llvm_jit")
+ add_test(
+ NAME ${name}
+ COMMAND ${LPYTHON} --jit ${extra_args} ${CMAKE_CURRENT_SOURCE_DIR}/${file_name}.py)
+ if (labels)
+ set_tests_properties(${name} PROPERTIES LABELS "${labels}")
+ endif()
+ if (${fail})
+ set_tests_properties(${name} PROPERTIES WILL_FAIL TRUE)
+ endif()
elseif (KIND STREQUAL "llvm_py")
add_custom_command(
OUTPUT ${name}.o
@@ -311,27 +321,14 @@ macro(RUN_UTIL RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_EXTRAFILES RUN_NOM
endmacro(RUN_UTIL)
macro(RUN)
- set(options FAIL NOFAST NOMOD ENABLE_CPYTHON LINK_NUMPY NO_WARNINGS)
+ set(options FAIL NOFAST NOMOD)
set(oneValueArgs NAME IMPORT_PATH COPY_TO_BIN REQ_PY_VER)
- set(multiValueArgs LABELS EXTRAFILES)
+ set(multiValueArgs LABELS EXTRAFILES EXTRA_ARGS)
cmake_parse_arguments(RUN "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN} )
- set(RUN_EXTRA_ARGS "")
set(RUN_FILE_NAME ${RUN_NAME})
- if (RUN_LINK_NUMPY)
- set(RUN_EXTRA_ARGS ${RUN_EXTRA_ARGS} --link-numpy)
- endif()
-
- if (RUN_ENABLE_CPYTHON)
- set(RUN_EXTRA_ARGS ${RUN_EXTRA_ARGS} --enable-cpython)
- endif()
-
- if (RUN_NO_WARNINGS)
- set(RUN_EXTRA_ARGS ${RUN_EXTRA_ARGS} --no-warnings)
- endif()
-
if (RUN_IMPORT_PATH)
# Only one import path supported for now
# Later add support for multiple import paths by looping over and appending to extra args
@@ -420,227 +417,238 @@ endmacro(COMPILE)
# Test zero and non-zero exit code and assert statements
-RUN(NAME array_01_decl LABELS cpython llvm c)
-RUN(NAME array_02_decl LABELS cpython llvm c)
-RUN(NAME array_03_decl LABELS cpython llvm c)
-RUN(NAME variable_decl_01 LABELS cpython llvm c)
-RUN(NAME variable_decl_02 LABELS cpython llvm c)
-RUN(NAME variable_decl_03 LABELS cpython llvm c)
-RUN(NAME array_expr_01 LABELS cpython llvm c)
-RUN(NAME array_expr_02 LABELS cpython llvm c NOFAST)
-RUN(NAME array_expr_03 LABELS cpython llvm c)
-RUN(NAME array_expr_04 LABELS cpython llvm c)
-RUN(NAME array_expr_05 LABELS cpython llvm c)
-RUN(NAME array_expr_06 LABELS cpython llvm c)
-RUN(NAME array_expr_07 LABELS cpython llvm c)
-RUN(NAME array_expr_08 LABELS cpython llvm c)
-RUN(NAME array_expr_09 LABELS cpython llvm c)
-RUN(NAME array_expr_10 LABELS cpython llvm c)
-RUN(NAME array_size_01 LABELS cpython llvm c)
-RUN(NAME array_size_02 LABELS cpython llvm c)
-RUN(NAME array_01 LABELS cpython llvm wasm c)
+RUN(NAME array_01_decl LABELS cpython llvm llvm_jit c)
+RUN(NAME array_02_decl LABELS cpython llvm llvm_jit c)
+RUN(NAME array_03_decl LABELS cpython llvm llvm_jit c)
+RUN(NAME variable_decl_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME variable_decl_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME variable_decl_03 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_expr_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_expr_02 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME array_expr_03 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_expr_04 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_expr_05 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_expr_06 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_expr_07 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_expr_08 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_expr_09 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_expr_10 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_size_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_size_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_01 LABELS cpython llvm llvm_jit wasm c)
RUN(NAME array_02 LABELS cpython wasm c)
-RUN(NAME array_03 LABELS cpython llvm c)
-RUN(NAME array_04 LABELS cpython llvm c)
-RUN(NAME array_05 LABELS cpython llvm c)
-RUN(NAME array_06 LABELS cpython llvm)
-RUN(NAME bindc_01 LABELS cpython llvm c)
-RUN(NAME bindc_02 LABELS cpython llvm c)
-RUN(NAME bindc_04 LABELS llvm c NOFAST)
-RUN(NAME bindc_07 LABELS cpython llvm c NOFAST)
-RUN(NAME bindc_08 LABELS cpython llvm c)
-RUN(NAME bindc_09 LABELS cpython llvm c)
-RUN(NAME bindc_09b LABELS cpython llvm c)
-RUN(NAME bindc_10 LABELS cpython llvm c NOFAST)
+RUN(NAME array_03 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_04 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_05 LABELS cpython llvm llvm_jit c)
+RUN(NAME array_06 LABELS cpython llvm llvm_jit)
+RUN(NAME bindc_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME bindc_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME bindc_04 LABELS llvm llvm_jit c NOFAST)
+RUN(NAME bindc_07 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME bindc_08 LABELS cpython llvm llvm_jit c)
+RUN(NAME bindc_09 LABELS cpython llvm llvm_jit c)
+RUN(NAME bindc_09b LABELS cpython llvm llvm_jit c)
+RUN(NAME bindc_10 LABELS cpython llvm llvm_jit c NOFAST)
RUN(NAME bindc_11 LABELS cpython) # This is CPython test only
-RUN(NAME exit_01 LABELS cpython llvm c NOFAST)
-RUN(NAME exit_02 FAIL LABELS cpython llvm c NOFAST)
-RUN(NAME exit_03 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
-RUN(NAME exit_04 FAIL LABELS cpython llvm c wasm wasm_x86 wasm_x64)
-RUN(NAME exit_01b LABELS cpython llvm c wasm wasm_x86 wasm_x64)
-RUN(NAME exit_02b FAIL LABELS cpython llvm c wasm wasm_x86 wasm_x64)
-RUN(NAME exit_02c FAIL LABELS cpython llvm c)
+RUN(NAME exit_01 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME exit_02 FAIL LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME exit_03 LABELS cpython llvm llvm_jit c wasm wasm_x86 wasm_x64)
+RUN(NAME exit_04 FAIL LABELS cpython llvm llvm_jit c wasm wasm_x86 wasm_x64)
+RUN(NAME exit_01b LABELS cpython llvm llvm_jit c wasm wasm_x86 wasm_x64)
+RUN(NAME exit_02b FAIL LABELS cpython llvm llvm_jit c wasm wasm_x86 wasm_x64)
+RUN(NAME exit_02c FAIL LABELS cpython llvm llvm_jit c)
# Test all four backends
-RUN(NAME print_01 LABELS cpython llvm c wasm) # wasm not yet supports sep and end keywords
+RUN(NAME print_01 LABELS cpython llvm llvm_jit c wasm) # wasm not yet supports sep and end keywords
RUN(NAME print_03 LABELS x86 c wasm wasm_x86 wasm_x64) # simple test case specifically for x86, wasm_x86 and wasm_x64
-RUN(NAME print_04 LABELS cpython llvm c)
-RUN(NAME print_06 LABELS cpython llvm c)
-RUN(NAME print_05 LABELS cpython llvm c wasm wasm_x64)
-RUN(NAME print_float LABELS cpython llvm c wasm wasm_x64)
-RUN(NAME print_list_tuple_01 LABELS cpython llvm c NOFAST)
-RUN(NAME print_list_tuple_02 LABELS cpython llvm c NOFAST)
-RUN(NAME print_list_tuple_03 LABELS cpython llvm c NOFAST)
-RUN(NAME test_list_item_mixed_print LABELS cpython llvm c NOFAST)
+RUN(NAME print_04 LABELS cpython llvm llvm_jit c)
+RUN(NAME print_06 LABELS cpython llvm llvm_jit c)
+RUN(NAME print_05 LABELS cpython llvm llvm_jit c wasm wasm_x64)
+RUN(NAME print_float LABELS cpython llvm llvm_jit c wasm wasm_x64)
+RUN(NAME print_list_tuple_01 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME print_list_tuple_02 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME print_list_tuple_03 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_list_item_mixed_print LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_intrinsic_function_mixed_print LABELS cpython llvm llvm_jit NOFAST)
# CPython and LLVM
-RUN(NAME const_01 LABELS cpython llvm c wasm)
-RUN(NAME const_02 LABELS cpython llvm c wasm)
+RUN(NAME const_01 LABELS cpython llvm llvm_jit c wasm)
+RUN(NAME const_02 LABELS cpython llvm llvm_jit c wasm)
RUN(NAME const_03 LABELS cpython llvm c
EXTRAFILES const_03b.c)
-RUN(NAME const_04 LABELS cpython llvm c)
-RUN(NAME expr_01 LABELS cpython llvm c wasm wasm_x64)
-RUN(NAME expr_02 LABELS cpython llvm c wasm wasm_x64)
-RUN(NAME expr_03 LABELS cpython llvm c wasm wasm_x64)
-RUN(NAME expr_04 LABELS cpython llvm c wasm NOFAST)
-RUN(NAME expr_05 LABELS cpython llvm c NOFAST)
-RUN(NAME expr_06 LABELS cpython llvm c NOFAST)
-RUN(NAME expr_07 LABELS cpython llvm c)
-RUN(NAME expr_08 LABELS llvm c NOFAST)
-RUN(NAME expr_09 LABELS cpython llvm c)
-RUN(NAME expr_10 LABELS cpython llvm c)
-RUN(NAME expr_11 LABELS cpython llvm c wasm)
-RUN(NAME expr_12 LABELS llvm c)
+RUN(NAME const_04 LABELS cpython llvm llvm_jit c)
+RUN(NAME expr_01 LABELS cpython llvm llvm_jit c wasm wasm_x64)
+RUN(NAME expr_02 LABELS cpython llvm llvm_jit c wasm wasm_x64)
+RUN(NAME expr_03 LABELS cpython llvm llvm_jit c wasm wasm_x64)
+RUN(NAME expr_04 LABELS cpython llvm llvm_jit c wasm NOFAST)
+RUN(NAME expr_05 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME expr_06 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME expr_07 LABELS cpython llvm llvm_jit c)
+RUN(NAME expr_08 LABELS llvm llvm_jit c NOFAST)
+RUN(NAME expr_09 LABELS cpython llvm llvm_jit c)
+RUN(NAME expr_10 LABELS cpython llvm llvm_jit c)
+RUN(NAME expr_11 LABELS cpython llvm llvm_jit c wasm)
+RUN(NAME expr_12 LABELS llvm llvm_jit c)
RUN(NAME expr_13 LABELS llvm c
EXTRAFILES expr_13b.c NOFAST)
-RUN(NAME expr_14 LABELS cpython llvm c)
-RUN(NAME expr_15 LABELS cpython llvm c)
-RUN(NAME expr_16 LABELS cpython llvm c)
-RUN(NAME expr_17 LABELS cpython llvm c)
-RUN(NAME expr_18 FAIL LABELS cpython llvm c)
-RUN(NAME expr_19 LABELS cpython llvm c)
-RUN(NAME expr_20 LABELS cpython llvm c)
-RUN(NAME expr_21 LABELS cpython llvm c)
-RUN(NAME expr_22 LABELS cpython llvm c)
-RUN(NAME expr_23 LABELS cpython llvm c)
+RUN(NAME expr_14 LABELS cpython llvm llvm_jit c)
+RUN(NAME expr_15 LABELS cpython llvm llvm_jit c)
+RUN(NAME expr_16 LABELS cpython llvm llvm_jit c)
+RUN(NAME expr_17 LABELS cpython llvm llvm_jit c)
+RUN(NAME expr_18 FAIL LABELS cpython llvm llvm_jit c)
+RUN(NAME expr_19 LABELS cpython llvm llvm_jit c)
+RUN(NAME expr_20 LABELS cpython llvm llvm_jit c)
+RUN(NAME expr_21 LABELS cpython llvm llvm_jit c)
+RUN(NAME expr_22 LABELS cpython llvm llvm_jit c)
+RUN(NAME expr_23 LABELS cpython llvm llvm_jit c)
RUN(NAME expr_24 LABELS cpython wasm) # mandelbrot
-RUN(NAME expr_01u LABELS cpython llvm c NOFAST)
-RUN(NAME expr_02u LABELS cpython llvm c NOFAST)
-RUN(NAME expr_03u LABELS cpython llvm c NOFAST)
-RUN(NAME expr_04u LABELS cpython llvm c)
-
-RUN(NAME loop_01 LABELS cpython llvm c)
-RUN(NAME loop_02 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
-RUN(NAME loop_03 LABELS cpython llvm c wasm wasm_x64)
-RUN(NAME loop_04 LABELS cpython llvm c)
-RUN(NAME loop_05 LABELS cpython llvm c)
-RUN(NAME loop_06 LABELS cpython llvm c NOFAST)
-RUN(NAME loop_07 LABELS cpython llvm c)
-RUN(NAME loop_08 LABELS cpython llvm c)
-RUN(NAME loop_09 LABELS cpython llvm)
-RUN(NAME loop_10 LABELS cpython llvm)
-RUN(NAME if_01 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
-RUN(NAME if_02 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
-RUN(NAME if_03 FAIL LABELS cpython llvm c NOFAST)
-RUN(NAME print_02 LABELS cpython llvm c)
-RUN(NAME test_types_01 LABELS cpython llvm c)
-RUN(NAME test_types_02 LABELS cpython llvm c wasm)
-RUN(NAME test_str_01 LABELS cpython llvm c)
-RUN(NAME test_str_02 LABELS cpython llvm c)
-RUN(NAME test_str_03 LABELS cpython llvm c)
-RUN(NAME test_str_04 LABELS cpython llvm c wasm)
-RUN(NAME test_str_05 LABELS cpython llvm c)
-RUN(NAME test_list_01 LABELS cpython llvm c)
-RUN(NAME test_list_02 LABELS cpython llvm c)
-RUN(NAME test_list_03 LABELS cpython llvm c NOFAST)
-RUN(NAME test_list_04 LABELS cpython llvm c NOFAST)
-RUN(NAME test_list_05 LABELS cpython llvm c NOFAST)
-RUN(NAME test_list_06 LABELS cpython llvm c)
-RUN(NAME test_list_07 LABELS cpython llvm c NOFAST)
-RUN(NAME test_list_08 LABELS cpython llvm c NOFAST)
-RUN(NAME test_list_09 LABELS cpython llvm c NOFAST)
-RUN(NAME test_list_10 LABELS cpython llvm c NOFAST)
-RUN(NAME test_list_11 LABELS cpython llvm c)
-RUN(NAME test_list_section LABELS cpython llvm c NOFAST)
-RUN(NAME test_list_section2 LABELS cpython llvm c NOFAST)
-RUN(NAME test_list_count LABELS cpython llvm)
-RUN(NAME test_list_index LABELS cpython llvm)
-RUN(NAME test_list_index2 LABELS cpython llvm)
-RUN(NAME test_list_repeat LABELS cpython llvm c NOFAST)
-RUN(NAME test_list_repeat2 LABELS cpython llvm c NOFAST)
-RUN(NAME test_list_reverse LABELS cpython llvm)
-RUN(NAME test_list_pop LABELS cpython llvm NOFAST) # TODO: Remove NOFAST from here.
-RUN(NAME test_list_pop2 LABELS cpython llvm NOFAST) # TODO: Remove NOFAST from here.
-RUN(NAME test_list_pop3 LABELS cpython llvm)
-RUN(NAME test_list_compare LABELS cpython llvm)
-RUN(NAME test_list_concat LABELS cpython llvm c NOFAST)
-RUN(NAME test_list_reserve LABELS cpython llvm)
-RUN(NAME test_const_list LABELS cpython llvm)
-RUN(NAME test_tuple_01 LABELS cpython llvm c)
-RUN(NAME test_tuple_02 LABELS cpython llvm c NOFAST)
-RUN(NAME test_tuple_03 LABELS cpython llvm c)
-RUN(NAME test_tuple_04 LABELS cpython llvm c)
-RUN(NAME test_tuple_concat LABELS cpython llvm)
-RUN(NAME test_tuple_nested LABELS cpython llvm)
-RUN(NAME test_dict_01 LABELS cpython llvm c)
-RUN(NAME test_dict_02 LABELS cpython llvm c NOFAST)
-RUN(NAME test_dict_03 LABELS cpython llvm NOFAST)
-RUN(NAME test_dict_04 LABELS cpython llvm NOFAST)
-RUN(NAME test_dict_05 LABELS cpython llvm c)
-RUN(NAME test_dict_06 LABELS cpython llvm c)
-RUN(NAME test_dict_07 LABELS cpython llvm c)
-RUN(NAME test_dict_08 LABELS cpython llvm c)
-RUN(NAME test_dict_09 LABELS cpython llvm c)
-RUN(NAME test_dict_10 LABELS cpython llvm c)
-RUN(NAME test_dict_11 LABELS cpython llvm c)
-RUN(NAME test_dict_12 LABELS cpython llvm c)
-RUN(NAME test_dict_13 LABELS cpython llvm c)
-RUN(NAME test_dict_bool LABELS cpython llvm)
-RUN(NAME test_dict_increment LABELS cpython llvm)
-RUN(NAME test_dict_keys_values LABELS cpython llvm)
-RUN(NAME test_dict_nested1 LABELS cpython llvm)
-RUN(NAME test_set_len LABELS cpython llvm)
-RUN(NAME test_set_add LABELS cpython llvm)
-RUN(NAME test_set_remove LABELS cpython llvm)
-RUN(NAME test_set_discard LABELS cpython llvm)
-RUN(NAME test_global_set LABELS cpython llvm)
-RUN(NAME test_for_loop LABELS cpython llvm c)
-RUN(NAME modules_01 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
-RUN(NAME modules_02 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
-RUN(NAME test_import_01 LABELS cpython llvm c)
-RUN(NAME test_import_02 LABELS cpython llvm c)
-RUN(NAME test_import_03 LABELS cpython llvm c)
-RUN(NAME test_import_04 LABELS cpython llvm c)
-RUN(NAME test_import_05 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
-RUN(NAME test_import_06 LABELS cpython llvm)
-RUN(NAME test_import_07 LABELS cpython llvm c)
-RUN(NAME test_math LABELS cpython llvm NOFAST)
-RUN(NAME test_numpy_01 LABELS cpython llvm c)
-RUN(NAME test_numpy_02 LABELS cpython llvm c)
-RUN(NAME test_numpy_03 LABELS cpython llvm c)
-RUN(NAME test_numpy_04 LABELS cpython llvm c)
-RUN(NAME elemental_01 LABELS cpython llvm c NOFAST)
-RUN(NAME elemental_02 LABELS cpython llvm c NOFAST)
-RUN(NAME elemental_03 LABELS cpython llvm c NOFAST)
-RUN(NAME elemental_04 LABELS cpython llvm c NOFAST)
-RUN(NAME elemental_05 LABELS cpython llvm c NOFAST)
-RUN(NAME elemental_06 LABELS cpython llvm c NOFAST)
-RUN(NAME elemental_07 LABELS cpython llvm c NOFAST)
-RUN(NAME elemental_08 LABELS cpython llvm c NOFAST)
-RUN(NAME elemental_09 LABELS cpython llvm c NOFAST)
-RUN(NAME elemental_10 LABELS cpython llvm c NOFAST)
-RUN(NAME elemental_11 LABELS cpython llvm c NOFAST)
-RUN(NAME elemental_12 LABELS cpython llvm c NOFAST)
-RUN(NAME elemental_13 LABELS cpython llvm c NOFAST)
-RUN(NAME test_random LABELS cpython llvm NOFAST)
-RUN(NAME test_random_02 LABELS cpython llvm NOFAST)
-RUN(NAME test_os LABELS cpython llvm c NOFAST)
-RUN(NAME test_builtin LABELS cpython llvm c)
-RUN(NAME test_builtin_abs LABELS cpython llvm c)
-RUN(NAME test_builtin_bool LABELS cpython llvm c)
-RUN(NAME test_builtin_pow LABELS cpython llvm c NO_WARNINGS)
-RUN(NAME test_builtin_int LABELS cpython llvm c)
-RUN(NAME test_builtin_len LABELS cpython llvm c)
-RUN(NAME test_builtin_str LABELS cpython llvm c)
-RUN(NAME test_builtin_oct LABELS cpython llvm c)
-RUN(NAME test_builtin_hex LABELS cpython llvm c)
-RUN(NAME test_builtin_bin LABELS cpython llvm c)
-RUN(NAME test_builtin_float LABELS cpython llvm c)
-RUN(NAME test_builtin_str_02 LABELS cpython llvm c NOFAST)
-RUN(NAME test_builtin_round LABELS cpython llvm c)
-RUN(NAME test_builtin_divmod LABELS cpython llvm c)
-RUN(NAME test_builtin_sum LABELS cpython llvm c)
-RUN(NAME test_math1 LABELS cpython llvm c)
-RUN(NAME test_math_02 LABELS cpython llvm NOFAST)
-RUN(NAME test_math_03 LABELS llvm) #1595: TODO: Test using CPython (3.11 recommended)
-RUN(NAME test_pass_compare LABELS cpython llvm c)
-RUN(NAME test_c_interop_01 LABELS cpython llvm c)
+RUN(NAME expr_01u LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME expr_02u LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME expr_03u LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME expr_04u LABELS cpython llvm llvm_jit c)
+
+RUN(NAME list_01 LABELS cpython llvm llvm_jit)
+
+RUN(NAME loop_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME loop_02 LABELS cpython llvm llvm_jit c wasm wasm_x86 wasm_x64)
+RUN(NAME loop_03 LABELS cpython llvm llvm_jit c wasm wasm_x64)
+RUN(NAME loop_04 LABELS cpython llvm llvm_jit c)
+RUN(NAME loop_05 LABELS cpython llvm llvm_jit c)
+RUN(NAME loop_06 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME loop_07 LABELS cpython llvm llvm_jit c)
+RUN(NAME loop_08 LABELS cpython llvm llvm_jit c)
+RUN(NAME loop_09 LABELS cpython llvm llvm_jit)
+RUN(NAME loop_10 LABELS cpython llvm llvm_jit)
+RUN(NAME loop_11 LABELS cpython llvm llvm_jit)
+RUN(NAME if_01 LABELS cpython llvm llvm_jit c wasm wasm_x86 wasm_x64)
+RUN(NAME if_02 LABELS cpython llvm llvm_jit c wasm wasm_x86 wasm_x64)
+RUN(NAME if_03 FAIL LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME print_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_types_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_types_02 LABELS cpython llvm llvm_jit c wasm)
+RUN(NAME test_str_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_str_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_str_03 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_str_04 LABELS cpython llvm llvm_jit c wasm)
+RUN(NAME test_str_05 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_list_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_list_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_list_03 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_list_04 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_list_05 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_list_06 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_list_07 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_list_08 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_list_09 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_list_10 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_list_11 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_list_section LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_list_section2 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_list_count LABELS cpython llvm llvm_jit)
+RUN(NAME test_list_index LABELS cpython llvm llvm_jit)
+RUN(NAME test_list_index2 LABELS cpython llvm llvm_jit)
+RUN(NAME test_list_repeat LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_list_repeat2 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_list_reverse LABELS cpython llvm llvm_jit)
+RUN(NAME test_list_pop LABELS cpython llvm llvm_jit NOFAST) # TODO: Remove NOFAST from here.
+RUN(NAME test_list_pop2 LABELS cpython llvm llvm_jit NOFAST) # TODO: Remove NOFAST from here.
+RUN(NAME test_list_pop3 LABELS cpython llvm llvm_jit)
+RUN(NAME test_list_compare LABELS cpython llvm llvm_jit)
+RUN(NAME test_list_compare2 LABELS cpython llvm llvm_jit)
+RUN(NAME test_list_concat LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_list_reserve LABELS cpython llvm llvm_jit)
+RUN(NAME test_const_list LABELS cpython llvm llvm_jit)
+RUN(NAME test_const_access LABELS cpython llvm llvm_jit)
+RUN(NAME test_tuple_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_tuple_02 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_tuple_03 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_tuple_04 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_tuple_concat LABELS cpython llvm llvm_jit)
+RUN(NAME test_tuple_nested LABELS cpython llvm llvm_jit)
+RUN(NAME test_const_dict LABELS cpython llvm llvm_jit)
+RUN(NAME test_dict_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_dict_02 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_dict_03 LABELS cpython llvm llvm_jit NOFAST)
+RUN(NAME test_dict_04 LABELS cpython llvm llvm_jit NOFAST)
+RUN(NAME test_dict_05 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_dict_06 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_dict_07 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_dict_08 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_dict_09 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_dict_10 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_dict_11 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_dict_12 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_dict_13 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_dict_bool LABELS cpython llvm llvm_jit)
+RUN(NAME test_dict_increment LABELS cpython llvm llvm_jit)
+RUN(NAME test_dict_keys_values LABELS cpython llvm llvm_jit)
+RUN(NAME test_dict_nested1 LABELS cpython llvm llvm_jit)
+RUN(NAME test_dict_clear LABELS cpython llvm)
+RUN(NAME test_set_len LABELS cpython llvm llvm_jit)
+RUN(NAME test_set_add LABELS cpython llvm llvm_jit)
+RUN(NAME test_set_remove LABELS cpython llvm llvm_jit)
+RUN(NAME test_set_discard LABELS cpython llvm llvm_jit)
+RUN(NAME test_set_clear LABELS cpython llvm)
+RUN(NAME test_set_pop LABELS cpython llvm)
+RUN(NAME test_global_set LABELS cpython llvm llvm_jit)
+RUN(NAME test_for_loop LABELS cpython llvm llvm_jit c)
+RUN(NAME modules_01 LABELS cpython llvm llvm_jit c wasm wasm_x86 wasm_x64)
+RUN(NAME modules_02 LABELS cpython llvm llvm_jit c wasm wasm_x86 wasm_x64)
+RUN(NAME test_import_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_import_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_import_03 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_import_04 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_import_05 LABELS cpython llvm llvm_jit c wasm wasm_x86 wasm_x64)
+RUN(NAME test_import_06 LABELS cpython llvm llvm_jit)
+RUN(NAME test_import_07 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_math LABELS cpython llvm llvm_jit NOFAST)
+RUN(NAME test_membership_01 LABELS cpython llvm)
+RUN(NAME test_numpy_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_numpy_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_numpy_03 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_numpy_04 LABELS cpython llvm llvm_jit c)
+RUN(NAME elemental_01 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME elemental_02 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME elemental_03 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME elemental_04 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME elemental_05 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME elemental_06 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME elemental_07 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME elemental_08 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME elemental_09 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME elemental_10 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME elemental_11 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME elemental_12 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME elemental_13 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_random LABELS cpython llvm llvm_jit NOFAST)
+RUN(NAME test_random_02 LABELS cpython llvm llvm_jit NOFAST)
+RUN(NAME test_os LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_builtin LABELS cpython llvm llvm_jit c)
+RUN(NAME test_builtin_abs LABELS cpython llvm llvm_jit c)
+RUN(NAME test_builtin_bool LABELS cpython llvm llvm_jit c)
+RUN(NAME test_builtin_pow LABELS cpython llvm llvm_jit c EXTRA_ARGS --no-warnings)
+RUN(NAME test_builtin_int LABELS cpython llvm llvm_jit c)
+RUN(NAME test_builtin_len LABELS cpython llvm llvm_jit c)
+RUN(NAME test_builtin_str LABELS cpython llvm llvm_jit c)
+RUN(NAME test_builtin_oct LABELS cpython llvm llvm_jit c)
+RUN(NAME test_builtin_hex LABELS cpython llvm llvm_jit c)
+RUN(NAME test_builtin_bin LABELS cpython llvm llvm_jit c)
+RUN(NAME test_builtin_float LABELS cpython llvm llvm_jit c)
+RUN(NAME test_builtin_str_02 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_builtin_round LABELS cpython llvm llvm_jit c)
+RUN(NAME test_builtin_divmod LABELS cpython llvm llvm_jit c)
+RUN(NAME test_builtin_sum LABELS cpython llvm llvm_jit c)
+RUN(NAME test_math1 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_math_02 LABELS cpython llvm llvm_jit NOFAST)
+RUN(NAME test_math_03 LABELS llvm llvm_jit) #1595: TODO: Test using CPython (3.11 recommended)
+RUN(NAME test_pass_compare LABELS cpython llvm llvm_jit c)
+RUN(NAME test_c_interop_01 LABELS cpython llvm llvm_jit c)
RUN(NAME test_c_interop_02 LABELS cpython llvm c
EXTRAFILES test_c_interop_02b.c)
RUN(NAME test_c_interop_03 LABELS cpython llvm c
EXTRAFILES test_c_interop_03b.c)
-RUN(NAME test_c_interop_04 LABELS cpython llvm c
+RUN(NAME test_c_interop_04 LABELS cpython llvm llvm_jit c
EXTRAFILES test_c_interop_04b.c)
RUN(NAME test_c_interop_05 LABELS llvm c
EXTRAFILES test_c_interop_05b.c)
@@ -650,192 +658,196 @@ RUN(NAME bindc_05 LABELS llvm c
EXTRAFILES bindc_05b.c)
RUN(NAME bindc_06 LABELS llvm c
EXTRAFILES bindc_06b.c)
-RUN(NAME bindpy_01 LABELS cpython c_py ENABLE_CPYTHON NOFAST COPY_TO_BIN bindpy_01_module.py)
-RUN(NAME bindpy_02 LABELS cpython c_py LINK_NUMPY COPY_TO_BIN bindpy_02_module.py)
-RUN(NAME bindpy_03 LABELS cpython c_py LINK_NUMPY NOFAST COPY_TO_BIN bindpy_03_module.py)
-RUN(NAME bindpy_04 LABELS cpython c_py LINK_NUMPY NOFAST COPY_TO_BIN bindpy_04_module.py)
-RUN(NAME bindpy_05 LABELS llvm_py c_py ENABLE_CPYTHON COPY_TO_BIN bindpy_05_module.py REQ_PY_VER 3.10)
-RUN(NAME test_generics_01 LABELS cpython llvm c NOFAST)
-RUN(NAME test_cmath LABELS cpython llvm c NOFAST)
-RUN(NAME test_complex_01 LABELS cpython llvm c wasm wasm_x64)
-RUN(NAME test_complex_02 LABELS cpython llvm c)
-RUN(NAME test_ConstantEllipsis LABLES cpython llvm c)
-RUN(NAME test_max_min LABELS cpython llvm c)
-RUN(NAME test_global LABELS cpython llvm c)
-RUN(NAME test_global_decl LABELS cpython llvm c)
-RUN(NAME test_ifexp_01 LABELS cpython llvm c)
-RUN(NAME test_ifexp_02 LABELS cpython llvm c)
-RUN(NAME test_ifexp_03 LABELS cpython llvm c)
-RUN(NAME test_unary_op_01 LABELS cpython llvm c) # unary minus
-RUN(NAME test_unary_op_02 LABELS cpython llvm c) # unary plus
-RUN(NAME test_unary_op_03 LABELS cpython llvm c wasm) # unary bitinvert
-RUN(NAME test_unary_op_04 LABELS cpython llvm c) # unary bitinvert
-RUN(NAME test_unary_op_05 LABELS cpython llvm c) # unsigned unary minus, plus
-RUN(NAME test_unary_op_06 LABELS cpython llvm c) # unsigned unary bitnot
-RUN(NAME test_unsigned_01 LABELS cpython llvm c) # unsigned bitshift left, right
-RUN(NAME test_unsigned_02 LABELS cpython llvm c)
-RUN(NAME test_unsigned_03 LABELS cpython llvm c)
-RUN(NAME test_bool_binop LABELS cpython llvm c)
-RUN(NAME test_issue_518 LABELS cpython llvm c NOFAST)
-RUN(NAME structs_01 LABELS cpython llvm c)
-RUN(NAME structs_02 LABELS cpython llvm c)
-RUN(NAME structs_02b LABELS cpython llvm c NOFAST)
-RUN(NAME structs_03 LABELS llvm c)
-RUN(NAME structs_04 LABELS cpython llvm c)
-RUN(NAME structs_05 LABELS cpython llvm c)
-RUN(NAME structs_06 LABELS cpython llvm c)
+RUN(NAME bindpy_01 LABELS cpython c_py EXTRA_ARGS --enable-cpython NOFAST COPY_TO_BIN bindpy_01_module.py)
+RUN(NAME bindpy_02 LABELS cpython c_py EXTRA_ARGS --link-numpy COPY_TO_BIN bindpy_02_module.py)
+RUN(NAME bindpy_03 LABELS cpython c_py EXTRA_ARGS --link-numpy NOFAST COPY_TO_BIN bindpy_03_module.py)
+RUN(NAME bindpy_04 LABELS cpython c_py EXTRA_ARGS --link-numpy NOFAST COPY_TO_BIN bindpy_04_module.py)
+RUN(NAME bindpy_05 LABELS llvm_py c_py EXTRA_ARGS --enable-cpython COPY_TO_BIN bindpy_05_module.py REQ_PY_VER 3.10)
+RUN(NAME test_generics_01 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_cmath LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_complex_01 LABELS cpython llvm llvm_jit c wasm wasm_x64)
+RUN(NAME test_complex_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_ConstantEllipsis LABLES cpython llvm llvm_jit c)
+RUN(NAME test_max_min LABELS cpython llvm llvm_jit c)
+RUN(NAME test_global LABELS cpython llvm llvm_jit c)
+RUN(NAME test_global_decl LABELS cpython llvm llvm_jit c)
+RUN(NAME test_ifexp_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_ifexp_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_ifexp_03 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_unary_op_01 LABELS cpython llvm llvm_jit c) # unary minus
+RUN(NAME test_unary_op_02 LABELS cpython llvm llvm_jit c) # unary plus
+RUN(NAME test_unary_op_03 LABELS cpython llvm llvm_jit c wasm) # unary bitinvert
+RUN(NAME test_unary_op_04 LABELS cpython llvm llvm_jit c) # unary bitinvert
+RUN(NAME test_unary_op_05 LABELS cpython llvm llvm_jit c) # unsigned unary minus, plus
+RUN(NAME test_unary_op_06 LABELS cpython llvm llvm_jit c) # unsigned unary bitnot
+RUN(NAME test_unsigned_01 LABELS cpython llvm llvm_jit c) # unsigned bitshift left, right
+RUN(NAME test_unsigned_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_unsigned_03 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_bool_binop LABELS cpython llvm llvm_jit c)
+RUN(NAME test_issue_518 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME structs_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_02b LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME structs_03 LABELS llvm llvm_jit c)
+RUN(NAME structs_04 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_05 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_06 LABELS cpython llvm llvm_jit c)
RUN(NAME structs_07 LABELS llvm c
EXTRAFILES structs_07b.c)
-RUN(NAME structs_08 LABELS cpython llvm c)
-RUN(NAME structs_09 LABELS cpython llvm c)
-RUN(NAME structs_10 LABELS cpython llvm c NOFAST)
-RUN(NAME structs_11 LABELS cpython llvm c)
-RUN(NAME structs_12 LABELS cpython llvm c)
+RUN(NAME structs_08 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_09 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_10 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME structs_11 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_12 LABELS cpython llvm llvm_jit c)
RUN(NAME structs_13 LABELS llvm c
EXTRAFILES structs_13b.c)
-RUN(NAME structs_14 LABELS cpython llvm c)
-RUN(NAME structs_15 LABELS cpython llvm c)
-RUN(NAME structs_16 LABELS cpython llvm c)
-RUN(NAME structs_17 LABELS cpython llvm c)
+RUN(NAME structs_14 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_15 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_16 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_17 LABELS cpython llvm llvm_jit c)
RUN(NAME structs_18 LABELS cpython llvm c
EXTRAFILES structs_18b.c)
RUN(NAME structs_19 LABELS cpython llvm c
EXTRAFILES structs_19b.c)
RUN(NAME structs_20 LABELS cpython llvm c
EXTRAFILES structs_20b.c)
-RUN(NAME structs_21 LABELS cpython llvm c)
-RUN(NAME structs_22 LABELS cpython llvm c NOFAST)
-RUN(NAME structs_23 LABELS cpython llvm c NOFAST)
-RUN(NAME structs_24 LABELS cpython llvm c)
-RUN(NAME structs_25 LABELS cpython llvm c)
-RUN(NAME structs_26 LABELS cpython llvm c)
-RUN(NAME structs_27 LABELS cpython llvm c)
-RUN(NAME structs_28 LABELS cpython llvm c)
-RUN(NAME structs_29 LABELS cpython llvm)
-RUN(NAME structs_30 LABELS cpython llvm c)
-RUN(NAME structs_31 LABELS cpython llvm c)
-RUN(NAME structs_32 LABELS cpython llvm c)
-RUN(NAME structs_33 LABELS cpython llvm c)
-RUN(NAME structs_34 LABELS cpython llvm c)
-RUN(NAME structs_35 LABELS cpython llvm)
-
-RUN(NAME symbolics_01 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_02 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_03 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_04 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_05 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_06 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_07 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_08 LABELS cpython_sym c_sym llvm_sym)
-RUN(NAME symbolics_09 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_10 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_11 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_12 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_13 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_14 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME test_gruntz LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_15 LABELS c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_16 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_17 LABELS cpython_sym c_sym llvm_sym NOFAST)
-RUN(NAME symbolics_18 LABELS cpython_sym c_sym llvm_sym NOFAST)
+RUN(NAME structs_21 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_22 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME structs_23 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME structs_24 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_25 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_26 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_27 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_28 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_29 LABELS cpython llvm llvm_jit)
+RUN(NAME structs_30 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_31 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_32 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_33 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_34 LABELS cpython llvm llvm_jit c)
+RUN(NAME structs_35 LABELS cpython llvm llvm_jit)
+
+RUN(NAME symbolics_01 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_02 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_03 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_04 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_05 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_06 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_07 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_08 LABELS cpython_sym c_sym llvm_sym llvm_jit EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_09 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_10 LABELS cpython_sym c_sym llvm_sym NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_11 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_12 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_13 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_14 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME test_gruntz LABELS cpython_sym c_sym llvm_sym NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_15 LABELS c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_16 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_17 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME symbolics_18 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+RUN(NAME gruntz_demo3 LABELS cpython_sym c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
RUN(NAME sizeof_01 LABELS llvm c
EXTRAFILES sizeof_01b.c)
-RUN(NAME sizeof_02 LABELS cpython llvm c)
-RUN(NAME enum_01 LABELS cpython llvm c)
-RUN(NAME enum_02 LABELS cpython llvm)
-RUN(NAME enum_03 LABELS cpython llvm c)
-RUN(NAME enum_04 LABELS cpython llvm c)
+RUN(NAME sizeof_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME enum_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME enum_02 LABELS cpython llvm llvm_jit)
+RUN(NAME enum_03 LABELS cpython llvm llvm_jit c)
+RUN(NAME enum_04 LABELS cpython llvm llvm_jit c)
RUN(NAME enum_05 LABELS llvm c
EXTRAFILES enum_05b.c)
-RUN(NAME enum_06 LABELS cpython llvm c)
+RUN(NAME enum_06 LABELS cpython llvm llvm_jit c)
RUN(NAME enum_07 IMPORT_PATH ..
- LABELS cpython llvm c)
-RUN(NAME union_01 LABELS cpython llvm c)
-RUN(NAME union_02 LABELS cpython llvm c NOFAST)
-RUN(NAME union_03 LABELS cpython llvm c)
+ LABELS cpython llvm llvm_jit c)
+RUN(NAME union_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME union_02 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME union_03 LABELS cpython llvm llvm_jit c)
RUN(NAME union_04 IMPORT_PATH ..
- LABELS cpython llvm c)
-RUN(NAME test_str_to_int LABELS cpython llvm c)
-RUN(NAME test_platform LABELS cpython llvm c)
-RUN(NAME test_vars_01 LABELS cpython llvm)
-RUN(NAME test_version LABELS cpython llvm)
-RUN(NAME logical_binop1 LABELS cpython llvm)
-RUN(NAME test_logical_compare LABELS cpython llvm)
-RUN(NAME test_logical_assignment LABELS cpython llvm)
-RUN(NAME vec_01 LABELS cpython llvm c NOFAST)
-RUN(NAME test_str_comparison LABELS cpython llvm c wasm)
-RUN(NAME test_bit_length LABELS cpython llvm c)
-RUN(NAME str_to_list_cast LABELS cpython llvm c)
-RUN(NAME cast_01 LABELS cpython llvm c)
-RUN(NAME cast_02 LABELS cpython llvm c)
-RUN(NAME test_sys_01 LABELS cpython llvm c NOFAST)
-RUN(NAME intent_01 LABELS cpython llvm)
-
-
-RUN(NAME test_package_01 LABELS cpython llvm NOFAST)
-RUN(NAME test_pkg_lpdraw LABELS cpython llvm wasm)
-RUN(NAME test_pkg_lnn_01 LABELS cpython llvm NOFAST)
-RUN(NAME test_pkg_lnn_02 LABELS cpython llvm NOFAST)
-RUN(NAME test_pkg_lpconvexhull LABELS cpython llvm c NOFAST)
-
-RUN(NAME generics_01 LABELS cpython llvm c)
-RUN(NAME generics_02 LABELS cpython llvm c)
-RUN(NAME generics_array_01 LABELS cpython llvm c)
-RUN(NAME generics_array_02 LABELS cpython llvm c)
-RUN(NAME generics_array_03 LABELS cpython llvm c)
-RUN(NAME generics_list_01 LABELS cpython llvm c)
-RUN(NAME test_statistics_01 LABELS cpython llvm NOFAST)
-RUN(NAME test_statistics_02 LABELS cpython llvm NOFAST REQ_PY_VER 3.10)
-RUN(NAME test_str_attributes LABELS cpython llvm c)
-RUN(NAME kwargs_01 LABELS cpython llvm c NOFAST)
-
-RUN(NAME func_inline_01 LABELS llvm c wasm)
-RUN(NAME func_inline_02 LABELS cpython llvm c)
-RUN(NAME func_static_01 LABELS cpython llvm c wasm)
-RUN(NAME func_static_02 LABELS cpython llvm c wasm)
-RUN(NAME func_dep_03 LABELS cpython llvm c)
-RUN(NAME func_dep_04 LABELS cpython llvm c)
-RUN(NAME func_internal_def_01 LABELS cpython llvm NOFAST)
-RUN(NAME func_01 LABELS cpython llvm)
-RUN(NAME func_02 LABELS c_sym llvm_sym NOFAST)
-
-RUN(NAME float_01 LABELS cpython llvm c wasm wasm_x64)
-RUN(NAME recursive_01 LABELS cpython llvm c wasm wasm_x64 wasm_x86)
-RUN(NAME comp_01 LABELS cpython llvm c wasm wasm_x64)
-RUN(NAME bit_operations_i32 LABELS cpython llvm c wasm wasm_x64)
-RUN(NAME bit_operations_i64 LABELS cpython llvm c wasm)
+ LABELS cpython llvm llvm_jit c)
+RUN(NAME test_str_to_int LABELS cpython llvm llvm_jit c)
+RUN(NAME test_platform LABELS cpython llvm llvm_jit c)
+RUN(NAME test_vars_01 LABELS cpython llvm llvm_jit)
+RUN(NAME test_version LABELS cpython llvm llvm_jit)
+RUN(NAME logical_binop1 LABELS cpython llvm llvm_jit)
+RUN(NAME test_logical_compare LABELS cpython llvm llvm_jit) # TODO: Add C backend after fixing issue #2708
+RUN(NAME test_logical_assignment LABELS cpython llvm llvm_jit) # TODO: Add C backend after fixing issue #2708
+RUN(NAME vec_01 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME test_str_comparison LABELS cpython llvm llvm_jit c wasm)
+RUN(NAME test_bit_length LABELS cpython c) # FIXME: This test fails on llvm & llvm_jit
+RUN(NAME str_to_list_cast LABELS cpython llvm llvm_jit c)
+RUN(NAME cast_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME cast_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_sys_01 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME intent_01 LABELS cpython llvm llvm_jit)
+
+
+RUN(NAME test_package_01 LABELS cpython llvm llvm_jit NOFAST)
+RUN(NAME test_pkg_lpdraw LABELS cpython llvm llvm_jit wasm)
+RUN(NAME test_pkg_lnn_01 LABELS cpython llvm llvm_jit NOFAST)
+RUN(NAME test_pkg_lnn_02 LABELS cpython llvm llvm_jit NOFAST)
+RUN(NAME test_pkg_lpconvexhull LABELS cpython llvm llvm_jit c NOFAST)
+
+RUN(NAME generics_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME generics_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME generics_array_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME generics_array_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME generics_array_03 LABELS cpython llvm llvm_jit c)
+RUN(NAME generics_list_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME test_statistics_01 LABELS cpython llvm llvm_jit NOFAST)
+RUN(NAME test_statistics_02 LABELS cpython llvm llvm_jit NOFAST REQ_PY_VER 3.10)
+RUN(NAME test_str_attributes LABELS cpython llvm llvm_jit c)
+RUN(NAME kwargs_01 LABELS cpython llvm llvm_jit c NOFAST)
+RUN(NAME def_func_01 LABELS cpython llvm llvm_jit c)
+
+RUN(NAME func_inline_01 LABELS llvm llvm_jit c wasm)
+RUN(NAME func_inline_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME func_static_01 LABELS cpython llvm llvm_jit c wasm)
+RUN(NAME func_static_02 LABELS cpython llvm llvm_jit c wasm)
+RUN(NAME func_dep_03 LABELS cpython llvm llvm_jit c)
+RUN(NAME func_dep_04 LABELS cpython llvm llvm_jit c)
+RUN(NAME func_internal_def_01 LABELS cpython llvm llvm_jit NOFAST)
+RUN(NAME func_01 LABELS cpython llvm llvm_jit)
+RUN(NAME func_02 LABELS c_sym llvm_sym llvm_jit NOFAST EXTRA_ARGS --enable-symengine)
+
+RUN(NAME float_01 LABELS cpython llvm llvm_jit c wasm wasm_x64)
+RUN(NAME recursive_01 LABELS cpython llvm llvm_jit c wasm wasm_x64 wasm_x86)
+RUN(NAME comp_01 LABELS cpython llvm llvm_jit c wasm wasm_x64)
+RUN(NAME bit_operations_i32 LABELS cpython llvm llvm_jit c wasm wasm_x64)
+RUN(NAME bit_operations_i64 LABELS cpython llvm llvm_jit c wasm)
RUN(NAME test_argv_01 LABELS cpython llvm NOFAST)
-RUN(NAME global_syms_01 LABELS cpython llvm c)
-RUN(NAME global_syms_02 LABELS cpython llvm c)
-RUN(NAME global_syms_03_b LABELS cpython llvm c)
-RUN(NAME global_syms_03_c LABELS cpython llvm c)
-RUN(NAME global_syms_04 LABELS cpython llvm c wasm wasm_x64)
-RUN(NAME global_syms_05 LABELS cpython llvm c)
-RUN(NAME global_syms_06 LABELS cpython llvm c)
+RUN(NAME global_syms_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME global_syms_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME global_syms_03_b LABELS cpython llvm llvm_jit c)
+RUN(NAME global_syms_03_c LABELS cpython llvm llvm_jit c)
+RUN(NAME global_syms_04 LABELS cpython llvm llvm_jit c wasm wasm_x64)
+RUN(NAME global_syms_05 LABELS cpython llvm llvm_jit c)
+RUN(NAME global_syms_06 LABELS cpython llvm llvm_jit c)
-RUN(NAME callback_01 LABELS cpython llvm c)
-RUN(NAME callback_02 LABELS cpython llvm c)
-RUN(NAME callback_03 LABELS cpython llvm c)
+RUN(NAME callback_01 LABELS cpython llvm llvm_jit c)
+RUN(NAME callback_02 LABELS cpython llvm llvm_jit c)
+RUN(NAME callback_03 LABELS cpython llvm llvm_jit c)
-RUN(NAME lambda_01 LABELS cpython llvm)
+RUN(NAME lambda_01 LABELS cpython llvm llvm_jit)
-RUN(NAME c_mangling LABELS cpython llvm c)
+RUN(NAME c_mangling LABELS cpython llvm llvm_jit c)
+RUN(NAME class_01 LABELS cpython llvm llvm_jit)
# callback_04 is to test emulation. So just run with cpython
RUN(NAME callback_04 IMPORT_PATH .. LABELS cpython)
# Intrinsic Functions
-RUN(NAME intrinsics_01 LABELS cpython llvm NOFAST) # any
-RUN(NAME intrinsics_02 LABELS cpython llvm c) # floordiv
-RUN(NAME test_builtin_type LABELS cpython llvm c) # type
+RUN(NAME intrinsics_01 LABELS cpython llvm llvm_jit NOFAST) # any
+RUN(NAME intrinsics_02 LABELS cpython llvm llvm_jit c) # floordiv
+RUN(NAME test_builtin_type LABELS cpython llvm llvm_jit c) # type
+RUN(NAME test_builtin_type_set LABELS cpython llvm llvm_jit) # type (specifically for `set`)
# lpython decorator
RUN(NAME lpython_decorator_01 LABELS cpython)
RUN(NAME lpython_decorator_02 LABELS cpython)
-COMPILE(NAME import_order_01 LABELS cpython llvm c) # any
+COMPILE(NAME import_order_01 LABELS cpython llvm llvm_jit c) # any
# LPython emulation mode
RUN(NAME lpython_emulation_01 LABELS cpython NOMOD)
diff --git a/integration_tests/class_01.py b/integration_tests/class_01.py
new file mode 100644
index 0000000000..103cb612c3
--- /dev/null
+++ b/integration_tests/class_01.py
@@ -0,0 +1,28 @@
+from lpython import i32,f64
+from math import sqrt
+
+class coord:
+ def __init__(self: "coord"):
+ self.x: i32 = 3
+ self.y: i32 = 4
+
+def main():
+ p1: coord = coord()
+ sq_dist : i32 = p1.x*p1.x + p1.y*p1.y
+ dist : f64 = sqrt(f64(sq_dist))
+ print("Squared Distance from origin = ", sq_dist)
+ assert sq_dist == 25
+ print("Distance from origin = ", dist)
+ assert dist == f64(5)
+ print("p1.x = 6")
+ print("p1.y = 8")
+ p1.x = i32(6)
+ p1.y = 8
+ sq_dist = p1.x*p1.x + p1.y*p1.y
+ dist = sqrt(f64(sq_dist))
+ print("Squared Distance from origin = ", sq_dist)
+ assert sq_dist == 100
+ print("Distance from origin = ", dist)
+ assert dist == f64(10)
+
+main()
diff --git a/integration_tests/def_func_01.py b/integration_tests/def_func_01.py
new file mode 100644
index 0000000000..2564cff13e
--- /dev/null
+++ b/integration_tests/def_func_01.py
@@ -0,0 +1,76 @@
+from lpython import i32,i64
+
+def factorial_1(x: i32, y:i32 =1) ->i32 :
+ if x <= 1:
+ return y
+ return x * factorial_1(x-1)
+
+def factorial_2(x: i32, y:i32=3 ,z:i32 =2) ->i32:
+ if x ==4:
+ return x * y * z
+ return x * factorial_2(x-1)
+
+def default_func(x : str ="Hello", y : str = " ", z : str = "World") ->str:
+ return x + y + z
+
+
+def even_positions(iterator : i32, to_add : str = "?")-> str:
+ if (iterator == 10): return ""
+ if iterator%2 == 0 :
+ return to_add + even_positions(iterator+1,"X")
+ return to_add +even_positions(iterator+1)
+
+
+
+def test_factorial_1():
+ test_00 : i32 = factorial_1(1)
+ print("test_00 is =>", test_00)
+ assert test_00 == 1
+
+ test_01 : i32 = factorial_1(5,0)
+ print("test_01 is =>", test_01)
+ assert test_01 == 120
+
+ test_02 : i32 = factorial_1(1,5555)
+ print("test_02 is =>", test_02)
+ assert test_02 == 5555
+
+def test_factorial_2():
+ test_03 : i32 =factorial_2(5,99999,99999)
+ print("test_03 is =>", test_03)
+ assert test_03 == 120
+
+ test_04 : i32 = factorial_2(4,-1,100)
+ print("test_04 is =>", test_04)
+ assert test_04 == -400
+
+def test_default_func():
+ test_05 :str = default_func()
+ print("test_05 is =>", test_05)
+ assert test_05 == "Hello World"
+
+ test_06 :str = default_func(y = "|||",x="Hi")
+ print("test_06 is =>", test_06)
+ assert test_06 == "Hi|||World"
+
+ test_07 :str = default_func(y = "++",z = "LPython")
+ print("test_07 is =>", test_07)
+ assert test_07 == "Hello++LPython"
+
+ test_8 :str = default_func("Welcome",z = "LPython")
+ print("test_8 is =>", test_8)
+ assert test_8 == "Welcome LPython"
+
+def test_even_positions():
+ test_09 : str = even_positions(0)
+ print("test_09 is =>", test_09)
+ assert test_09 == "?X?X?X?X?X"
+
+ test_10 : str = even_positions(0,"W")
+ print("test_10 is =>", test_10)
+ assert test_10 == "WX?X?X?X?X"
+
+test_factorial_1()
+test_factorial_2()
+test_default_func()
+test_even_positions()
diff --git a/integration_tests/gruntz_demo.py b/integration_tests/gruntz_demo.py
new file mode 100644
index 0000000000..6beb38f330
--- /dev/null
+++ b/integration_tests/gruntz_demo.py
@@ -0,0 +1,399 @@
+"""
+Limits
+======
+
+Implemented according to the PhD thesis
+https://www.cybertester.com/data/gruntz.pdf, which contains very thorough
+descriptions of the algorithm including many examples. We summarize here
+the gist of it.
+
+All functions are sorted according to how rapidly varying they are at
+infinity using the following rules. Any two functions f and g can be
+compared using the properties of L:
+
+L=lim log|f(x)| / log|g(x)| (for x -> oo)
+
+We define >, < ~ according to::
+
+ 1. f > g .... L=+-oo
+
+ we say that:
+ - f is greater than any power of g
+ - f is more rapidly varying than g
+ - f goes to infinity/zero faster than g
+
+ 2. f < g .... L=0
+
+ we say that:
+ - f is lower than any power of g
+
+ 3. f ~ g .... L!=0, +-oo
+
+ we say that:
+ - both f and g are bounded from above and below by suitable integral
+ powers of the other
+
+Examples
+========
+::
+ 2 < x < exp(x) < exp(x**2) < exp(exp(x))
+ 2 ~ 3 ~ -5
+ x ~ x**2 ~ x**3 ~ 1/x ~ x**m ~ -x
+ exp(x) ~ exp(-x) ~ exp(2x) ~ exp(x)**2 ~ exp(x+exp(-x))
+ f ~ 1/f
+
+So we can divide all the functions into comparability classes (x and x^2
+belong to one class, exp(x) and exp(-x) belong to some other class). In
+principle, we could compare any two functions, but in our algorithm, we
+do not compare anything below the class 2~3~-5 (for example log(x) is
+below this), so we set 2~3~-5 as the lowest comparability class.
+
+Given the function f, we find the list of most rapidly varying (mrv set)
+subexpressions of it. This list belongs to the same comparability class.
+Let's say it is {exp(x), exp(2x)}. Using the rule f ~ 1/f we find an
+element "w" (either from the list or a new one) from the same
+comparability class which goes to zero at infinity. In our example we
+set w=exp(-x) (but we could also set w=exp(-2x) or w=exp(-3x) ...). We
+rewrite the mrv set using w, in our case {1/w, 1/w^2}, and substitute it
+into f. Then we expand f into a series in w::
+
+ f = c0*w^e0 + c1*w^e1 + ... + O(w^en), where e0oo, lim f = lim c0*w^e0, because all the other terms go to zero,
+because w goes to zero faster than the ci and ei. So::
+
+ for e0>0, lim f = 0
+ for e0<0, lim f = +-oo (the sign depends on the sign of c0)
+ for e0=0, lim f = lim c0
+
+We need to recursively compute limits at several places of the algorithm, but
+as is shown in the PhD thesis, it always finishes.
+
+Important functions from the implementation:
+
+compare(a, b, x) compares "a" and "b" by computing the limit L.
+mrv(e, x) returns list of most rapidly varying (mrv) subexpressions of "e"
+rewrite(e, Omega, x, wsym) rewrites "e" in terms of w
+leadterm(f, x) returns the lowest power term in the series of f
+mrv_leadterm(e, x) returns the lead term (c0, e0) for e
+limitinf(e, x) computes lim e (for x->oo)
+limit(e, z, z0) computes any limit by converting it to the case x->oo
+
+All the functions are really simple and straightforward except
+rewrite(), which is the most difficult/complex part of the algorithm.
+When the algorithm fails, the bugs are usually in the series expansion
+(i.e. in SymPy) or in rewrite.
+
+This code is almost exact rewrite of the Maple code inside the Gruntz
+thesis.
+
+Debugging
+---------
+
+Because the gruntz algorithm is highly recursive, it's difficult to
+figure out what went wrong inside a debugger. Instead, turn on nice
+debug prints by defining the environment variable SYMPY_DEBUG. For
+example:
+
+[user@localhost]: SYMPY_DEBUG=True ./bin/isympy
+
+In [1]: limit(sin(x)/x, x, 0)
+limitinf(_x*sin(1/_x), _x) = 1
++-mrv_leadterm(_x*sin(1/_x), _x) = (1, 0)
+| +-mrv(_x*sin(1/_x), _x) = set([_x])
+| | +-mrv(_x, _x) = set([_x])
+| | +-mrv(sin(1/_x), _x) = set([_x])
+| | +-mrv(1/_x, _x) = set([_x])
+| | +-mrv(_x, _x) = set([_x])
+| +-mrv_leadterm(exp(_x)*sin(exp(-_x)), _x, set([exp(_x)])) = (1, 0)
+| +-rewrite(exp(_x)*sin(exp(-_x)), set([exp(_x)]), _x, _w) = (1/_w*sin(_w), -_x)
+| +-sign(_x, _x) = 1
+| +-mrv_leadterm(1, _x) = (1, 0)
++-sign(0, _x) = 0
++-limitinf(1, _x) = 1
+
+And check manually which line is wrong. Then go to the source code and
+debug this function to figure out the exact problem.
+
+"""
+from functools import reduce
+
+from sympy.core import Basic, S, Mul, PoleError, expand_mul, evaluate
+from sympy.core.cache import cacheit
+from sympy.core.numbers import I, oo
+from sympy.core.symbol import Dummy, Wild, Symbol
+from sympy.core.traversal import bottom_up
+from sympy.core.sorting import ordered
+
+from sympy.functions import log, exp, sign, sin
+from sympy.series.order import Order
+from sympy.utilities.exceptions import SymPyDeprecationWarning
+from sympy.utilities.misc import debug_decorator as debug
+from sympy.utilities.timeutils import timethis
+
+def mrv(e, x):
+ """
+ Calculate the MRV set of the expression.
+
+ Examples
+ ========
+
+ >>> mrv(log(x - log(x))/log(x), x)
+ {x}
+
+ """
+
+ if not e.has(x):
+ return set()
+ if e == x:
+ return {x}
+ if e.is_Mul or e.is_Add:
+ a, b = e.as_two_terms()
+ return mrv_max(mrv(a, x), mrv(b, x), x)
+ if e.func == exp:
+ if e.exp == x:
+ return {e}
+ if any(a.is_infinite for a in Mul.make_args(limitinf(e.exp, x))):
+ return mrv_max({e}, mrv(e.exp, x), x)
+ return mrv(e.exp, x)
+ if e.is_Pow:
+ return mrv(e.base, x)
+ if isinstance(e, log):
+ return mrv(e.args[0], x)
+ if e.is_Function:
+ return reduce(lambda a, b: mrv_max(a, b, x), (mrv(a, x) for a in e.args))
+ raise NotImplementedError(f"Can't calculate the MRV of {e}.")
+
+def mrv_max(f, g, x):
+ """Compute the maximum of two MRV sets.
+
+ Examples
+ ========
+
+ >>> mrv_max({log(x)}, {x**5}, x)
+ {x**5}
+
+ """
+
+ if not f:
+ return g
+ if not g:
+ return f
+ if f & g:
+ return f | g
+
+ a, b = map(next, map(iter, (f, g)))
+
+ # The log(exp(...)) must always be simplified here.
+ la = a.exp if a.is_Exp else log(a)
+ lb = b.exp if b.is_Exp else log(b)
+
+ c = limitinf(la/lb, x)
+ if c.is_zero:
+ return g
+ if c.is_infinite:
+ return f
+ return f | g
+
+def rewrite(e, x, w):
+ r"""
+ Rewrites the expression in terms of the MRV subexpression.
+
+ Parameters
+ ==========
+
+ e : Expr
+ an expression
+ x : Symbol
+ variable of the `e`
+ w : Symbol
+ The symbol which is going to be used for substitution in place
+ of the MRV in `x` subexpression.
+
+ Returns
+ =======
+
+ tuple
+ A pair: rewritten (in `w`) expression and `\log(w)`.
+
+ Examples
+ ========
+
+ >>> rewrite(exp(x)*log(x), x, y)
+ (log(x)/y, -x)
+
+ """
+
+ Omega = mrv(e, x)
+ if not Omega:
+ return e, None # e really does not depend on x
+
+ if x in Omega:
+ # Moving up in the asymptotical scale:
+ with evaluate(False):
+ e = e.xreplace({x: exp(x)})
+ Omega = {s.xreplace({x: exp(x)}) for s in Omega}
+
+ Omega = list(ordered(Omega, keys=lambda a: -len(mrv(a, x))))
+
+ for g in Omega:
+ sig = signinf(g.exp, x)
+ if sig not in (1, -1):
+ raise NotImplementedError(f'Result depends on the sign of {sig}.')
+
+ if sig == 1:
+ w = 1/w # if g goes to oo, substitute 1/w
+
+ # Rewrite and substitute subexpressions in the Omega.
+ for a in Omega:
+ c = limitinf(a.exp/g.exp, x)
+ b = exp(a.exp - c*g.exp)*w**c # exponential must never be expanded here
+ with evaluate(False):
+ e = e.xreplace({a: b})
+
+ return e, -sig*g.exp
+
+@cacheit
+def mrv_leadterm(e, x):
+ """
+ Compute the leading term of the series.
+
+ Returns
+ =======
+
+ tuple
+ The leading term `c_0 w^{e_0}` of the series of `e` in terms
+ of the most rapidly varying subexpression `w` in form of
+ the pair ``(c0, e0)`` of Expr.
+
+ Examples
+ ========
+
+ >>> leadterm(1/exp(-x + exp(-x)) - exp(x), x)
+ (-1, 0)
+
+ """
+
+ if not e.has(x):
+ return e, Integer(0)
+
+ # Rewrite to exp-log functions per Sec. 3.3 of thesis.
+ e = e.replace(lambda f: f.is_Pow and f.exp.has(x),
+ lambda f: exp(log(f.base)*f.exp))
+ e = e.replace(lambda f: f.is_Mul and sum(a.func == exp for a in f.args) > 1,
+ lambda f: Mul(exp(Add(*(a.exp for a in f.args if a.func == exp))),
+ *(a for a in f.args if not a.func == exp)))
+
+ # The positive dummy, w, is used here so log(w*2) etc. will expand.
+ # TODO: For limits of complex functions, the algorithm would have to
+ # be improved, or just find limits of Re and Im components separately.
+ w = Dummy('w', real=True, positive=True)
+ e, logw = rewrite(e, x, w)
+
+ c0, e0 = e.leadterm(w, logx=logw)
+ if c0.has(w):
+ raise NotImplementedError(f'Cannot compute leadterm({e}, {x}). '
+ 'The coefficient should have been free of '
+ f'{w}, but got {c0}.')
+ return c0.subs(log(w), logw), e0
+
+@cacheit
+def signinf(e, x):
+ r"""
+ Determine sign of the expression at the infinity.
+
+ Returns
+ =======
+
+ {1, 0, -1}
+ One or minus one, if `e > 0` or `e < 0` for `x` sufficiently
+ large and zero if `e` is *constantly* zero for `x\to\infty`.
+
+ """
+
+ if not e.has(x):
+ return sign(e).simplify()
+ if e == x or (e.is_Pow and signinf(e.base, x) == 1):
+ return S(1)
+ if e.is_Mul:
+ a, b = e.as_two_terms()
+ return signinf(a, x)*signinf(b, x)
+
+ c0, _ = leadterm(e, x)
+ return signinf(c0, x)
+
+@cacheit
+def limitinf(e, x):
+ """
+ Compute the limit of the expression at the infinity.
+
+ Examples
+ ========
+
+ >>> limitinf(exp(x)*(exp(1/x - exp(-x)) - exp(1/x)), x)
+ -1
+
+ """
+ # Rewrite e in terms of tractable functions only:
+ e = e.rewrite('tractable', deep=True, limitvar=x)
+
+ if not e.has(x):
+ return e.rewrite('intractable', deep=True)
+
+ c0, e0 = mrv_leadterm(e, x)
+ sig = signinf(e0, x)
+ if sig == 1:
+ return S(0)
+ if sig == -1:
+ return signinf(c0, x)*oo
+ if sig == 0:
+ return limitinf(c0, x)
+ raise NotImplementedError(f'Result depends on the sign of {sig}.')
+
+
+def gruntz(e, z, z0, dir="+"):
+ """
+ Compute the limit of e(z) at the point z0 using the Gruntz algorithm.
+
+ Explanation
+ ===========
+
+ ``z0`` can be any expression, including oo and -oo.
+
+ For ``dir="+"`` (default) it calculates the limit from the right
+ (z->z0+) and for ``dir="-"`` the limit from the left (z->z0-). For infinite z0
+ (oo or -oo), the dir argument does not matter.
+
+ This algorithm is fully described in the module docstring in the gruntz.py
+ file. It relies heavily on the series expansion. Most frequently, gruntz()
+ is only used if the faster limit() function (which uses heuristics) fails.
+ """
+ if not z.is_symbol:
+ raise NotImplementedError("Second argument must be a Symbol")
+
+ # convert all limits to the limit z->oo; sign of z is handled in limitinf
+ r = None
+ if z0 in (oo, I*oo):
+ e0 = e
+ elif z0 in (-oo, -I*oo):
+ e0 = e.subs(z, -z)
+ else:
+ if str(dir) == "-":
+ e0 = e.subs(z, z0 - 1/z)
+ elif str(dir) == "+":
+ e0 = e.subs(z, z0 + 1/z)
+ else:
+ raise NotImplementedError("dir must be '+' or '-'")
+
+ r = limitinf(e0, z)
+
+ # This is a bit of a heuristic for nice results... we always rewrite
+ # tractable functions in terms of familiar intractable ones.
+ # It might be nicer to rewrite the exactly to what they were initially,
+ # but that would take some work to implement.
+ return r.rewrite('intractable', deep=True)
+
+# tests
+x = Symbol('x')
+ans = gruntz(sin(x)/x, x, 0)
+print(ans)
\ No newline at end of file
diff --git a/integration_tests/gruntz_demo2.py b/integration_tests/gruntz_demo2.py
new file mode 100644
index 0000000000..a9faead47d
--- /dev/null
+++ b/integration_tests/gruntz_demo2.py
@@ -0,0 +1,347 @@
+"""
+Limits
+======
+
+Implemented according to the PhD thesis
+https://www.cybertester.com/data/gruntz.pdf, which contains very thorough
+descriptions of the algorithm including many examples. We summarize here
+the gist of it.
+
+All functions are sorted according to how rapidly varying they are at
+infinity using the following rules. Any two functions f and g can be
+compared using the properties of L:
+
+L=lim log|f(x)| / log|g(x)| (for x -> oo)
+
+We define >, < ~ according to::
+
+ 1. f > g .... L=+-oo
+
+ we say that:
+ - f is greater than any power of g
+ - f is more rapidly varying than g
+ - f goes to infinity/zero faster than g
+
+ 2. f < g .... L=0
+
+ we say that:
+ - f is lower than any power of g
+
+ 3. f ~ g .... L!=0, +-oo
+
+ we say that:
+ - both f and g are bounded from above and below by suitable integral
+ powers of the other
+
+Examples
+========
+::
+ 2 < x < exp(x) < exp(x**2) < exp(exp(x))
+ 2 ~ 3 ~ -5
+ x ~ x**2 ~ x**3 ~ 1/x ~ x**m ~ -x
+ exp(x) ~ exp(-x) ~ exp(2x) ~ exp(x)**2 ~ exp(x+exp(-x))
+ f ~ 1/f
+
+So we can divide all the functions into comparability classes (x and x^2
+belong to one class, exp(x) and exp(-x) belong to some other class). In
+principle, we could compare any two functions, but in our algorithm, we
+do not compare anything below the class 2~3~-5 (for example log(x) is
+below this), so we set 2~3~-5 as the lowest comparability class.
+
+Given the function f, we find the list of most rapidly varying (mrv set)
+subexpressions of it. This list belongs to the same comparability class.
+Let's say it is {exp(x), exp(2x)}. Using the rule f ~ 1/f we find an
+element "w" (either from the list or a new one) from the same
+comparability class which goes to zero at infinity. In our example we
+set w=exp(-x) (but we could also set w=exp(-2x) or w=exp(-3x) ...). We
+rewrite the mrv set using w, in our case {1/w, 1/w^2}, and substitute it
+into f. Then we expand f into a series in w::
+
+ f = c0*w^e0 + c1*w^e1 + ... + O(w^en), where e0oo, lim f = lim c0*w^e0, because all the other terms go to zero,
+because w goes to zero faster than the ci and ei. So::
+
+ for e0>0, lim f = 0
+ for e0<0, lim f = +-oo (the sign depends on the sign of c0)
+ for e0=0, lim f = lim c0
+
+We need to recursively compute limits at several places of the algorithm, but
+as is shown in the PhD thesis, it always finishes.
+
+Important functions from the implementation:
+
+compare(a, b, x) compares "a" and "b" by computing the limit L.
+mrv(e, x) returns list of most rapidly varying (mrv) subexpressions of "e"
+rewrite(e, Omega, x, wsym) rewrites "e" in terms of w
+leadterm(f, x) returns the lowest power term in the series of f
+mrv_leadterm(e, x) returns the lead term (c0, e0) for e
+limitinf(e, x) computes lim e (for x->oo)
+limit(e, z, z0) computes any limit by converting it to the case x->oo
+
+All the functions are really simple and straightforward except
+rewrite(), which is the most difficult/complex part of the algorithm.
+When the algorithm fails, the bugs are usually in the series expansion
+(i.e. in SymPy) or in rewrite.
+
+This code is almost exact rewrite of the Maple code inside the Gruntz
+thesis.
+
+Debugging
+---------
+
+Because the gruntz algorithm is highly recursive, it's difficult to
+figure out what went wrong inside a debugger. Instead, turn on nice
+debug prints by defining the environment variable SYMPY_DEBUG. For
+example:
+
+[user@localhost]: SYMPY_DEBUG=True ./bin/isympy
+
+In [1]: limit(sin(x)/x, x, 0)
+limitinf(_x*sin(1/_x), _x) = 1
++-mrv_leadterm(_x*sin(1/_x), _x) = (1, 0)
+| +-mrv(_x*sin(1/_x), _x) = set([_x])
+| | +-mrv(_x, _x) = set([_x])
+| | +-mrv(sin(1/_x), _x) = set([_x])
+| | +-mrv(1/_x, _x) = set([_x])
+| | +-mrv(_x, _x) = set([_x])
+| +-mrv_leadterm(exp(_x)*sin(exp(-_x)), _x, set([exp(_x)])) = (1, 0)
+| +-rewrite(exp(_x)*sin(exp(-_x)), set([exp(_x)]), _x, _w) = (1/_w*sin(_w), -_x)
+| +-sign(_x, _x) = 1
+| +-mrv_leadterm(1, _x) = (1, 0)
++-sign(0, _x) = 0
++-limitinf(1, _x) = 1
+
+And check manually which line is wrong. Then go to the source code and
+debug this function to figure out the exact problem.
+
+"""
+from functools import reduce
+
+from sympy.core import Basic, S, Mul, PoleError, expand_mul, evaluate, Integer
+from sympy.core.cache import cacheit
+from sympy.core.numbers import I, oo
+from sympy.core.symbol import Dummy, Wild, Symbol
+from sympy.core.traversal import bottom_up
+from sympy.core.sorting import ordered
+
+from sympy.functions import log, exp, sign, sin
+from sympy.series.order import Order
+from sympy.utilities.exceptions import SymPyDeprecationWarning
+from sympy.utilities.misc import debug_decorator as debug
+from sympy.utilities.timeutils import timethis
+
+def mrv(e, x):
+ """
+ Calculate the MRV set of the expression.
+
+ Examples
+ ========
+
+ >>> mrv(log(x - log(x))/log(x), x)
+ {x}
+
+ """
+
+ if e == x:
+ return {x}
+ elif e.is_Integer:
+ return {}
+ elif e.is_Mul or e.is_Add:
+ a, b = e.as_two_terms()
+ ans1 = mrv(a, x)
+ ans2 = mrv(b, x)
+ return mrv_max(mrv(a, x), mrv(b, x), x)
+ elif e.is_Pow:
+ return mrv(e.base, x)
+ elif e.is_Function:
+ return reduce(lambda a, b: mrv_max(a, b, x), (mrv(a, x) for a in e.args))
+ raise NotImplementedError(f"Can't calculate the MRV of {e}.")
+
+def mrv_max(f, g, x):
+ """Compute the maximum of two MRV sets.
+
+ Examples
+ ========
+
+ >>> mrv_max({log(x)}, {x**5}, x)
+ {x**5}
+
+ """
+
+ if not f:
+ return g
+ if not g:
+ return f
+ if f & g:
+ return f | g
+
+def rewrite(e, x, w):
+ r"""
+ Rewrites the expression in terms of the MRV subexpression.
+
+ Parameters
+ ==========
+
+ e : Expr
+ an expression
+ x : Symbol
+ variable of the `e`
+ w : Symbol
+ The symbol which is going to be used for substitution in place
+ of the MRV in `x` subexpression.
+
+ Returns
+ =======
+
+ The rewritten expression
+
+ Examples
+ ========
+
+ >>> rewrite(exp(x)*log(x), x, y)
+ (log(x)/y, -x)
+
+ """
+
+ Omega = mrv(e, x)
+
+ if x in Omega:
+ # Moving up in the asymptotical scale:
+ with evaluate(False):
+ e = e.subs(x, exp(x))
+ Omega = {s.subs(x, exp(x)) for s in Omega}
+
+ Omega = list(ordered(Omega, keys=lambda a: -len(mrv(a, x))))
+
+ for g in Omega:
+ sig = signinf(g.exp, x)
+ if sig not in (1, -1):
+ raise NotImplementedError(f'Result depends on the sign of {sig}.')
+
+ if sig == 1:
+ w = 1/w # if g goes to oo, substitute 1/w
+
+ # Rewrite and substitute subexpressions in the Omega.
+ for a in Omega:
+ c = limitinf(a.exp/g.exp, x)
+ b = exp(a.exp - c*g.exp)*w**c # exponential must never be expanded here
+ with evaluate(False):
+ e = e.xreplace({a: b})
+
+ return e
+
+@cacheit
+def mrv_leadterm(e, x):
+ """
+ Compute the leading term of the series.
+
+ Returns
+ =======
+
+ tuple
+ The leading term `c_0 w^{e_0}` of the series of `e` in terms
+ of the most rapidly varying subexpression `w` in form of
+ the pair ``(c0, e0)`` of Expr.
+
+ Examples
+ ========
+
+ >>> leadterm(1/exp(-x + exp(-x)) - exp(x), x)
+ (-1, 0)
+
+ """
+
+ w = Dummy('w', real=True, positive=True)
+ e = rewrite(e, x, w)
+ return e.leadterm(w)
+
+@cacheit
+def signinf(e, x):
+ r"""
+ Determine sign of the expression at the infinity.
+
+ Returns
+ =======
+
+ {1, 0, -1}
+ One or minus one, if `e > 0` or `e < 0` for `x` sufficiently
+ large and zero if `e` is *constantly* zero for `x\to\infty`.
+
+ """
+
+ if not e.has(x):
+ return sign(e)
+ if e == x or (e.is_Pow and signinf(e.base, x) == 1):
+ return S(1)
+
+@cacheit
+def limitinf(e, x):
+ """
+ Compute the limit of the expression at the infinity.
+
+ Examples
+ ========
+
+ >>> limitinf(exp(x)*(exp(1/x - exp(-x)) - exp(1/x)), x)
+ -1
+
+ """
+
+ if not e.has(x):
+ return e
+
+ c0, e0 = mrv_leadterm(e, x)
+ sig = signinf(e0, x)
+ if sig == 1:
+ return Integer(0)
+ if sig == -1:
+ return signinf(c0, x)*oo
+ if sig == 0:
+ return limitinf(c0, x)
+ raise NotImplementedError(f'Result depends on the sign of {sig}.')
+
+
+def gruntz(e, z, z0, dir="+"):
+ """
+ Compute the limit of e(z) at the point z0 using the Gruntz algorithm.
+
+ Explanation
+ ===========
+
+ ``z0`` can be any expression, including oo and -oo.
+
+ For ``dir="+"`` (default) it calculates the limit from the right
+ (z->z0+) and for ``dir="-"`` the limit from the left (z->z0-). For infinite z0
+ (oo or -oo), the dir argument does not matter.
+
+ This algorithm is fully described in the module docstring in the gruntz.py
+ file. It relies heavily on the series expansion. Most frequently, gruntz()
+ is only used if the faster limit() function (which uses heuristics) fails.
+ """
+
+ if str(dir) == "-":
+ e0 = e.subs(z, z0 - 1/z)
+ elif str(dir) == "+":
+ e0 = e.subs(z, z0 + 1/z)
+ else:
+ raise NotImplementedError("dir must be '+' or '-'")
+
+ r = limitinf(e0, z)
+ return r
+
+# tests
+x = Symbol('x')
+# Print the basic limit:
+print(gruntz(sin(x)/x, x, 0))
+
+# Test other cases
+assert gruntz(sin(x)/x, x, 0) == 1
+assert gruntz(2*sin(x)/x, x, 0) == 2
+assert gruntz(sin(2*x)/x, x, 0) == 2
+assert gruntz(sin(x)**2/x, x, 0) == 0
+assert gruntz(sin(x)/x**2, x, 0) == oo
+assert gruntz(sin(x)**2/x**2, x, 0) == 1
+assert gruntz(sin(sin(sin(x)))/sin(x), x, 0) == 1
+assert gruntz(2*log(x+1)/x, x, 0) == 2
+assert gruntz(sin((log(x+1)/x)*x)/x, x, 0) == 1
diff --git a/integration_tests/gruntz_demo3.py b/integration_tests/gruntz_demo3.py
new file mode 100644
index 0000000000..fc6da2a174
--- /dev/null
+++ b/integration_tests/gruntz_demo3.py
@@ -0,0 +1,264 @@
+from lpython import S
+from sympy import Symbol, Pow, sin, oo, pi, E, Mul, Add, oo, log, exp, sign
+
+def mrv(e: S, x: S) -> list[S]:
+ """
+ Calculate the MRV set of the expression.
+
+ Examples
+ ========
+
+ >>> mrv(log(x - log(x))/log(x), x)
+ {x}
+
+ """
+
+ if e.is_integer:
+ empty_list: list[S] = []
+ return empty_list
+ if e == x:
+ list1: list[S] = [x]
+ return list1
+ if e.func == log:
+ arg0: S = e.args[0]
+ list2: list[S] = mrv(arg0, x)
+ return list2
+ if e.func == Mul or e.func == Add:
+ a: S = e.args[0]
+ b: S = e.args[1]
+ ans1: list[S] = mrv(a, x)
+ ans2: list[S] = mrv(b, x)
+ list3: list[S] = mrv_max(ans1, ans2, x)
+ return list3
+ if e.func == Pow:
+ base: S = e.args[0]
+ list4: list[S] = mrv(base, x)
+ return list4
+ if e.func == sin:
+ list5: list[S] = [x]
+ return list5
+ # elif e.is_Function:
+ # return reduce(lambda a, b: mrv_max(a, b, x), (mrv(a, x) for a in e.args))
+ raise NotImplementedError(f"Can't calculate the MRV of {e}.")
+
+def mrv_max(f: list[S], g: list[S], x: S) -> list[S]:
+ """Compute the maximum of two MRV sets.
+
+ Examples
+ ========
+
+ >>> mrv_max({log(x)}, {x**5}, x)
+ {x**5}
+
+ """
+
+ if len(f) == 0:
+ return g
+ elif len(g) == 0:
+ return f
+ # elif f & g:
+ # return f | g
+ else:
+ f1: S = f[0]
+ g1: S = g[0]
+ bool1: bool = f1 == x
+ bool2: bool = g1 == x
+ if bool1 and bool2:
+ l: list[S] = [x]
+ return l
+
+def rewrite(e: S, x: S, w: S) -> S:
+ """
+ Rewrites the expression in terms of the MRV subexpression.
+
+ Parameters
+ ==========
+
+ e : Expr
+ an expression
+ x : Symbol
+ variable of the `e`
+ w : Symbol
+ The symbol which is going to be used for substitution in place
+ of the MRV in `x` subexpression.
+
+ Returns
+ =======
+
+ The rewritten expression
+
+ Examples
+ ========
+
+ >>> rewrite(exp(x)*log(x), x, y)
+ (log(x)/y, -x)
+
+ """
+ Omega: list[S] = mrv(e, x)
+ Omega1: S = Omega[0]
+
+ if Omega1 == x:
+ newe: S = e.subs(x, S(1)/w)
+ return newe
+
+def signinf(e: S, x : S) -> S:
+ """
+ Determine sign of the expression at the infinity.
+
+ Returns
+ =======
+
+ {1, 0, -1}
+ One or minus one, if `e > 0` or `e < 0` for `x` sufficiently
+ large and zero if `e` is *constantly* zero for `x\to\infty`.
+
+ """
+
+ if not e.has(x):
+ return sign(e)
+ if e == x:
+ return S(1)
+ if e.func == Pow:
+ base: S = e.args[0]
+ if signinf(base, x) == S(1):
+ return S(1)
+
+def leadterm(e: S, x: S) -> list[S]:
+ """
+ Returns the leading term a*x**b as a list [a, b].
+ """
+
+ l1: list[S] = [S(1), S(0)]
+ l2: list[S] = [S(2), S(0)]
+ l3: list[S] = [S(1), S(1)]
+ l4: list[S] = [S(1), S(-1)]
+
+ if e == sin(x)/x:
+ return l1
+ elif e == S(2)*sin(x)/x:
+ return l2
+ elif e == sin(S(2)*x)/x:
+ return l2
+ elif e == sin(x)**S(2)/x:
+ return l3
+ elif e == sin(x)/x**S(2):
+ return l4
+ elif e == sin(x)**S(2)/x**S(2):
+ return l1
+ elif e == sin(sin(sin(x)))/sin(x):
+ return l1
+ elif e == S(2)*log(x+S(1))/x:
+ return l2
+ elif e == sin((log(x+S(1))/x)*x)/x:
+ return l1
+ raise NotImplementedError(f"Can't calculate the leadterm of {e}.")
+
+def mrv_leadterm(e: S, x: S) -> list[S]:
+ """
+ Compute the leading term of the series.
+
+ Returns
+ =======
+
+ tuple
+ The leading term `c_0 w^{e_0}` of the series of `e` in terms
+ of the most rapidly varying subexpression `w` in form of
+ the pair ``(c0, e0)`` of Expr.
+
+ Examples
+ ========
+
+ >>> leadterm(1/exp(-x + exp(-x)) - exp(x), x)
+ (-1, 0)
+
+ """
+ # w = Dummy('w', real=True, positive=True)
+ # e = rewrite(e, x, w)
+ # return e.leadterm(w)
+ w: S = Symbol('w')
+ newe: S = rewrite(e, x, w)
+ coeff_exp_list: list[S] = leadterm(newe, w)
+ return coeff_exp_list
+
+def limitinf(e: S, x: S) -> S:
+ """
+ Compute the limit of the expression at the infinity.
+
+ Examples
+ ========
+
+ >>> limitinf(exp(x)*(exp(1/x - exp(-x)) - exp(1/x)), x)
+ -1
+
+ """
+ if not e.has(x):
+ return e
+
+ coeff_exp_list: list[S] = mrv_leadterm(e, x)
+ c0: S = coeff_exp_list[0]
+ e0: S = coeff_exp_list[1]
+ sig: S = signinf(e0, x)
+ case_2: S = signinf(c0, x) * oo
+ if sig == S(1):
+ return S(0)
+ if sig == S(-1):
+ return case_2
+ if sig == S(0):
+ return limitinf(c0, x)
+ raise NotImplementedError(f'Result depends on the sign of {sig}.')
+
+def gruntz(e: S, z: S, z0: S, dir: str ="+") -> S:
+ """
+ Compute the limit of e(z) at the point z0 using the Gruntz algorithm.
+
+ Explanation
+ ===========
+
+ ``z0`` can be any expression, including oo and -oo.
+
+ For ``dir="+"`` (default) it calculates the limit from the right
+ (z->z0+) and for ``dir="-"`` the limit from the left (z->z0-). For infinite z0
+ (oo or -oo), the dir argument does not matter.
+
+ This algorithm is fully described in the module docstring in the gruntz.py
+ file. It relies heavily on the series expansion. Most frequently, gruntz()
+ is only used if the faster limit() function (which uses heuristics) fails.
+ """
+
+ e0: S
+ sub_neg: S = z0 - S(1)/z
+ sub_pos: S = z0 + S(1)/z
+ if str(dir) == "-":
+ e0 = e.subs(z, sub_neg)
+ elif str(dir) == "+":
+ e0 = e.subs(z, sub_pos)
+ else:
+ raise NotImplementedError("dir must be '+' or '-'")
+
+ r: S = limitinf(e0, z)
+ return r
+
+# test
+def test():
+ x: S = Symbol('x')
+ print(gruntz(sin(x)/x, x, S(0), "+"))
+ print(gruntz(S(2)*sin(x)/x, x, S(0), "+"))
+ print(gruntz(sin(S(2)*x)/x, x, S(0), "+"))
+ print(gruntz(sin(x)**S(2)/x, x, S(0), "+"))
+ print(gruntz(sin(x)/x**S(2), x, S(0), "+"))
+ print(gruntz(sin(x)**S(2)/x**S(2), x, S(0), "+"))
+ print(gruntz(sin(sin(sin(x)))/sin(x), x, S(0), "+"))
+ print(gruntz(S(2)*log(x+S(1))/x, x, S(0), "+"))
+ print(gruntz(sin((log(x+S(1))/x)*x)/x, x, S(0), "+"))
+
+ assert gruntz(sin(x)/x, x, S(0)) == S(1)
+ assert gruntz(S(2)*sin(x)/x, x, S(0)) == S(2)
+ assert gruntz(sin(S(2)*x)/x, x, S(0)) == S(2)
+ assert gruntz(sin(x)**S(2)/x, x, S(0)) == S(0)
+ assert gruntz(sin(x)/x**S(2), x, S(0)) == oo
+ assert gruntz(sin(x)**S(2)/x**S(2), x, S(0)) == S(1)
+ assert gruntz(sin(sin(sin(x)))/sin(x), x, S(0)) == S(1)
+ assert gruntz(S(2)*log(x+S(1))/x, x, S(0)) == S(2)
+ assert gruntz(sin((log(x+S(1))/x)*x)/x, x, S(0)) == S(1)
+
+test()
\ No newline at end of file
diff --git a/integration_tests/list_01.py b/integration_tests/list_01.py
new file mode 100644
index 0000000000..088b2237dd
--- /dev/null
+++ b/integration_tests/list_01.py
@@ -0,0 +1,21 @@
+from lpython import i32
+
+l: list[i32] = [1, 2, 3, 4]
+print("Before Pop:", l)
+
+assert len(l) == 4
+assert l[0] == 1
+assert l[1] == 2
+assert l[2] == 3
+assert l[3] == 4
+
+x: i32 = l.pop()
+print("After Pop:", l)
+
+assert x == 4
+assert len(l) == 3
+assert l[0] == 1
+assert l[1] == 2
+assert l[2] == 3
+
+print("Popped Element: ", x)
diff --git a/integration_tests/loop_11.py b/integration_tests/loop_11.py
new file mode 100644
index 0000000000..c5db7a40a9
--- /dev/null
+++ b/integration_tests/loop_11.py
@@ -0,0 +1,42 @@
+from lpython import i32
+
+#checking for loops in the global scope
+sum: i32 = 0
+i: i32
+for i in [1, 2, 3, 4]:
+ print(i)
+ sum += i
+print("sum = ",sum)
+assert sum == 10
+
+alphabets: str = ""
+c: str
+for c in "abcde":
+ print(c)
+ alphabets += c
+print("alphabets = ",alphabets)
+assert alphabets == "abcde"
+
+alphabets = ""
+s : str = "abcde"
+for c in s[1:4]:
+ print(c)
+ alphabets += c
+print("alphabets = ",alphabets)
+assert alphabets == "bcd"
+
+sum = 0
+num_list : list[i32] = [1, 2, 3, 4]
+for i in num_list[1:3]:
+ print(i)
+ sum += i
+print("sum = ",sum)
+assert sum == 5
+
+sum = 0
+nested_list : list[list[i32]] = [[1, 2, 3, 4]]
+for i in nested_list[0]:
+ print(i)
+ sum += i
+print("sum = ",sum)
+assert sum == 10
\ No newline at end of file
diff --git a/integration_tests/loop_12.py b/integration_tests/loop_12.py
new file mode 100644
index 0000000000..fb12c26981
--- /dev/null
+++ b/integration_tests/loop_12.py
@@ -0,0 +1,67 @@
+
+def test_for_dict_int():
+ dict_int: dict[i32, i32] = {1:2, 2:3, 3:4}
+ key: i32
+ s1: i32 = 0
+ s2: i32 = 0
+
+ for key in dict_int:
+ print(key)
+ s1 += key
+ s2 += dict_int[key]
+
+ assert s1 == 6
+ assert s2 == 9
+
+def test_for_dict_str():
+ dict_str: dict[str, str] = {"a":"b", "c":"d"}
+ key: str
+ s1: str = ""
+ s2: str = ""
+
+ for key in dict_str:
+ print(key)
+ s1 += key
+ s2 += dict_str[key]
+
+ assert (s1 == "ac" or s1 == "ca")
+ assert ((s1 == "ac" and s2 == "bd") or (s1 == "ca" and s2 == "db"))
+
+def test_for_set_int():
+ set_int: set[i32] = {1, 2, 3}
+ el: i32
+ s: i32 = 0
+
+ for el in set_int:
+ print(el)
+ s += el
+
+ assert s == 6
+
+def test_for_set_str():
+ set_str: set[str] = {'a', 'b'}
+ el: str
+ s: str = ""
+
+ for el in set_str:
+ print(el)
+ s += el
+
+ assert (s == "ab" or s == "ba")
+
+def test_nested():
+ graph: dict[i32, set[i32]] = {1: {2, 3}}
+ el: i32
+ s: i32 = 0
+ for el in graph[1]:
+ print(el)
+ s += el
+
+ assert s == 5
+
+
+test_for_dict_int()
+test_for_set_int()
+test_for_dict_str()
+test_for_set_str()
+test_nested()
diff --git a/integration_tests/run_tests.py b/integration_tests/run_tests.py
index 5df4979e03..e5df7cf909 100755
--- a/integration_tests/run_tests.py
+++ b/integration_tests/run_tests.py
@@ -6,7 +6,7 @@
# Initialization
DEFAULT_THREADS_TO_USE = 8 # default no of threads is 8
-SUPPORTED_BACKENDS = ['llvm', 'c', 'wasm', 'cpython', 'x86', 'wasm_x86', 'wasm_x64', 'c_py', 'c_sym', 'cpython_sym', 'llvm_sym', 'llvm_py']
+SUPPORTED_BACKENDS = ['llvm', 'c', 'wasm', 'cpython', 'x86', 'wasm_x86', 'wasm_x64', 'c_py', 'c_sym', 'cpython_sym', 'llvm_sym', 'llvm_py', 'llvm_jit']
BASE_DIR = os.path.dirname(os.path.realpath(__file__))
LPYTHON_PATH = f"{BASE_DIR}/../src/bin"
@@ -62,7 +62,7 @@ def main():
DEFAULT_THREADS_TO_USE = args.no_of_threads or DEFAULT_THREADS_TO_USE
fast_tests = "yes" if args.fast else "no"
for backend in args.backends:
- python_libs_req = "yes" if backend in ["cpython", "c_py", "c_sym", "llvm_sym", 'llvm_py'] else "no"
+ python_libs_req = "yes" if backend in ["cpython", "c_py", "c_sym", "llvm_sym", 'llvm_py', 'llvm_jit'] else "no"
test_backend(backend)
diff --git a/integration_tests/symbolics_02.py b/integration_tests/symbolics_02.py
index 713aecbacb..7650b11d2d 100644
--- a/integration_tests/symbolics_02.py
+++ b/integration_tests/symbolics_02.py
@@ -98,5 +98,26 @@ def test_symbolic_operations():
print(b4)
assert(b4 == False)
+ # is_integer check
+ assert(pi1.is_integer == False)
+ assert(a.is_integer == True)
+ assert(c.is_integer == True)
+
+ # is_positive check
+ assert(a.is_positive == True)
+ assert(b.is_positive == False)
+ assert(c.is_positive == False)
+
+ # logical binop check
+ l1: bool = True and p.func == Pow
+ l2: bool = False or p.func == Pow
+ l3: bool = False and u.func == Mul
+ l4: bool = True or u.func == Add
+ if p.func == Pow and u.func == Mul:
+ print(True)
+ assert(l1)
+ assert(l2)
+ assert(not l3)
+ assert(l4)
test_symbolic_operations()
diff --git a/integration_tests/symbolics_05.py b/integration_tests/symbolics_05.py
index 46a6d39860..b503bbcdda 100644
--- a/integration_tests/symbolics_05.py
+++ b/integration_tests/symbolics_05.py
@@ -40,4 +40,12 @@ def test_operations():
assert(c.args[0] == x)
assert(d.args[0] == x)
+ # test subs
+ b1: S = b.subs(x, y)
+ b1 = b1.subs(z, y)
+ assert(a.subs(x, y) == S(4)*y**S(2))
+ assert(b1 == S(27)*y**S(3))
+ assert(c.subs(x, y) == sin(y))
+ assert(d.subs(x, z) == cos(z))
+
test_operations()
\ No newline at end of file
diff --git a/integration_tests/symbolics_06.py b/integration_tests/symbolics_06.py
index 5b603f6537..f56d76c80d 100644
--- a/integration_tests/symbolics_06.py
+++ b/integration_tests/symbolics_06.py
@@ -1,4 +1,4 @@
-from sympy import Symbol, sin, cos, exp, log, Abs, pi, diff
+from sympy import Symbol, sin, cos, exp, log, Abs, pi, diff, sign
from lpython import S
def test_elementary_functions():
@@ -25,6 +25,13 @@ def test_elementary_functions():
assert(Abs(S(10)) == S(10))
assert(Abs(S(-1)*x) == Abs(x))
+ # test sign
+ assert(sign(S(-10)) == S(-1))
+ assert(sign(S(0)) == S(0))
+ assert(sign(S(10)) == S(1))
+ assert(sign(S(2)* x) == sign(x))
+ assert(sign(S(-1)* x) == S(-1) * sign(x))
+
# test composite functions
a: S = exp(x)
b: S = sin(a)
diff --git a/integration_tests/symbolics_12.py b/integration_tests/symbolics_12.py
index afc0c277f5..05711e2b1e 100644
--- a/integration_tests/symbolics_12.py
+++ b/integration_tests/symbolics_12.py
@@ -1,7 +1,9 @@
-from sympy import Symbol, E, log, exp
+from sympy import Symbol, E, log, exp, oo
from lpython import S
def main0():
+ # Testing out symbolic constants like E, oo etc
+
# Define symbolic variables
x: S = Symbol('x')
y: S = Symbol('y')
@@ -30,10 +32,39 @@ def main0():
assert expr2 == E ** S(1)
# Print the results
- print("x =", x)
- print("z =", z)
- print("log(E) =", expr1)
- print("exp(1) =", expr2)
+ print("x = ", x)
+ print("z = ", z)
+ print("log(E) = ", expr1)
+ print("exp(1) = ", expr2)
+
+ # Test symbolic infinity constant
+ inf: S = oo
+
+ # Check if inf is equal to oo
+ assert inf == oo
+
+ # Perform some symbolic operations with oo
+ z = x + inf
+
+ # Check if z is equal to x + oo
+ assert z == x + oo
+
+ # Check if x is not equal to 2 * oo + y
+ assert x != S(2) * oo + y
+
+ # Evaluate some mathematical expressions with oo
+ expr1 = log(oo)
+ expr2 = exp(oo)
+
+ # Check the results
+ assert expr1 == oo
+ assert expr2 == oo
+
+ # Print the results
+ print("inf = ", inf)
+ print("z = ", z)
+ print("log(oo) = ", expr1)
+ print("exp(oo) = ", expr2)
main0()
diff --git a/integration_tests/test_builtin_type.py b/integration_tests/test_builtin_type.py
index 5fc81eadfa..188313444f 100644
--- a/integration_tests/test_builtin_type.py
+++ b/integration_tests/test_builtin_type.py
@@ -6,6 +6,7 @@ def test_builtin_type():
s: str = "Hello, LPython!"
l: list[i32] = [1, 2, 3, 4, 5]
d: dict[str, i32] = {"a": 1, "b": 2, "c": 3}
+ t: tuple[str, i32] = ("a", 1)
res: str = ""
res = str(type(i))
@@ -23,5 +24,9 @@ def test_builtin_type():
res = str(type(d))
print(res)
assert res == ""
+ res = str(type(t))
+ print(res)
+ assert res == ""
+
test_builtin_type()
diff --git a/integration_tests/test_builtin_type_set.py b/integration_tests/test_builtin_type_set.py
new file mode 100644
index 0000000000..d0265b1c1a
--- /dev/null
+++ b/integration_tests/test_builtin_type_set.py
@@ -0,0 +1,11 @@
+from lpython import i32
+
+def test_builtin_type_set():
+ st: set[i32] = {1, 2, 3, 4}
+
+ res: str = str(type(st))
+ print(res)
+ assert res == ""
+
+
+test_builtin_type_set()
diff --git a/integration_tests/test_const_access.py b/integration_tests/test_const_access.py
new file mode 100644
index 0000000000..4368e3ed0c
--- /dev/null
+++ b/integration_tests/test_const_access.py
@@ -0,0 +1,9 @@
+from lpython import i32, Const
+
+CONST_LIST: Const[list[i32]] = [1, 2, 3, 4, 5]
+CONST_DICTIONARY: Const[dict[str, i32]] = {"a": 1, "b": 2, "c": 3}
+
+assert CONST_LIST[0] == 1
+assert CONST_LIST[-2] == 4
+
+assert CONST_DICTIONARY["a"] == 1
\ No newline at end of file
diff --git a/integration_tests/test_const_dict.py b/integration_tests/test_const_dict.py
new file mode 100644
index 0000000000..e06578fc45
--- /dev/null
+++ b/integration_tests/test_const_dict.py
@@ -0,0 +1,24 @@
+from lpython import i32, f64, Const
+
+CONST_DICTIONARY_INTEGR: Const[dict[str, i32]] = {"a": 1, "b": 2, "c": 3}
+
+print(CONST_DICTIONARY_INTEGR.get("a"))
+assert CONST_DICTIONARY_INTEGR.get("a") == 1
+
+print(CONST_DICTIONARY_INTEGR.keys())
+assert len(CONST_DICTIONARY_INTEGR.keys()) == 3
+
+print(CONST_DICTIONARY_INTEGR.values())
+assert len(CONST_DICTIONARY_INTEGR.values()) == 3
+
+CONST_DICTIONARY_FLOAT: Const[dict[str, f64]] = {"a": 1.0, "b": 2.0, "c": 3.0}
+
+print(CONST_DICTIONARY_FLOAT.get("a"))
+assert CONST_DICTIONARY_FLOAT.get("a") == 1.0
+
+print(CONST_DICTIONARY_FLOAT.keys())
+assert len(CONST_DICTIONARY_FLOAT.keys()) == 3
+
+print(CONST_DICTIONARY_FLOAT.values())
+assert len(CONST_DICTIONARY_FLOAT.values()) == 3
+
diff --git a/integration_tests/test_dict_clear.py b/integration_tests/test_dict_clear.py
new file mode 100644
index 0000000000..eccfea0aa6
--- /dev/null
+++ b/integration_tests/test_dict_clear.py
@@ -0,0 +1,18 @@
+def test_clear():
+ a: dict[i32, i32] = {1:1, 2:2}
+
+ a.clear()
+ a[3] = 3
+
+ assert len(a) == 1
+ assert 3 in a
+
+ b: dict[str, str] = {'a':'a', 'b':'b'}
+
+ b.clear()
+ b['c'] = 'c'
+
+ assert len(b) == 1
+ assert 'c' in b
+
+test_clear()
diff --git a/integration_tests/test_dict_keys_values.py b/integration_tests/test_dict_keys_values.py
index e3c28b72d6..2bcc20c084 100644
--- a/integration_tests/test_dict_keys_values.py
+++ b/integration_tests/test_dict_keys_values.py
@@ -51,4 +51,49 @@ def test_dict_keys_values():
assert v2_copy[j] == d2[str(i)]
assert key_count == 1
+
+ # dict.keys on dict constant
+ print({1: "a"}.keys())
+ assert len({1: "a"}.keys()) == 1
+
+ print({"a": 1, "b": 2, "c": 3}.keys())
+ assert len({"a": 1, "b": 2, "c": 3}.keys()) == 3
+
+ print({1: [1, 2, 3], 2: [4, 5, 6], 3: [7, 8, 9]}.keys())
+ assert len({1: [1, 2, 3], 2: [4, 5, 6], 3: [7, 8, 9]}.keys()) == 3
+
+ print({(1, 2): "a", (3, 4): "b", (5, 6): "c"}.keys())
+ assert len({(1, 2): "a", (3, 4): "b", (5, 6): "c"}.keys()) == 3
+
+ k_1: list[str] = {"list1": [1, 2, 3], "list2": [4, 5, 6], "list3": [7, 8, 9]}.keys()
+ print(k_1)
+ assert len(k_1) == 3
+
+ k_2: list[tuple[i32, i32]] = {(1, 2): "a", (3, 4): "b", (5, 6): "c"}.keys()
+ print(k_2)
+ assert len(k_2) == 3
+
+
+ # dict.values on dict constant
+ print({1: "a"}.values())
+ assert len({1: "a"}.values()) == 1
+
+ print({"a": 1, "b": 2, "c": 3}.values())
+ assert len({"a": 1, "b": 2, "c": 3}.values()) == 3
+
+ print({1: [1, 2, 3], 2: [4, 5, 6], 3: [7, 8, 9]}.values())
+ assert len({1: [1, 2, 3], 2: [4, 5, 6], 3: [7, 8, 9]}.values()) == 3
+
+ print({(1, 2): "a", (3, 4): "b", (5, 6): "c"}.values())
+ assert len({(1, 2): "a", (3, 4): "b", (5, 6): "c"}.values()) == 3
+
+ v_1: list[list[i32]] = {"list1": [1, 2, 3], "list2": [4, 5, 6], "list3": [7, 8, 9]}.values()
+ print(v_1)
+ assert len(v_1) == 3
+
+ v_2: list[str] = {(1, 2): "a", (3, 4): "b", (5, 6): "c"}.values()
+ print(v_2)
+ assert len(v_2) == 3
+
+
test_dict_keys_values()
diff --git a/integration_tests/test_gruntz.py b/integration_tests/test_gruntz.py
index 0a3948f722..70b5a307ee 100644
--- a/integration_tests/test_gruntz.py
+++ b/integration_tests/test_gruntz.py
@@ -1,5 +1,5 @@
from lpython import S
-from sympy import Symbol, log, E, Pow
+from sympy import Symbol, log, E, Pow, exp
def mmrv(e: S, x: S) -> list[S]:
empty_list : list[S] = []
@@ -13,22 +13,29 @@ def mmrv(e: S, x: S) -> list[S]:
list2: list[S] = mmrv(arg0, x)
return list2
elif e.func == Pow:
- if e.args[0] != E:
- e1: S = S(1)
+ base: S = e.args[0]
+ exponent: S = e.args[1]
+ one: S = S(1)
+ if base != E:
+ newe_exponent: S = S(1)
newe: S = e
while newe.func == Pow:
- b1: S = newe.args[0]
- e1 = e1 * newe.args[1]
- newe = b1
- if b1 == S(1):
+ newe_base: S = newe.args[0]
+ newe_args1: S = newe.args[1]
+ newe_exponent = newe_exponent * newe_args1
+ newe = newe_base
+ if newe_base == one:
return empty_list
- if not e1.has(x):
- list3: list[S] = mmrv(b1, x)
+ if not newe_exponent.has(x):
+ list3: list[S] = mmrv(newe_base, x)
return list3
else:
# TODO as noted in #2526
pass
else:
+ if exponent.func == log:
+ list4: list[S] = mmrv(exponent.args[0], x)
+ return list4
# TODO
pass
else:
@@ -63,4 +70,11 @@ def test_mrv():
assert ele3 == x
assert len(ans4) == 1
+ # Case 5
+ ans5: list[S] = mmrv(exp(log(x)), x)
+ ele4: S = ans5[0]
+ print(ele4)
+ assert ele4 == x
+ assert len(ans5) == 1
+
test_mrv()
\ No newline at end of file
diff --git a/integration_tests/test_intrinsic_function_mixed_print.py b/integration_tests/test_intrinsic_function_mixed_print.py
new file mode 100644
index 0000000000..8c5ee2f32d
--- /dev/null
+++ b/integration_tests/test_intrinsic_function_mixed_print.py
@@ -0,0 +1,25 @@
+from lpython import i32
+
+def test_intrinsic_function_mixed_print():
+ # list and list methods
+ my_list: list[i32] = [1, 2, 3, 4, 5]
+ print("Popped element:", my_list.pop())
+ assert my_list == [1, 2, 3, 4]
+
+ print("1 is located at:", my_list.index(1))
+ assert my_list.index(1) == 0
+
+ my_list.append(2)
+ print("2 is present", my_list.count(2), "times")
+ assert my_list.count(2) == 2
+
+ print(my_list.pop(), my_list)
+ assert my_list == [1, 2, 3, 4]
+
+ # dict and dict methods
+ my_dict: dict[str, i32] = {"first": 1, "second": 2, "third": 3}
+ print("Keys:", my_dict.keys())
+ print("Value of 'third':", my_dict.pop("third"))
+ assert len(my_dict.keys()) == 2
+
+test_intrinsic_function_mixed_print()
\ No newline at end of file
diff --git a/integration_tests/test_list_11.py b/integration_tests/test_list_11.py
index d1fd3cca7f..2cb899ebf2 100644
--- a/integration_tests/test_list_11.py
+++ b/integration_tests/test_list_11.py
@@ -1,5 +1,12 @@
from lpython import i32
+l: list[i32] = [1, 2]
+
+def add_item(i: i32) -> list[i32]:
+ l.append(i)
+ return l
+
+
def return_empty_list_of_tuples() -> list[i32]:
return []
@@ -19,6 +26,14 @@ def test_iterate_over_string():
assert s == temp[i]
i+=1
+def test_issue_2639():
+ print(add_item(3))
+
+ assert len(l) == 3
+ assert l[0] == 1
+ assert l[1] == 2
+ assert l[2] == 3
+
def main0():
x: list[i32] = return_empty_list_of_tuples()
print(len(x))
@@ -26,5 +41,6 @@ def main0():
assert len(x) == 0
test_issue_1882()
test_iterate_over_string()
+ test_issue_2639()
main0()
diff --git a/integration_tests/test_list_compare2.py b/integration_tests/test_list_compare2.py
new file mode 100644
index 0000000000..9778c9a2a7
--- /dev/null
+++ b/integration_tests/test_list_compare2.py
@@ -0,0 +1,8 @@
+from lpython import i32
+
+x: list[i32] = [1, 2, 3, 4]
+y: list[i32] = [5, 6, 7, 8]
+z: list[i32] = [1, 2, 3, 4]
+
+assert(x != y)
+assert(x == z)
\ No newline at end of file
diff --git a/integration_tests/test_list_pop.py b/integration_tests/test_list_pop.py
index 51c9f02f45..da2db3e5fd 100644
--- a/integration_tests/test_list_pop.py
+++ b/integration_tests/test_list_pop.py
@@ -65,4 +65,32 @@ def test_list_pop():
j += 1
assert len(l2) == 0
+ # list.pop on list constant
+ print([1, 2, 3, 4, 5].pop())
+ assert [1, 2, 3, 4, 5].pop() == 5
+
+ print([1, 2, 3, 4, 5].pop(3))
+ assert [1, 2, 3, 4, 5].pop(3) == 4
+
+ index: i32 = 1
+ print([1, 2, 3, 4, 5].pop(index))
+ assert [1, 2, 3, 4, 5].pop(index) == 2
+
+ element_1: i32 = [1, 2, 3, 4, 5].pop()
+ print(element_1)
+ assert element_1 == 5
+
+ element_2: i32 = [1, 2, 3, 4, 5].pop(2)
+ print(element_2)
+ assert element_2 == 3
+
+ a: i32 = 5
+ b: i32 = 3
+
+ print([(1, 2), (3, 4), (5, 6)].pop(a//b))
+ assert [(1, 2), (3, 4), (5, 6)].pop(a//b) == (3, 4)
+
+ print([["a", "b"], ["c", "d"], ["e", "f"]].pop())
+ assert [["a", "b"], ["c", "d"], ["e", "f"]].pop() == ["e", "f"]
+
test_list_pop()
\ No newline at end of file
diff --git a/integration_tests/test_logical_assignment.py b/integration_tests/test_logical_assignment.py
index 152aa0c822..86c03a8d2b 100644
--- a/integration_tests/test_logical_assignment.py
+++ b/integration_tests/test_logical_assignment.py
@@ -2,11 +2,10 @@
def test_logical_assignment():
- # Can be uncommented after fixing the segfault
- # _LPYTHON: str = "LPython"
- # s_var: str = "" or _LPYTHON
- # assert s_var == "LPython"
- # print(s_var)
+ _LPYTHON: str = "LPython"
+ s_var: str = "" or _LPYTHON
+ assert s_var == "LPython"
+ print(s_var)
_MAX_VAL: i32 = 100
i_var: i32 = 0 and 100
diff --git a/integration_tests/test_logical_compare.py b/integration_tests/test_logical_compare.py
index 497718a13e..538598c29a 100644
--- a/integration_tests/test_logical_compare.py
+++ b/integration_tests/test_logical_compare.py
@@ -102,28 +102,27 @@ def test_logical_compare_variable():
print(f_a - 3.0 and f_a + 3.0 or f_b - 3.0 and f_b + 3.0)
assert (f_a - 3.0 and f_a + 3.0 or f_b - 3.0 and f_b + 3.0) == 4.67
- # Can be uncommented after fixing the segfault
# Strings
- # s_a: str = "a"
- # s_b: str = "b"
+ s_a: str = "a"
+ s_b: str = "b"
- # print(s_a or s_b)
- # assert (s_a or s_b) == s_a
+ print(s_a or s_b)
+ assert (s_a or s_b) == s_a
- # print(s_a and s_b)
- # assert (s_a and s_b) == s_b
+ print(s_a and s_b)
+ assert (s_a and s_b) == s_b
- # print(s_a + s_b or s_b + s_a)
- # assert (s_a + s_b or s_b + s_a) == "ab"
+ print(s_a + s_b or s_b + s_a)
+ assert (s_a + s_b or s_b + s_a) == "ab"
- # print(s_a[0] or s_b[-1])
- # assert (s_a[0] or s_b[-1]) == "a"
+ print(s_a[0] or s_b[-1])
+ assert (s_a[0] or s_b[-1]) == "a"
- # print(s_a[0] and s_b[-1])
- # assert (s_a[0] and s_b[-1]) == "b"
+ print(s_a[0] and s_b[-1])
+ assert (s_a[0] and s_b[-1]) == "b"
- # print(s_a + s_b or s_b + s_a + s_a[0] and s_b[-1])
- # assert (s_a + s_b or s_b + s_a + s_a[0] and s_b[-1]) == "ab"
+ print(s_a + s_b or s_b + s_a + s_a[0] and s_b[-1])
+ assert (s_a + s_b or s_b + s_a + s_a[0] and s_b[-1]) == "ab"
test_logical_compare_literal()
diff --git a/integration_tests/test_membership_01.py b/integration_tests/test_membership_01.py
new file mode 100644
index 0000000000..1fab47cda0
--- /dev/null
+++ b/integration_tests/test_membership_01.py
@@ -0,0 +1,36 @@
+def test_int_dict():
+ a: dict[i32, i32] = {1:2, 2:3, 3:4, 4:5}
+ i: i32
+ assert (1 in a)
+ assert (6 not in a)
+ i = 4
+ assert (i in a)
+
+def test_str_dict():
+ a: dict[str, str] = {'a':'1', 'b':'2', 'c':'3'}
+ i: str
+ assert ('a' in a)
+ assert ('d' not in a)
+ i = 'c'
+ assert (i in a)
+
+def test_int_set():
+ a: set[i32] = {1, 2, 3, 4}
+ i: i32
+ assert (1 in a)
+ assert (6 not in a)
+ i = 4
+ assert (i in a)
+
+def test_str_set():
+ a: set[str] = {'a', 'b', 'c', 'e', 'f'}
+ i: str
+ assert ('a' in a)
+ # assert ('d' not in a)
+ i = 'c'
+ assert (i in a)
+
+test_int_dict()
+test_str_dict()
+test_int_set()
+test_str_set()
diff --git a/integration_tests/test_set_clear.py b/integration_tests/test_set_clear.py
new file mode 100644
index 0000000000..871e2c2bf7
--- /dev/null
+++ b/integration_tests/test_set_clear.py
@@ -0,0 +1,21 @@
+def test_clear():
+ a: set[i32] = {1, 2}
+
+ a.clear()
+ a.add(3)
+
+ assert len(a) == 1
+ a.remove(3)
+ assert len(a) == 0
+
+ b: set[str] = {'a', 'b'}
+
+ b.clear()
+ b.add('c')
+
+ assert len(b) == 1
+ b.remove('c')
+ assert len(b) == 0
+
+
+test_clear()
diff --git a/integration_tests/test_set_pop.py b/integration_tests/test_set_pop.py
new file mode 100644
index 0000000000..af4500e236
--- /dev/null
+++ b/integration_tests/test_set_pop.py
@@ -0,0 +1,26 @@
+def set_pop_str():
+ s: set[str] = {'a', 'b', 'c'}
+
+ assert s.pop() in {'a', 'b', 'c'}
+ assert len(s) == 2
+ assert s.pop() in {'a', 'b', 'c'}
+ assert s.pop() in {'a', 'b', 'c'}
+ assert len(s) == 0
+
+ s.add('d')
+ assert s.pop() == 'd'
+
+def set_pop_int():
+ s: set[i32] = {1, 2, 3}
+
+ assert s.pop() in {1, 2, 3}
+ assert len(s) == 2
+ assert s.pop() in {1, 2, 3}
+ assert s.pop() in {1, 2, 3}
+ assert len(s) == 0
+
+ s.add(4)
+ assert s.pop() == 4
+
+set_pop_str()
+set_pop_int()
diff --git a/integration_tests/test_str_01.py b/integration_tests/test_str_01.py
index a889a85d83..6be357aa3b 100644
--- a/integration_tests/test_str_01.py
+++ b/integration_tests/test_str_01.py
@@ -1,3 +1,5 @@
+from lpython import i32
+
def f():
x: str
x = "ok"
@@ -58,9 +60,38 @@ def test_str_repeat():
assert a*3 == "XyzXyzXyz"
assert a*2*3 == "XyzXyzXyzXyzXyzXyz"
assert 3*a*3 == "XyzXyzXyzXyzXyzXyzXyzXyzXyz"
- assert a*-1 == ""
+ b: str = a * -1
+ assert b == ""
assert len(a*(10**6)) == (3 * 10 ** 6)
+ # string repeat with a non-constant integer
+ s: str = "#"
+ n: i32 = 5
+
+ assert s * n == "#####"
+ assert n * s == "#####"
+
+ assert "@" * n == "@@@@@"
+ assert "@#$%" * n == "@#$%@#$%@#$%@#$%@#$%"
+
+ s = "@#$%"
+ assert n * s == "@#$%@#$%@#$%@#$%@#$%"
+
+ n = 10 ** 6
+ assert len(s * n) == (4 * 10 ** 6)
+
+ s = "$"
+ m: i32 = 2
+ n = 5
+ t: str = s * m * n
+ assert t == "$$$$$$$$$$"
+ assert s * m * 2 == "$$$$"
+ assert 2 * (m + n) * s == "$$$$$$$$$$$$$$"
+
+ t = 2 * (m + n) * "abc-"
+ assert t == "abc-abc-abc-abc-abc-abc-abc-abc-abc-abc-abc-abc-abc-abc-"
+
+
def test_str_join():
a: str
a = ","
diff --git a/integration_tests/test_str_attributes.py b/integration_tests/test_str_attributes.py
index 0a55e9e801..b8b24cf8fa 100755
--- a/integration_tests/test_str_attributes.py
+++ b/integration_tests/test_str_attributes.py
@@ -472,6 +472,31 @@ def is_numeric():
assert "".isnumeric() == False
assert "ab2%3".isnumeric() == False
+def center():
+ s: str = "test"
+ assert s.center(8,'*') == "**test**"
+ assert s.center(11) == " test "
+ assert s.center(2) == "test"
+ assert s.center(4) == "test"
+ assert s.center(9,'/') == "///test//"
+
+def expandtabs():
+ s: str = '01\t012\t0123\t01234'
+ assert s.expandtabs() == "01 012 0123 01234"
+ assert s.expandtabs(4) == "01 012 0123 01234"
+ assert s.expandtabs(-1) == "01012012301234"
+ s = '\t'
+ assert s.expandtabs() == " "
+ s = ''
+ assert s.expandtabs() == ""
+ s = '\tThis\ris\na\ttest'
+ assert s.expandtabs(4) == " This\ris\na test"
+ s = '\t\t\t'
+ assert s.expandtabs(2) == " "
+ s = 'test\ttest'
+ assert s.expandtabs(0) == "testtest"
+ assert s.expandtabs(-5) == "testtest"
+
def check():
capitalize()
lower()
@@ -492,6 +517,8 @@ def check():
is_space()
is_alnum()
is_numeric()
+ center()
+ expandtabs()
check()
diff --git a/share/jupyter/kernels/lpython/kernel.json.in b/share/jupyter/kernels/lpython/kernel.json.in
new file mode 100644
index 0000000000..e1af020ba4
--- /dev/null
+++ b/share/jupyter/kernels/lpython/kernel.json.in
@@ -0,0 +1,10 @@
+{
+ "display_name": "LPython",
+ "argv": [
+ "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/lpython",
+ "kernel",
+ "-f",
+ "{connection_file}"
+ ],
+ "language": "python"
+}
diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp
index ea8c873c88..25f7ca8119 100644
--- a/src/bin/lpython.cpp
+++ b/src/bin/lpython.cpp
@@ -29,10 +29,12 @@
#include
#include
#include
+#include
#include
#include
#include
#include
+#include
#include
#include
@@ -743,6 +745,11 @@ void print_time_report(std::vector> ×, bool
#ifdef HAVE_LFORTRAN_LLVM
+void section(const std::string &s)
+{
+ std::cout << color(LCompilers::style::bold) << color(LCompilers::fg::blue) << s << color(LCompilers::style::reset) << color(LCompilers::fg::reset) << std::endl;
+}
+
int emit_llvm(const std::string &infile,
const std::string &runtime_library_dir,
LCompilers::PassManager& pass_manager,
@@ -792,13 +799,239 @@ int emit_llvm(const std::string &infile,
return 0;
}
-int compile_python_to_object_file(
+bool determine_completeness(std::string command)
+{
+ auto get_last_line = [](std::string input) {
+ if(input.length() == 1) {
+ return input;
+ }
+ size_t position = input.length() - 2;
+ while ((!(input[position] == '\n' || input[position] == '\r')) && (position > 0)) {
+ position--;
+ }
+ if(input[position] == '\n' || input[position] == '\r') {
+ position += 1;
+ }
+ return input.substr(position);
+ };
+
+ std::string last_line = get_last_line(command);
+ if ((last_line.rfind("def", 0) == 0) ||
+ (last_line.rfind("for", 0) == 0) ||
+ (last_line.rfind("if", 0) == 0) ||
+ (last_line.rfind("else", 0) == 0) ||
+ (last_line.rfind("elif", 0) == 0) ||
+ (last_line.rfind("class", 0) == 0) ||
+ (last_line.rfind('@', 0) == 0) ||
+ (last_line.rfind(' ', 0) == 0) ||
+ (last_line.rfind('\t', 0) == 0)) {
+ return false;
+ }
+ return true;
+}
+
+int interactive_python_repl(
+ LCompilers::PassManager& pass_manager,
+ CompilerOptions &compiler_options,
+ bool verbose)
+{
+ Allocator al(4*1024);
+ compiler_options.interactive = true;
+ LCompilers::PythonCompiler fe(compiler_options);
+ LCompilers::diag::Diagnostics diagnostics;
+ LCompilers::LocationManager lm;
+ std::vector> times;
+ LCompilers::PythonCompiler::EvalResult r;
+
+ Terminal term(true, false);
+ std::cout << "Interactive LPython. Experimental prototype, not ready for end users." << std::endl;
+ std::string version = LFORTRAN_VERSION;
+ std::cout << "LPython version: " << version << std::endl;
+ std::cout << " * Use Ctrl-D to exit" << std::endl;
+ std::cout << " * Use Enter to submit" << std::endl;
+ std::cout << " * Use Alt-Enter or Ctrl-N to make a new line" << std::endl;
+ std::cout << " - Editing (Keys: Left, Right, Home, End, Backspace, Delete)" << std::endl;
+ std::cout << " - History (Keys: Up, Down)" << std::endl;
+
+ std::vector history;
+
+ std::function iscomplete = determine_completeness;
+
+ std::string code_string;
+ size_t cell_count = 0;
+ while (true) {
+ std::string code_string = prompt0(term, ">>> ", history, iscomplete);
+ if (code_string.size() == 1 && code_string[0] == CTRL_KEY('d')) {
+ std::cout << std::endl;
+ std::cout << "Exiting." << std::endl;
+ return 0;
+ }
+
+ {
+ cell_count++;
+ LCompilers::LocationManager::FileLocations fl;
+ fl.in_filename = "input";
+ std::ofstream out("input");
+ out << code_string;
+ lm.files.push_back(fl);
+ lm.init_simple(code_string);
+ lm.file_ends.push_back(code_string.size());
+ }
+
+ try {
+ auto evaluation_start_time = std::chrono::high_resolution_clock::now();
+ LCompilers::Result
+ res = fe.evaluate(code_string, verbose, lm, pass_manager, diagnostics);
+ if (res.ok) {
+ r = res.result;
+ } else {
+ LCOMPILERS_ASSERT(diagnostics.has_error())
+ std::cerr << diagnostics.render(lm, compiler_options);
+ diagnostics.clear();
+ continue;
+ }
+
+ auto evaluation_end_time = std::chrono::high_resolution_clock::now();
+ times.push_back(std::make_pair("evalution " + std::to_string(cell_count), std::chrono::duration
+ (evaluation_start_time - evaluation_end_time).count()));
+
+ } catch (const LCompilers::LCompilersException &e) {
+ std::cerr << "Internal Compiler Error: Unhandled exception" << std::endl;
+ std::vector d = e.stacktrace_addresses();
+ get_local_addresses(d);
+ get_local_info(d);
+ std::cerr << stacktrace2str(d, LCompilers::stacktrace_depth);
+ std::cerr << e.name() + ": " << e.msg() << std::endl;
+ continue;
+ }
+
+ if (verbose) {
+ section("AST:");
+ std::cout << r.ast << std::endl;
+ section("ASR:");
+ std::cout << r.asr << std::endl;
+ section("LLVM IR:");
+ std::cout << r.llvm_ir << std::endl;
+ }
+
+ switch (r.type) {
+ case (LCompilers::PythonCompiler::EvalResult::integer1) : {
+ if (verbose) std::cout << "Return type: i8" << std::endl;
+ if (verbose) section("Result:");
+ std::cout << r.i32 << std::endl;
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::integer2) : {
+ if (verbose) std::cout << "Return type: i16" << std::endl;
+ if (verbose) section("Result:");
+ std::cout << r.i64 << std::endl;
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::integer4) : {
+ if (verbose) std::cout << "Return type: i32" << std::endl;
+ if (verbose) section("Result:");
+ std::cout << r.i32 << std::endl;
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::integer8) : {
+ if (verbose) std::cout << "Return type: i64" << std::endl;
+ if (verbose) section("Result:");
+ std::cout << r.i64 << std::endl;
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::unsignedInteger1) : {
+ if (verbose) std::cout << "Return type: u8" << std::endl;
+ if (verbose) section("Result:");
+ std::cout << r.u32 << std::endl;
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::unsignedInteger2) : {
+ if (verbose) std::cout << "Return type: u16" << std::endl;
+ if (verbose) section("Result:");
+ std::cout << r.u64 << std::endl;
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::unsignedInteger4) : {
+ if (verbose) std::cout << "Return type: u32" << std::endl;
+ if (verbose) section("Result:");
+ std::cout << r.u32 << std::endl;
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::unsignedInteger8) : {
+ if (verbose) std::cout << "Return type: u64" << std::endl;
+ if (verbose) section("Result:");
+ std::cout << r.u64 << std::endl;
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::real4) : {
+ if (verbose) std::cout << "Return type: f32" << std::endl;
+ if (verbose) section("Result:");
+ std::cout << std::setprecision(8) << r.f32 << std::endl;
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::real8) : {
+ if (verbose) std::cout << "Return type: f64" << std::endl;
+ if (verbose) section("Result:");
+ std::cout << std::setprecision(17) << r.f64 << std::endl;
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::complex4) : {
+ if (verbose) std::cout << "Return type: c32" << std::endl;
+ if (verbose) section("Result:");
+ std::cout << std::setprecision(8) << "(" << r.c32.re << ", " << r.c32.im << ")" << std::endl;
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::complex8) : {
+ if (verbose) std::cout << "Return type: c64" << std::endl;
+ if (verbose) section("Result:");
+ std::cout << std::setprecision(17) << "(" << r.c64.re << ", " << r.c64.im << ")" << std::endl;
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::boolean) : {
+ if (verbose) std::cout << "Return type: logical" << std::endl;
+ if (verbose) section("Result:");
+ std::cout << (r.b ? "True" : "False") << std::endl;
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::string) : {
+ if (verbose) std::cout << "Return type: str" << std::endl;
+ if (verbose) section("Result:");
+ std::cout << (r.str == nullptr ? "" : r.str) << std::endl;
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::statement) : {
+ if (verbose) {
+ std::cout << "Return type: none" << std::endl;
+ section("Result:");
+ std::cout << "(statement)" << std::endl;
+ }
+ break;
+ }
+ case (LCompilers::PythonCompiler::EvalResult::none) : {
+ if (verbose) {
+ std::cout << "Return type: none" << std::endl;
+ section("Result:");
+ std::cout << "(nothing to execute)" << std::endl;
+ }
+ break;
+ }
+ default : throw LCompilers::LCompilersException("Return type not supported");
+ }
+ }
+ return 0;
+}
+
+/*
+ Compiles python to object file, if `to_jit` is false
+ otherwise execute python code using llvm JIT
+*/
+int compile_python_using_llvm(
const std::string &infile,
const std::string &outfile,
const std::string &runtime_library_dir,
LCompilers::PassManager& pass_manager,
CompilerOptions &compiler_options,
- bool time_report, bool arg_c=false)
+ bool time_report, bool arg_c=false, bool to_jit=false)
{
Allocator al(4*1024);
LCompilers::diag::Diagnostics diagnostics;
@@ -869,7 +1102,6 @@ int compile_python_to_object_file(
}
LCompilers::PythonCompiler fe(compiler_options);
LCompilers::LLVMEvaluator e(compiler_options.target);
- std::unique_ptr m;
auto asr_to_llvm_start = std::chrono::high_resolution_clock::now();
LCompilers::Result>
res = fe.get_llvm3(*asr, pass_manager, diagnostics, infile);
@@ -882,12 +1114,48 @@ int compile_python_to_object_file(
print_time_report(times, time_report);
return 3;
}
- m = std::move(res.result);
- auto llvm_start = std::chrono::high_resolution_clock::now();
- e.save_object_file(*(m->m_m), outfile);
- auto llvm_end = std::chrono::high_resolution_clock::now();
- times.push_back(std::make_pair("LLVM to binary", std::chrono::duration(llvm_end - llvm_start).count()));
- print_time_report(times, time_report);
+ std::unique_ptr m = std::move(res.result);
+
+ if (to_jit) {
+ LCompilers::LPython::DynamicLibrary cpython_lib;
+ LCompilers::LPython::DynamicLibrary symengine_lib;
+
+ if (compiler_options.enable_cpython) {
+ LCompilers::LPython::open_cpython_library(cpython_lib);
+ }
+ if (compiler_options.enable_symengine) {
+ LCompilers::LPython::open_symengine_library(symengine_lib);
+ }
+
+ auto llvm_start = std::chrono::high_resolution_clock::now();
+
+ bool call_stmts = false;
+ if (m->get_return_type("__module___main_____main__global_stmts") == "void") {
+ call_stmts = true;
+ }
+
+ e.add_module(std::move(m));
+ if (call_stmts) {
+ e.execfn("__module___main_____main__global_stmts");
+ }
+
+ if (compiler_options.enable_cpython) {
+ LCompilers::LPython::close_cpython_library(cpython_lib);
+ }
+ if (compiler_options.enable_symengine) {
+ LCompilers::LPython::close_symengine_library(symengine_lib);
+ }
+
+ auto llvm_end = std::chrono::high_resolution_clock::now();
+ times.push_back(std::make_pair("LLVM JIT execution", std::chrono::duration(llvm_end - llvm_start).count()));
+ print_time_report(times, time_report);
+ } else {
+ auto llvm_start = std::chrono::high_resolution_clock::now();
+ e.save_object_file(*(m->m_m), outfile);
+ auto llvm_end = std::chrono::high_resolution_clock::now();
+ times.push_back(std::make_pair("LLVM to binary", std::chrono::duration(llvm_end - llvm_start).count()));
+ print_time_report(times, time_report);
+ }
return 0;
}
@@ -1560,6 +1828,7 @@ int main(int argc, char *argv[])
bool print_rtl_header_dir = false;
bool print_rtl_dir = false;
bool separate_compilation = false;
+ bool to_jit = false;
std::string arg_fmt_file;
// int arg_fmt_indent = 4;
@@ -1593,6 +1862,7 @@ int main(int argc, char *argv[])
app.add_option("-I", compiler_options.import_paths, "Specify the paths"
"to look for the module")->allow_extra_args(false);
// app.add_option("-J", arg_J, "Where to save mod files");
+ app.add_flag("--jit", to_jit, "Execute the program using just-in-time (JIT) compiler");
app.add_flag("-g", compiler_options.emit_debug_info, "Compile with debugging information");
app.add_flag("--debug-with-line-column", compiler_options.emit_debug_line_column,
"Convert the linear location info into line + column in the debugging information");
@@ -1743,8 +2013,12 @@ int main(int argc, char *argv[])
// }
if (kernel) {
- std::cerr << "The kernel subcommand is not implemented yet for LPython." << std::endl;
- return 1;
+#ifdef HAVE_LFORTRAN_XEUS
+ return LCompilers::LPython::run_kernel(arg_kernel_f);
+#else
+ std::cerr << "The kernel subcommand requires LFortran to be compiled with XEUS support. Recompile with `WITH_XEUS=yes`." << std::endl;
+ return 1;
+#endif
}
// if (mod) {
@@ -1783,8 +2057,17 @@ int main(int argc, char *argv[])
}
if (arg_files.size() == 0) {
- std::cerr << "Interactive prompt is not implemented yet in LPython" << std::endl;
+#ifdef HAVE_LFORTRAN_LLVM
+ lpython_pass_manager.parse_pass_arg(arg_pass, skip_pass);
+ lpython_pass_manager.use_default_passes();
+ compiler_options.po.disable_main = true;
+ compiler_options.emit_debug_line_column = false;
+ compiler_options.generate_object_code = false;
+ return interactive_python_repl(lpython_pass_manager, compiler_options, arg_v);
+#else
+ std::cerr << "Interactive prompt requires the LLVM backend to be enabled. Recompile with `WITH_LLVM=yes`." << std::endl;
return 1;
+#endif
}
// TODO: for now we ignore the other filenames, only handle
@@ -1894,10 +2177,10 @@ int main(int argc, char *argv[])
}
}
- if (arg_c) {
+ if (arg_c && !to_jit) {
if (backend == Backend::llvm) {
#ifdef HAVE_LFORTRAN_LLVM
- return compile_python_to_object_file(arg_file, outfile, runtime_library_dir, lpython_pass_manager, compiler_options, time_report,
+ return compile_python_using_llvm(arg_file, outfile, runtime_library_dir, lpython_pass_manager, compiler_options, time_report,
arg_c);
#else
std::cerr << "The -c option requires the LLVM backend to be enabled. Recompile with `WITH_LLVM=yes`." << std::endl;
@@ -1911,6 +2194,23 @@ int main(int argc, char *argv[])
if (endswith(arg_file, ".py"))
{
int err = 0;
+ if (to_jit) {
+#ifdef HAVE_LFORTRAN_LLVM
+ if (backend != Backend::llvm) {
+ std::cerr << "JIT option is only available with LLVM backend" << std::endl;
+ return 1;
+ }
+ compiler_options.emit_debug_info = false;
+ compiler_options.emit_debug_line_column = false;
+ compiler_options.generate_object_code = false;
+ return compile_python_using_llvm(arg_file, "", runtime_library_dir,
+ lpython_pass_manager, compiler_options, time_report, false, true);
+#else
+ std::cerr << "Just-In-Time Compilation of Python files requires the LLVM backend to be enabled."
+ " Recompile with `WITH_LLVM=yes`." << std::endl;
+ return 1;
+#endif
+ }
if (backend == Backend::x86) {
err = compile_to_binary_x86(arg_file, outfile,
runtime_library_dir, compiler_options, time_report);
@@ -1931,7 +2231,7 @@ int main(int argc, char *argv[])
} else if (backend == Backend::llvm) {
#ifdef HAVE_LFORTRAN_LLVM
std::string tmp_o = outfile + ".tmp.o";
- err = compile_python_to_object_file(arg_file, tmp_o, runtime_library_dir,
+ err = compile_python_using_llvm(arg_file, tmp_o, runtime_library_dir,
lpython_pass_manager, compiler_options, time_report);
if (err != 0) return err;
err = link_executable({tmp_o}, outfile, runtime_library_dir,
diff --git a/src/libasr/ASR.asdl b/src/libasr/ASR.asdl
index 578e31692c..8feb600c09 100644
--- a/src/libasr/ASR.asdl
+++ b/src/libasr/ASR.asdl
@@ -15,7 +15,7 @@ symbol
| GenericProcedure(symbol_table parent_symtab, identifier name, symbol* procs, access access)
| CustomOperator(symbol_table parent_symtab, identifier name, symbol* procs, access access)
| ExternalSymbol(symbol_table parent_symtab, identifier name, symbol external, identifier module_name, identifier* scope_names, identifier original_name, access access)
- | StructType(symbol_table symtab, identifier name, identifier* dependencies, identifier* members, abi abi, access access, bool is_packed, bool is_abstract, call_arg* initializers, expr? alignment, symbol? parent)
+ | Struct(symbol_table symtab, identifier name, identifier* dependencies, identifier* members, identifier* member_functions, abi abi, access access, bool is_packed, bool is_abstract, call_arg* initializers, expr? alignment, symbol? parent)
| EnumType(symbol_table symtab, identifier name, identifier* dependencies, identifier* members, abi abi, access access, enumtype enum_value_type, ttype type, symbol? parent)
| UnionType(symbol_table symtab, identifier name, identifier* dependencies, identifier* members, abi abi, access access, call_arg* initializers, symbol? parent)
| Variable(symbol_table parent_symtab, identifier name, identifier* dependencies, intent intent, expr? symbolic_value, expr? value, storage_type storage, ttype type, symbol? type_declaration, abi abi, access access, presence presence, bool value_attr)
@@ -40,6 +40,7 @@ stmt
| ErrorStop(expr? code)
| Exit(identifier? stmt_name)
| ForAllSingle(do_loop_head head, stmt assign_stmt)
+ | ForEach(expr var, expr container, stmt* body)
| GoTo(int target_id, identifier name)
| GoToTarget(int id, identifier name)
| If(expr test, stmt* body, stmt* orelse)
@@ -74,6 +75,8 @@ stmt
| ListRemove(expr a, expr ele)
| ListClear(expr a)
| DictInsert(expr a, expr key, expr value)
+ | DictClear(expr a)
+ | SetClear(expr a)
| Expr(expr expression)
expr
@@ -85,7 +88,7 @@ expr
| IntrinsicArrayFunction(int arr_intrinsic_id, expr* args, int overload_id, ttype? type, expr? value)
| IntrinsicImpureFunction(int impure_intrinsic_id, expr* args, int overload_id, ttype? type, expr? value)
| TypeInquiry(int inquiry_id, ttype arg_type, expr? arg, ttype type, expr value)
- | StructTypeConstructor(symbol dt_sym, call_arg* args, ttype type, expr? value)
+ | StructConstructor(symbol dt_sym, call_arg* args, ttype type, expr? value)
| EnumTypeConstructor(symbol dt_sym, expr* args, ttype type, expr? value)
| UnionTypeConstructor(symbol dt_sym, expr* args, ttype type, expr? value)
| ImpliedDoLoop(expr* values, expr var, expr start, expr end, expr? increment, ttype type, expr? value)
@@ -118,12 +121,14 @@ expr
| ListConcat(expr left, expr right, ttype type, expr? value)
| ListCompare(expr left, cmpop op, expr right, ttype type, expr? value)
| ListCount(expr arg, expr ele, ttype type, expr? value)
+ | ListContains(expr left, expr right, ttype type, expr? value)
| SetConstant(expr* elements, ttype type)
| SetLen(expr arg, ttype type, expr? value)
| TupleConstant(expr* elements, ttype type)
| TupleLen(expr arg, ttype type, expr value)
| TupleCompare(expr left, cmpop op, expr right, ttype type, expr? value)
| TupleConcat(expr left, expr right, ttype type, expr? value)
+ | TupleContains(expr left, expr right, ttype type, expr? value)
| StringConstant(string s, ttype type)
| StringConcat(expr left, expr right, ttype type, expr? value)
| StringRepeat(expr left, expr right, ttype type, expr? value)
@@ -131,6 +136,7 @@ expr
| StringItem(expr arg, expr idx, ttype type, expr? value)
| StringSection(expr arg, expr? start, expr? end, expr? step, ttype type, expr? value)
| StringCompare(expr left, cmpop op, expr right, ttype type, expr? value)
+ | StringContains(expr left, expr right, ttype type, expr? value)
| StringOrd(expr arg, ttype type, expr? value)
| StringChr(expr arg, ttype type, expr? value)
| StringFormat(expr fmt, expr* args, string_format_kind kind, ttype type, expr? value)
@@ -176,6 +182,8 @@ expr
| ListRepeat(expr left, expr right, ttype type, expr? value)
| DictPop(expr a, expr key, ttype type, expr? value)
| SetPop(expr a, ttype type, expr? value)
+ | SetContains(expr left, expr right, ttype type, expr? value)
+ | DictContains(expr left, expr right, ttype type, expr? value)
| IntegerBitLen(expr a, ttype type, expr? value)
| Ichar(expr arg, ttype type, expr? value)
| Iachar(expr arg, ttype type, expr? value)
@@ -194,7 +202,7 @@ ttype
| Set(ttype type)
| List(ttype type)
| Tuple(ttype* type)
- | Struct(symbol derived_type)
+ | StructType(ttype* data_member_types, ttype* member_function_types, bool is_cstruct, symbol derived_type)
| Enum(symbol enum_type)
| Union(symbol union_type)
| Class(symbol class_type)
diff --git a/src/libasr/asr_scopes.cpp b/src/libasr/asr_scopes.cpp
index 4fae6739e8..c999eaec69 100644
--- a/src/libasr/asr_scopes.cpp
+++ b/src/libasr/asr_scopes.cpp
@@ -3,6 +3,7 @@
#include
#include
+#include
std::string lcompilers_unique_ID;
@@ -39,9 +40,13 @@ void SymbolTable::mark_all_variables_external(Allocator &al) {
case (ASR::symbolType::Function) : {
ASR::Function_t *v = ASR::down_cast(a.second);
ASR::FunctionType_t* v_func_type = ASR::down_cast(v->m_function_signature);
- v_func_type->m_abi = ASR::abiType::Interactive;
- v->m_body = nullptr;
- v->n_body = 0;
+ if (v_func_type->m_abi != ASR::abiType::Interactive) {
+ v_func_type->m_abi = ASR::abiType::Interactive;
+ v->m_body = nullptr;
+ v->n_body = 0;
+ PassUtils::UpdateDependenciesVisitor ud(al);
+ ud.visit_Function(*v);
+ }
break;
}
case (ASR::symbolType::Module) : {
diff --git a/src/libasr/asr_utils.cpp b/src/libasr/asr_utils.cpp
index 009076b33b..bcce3db313 100644
--- a/src/libasr/asr_utils.cpp
+++ b/src/libasr/asr_utils.cpp
@@ -414,8 +414,8 @@ void set_intrinsic(ASR::symbol_t* sym) {
func_sym_type->m_abi = ASR::abiType::Intrinsic;
break;
}
- case ASR::symbolType::StructType: {
- ASR::StructType_t* derived_type_sym = ASR::down_cast(sym);
+ case ASR::symbolType::Struct: {
+ ASR::Struct_t* derived_type_sym = ASR::down_cast(sym);
derived_type_sym->m_abi = ASR::abiType::Intrinsic;
break;
}
@@ -467,8 +467,8 @@ ASR::asr_t* getStructInstanceMember_t(Allocator& al, const Location& loc,
ASR::asr_t* v_var, ASR::symbol_t *v,
ASR::symbol_t* member, SymbolTable* current_scope) {
member = ASRUtils::symbol_get_past_external(member);
- if (ASR::is_a(*member)) {
- ASR::StructType_t* member_variable = ASR::down_cast(member);
+ if (ASR::is_a(*member)) {
+ ASR::Struct_t* member_variable = ASR::down_cast(member);
ASR::symbol_t *mem_es = nullptr;
std::string mem_name = "1_" + std::string(ASRUtils::symbol_name(member));
if (current_scope->resolve_symbol(mem_name)) {
@@ -480,7 +480,7 @@ ASR::asr_t* getStructInstanceMember_t(Allocator& al, const Location& loc,
nullptr, 0, member_variable->m_name, ASR::accessType::Public));
current_scope->add_symbol(mem_name, mem_es);
}
- ASR::ttype_t* member_type = ASRUtils::TYPE(ASR::make_Struct_t(al,
+ ASR::ttype_t* member_type = ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al,
member_variable->base.base.loc, mem_es));
return ASR::make_StructInstanceMember_t(al, loc, ASRUtils::EXPR(v_var),
mem_es, ASRUtils::fix_scoped_type(al, member_type, current_scope), nullptr);
@@ -493,8 +493,8 @@ ASR::asr_t* getStructInstanceMember_t(Allocator& al, const Location& loc,
ASR::dimension_t* m_dims = nullptr;
size_t n_dims = ASRUtils::extract_dimensions_from_ttype(member_type, m_dims);
switch( member_type_->type ) {
- case ASR::ttypeType::Struct: {
- ASR::Struct_t* der = ASR::down_cast(member_type_);
+ case ASR::ttypeType::StructType: {
+ ASR::StructType_t* der = ASR::down_cast(member_type_);
std::string der_type_name = ASRUtils::symbol_name(der->m_derived_type);
ASR::symbol_t* der_type_sym = current_scope->resolve_symbol(der_type_name);
if( der_type_sym == nullptr ) {
@@ -505,9 +505,9 @@ ASR::asr_t* getStructInstanceMember_t(Allocator& al, const Location& loc,
ASR::ExternalSymbol_t* m_ext = ASR::down_cast(m_external);
m_external = m_ext->m_external;
module_name = m_ext->m_module_name;
- } else if( ASR::is_a(*m_external) ) {
+ } else if( ASR::is_a(*m_external) ) {
ASR::symbol_t* asr_owner = ASRUtils::get_asr_owner(m_external);
- if( ASR::is_a(*asr_owner) ||
+ if( ASR::is_a(*asr_owner) ||
ASR::is_a(*asr_owner) ) {
module_name = ASRUtils::symbol_name(asr_owner);
}
@@ -543,10 +543,10 @@ ASR::asr_t* getStructInstanceMember_t(Allocator& al, const Location& loc,
} else {
der_ext = current_scope->get_symbol(mangled_name);
}
- ASR::asr_t* der_new = ASR::make_Struct_t(al, loc, der_ext);
+ ASR::asr_t* der_new = ASRUtils::make_StructType_t_util(al, loc, der_ext);
member_type_ = ASRUtils::TYPE(der_new);
} else if(ASR::is_a(*der_type_sym)) {
- member_type_ = ASRUtils::TYPE(ASR::make_Struct_t(al, loc, der_type_sym));
+ member_type_ = ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al, loc, der_type_sym));
}
member_type = ASRUtils::make_Array_t_util(al, loc,
member_type_, m_dims, n_dims);
@@ -586,13 +586,13 @@ bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right,
const std::function err) {
ASR::ttype_t *left_type = ASRUtils::expr_type(left);
ASR::ttype_t *right_type = ASRUtils::expr_type(right);
- ASR::StructType_t *left_struct = nullptr;
- if ( ASR::is_a(*left_type) ) {
- left_struct = ASR::down_cast(
- ASRUtils::symbol_get_past_external(ASR::down_cast(
+ ASR::Struct_t *left_struct = nullptr;
+ if ( ASR::is_a(*left_type) ) {
+ left_struct = ASR::down_cast(
+ ASRUtils::symbol_get_past_external(ASR::down_cast(
left_type)->m_derived_type));
} else if ( ASR::is_a(*left_type) ) {
- left_struct = ASR::down_cast(
+ left_struct = ASR::down_cast(
ASRUtils::symbol_get_past_external(ASR::down_cast(
left_type)->m_class_type));
}
@@ -666,8 +666,8 @@ bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right,
ASR::dimension_t* m_dims = nullptr;
size_t n_dims = ASRUtils::extract_dimensions_from_ttype(return_type, m_dims);
return_type = ASRUtils::type_get_past_array(return_type);
- if( ASR::is_a(*return_type) ) {
- ASR::Struct_t* struct_t = ASR::down_cast(return_type);
+ if( ASR::is_a(*return_type) ) {
+ ASR::StructType_t* struct_t = ASR::down_cast(return_type);
if( curr_scope->get_counter() !=
ASRUtils::symbol_parent_symtab(struct_t->m_derived_type)->get_counter() &&
!curr_scope->resolve_symbol(ASRUtils::symbol_name(struct_t->m_derived_type)) ) {
@@ -677,7 +677,7 @@ bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right,
ASRUtils::symbol_name(ASRUtils::get_asr_owner(struct_t->m_derived_type)), nullptr, 0,
ASRUtils::symbol_name(struct_t->m_derived_type), ASR::accessType::Public)));
}
- return_type = ASRUtils::TYPE(ASR::make_Struct_t(al, loc,
+ return_type = ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al, loc,
curr_scope->resolve_symbol(ASRUtils::symbol_name(struct_t->m_derived_type))));
if( is_array ) {
return_type = ASRUtils::make_Array_t_util(al, loc, return_type, m_dims, n_dims);
@@ -757,8 +757,8 @@ void process_overloaded_unary_minus_function(ASR::symbol_t* proc, ASR::expr_t* o
ASR::dimension_t* m_dims = nullptr;
size_t n_dims = ASRUtils::extract_dimensions_from_ttype(return_type, m_dims);
return_type = ASRUtils::type_get_past_array(return_type);
- if( ASR::is_a(*return_type) ) {
- ASR::Struct_t* struct_t = ASR::down_cast(return_type);
+ if( ASR::is_a(*return_type) ) {
+ ASR::StructType_t* struct_t = ASR::down_cast(return_type);
if( curr_scope->get_counter() !=
ASRUtils::symbol_parent_symtab(struct_t->m_derived_type)->get_counter() &&
!curr_scope->resolve_symbol(ASRUtils::symbol_name(struct_t->m_derived_type)) ) {
@@ -768,7 +768,7 @@ void process_overloaded_unary_minus_function(ASR::symbol_t* proc, ASR::expr_t* o
ASRUtils::symbol_name(ASRUtils::get_asr_owner(struct_t->m_derived_type)), nullptr, 0,
ASRUtils::symbol_name(struct_t->m_derived_type), ASR::accessType::Public)));
}
- return_type = ASRUtils::TYPE(ASR::make_Struct_t(al, loc,
+ return_type = ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al, loc,
curr_scope->resolve_symbol(ASRUtils::symbol_name(struct_t->m_derived_type))));
if( is_array ) {
return_type = ASRUtils::make_Array_t_util(
@@ -797,14 +797,14 @@ bool use_overloaded_unary_minus(ASR::expr_t* operand,
ASR::ttype_t *operand_type = ASRUtils::expr_type(operand);
ASR::symbol_t* sym = curr_scope->resolve_symbol("~sub");
if( !sym ) {
- if( ASR::is_a(*operand_type) ) {
- ASR::Struct_t* struct_t = ASR::down_cast(operand_type);
+ if( ASR::is_a(*operand_type) ) {
+ ASR::StructType_t* struct_t = ASR::down_cast(operand_type);
ASR::symbol_t* struct_t_sym = ASRUtils::symbol_get_past_external(struct_t->m_derived_type);
- if( ASR::is_a(*struct_t_sym) ) {
- ASR::StructType_t* struct_type_t = ASR::down_cast(struct_t_sym);
+ if( ASR::is_a(*struct_t_sym) ) {
+ ASR::Struct_t* struct_type_t = ASR::down_cast(struct_t_sym);
sym = struct_type_t->m_symtab->resolve_symbol("~sub");
while( sym == nullptr && struct_type_t->m_parent != nullptr ) {
- struct_type_t = ASR::down_cast(
+ struct_type_t = ASR::down_cast(
ASRUtils::symbol_get_past_external(struct_type_t->m_parent));
sym = struct_type_t->m_symtab->resolve_symbol("~sub");
}
@@ -850,7 +850,7 @@ bool use_overloaded_unary_minus(ASR::expr_t* operand,
}
bool is_op_overloaded(ASR::binopType op, std::string& intrinsic_op_name,
- SymbolTable* curr_scope, ASR::StructType_t* left_struct) {
+ SymbolTable* curr_scope, ASR::Struct_t* left_struct) {
bool result = true;
switch(op) {
case ASR::binopType::Add: {
@@ -972,14 +972,14 @@ bool use_overloaded_assignment(ASR::expr_t* target, ASR::expr_t* value,
ASR::symbol_t* sym = curr_scope->resolve_symbol("~assign");
ASR::expr_t* expr_dt = nullptr;
if( !sym ) {
- if( ASR::is_a(*target_type) ) {
- ASR::StructType_t* target_struct = ASR::down_cast(
- ASRUtils::symbol_get_past_external(ASR::down_cast(target_type)->m_derived_type));
+ if( ASR::is_a(*target_type) ) {
+ ASR::Struct_t* target_struct = ASR::down_cast(
+ ASRUtils::symbol_get_past_external(ASR::down_cast(target_type)->m_derived_type));
sym = target_struct->m_symtab->resolve_symbol("~assign");
expr_dt = target;
- } else if( ASR::is_a(*value_type) ) {
- ASR::StructType_t* value_struct = ASR::down_cast(
- ASRUtils::symbol_get_past_external(ASR::down_cast(value_type)->m_derived_type));
+ } else if( ASR::is_a(*value_type) ) {
+ ASR::Struct_t* value_struct = ASR::down_cast(
+ ASRUtils::symbol_get_past_external(ASR::down_cast(value_type)->m_derived_type));
sym = value_struct->m_symtab->resolve_symbol("~assign");
expr_dt = value;
}
@@ -1074,9 +1074,9 @@ bool use_overloaded_file_read_write(std::string &read_write, Vec a
ASR::symbol_t* sym = curr_scope->resolve_symbol(read_write);
ASR::expr_t* expr_dt = nullptr;
if( sym == nullptr ) {
- if( ASR::is_a(*arg_type) ) {
- ASR::StructType_t* arg_struct = ASR::down_cast(
- ASRUtils::symbol_get_past_external(ASR::down_cast(arg_type)->m_derived_type));
+ if( ASR::is_a(*arg_type) ) {
+ ASR::Struct_t* arg_struct = ASR::down_cast(
+ ASRUtils::symbol_get_past_external(ASR::down_cast(arg_type)->m_derived_type));
sym = arg_struct->m_symtab->resolve_symbol(read_write);
expr_dt = args[0];
}
@@ -1120,13 +1120,13 @@ bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right,
const std::function err) {
ASR::ttype_t *left_type = ASRUtils::expr_type(left);
ASR::ttype_t *right_type = ASRUtils::expr_type(right);
- ASR::StructType_t *left_struct = nullptr;
- if ( ASR::is_a(*left_type) ) {
- left_struct = ASR::down_cast(
- ASRUtils::symbol_get_past_external(ASR::down_cast(
+ ASR::Struct_t *left_struct = nullptr;
+ if ( ASR::is_a(*left_type) ) {
+ left_struct = ASR::down_cast(
+ ASRUtils::symbol_get_past_external(ASR::down_cast(
left_type)->m_derived_type));
} else if ( ASR::is_a(*left_type) ) {
- left_struct = ASR::down_cast(
+ left_struct = ASR::down_cast(
ASRUtils::symbol_get_past_external(ASR::down_cast(
left_type)->m_class_type));
}
@@ -1157,9 +1157,9 @@ bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right,
if( (left_arg_type->type == left_type->type &&
right_arg_type->type == right_type->type)
|| (ASR::is_a(*left_arg_type) &&
- ASR::is_a(*left_type))
+ ASR::is_a(*left_type))
|| (ASR::is_a(*right_arg_type) &&
- ASR::is_a(*right_type))) {
+ ASR::is_a(*right_type))) {
found = true;
Vec a_args;
a_args.reserve(al, 2);
@@ -1218,7 +1218,7 @@ bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right,
}
bool is_op_overloaded(ASR::cmpopType op, std::string& intrinsic_op_name,
- SymbolTable* curr_scope, ASR::StructType_t *left_struct) {
+ SymbolTable* curr_scope, ASR::Struct_t *left_struct) {
bool result = true;
switch(op) {
case ASR::cmpopType::Eq: {
diff --git a/src/libasr/asr_utils.h b/src/libasr/asr_utils.h
index a03c5b9b80..89f3adb0a5 100644
--- a/src/libasr/asr_utils.h
+++ b/src/libasr/asr_utils.h
@@ -441,8 +441,8 @@ static inline char *symbol_name(const ASR::symbol_t *f)
case ASR::symbolType::GenericProcedure: {
return ASR::down_cast(f)->m_name;
}
- case ASR::symbolType::StructType: {
- return ASR::down_cast(f)->m_name;
+ case ASR::symbolType::Struct: {
+ return ASR::down_cast(f)->m_name;
}
case ASR::symbolType::EnumType: {
return ASR::down_cast(f)->m_name;
@@ -554,8 +554,8 @@ static inline std::string type_to_str(const ASR::ttype_t *t)
case ASR::ttypeType::List: {
return "list";
}
- case ASR::ttypeType::Struct: {
- return ASRUtils::symbol_name(ASR::down_cast(t)->m_derived_type);
+ case ASR::ttypeType::StructType: {
+ return ASRUtils::symbol_name(ASR::down_cast(t)->m_derived_type);
}
case ASR::ttypeType::Class: {
return ASRUtils::symbol_name(ASR::down_cast(t)->m_class_type);
@@ -705,8 +705,8 @@ static inline std::pair symbol_dependencies(const ASR::symbol_t
ASR::Function_t* sym = ASR::down_cast(f);
return std::make_pair(sym->m_dependencies, sym->n_dependencies);
}
- case ASR::symbolType::StructType: {
- ASR::StructType_t* sym = ASR::down_cast(f);
+ case ASR::symbolType::Struct: {
+ ASR::Struct_t* sym = ASR::down_cast(f);
return std::make_pair(sym->m_dependencies, sym->n_dependencies);
}
case ASR::symbolType::EnumType: {
@@ -747,8 +747,8 @@ static inline SymbolTable *symbol_parent_symtab(const ASR::symbol_t *f)
case ASR::symbolType::GenericProcedure: {
return ASR::down_cast(f)->m_parent_symtab;
}
- case ASR::symbolType::StructType: {
- return ASR::down_cast(f)->m_symtab->parent;
+ case ASR::symbolType::Struct: {
+ return ASR::down_cast(f)->m_symtab->parent;
}
case ASR::symbolType::EnumType: {
return ASR::down_cast(f)->m_symtab->parent;
@@ -801,8 +801,8 @@ static inline SymbolTable *symbol_symtab(const ASR::symbol_t *f)
return nullptr;
//throw LCompilersException("GenericProcedure does not have a symtab");
}
- case ASR::symbolType::StructType: {
- return ASR::down_cast(f)->m_symtab;
+ case ASR::symbolType::Struct: {
+ return ASR::down_cast(f)->m_symtab;
}
case ASR::symbolType::EnumType: {
return ASR::down_cast(f)->m_symtab;
@@ -903,7 +903,7 @@ static inline bool is_c_ptr(ASR::symbol_t* v, std::string v_name="") {
v_name = ASRUtils::symbol_name(v);
}
ASR::symbol_t* v_orig = ASRUtils::symbol_get_past_external(v);
- if( ASR::is_a(*v_orig) ) {
+ if( ASR::is_a(*v_orig) ) {
ASR::Module_t* der_type_module = ASRUtils::get_sym_module0(v_orig);
return (der_type_module && std::string(der_type_module->m_name) ==
"lfortran_intrinsic_iso_c_binding" &&
@@ -1068,9 +1068,9 @@ static inline bool is_value_constant(ASR::expr_t *a_value) {
ASR::ArrayPhysicalCast_t*
array_physical_t = ASR::down_cast(a_value);
return is_value_constant(array_physical_t->m_arg);
- } case ASR::exprType::StructTypeConstructor: {
- ASR::StructTypeConstructor_t* struct_type_constructor =
- ASR::down_cast(a_value);
+ } case ASR::exprType::StructConstructor: {
+ ASR::StructConstructor_t* struct_type_constructor =
+ ASR::down_cast(a_value);
bool is_constant = true;
for( size_t i = 0; i < struct_type_constructor->n_args; i++ ) {
if( struct_type_constructor->m_args[i].m_value ) {
@@ -1481,8 +1481,8 @@ static inline std::string get_type_code(const ASR::ttype_t *t, bool use_undersco
case ASR::ttypeType::CPtr: {
return "CPtr";
}
- case ASR::ttypeType::Struct: {
- ASR::Struct_t* d = ASR::down_cast(t);
+ case ASR::ttypeType::StructType: {
+ ASR::StructType_t* d = ASR::down_cast(t);
if( ASRUtils::symbol_get_past_external(d->m_derived_type) ) {
res = symbol_name(ASRUtils::symbol_get_past_external(d->m_derived_type));
} else {
@@ -1635,8 +1635,8 @@ static inline std::string type_to_str_python(const ASR::ttype_t *t,
case ASR::ttypeType::CPtr: {
return "CPtr";
}
- case ASR::ttypeType::Struct: {
- ASR::Struct_t* d = ASR::down_cast(t);
+ case ASR::ttypeType::StructType: {
+ ASR::StructType_t* d = ASR::down_cast(t);
return "struct " + std::string(symbol_name(d->m_derived_type));
}
case ASR::ttypeType::Enum: {
@@ -1936,7 +1936,7 @@ bool use_overloaded_unary_minus(ASR::expr_t* operand,
const std::function err);
bool is_op_overloaded(ASR::binopType op, std::string& intrinsic_op_name,
- SymbolTable* curr_scope, ASR::StructType_t* left_struct=nullptr);
+ SymbolTable* curr_scope, ASR::Struct_t* left_struct=nullptr);
bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right,
ASR::cmpopType op, std::string& intrinsic_op_name,
@@ -1947,7 +1947,7 @@ bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right,
const std::function err);
bool is_op_overloaded(ASR::cmpopType op, std::string& intrinsic_op_name,
- SymbolTable* curr_scope, ASR::StructType_t *left_struct);
+ SymbolTable* curr_scope, ASR::Struct_t *left_struct);
bool use_overloaded_assignment(ASR::expr_t* target, ASR::expr_t* value,
SymbolTable* curr_scope, ASR::asr_t*& asr,
@@ -2149,7 +2149,7 @@ inline size_t extract_dimensions_from_ttype(ASR::ttype_t *x,
case ASR::ttypeType::Complex:
case ASR::ttypeType::Character:
case ASR::ttypeType::Logical:
- case ASR::ttypeType::Struct:
+ case ASR::ttypeType::StructType:
case ASR::ttypeType::Enum:
case ASR::ttypeType::Union:
case ASR::ttypeType::Class:
@@ -2420,7 +2420,7 @@ inline bool ttype_set_dimensions(ASR::ttype_t** x,
case ASR::ttypeType::Complex:
case ASR::ttypeType::Character:
case ASR::ttypeType::Logical:
- case ASR::ttypeType::Struct:
+ case ASR::ttypeType::StructType:
case ASR::ttypeType::Enum:
case ASR::ttypeType::Union:
case ASR::ttypeType::TypeParameter: {
@@ -2450,6 +2450,42 @@ static inline bool is_aggregate_type(ASR::ttype_t* asr_type) {
static inline ASR::dimension_t* duplicate_dimensions(Allocator& al, ASR::dimension_t* m_dims, size_t n_dims);
+static inline ASR::asr_t* make_StructType_t_util(Allocator& al, Location loc, ASR::symbol_t* der){
+ ASR::Struct_t* st = ASR::down_cast(ASRUtils::symbol_get_past_external(der));
+ Vec members;
+ members.reserve(al, 1);
+ Vec member_functions;
+ member_functions.reserve(al, 1);
+ SymbolTable* current_scope = st->m_symtab;
+ for(size_t i = 0; i < st->n_members; i++){
+ ASR::symbol_t* temp = current_scope->get_symbol(st->m_members[i]);
+ if(ASR::is_a(*temp)){
+ ASR::Variable_t* var = ASR::down_cast(
+ ASRUtils::symbol_get_past_external(temp));
+ members.push_back(al,var->m_type);
+ }
+ }
+ for(size_t i = 0; i < st->n_member_functions; i++){
+ ASR::symbol_t* sym = current_scope->get_symbol(st->m_member_functions[i]);
+ if(sym && ASR::is_a(*sym)){
+ ASR::Function_t *f = ASR::down_cast(
+ ASRUtils::symbol_get_past_external(sym));
+ ASR::ttype_t* f_type = f->m_function_signature;
+ member_functions.push_back(al, f_type);
+ }
+ }
+ bool is_cstruct = member_functions.n == 0;
+ return ASR::make_StructType_t(al,
+ loc,
+ members.p,
+ members.n,
+ member_functions.p,
+ member_functions.n,
+ is_cstruct,
+ der);
+
+}
+
static inline ASR::ttype_t* duplicate_type(Allocator& al, const ASR::ttype_t* t,
Vec* dims=nullptr,
ASR::array_physical_typeType physical_type=ASR::array_physical_typeType::DescriptorArray,
@@ -2504,9 +2540,15 @@ static inline ASR::ttype_t* duplicate_type(Allocator& al, const ASR::ttype_t* t,
tnew->m_kind, tnew->m_len, tnew->m_len_expr));
break;
}
- case ASR::ttypeType::Struct: {
- ASR::Struct_t* tnew = ASR::down_cast(t);
- t_ = ASRUtils::TYPE(ASR::make_Struct_t(al, t->base.loc, tnew->m_derived_type));
+ case ASR::ttypeType::StructType: {
+ ASR::StructType_t* tnew = ASR::down_cast(t);
+ t_ = ASRUtils::TYPE(ASR::make_StructType_t(al, t->base.loc,
+ tnew->m_data_member_types,
+ tnew->n_data_member_types,
+ tnew->m_member_function_types,
+ tnew->n_member_function_types,
+ tnew->m_is_cstruct,
+ tnew->m_derived_type));
break;
}
case ASR::ttypeType::Class: {
@@ -2654,9 +2696,15 @@ static inline ASR::ttype_t* duplicate_type_without_dims(Allocator& al, const ASR
return ASRUtils::TYPE(ASR::make_Character_t(al, loc,
tnew->m_kind, tnew->m_len, tnew->m_len_expr));
}
- case ASR::ttypeType::Struct: {
- ASR::Struct_t* tstruct = ASR::down_cast(t);
- return ASRUtils::TYPE(ASR::make_Struct_t(al, loc, tstruct->m_derived_type));
+ case ASR::ttypeType::StructType: {
+ ASR::StructType_t* tstruct = ASR::down_cast(t);
+ return ASRUtils::TYPE(ASR::make_StructType_t(al, t->base.loc,
+ tstruct->m_data_member_types,
+ tstruct->n_data_member_types,
+ tstruct->m_member_function_types,
+ tstruct->n_member_function_types,
+ tstruct->m_is_cstruct,
+ tstruct->m_derived_type));
}
case ASR::ttypeType::Pointer: {
ASR::Pointer_t* ptr = ASR::down_cast(t);
@@ -2698,8 +2746,8 @@ inline bool is_same_type_pointer(ASR::ttype_t* source, ASR::ttype_t* dest) {
dest = temp;
}
dest = ASRUtils::type_get_past_array(ASR::down_cast(dest)->m_type);
- if( (ASR::is_a(*source) || ASR::is_a(*source)) &&
- (ASR::is_a(*dest) || ASR::is_a(*dest)) ) {
+ if( (ASR::is_a(*source) || ASR::is_a(*source)) &&
+ (ASR::is_a(*dest) || ASR::is_a(*dest)) ) {
return true;
}
bool res = source->type == dest->type;
@@ -2872,20 +2920,20 @@ inline bool is_parent(SymbolTable* a, SymbolTable* b) {
return false;
}
-inline bool is_parent(ASR::StructType_t* a, ASR::StructType_t* b) {
+inline bool is_parent(ASR::Struct_t* a, ASR::Struct_t* b) {
ASR::symbol_t* current_parent = b->m_parent;
while( current_parent ) {
current_parent = ASRUtils::symbol_get_past_external(current_parent);
if( current_parent == (ASR::symbol_t*) a ) {
return true;
}
- LCOMPILERS_ASSERT(ASR::is_a(*current_parent));
- current_parent = ASR::down_cast(current_parent)->m_parent;
+ LCOMPILERS_ASSERT(ASR::is_a(*current_parent));
+ current_parent = ASR::down_cast(current_parent)->m_parent;
}
return false;
}
-inline bool is_derived_type_similar(ASR::StructType_t* a, ASR::StructType_t* b) {
+inline bool is_derived_type_similar(ASR::Struct_t* a, ASR::Struct_t* b) {
return a == b || is_parent(a, b) || is_parent(b, a) ||
(std::string(a->m_name) == "~abstract_type" &&
std::string(b->m_name) == "~abstract_type");
@@ -3080,13 +3128,13 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b,
ASR::List_t *b2 = ASR::down_cast(b);
return types_equal(a2->m_type, b2->m_type);
}
- case (ASR::ttypeType::Struct) : {
- ASR::Struct_t *a2 = ASR::down_cast(a);
- ASR::Struct_t *b2 = ASR::down_cast(b);
- ASR::StructType_t *a2_type = ASR::down_cast(
+ case (ASR::ttypeType::StructType) : {
+ ASR::StructType_t *a2 = ASR::down_cast(a);
+ ASR::StructType_t *b2 = ASR::down_cast(b);
+ ASR::Struct_t *a2_type = ASR::down_cast(
ASRUtils::symbol_get_past_external(
a2->m_derived_type));
- ASR::StructType_t *b2_type = ASR::down_cast(
+ ASR::Struct_t *b2_type = ASR::down_cast(
ASRUtils::symbol_get_past_external(
b2->m_derived_type));
return a2_type == b2_type;
@@ -3103,9 +3151,9 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b,
ASR::ClassType_t *a2_type = ASR::down_cast(a2_typesym);
ASR::ClassType_t *b2_type = ASR::down_cast(b2_typesym);
return a2_type == b2_type;
- } else if( a2_typesym->type == ASR::symbolType::StructType ) {
- ASR::StructType_t *a2_type = ASR::down_cast(a2_typesym);
- ASR::StructType_t *b2_type = ASR::down_cast(b2_typesym);
+ } else if( a2_typesym->type == ASR::symbolType::Struct ) {
+ ASR::Struct_t *a2_type = ASR::down_cast(a2_typesym);
+ ASR::Struct_t *b2_type = ASR::down_cast(b2_typesym);
return is_derived_type_similar(a2_type, b2_type);
}
return false;
@@ -3141,9 +3189,9 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b,
}
default : return false;
}
- } else if( a->type == ASR::ttypeType::Struct &&
+ } else if( a->type == ASR::ttypeType::StructType &&
b->type == ASR::ttypeType::Class ) {
- ASR::Struct_t *a2 = ASR::down_cast(a);
+ ASR::StructType_t *a2 = ASR::down_cast(a);
ASR::Class_t *b2 = ASR::down_cast(b);
ASR::symbol_t* a2_typesym = ASRUtils::symbol_get_past_external(a2->m_derived_type);
ASR::symbol_t* b2_typesym = ASRUtils::symbol_get_past_external(b2->m_class_type);
@@ -3154,15 +3202,15 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b,
ASR::ClassType_t *a2_type = ASR::down_cast(a2_typesym);
ASR::ClassType_t *b2_type = ASR::down_cast(b2_typesym);
return a2_type == b2_type;
- } else if( a2_typesym->type == ASR::symbolType::StructType ) {
- ASR::StructType_t *a2_type = ASR::down_cast(a2_typesym);
- ASR::StructType_t *b2_type = ASR::down_cast(b2_typesym);
+ } else if( a2_typesym->type == ASR::symbolType::Struct ) {
+ ASR::Struct_t *a2_type = ASR::down_cast(a2_typesym);
+ ASR::Struct_t *b2_type = ASR::down_cast(b2_typesym);
return is_derived_type_similar(a2_type, b2_type);
}
} else if( a->type == ASR::ttypeType::Class &&
- b->type == ASR::ttypeType::Struct ) {
+ b->type == ASR::ttypeType::StructType ) {
ASR::Class_t *a2 = ASR::down_cast(a);
- ASR::Struct_t *b2 = ASR::down_cast(b);
+ ASR::StructType_t *b2 = ASR::down_cast(b);
ASR::symbol_t* a2_typesym = ASRUtils::symbol_get_past_external(a2->m_class_type);
ASR::symbol_t* b2_typesym = ASRUtils::symbol_get_past_external(b2->m_derived_type);
if( a2_typesym->type != b2_typesym->type ) {
@@ -3172,9 +3220,9 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b,
ASR::ClassType_t *a2_type = ASR::down_cast(a2_typesym);
ASR::ClassType_t *b2_type = ASR::down_cast(b2_typesym);
return a2_type == b2_type;
- } else if( a2_typesym->type == ASR::symbolType::StructType ) {
- ASR::StructType_t *a2_type = ASR::down_cast(a2_typesym);
- ASR::StructType_t *b2_type = ASR::down_cast(b2_typesym);
+ } else if( a2_typesym->type == ASR::symbolType::Struct ) {
+ ASR::Struct_t *a2_type = ASR::down_cast(a2_typesym);
+ ASR::Struct_t *b2_type = ASR::down_cast(b2_typesym);
return is_derived_type_similar(a2_type, b2_type);
}
}
@@ -3263,13 +3311,13 @@ inline bool types_equal_with_substitution(ASR::ttype_t *a, ASR::ttype_t *b,
ASR::List_t *b2 = ASR::down_cast(b);
return types_equal_with_substitution(a2->m_type, b2->m_type, subs);
}
- case (ASR::ttypeType::Struct) : {
- ASR::Struct_t *a2 = ASR::down_cast(a);
- ASR::Struct_t *b2 = ASR::down_cast(b);
- ASR::StructType_t *a2_type = ASR::down_cast(
+ case (ASR::ttypeType::StructType) : {
+ ASR::StructType_t *a2 = ASR::down_cast(a);
+ ASR::StructType_t *b2 = ASR::down_cast(b);
+ ASR::Struct_t *a2_type = ASR::down_cast(
ASRUtils::symbol_get_past_external(
a2->m_derived_type));
- ASR::StructType_t *b2_type = ASR::down_cast(
+ ASR::Struct_t *b2_type = ASR::down_cast(
ASRUtils::symbol_get_past_external(
b2->m_derived_type));
return a2_type == b2_type;
@@ -3286,9 +3334,9 @@ inline bool types_equal_with_substitution(ASR::ttype_t *a, ASR::ttype_t *b,
ASR::ClassType_t *a2_type = ASR::down_cast(a2_typesym);
ASR::ClassType_t *b2_type = ASR::down_cast(b2_typesym);
return a2_type == b2_type;
- } else if( a2_typesym->type == ASR::symbolType::StructType ) {
- ASR::StructType_t *a2_type = ASR::down_cast(a2_typesym);
- ASR::StructType_t *b2_type = ASR::down_cast(b2_typesym);
+ } else if( a2_typesym->type == ASR::symbolType::Struct ) {
+ ASR::Struct_t *a2_type = ASR::down_cast(a2_typesym);
+ ASR::Struct_t *b2_type = ASR::down_cast(b2_typesym);
return is_derived_type_similar(a2_type, b2_type);
}
return false;
@@ -3324,9 +3372,9 @@ inline bool types_equal_with_substitution(ASR::ttype_t *a, ASR::ttype_t *b,
}
default : return false;
}
- } else if( a->type == ASR::ttypeType::Struct &&
+ } else if( a->type == ASR::ttypeType::StructType &&
b->type == ASR::ttypeType::Class ) {
- ASR::Struct_t *a2 = ASR::down_cast(a);
+ ASR::StructType_t *a2 = ASR::down_cast(a);
ASR::Class_t *b2 = ASR::down_cast(b);
ASR::symbol_t* a2_typesym = ASRUtils::symbol_get_past_external(a2->m_derived_type);
ASR::symbol_t* b2_typesym = ASRUtils::symbol_get_past_external(b2->m_class_type);
@@ -3337,15 +3385,15 @@ inline bool types_equal_with_substitution(ASR::ttype_t *a, ASR::ttype_t *b,
ASR::ClassType_t *a2_type = ASR::down_cast(a2_typesym);
ASR::ClassType_t *b2_type = ASR::down_cast(b2_typesym);
return a2_type == b2_type;
- } else if( a2_typesym->type == ASR::symbolType::StructType ) {
- ASR::StructType_t *a2_type = ASR::down_cast(a2_typesym);
- ASR::StructType_t *b2_type = ASR::down_cast(b2_typesym);
+ } else if( a2_typesym->type == ASR::symbolType::Struct ) {
+ ASR::Struct_t *a2_type = ASR::down_cast(a2_typesym);
+ ASR::Struct_t *b2_type = ASR::down_cast(b2_typesym);
return is_derived_type_similar(a2_type, b2_type);
}
} else if( a->type == ASR::ttypeType::Class &&
- b->type == ASR::ttypeType::Struct ) {
+ b->type == ASR::ttypeType::StructType ) {
ASR::Class_t *a2 = ASR::down_cast(a);
- ASR::Struct_t *b2 = ASR::down_cast(b);
+ ASR::StructType_t *b2 = ASR::down_cast(b);
ASR::symbol_t* a2_typesym = ASRUtils::symbol_get_past_external(a2->m_class_type);
ASR::symbol_t* b2_typesym = ASRUtils::symbol_get_past_external(b2->m_derived_type);
if( a2_typesym->type != b2_typesym->type ) {
@@ -3355,9 +3403,9 @@ inline bool types_equal_with_substitution(ASR::ttype_t *a, ASR::ttype_t *b,
ASR::ClassType_t *a2_type = ASR::down_cast(a2_typesym);
ASR::ClassType_t *b2_type = ASR::down_cast(b2_typesym);
return a2_type == b2_type;
- } else if( a2_typesym->type == ASR::symbolType::StructType ) {
- ASR::StructType_t *a2_type = ASR::down_cast(a2_typesym);
- ASR::StructType_t *b2_type = ASR::down_cast(b2_typesym);
+ } else if( a2_typesym->type == ASR::symbolType::Struct ) {
+ ASR::Struct_t *a2_type = ASR::down_cast(a2_typesym);
+ ASR::Struct_t *b2_type = ASR::down_cast(b2_typesym);
return is_derived_type_similar(a2_type, b2_type);
}
}
@@ -3607,8 +3655,8 @@ static inline ASR::symbol_t* import_struct_instance_member(Allocator& al, ASR::s
mem_type = ASRUtils::type_get_past_array(
ASRUtils::type_get_past_pointer(
ASRUtils::type_get_past_allocatable(mem_type)));
- if( mem_type && ASR::is_a(*mem_type) ) {
- ASR::Struct_t* struct_t = ASR::down_cast(mem_type);
+ if( mem_type && ASR::is_a(*mem_type) ) {
+ ASR::StructType_t* struct_t = ASR::down_cast(mem_type);
std::string struct_type_name = ASRUtils::symbol_name(struct_t->m_derived_type);
ASR::symbol_t* struct_t_m_derived_type = ASRUtils::symbol_get_past_external(struct_t->m_derived_type);
if( scope->resolve_symbol(struct_type_name) == nullptr ) {
@@ -3621,9 +3669,10 @@ static inline ASR::symbol_t* import_struct_instance_member(Allocator& al, ASR::s
nullptr, 0, s2c(al, struct_type_name), ASR::accessType::Public));
scope->add_symbol(struct_type_name_, imported_struct_type);
}
- mem_type = ASRUtils::TYPE(ASR::make_Struct_t(al, mem_type->base.loc, scope->get_symbol(struct_type_name_)));
+ mem_type = ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al, mem_type->base.loc,
+ scope->get_symbol(struct_type_name_)));
} else {
- mem_type = ASRUtils::TYPE(ASR::make_Struct_t(al, mem_type->base.loc,
+ mem_type = ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al, mem_type->base.loc,
scope->resolve_symbol(struct_type_name)));
}
}
@@ -3853,7 +3902,7 @@ class FixScopedTypeVisitor: public ASR::BaseExprReplacer {
FixScopedTypeVisitor(Allocator& al_, SymbolTable* current_scope_) :
al(al_), current_scope(current_scope_) {}
- void replace_Struct(ASR::Struct_t* x) {
+ void replace_StructType(ASR::StructType_t* x) {
ASR::symbol_t* m_derived_type = current_scope->resolve_symbol(
ASRUtils::symbol_name(x->m_derived_type));
if (m_derived_type == nullptr) {
@@ -3924,7 +3973,7 @@ class ReplaceWithFunctionParamVisitor: public ASR::BaseExprReplacerm_derived_type);
ASR::symbol_t* derived_type_sym = current_scope->resolve_symbol(derived_type_name);
LCOMPILERS_ASSERT_MSG( derived_type_sym != nullptr,
@@ -4080,9 +4129,9 @@ class SymbolDuplicator {
new_symbol_name = block->m_name;
break;
}
- case ASR::symbolType::StructType: {
- ASR::StructType_t* struct_type = ASR::down_cast(symbol);
- new_symbol = duplicate_StructType(struct_type, destination_symtab);
+ case ASR::symbolType::Struct: {
+ ASR::Struct_t* struct_type = ASR::down_cast(symbol);
+ new_symbol = duplicate_Struct(struct_type, destination_symtab);
new_symbol_name = struct_type->m_name;
break;
}
@@ -4114,8 +4163,8 @@ class SymbolDuplicator {
if( !node_duplicator.success ) {
return nullptr;
}
- if (ASR::is_a(*m_type)) {
- ASR::Struct_t* st = ASR::down_cast(m_type);
+ if (ASR::is_a(*m_type)) {
+ ASR::StructType_t* st = ASR::down_cast(m_type);
std::string derived_type_name = ASRUtils::symbol_name(st->m_derived_type);
ASR::symbol_t* derived_type_sym = destination_symtab->resolve_symbol(derived_type_name);
LCOMPILERS_ASSERT_MSG( derived_type_sym != nullptr, "derived_type_sym cannot be nullptr");
@@ -4255,14 +4304,16 @@ class SymbolDuplicator {
new_body.p, new_body.size()));
}
- ASR::symbol_t* duplicate_StructType(ASR::StructType_t* struct_type_t,
+ ASR::symbol_t* duplicate_Struct(ASR::Struct_t* struct_type_t,
SymbolTable* destination_symtab) {
SymbolTable* struct_type_symtab = al.make_new(destination_symtab);
duplicate_SymbolTable(struct_type_t->m_symtab, struct_type_symtab);
- return ASR::down_cast(ASR::make_StructType_t(
+ return ASR::down_cast(ASR::make_Struct_t(
al, struct_type_t->base.base.loc, struct_type_symtab,
struct_type_t->m_name, struct_type_t->m_dependencies, struct_type_t->n_dependencies,
- struct_type_t->m_members, struct_type_t->n_members, struct_type_t->m_abi,
+ struct_type_t->m_members, struct_type_t->n_members,
+ struct_type_t->m_member_functions, struct_type_t->n_member_functions,
+ struct_type_t->m_abi,
struct_type_t->m_access, struct_type_t->m_is_packed, struct_type_t->m_is_abstract,
struct_type_t->m_initializers, struct_type_t->n_initializers, struct_type_t->m_alignment,
struct_type_t->m_parent));
@@ -4515,7 +4566,7 @@ static inline bool is_pass_array_by_data_possible(ASR::Function_t* x, std::vecto
argi->m_intent == ASRUtils::intent_out ||
argi->m_intent == ASRUtils::intent_inout) &&
!ASR::is_a(*argi->m_type) &&
- !ASR::is_a(*argi->m_type) &&
+ !ASR::is_a