Open certik opened 2 years ago
There is one issue with pointers: they require special handling in serialization and in printing. Currently every symbol
is actually a pointer, and it is printed with the symbol table ID and a name; and serialized with the same approach. Deserialization requires special handling of this too.
So the stmt_ptr
would require special handling as well and does not seem worth it.
There are two ways out:
Label(identifier name)
with a unique string ID (for Fortran that uses integers, we can use a string representation of the integer). Then GoToTarget and GoTo would just reference this symbol.The second approach would look like this:
diff --git a/src/libasr/ASR.asdl b/src/libasr/ASR.asdl
index 2f120d29e..9817e9ad5 100644
--- a/src/libasr/ASR.asdl
+++ b/src/libasr/ASR.asdl
@@ -105,6 +105,7 @@ symbol
proc_name, symbol proc, abi abi)
| AssociateBlock(symbol_table symtab, identifier name, stmt* body)
| Block(symbol_table symtab, identifier name, stmt* body)
+ | GoToLabel(symbol_table parent_symtab, identifier name)
storage_type = Default | Save | Parameter | Allocatable
access = Public | Private
@@ -169,10 +170,10 @@ stmt
-- GoTo points to a GoToTarget with the corresponding target_id within
-- the same procedure. We currently use `int` IDs to link GoTo with
-- GoToTarget to avoid issues with serialization.
- | GoTo(int target_id)
+ | GoTo(symbol label)
-- An empty statement, a target of zero or more GoTo statements
-- the `id` is only unique within a procedure
- | GoToTarget(int id)
+ | GoToTarget(symbol label)
| If(expr test, stmt* body, stmt* orelse)
| IfArithmetic(expr test, int lt_label, int eq_label, int gt_label)
| Print(expr? fmt, expr* values, expr? separator, expr? end)
I think that should work, but it seems it might be more complicated than the first approach.
Here is how Wolfram does it: https://reference.wolfram.com/language/ref/Goto.html
It seems that all things considered, the simplest way seems to be this diff, applied to the current main:
diff --git a/src/libasr/ASR.asdl b/src/libasr/ASR.asdl
index a7721a7a7..eec1e8bac 100644
--- a/src/libasr/ASR.asdl
+++ b/src/libasr/ASR.asdl
@@ -173,10 +173,10 @@ stmt
-- GoTo points to a GoToTarget with the corresponding target_id within
-- the same procedure. We currently use `int` IDs to link GoTo with
-- GoToTarget to avoid issues with serialization.
- | GoTo(int target_id, identifier name)
+ | GoTo(identifier target_id)
-- An empty statement, a target of zero or more GoTo statements
-- the `id` is only unique within a procedure
- | GoToTarget(int id, identifier name)
+ | GoToTarget(identifier id)
| If(expr test, stmt* body, stmt* orelse)
| IfArithmetic(expr test, int lt_label, int eq_label, int gt_label)
| Print(expr? fmt, expr* values, expr? separator, expr? end)
And just use the string id
. Fortran would just convert the integer to a string. Python would use the string directly.
I'm rereading this old classic for ideas.
https://dspace.mit.edu/bitstream/handle/1721.1/5753/AIM-443.pdf?sequence=2&isAllowed=y
https://github.com/lcompilers/lpython/issues/1167#issuecomment-1264090265 makes sense to me and should be simple enough. Does LLVM allow using string IDs for labels? If so then using string IDs makes more sense.
@czgdp1807 had a great idea here how to improve GoTo / GoToTarget: https://github.com/lcompilers/lpython/pull/1163#issuecomment-1263052400
Change
GoTo(int target_id, identifier name)
toGoTo(stmt_t goto_target)
. Then one can doASR::down_cast<ASR::GoToTarget>(goto_object->goto_target)->m_name
. So it would look like this:Except that this would not work, as
GoTo
would contain a new (copy) ofGoToTarget
, not related to the actual target.The reason is that we can't represent links/pointers in ASDL. For the symbol table we implemented pointers implicitly: the ASDL->C++ translation script recognizes heuristically when the value is needed, and when a pointer is needed.
The way out of this could be to create an addition to ASDL, that when
_ptr
is appended after a type, it will be a pointer to this type, not the value.So the final change would look something like this: