koatl 0.1.37__tar.gz → 0.1.38__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.38}/Cargo.lock +1 -1
- {koatl-0.1.37 → koatl-0.1.38}/PKG-INFO +1 -1
- {koatl-0.1.37 → koatl-0.1.38}/koatl/Cargo.toml +1 -1
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/prelude/__init__.tl +1 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/runtime/__init__.py +0 -3
- {koatl-0.1.37 → koatl-0.1.38/koatl}/python/koatl/std/alg/base.tl +2 -0
- {koatl-0.1.37 → koatl-0.1.38/koatl}/python/koatl/std/iter.tl +2 -1
- koatl-0.1.37/koatl/python/koatl/runtime/classes.py → koatl-0.1.38/koatl/python/koatl/std/trait.py +1 -1
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/parser/src/lexer.rs +176 -94
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/prelude/__init__.tl +1 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/runtime/__init__.py +0 -3
- {koatl-0.1.37/koatl → koatl-0.1.38}/python/koatl/std/alg/base.tl +2 -0
- {koatl-0.1.37/koatl → koatl-0.1.38}/python/koatl/std/iter.tl +2 -1
- koatl-0.1.37/python/koatl/runtime/classes.py → koatl-0.1.38/python/koatl/std/trait.py +1 -1
- {koatl-0.1.37 → koatl-0.1.38}/Cargo.toml +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/README.md +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/.github/workflows/CI.yml +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/.gitignore +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/LICENSE +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/README.md +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/__init__.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/__main__.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/cli.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/runtime/helpers.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/runtime/record.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/runtime/virtual.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/std/alg/__init__.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/std/alg/async.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/std/alg/env.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/std/alg/memo.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/std/alg/result.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/std/data/__init__.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/std/data/list.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/std/io.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/std/lazy_module.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/python/koatl/std/re.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/requirements.txt +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/src/emit_py.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/src/lib.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/containers.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/data.txt +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/decorators.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/destructure.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/escape_ident.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/fstr.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/functions.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/generator.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/if_expr.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/loops.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/match.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/nary-list.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/placeholder.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/precedence.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/record.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/scopes.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/semantic_whitespace.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/short_circuit.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/base/with.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/prelude/async.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/prelude/aug_assign.tl +0 -0
- {koatl-0.1.37/koatl/tests/e2e/base → koatl-0.1.38/koatl/tests/e2e/prelude}/coal.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/prelude/env.tl +0 -0
- {koatl-0.1.37/koatl/tests/e2e/base → koatl-0.1.38/koatl/tests/e2e/prelude}/imports.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/prelude/iterables.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/prelude/list.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/prelude/memo.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/prelude/result.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/prelude/slice.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/prelude/try.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/prelude/virtual.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/util/__init__.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/util/module0.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/util/module1.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/e2e/util/module2.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/parse/arith.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/parse/assign.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/parse/block-comments.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/parse/deco.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/parse/func.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/parse/matches.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/test_e2e.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl/tests/test_parse.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/Cargo.toml +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/parser/Cargo.toml +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/parser/src/ast.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/parser/src/lib.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/parser/src/parser.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/parser/src/util.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/src/inference.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/src/lib.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/src/main.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/src/parse_timer.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/src/parser.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/src/py/ast.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/src/py/emit.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/src/py/mod.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/src/py/util.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/src/resolve_scopes.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/src/transform.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/src/types.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/koatl-core/src/util.rs +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/pyproject.toml +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/__init__.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/__main__.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/cli.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/runtime/helpers.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/runtime/record.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/runtime/virtual.py +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/std/alg/__init__.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/std/alg/async.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/std/alg/env.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/std/alg/memo.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/std/alg/result.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/std/data/__init__.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/std/data/list.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/std/io.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/std/lazy_module.tl +0 -0
- {koatl-0.1.37 → koatl-0.1.38}/python/koatl/std/re.tl +0 -0
|
@@ -19,7 +19,6 @@ meta_finder.install_hook()
|
|
|
19
19
|
from .virtual import *
|
|
20
20
|
from .record import *
|
|
21
21
|
from .helpers import *
|
|
22
|
-
from .classes import *
|
|
23
22
|
|
|
24
23
|
|
|
25
24
|
def dummy(name):
|
|
@@ -52,7 +51,6 @@ __tl__ = SimpleNamespace(
|
|
|
52
51
|
**{name: helpers.__dict__[name] for name in helpers.__all__},
|
|
53
52
|
**{name: record.__dict__[name] for name in record.__all__},
|
|
54
53
|
**{name: virtual.__dict__[name] for name in virtual.__all__},
|
|
55
|
-
**{name: classes.__dict__[name] for name in classes.__all__},
|
|
56
54
|
)
|
|
57
55
|
|
|
58
56
|
|
|
@@ -61,5 +59,4 @@ __all__ = [
|
|
|
61
59
|
*helpers.__all__,
|
|
62
60
|
*record.__all__,
|
|
63
61
|
*virtual.__all__,
|
|
64
|
-
*classes.__all__,
|
|
65
62
|
]
|
|
@@ -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
|
koatl-0.1.37/koatl/python/koatl/runtime/classes.py → koatl-0.1.38/koatl/python/koatl/std/trait.py
RENAMED
|
@@ -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
|
|
|
@@ -541,6 +541,19 @@ where
|
|
|
541
541
|
}
|
|
542
542
|
}
|
|
543
543
|
|
|
544
|
+
fn parse_char(&mut self, c: char) -> TResult<'src, ()> {
|
|
545
|
+
let start = self.cursor();
|
|
546
|
+
|
|
547
|
+
if self.next() != Some(c) {
|
|
548
|
+
return Err(Rich::custom(
|
|
549
|
+
self.span_since(&start),
|
|
550
|
+
format!("expected '{c}'"),
|
|
551
|
+
));
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
Ok(())
|
|
555
|
+
}
|
|
556
|
+
|
|
544
557
|
fn parse_seq(&mut self, seq: &str) -> TResult<'src, ()> {
|
|
545
558
|
let start = self.cursor();
|
|
546
559
|
|
|
@@ -579,78 +592,67 @@ where
|
|
|
579
592
|
}
|
|
580
593
|
}
|
|
581
594
|
|
|
582
|
-
fn
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
loop {
|
|
589
|
-
if self.try_parse(|x| x.parse_seq("\"")).is_ok() {
|
|
590
|
-
return Ok(Token::Str(s).spanned(self.span_since(&start)));
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
if self.try_parse(|x| x.parse_newline()).is_ok() {
|
|
594
|
-
return Err(Rich::custom(self.span_since(&start), "unterminated string"));
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
s.push(self.parse_escaped_char()?);
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
fn parse_verbatim_str(&mut self) -> TResult<'src, Spanned<Token<'src>>> {
|
|
602
|
-
let start = self.cursor();
|
|
603
|
-
|
|
604
|
-
self.parse_seq("\"\"\"")?;
|
|
605
|
-
|
|
606
|
-
let mut s = String::new();
|
|
607
|
-
loop {
|
|
608
|
-
if self.try_parse(|x| x.parse_seq("\"\"\"")).is_ok() {
|
|
609
|
-
return Ok(Token::Str(s).spanned(self.span_since(&start)));
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
s.push(self.next().ok_or_else(|| {
|
|
613
|
-
Rich::custom(self.span_since(&start), "unterminated verbatim string")
|
|
614
|
-
})?);
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
fn parse_fstr_inner(&mut self, ending: &str, verbatim: bool) -> TResult<'src, TokenList<'src>> {
|
|
595
|
+
fn parse_fstr_inner(
|
|
596
|
+
&mut self,
|
|
597
|
+
ending_char: char,
|
|
598
|
+
ending_char_count: u32,
|
|
599
|
+
verbatim: bool,
|
|
600
|
+
) -> TResult<'src, TokenList<'src>> {
|
|
619
601
|
let mut marker = self.cursor();
|
|
620
602
|
let mut tokens = vec![];
|
|
621
603
|
let mut current_str = String::new();
|
|
622
604
|
|
|
605
|
+
let mut seen_quotes = 0;
|
|
606
|
+
let mut ending_marker = self.input.save();
|
|
623
607
|
loop {
|
|
624
|
-
if self.
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
return Ok(TokenList(tokens));
|
|
608
|
+
if !verbatim && self.try_parse(|x| x.parse_newline()).is_ok() {
|
|
609
|
+
return Err(Rich::custom(
|
|
610
|
+
self.span_since(&marker),
|
|
611
|
+
"unterminated fstring",
|
|
612
|
+
));
|
|
632
613
|
}
|
|
633
614
|
|
|
634
|
-
|
|
615
|
+
let Some(peeked) = self.peek() else {
|
|
635
616
|
return Err(Rich::custom(
|
|
636
617
|
self.span_since(&marker),
|
|
637
618
|
"unterminated fstring",
|
|
638
619
|
));
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
let mut save_marker = false;
|
|
623
|
+
|
|
624
|
+
if peeked == ending_char {
|
|
625
|
+
seen_quotes += 1;
|
|
626
|
+
|
|
627
|
+
if seen_quotes == ending_char_count {
|
|
628
|
+
if tokens.len() == 0 {
|
|
629
|
+
tokens
|
|
630
|
+
.push(Token::FstrBegin(current_str).spanned(self.span_since(&marker)));
|
|
631
|
+
} else {
|
|
632
|
+
tokens.push(
|
|
633
|
+
Token::FstrContinue(current_str).spanned(self.span_since(&marker)),
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
self.input.rewind(ending_marker);
|
|
638
|
+
|
|
639
|
+
return Ok(TokenList(tokens));
|
|
640
|
+
}
|
|
641
|
+
} else {
|
|
642
|
+
for _ in 0..seen_quotes {
|
|
643
|
+
current_str.push(ending_char);
|
|
644
|
+
}
|
|
645
|
+
seen_quotes = 0;
|
|
646
|
+
save_marker = true;
|
|
639
647
|
}
|
|
640
648
|
|
|
641
649
|
if self.try_parse(|x| x.parse_seq("{{")).is_ok() {
|
|
642
650
|
current_str.push('{');
|
|
643
|
-
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
if self.try_parse(|x| x.parse_seq("}}")).is_ok() {
|
|
651
|
+
} else if self.try_parse(|x| x.parse_seq("}}")).is_ok() {
|
|
647
652
|
current_str.push('}');
|
|
648
|
-
|
|
649
|
-
} else if self.try_parse(|x| x.parse_seq("}")).is_ok() {
|
|
653
|
+
} else if self.try_parse(|x| x.parse_char('}')).is_ok() {
|
|
650
654
|
return Err(Rich::custom(self.span_since(&marker), "unexpected '}'"));
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
if self.try_parse(|x| x.parse_seq("{")).is_ok() {
|
|
655
|
+
} else if self.try_parse(|x| x.parse_char('{')).is_ok() {
|
|
654
656
|
if tokens.len() == 0 {
|
|
655
657
|
tokens.push(Token::FstrBegin(current_str).spanned(self.span_since(&marker)));
|
|
656
658
|
} else {
|
|
@@ -669,7 +671,7 @@ where
|
|
|
669
671
|
let mut format_tokens = vec![];
|
|
670
672
|
if self.try_parse(|x| x.parse_seq("!")).is_ok() {
|
|
671
673
|
format_tokens.push(Token::Symbol("!").spanned(self.span_since(&marker)));
|
|
672
|
-
format_tokens.extend(self.parse_fstr_inner(
|
|
674
|
+
format_tokens.extend(self.parse_fstr_inner('}', 1, verbatim)?);
|
|
673
675
|
}
|
|
674
676
|
|
|
675
677
|
self.parse_seq("}")?;
|
|
@@ -690,72 +692,152 @@ where
|
|
|
690
692
|
tokens.extend(format_tokens);
|
|
691
693
|
|
|
692
694
|
marker = self.cursor();
|
|
695
|
+
} else {
|
|
696
|
+
let next_char = if verbatim {
|
|
697
|
+
self.next().ok_or_else(|| {
|
|
698
|
+
Rich::custom(self.span_since(&marker), "unterminated verbatim fstring")
|
|
699
|
+
})?
|
|
700
|
+
} else {
|
|
701
|
+
self.parse_escaped_char()?
|
|
702
|
+
};
|
|
693
703
|
|
|
694
|
-
|
|
704
|
+
if save_marker {
|
|
705
|
+
current_str.push(next_char);
|
|
706
|
+
}
|
|
695
707
|
}
|
|
696
708
|
|
|
697
|
-
if
|
|
698
|
-
|
|
699
|
-
Rich::custom(self.span_since(&marker), "unterminated verbatim fstring")
|
|
700
|
-
})?);
|
|
701
|
-
} else {
|
|
702
|
-
current_str.push(self.parse_escaped_char()?);
|
|
709
|
+
if save_marker {
|
|
710
|
+
ending_marker = self.input.save();
|
|
703
711
|
}
|
|
704
712
|
}
|
|
705
713
|
}
|
|
706
714
|
|
|
707
|
-
fn
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
715
|
+
fn parse_regular_str(&mut self, ch: char) -> TResult<'src, Spanned<Token<'src>>> {
|
|
716
|
+
let start = self.cursor();
|
|
717
|
+
let mut quote_count = 0;
|
|
718
|
+
|
|
719
|
+
let mut verbatim = self.try_parse(|x| x.parse_char('r')).is_ok();
|
|
720
|
+
|
|
721
|
+
while self.try_parse(|x| x.parse_char(ch)).is_ok() {
|
|
722
|
+
quote_count += 1;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
if quote_count == 2 {
|
|
726
|
+
return Ok(Token::Str(String::new()).spanned(self.span_since(&start)));
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
verbatim |= quote_count >= 3;
|
|
730
|
+
|
|
731
|
+
let mut seen_quotes = 0;
|
|
732
|
+
let mut s = String::new();
|
|
733
|
+
loop {
|
|
734
|
+
if !verbatim && self.try_parse(|x| x.parse_newline()).is_ok() {
|
|
735
|
+
return Err(Rich::custom(self.span_since(&start), "unterminated string"));
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
let Some(peeked) = self.peek() else {
|
|
739
|
+
return Err(Rich::custom(self.span_since(&start), "unterminated string"));
|
|
740
|
+
};
|
|
741
|
+
|
|
742
|
+
let mut push_next = false;
|
|
743
|
+
if peeked == ch {
|
|
744
|
+
seen_quotes += 1;
|
|
745
|
+
|
|
746
|
+
if seen_quotes == quote_count {
|
|
747
|
+
self.next();
|
|
748
|
+
return Ok(Token::Str(s).spanned(self.span_since(&start)));
|
|
749
|
+
}
|
|
750
|
+
} else {
|
|
751
|
+
for _ in 0..seen_quotes {
|
|
752
|
+
s.push(ch);
|
|
753
|
+
}
|
|
754
|
+
seen_quotes = 0;
|
|
755
|
+
push_next = true;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
let next_char = if verbatim {
|
|
759
|
+
self.next().unwrap()
|
|
760
|
+
} else {
|
|
761
|
+
self.parse_escaped_char()?
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
if push_next {
|
|
765
|
+
s.push(next_char);
|
|
766
|
+
}
|
|
718
767
|
}
|
|
719
768
|
}
|
|
720
769
|
|
|
721
|
-
fn
|
|
770
|
+
fn parse_fstr(&mut self, ch: char) -> TResult<'src, TokenList<'src>> {
|
|
722
771
|
let start = self.cursor();
|
|
772
|
+
let mut verbatim = self.try_parse(|x| x.parse_seq("r")).is_ok();
|
|
723
773
|
|
|
724
|
-
|
|
725
|
-
|
|
774
|
+
self.parse_seq("f")?;
|
|
775
|
+
let mut quote_count = 0;
|
|
776
|
+
|
|
777
|
+
while self.try_parse(|x| x.parse_char(ch)).is_ok() {
|
|
778
|
+
quote_count += 1;
|
|
726
779
|
}
|
|
727
780
|
|
|
728
|
-
if
|
|
729
|
-
return Ok((
|
|
781
|
+
if quote_count == 2 {
|
|
782
|
+
return Ok(TokenList(vec![
|
|
783
|
+
Token::FstrBegin(String::new()).spanned(self.span_since(&start)),
|
|
784
|
+
]));
|
|
730
785
|
}
|
|
731
786
|
|
|
732
|
-
|
|
733
|
-
self.span_since(&start),
|
|
734
|
-
"expected string start",
|
|
735
|
-
))
|
|
736
|
-
}
|
|
787
|
+
verbatim |= quote_count >= 3;
|
|
737
788
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
789
|
+
let inner = self.parse_fstr_inner(ch, quote_count, verbatim)?;
|
|
790
|
+
|
|
791
|
+
let start = self.cursor();
|
|
792
|
+
|
|
793
|
+
let mut close_quote_count = 0;
|
|
794
|
+
while self.try_parse(|x| x.parse_char(ch)).is_ok() {
|
|
795
|
+
close_quote_count += 1;
|
|
742
796
|
}
|
|
743
797
|
|
|
744
|
-
if
|
|
745
|
-
|
|
746
|
-
|
|
798
|
+
if quote_count != close_quote_count {
|
|
799
|
+
return Err(Rich::custom(
|
|
800
|
+
self.span_since(&start),
|
|
801
|
+
format!(
|
|
802
|
+
"expected {} closing quotes, found {}",
|
|
803
|
+
quote_count, close_quote_count
|
|
804
|
+
),
|
|
805
|
+
));
|
|
747
806
|
}
|
|
748
807
|
|
|
749
|
-
|
|
750
|
-
|
|
808
|
+
return Ok(inner);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
fn parse_str_start(&mut self) -> TResult<'src, ()> {
|
|
812
|
+
let start = self.cursor();
|
|
813
|
+
|
|
814
|
+
let _ = self.try_parse(|x| x.parse_ident_or_token());
|
|
815
|
+
self.parse_char('"')?;
|
|
816
|
+
|
|
817
|
+
Ok(())
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
fn parse_str(&mut self) -> TResult<'src, TokenList<'src>> {
|
|
821
|
+
if self.look_ahead(|x| x.parse_seq("rf\"")).is_ok() {
|
|
822
|
+
let tokens = self.parse_fstr('"')?;
|
|
751
823
|
return Ok(tokens);
|
|
752
824
|
}
|
|
753
825
|
|
|
754
826
|
if self.look_ahead(|x| x.parse_seq("f\"")).is_ok() {
|
|
755
|
-
let tokens = self.parse_fstr(
|
|
827
|
+
let tokens = self.parse_fstr('"')?;
|
|
756
828
|
return Ok(tokens);
|
|
757
829
|
}
|
|
758
830
|
|
|
831
|
+
if self.look_ahead(|x| x.parse_seq("r\"")).is_ok() {
|
|
832
|
+
let token = self.parse_regular_str('"')?;
|
|
833
|
+
return Ok(TokenList(vec![token]));
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
if self.look_ahead(|x| x.parse_seq("\"")).is_ok() {
|
|
837
|
+
let token = self.parse_regular_str('"')?;
|
|
838
|
+
return Ok(TokenList(vec![token]));
|
|
839
|
+
}
|
|
840
|
+
|
|
759
841
|
Err(Rich::custom(
|
|
760
842
|
self.span_since(&self.cursor()),
|
|
761
843
|
"expected string start",
|
|
@@ -19,7 +19,6 @@ meta_finder.install_hook()
|
|
|
19
19
|
from .virtual import *
|
|
20
20
|
from .record import *
|
|
21
21
|
from .helpers import *
|
|
22
|
-
from .classes import *
|
|
23
22
|
|
|
24
23
|
|
|
25
24
|
def dummy(name):
|
|
@@ -52,7 +51,6 @@ __tl__ = SimpleNamespace(
|
|
|
52
51
|
**{name: helpers.__dict__[name] for name in helpers.__all__},
|
|
53
52
|
**{name: record.__dict__[name] for name in record.__all__},
|
|
54
53
|
**{name: virtual.__dict__[name] for name in virtual.__all__},
|
|
55
|
-
**{name: classes.__dict__[name] for name in classes.__all__},
|
|
56
54
|
)
|
|
57
55
|
|
|
58
56
|
|
|
@@ -61,5 +59,4 @@ __all__ = [
|
|
|
61
59
|
*helpers.__all__,
|
|
62
60
|
*record.__all__,
|
|
63
61
|
*virtual.__all__,
|
|
64
|
-
*classes.__all__,
|
|
65
62
|
]
|
|
@@ -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
|
|
@@ -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
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|