Skip to content

Commit

Permalink
[translation] Rewrite code that returns variants conditionally
Browse files Browse the repository at this point in the history
Document the gotcha in mycpp/README.md
  • Loading branch information
Andy C committed Aug 28, 2023
1 parent 60fe7a4 commit 1863493
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 6 deletions.
34 changes: 32 additions & 2 deletions mycpp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ More work in this pass:

Note: I really wish we were not using visitors, but that's inherited from MyPy.

## Translation Notes
## WARNING: Assumptions Not Checked

### WARNING: Assumptions Not Checked
### Global Constants Can't Be Mutated

We translate top level constants to statically initialized C data structures
(zero startup cost):
Expand All @@ -122,6 +122,36 @@ We translate top level constants to statically initialized C data structures
Even though `List` and `Dict` are mutable in general, you should **NOT** mutate
these global instances! The C++ code will break at runtime.

### Gotcha about Returning Variants (Subclasses) of a type

MyPy will accept this code:

```
if cond:
sig = proc_sig.Open # type: proc_sig_t
# bad because mycpp HOISTS this
else:
sig = proc_sig.Closed.CreateNull()
sig.words = words # assignment fails
return sig
```

It will translate to C++, but fail to compile. Instead, rewrite it like this:

```
sig = None # type: proc_sig_t
if cond:
sig = proc_sig.Open # type: proc_sig_t
# bad because mycpp HOISTS this
else:
closed = proc_sig.Closed.CreateNull()
closed.words = words # assignment fails
sig = closed
return sig
```

## More Translation Notes

### "Creative Hacks"

- `with tagswitch(d) as case` → `switch / case`
Expand Down
12 changes: 8 additions & 4 deletions ysh/expr_to_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -1002,20 +1002,24 @@ def Proc(self, pnode):

#self.p_printer.Print(pnode)

sig = None # type: proc_sig_t

n = pnode.NumChildren()
if n == 1: # proc f {
sig = proc_sig.Open # type: proc_sig_t
sig = proc_sig.Open
elif n == 3: # proc f () {
sig = proc_sig.Closed.CreateNull(alloc_lists=True) # no params
else:
sig = proc_sig.Closed.CreateNull(alloc_lists=True) # no params
closed = proc_sig.Closed.CreateNull(alloc_lists=True) # no params

sig.words, sig.rest_words = self._FuncParams(pnode.GetChild(1))
closed.words, closed.rest_words = self._FuncParams(pnode.GetChild(1))
#sig.typed, sig.rest_typed = self._FuncParams(pnode.GetChild(2))
#sig.named, sig.rest_named = self._FuncParams(pnode.GetChild(3))

# TODO:
sig.block_param = None
closed.block_param = None

sig = closed

return sig

Expand Down

0 comments on commit 1863493

Please sign in to comment.