From 74bcef36bea53b78526623bde6047bec449e3a23 Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Sat, 28 Sep 2024 14:10:32 -0300 Subject: [PATCH] making llvmlite to be optional (#1101) Following the requirement in #1099, this PR makes the dependency in llvm-lite optional. Notice that the "Action Tests" here still run over the full installation, which includes this library. --- mathics/builtin/compilation.py | 9 ++++----- mathics/compile/__init__.py | 5 +++-- mathics/compile/types.py | 16 +++++++++++----- mathics/core/convert/function.py | 4 ++++ mathics/eval/distance.py | 1 + mathics/eval/drawing/plot.py | 3 +++ mathics/eval/files_io/read.py | 12 +++++++----- mathics/eval/hyperbolic.py | 1 + mathics/eval/strings.py | 1 + pyproject.toml | 2 +- requirements-full.txt | 1 + test/builtin/atomic/test_strings2.py | 2 +- test/builtin/test_compilation.py | 6 ++++++ test/builtin/test_compile.py | 8 ++++++++ .../test_duplicate_builtins.py | 1 + test/doc/test_common.py | 1 + test/doc/test_doctests.py | 1 + test/doc/test_latex.py | 1 + 18 files changed, 56 insertions(+), 19 deletions(-) diff --git a/mathics/builtin/compilation.py b/mathics/builtin/compilation.py index c25fa7c6b..110f5338c 100644 --- a/mathics/builtin/compilation.py +++ b/mathics/builtin/compilation.py @@ -49,18 +49,18 @@ class Compile(Builtin): >> cf = Compile[{x, y}, x + 2 y] - = CompiledFunction[{x, y}, x + 2 y, -CompiledCode-] + = CompiledFunction[{x, y}, x + 2 y, ...] >> cf[2.5, 4.3] = 11.1 >> cf = Compile[{{x, _Real}}, Sin[x]] - = CompiledFunction[{x}, Sin[x], -CompiledCode-] + = CompiledFunction[{x}, Sin[x], ...] >> cf[1.4] = 0.98545 Compile supports basic flow control: >> cf = Compile[{{x, _Real}, {y, _Integer}}, If[x == 0.0 && y <= 0, 0.0, Sin[x ^ y] + 1 / Min[x, 0.5]] + 0.5] - = CompiledFunction[{x, y}, ..., -CompiledCode-] + = CompiledFunction[{x, y}, ...] >> cf[3.5, 2] = 2.18888 @@ -78,7 +78,6 @@ class Compile(Builtin): "fdup": "Duplicate parameter `1` found in `2`.", } - requires = ("llvmlite",) summary_text = "compile an expression" def eval(self, vars, expr, evaluation: Evaluation): @@ -172,7 +171,7 @@ class CompiledFunction(Builtin): >> sqr = Compile[{x}, x x] - = CompiledFunction[{x}, x ^ 2, -CompiledCode-] + = CompiledFunction[{x}, x ^ 2, ...] >> Head[sqr] = CompiledFunction >> sqr[2] diff --git a/mathics/compile/__init__.py b/mathics/compile/__init__.py index 9c4601445..9469302c2 100644 --- a/mathics/compile/__init__.py +++ b/mathics/compile/__init__.py @@ -15,8 +15,9 @@ has_llvmlite = False +from .base import CompileArg, CompileError +from .types import * + if has_llvmlite: - from .base import CompileArg, CompileError from .compile import _compile from .ir import IRGenerator - from .types import * diff --git a/mathics/compile/types.py b/mathics/compile/types.py index 20db7fde3..c55ad8b36 100644 --- a/mathics/compile/types.py +++ b/mathics/compile/types.py @@ -1,9 +1,15 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from llvmlite import ir +try: + from llvmlite import ir -int_type = ir.IntType(64) -real_type = ir.DoubleType() -bool_type = ir.IntType(1) -void_type = ir.VoidType() + int_type = ir.IntType(64) + real_type = ir.DoubleType() + bool_type = ir.IntType(1) + void_type = ir.VoidType() +except: + int_type = int + real_type = float + bool_type = bool + void_type = type(None) diff --git a/mathics/core/convert/function.py b/mathics/core/convert/function.py index cd7e9591a..75f632465 100644 --- a/mathics/core/convert/function.py +++ b/mathics/core/convert/function.py @@ -22,6 +22,10 @@ } except ImportError: use_llvm = False + bool_type = bool + int_type = int + real_type = float + permitted_types = { Expression(SymbolBlank, SymbolInteger): int, Expression(SymbolBlank, SymbolReal): float, diff --git a/mathics/eval/distance.py b/mathics/eval/distance.py index 34c041e7b..9eacc55ad 100644 --- a/mathics/eval/distance.py +++ b/mathics/eval/distance.py @@ -1,6 +1,7 @@ """ Distance-related evaluation functions and exception classes """ + from mathics.core.atoms import Integer, Real diff --git a/mathics/eval/drawing/plot.py b/mathics/eval/drawing/plot.py index 4ef4e9057..2270cf85e 100644 --- a/mathics/eval/drawing/plot.py +++ b/mathics/eval/drawing/plot.py @@ -111,8 +111,11 @@ def quiet_f(*args): expr: Optional[Type[BaseElement]] = Expression(SymbolN, expr).evaluate(evaluation) def quiet_f(*args): + old_quiet_all = evaluation.quiet_all + evaluation.quiet_all = True vars = {arg_name: Real(arg) for arg_name, arg in zip(arg_names, args)} value = dynamic_scoping(expr.evaluate, vars, evaluation) + evaluation.quiet_all = old_quiet_all if list_is_expected: if value.has_form("List", None): value = [extract_pyreal(item) for item in value.elements] diff --git a/mathics/eval/files_io/read.py b/mathics/eval/files_io/read.py index 133c45cc3..201abf908 100644 --- a/mathics/eval/files_io/read.py +++ b/mathics/eval/files_io/read.py @@ -248,12 +248,14 @@ def read_list_from_types(read_types): # TODO: look for a better implementation handling "Hold[Expression]". # read_types = ( - SymbolHoldExpression - if ( - typ.get_head_name() == "System`Hold" - and typ.elements[0].get_name() == "System`Expression" + ( + SymbolHoldExpression + if ( + typ.get_head_name() == "System`Hold" + and typ.elements[0].get_name() == "System`Expression" + ) + else typ ) - else typ for typ in read_types ) diff --git a/mathics/eval/hyperbolic.py b/mathics/eval/hyperbolic.py index 832a9ca53..75ac87b85 100644 --- a/mathics/eval/hyperbolic.py +++ b/mathics/eval/hyperbolic.py @@ -1,6 +1,7 @@ """ Mathics3 builtins from mathics.core.numbers.hyperbolic """ + from sympy import Symbol as SympySymbol from mathics.core.convert.sympy import from_sympy diff --git a/mathics/eval/strings.py b/mathics/eval/strings.py index ccb8caa89..8bc41fce1 100644 --- a/mathics/eval/strings.py +++ b/mathics/eval/strings.py @@ -1,6 +1,7 @@ """ String-related evaluation functions. """ + from mathics.core.atoms import String from mathics.core.element import BaseElement from mathics.core.evaluation import Evaluation diff --git a/pyproject.toml b/pyproject.toml index 07a2dbcfe..8a54e597d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ build-backend = "setuptools.build_meta" description = "A general-purpose computer algebra system." dependencies = [ "Mathics-Scanner >= 1.3.0", - "llvmlite", +# "llvmlite", "mpmath>=1.2.0", "numpy<1.27", "palettable", diff --git a/requirements-full.txt b/requirements-full.txt index 529cc51b7..7c72efe5a 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -6,3 +6,4 @@ pyocr # Used for TextRecognize scikit-image >= 0.17 # FindMinimum can use this; used by Image as well unidecode # Used in Transliterate wordcloud >= 1.9.3 # Used in builtin/image.py by WordCloud(). Previous versions assume "image.textsize" which no longer exists +llvmlite # Used for llvm compiling diff --git a/test/builtin/atomic/test_strings2.py b/test/builtin/atomic/test_strings2.py index 7e7facf67..3196b8dc4 100644 --- a/test/builtin/atomic/test_strings2.py +++ b/test/builtin/atomic/test_strings2.py @@ -64,7 +64,7 @@ def test_string_split(): ( 'StringSplit["This is a sentence, which goes on.", Except[WordCharacter] ..]', "{This, is, a, sentence, which, goes, on}", - ) + ), # # FIXME: these forms are not implemented yet: # ('StringSplit["11a22b3", _?LetterQ]', '{11, 22, 3}'), # ('StringSplit["a b::c d::e f g", "::" -> "--"]'), '{a, b, --, c d, --, e f g}'), diff --git a/test/builtin/test_compilation.py b/test/builtin/test_compilation.py index 29dfa4825..295257dff 100644 --- a/test/builtin/test_compilation.py +++ b/test/builtin/test_compilation.py @@ -9,7 +9,13 @@ import pytest +from mathics.compile import has_llvmlite + +@pytest.mark.skipif( + not has_llvmlite, + reason="requires llvmlite", +) @pytest.mark.parametrize( ("str_expr", "msgs", "str_expected", "fail_msg"), [ diff --git a/test/builtin/test_compile.py b/test/builtin/test_compile.py index f512533f8..fecd1af50 100644 --- a/test/builtin/test_compile.py +++ b/test/builtin/test_compile.py @@ -42,6 +42,10 @@ ) +@pytest.mark.skipif( + not has_llvmlite, + reason="requires llvmlite", +) def test_compile_code(): for str_expr, x, res in [ ("Sin[x]", 1.5, 0.997495), @@ -60,6 +64,10 @@ def test_compile_code(): assert abs(y - res) < 1.0e-6 +@pytest.mark.skipif( + not has_llvmlite, + reason="requires llvmlite", +) def test_builtin_fns_with_symbols_1(): for str_expr, x, res in [ ("Sin[x]", 1.5, 0.997495), diff --git a/test/consistency-and-style/test_duplicate_builtins.py b/test/consistency-and-style/test_duplicate_builtins.py index c8dc3c6e5..7094c4fa2 100644 --- a/test/consistency-and-style/test_duplicate_builtins.py +++ b/test/consistency-and-style/test_duplicate_builtins.py @@ -4,6 +4,7 @@ In the past when reorganizing builtin functions we sometimes had missing or duplicate built-in functions definitions. """ + import os import pytest diff --git a/test/doc/test_common.py b/test/doc/test_common.py index 8d7ff17e7..bf8bf6212 100644 --- a/test/doc/test_common.py +++ b/test/doc/test_common.py @@ -1,6 +1,7 @@ """ Pytests for the documentation system. Basic functions and classes. """ + import os.path as osp from mathics.core.evaluation import Message, Print diff --git a/test/doc/test_doctests.py b/test/doc/test_doctests.py index cee480a85..6fc15bed0 100644 --- a/test/doc/test_doctests.py +++ b/test/doc/test_doctests.py @@ -1,6 +1,7 @@ """ Pytests for the documentation system. Basic functions and classes. """ + import os.path as osp from mathics.core.evaluation import Message, Print diff --git a/test/doc/test_latex.py b/test/doc/test_latex.py index 2645421f7..30cd1a0d6 100644 --- a/test/doc/test_latex.py +++ b/test/doc/test_latex.py @@ -1,6 +1,7 @@ """ Pytests for the documentation system. Basic functions and classes. """ + import os.path as osp from mathics.core.evaluation import Message, Print