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.
Files changed (147) hide show
  1. {koatl-0.3.9 → koatl-0.3.11}/Cargo.lock +2 -2
  2. {koatl-0.3.9 → koatl-0.3.11}/PKG-INFO +1 -1
  3. {koatl-0.3.9 → koatl-0.3.11}/koatl/Cargo.toml +1 -1
  4. {koatl-0.3.9 → koatl-0.3.11}/koatl/src/emit_py.rs +47 -23
  5. koatl-0.3.11/koatl/tests/e2e/base/arguments.tl +41 -0
  6. koatl-0.3.11/koatl/tests/fail-parse/arguments_mixed_defaults.tl +1 -0
  7. koatl-0.3.11/koatl/tests/fail-parse/arguments_multiple_kwargs.tl +1 -0
  8. koatl-0.3.11/koatl/tests/fail-parse/arguments_multiple_kwonly_markers.tl +1 -0
  9. koatl-0.3.11/koatl/tests/fail-parse/arguments_multiple_posonly_markers.tl +1 -0
  10. koatl-0.3.11/koatl/tests/fail-parse/arguments_multiple_varargs.tl +1 -0
  11. koatl-0.3.11/koatl/tests/fail-parse/arguments_posonly_after_kwonly.tl +1 -0
  12. koatl-0.3.11/koatl/tests/fail-parse/arguments_vararg_and_kwonly_marker.tl +1 -0
  13. koatl-0.3.11/koatl/tests/parse/mutual-recursion.tl +2 -0
  14. koatl-0.3.11/koatl/tests/test_parse_fail.py +26 -0
  15. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/ast.rs +2 -0
  16. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/lift_cst.rs +2 -0
  17. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/py/ast.rs +35 -6
  18. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/py/ast_builder.rs +2 -23
  19. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/py/emit.rs +75 -27
  20. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/resolve_scopes.rs +22 -12
  21. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/transform.rs +157 -24
  22. {koatl-0.3.9 → koatl-0.3.11}/koatl-parser/src/cst.rs +6 -0
  23. {koatl-0.3.9 → koatl-0.3.11}/koatl-parser/src/parser.rs +8 -0
  24. {koatl-0.3.9 → koatl-0.3.11}/koatl-parser/src/simple_fmt.rs +2 -0
  25. {koatl-0.3.9 → koatl-0.3.11}/Cargo.toml +0 -0
  26. {koatl-0.3.9 → koatl-0.3.11}/README.md +0 -0
  27. {koatl-0.3.9 → koatl-0.3.11}/koatl/.github/workflows/CI.yml +0 -0
  28. {koatl-0.3.9 → koatl-0.3.11}/koatl/.gitignore +0 -0
  29. {koatl-0.3.9 → koatl-0.3.11}/koatl/LICENSE +0 -0
  30. {koatl-0.3.9 → koatl-0.3.11}/koatl/README.md +0 -0
  31. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/__init__.py +0 -0
  32. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/__main__.py +0 -0
  33. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/cli.py +0 -0
  34. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/notebook/__init__.py +0 -0
  35. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/notebook/magic.py +0 -0
  36. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/prelude/__init__.tl +0 -0
  37. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/runtime/__init__.py +0 -0
  38. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/runtime/meta_finder.py +0 -0
  39. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/runtime/record.py +0 -0
  40. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/runtime/vattr.py +0 -0
  41. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/__init__.tl +0 -0
  42. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/control/__init__.tl +0 -0
  43. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/control/async.tl +0 -0
  44. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/control/base.tl +0 -0
  45. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/control/do.tl +0 -0
  46. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/control/env.tl +0 -0
  47. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/control/memo.tl +0 -0
  48. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/control/result.tl +0 -0
  49. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/data/__init__.tl +0 -0
  50. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/data/list.tl +0 -0
  51. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/data/record.tl +0 -0
  52. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/ext.tl +0 -0
  53. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/io.tl +0 -0
  54. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/iter.tl +0 -0
  55. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/json.tl +0 -0
  56. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/lazy_module.tl +0 -0
  57. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/pickle.tl +0 -0
  58. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/re.tl +0 -0
  59. {koatl-0.3.9 → koatl-0.3.11}/koatl/python/koatl/std/trait.py +0 -0
  60. {koatl-0.3.9 → koatl-0.3.11}/koatl/requirements.txt +0 -0
  61. {koatl-0.3.9 → koatl-0.3.11}/koatl/src/lib.rs +0 -0
  62. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/containers.tl +0 -0
  63. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/data.txt +0 -0
  64. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/decorators.tl +0 -0
  65. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
  66. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/destructure.tl +0 -0
  67. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/escape_ident.tl +0 -0
  68. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/fstr.tl +0 -0
  69. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/functions.tl +0 -0
  70. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/generator.tl +0 -0
  71. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/if_expr.tl +0 -0
  72. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/loops.tl +0 -0
  73. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/match.tl +0 -0
  74. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/nary-list.tl +0 -0
  75. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/placeholder.tl +0 -0
  76. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/precedence.tl +0 -0
  77. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/scopes.tl +0 -0
  78. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/semantic_whitespace.tl +0 -0
  79. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/short_circuit.tl +0 -0
  80. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/base/with.tl +0 -0
  81. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/async.tl +0 -0
  82. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/aug_assign.tl +0 -0
  83. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/coal.tl +0 -0
  84. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/env.tl +0 -0
  85. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/imports.tl +0 -0
  86. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/iterables.tl +0 -0
  87. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/list.tl +0 -0
  88. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/memo.tl +0 -0
  89. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/record.tl +0 -0
  90. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/result.tl +0 -0
  91. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/slice.tl +0 -0
  92. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/try.tl +0 -0
  93. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/prelude/virtual.tl +0 -0
  94. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/util/__init__.py +0 -0
  95. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/util/module0.tl +0 -0
  96. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/util/module1.tl +0 -0
  97. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/e2e/util/module2.tl +0 -0
  98. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/parse/arith.tl +0 -0
  99. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/parse/assign.tl +0 -0
  100. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/parse/block-comments.tl +0 -0
  101. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/parse/deco.tl +0 -0
  102. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/parse/func.tl +0 -0
  103. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/parse/matches.tl +0 -0
  104. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/parse/numbers.tl +0 -0
  105. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/test_e2e.py +0 -0
  106. {koatl-0.3.9 → koatl-0.3.11}/koatl/tests/test_parse.py +0 -0
  107. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/Cargo.toml +0 -0
  108. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/ast_builder.rs +0 -0
  109. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/inference.rs +0 -0
  110. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/lib.rs +0 -0
  111. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/main.rs +0 -0
  112. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/py/mod.rs +0 -0
  113. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/types.rs +0 -0
  114. {koatl-0.3.9 → koatl-0.3.11}/koatl-core/src/util.rs +0 -0
  115. {koatl-0.3.9 → koatl-0.3.11}/koatl-parser/Cargo.toml +0 -0
  116. {koatl-0.3.9 → koatl-0.3.11}/koatl-parser/src/lexer.rs +0 -0
  117. {koatl-0.3.9 → koatl-0.3.11}/koatl-parser/src/lib.rs +0 -0
  118. {koatl-0.3.9 → koatl-0.3.11}/pyproject.toml +0 -0
  119. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/__init__.py +0 -0
  120. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/__main__.py +0 -0
  121. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/cli.py +0 -0
  122. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/notebook/__init__.py +0 -0
  123. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/notebook/magic.py +0 -0
  124. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/prelude/__init__.tl +0 -0
  125. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/runtime/__init__.py +0 -0
  126. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/runtime/meta_finder.py +0 -0
  127. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/runtime/record.py +0 -0
  128. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/runtime/vattr.py +0 -0
  129. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/__init__.tl +0 -0
  130. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/control/__init__.tl +0 -0
  131. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/control/async.tl +0 -0
  132. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/control/base.tl +0 -0
  133. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/control/do.tl +0 -0
  134. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/control/env.tl +0 -0
  135. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/control/memo.tl +0 -0
  136. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/control/result.tl +0 -0
  137. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/data/__init__.tl +0 -0
  138. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/data/list.tl +0 -0
  139. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/data/record.tl +0 -0
  140. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/ext.tl +0 -0
  141. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/io.tl +0 -0
  142. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/iter.tl +0 -0
  143. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/json.tl +0 -0
  144. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/lazy_module.tl +0 -0
  145. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/pickle.tl +0 -0
  146. {koatl-0.3.9 → koatl-0.3.11}/python/koatl/std/re.tl +0 -0
  147. {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.9"
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.0"
251
+ version = "0.1.1"
252
252
  dependencies = [
253
253
  "anyhow",
254
254
  "clap",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: koatl
3
- Version: 0.3.9
3
+ Version: 0.3.11
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "koatl"
3
- version = "0.3.9"
3
+ version = "0.3.11"
4
4
  edition = "2021"
5
5
 
6
6
  [lib]
@@ -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 Vec<PyArgDefItem<'src>> {
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
- for arg in self {
121
- match arg {
122
- PyArgDefItem::Arg(arg_name, default) => {
123
- let arg_ast = ctx.ast_cls("arg", (arg_name.as_ref(), ctx.py.None()))?;
124
- py_args.push(arg_ast);
125
- if let Some(default_expr) = default {
126
- py_defaults.push(default_expr.emit_py(ctx)?);
127
- }
128
- }
129
- PyArgDefItem::ArgSpread(arg_name) => {
130
- vararg = Some(ctx.ast_cls("arg", (arg_name.as_ref(), ctx.py.None()))?);
131
- }
132
- PyArgDefItem::KwargSpread(arg_name) => {
133
- kwarg = Some(ctx.ast_cls("arg", (arg_name.as_ref(), ctx.py.None()))?);
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
- Vec::<PyObject>::new(), // posonlyargs
142
- py_args, // args
143
- vararg, // vararg
144
- Vec::<PyObject>::new(), // kwonlyargs
145
- Vec::<PyObject>::new(), // kw_defaults
146
- kwarg, // kwarg
147
- py_defaults, // 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,2 @@
1
+ let a = () => b()
2
+ let b = () => a()
@@ -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.")
@@ -138,6 +138,8 @@ pub enum ArgDefItem<'a, TTree: Tree> {
138
138
  Arg(TTree::Pattern, Option<TTree::Expr>),
139
139
  ArgSpread(SIdent<'a>),
140
140
  KwargSpread(SIdent<'a>),
141
+ PosOnlyMarker,
142
+ KwOnlyMarker,
141
143
  }
142
144
 
143
145
  #[derive(Debug, Clone)]
@@ -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: Vec<PyArgDefItem<'a>>,
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 enum PyArgDefItem<'a> {
192
- Arg(PyToken<'a>, Option<SPyExpr<'a>>),
193
- ArgSpread(PyToken<'a>),
194
- KwargSpread(PyToken<'a>),
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(Vec<PyArgDefItem<'a>>, Box<SPyExpr<'a>>),
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: Vec<PyArgDefItem<'src>>,
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 PyArgDefItem<'_> {
108
+ impl PyArgList<'_> {
109
109
  fn emit_to(&mut self, ctx: &mut EmitCtx) -> TlResult<()> {
110
- match self {
111
- PyArgDefItem::Arg(name, default) => {
112
- if let Some(default) = default {
113
- ctx.emit(name);
114
- ctx.emit("=");
115
- default.emit_to(ctx, LOW_PREC)?;
116
- } else {
117
- ctx.emit(name);
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
- PyArgDefItem::ArgSpread(name) => {
121
- ctx.emit(&format!("*{}", name));
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
- PyArgDefItem::KwargSpread(name) => {
124
- ctx.emit(&format!("**{}", name));
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
- ctx.emit("");
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
- for (i, arg) in args.iter_mut().enumerate() {
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.errors.extend(
333
- TlErrBuilder::new()
334
- .message("Cannot shadow declarations in a class or global scope")
335
- .span(name.span)
336
- .context(
337
- "Previous declaration here",
338
- self.declarations[found.decl].loc,
339
- )
340
- .build(),
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(tree.level) + &base_module;
1688
+ let full_module = ".".repeat(level) + &base_module;
1679
1689
 
1680
1690
  match &tree.leaf.value {
1681
1691
  ImportLeaf::Multi(branches) => {