lambda-repl 1.1.0__py3-none-any.whl → 1.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
lambda_repl/__init__.py CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  from __future__ import annotations
6
6
  from cmd import Cmd
7
+ from importlib import import_module
7
8
  from typing import Any
8
9
  from lambda_calculus.terms import Term
9
10
  from lambda_calculus.visitors.normalisation import (
@@ -14,7 +15,7 @@ from lark.exceptions import UnexpectedInput
14
15
  from .parsing import LambdaTransformer
15
16
  from .aliases import Aliases
16
17
 
17
- __version__ = "1.1.0"
18
+ __version__ = "1.2.1"
18
19
  __author__ = "Eric Niklas Wolf"
19
20
  __email__ = "eric_niklas.wolf@mailbox.tu-dresden.de"
20
21
  __all__ = (
@@ -51,6 +52,19 @@ class LambdaREPL(Cmd):
51
52
  self.stdout.write(error.get_context(term))
52
53
  return None
53
54
 
55
+ def import_term(self, location: str) -> Term[str] | None:
56
+ """import a term and handle error display"""
57
+ module, _, name = location.strip().rpartition(".")
58
+ try:
59
+ term = getattr(import_module(module), name)
60
+ except Exception as error: # pylint: disable=W0718
61
+ self.stdout.write(f"Error while importing: {error}\n")
62
+ return None
63
+ if not isinstance(term, Term):
64
+ self.stdout.write(f"Error: object {term} is not a lambda term\n")
65
+ return None
66
+ return term
67
+
54
68
  def emptyline(self) -> bool:
55
69
  """ignore empty lines"""
56
70
  return False
@@ -95,6 +109,17 @@ class LambdaREPL(Cmd):
95
109
  self.stdout.write("invalid Command: missing alias value\n")
96
110
  return False
97
111
 
112
+ def do_import(self, arg: str) -> bool:
113
+ """import an alias from a module with name = module.name"""
114
+ match arg.partition("="):
115
+ case (alias, "=", location):
116
+ term = self.import_term(location)
117
+ if term is not None:
118
+ self.aliases[alias.strip()] = term
119
+ case _:
120
+ self.stdout.write("invalid Command: missing import location\n")
121
+ return False
122
+
98
123
  def do_aliases(self, _: object) -> bool:
99
124
  """list defined aliases"""
100
125
  for alias, term in self.aliases.items():
lambda_repl/grammar.lark CHANGED
@@ -4,8 +4,10 @@ VARIABLE: /[^\s().λ\\]+/
4
4
 
5
5
  abstraction: ("\\" | "λ") VARIABLE "." term
6
6
 
7
- application: ( abstraction | VARIABLE | brackets ) ( _WHITESPACE ( abstraction | VARIABLE | brackets ) )+
7
+ application: _application_term _WHITESPACE (abstraction | _simple_term)
8
8
 
9
- ?brackets: "(" term ")"
9
+ ?term: abstraction | _application_term
10
10
 
11
- ?term: abstraction | application | VARIABLE | brackets
11
+ _application_term: application | _simple_term
12
+
13
+ _simple_term: VARIABLE | "(" term ")"
lambda_repl/parsing.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  from __future__ import annotations
6
6
  from collections import deque
7
- from collections.abc import Iterator, Sequence
7
+ from collections.abc import Iterator
8
8
  from itertools import chain
9
9
  from lambda_calculus.terms import Abstraction, Application, Term, Variable
10
10
  from lark import Lark, Token
@@ -52,10 +52,10 @@ class LambdaTransformer(Transformer[Token, Term[str]]):
52
52
  """parse a string and return the transformed lambda term"""
53
53
  # the parser sometimes return tokens directly instead of a tree
54
54
  match PARSER.parse(string):
55
- case Token(type="VARIABLE") as name: # type: ignore
56
- return self.VARIABLE(name) # type: ignore
57
- case Token() as token: # type: ignore
58
- raise UnexpectedToken(token, {"VARIABLE",})
55
+ case Token(type="VARIABLE") as name:
56
+ return self.VARIABLE(name)
57
+ case Token() as token:
58
+ raise UnexpectedToken(token, {"VARIABLE", })
59
59
  case tree:
60
60
  return self.transform(tree)
61
61
 
@@ -63,6 +63,10 @@ class LambdaTransformer(Transformer[Token, Term[str]]):
63
63
  """handle unknown nodes"""
64
64
  raise UnexpectedInput(f"unknown node: {data}")
65
65
 
66
+ def __default_token__(self, token: Token) -> Token:
67
+ """handle unknown tokens"""
68
+ raise UnexpectedInput(f"unknown token: {token}")
69
+
66
70
  def VARIABLE(self, name: Token) -> Variable[str]:
67
71
  """transform a variable node"""
68
72
  return Variable(name.value)
@@ -72,9 +76,10 @@ class LambdaTransformer(Transformer[Token, Term[str]]):
72
76
  """transform an abstraction"""
73
77
  return Abstraction(variable.name, body)
74
78
 
75
- def application(self, children: Sequence[Term[str]]) -> Application[str]:
79
+ @v_args(inline=True)
80
+ def application(self, abstraction: Term[str], argument: Term[str]) -> Application[str]:
76
81
  """transform an application"""
77
- return Application.with_arguments(children[0], children[1:])
82
+ return Application(abstraction, argument)
78
83
 
79
84
 
80
85
  PARSER = Lark.open_from_package(
@@ -1,10 +1,11 @@
1
- Metadata-Version: 2.1
2
- Name: lambda-repl
3
- Version: 1.1.0
1
+ Metadata-Version: 2.4
2
+ Name: lambda_repl
3
+ Version: 1.2.1
4
4
  Summary: REPL for the lambda calculus
5
- Author-email: Eric Niklas Wolf <eric_niklas.wolf@mailbox.tu-dresden.de>
6
5
  Project-URL: Repository, https://github.com/Deric-W/lambda_repl
7
6
  Project-URL: Bugtracker, https://github.com/Deric-W/lambda_repl/issues
7
+ Author-email: Eric Niklas Wolf <eric_niklas.wolf@mailbox.tu-dresden.de>
8
+ License-File: LICENSE
8
9
  Classifier: Intended Audience :: Education
9
10
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
10
11
  Classifier: Operating System :: OS Independent
@@ -13,23 +14,25 @@ Classifier: Topic :: Education
13
14
  Classifier: Topic :: Utilities
14
15
  Classifier: Typing :: Typed
15
16
  Requires-Python: >=3.10
17
+ Requires-Dist: lambda-calculus~=3.0
18
+ Requires-Dist: lark~=1.0
16
19
  Description-Content-Type: text/markdown
17
- License-File: LICENSE
18
- Requires-Dist: lambda-calculus (~=2.0)
19
- Requires-Dist: lark (~=1.0)
20
20
 
21
21
  # lambda_repl
22
22
 
23
+ [![Hatch project](https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg)](https://github.com/pypa/hatch)
23
24
  ![Tests](https://github.com/Deric-W/lambda_repl/actions/workflows/Tests.yaml/badge.svg)
24
25
  [![codecov](https://codecov.io/gh/Deric-W/lambda_repl/branch/main/graph/badge.svg?token=SU3982mC17)](https://codecov.io/gh/Deric-W/lambda_repl)
25
26
 
26
- The `lambda_repl` package contains a [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) for the [lambda calculus](https://en.wikipedia.org/wiki/Lambda_calculus).
27
+ The `lambda_repl` package contains a [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)
28
+ for the [lambda calculus](https://en.wikipedia.org/wiki/Lambda_calculus).
27
29
 
28
30
  To use it, execute `lambda-repl` or `python3 -m lambda_repl` and enter commands.
29
31
 
30
32
  ## Requirements
31
33
 
32
- Python >= 3.10 and the `lambda_calculus` package are required to use this package.
34
+ Python >= 3.10 and the packages [`lambda_calculus`](https://github.com/Deric-W/lambda_calculus)
35
+ and [`lark`](https://github.com/lark-parser/lark) are required to use this package.
33
36
 
34
37
  ## Installation
35
38
 
@@ -44,9 +47,11 @@ python3 -m lambda_repl
44
47
  Welcome to the the Lambda REPL, type 'help' for help
45
48
  λ alias I = \x.x
46
49
  λ alias K = λx.λy.x
50
+ λ import SUCC = lambda_calculus.terms.arithmetic.SUCCESSOR
47
51
  λ aliases
48
52
  I = (λx.x)
49
53
  K = (λx.(λy.x))
54
+ SUCC = (λn.(λf.(λx.(f ((n f) x)))))
50
55
  λ trace K a b
51
56
  β ((λy.a) b)
52
57
  β a
@@ -0,0 +1,12 @@
1
+ lambda_repl/__init__.py,sha256=3cAdjhU-P2CvQ7-Yww1ag8OawfcrW1uONab9J6XDsdQ,4823
2
+ lambda_repl/__main__.py,sha256=0R69kMLopBXwWwgiq_kB8vdvUXHWF_95iRIrPYMtidg,103
3
+ lambda_repl/aliases.py,sha256=U0-JFP3fI-9-su0M3DiTqp6fMfZQfcdmOxxdzE5iHgQ,1815
4
+ lambda_repl/grammar.lark,sha256=C3Cn24FyOBQERwLvgZ2iYnspA9of2OQKJoFVNlD3DE0,291
5
+ lambda_repl/main.py,sha256=SrxFQwUfQFWCpXYgyCn1h-cHyJnBYee-kIdZn0CbbBU,1229
6
+ lambda_repl/parsing.py,sha256=eZuHX7qR0aAqeIxX83SHM_Az8MvdROL7KmplS1zFGTM,3112
7
+ lambda_repl/py.typed,sha256=rVxfNzv1aKmfThIlRztkUwWiKeYa4XTdtNMh3FV-dGM,25
8
+ lambda_repl-1.2.1.dist-info/METADATA,sha256=uI6qGfcbmt6zfcVcJ19L3-I-ra_fFSgz2CtsPmmjWz8,1986
9
+ lambda_repl-1.2.1.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
10
+ lambda_repl-1.2.1.dist-info/entry_points.txt,sha256=k_lpUdSJyLWmOpBUiJG569al7o5XOZNeGJBrBqYBaNc,58
11
+ lambda_repl-1.2.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
12
+ lambda_repl-1.2.1.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.1)
2
+ Generator: hatchling 1.30.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
@@ -1,13 +0,0 @@
1
- lambda_repl/__init__.py,sha256=r8q0eqyRnsAalTxsEjmi5nbNy1gC-Dkj8fq2itOXeEU,3781
2
- lambda_repl/__main__.py,sha256=0R69kMLopBXwWwgiq_kB8vdvUXHWF_95iRIrPYMtidg,103
3
- lambda_repl/aliases.py,sha256=U0-JFP3fI-9-su0M3DiTqp6fMfZQfcdmOxxdzE5iHgQ,1815
4
- lambda_repl/grammar.lark,sha256=yE3sSoIpEShOzplMIWnDeS5e4o7ODA_JJtMLzsTlUUs,279
5
- lambda_repl/main.py,sha256=SrxFQwUfQFWCpXYgyCn1h-cHyJnBYee-kIdZn0CbbBU,1229
6
- lambda_repl/parsing.py,sha256=1pWv_C0KMLeTXcaoFPRDFJgypFpo1IuueUEJkAQ1mE0,3025
7
- lambda_repl/py.typed,sha256=rVxfNzv1aKmfThIlRztkUwWiKeYa4XTdtNMh3FV-dGM,25
8
- lambda_repl-1.1.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
9
- lambda_repl-1.1.0.dist-info/METADATA,sha256=V_vD35_eGvdTebqHxYmNGHIlZBTy0a2NNRMcW6-oVE0,1686
10
- lambda_repl-1.1.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
11
- lambda_repl-1.1.0.dist-info/entry_points.txt,sha256=k_lpUdSJyLWmOpBUiJG569al7o5XOZNeGJBrBqYBaNc,58
12
- lambda_repl-1.1.0.dist-info/top_level.txt,sha256=S7zlQx9MQUHM6OzLqKf8U6pW1ucdFKOMe-WHYK0T2N0,12
13
- lambda_repl-1.1.0.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- lambda_repl