koatl 0.1.37__tar.gz → 0.1.39__tar.gz
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.
- {koatl-0.1.37 → koatl-0.1.39}/Cargo.lock +1 -1
- {koatl-0.1.37 → koatl-0.1.39}/PKG-INFO +1 -1
- {koatl-0.1.37 → koatl-0.1.39}/koatl/Cargo.toml +1 -1
- koatl-0.1.39/koatl/python/koatl/prelude/__init__.tl +40 -0
- koatl-0.1.39/koatl/python/koatl/runtime/__init__.py +47 -0
- koatl-0.1.39/koatl/python/koatl/runtime/record.py +252 -0
- koatl-0.1.37/koatl/python/koatl/runtime/virtual.py → koatl-0.1.39/koatl/python/koatl/runtime/vattr.py +1 -37
- {koatl-0.1.37 → koatl-0.1.39/koatl}/python/koatl/std/alg/base.tl +2 -0
- koatl-0.1.39/koatl/python/koatl/std/alg/do.tl +34 -0
- {koatl-0.1.37 → koatl-0.1.39/koatl}/python/koatl/std/alg/result.tl +17 -1
- koatl-0.1.39/koatl/python/koatl/std/data/__init__.tl +2 -0
- koatl-0.1.39/koatl/python/koatl/std/data/record.tl +5 -0
- koatl-0.1.39/koatl/python/koatl/std/ext.tl +24 -0
- {koatl-0.1.37 → koatl-0.1.39/koatl}/python/koatl/std/iter.tl +2 -1
- {koatl-0.1.37 → koatl-0.1.39}/koatl/python/koatl/std/lazy_module.tl +13 -1
- koatl-0.1.37/koatl/python/koatl/runtime/classes.py → koatl-0.1.39/koatl/python/koatl/std/trait.py +3 -3
- {koatl-0.1.37 → koatl-0.1.39}/koatl/src/lib.rs +3 -2
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/containers.tl +4 -1
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/parser/src/lexer.rs +180 -122
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/parser/src/parser.rs +0 -1
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/src/py/emit.rs +3 -1
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/src/resolve_scopes.rs +5 -3
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/src/transform.rs +9 -2
- koatl-0.1.39/python/koatl/prelude/__init__.tl +40 -0
- koatl-0.1.39/python/koatl/runtime/__init__.py +47 -0
- koatl-0.1.39/python/koatl/runtime/record.py +252 -0
- koatl-0.1.37/python/koatl/runtime/virtual.py → koatl-0.1.39/python/koatl/runtime/vattr.py +1 -37
- {koatl-0.1.37/koatl → koatl-0.1.39}/python/koatl/std/alg/base.tl +2 -0
- koatl-0.1.39/python/koatl/std/alg/do.tl +34 -0
- {koatl-0.1.37/koatl → koatl-0.1.39}/python/koatl/std/alg/result.tl +17 -1
- koatl-0.1.39/python/koatl/std/data/__init__.tl +2 -0
- koatl-0.1.39/python/koatl/std/data/record.tl +5 -0
- koatl-0.1.39/python/koatl/std/ext.tl +24 -0
- {koatl-0.1.37/koatl → koatl-0.1.39}/python/koatl/std/iter.tl +2 -1
- {koatl-0.1.37 → koatl-0.1.39}/python/koatl/std/lazy_module.tl +13 -1
- koatl-0.1.37/python/koatl/runtime/classes.py → koatl-0.1.39/python/koatl/std/trait.py +3 -3
- koatl-0.1.37/koatl/python/koatl/prelude/__init__.tl +0 -60
- koatl-0.1.37/koatl/python/koatl/runtime/__init__.py +0 -65
- koatl-0.1.37/koatl/python/koatl/runtime/helpers.py +0 -71
- koatl-0.1.37/koatl/python/koatl/runtime/record.py +0 -116
- koatl-0.1.37/koatl/python/koatl/std/data/__init__.tl +0 -1
- koatl-0.1.37/python/koatl/prelude/__init__.tl +0 -60
- koatl-0.1.37/python/koatl/runtime/__init__.py +0 -65
- koatl-0.1.37/python/koatl/runtime/helpers.py +0 -71
- koatl-0.1.37/python/koatl/runtime/record.py +0 -116
- koatl-0.1.37/python/koatl/std/data/__init__.tl +0 -1
- {koatl-0.1.37 → koatl-0.1.39}/Cargo.toml +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/README.md +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/.github/workflows/CI.yml +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/.gitignore +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/LICENSE +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/README.md +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/python/koatl/__init__.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/python/koatl/__main__.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/python/koatl/cli.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/python/koatl/std/alg/__init__.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/python/koatl/std/alg/async.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/python/koatl/std/alg/env.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/python/koatl/std/alg/memo.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/python/koatl/std/data/list.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/python/koatl/std/io.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/python/koatl/std/re.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/requirements.txt +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/src/emit_py.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/data.txt +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/decorators.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/destructure.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/escape_ident.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/fstr.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/functions.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/generator.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/if_expr.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/loops.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/match.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/nary-list.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/placeholder.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/precedence.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/scopes.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/semantic_whitespace.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/short_circuit.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/base/with.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/prelude/async.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/prelude/aug_assign.tl +0 -0
- {koatl-0.1.37/koatl/tests/e2e/base → koatl-0.1.39/koatl/tests/e2e/prelude}/coal.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/prelude/env.tl +0 -0
- {koatl-0.1.37/koatl/tests/e2e/base → koatl-0.1.39/koatl/tests/e2e/prelude}/imports.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/prelude/iterables.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/prelude/list.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/prelude/memo.tl +0 -0
- {koatl-0.1.37/koatl/tests/e2e/base → koatl-0.1.39/koatl/tests/e2e/prelude}/record.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/prelude/result.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/prelude/slice.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/prelude/try.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/prelude/virtual.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/util/__init__.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/util/module0.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/util/module1.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/e2e/util/module2.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/parse/arith.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/parse/assign.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/parse/block-comments.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/parse/deco.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/parse/func.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/parse/matches.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/test_e2e.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl/tests/test_parse.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/Cargo.toml +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/parser/Cargo.toml +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/parser/src/ast.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/parser/src/lib.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/parser/src/util.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/src/inference.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/src/lib.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/src/main.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/src/parse_timer.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/src/parser.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/src/py/ast.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/src/py/mod.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/src/py/util.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/src/types.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/koatl-core/src/util.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/pyproject.toml +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/python/koatl/__init__.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/python/koatl/__main__.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/python/koatl/cli.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/python/koatl/std/alg/__init__.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/python/koatl/std/alg/async.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/python/koatl/std/alg/env.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/python/koatl/std/alg/memo.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/python/koatl/std/data/list.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/python/koatl/std/io.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.39}/python/koatl/std/re.tl +0 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export import koatl.std.(
|
|
2
|
+
trait.*
|
|
3
|
+
ext.*
|
|
4
|
+
data.*
|
|
5
|
+
iter.*
|
|
6
|
+
alg.(Result, Ok, Err, Env, Memo, Async, AsyncMemo)
|
|
7
|
+
alg.do
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
import koatl.std.(
|
|
11
|
+
re.Pattern
|
|
12
|
+
lazy_module.(LazyModule, RootModulesProxy)
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
export std = LazyModule("koatl.std")
|
|
16
|
+
export mod = RootModulesProxy()
|
|
17
|
+
|
|
18
|
+
Extension.trait(Iterable)
|
|
19
|
+
|
|
20
|
+
Extension.property(list, "len")& List.len.fget
|
|
21
|
+
|
|
22
|
+
Extension.property(object, "result")& self => Result(self)
|
|
23
|
+
|
|
24
|
+
Extension.method(str, "match")& (regex, str) => Pattern(regex).match(str)
|
|
25
|
+
|
|
26
|
+
# Note: the below methods have arguments in reverse order to Python's re module.
|
|
27
|
+
Extension.method(str, "matches")& (str, regex) => Pattern(regex).match(str)
|
|
28
|
+
Extension.method(str, "search")& (str, regex) => Pattern(regex).search(str)
|
|
29
|
+
|
|
30
|
+
__tl__.do = koatl.std.alg.do.do
|
|
31
|
+
|
|
32
|
+
__tl__.op_map = koatl.std.alg.result.op_map
|
|
33
|
+
__tl__.op_coal = koatl.std.alg.result.op_coal
|
|
34
|
+
|
|
35
|
+
__tl__.Ok = koatl.std.alg.result.Ok
|
|
36
|
+
__tl__.Err = koatl.std.alg.result.Err
|
|
37
|
+
__tl__.Result = koatl.std.alg.result.Result
|
|
38
|
+
|
|
39
|
+
__tl__.memo_value = koatl.std.alg.memo.Memo.value
|
|
40
|
+
__tl__.async_memo_value = koatl.std.alg.memo.AsyncMemo.value
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import importlib
|
|
3
|
+
from types import SimpleNamespace
|
|
4
|
+
|
|
5
|
+
from koatl.runtime.record import Record
|
|
6
|
+
from . import meta_finder, vattr
|
|
7
|
+
|
|
8
|
+
meta_finder.install_hook()
|
|
9
|
+
|
|
10
|
+
__all__ = ["__tl__"]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def set_exports(package_name, globals_dict, exports, module_star_exports):
|
|
14
|
+
exports = set(exports)
|
|
15
|
+
|
|
16
|
+
for module in module_star_exports:
|
|
17
|
+
mod = importlib.import_module(module, package_name)
|
|
18
|
+
|
|
19
|
+
if hasattr(mod, "__all__"):
|
|
20
|
+
for name in mod.__all__:
|
|
21
|
+
exports.add(name)
|
|
22
|
+
else:
|
|
23
|
+
for name in dir(mod):
|
|
24
|
+
if name.startswith("_"):
|
|
25
|
+
continue
|
|
26
|
+
|
|
27
|
+
exports.add(name)
|
|
28
|
+
|
|
29
|
+
if "__all__" not in globals_dict:
|
|
30
|
+
globals_dict["__all__"] = ()
|
|
31
|
+
|
|
32
|
+
globals_dict["__all__"] = tuple(set(globals_dict["__all__"]) | exports)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
__tl__ = SimpleNamespace(
|
|
36
|
+
Exception=Exception,
|
|
37
|
+
slice=slice,
|
|
38
|
+
type=type,
|
|
39
|
+
partial=functools.partial,
|
|
40
|
+
#
|
|
41
|
+
record_literal=Record.from_dict_ref,
|
|
42
|
+
#
|
|
43
|
+
set_exports=set_exports,
|
|
44
|
+
#
|
|
45
|
+
vget=vattr.vget,
|
|
46
|
+
vhas=vattr.vhas,
|
|
47
|
+
)
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import collections
|
|
2
|
+
from collections.abc import MutableMapping
|
|
3
|
+
import functools
|
|
4
|
+
import inspect
|
|
5
|
+
import re
|
|
6
|
+
|
|
7
|
+
_property = property
|
|
8
|
+
|
|
9
|
+
__all__ = ["Record"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@collections.abc.MutableMapping.register
|
|
13
|
+
class Record:
|
|
14
|
+
def __init__(self, data=None, /, **kwargs):
|
|
15
|
+
if data is None:
|
|
16
|
+
self.__dict__ = kwargs
|
|
17
|
+
else:
|
|
18
|
+
self.__dict__ = dict(data, **kwargs)
|
|
19
|
+
|
|
20
|
+
@classmethod
|
|
21
|
+
def from_dict_ref(cls, dict_obj):
|
|
22
|
+
if not isinstance(dict_obj, dict):
|
|
23
|
+
raise TypeError("Expected a dictionary")
|
|
24
|
+
|
|
25
|
+
self = cls.__new__(cls)
|
|
26
|
+
self.__dict__ = dict_obj
|
|
27
|
+
return self
|
|
28
|
+
|
|
29
|
+
@staticmethod
|
|
30
|
+
def method(fn):
|
|
31
|
+
fn._method = True
|
|
32
|
+
return fn
|
|
33
|
+
|
|
34
|
+
@staticmethod
|
|
35
|
+
def property(fn):
|
|
36
|
+
fn._property = True
|
|
37
|
+
return fn
|
|
38
|
+
|
|
39
|
+
def __getattribute__(self, name):
|
|
40
|
+
dict = object.__getattribute__(self, "__dict__")
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
attr = dict[name]
|
|
44
|
+
|
|
45
|
+
if hasattr(attr, "_property"):
|
|
46
|
+
return attr(self)
|
|
47
|
+
elif hasattr(attr, "_method"):
|
|
48
|
+
return functools.partial(attr, self)
|
|
49
|
+
except KeyError:
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
return object.__getattribute__(self, name)
|
|
53
|
+
|
|
54
|
+
@_property
|
|
55
|
+
def iter(self):
|
|
56
|
+
return self.items()
|
|
57
|
+
|
|
58
|
+
# MutableMapping
|
|
59
|
+
def __len__(self):
|
|
60
|
+
return len(self.__dict__)
|
|
61
|
+
|
|
62
|
+
def __getitem__(self, key):
|
|
63
|
+
try:
|
|
64
|
+
return self.__dict__[key]
|
|
65
|
+
except KeyError as e:
|
|
66
|
+
raise e
|
|
67
|
+
|
|
68
|
+
def __setitem__(self, key, item):
|
|
69
|
+
self.__dict__[key] = item
|
|
70
|
+
|
|
71
|
+
def __delitem__(self, key):
|
|
72
|
+
del self.__dict__[key]
|
|
73
|
+
|
|
74
|
+
def __iter__(self):
|
|
75
|
+
return iter(self.__dict__)
|
|
76
|
+
|
|
77
|
+
def __contains__(self, key):
|
|
78
|
+
return key in self.__dict__
|
|
79
|
+
|
|
80
|
+
def get(self, key, default=None):
|
|
81
|
+
return self.__dict__.get(key, default)
|
|
82
|
+
|
|
83
|
+
def items(self):
|
|
84
|
+
return self.__dict__.items()
|
|
85
|
+
|
|
86
|
+
def keys(self):
|
|
87
|
+
return self.__dict__.keys()
|
|
88
|
+
|
|
89
|
+
def values(self):
|
|
90
|
+
return self.__dict__.values()
|
|
91
|
+
|
|
92
|
+
# dict
|
|
93
|
+
def __repr__(self):
|
|
94
|
+
return repr(self.__dict__)
|
|
95
|
+
|
|
96
|
+
def __or__(self, other):
|
|
97
|
+
if isinstance(other, Record):
|
|
98
|
+
return self.__class__(self.__dict__ | other.__dict__)
|
|
99
|
+
if isinstance(other, dict):
|
|
100
|
+
return self.__class__(self.__dict__ | other)
|
|
101
|
+
return NotImplemented
|
|
102
|
+
|
|
103
|
+
def __ror__(self, other):
|
|
104
|
+
if isinstance(other, Record):
|
|
105
|
+
return self.__class__(other.__dict__ | self.__dict__)
|
|
106
|
+
if isinstance(other, dict):
|
|
107
|
+
return self.__class__(other | self.__dict__)
|
|
108
|
+
return NotImplemented
|
|
109
|
+
|
|
110
|
+
def __ior__(self, other):
|
|
111
|
+
if isinstance(other, Record):
|
|
112
|
+
self.__dict__ |= other.__dict__
|
|
113
|
+
else:
|
|
114
|
+
self.__dict__ |= other
|
|
115
|
+
return self
|
|
116
|
+
|
|
117
|
+
def __copy__(self):
|
|
118
|
+
inst = self.__class__.__new__(self.__class__)
|
|
119
|
+
inst.__dict__ = self.__dict__.copy()
|
|
120
|
+
return inst
|
|
121
|
+
|
|
122
|
+
def copy(self):
|
|
123
|
+
if self.__class__ is Record:
|
|
124
|
+
return Record(self.__dict__.copy())
|
|
125
|
+
import copy
|
|
126
|
+
|
|
127
|
+
data = self.__dict__
|
|
128
|
+
try:
|
|
129
|
+
self.__dict__ = {}
|
|
130
|
+
c = copy.copy(self)
|
|
131
|
+
finally:
|
|
132
|
+
self.__dict__ = data
|
|
133
|
+
c.update(self)
|
|
134
|
+
return c
|
|
135
|
+
|
|
136
|
+
@_property
|
|
137
|
+
def len(self):
|
|
138
|
+
return len(self)
|
|
139
|
+
|
|
140
|
+
# Other
|
|
141
|
+
|
|
142
|
+
def __repr__(self):
|
|
143
|
+
return self._repr_with_visited(set())
|
|
144
|
+
|
|
145
|
+
def __hash__(self):
|
|
146
|
+
return hash(tuple(sorted(self.items())))
|
|
147
|
+
|
|
148
|
+
def __eq__(self, other):
|
|
149
|
+
if isinstance(other, Record):
|
|
150
|
+
return self.__dict__ == other.__dict__
|
|
151
|
+
|
|
152
|
+
if isinstance(other, dict):
|
|
153
|
+
return self.__dict__ == other
|
|
154
|
+
|
|
155
|
+
return NotImplemented
|
|
156
|
+
|
|
157
|
+
def _repr_with_visited(self, visited):
|
|
158
|
+
# Handle cycles by checking if this object is already being processed
|
|
159
|
+
obj_id = id(self)
|
|
160
|
+
if obj_id in visited:
|
|
161
|
+
return "{...}"
|
|
162
|
+
|
|
163
|
+
visited.add(obj_id)
|
|
164
|
+
try:
|
|
165
|
+
if not self:
|
|
166
|
+
return "{}"
|
|
167
|
+
|
|
168
|
+
items = []
|
|
169
|
+
for key, value in self.items():
|
|
170
|
+
key_str = self._format_key(key)
|
|
171
|
+
|
|
172
|
+
# Handle value representation with cycle detection
|
|
173
|
+
if isinstance(value, Record):
|
|
174
|
+
value_str = value._repr_with_visited(visited.copy())
|
|
175
|
+
elif hasattr(value, "__dict__") and hasattr(value, "__class__"):
|
|
176
|
+
# For other objects that might contain cycles, use a simple repr
|
|
177
|
+
value_str = repr(value)
|
|
178
|
+
else:
|
|
179
|
+
value_str = repr(value)
|
|
180
|
+
|
|
181
|
+
items.append(f"{key_str}: {value_str}")
|
|
182
|
+
|
|
183
|
+
return "{" + ", ".join(items) + "}"
|
|
184
|
+
finally:
|
|
185
|
+
visited.remove(obj_id)
|
|
186
|
+
|
|
187
|
+
def _format_key(self, key):
|
|
188
|
+
if isinstance(key, str):
|
|
189
|
+
if self._is_identifier(key):
|
|
190
|
+
# If key is an identifier, drop the quotes
|
|
191
|
+
return key
|
|
192
|
+
return f'"{key}"'
|
|
193
|
+
|
|
194
|
+
elif isinstance(key, (int, float, bool, type(None))):
|
|
195
|
+
# If key is a literal like 0, 1, True, False, None, use repr
|
|
196
|
+
return repr(key)
|
|
197
|
+
|
|
198
|
+
else:
|
|
199
|
+
# Otherwise, use f"({repr(key)})"
|
|
200
|
+
return f"({repr(key)})"
|
|
201
|
+
|
|
202
|
+
def _is_identifier(self, s):
|
|
203
|
+
return (
|
|
204
|
+
isinstance(s, str)
|
|
205
|
+
and re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", s)
|
|
206
|
+
and s not in koatl_keywords
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
for key, value in MutableMapping.__dict__.items():
|
|
211
|
+
# copy over mixin methods from MutableMapping
|
|
212
|
+
if key.startswith("__"):
|
|
213
|
+
continue
|
|
214
|
+
|
|
215
|
+
if not inspect.isfunction(value):
|
|
216
|
+
continue
|
|
217
|
+
|
|
218
|
+
if hasattr(value, "__isabstractmethod__") and value.__isabstractmethod__:
|
|
219
|
+
continue
|
|
220
|
+
|
|
221
|
+
if key not in Record.__dict__:
|
|
222
|
+
setattr(Record, key, value)
|
|
223
|
+
|
|
224
|
+
koatl_keywords = {
|
|
225
|
+
"if",
|
|
226
|
+
"then",
|
|
227
|
+
"else",
|
|
228
|
+
"import",
|
|
229
|
+
"export",
|
|
230
|
+
"as",
|
|
231
|
+
"class",
|
|
232
|
+
"while",
|
|
233
|
+
"for",
|
|
234
|
+
"in",
|
|
235
|
+
"break",
|
|
236
|
+
"continue",
|
|
237
|
+
"with",
|
|
238
|
+
"yield",
|
|
239
|
+
"global",
|
|
240
|
+
"return",
|
|
241
|
+
"raise",
|
|
242
|
+
"try",
|
|
243
|
+
"except",
|
|
244
|
+
"finally",
|
|
245
|
+
"and",
|
|
246
|
+
"or",
|
|
247
|
+
"not",
|
|
248
|
+
"await",
|
|
249
|
+
"let",
|
|
250
|
+
"const",
|
|
251
|
+
"with",
|
|
252
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from functools import partial
|
|
2
2
|
from itertools import count
|
|
3
|
-
from
|
|
4
|
-
from koatl._rs import fast_vget, fast_vset, fast_vset_trait
|
|
3
|
+
from koatl._rs import fast_vget
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
def vget(obj, name, ignore_traits=False):
|
|
@@ -66,38 +65,3 @@ def vhas(obj, name, ignore_traits=False):
|
|
|
66
65
|
return True
|
|
67
66
|
|
|
68
67
|
return False
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def ext_prop(type, name):
|
|
72
|
-
def impl(value):
|
|
73
|
-
value._property = True
|
|
74
|
-
fast_vset(type, name, value)
|
|
75
|
-
return value
|
|
76
|
-
|
|
77
|
-
return impl
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def ext_method(type, name):
|
|
81
|
-
def impl(value):
|
|
82
|
-
fast_vset(type, name, value)
|
|
83
|
-
return value
|
|
84
|
-
|
|
85
|
-
return impl
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def ext_trait(type):
|
|
89
|
-
for name, value in type._own_methods.items():
|
|
90
|
-
fast_vset_trait(type.__name__, type._trait_reqs, name, value)
|
|
91
|
-
return type
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
Extension = SimpleNamespace(
|
|
95
|
-
property=ext_prop,
|
|
96
|
-
method=ext_method,
|
|
97
|
-
trait=ext_trait,
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
__all__ = [
|
|
102
|
-
"Extension",
|
|
103
|
-
]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import functools.wraps
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export do = f => wraps(f)& (*args, **kwargs) =>
|
|
5
|
+
let gen = f(*args, **kwargs)
|
|
6
|
+
|
|
7
|
+
let m
|
|
8
|
+
try:
|
|
9
|
+
m = gen.send(None)
|
|
10
|
+
except StopIteration() as e:
|
|
11
|
+
raise ValueError(
|
|
12
|
+
"Returning before `@` is not allowed. "
|
|
13
|
+
"Use `return @MonadType.pure(value)` instead."
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
# TODO: this is a workaround to avoid recursion.
|
|
18
|
+
# is it possible to derive bind_gen directly from bind_once?
|
|
19
|
+
|
|
20
|
+
return m.bind_gen(gen)
|
|
21
|
+
except AttributeError():
|
|
22
|
+
None
|
|
23
|
+
|
|
24
|
+
let recurse = v =>
|
|
25
|
+
try:
|
|
26
|
+
m = gen.send(v)
|
|
27
|
+
return m.bind_once(recurse)
|
|
28
|
+
except StopIteration() as e:
|
|
29
|
+
return m.pure(e.value)
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
return m.bind_once(recurse)
|
|
33
|
+
except AttributeError():
|
|
34
|
+
raise ValueError("@ can only be used with an object that has `bind_once`.")
|
|
@@ -7,6 +7,22 @@ infer_ok = x =>
|
|
|
7
7
|
BaseException() => False
|
|
8
8
|
default True
|
|
9
9
|
|
|
10
|
+
op_coal = (x, f) =>
|
|
11
|
+
if x matches Result():
|
|
12
|
+
return x.coalesce(f)
|
|
13
|
+
|
|
14
|
+
if not infer_ok(x):
|
|
15
|
+
return f()
|
|
16
|
+
return x
|
|
17
|
+
|
|
18
|
+
op_map = (x, f) =>
|
|
19
|
+
if x matches Result():
|
|
20
|
+
return x.map(f)
|
|
21
|
+
|
|
22
|
+
if infer_ok(x):
|
|
23
|
+
return f(x)
|
|
24
|
+
return x
|
|
25
|
+
|
|
10
26
|
export Result = class(MonadOnce):
|
|
11
27
|
__slots__ = ()
|
|
12
28
|
__match_args__ = ("value",)
|
|
@@ -158,4 +174,4 @@ export Err = class(Result):
|
|
|
158
174
|
if self.value matches BaseException():
|
|
159
175
|
raise self.value
|
|
160
176
|
raise ValueError(f"Expected Ok, got {repr(self)}")
|
|
161
|
-
coalesce = (self, f) => f()
|
|
177
|
+
coalesce = (self, f) => f()
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import koatl._rs.(fast_vset, fast_vset_trait)
|
|
2
|
+
|
|
3
|
+
ext_prop = (type, name) => value =>
|
|
4
|
+
value::_property = True
|
|
5
|
+
fast_vset(type, name, value)
|
|
6
|
+
value
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
ext_method = (type, name) => value =>
|
|
10
|
+
fast_vset(type, name, value)
|
|
11
|
+
value
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
ext_trait = type =>
|
|
15
|
+
for name, value in type::_own_methods:
|
|
16
|
+
fast_vset_trait(type::__name__, type::_trait_reqs, name, value)
|
|
17
|
+
type
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
export Extension = {
|
|
21
|
+
property: ext_prop,
|
|
22
|
+
method: ext_method,
|
|
23
|
+
trait: ext_trait,
|
|
24
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import itertools
|
|
2
2
|
import builtins
|
|
3
|
-
import .alg.(Traversable, Ok, Err, Memo, Async, AsyncMemo, Result)
|
|
4
3
|
|
|
4
|
+
import koatl.std.trait.Trait
|
|
5
|
+
import .alg.(Traversable, Ok, Err, Memo, Async, AsyncMemo, Result)
|
|
5
6
|
|
|
6
7
|
export Iterable = class(Traversable, Trait):
|
|
7
8
|
iter = Trait.abstract& self => None
|
|
@@ -30,4 +30,16 @@ export LazyModule = class:
|
|
|
30
30
|
|
|
31
31
|
raise AttributeError(f"Module '{self._name}' has no attribute '{attr}'")
|
|
32
32
|
|
|
33
|
-
__repr__ = self => f"LazyModule({self._name})"
|
|
33
|
+
__repr__ = self => f"LazyModule({self._name})"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
export RootModulesProxy = class:
|
|
37
|
+
__init__ = (self) =>
|
|
38
|
+
self._modules = {}
|
|
39
|
+
|
|
40
|
+
__getattr__ = (self, attr) =>
|
|
41
|
+
if attr not in self._modules:
|
|
42
|
+
self._modules[attr] = LazyModule(attr)
|
|
43
|
+
return self._modules[attr]
|
|
44
|
+
|
|
45
|
+
__repr__ = self => f"RootModulesProxy({self._modules})"
|
koatl-0.1.37/koatl/python/koatl/runtime/classes.py → koatl-0.1.39/koatl/python/koatl/std/trait.py
RENAMED
|
@@ -2,7 +2,7 @@ import abc
|
|
|
2
2
|
import collections
|
|
3
3
|
import inspect
|
|
4
4
|
|
|
5
|
-
from koatl.
|
|
5
|
+
from koatl.prelude import __tl__
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
@collections.abc.Mapping.register
|
|
@@ -40,7 +40,7 @@ class MappingMeta(type):
|
|
|
40
40
|
return [(k, v) for k, v in inspect.getmembers(self) if not k.startswith("_")]
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
# A utility base class to inherit from
|
|
43
|
+
# A utility base class to inherit from that implements Mapping on the type and thus destructuring.
|
|
44
44
|
class Class(metaclass=MappingMeta):
|
|
45
45
|
pass
|
|
46
46
|
|
|
@@ -90,7 +90,7 @@ class TraitMeta(MappingMeta):
|
|
|
90
90
|
# Check if the exact class has _trait_reqs, in which case it's a trait.
|
|
91
91
|
if "_trait_reqs" in cls.__dict__:
|
|
92
92
|
for req in cls._trait_reqs:
|
|
93
|
-
if not vhas(instance, req):
|
|
93
|
+
if not __tl__.vhas(instance, req):
|
|
94
94
|
return False
|
|
95
95
|
|
|
96
96
|
return True
|
|
@@ -118,8 +118,9 @@ fn fast_vget<'py, 'ptr>(
|
|
|
118
118
|
let vtbl2 = VTBL2.lock().unwrap();
|
|
119
119
|
|
|
120
120
|
if let Some(traits) = vtbl2.get(&name) {
|
|
121
|
-
let
|
|
122
|
-
let
|
|
121
|
+
let runtime = py.import("koatl.runtime")?;
|
|
122
|
+
let tl = runtime.getattr("__tl__")?;
|
|
123
|
+
let vget = tl.getattr("vget")?;
|
|
123
124
|
|
|
124
125
|
for t in traits {
|
|
125
126
|
let mut ok = true;
|
|
@@ -2,7 +2,10 @@ import util.assert_eq
|
|
|
2
2
|
|
|
3
3
|
assert_eq(type([1, 2, 3]), list)
|
|
4
4
|
assert_eq(type((1, 2, 3)), tuple)
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
# Record type is not directly made available by the runtime.
|
|
7
|
+
assert_eq(type({1: 2}).__name__, "Record")
|
|
8
|
+
|
|
6
9
|
assert_eq(type(()), tuple)
|
|
7
10
|
assert_eq(type((1,)), tuple)
|
|
8
11
|
assert_eq(type(1), int)
|