[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[COMMITTED] pkl: gen: fix handling of type closures
From: |
Jose E. Marchesi |
Subject: |
[COMMITTED] pkl: gen: fix handling of type closures |
Date: |
Wed, 05 Jan 2022 15:15:01 +0100 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) |
This patch fixes a series of very annoying crashes that were related
to the fact some closures stored in AST nodes were missing a proper
environment when invoked.
2022-01-05 Jose E. Marchesi <jemarch@gnu.org>
* libpoke/pkl-gen.c (pkl_gen_pr_decl): Compile type closures
conditionally but install environment unconditionally.
(LMAP): Likewise.
(pkl_gen_pr_array): Likewise.
(pkl_gen_pr_struct): Likewise.
* testsuite/poke.map/maps-structs-19.pk: Likewise.
* testsuite/poke.map/nsmap-6.pk: Likewise.
* testsuite/poke.pkl/scons-65.pk: New test.
* testsuite/poke.pkl/scons-66.pk: Likewise.
* testsuite/poke.pkl/scons-67.pk: Likewise.
* testsuite/poke.map/write-structs-1.pk: Likewise.
* testsuite/Makefile.am (EXTRA_DIST): Add new tests.
---
ChangeLog | 15 ++
libpoke/pkl-gen.c | 473 ++++++++++++++--------------------
testsuite/Makefile.am | 6 +
testsuite/poke.map/maps-structs-19.pk | 12 +
testsuite/poke.map/nsmap-6.pk | 10 +
testsuite/poke.map/write-structs-1.pk | 10 +
testsuite/poke.pkl/scons-65.pk | 16 ++
testsuite/poke.pkl/scons-66.pk | 12 +
testsuite/poke.pkl/scons-67.pk | 12 +
9 files changed, 293 insertions(+), 273 deletions(-)
create mode 100644 testsuite/poke.map/maps-structs-19.pk
create mode 100644 testsuite/poke.map/nsmap-6.pk
create mode 100644 testsuite/poke.map/write-structs-1.pk
create mode 100644 testsuite/poke.pkl/scons-65.pk
create mode 100644 testsuite/poke.pkl/scons-66.pk
create mode 100644 testsuite/poke.pkl/scons-67.pk
diff --git a/ChangeLog b/ChangeLog
index 1e0f25c9..457d87b0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2022-01-05 Jose E. Marchesi <jemarch@gnu.org>
+
+ * libpoke/pkl-gen.c (pkl_gen_pr_decl): Compile type closures
+ conditionally but install environment unconditionally.
+ (LMAP): Likewise.
+ (pkl_gen_pr_array): Likewise.
+ (pkl_gen_pr_struct): Likewise.
+ * testsuite/poke.map/maps-structs-19.pk: Likewise.
+ * testsuite/poke.map/nsmap-6.pk: Likewise.
+ * testsuite/poke.pkl/scons-65.pk: New test.
+ * testsuite/poke.pkl/scons-66.pk: Likewise.
+ * testsuite/poke.pkl/scons-67.pk: Likewise.
+ * testsuite/poke.map/write-structs-1.pk: Likewise.
+ * testsuite/Makefile.am (EXTRA_DIST): Add new tests.
+
2022-01-04 David Faust <david.faust@oracle.com>
* testsuite/poke.pickles/btf-test.pk: New test.
diff --git a/libpoke/pkl-gen.c b/libpoke/pkl-gen.c
index 1c9e3aef..5d3c1a65 100644
--- a/libpoke/pkl-gen.c
+++ b/libpoke/pkl-gen.c
@@ -194,118 +194,118 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_decl)
{
case PKL_TYPE_STRUCT:
{
- pvm_val mapper_closure;
- pvm_val writer_closure;
- pvm_val constructor_closure;
- pvm_val comparator_closure;
- pvm_val integrator_closure;
- pvm_val deintegrator_closure;
-
pkl_ast_node type_struct = initial;
- /* Compile the struct closures, complete them using the
- current environment and install them in the AST node.
- But only if they haven't been compiled already. */
+ /* Compile the struct closures and complete them using the
+ current environment. */
if (PKL_AST_TYPE_S_WRITER (type_struct) == PVM_NULL)
{
+ pvm_val writer_closure;
+
PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_WRITER);
{
if (PKL_AST_TYPE_S_UNION_P (type_struct))
RAS_FUNCTION_UNION_WRITER (writer_closure, type_struct);
else
RAS_FUNCTION_STRUCT_WRITER (writer_closure, type_struct);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, writer_closure);
/* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
/* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP);
/* _ */
}
PKL_GEN_POP_CONTEXT;
-
PKL_AST_TYPE_S_WRITER (type_struct) = writer_closure;
}
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
+ PKL_AST_TYPE_S_WRITER (type_struct)); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); /* _ */
+
if (PKL_AST_TYPE_S_MAPPER (type_struct) == PVM_NULL)
{
+ pvm_val mapper_closure;
+
PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_MAPPER);
- {
- RAS_FUNCTION_STRUCT_MAPPER (mapper_closure, type_struct);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, mapper_closure);
/* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
/* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP);
/* _ */
- }
+ RAS_FUNCTION_STRUCT_MAPPER (mapper_closure, type_struct);
PKL_GEN_POP_CONTEXT;
-
PKL_AST_TYPE_S_MAPPER (type_struct) = mapper_closure;
}
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
+ PKL_AST_TYPE_S_MAPPER (type_struct)); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); /* _ */
+
if (PKL_AST_TYPE_S_CONSTRUCTOR (type_struct) == PVM_NULL)
{
+ pvm_val constructor_closure;
+
PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_CONSTRUCTOR);
- {
- RAS_FUNCTION_STRUCT_CONSTRUCTOR (constructor_closure,
- type_struct); /*
CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
constructor_closure); /* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
/* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP);
/* _ */
- }
+ RAS_FUNCTION_STRUCT_CONSTRUCTOR (constructor_closure,
+ type_struct);
PKL_GEN_POP_CONTEXT;
-
PKL_AST_TYPE_S_CONSTRUCTOR (type_struct) = constructor_closure;
}
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
+ PKL_AST_TYPE_S_CONSTRUCTOR (type_struct)); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); /* _ */
if (PKL_AST_TYPE_S_COMPARATOR (type_struct) == PVM_NULL)
{
+ pvm_val comparator_closure;
+
PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_COMPARATOR);
- {
- RAS_FUNCTION_STRUCT_COMPARATOR (comparator_closure,
- type_struct); /*
CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
comparator_closure); /* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
/* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP);
/* _ */
- }
+ RAS_FUNCTION_STRUCT_COMPARATOR (comparator_closure,
+ type_struct);
PKL_GEN_POP_CONTEXT;
-
PKL_AST_TYPE_S_COMPARATOR (type_struct) = comparator_closure;
}
- if (PKL_AST_TYPE_S_ITYPE (type_struct)
- && PKL_AST_TYPE_S_INTEGRATOR (type_struct) == PVM_NULL)
- {
- /* Yes, the in_writer context is also used for
- integrators, since integrators do not call writers
- nor the other way around. This eases sharing of
- code in the pks. */
- PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_WRITER);
- {
- RAS_FUNCTION_STRUCT_INTEGRATOR (integrator_closure,
- type_struct); /*
CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
integrator_closure); /* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
/* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP);
/* _ */
- }
- PKL_GEN_POP_CONTEXT;
-
- PKL_AST_TYPE_S_INTEGRATOR (type_struct) = integrator_closure;
- }
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
+ PKL_AST_TYPE_S_COMPARATOR (type_struct)); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); /* _ */
- if (PKL_AST_TYPE_S_ITYPE (type_struct)
- && PKL_AST_TYPE_S_DEINTEGRATOR (type_struct) == PVM_NULL)
+ if (PKL_AST_TYPE_S_ITYPE (type_struct))
{
- /* Yes, the in_writer context is also used for
- deintegrators, since deintegrators do not call
- writers nor the other way around. This eases
- sharing of code in the pks. */
- PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_WRITER);
- {
- RAS_FUNCTION_STRUCT_DEINTEGRATOR (deintegrator_closure,
- type_struct); /*
CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
deintegrator_closure); /* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
/* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP);
/* _ */
- }
- PKL_GEN_POP_CONTEXT;
+ if (PKL_AST_TYPE_S_INTEGRATOR (type_struct) == PVM_NULL)
+ {
+ pvm_val integrator_closure;
+
+ /* Yes, the in_writer context is also used for
+ integrators, since integrators do not call
+ writers nor the other way around. This eases
+ sharing of code in the pks. */
+ PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_WRITER);
+ RAS_FUNCTION_STRUCT_INTEGRATOR (integrator_closure,
+ type_struct);
+ PKL_GEN_POP_CONTEXT;
+ PKL_AST_TYPE_S_INTEGRATOR (type_struct) =
integrator_closure;
+ }
+
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
+ PKL_AST_TYPE_S_INTEGRATOR (type_struct)); /* CLS
*/
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* CLS
*/
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); /* _ */
+
+ if (PKL_AST_TYPE_S_DEINTEGRATOR (type_struct) == PVM_NULL)
+ {
+ pvm_val deintegrator_closure;
+
+ /* Yes, the in_writer context is also used for
+ deintegrators, since deintegrators do not call
+ writers nor the other way around. This eases
+ sharing of code in the pks. */
+ PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_WRITER);
+ RAS_FUNCTION_STRUCT_DEINTEGRATOR (deintegrator_closure,
+ type_struct);
+ PKL_GEN_POP_CONTEXT;
+ PKL_AST_TYPE_S_DEINTEGRATOR (type_struct) =
deintegrator_closure;
+ }
- PKL_AST_TYPE_S_DEINTEGRATOR (type_struct) =
deintegrator_closure;
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
+ PKL_AST_TYPE_S_DEINTEGRATOR (type_struct)); /*
CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /*
CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); /* _
*/
}
PKL_PASS_BREAK;
@@ -313,10 +313,6 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_decl)
}
case PKL_TYPE_ARRAY:
{
- pvm_val mapper_closure;
- pvm_val writer_closure;
- pvm_val constructor_closure;
-
pkl_ast_node array_type = initial;
/* Compile the arrays closures and complete them using the
@@ -337,49 +333,57 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_decl)
PKL_GEN_POP_CONTEXT;
}
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
+ PKL_AST_TYPE_A_BOUNDER (array_type)); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); /* _ */
+
if (PKL_AST_TYPE_A_WRITER (array_type) == PVM_NULL)
{
+ pvm_val writer_closure;
+
PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_WRITER);
- {
- RAS_FUNCTION_ARRAY_WRITER (writer_closure, array_type);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, writer_closure);
/* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
/* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP);
/* _ */
- }
+ RAS_FUNCTION_ARRAY_WRITER (writer_closure, array_type);
PKL_GEN_POP_CONTEXT;
-
PKL_AST_TYPE_A_WRITER (array_type) = writer_closure;
}
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
+ PKL_AST_TYPE_A_WRITER (array_type)); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); /* _ */
+
if (PKL_AST_TYPE_A_MAPPER (array_type) == PVM_NULL)
{
+ pvm_val mapper_closure;
+
PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_MAPPER);
- {
- RAS_FUNCTION_ARRAY_MAPPER (mapper_closure, array_type);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, mapper_closure);
/* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
/* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP);
/* _ */
- }
+ RAS_FUNCTION_ARRAY_MAPPER (mapper_closure, array_type);
PKL_GEN_POP_CONTEXT;
-
PKL_AST_TYPE_A_MAPPER (array_type) = mapper_closure;
}
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
+ PKL_AST_TYPE_A_MAPPER (array_type)); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); /* _ */
+
if (PKL_AST_TYPE_A_CONSTRUCTOR (array_type) == PVM_NULL)
{
+ pvm_val constructor_closure;
+
PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_CONSTRUCTOR);
- {
- RAS_FUNCTION_ARRAY_CONSTRUCTOR (constructor_closure,
- array_type); /*
CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
constructor_closure); /* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
/* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP);
/* _ */
- }
+ RAS_FUNCTION_ARRAY_CONSTRUCTOR (constructor_closure,
+ array_type);
PKL_GEN_POP_CONTEXT;
-
PKL_AST_TYPE_A_CONSTRUCTOR (array_type) = constructor_closure;
}
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
+ PKL_AST_TYPE_A_CONSTRUCTOR (array_type)); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); /* _ */
+
PKL_PASS_BREAK;
break;
}
@@ -813,30 +817,25 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_ass_stmt)
? PKL_AST_TYPE_A_WRITER ((TYPE)) \
: PKL_AST_TYPE_S_WRITER ((TYPE))); \
\
- /* Make sure the type has a writer. */ \
- /* Note how anonymous types from within structs */ \
- /* need the writer to be re-compiled. This sucks :/ */ \
- if (writer == PVM_NULL \
- || !PKL_AST_TYPE_NAME ((TYPE))) \
- { \
- PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_WRITER); \
+ /* If the type is anonymous it wont' have a compiled */ \
+ /* writer. */ \
+ if (!PKL_AST_TYPE_NAME ((TYPE))) \
{ \
- if (lvalue_type_code == PKL_TYPE_ARRAY) \
- RAS_FUNCTION_ARRAY_WRITER (writer, (TYPE)); \
- else if (PKL_AST_TYPE_S_UNION_P ((TYPE))) \
- RAS_FUNCTION_UNION_WRITER (writer, (TYPE)); \
- else \
- RAS_FUNCTION_STRUCT_WRITER (writer, (TYPE)); \
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, writer); /* CLS */ \
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* CLS */ \
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); /* _ */ \
- } \
- PKL_GEN_POP_CONTEXT; \
+ assert (writer == PVM_NULL); \
+ PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_WRITER); \
+ { \
+ if (lvalue_type_code == PKL_TYPE_ARRAY) \
+ RAS_FUNCTION_ARRAY_WRITER (writer, (TYPE)); \
+ else if (PKL_AST_TYPE_S_UNION_P ((TYPE))) \
+ RAS_FUNCTION_UNION_WRITER (writer, (TYPE)); \
+ else \
+ RAS_FUNCTION_STRUCT_WRITER (writer, (TYPE)); \
+ } \
+ PKL_GEN_POP_CONTEXT; \
\
- if (lvalue_type_code == PKL_TYPE_ARRAY) \
- PKL_AST_TYPE_A_WRITER ((TYPE)) = writer; \
- else \
- PKL_AST_TYPE_S_WRITER ((TYPE)) = writer; \
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, writer); \
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); \
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); \
} \
\
/* VAL IOS BOFF */ \
@@ -1013,7 +1012,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_ass_stmt)
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_NIP); /* VAL SCT ID STRICT_P */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_BZI, label1);
- /* Strict value: set with integriy. */
+ /* Strict value: set with integrity. */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP);
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_ROT);
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_SSETC, struct_type);
@@ -2480,14 +2479,11 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_array)
/* Install a writer in the array. */
PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_WRITER);
- {
- RAS_FUNCTION_ARRAY_WRITER (array_type_writer, array_type);
- PKL_AST_TYPE_A_WRITER (array_type) = array_type_writer;
- }
+ RAS_FUNCTION_ARRAY_WRITER (array_type_writer, array_type);
PKL_GEN_POP_CONTEXT;
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, array_type_writer); /* CLS */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_MSETW); /* ARR */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_MSETW); /* ARR */
}
PKL_PHASE_END_HANDLER
@@ -3074,31 +3070,17 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_array)
pkl_gen_pr_decl. */
bounder_created = 1;
+ assert (!PKL_AST_TYPE_NAME (array_type));
PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_ARRAY_BOUNDER);
PKL_PASS_SUBPASS (array_type);
PKL_GEN_POP_CONTEXT;
}
- if (array_type_mapper != PVM_NULL)
- {
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
- array_type_mapper); /* ... STRICT IOS OFF CLS */
- }
- else
- {
- /* Compile a mapper function and complete it using the
- current environment. */
- pvm_val mapper_closure;
-
- RAS_FUNCTION_ARRAY_MAPPER (mapper_closure, array_type);
-
- /* Complete the mapper closure with the current
- environment. */
- /* OFF */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, mapper_closure);
- /* ... STRICT IOS OFF
CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* ... STRICT IOS OFF
CLS */
- }
+ if (array_type_mapper == PVM_NULL)
+ RAS_FUNCTION_ARRAY_MAPPER (array_type_mapper, array_type);
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, array_type_mapper);
+ if (!PKL_AST_TYPE_NAME (array_type))
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* ... STRICT IOS OFF
CLS */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_TOR); /* ... STRICT IOS OFF
[CLS] */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_ATR); /* ... STRICT IOS OFF
CLS [CLS] */
@@ -3159,25 +3141,15 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_array)
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_SWAP); /* VAL STRICT */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_MSETS); /* VAL */
- if (array_type_writer != PVM_NULL)
- {
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
- array_type_writer); /* VAL CLS */
- }
- else
+ if (array_type_writer == PVM_NULL)
{
- pvm_val writer_closure;
-
- /* Compile a writer function to a closure. */
PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_WRITER);
- RAS_FUNCTION_ARRAY_WRITER (writer_closure, array_type);
+ RAS_FUNCTION_ARRAY_WRITER (array_type_writer, array_type);
PKL_GEN_POP_CONTEXT;
-
- /* Complete the writer closure with the current
- environment. */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, writer_closure); /* VAL
CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* VAL
CLS */
}
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, array_type_writer);
+ if (!PKL_AST_TYPE_NAME (array_type))
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* VAL CLS */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_MSETW); /* VAL */
/* Yay!, we are done ;) */
@@ -3199,14 +3171,10 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_array)
/* If the array type doesn't have a printer, compile one. */
if (printer_closure == PVM_NULL)
- {
- RAS_FUNCTION_ARRAY_PRINTER (printer_closure, array_type);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, printer_closure);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
- PKL_AST_TYPE_A_PRINTER (array_type) = printer_closure;
- }
- else
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, printer_closure);
+ RAS_FUNCTION_ARRAY_PRINTER (printer_closure, array_type);
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, printer_closure);
+ if (!PKL_AST_TYPE_NAME (array_type))
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
/* Invoke the printer. */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_CALL); /* _ */
@@ -3221,14 +3189,10 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_array)
/* If the array type doesn't have a formater, compile one. */
if (formater_closure == PVM_NULL)
- {
- RAS_FUNCTION_ARRAY_FORMATER (formater_closure, array_type);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, formater_closure);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
- PKL_AST_TYPE_A_FORMATER (array_type) = formater_closure;
- }
- else
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, formater_closure);
+ RAS_FUNCTION_ARRAY_FORMATER (formater_closure, array_type);
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, formater_closure);
+ if (!PKL_AST_TYPE_NAME (array_type))
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
/* Invoke the formater. */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_CALL); /* _ */
@@ -3240,7 +3204,6 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_array)
pkl_ast_node array_type = PKL_PASS_NODE;
pkl_ast_node array_type_bound = PKL_AST_TYPE_A_BOUND (array_type);
pvm_val array_type_constructor = PKL_AST_TYPE_A_CONSTRUCTOR (array_type);
- pvm_val array_type_writer = PKL_AST_TYPE_A_WRITER (array_type);
int bounder_created = 0;
PKL_GEN_PAYLOAD->constructor_depth++;
@@ -3256,6 +3219,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_array)
Named array types have their bounder compiled in
pkl_gen_pr_decl. */
bounder_created = 1;
+ assert (!PKL_AST_TYPE_NAME (array_type));
PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_ARRAY_BOUNDER);
PKL_PASS_SUBPASS (array_type);
PKL_GEN_POP_CONTEXT;
@@ -3292,39 +3256,13 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_array)
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, PVM_NULL);
/* Make sure the array type has a constructor, and call it. */
- if (array_type_constructor != PVM_NULL)
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
- array_type_constructor); /* EBOUND SBOUND CLS */
- else
- {
- RAS_FUNCTION_ARRAY_CONSTRUCTOR (array_type_constructor, array_type);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, array_type_constructor);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
- }
+ if (array_type_constructor == PVM_NULL)
+ RAS_FUNCTION_ARRAY_CONSTRUCTOR (array_type_constructor, array_type);
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, array_type_constructor);
+ if (!PKL_AST_TYPE_NAME (array_type))
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_CALL); /* ARR */
-
- /* Install a writer in the constructed array. This is needed
- when the value is used as the right-hand-side to a
- map-assignment operation. */
- if (array_type_writer == PVM_NULL)
- {
- PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_WRITER);
- {
- RAS_FUNCTION_ARRAY_WRITER (array_type_writer, array_type);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, array_type_writer); /*
CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /*
CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); /* _
*/
- }
- PKL_GEN_POP_CONTEXT;
-
- PKL_AST_TYPE_A_WRITER (array_type) = array_type_writer;
- }
-
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
- array_type_writer); /* ARR CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_MSETW); /* ARR */
-
PKL_GEN_PAYLOAD->constructor_depth--;
if (bounder_created)
@@ -3423,6 +3361,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_struct)
pvm_val type_struct_mapper = PKL_AST_TYPE_S_MAPPER (type_struct);
pvm_val type_struct_writer = PKL_AST_TYPE_S_WRITER (type_struct);
+ pvm_val type_struct_constructor = PKL_AST_TYPE_S_CONSTRUCTOR
(type_struct);
/* Make a copy of the IOS and STRICT. We will need to install
them in the resulting value later. */
@@ -3432,21 +3371,13 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_struct)
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_OVER);
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_FROMR); /* STRICT IOS STRICT IOS OFF
*/
- if (type_struct_mapper != PVM_NULL)
- {
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
- type_struct_mapper);
- }
- else
- {
- /* Compile a mapper function and complete it using the
- current environment. */
- pvm_val mapper_closure;
-
- RAS_FUNCTION_STRUCT_MAPPER (mapper_closure, type_struct);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, mapper_closure);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
- } /* ... STRICT IOS OFF CLS */
+ /* Compile a mapper function and complete it using the current
+ environment. */
+ if (type_struct_mapper == PVM_NULL)
+ RAS_FUNCTION_STRUCT_MAPPER (type_struct_mapper, type_struct);
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, type_struct_mapper);
+ if (!PKL_AST_TYPE_NAME (type_struct))
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* ... STRICT IOS OFF CLS */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_TOR); /* ... STRICT IOS OFF [CLS]
*/
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_ATR); /* ... STRICT IOS OFF CLS
[CLS] */
@@ -3481,27 +3412,41 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_struct)
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_SWAP); /* VAL STRICT */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_MSETS); /* VAL */
- if (type_struct_writer != PVM_NULL)
+ /* Compile a constructor function and complete it using the
+ current environment. */
+ if (type_struct_constructor == PVM_NULL)
{
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
- type_struct_writer); /* VAL CLS */
+ assert (!PKL_AST_TYPE_NAME (type_struct));
+ PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_CONSTRUCTOR);
+ RAS_FUNCTION_STRUCT_CONSTRUCTOR (type_struct_constructor,
type_struct);
+ PKL_GEN_POP_CONTEXT;
+ /* We normally do not install closures in anonymous types,
+ but this one is needed by ssetc. */
+ PKL_AST_TYPE_S_CONSTRUCTOR (type_struct) = type_struct_constructor;
}
- else
+ if (!PKL_AST_TYPE_NAME (type_struct))
{
- /* Compile a writer function and complete it using the
- current environment. */
- pvm_val writer_closure;
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, type_struct_constructor);
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP);
+ }
+ /* Compile a writer function and complete it using the current
+ environment. */
+ if (type_struct_writer == PVM_NULL)
+ {
+ assert (!PKL_AST_TYPE_NAME (type_struct));
PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_WRITER);
if (PKL_AST_TYPE_S_UNION_P (type_struct))
- RAS_FUNCTION_UNION_WRITER (writer_closure, type_struct);
+ RAS_FUNCTION_UNION_WRITER (type_struct_writer, type_struct);
else
- RAS_FUNCTION_STRUCT_WRITER (writer_closure, type_struct);
+ RAS_FUNCTION_STRUCT_WRITER (type_struct_writer, type_struct);
PKL_GEN_POP_CONTEXT;
+ }
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, writer_closure); /* VAL
CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, type_struct_writer); /* VAL
CLS */
+ if (!PKL_AST_TYPE_NAME (type_struct))
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* VAL
CLS */
- }
/* Install the writer into the value. */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_MSETW); /* VAL */
@@ -3535,53 +3480,40 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_struct)
s = ASTREF(s); pkl_ast_node_free (s);
}
- if (type_struct_constructor != PVM_NULL)
+ if (type_struct_constructor == PVM_NULL)
{
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
- type_struct_constructor); /* SCT CLS */
- }
- else
- {
- /* Compile a constructor function and complete it using the
- current environment. */
- pvm_val constructor_closure;
-
- RAS_FUNCTION_STRUCT_CONSTRUCTOR (constructor_closure, type_struct);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, constructor_closure);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* SCT CLS */
-
- /* Since this is an anonymous struct, install the
- constructor in it. This is needed by other operations
- like sseti. */
- PKL_AST_TYPE_S_CONSTRUCTOR (type_struct) = constructor_closure;
+ RAS_FUNCTION_STRUCT_CONSTRUCTOR (type_struct_constructor,
type_struct);
+ /* We normally do not install closures in anonymous types,
+ but this one is needed by ssetc. */
+ PKL_AST_TYPE_S_CONSTRUCTOR (type_struct) = type_struct_constructor;
}
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, type_struct_constructor);
+ if (!PKL_AST_TYPE_NAME (type_struct))
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* SCT CLS */
/* Call the constructor to get a new struct. */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_CALL); /* NSCT */
- /* Install a writer in the constructed struct. This is needed
- when the value is used as the right-hand-side to a
- map-assignment operation. */
+ /* Compile a writer function and complete it using the current
+ environment. */
if (type_struct_writer == PVM_NULL)
{
- /* The struct type is anonymous and doesn't have a writer.
- Compile one in this environment. */
-
+ assert (!PKL_AST_TYPE_NAME (type_struct));
PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_WRITER);
{
if (PKL_AST_TYPE_S_UNION_P (type_struct))
RAS_FUNCTION_UNION_WRITER (type_struct_writer, type_struct);
else
RAS_FUNCTION_STRUCT_WRITER (type_struct_writer, type_struct);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, type_struct_writer); /*
CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /*
CLS */
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); /*
_ */
}
PKL_GEN_POP_CONTEXT;
}
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
- type_struct_writer); /* NCSCT CLS */
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, type_struct_writer);
+ if (!PKL_AST_TYPE_NAME (type_struct))
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC); /* NCSCT CLS */
+
+ /* Install the writer into the value. */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_MSETW); /* NCSCT */
/* And we are done. */
@@ -3599,15 +3531,10 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_struct)
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_OVER);
if (comparator_closure == PVM_NULL)
- {
- /* Compile a comparator function and complete it using the
- current environment. */
- RAS_FUNCTION_STRUCT_COMPARATOR (comparator_closure, type_struct);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, comparator_closure);
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
- }
- else
- pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, comparator_closure);
+ RAS_FUNCTION_STRUCT_COMPARATOR (comparator_closure, type_struct);
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, comparator_closure);
+ if (!PKL_AST_TYPE_NAME (type_struct))
+ pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
/* Call the comparator. */
pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_CALL); /* SCT1 SCT2 INT */
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 049f483d..1fd5f419 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -313,6 +313,7 @@ EXTRA_DIST = \
poke.map/maps-structs-16.pk \
poke.map/maps-structs-17.pk \
poke.map/maps-structs-18.pk \
+ poke.map/maps-structs-19.pk \
poke.map/maps-structs-anonfield-1.pk \
poke.map/maps-structs-anonfield-2.pk \
poke.map/maps-structs-anonfield-3.pk \
@@ -504,6 +505,7 @@ EXTRA_DIST = \
poke.map/nsmap-3.pk \
poke.map/nsmap-4.pk \
poke.map/nsmap-5.pk \
+ poke.map/nsmap-6.pk \
poke.map/strict-attr-1.pk \
poke.map/strict-attr-2.pk \
poke.map/strict-attr-3.pk \
@@ -528,6 +530,7 @@ EXTRA_DIST = \
poke.map/write-unions-1.pk \
poke.map/write-unions-2.pk \
poke.map/write-unions-3.pk \
+ poke.map/write-structs-1.pk \
poke.pickles/pickles.exp \
poke.pickles/argp-test.pk \
poke.pickles/color-test.pk \
@@ -1717,6 +1720,9 @@ EXTRA_DIST = \
poke.pkl/scons-62.pk \
poke.pkl/scons-63.pk \
poke.pkl/scons-64.pk \
+ poke.pkl/scons-65.pk \
+ poke.pkl/scons-66.pk \
+ poke.pkl/scons-67.pk \
poke.pkl/scons-anon-field-1.pk \
poke.pkl/scons-anon-field-2.pk \
poke.pkl/scons-anon-field-3.pk \
diff --git a/testsuite/poke.map/maps-structs-19.pk
b/testsuite/poke.map/maps-structs-19.pk
new file mode 100644
index 00000000..bf84d2c8
--- /dev/null
+++ b/testsuite/poke.map/maps-structs-19.pk
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-data {c*} {0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x90 0xa0 0xb0
0xc0} } */
+
+type Foo =
+ struct
+ {
+ type Record = struct { };
+ Record rec;
+ };
+
+/* { dg-command {Foo @ 2#B} } */
+/* { dg-output "Foo \{rec=Record \{\}\}" } */
diff --git a/testsuite/poke.map/nsmap-6.pk b/testsuite/poke.map/nsmap-6.pk
new file mode 100644
index 00000000..aacf1a32
--- /dev/null
+++ b/testsuite/poke.map/nsmap-6.pk
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-data {c*} {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00} } */
+
+type S = struct { struct { uint<8> x; } b; };
+
+/* { dg-command { .set obase 16 } } */
+/* { dg-command { var s = S @! 1#B } } */
+/* { dg-command { s.b.x = 3 } } */
+/* { dg-command { byte @ 1#B } } */
+/* { dg-output "0x3UB" } */
diff --git a/testsuite/poke.map/write-structs-1.pk
b/testsuite/poke.map/write-structs-1.pk
new file mode 100644
index 00000000..99eeb4f0
--- /dev/null
+++ b/testsuite/poke.map/write-structs-1.pk
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-data {c*} {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00} } */
+
+type S = struct { struct { uint<8> x; } b; };
+
+/* { dg-command { .set obase 16 } } */
+/* { dg-command { var s = S @ 1#B } } */
+/* { dg-command { s.b.x = 3 } } */
+/* { dg-command { byte @ 1#B } } */
+/* { dg-output "0x3UB" } */
diff --git a/testsuite/poke.pkl/scons-65.pk b/testsuite/poke.pkl/scons-65.pk
new file mode 100644
index 00000000..7d230ee2
--- /dev/null
+++ b/testsuite/poke.pkl/scons-65.pk
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+
+type Foo =
+ struct
+ {
+ offset<uint<32>, B> rec_size;
+ uint<32> num_recs;
+
+ type Record = struct { uint<8> a; };
+
+ Record [rec_size * num_recs] recs;
+ };
+
+/* { dg-command {.set obase 16} } */
+/* { dg-command {Foo { rec_size = 1#B, num_recs = 1 } } } */
+/* { dg-output "Foo \{rec_size=0x1U#B,num_recs=0x1U,recs=\\\[Record
\{a=0x0UB\}\\\]\}" } */
diff --git a/testsuite/poke.pkl/scons-66.pk b/testsuite/poke.pkl/scons-66.pk
new file mode 100644
index 00000000..d1b89740
--- /dev/null
+++ b/testsuite/poke.pkl/scons-66.pk
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+
+type Foo =
+ struct
+ {
+ byte[2] d;
+ byte c : c == d[0] + d[1];
+ };
+
+/* { dg-command {var f = Foo {}} } */
+/* { dg-command {try f.d = [2UB,3UB]; catch if E_constraint { printf
"caught\n"; } } } */
+/* { dg-output "caught" } */
diff --git a/testsuite/poke.pkl/scons-67.pk b/testsuite/poke.pkl/scons-67.pk
new file mode 100644
index 00000000..8a20c089
--- /dev/null
+++ b/testsuite/poke.pkl/scons-67.pk
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+
+type S =
+ struct
+ {
+ int nbytes;
+ type Array = byte[nbytes];
+ Array bytes;
+ };
+
+/* { dg-command {S { nbytes = 2}} } */
+/* { dg-output "S \{nbytes=2,bytes=\\\[0UB,0UB\\\]\}" } */
--
2.11.0
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [COMMITTED] pkl: gen: fix handling of type closures,
Jose E. Marchesi <=