diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index b05315e..fec59f8 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -27,7 +27,6 @@ jobs: pr_sha: ${{ github.event.pull_request.head.sha }} tests: - needs: check-branch timeout-minutes: 10 strategy: matrix: diff --git a/conda/dev.yaml b/conda/dev.yaml index febf865..832ca74 100644 --- a/conda/dev.yaml +++ b/conda/dev.yaml @@ -15,3 +15,4 @@ dependencies: # fix issues with distlib - paginate - pyrepl + - msgpack-python diff --git a/conda/release.yaml b/conda/release.yaml index 1a25173..4874722 100644 --- a/conda/release.yaml +++ b/conda/release.yaml @@ -15,3 +15,4 @@ dependencies: # fix issues with distlib - paginate - pyrepl + - msgpack-python diff --git a/poetry.lock b/poetry.lock index baf7f40..d0009b8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -109,6 +109,23 @@ types-python-dateutil = ">=2.8.10" doc = ["doc8", "sphinx (>=7.0.0)", "sphinx-autobuild", "sphinx-autodoc-typehints", "sphinx_rtd_theme (>=1.3.0)"] test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "pytz (==2021.1)", "simplejson (==3.*)"] +[[package]] +name = "asciinet" +version = "0.3.1" +description = "A wrapper around the scala ascii-graphs library" +optional = false +python-versions = "*" +files = [ + {file = "asciinet-0.3.1-py3-none-any.whl", hash = "sha256:0aa8754ee9d9eff839f3f6dc3c25f79f486eea5bdd7c1aef4f88062b727b8dbd"}, + {file = "asciinet-0.3.1.tar.gz", hash = "sha256:9830641c81c5b7930c442d7fee4add01fc0518fc4f2f5e5d53de866010074a41"}, +] + +[package.dependencies] +msgpack-python = ">=0.4.2" +natsort = ">=3.2.0" +networkx = ">=1.9" +requests = ">=2.3.0" + [[package]] name = "asttokens" version = "2.4.1" @@ -144,18 +161,20 @@ wheel = ">=0.23.0,<1.0" [[package]] name = "astx" -version = "0.12.2" +version = "0.15.0" description = "ASTx is an agnostic expression structure for AST." optional = false python-versions = "<4,>=3.8.1" files = [ - {file = "astx-0.12.2-py3-none-any.whl", hash = "sha256:d53df84784f8678204d38e63fda6e35c3a039796372b607f6fa57adfa8987f39"}, - {file = "astx-0.12.2.tar.gz", hash = "sha256:ff6f19f0c735d8cf3d347e9a740b43fa8b5a163a74a5544ef3de57ad60dd52a3"}, + {file = "astx-0.15.0-py3-none-any.whl", hash = "sha256:53dd96d52cdbb478c752501a2dc4dfc99cb4289aacaa1e663434beb519e107aa"}, + {file = "astx-0.15.0.tar.gz", hash = "sha256:b18bc36e8383397526396c48f77806e61c84027f1078f0a8b744996b9bc5fa59"}, ] [package.dependencies] +asciinet = ">=0.3.1" atpublic = ">=4.0" graphviz = ">=0.20.1" +msgpack = ">=1" typing-extensions = {version = ">=4", markers = "python_version < \"3.9\""} [[package]] @@ -1947,6 +1966,81 @@ files = [ griffe = ">=0.44" mkdocstrings = ">=0.24.2" +[[package]] +name = "msgpack" +version = "1.0.8" +description = "MessagePack serializer" +optional = false +python-versions = ">=3.8" +files = [ + {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:505fe3d03856ac7d215dbe005414bc28505d26f0c128906037e66d98c4e95868"}, + {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b7842518a63a9f17107eb176320960ec095a8ee3b4420b5f688e24bf50c53c"}, + {file = "msgpack-1.0.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:376081f471a2ef24828b83a641a02c575d6103a3ad7fd7dade5486cad10ea659"}, + {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e390971d082dba073c05dbd56322427d3280b7cc8b53484c9377adfbae67dc2"}, + {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e073efcba9ea99db5acef3959efa45b52bc67b61b00823d2a1a6944bf45982"}, + {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82d92c773fbc6942a7a8b520d22c11cfc8fd83bba86116bfcf962c2f5c2ecdaa"}, + {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9ee32dcb8e531adae1f1ca568822e9b3a738369b3b686d1477cbc643c4a9c128"}, + {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e3aa7e51d738e0ec0afbed661261513b38b3014754c9459508399baf14ae0c9d"}, + {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69284049d07fce531c17404fcba2bb1df472bc2dcdac642ae71a2d079d950653"}, + {file = "msgpack-1.0.8-cp310-cp310-win32.whl", hash = "sha256:13577ec9e247f8741c84d06b9ece5f654920d8365a4b636ce0e44f15e07ec693"}, + {file = "msgpack-1.0.8-cp310-cp310-win_amd64.whl", hash = "sha256:e532dbd6ddfe13946de050d7474e3f5fb6ec774fbb1a188aaf469b08cf04189a"}, + {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9517004e21664f2b5a5fd6333b0731b9cf0817403a941b393d89a2f1dc2bd836"}, + {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d16a786905034e7e34098634b184a7d81f91d4c3d246edc6bd7aefb2fd8ea6ad"}, + {file = "msgpack-1.0.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2872993e209f7ed04d963e4b4fbae72d034844ec66bc4ca403329db2074377b"}, + {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c330eace3dd100bdb54b5653b966de7f51c26ec4a7d4e87132d9b4f738220ba"}, + {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b5c044f3eff2a6534768ccfd50425939e7a8b5cf9a7261c385de1e20dcfc85"}, + {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1876b0b653a808fcd50123b953af170c535027bf1d053b59790eebb0aeb38950"}, + {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dfe1f0f0ed5785c187144c46a292b8c34c1295c01da12e10ccddfc16def4448a"}, + {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3528807cbbb7f315bb81959d5961855e7ba52aa60a3097151cb21956fbc7502b"}, + {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e2f879ab92ce502a1e65fce390eab619774dda6a6ff719718069ac94084098ce"}, + {file = "msgpack-1.0.8-cp311-cp311-win32.whl", hash = "sha256:26ee97a8261e6e35885c2ecd2fd4a6d38252246f94a2aec23665a4e66d066305"}, + {file = "msgpack-1.0.8-cp311-cp311-win_amd64.whl", hash = "sha256:eadb9f826c138e6cf3c49d6f8de88225a3c0ab181a9b4ba792e006e5292d150e"}, + {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:114be227f5213ef8b215c22dde19532f5da9652e56e8ce969bf0a26d7c419fee"}, + {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d661dc4785affa9d0edfdd1e59ec056a58b3dbb9f196fa43587f3ddac654ac7b"}, + {file = "msgpack-1.0.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d56fd9f1f1cdc8227d7b7918f55091349741904d9520c65f0139a9755952c9e8"}, + {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0726c282d188e204281ebd8de31724b7d749adebc086873a59efb8cf7ae27df3"}, + {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8db8e423192303ed77cff4dce3a4b88dbfaf43979d280181558af5e2c3c71afc"}, + {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99881222f4a8c2f641f25703963a5cefb076adffd959e0558dc9f803a52d6a58"}, + {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b5505774ea2a73a86ea176e8a9a4a7c8bf5d521050f0f6f8426afe798689243f"}, + {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ef254a06bcea461e65ff0373d8a0dd1ed3aa004af48839f002a0c994a6f72d04"}, + {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e1dd7839443592d00e96db831eddb4111a2a81a46b028f0facd60a09ebbdd543"}, + {file = "msgpack-1.0.8-cp312-cp312-win32.whl", hash = "sha256:64d0fcd436c5683fdd7c907eeae5e2cbb5eb872fafbc03a43609d7941840995c"}, + {file = "msgpack-1.0.8-cp312-cp312-win_amd64.whl", hash = "sha256:74398a4cf19de42e1498368c36eed45d9528f5fd0155241e82c4082b7e16cffd"}, + {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ceea77719d45c839fd73abcb190b8390412a890df2f83fb8cf49b2a4b5c2f40"}, + {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ab0bbcd4d1f7b6991ee7c753655b481c50084294218de69365f8f1970d4c151"}, + {file = "msgpack-1.0.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1cce488457370ffd1f953846f82323cb6b2ad2190987cd4d70b2713e17268d24"}, + {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3923a1778f7e5ef31865893fdca12a8d7dc03a44b33e2a5f3295416314c09f5d"}, + {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22e47578b30a3e199ab067a4d43d790249b3c0587d9a771921f86250c8435db"}, + {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd739c9251d01e0279ce729e37b39d49a08c0420d3fee7f2a4968c0576678f77"}, + {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d3420522057ebab1728b21ad473aa950026d07cb09da41103f8e597dfbfaeb13"}, + {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5845fdf5e5d5b78a49b826fcdc0eb2e2aa7191980e3d2cfd2a30303a74f212e2"}, + {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a0e76621f6e1f908ae52860bdcb58e1ca85231a9b0545e64509c931dd34275a"}, + {file = "msgpack-1.0.8-cp38-cp38-win32.whl", hash = "sha256:374a8e88ddab84b9ada695d255679fb99c53513c0a51778796fcf0944d6c789c"}, + {file = "msgpack-1.0.8-cp38-cp38-win_amd64.whl", hash = "sha256:f3709997b228685fe53e8c433e2df9f0cdb5f4542bd5114ed17ac3c0129b0480"}, + {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f51bab98d52739c50c56658cc303f190785f9a2cd97b823357e7aeae54c8f68a"}, + {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:73ee792784d48aa338bba28063e19a27e8d989344f34aad14ea6e1b9bd83f596"}, + {file = "msgpack-1.0.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f9904e24646570539a8950400602d66d2b2c492b9010ea7e965025cb71d0c86d"}, + {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e75753aeda0ddc4c28dce4c32ba2f6ec30b1b02f6c0b14e547841ba5b24f753f"}, + {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5dbf059fb4b7c240c873c1245ee112505be27497e90f7c6591261c7d3c3a8228"}, + {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4916727e31c28be8beaf11cf117d6f6f188dcc36daae4e851fee88646f5b6b18"}, + {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7938111ed1358f536daf311be244f34df7bf3cdedb3ed883787aca97778b28d8"}, + {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:493c5c5e44b06d6c9268ce21b302c9ca055c1fd3484c25ba41d34476c76ee746"}, + {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"}, + {file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"}, + {file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"}, + {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"}, +] + +[[package]] +name = "msgpack-python" +version = "0.5.6" +description = "MessagePack (de)serializer." +optional = false +python-versions = "*" +files = [ + {file = "msgpack-python-0.5.6.tar.gz", hash = "sha256:378cc8a6d3545b532dfd149da715abae4fda2a3adb6d74e525d0d5e51f46909b"}, +] + [[package]] name = "mypy" version = "1.10.0" @@ -2005,6 +2099,21 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "natsort" +version = "8.4.0" +description = "Simple yet flexible natural sorting in Python." +optional = false +python-versions = ">=3.7" +files = [ + {file = "natsort-8.4.0-py3-none-any.whl", hash = "sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c"}, + {file = "natsort-8.4.0.tar.gz", hash = "sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581"}, +] + +[package.extras] +fast = ["fastnumbers (>=2.0.0)"] +icu = ["PyICU (>=1.0.0)"] + [[package]] name = "nbclient" version = "0.6.8" @@ -2114,6 +2223,24 @@ files = [ {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, ] +[[package]] +name = "networkx" +version = "3.1" +description = "Python package for creating and manipulating graphs and networks" +optional = false +python-versions = ">=3.8" +files = [ + {file = "networkx-3.1-py3-none-any.whl", hash = "sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36"}, + {file = "networkx-3.1.tar.gz", hash = "sha256:de346335408f84de0eada6ff9fafafff9bcda11f0a0dfaa931133debb146ab61"}, +] + +[package.extras] +default = ["matplotlib (>=3.4)", "numpy (>=1.20)", "pandas (>=1.3)", "scipy (>=1.8)"] +developer = ["mypy (>=1.1)", "pre-commit (>=3.2)"] +doc = ["nb2plots (>=0.6)", "numpydoc (>=1.5)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.13)", "sphinx (>=6.1)", "sphinx-gallery (>=0.12)", "texext (>=0.6.7)"] +extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.10)", "sympy (>=1.10)"] +test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"] + [[package]] name = "nodeenv" version = "1.8.0" @@ -3717,4 +3844,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.8.1,<4" -content-hash = "26bf085d0fd07d45f0381eb7c3075b0b5ba7959da57fb8c56978e8fe557f4e2c" +content-hash = "8707ba4d44af6a14d92ac021f5d5999ef293933275a12e674f6cce6ceb447830" diff --git a/pyproject.toml b/pyproject.toml index 922b47f..ef00b69 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,7 @@ include = ["src/irx/py.typed"] [tool.poetry.dependencies] python = ">=3.8.1,<4" atpublic = ">=4.0" -astx = "0.12.2" +astx = "0.15.0" typing-extensions = { version = "^4", python = "<3.9" } llvmlite = ">=0.41.1" plum-dispatch = ">=2.2.2" diff --git a/src/irx/builders/llvmliteir.py b/src/irx/builders/llvmliteir.py index c3e33b4..d61bf37 100644 --- a/src/irx/builders/llvmliteir.py +++ b/src/irx/builders/llvmliteir.py @@ -206,7 +206,7 @@ def create_entry_block_alloca( @dispatch.abstract def visit(self, expr: astx.AST) -> None: """Translate an ASTx expression.""" - raise Exception("Not implemented yet.") + raise Exception("astx.AST doesn't have a direct translation.") @dispatch # type: ignore[no-redef] def visit(self, expr: astx.BinaryOp) -> None: @@ -272,12 +272,13 @@ def visit(self, expr: astx.BinaryOp) -> None: elif expr.op_code == "<": # note: it should be according the datatype, # e.g. for float it should be fcmp - cmp_result = self._llvm.ir_builder.cmp_unordered( + cmp_result = self._llvm.ir_builder.icmp_signed( "<", llvm_lhs, llvm_rhs, "lttmp" ) - result = self._llvm.ir_builder.uitofp( + result = self._llvm.ir_builder.zext( cmp_result, self._llvm.INT32_TYPE, "booltmp" ) + self.result_stack.append(result) return elif expr.op_code == ">": @@ -592,6 +593,73 @@ def visit(self, expr: astx.ForRangeLoop) -> None: result = ir.Constant(self._llvm.INT32_TYPE, 0) self.result_stack.append(result) + @dispatch # type: ignore[no-redef] + def visit(self, expr: astx.While) -> None: + """Translate ASTx While Loop to LLVM-IR.""" + # Create blocks for the condition check, the loop body, + # and the block after the loop. + cond_bb = self._llvm.ir_builder.function.append_basic_block( + "whilecond" + ) + body_bb = self._llvm.ir_builder.function.append_basic_block( + "whilebody" + ) + after_bb = self._llvm.ir_builder.function.append_basic_block( + "afterwhile" + ) + + # Branch to the condition check block. + self._llvm.ir_builder.branch(cond_bb) + + # Start inserting into the condition check block. + self._llvm.ir_builder.position_at_start(cond_bb) + + # Emit the condition. + self.visit(expr.condition) + cond_val = self.result_stack.pop() + if not cond_val: + raise Exception("codegen: Invalid condition expression.") + + # Convert condition to a bool by comparing non-equal to 0. + if isinstance(cond_val.type, (ir.FloatType, ir.DoubleType)): + cmp_instruction = self._llvm.ir_builder.fcmp_ordered + zero_val = ir.Constant(cond_val.type, 0.0) + else: + cmp_instruction = self._llvm.ir_builder.icmp_signed + zero_val = ir.Constant(cond_val.type, 0) + + cond_val = cmp_instruction( + "!=", + cond_val, + zero_val, + "whilecond", + ) + + # Conditional branch based on the condition. + self._llvm.ir_builder.cbranch(cond_val, body_bb, after_bb) + + # Start inserting into the loop body block. + self._llvm.ir_builder.position_at_start(body_bb) + + # Emit the body of the loop. This, like any other expr, can change + # the current basic_block. Note that we ignore the value computed by + # the body, but don't allow an error. + self.visit(expr.body) + body_val = self.result_stack.pop() + + if not body_val: + return + + # Branch back to the condition check. + self._llvm.ir_builder.branch(cond_bb) + + # Start inserting into the block after the loop. + self._llvm.ir_builder.position_at_start(after_bb) + + # While loop always returns 0. + result = ir.Constant(self._llvm.INT32_TYPE, 0) + self.result_stack.append(result) + @dispatch # type: ignore[no-redef] def visit(self, expr: astx.Module) -> None: """Translate ASTx Module to LLVM-IR.""" @@ -718,6 +786,33 @@ def visit(self, expr: astx.Variable) -> None: result = self._llvm.ir_builder.load(expr_var, expr.name) self.result_stack.append(result) + @dispatch # type: ignore[no-redef] + def visit(self, expr: astx.VariableAssignment) -> None: + """Translate variable assignment expression.""" + # Get the name of the variable to assign to + var_name = expr.name + + # Codegen the value expression on the right-hand side + self.visit(expr.value) + llvm_value = safe_pop(self.result_stack) + + if not llvm_value: + raise Exception("codegen: Invalid value in VariableAssignment.") + + # Look up the variable in the named values + llvm_var = self.named_values.get(var_name) + + if not llvm_var: + raise Exception( + f"Variable '{var_name}' not found in the named values." + ) + + # Store the value in the variable + self._llvm.ir_builder.store(llvm_value, llvm_var) + + # Optionally, you can push the result onto the result stack if needed + self.result_stack.append(llvm_value) + @dispatch # type: ignore[no-redef] def visit(self, expr: astx.VariableDeclaration) -> None: """Translate ASTx Variable to LLVM-IR.""" diff --git a/tests/examples/__init__.py b/tests/examples/__init__.py new file mode 100644 index 0000000..1e263e5 --- /dev/null +++ b/tests/examples/__init__.py @@ -0,0 +1 @@ +"""Tests with real examples.""" diff --git a/tests/examples/test_fibonacci.py b/tests/examples/test_fibonacci.py new file mode 100644 index 0000000..6407c0d --- /dev/null +++ b/tests/examples/test_fibonacci.py @@ -0,0 +1,116 @@ +"""Test irx with a fibonnaci function.""" + +from __future__ import annotations + +from typing import Type + +import astx +import pytest + +from irx.builders.base import Builder +from irx.builders.llvmliteir import LLVMLiteIR + +from ..conftest import check_result + + +@pytest.mark.parametrize( + "action,expected_file", + [("build", "")], +) +@pytest.mark.parametrize( + "builder_class", + [ + LLVMLiteIR, + ], +) +def test_function_call_fibonacci( + action: str, expected_file: str, builder_class: Type[Builder] +) -> None: + """Test the FunctionCall class with Fibonacci.""" + # Initialize the ASTx module + builder = builder_class() + module = builder.module() + + # Define the Fibonacci function prototype + fib_proto = astx.FunctionPrototype( + name="fib", + args=astx.Arguments(astx.Argument("n", astx.Int32)), + return_type=astx.Int32, + ) + + # Create the function body block + fib_block = astx.Block() + + # Declare the variables + decl_a = astx.VariableDeclaration( # noqa: F841 + name="a", + type_=astx.Int32, + value=astx.LiteralInt32(0), + parent=fib_block, + ) + decl_b = astx.VariableDeclaration( # noqa: F841 + name="b", + type_=astx.Int32, + value=astx.LiteralInt32(1), + parent=fib_block, + ) + decl_i = astx.VariableDeclaration( # noqa: F841 + name="i", + type_=astx.Int32, + value=astx.LiteralInt32(2), + parent=fib_block, + ) + decl_sum = astx.VariableDeclaration( # noqa: F841 + name="sum", + type_=astx.Int32, + value=astx.LiteralInt32(0), + parent=fib_block, + ) + + # Create the loop condition + cond = astx.BinaryOp( + op_code="<", lhs=astx.Variable(name="i"), rhs=astx.Variable(name="n") + ) + + # Define the loop body + loop_block = astx.Block() + assign_sum = astx.VariableAssignment( + name="sum", + value=astx.BinaryOp( + op_code="+", + lhs=astx.Variable(name="a"), + rhs=astx.Variable(name="b"), + ), + ) + assign_a = astx.VariableAssignment(name="a", value=astx.Variable(name="b")) + assign_b = astx.VariableAssignment( + name="b", value=astx.Variable(name="sum") + ) + inc_i = astx.VariableAssignment( + name="i", + value=astx.BinaryOp( + op_code="+", lhs=astx.Variable(name="i"), rhs=astx.LiteralInt32(1) + ), + ) + + # Add declarations and assignments to the loop body + loop_block.append(assign_sum) + loop_block.append(assign_a) + loop_block.append(assign_b) + loop_block.append(inc_i) + + # Create the loop statement + loop = astx.While(condition=cond, body=loop_block) + fib_block.append(loop) + + # Add return statement + return_stmt = astx.FunctionReturn(astx.Variable(name="b")) + fib_block.append(return_stmt) + + # Define the function with its body + fib_fn = astx.Function(prototype=fib_proto, body=fib_block) + + # Append the Fibonacci function to the module block + module.block.append(fib_fn) + + check_result(action, builder, module, expected_file)