koatl 0.3.9__tar.gz → 0.3.11__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.3.9 → koatl-0.3.11}/Cargo.lock +2 -2
- {koatl-0.3.9 → koatl-0.3.11}/PKG-INFO +1 -1
- {koatl-0.3.9 → koatl-0.3.11}/koatl/Cargo.toml +1 -1
- {koatl-0.3.9 → koatl-0.3.11}/koatl/src/emit_py.rs +47 -23
- koatl-0.3.11/koatl/tests/e2e/base/arguments.tl +41 -0
- koatl-0.3.11/koatl/tests/fail-parse/arguments_mixed_defaults.tl +1 -0
- koatl-0.3.11/koatl/tests/fail-parse/arguments_multiple_kwargs.tl +1 -0
- koatl-0.3.11/koatl/tests/fail-parse/arguments_multiple_kwonly_markers.tl +1 -0
- koatl-0.3.11/koatl/tests/fail-parse/arguments_multiple_posonly_markers.tl +1 -0
- koatl-0.3.11/koatl/tests/fail-parse/arguments_multiple_varargs.tl +1 -0
- koatl-0.3.11/koatl/tests/fail-parse/arguments_posonly_after_kwonly.tl +1 -0
- koatl-0.3.11/koatl/tests/fail-parse/arguments_vararg_and_kwonly_marker.tl +1 -0
- koatl-0.3.11/koatl/tests/parse/mutual-recursion.tl +2 -0
- koatl-0.3.11/koatl/tests/test_parse_fail.py +26 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/ast.rs +2 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/lift_cst.rs +2 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/py/ast.rs +35 -6
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/py/ast_builder.rs +2 -23
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/py/emit.rs +75 -27
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/resolve_scopes.rs +22 -12
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/transform.rs +157 -24
- {koatl-0.3.9 → koatl-0.3.11}/koatl-parser/src/cst.rs +6 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-parser/src/parser.rs +8 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-parser/src/simple_fmt.rs +2 -0
- {koatl-0.3.9 → koatl-0.3.11}/Cargo.toml +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/README.md +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/.github/workflows/CI.yml +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/.gitignore +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/LICENSE +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/README.md +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/__init__.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/__main__.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/cli.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/notebook/magic.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/prelude/__init__.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/runtime/__init__.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/runtime/record.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/runtime/vattr.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/__init__.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/control/__init__.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/control/async.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/control/base.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/control/do.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/control/env.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/control/memo.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/control/result.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/data/__init__.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/data/list.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/data/record.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/ext.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/io.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/iter.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/json.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/lazy_module.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/pickle.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/re.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/trait.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/requirements.txt +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/src/lib.rs +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/containers.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/data.txt +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/decorators.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/destructure.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/escape_ident.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/fstr.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/functions.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/generator.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/if_expr.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/loops.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/match.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/nary-list.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/placeholder.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/precedence.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/scopes.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/semantic_whitespace.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/short_circuit.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/with.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/async.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/aug_assign.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/coal.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/env.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/imports.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/iterables.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/list.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/memo.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/record.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/result.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/slice.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/try.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/virtual.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/util/__init__.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/util/module0.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/util/module1.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/util/module2.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/parse/arith.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/parse/assign.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/parse/block-comments.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/parse/deco.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/parse/func.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/parse/matches.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/parse/numbers.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/test_e2e.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/test_parse.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/Cargo.toml +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/ast_builder.rs +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/inference.rs +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/lib.rs +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/main.rs +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/py/mod.rs +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/types.rs +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/util.rs +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-parser/Cargo.toml +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-parser/src/lexer.rs +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/koatl-parser/src/lib.rs +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/pyproject.toml +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/__init__.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/__main__.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/cli.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/notebook/magic.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/prelude/__init__.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/runtime/__init__.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/runtime/record.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/runtime/vattr.py +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/__init__.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/control/__init__.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/control/async.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/control/base.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/control/do.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/control/env.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/control/memo.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/control/result.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/data/__init__.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/data/list.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/data/record.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/ext.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/io.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/iter.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/json.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/lazy_module.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/pickle.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/re.tl +0 -0
- {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/trait.py +0 -0
|
@@ -190,7 +190,7 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
|
|
190
190
|
|
|
191
191
|
[[package]]
|
|
192
192
|
name = "koatl"
|
|
193
|
-
version = "0.3.
|
|
193
|
+
version = "0.3.11"
|
|
194
194
|
dependencies = [
|
|
195
195
|
"ariadne",
|
|
196
196
|
"koatl-core",
|
|
@@ -248,7 +248,7 @@ dependencies = [
|
|
|
248
248
|
|
|
249
249
|
[[package]]
|
|
250
250
|
name = "ohtli"
|
|
251
|
-
version = "0.1.
|
|
251
|
+
version = "0.1.1"
|
|
252
252
|
dependencies = [
|
|
253
253
|
"anyhow",
|
|
254
254
|
"clap",
|
|
@@ -110,41 +110,65 @@ impl<'src> PyBlockExt<'src> for PyBlock<'src> {
|
|
|
110
110
|
trait PyArgDefExt<'src> {
|
|
111
111
|
fn emit_py<'py>(&self, ctx: &PyCtx<'py, 'src>) -> PyTlResult<PyObject>;
|
|
112
112
|
}
|
|
113
|
-
impl<'src> PyArgDefExt<'src> for
|
|
113
|
+
impl<'src> PyArgDefExt<'src> for PyArgList<'src> {
|
|
114
114
|
fn emit_py<'py>(&self, ctx: &PyCtx<'py, 'src>) -> PyTlResult<PyObject> {
|
|
115
|
+
let mut py_posonlyargs = Vec::new();
|
|
115
116
|
let mut py_args = Vec::new();
|
|
117
|
+
let mut py_kwonlyargs = Vec::new();
|
|
116
118
|
let mut py_defaults = Vec::new();
|
|
119
|
+
let mut py_kw_defaults = Vec::new();
|
|
117
120
|
let mut vararg = None;
|
|
118
121
|
let mut kwarg = None;
|
|
119
122
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
123
|
+
// Process position-only arguments
|
|
124
|
+
for (arg_name, default) in &self.posonlyargs {
|
|
125
|
+
let arg_ast = ctx.ast_cls("arg", (arg_name.as_ref(), ctx.py.None()))?;
|
|
126
|
+
py_posonlyargs.push(arg_ast);
|
|
127
|
+
if let Some(default_expr) = default {
|
|
128
|
+
py_defaults.push(default_expr.emit_py(ctx)?);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Process regular arguments
|
|
133
|
+
for (arg_name, default) in &self.args {
|
|
134
|
+
let arg_ast = ctx.ast_cls("arg", (arg_name.as_ref(), ctx.py.None()))?;
|
|
135
|
+
py_args.push(arg_ast);
|
|
136
|
+
if let Some(default_expr) = default {
|
|
137
|
+
py_defaults.push(default_expr.emit_py(ctx)?);
|
|
135
138
|
}
|
|
136
139
|
}
|
|
137
140
|
|
|
141
|
+
// Process *args
|
|
142
|
+
if let Some(arg_name) = &self.vararg {
|
|
143
|
+
vararg = Some(ctx.ast_cls("arg", (arg_name.as_ref(), ctx.py.None()))?);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Process keyword-only arguments
|
|
147
|
+
for (arg_name, default) in &self.kwonlyargs {
|
|
148
|
+
let arg_ast = ctx.ast_cls("arg", (arg_name.as_ref(), ctx.py.None()))?;
|
|
149
|
+
py_kwonlyargs.push(arg_ast);
|
|
150
|
+
if let Some(default_expr) = default {
|
|
151
|
+
py_kw_defaults.push(default_expr.emit_py(ctx)?);
|
|
152
|
+
} else {
|
|
153
|
+
py_kw_defaults.push(ctx.py.None());
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Process **kwargs
|
|
158
|
+
if let Some(arg_name) = &self.kwarg {
|
|
159
|
+
kwarg = Some(ctx.ast_cls("arg", (arg_name.as_ref(), ctx.py.None()))?);
|
|
160
|
+
}
|
|
161
|
+
|
|
138
162
|
ctx.ast_cls(
|
|
139
163
|
"arguments",
|
|
140
164
|
(
|
|
141
|
-
|
|
142
|
-
py_args,
|
|
143
|
-
vararg,
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
kwarg,
|
|
147
|
-
py_defaults,
|
|
165
|
+
py_posonlyargs, // posonlyargs
|
|
166
|
+
py_args, // args
|
|
167
|
+
vararg, // vararg
|
|
168
|
+
py_kwonlyargs, // kwonlyargs
|
|
169
|
+
py_kw_defaults, // kw_defaults
|
|
170
|
+
kwarg, // kwarg
|
|
171
|
+
py_defaults, // defaults
|
|
148
172
|
),
|
|
149
173
|
)
|
|
150
174
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import util.assert_eq
|
|
2
|
+
|
|
3
|
+
# Test *args with keyword-only default argument
|
|
4
|
+
let fn = (*args, default=2) => args + (default,)
|
|
5
|
+
|
|
6
|
+
assert_eq(fn(1, 3), (1, 3, 2))
|
|
7
|
+
|
|
8
|
+
# Test regular arg with default and *args
|
|
9
|
+
fn = (a, b=2, *args) => (a, b) + args
|
|
10
|
+
|
|
11
|
+
assert_eq(fn(1, 3, 4, 5), (1, 3, 4, 5))
|
|
12
|
+
assert_eq(fn(1), (1, 2))
|
|
13
|
+
fn = (a, /, b, *, c=5) => (a, b, c)
|
|
14
|
+
|
|
15
|
+
assert_eq(fn(1, 2), (1, 2, 5))
|
|
16
|
+
assert_eq(fn(1, 2, c=10), (1, 2, 10))
|
|
17
|
+
fn = (a, b=3, /, c=4) => (a, b, c)
|
|
18
|
+
|
|
19
|
+
assert_eq(fn(1), (1, 3, 4))
|
|
20
|
+
assert_eq(fn(1, 2), (1, 2, 4))
|
|
21
|
+
assert_eq(fn(1, 2, 5), (1, 2, 5))
|
|
22
|
+
fn = (a, b, *, c, d=10) => (a, b, c, d)
|
|
23
|
+
|
|
24
|
+
assert_eq(fn(1, 2, c=3), (1, 2, 3, 10))
|
|
25
|
+
assert_eq(fn(1, 2, c=3, d=4), (1, 2, 3, 4))
|
|
26
|
+
|
|
27
|
+
# Test **kwargs
|
|
28
|
+
fn = (a, **kwargs) => (a, kwargs)
|
|
29
|
+
|
|
30
|
+
assert_eq(fn(1), (1, {}))
|
|
31
|
+
assert_eq(fn(1, b=2, c=3), (1, {"b": 2, "c": 3}))
|
|
32
|
+
fn = (a, b, /, c, *args, d, e=5, **kwargs) => (a, b, c, args, d, e, kwargs)
|
|
33
|
+
|
|
34
|
+
assert_eq(fn(1, 2, 3, d=4), (1, 2, 3, (), 4, 5, {}))
|
|
35
|
+
assert_eq(fn(1, 2, 3, 4, 5, d=6, e=7, f=8), (1, 2, 3, (4, 5), 6, 7, {"f": 8}))
|
|
36
|
+
fn = (a, b, c, /) => (a, b, c)
|
|
37
|
+
|
|
38
|
+
assert_eq(fn(1, 2, 3), (1, 2, 3))
|
|
39
|
+
fn = (*, a, b) => (a, b)
|
|
40
|
+
|
|
41
|
+
assert_eq(fn(a=1, b=2), (1, 2))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let a = (b=3, c, default=2, *a) => None
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let a = (**a, **b) => None
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let a = (*, *, default=2) => None
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let a = (a, /, b, /, c) => None
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let a = (*a, *b) => None
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let a = (a, *, /, default=2) => None
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let a = (*a, *, default=2) => None
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import koatl.cli
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_test_data():
|
|
7
|
+
data_dirs = [
|
|
8
|
+
Path(__file__).parent / "fail-parse",
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
test_cases = []
|
|
12
|
+
for data_dir in data_dirs:
|
|
13
|
+
for file_path in data_dir.glob("*.tl"):
|
|
14
|
+
test_cases.append(pytest.param(file_path, id=str(file_path)))
|
|
15
|
+
|
|
16
|
+
return test_cases
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@pytest.mark.parametrize("test_file", get_test_data())
|
|
20
|
+
def test_parse(test_file):
|
|
21
|
+
try:
|
|
22
|
+
koatl.cli.transpile_from_path(test_file, mode="script")
|
|
23
|
+
except:
|
|
24
|
+
return
|
|
25
|
+
|
|
26
|
+
raise AssertionError("Expected parse to fail but it succeeded.")
|
|
@@ -555,6 +555,8 @@ impl<'src, 'tok> Lift<ast::ArgDefItem<'src, ast::STree<'src>>>
|
|
|
555
555
|
cst::ArgDefItem::KwargSpread { name, .. } => {
|
|
556
556
|
ast::ArgDefItem::KwargSpread(name.lift_as_ident())
|
|
557
557
|
}
|
|
558
|
+
cst::ArgDefItem::PosOnlyMarker { .. } => ast::ArgDefItem::PosOnlyMarker,
|
|
559
|
+
cst::ArgDefItem::KwOnlyMarker { .. } => ast::ArgDefItem::KwOnlyMarker,
|
|
558
560
|
}
|
|
559
561
|
}
|
|
560
562
|
}
|
|
@@ -47,7 +47,7 @@ impl<'a> PyDecorators<'a> {
|
|
|
47
47
|
#[derive(Debug, Clone)]
|
|
48
48
|
pub struct PyFnDef<'a> {
|
|
49
49
|
pub name: PyToken<'a>,
|
|
50
|
-
pub args:
|
|
50
|
+
pub args: PyArgList<'a>,
|
|
51
51
|
pub body: PyBlock<'a>,
|
|
52
52
|
pub decorators: PyDecorators<'a>,
|
|
53
53
|
pub async_: bool,
|
|
@@ -188,10 +188,39 @@ pub enum PyCallItem<'a> {
|
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
#[derive(Debug, Clone)]
|
|
191
|
-
pub
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
191
|
+
pub struct PyArgList<'a> {
|
|
192
|
+
/// Position-only arguments (before `/` marker)
|
|
193
|
+
pub posonlyargs: Vec<(PyToken<'a>, Option<SPyExpr<'a>>)>,
|
|
194
|
+
/// Regular positional or keyword arguments
|
|
195
|
+
pub args: Vec<(PyToken<'a>, Option<SPyExpr<'a>>)>,
|
|
196
|
+
/// Variadic positional argument (*args)
|
|
197
|
+
pub vararg: Option<PyToken<'a>>,
|
|
198
|
+
/// Keyword-only arguments (after `*` or `*args`)
|
|
199
|
+
pub kwonlyargs: Vec<(PyToken<'a>, Option<SPyExpr<'a>>)>,
|
|
200
|
+
/// Variadic keyword argument (**kwargs)
|
|
201
|
+
pub kwarg: Option<PyToken<'a>>,
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
impl<'a> PyArgList<'a> {
|
|
205
|
+
pub fn empty() -> Self {
|
|
206
|
+
PyArgList {
|
|
207
|
+
posonlyargs: vec![],
|
|
208
|
+
args: vec![],
|
|
209
|
+
vararg: None,
|
|
210
|
+
kwonlyargs: vec![],
|
|
211
|
+
kwarg: None,
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
pub fn simple_args(args: Vec<(PyToken<'a>, Option<SPyExpr<'a>>)>) -> Self {
|
|
216
|
+
PyArgList {
|
|
217
|
+
posonlyargs: vec![],
|
|
218
|
+
args,
|
|
219
|
+
vararg: None,
|
|
220
|
+
kwonlyargs: vec![],
|
|
221
|
+
kwarg: None,
|
|
222
|
+
}
|
|
223
|
+
}
|
|
195
224
|
}
|
|
196
225
|
|
|
197
226
|
#[derive(Debug, Clone)]
|
|
@@ -225,7 +254,7 @@ pub enum PyExpr<'a> {
|
|
|
225
254
|
Subscript(Box<SPyExpr<'a>>, Box<SPyExpr<'a>>, PyAccessCtx),
|
|
226
255
|
|
|
227
256
|
IfExpr(Box<SPyExpr<'a>>, Box<SPyExpr<'a>>, Box<SPyExpr<'a>>),
|
|
228
|
-
Lambda(
|
|
257
|
+
Lambda(PyArgList<'a>, Box<SPyExpr<'a>>),
|
|
229
258
|
|
|
230
259
|
List(Vec<PyListItem<'a>>, PyAccessCtx),
|
|
231
260
|
Tuple(Vec<PyListItem<'a>>, PyAccessCtx),
|
|
@@ -69,7 +69,7 @@ impl PyAstBuilder {
|
|
|
69
69
|
pub fn fn_def<'src>(
|
|
70
70
|
&self,
|
|
71
71
|
name: impl Into<PyToken<'src>>,
|
|
72
|
-
args:
|
|
72
|
+
args: PyArgList<'src>,
|
|
73
73
|
body: PyBlock<'src>,
|
|
74
74
|
async_: bool,
|
|
75
75
|
) -> SPyStmt<'src> {
|
|
@@ -305,11 +305,7 @@ impl PyAstBuilder {
|
|
|
305
305
|
(PyExpr::YieldFrom(Box::new(value)), self.span).into()
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
-
pub fn lambda<'src>(
|
|
309
|
-
&self,
|
|
310
|
-
args: Vec<PyArgDefItem<'src>>,
|
|
311
|
-
body: SPyExpr<'src>,
|
|
312
|
-
) -> SPyExpr<'src> {
|
|
308
|
+
pub fn lambda<'src>(&self, args: PyArgList<'src>, body: SPyExpr<'src>) -> SPyExpr<'src> {
|
|
313
309
|
(PyExpr::Lambda(args, Box::new(body)), self.span).into()
|
|
314
310
|
}
|
|
315
311
|
|
|
@@ -334,23 +330,6 @@ impl PyAstBuilder {
|
|
|
334
330
|
PyCallItem::KwargSpread(expr)
|
|
335
331
|
}
|
|
336
332
|
|
|
337
|
-
// Utility builders for argument definitions
|
|
338
|
-
pub fn arg_def<'src>(
|
|
339
|
-
&self,
|
|
340
|
-
name: impl Into<PyToken<'src>>,
|
|
341
|
-
default: Option<SPyExpr<'src>>,
|
|
342
|
-
) -> PyArgDefItem<'src> {
|
|
343
|
-
PyArgDefItem::Arg(name.into(), default)
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
pub fn arg_def_spread<'src>(&self, name: impl Into<PyToken<'src>>) -> PyArgDefItem<'src> {
|
|
347
|
-
PyArgDefItem::ArgSpread(name.into())
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
pub fn kwarg_def_spread<'src>(&self, name: impl Into<PyToken<'src>>) -> PyArgDefItem<'src> {
|
|
351
|
-
PyArgDefItem::KwargSpread(name.into())
|
|
352
|
-
}
|
|
353
|
-
|
|
354
333
|
// Utility builders for tuple items
|
|
355
334
|
pub fn list_item<'src>(&self, expr: SPyExpr<'src>) -> PyListItem<'src> {
|
|
356
335
|
PyListItem::Item(expr)
|
|
@@ -105,26 +105,85 @@ impl PyCallItem<'_> {
|
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
impl
|
|
108
|
+
impl PyArgList<'_> {
|
|
109
109
|
fn emit_to(&mut self, ctx: &mut EmitCtx) -> TlResult<()> {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
110
|
+
let mut first = true;
|
|
111
|
+
|
|
112
|
+
// Emit position-only arguments
|
|
113
|
+
for (name, default) in &mut self.posonlyargs {
|
|
114
|
+
if !first {
|
|
115
|
+
ctx.emit(", ");
|
|
116
|
+
}
|
|
117
|
+
first = false;
|
|
118
|
+
|
|
119
|
+
ctx.emit(name);
|
|
120
|
+
if let Some(default) = default {
|
|
121
|
+
ctx.emit("=");
|
|
122
|
+
default.emit_to(ctx, LOW_PREC)?;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Emit position-only marker if there are position-only args
|
|
127
|
+
if !self.posonlyargs.is_empty() {
|
|
128
|
+
if !first {
|
|
129
|
+
ctx.emit(", ");
|
|
130
|
+
}
|
|
131
|
+
first = false;
|
|
132
|
+
ctx.emit("/");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Emit regular args
|
|
136
|
+
for (name, default) in &mut self.args {
|
|
137
|
+
if !first {
|
|
138
|
+
ctx.emit(", ");
|
|
139
|
+
}
|
|
140
|
+
first = false;
|
|
141
|
+
|
|
142
|
+
ctx.emit(name);
|
|
143
|
+
if let Some(default) = default {
|
|
144
|
+
ctx.emit("=");
|
|
145
|
+
default.emit_to(ctx, LOW_PREC)?;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Emit *args
|
|
150
|
+
if let Some(vararg) = &self.vararg {
|
|
151
|
+
if !first {
|
|
152
|
+
ctx.emit(", ");
|
|
153
|
+
}
|
|
154
|
+
first = false;
|
|
155
|
+
ctx.emit(&format!("*{}", vararg));
|
|
156
|
+
} else if !self.kwonlyargs.is_empty() {
|
|
157
|
+
// If there are keyword-only args but no *args, emit bare *
|
|
158
|
+
if !first {
|
|
159
|
+
ctx.emit(", ");
|
|
119
160
|
}
|
|
120
|
-
|
|
121
|
-
|
|
161
|
+
first = false;
|
|
162
|
+
ctx.emit("*");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Emit keyword-only args
|
|
166
|
+
for (name, default) in &mut self.kwonlyargs {
|
|
167
|
+
if !first {
|
|
168
|
+
ctx.emit(", ");
|
|
122
169
|
}
|
|
123
|
-
|
|
124
|
-
|
|
170
|
+
first = false;
|
|
171
|
+
|
|
172
|
+
ctx.emit(name);
|
|
173
|
+
if let Some(default) = default {
|
|
174
|
+
ctx.emit("=");
|
|
175
|
+
default.emit_to(ctx, LOW_PREC)?;
|
|
125
176
|
}
|
|
126
177
|
}
|
|
127
178
|
|
|
179
|
+
// Emit **kwargs
|
|
180
|
+
if let Some(kwarg) = &self.kwarg {
|
|
181
|
+
if !first {
|
|
182
|
+
ctx.emit(", ");
|
|
183
|
+
}
|
|
184
|
+
ctx.emit(&format!("**{}", kwarg));
|
|
185
|
+
}
|
|
186
|
+
|
|
128
187
|
Ok(())
|
|
129
188
|
}
|
|
130
189
|
}
|
|
@@ -546,13 +605,7 @@ impl SPyExpr<'_> {
|
|
|
546
605
|
}
|
|
547
606
|
PyExpr::Lambda(args, body) => {
|
|
548
607
|
ctx.emit("(lambda ");
|
|
549
|
-
|
|
550
|
-
for (i, arg) in args.iter_mut().enumerate() {
|
|
551
|
-
if i > 0 {
|
|
552
|
-
ctx.emit(", ");
|
|
553
|
-
}
|
|
554
|
-
arg.emit_to(ctx)?;
|
|
555
|
-
}
|
|
608
|
+
args.emit_to(ctx)?;
|
|
556
609
|
ctx.emit(": ");
|
|
557
610
|
body.emit_to(ctx, HIGH_PREC)?;
|
|
558
611
|
ctx.emit(")");
|
|
@@ -779,12 +832,7 @@ impl SPyStmt<'_> {
|
|
|
779
832
|
ctx.emit("def ");
|
|
780
833
|
ctx.emit(&name);
|
|
781
834
|
ctx.emit("(");
|
|
782
|
-
|
|
783
|
-
if i > 0 {
|
|
784
|
-
ctx.emit(", ");
|
|
785
|
-
}
|
|
786
|
-
arg.emit_to(ctx)?;
|
|
787
|
-
}
|
|
835
|
+
args.emit_to(ctx)?;
|
|
788
836
|
ctx.emit("):");
|
|
789
837
|
ctx.emit_endl();
|
|
790
838
|
body.emit_to(ctx, 1)?;
|
|
@@ -180,6 +180,8 @@ impl<'src> ResolveState<'src> {
|
|
|
180
180
|
DeclType::Let,
|
|
181
181
|
);
|
|
182
182
|
|
|
183
|
+
self.declarations[decl].is_implicit_global = true;
|
|
184
|
+
|
|
183
185
|
self.scopes[self.root_scope].locals.push(decl.clone());
|
|
184
186
|
|
|
185
187
|
return Ok(decl);
|
|
@@ -329,16 +331,20 @@ impl<'src> ResolveState<'src> {
|
|
|
329
331
|
DeclType::Let | DeclType::Const => {
|
|
330
332
|
if class || global {
|
|
331
333
|
if let Some(found) = self.scope_stack.find_decl(self, &name) {
|
|
332
|
-
self.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
334
|
+
if !self.declarations[found.decl].is_implicit_global {
|
|
335
|
+
self.errors.extend(
|
|
336
|
+
TlErrBuilder::new()
|
|
337
|
+
.message(
|
|
338
|
+
"Cannot shadow declarations in a class or global scope",
|
|
339
|
+
)
|
|
340
|
+
.span(name.span)
|
|
341
|
+
.context(
|
|
342
|
+
"Previous declaration here",
|
|
343
|
+
self.declarations[found.decl].loc,
|
|
344
|
+
)
|
|
345
|
+
.build(),
|
|
346
|
+
);
|
|
347
|
+
}
|
|
342
348
|
}
|
|
343
349
|
}
|
|
344
350
|
}
|
|
@@ -469,6 +475,7 @@ pub struct Declaration<'src> {
|
|
|
469
475
|
pub loc: Span,
|
|
470
476
|
pub typ: Type,
|
|
471
477
|
|
|
478
|
+
pub is_implicit_global: bool,
|
|
472
479
|
pub is_fn_arg: bool,
|
|
473
480
|
pub is_exported: bool,
|
|
474
481
|
pub is_const: bool,
|
|
@@ -498,8 +505,9 @@ impl<'src> DeclSlotMapExt<'src> for SlotMap<DeclarationKey, Declaration<'src>> {
|
|
|
498
505
|
scope,
|
|
499
506
|
loc: name.span,
|
|
500
507
|
typ: Type::Unprocessed,
|
|
501
|
-
is_fn_arg: false,
|
|
502
508
|
|
|
509
|
+
is_implicit_global: false,
|
|
510
|
+
is_fn_arg: false,
|
|
503
511
|
is_const: matches!(modifier, DeclType::Const),
|
|
504
512
|
is_exported: matches!(modifier, DeclType::Export),
|
|
505
513
|
is_import: false,
|
|
@@ -1282,6 +1290,8 @@ impl<'src> SExprExt<'src> for Indirect<SExpr<'src>> {
|
|
|
1282
1290
|
|
|
1283
1291
|
ArgDefItem::KwargSpread(arg)
|
|
1284
1292
|
}
|
|
1293
|
+
ArgDefItem::PosOnlyMarker => ArgDefItem::PosOnlyMarker,
|
|
1294
|
+
ArgDefItem::KwOnlyMarker => ArgDefItem::KwOnlyMarker,
|
|
1285
1295
|
})
|
|
1286
1296
|
.collect::<Vec<_>>();
|
|
1287
1297
|
|
|
@@ -1675,7 +1685,7 @@ impl<'src> SStmtExt<'src> for Indirect<SStmt<'src>> {
|
|
|
1675
1685
|
.collect::<Vec<_>>()
|
|
1676
1686
|
.join(".");
|
|
1677
1687
|
|
|
1678
|
-
let full_module = ".".repeat(
|
|
1688
|
+
let full_module = ".".repeat(level) + &base_module;
|
|
1679
1689
|
|
|
1680
1690
|
match &tree.leaf.value {
|
|
1681
1691
|
ImportLeaf::Multi(branches) => {
|