From: Kevin K. <kev...@gm...> - 2017-11-11 16:52:56
|
Donal, I see you're running ahead of me again (which is fine, I'm slow). You added a bunch of new quadcode instructions for implementing the ARRAY_STK bytecodes: directArrayAppend directArrayExists directArrayGet directArrayLappend directArrayLappendList directArraySet directArrayUnset (I think that's the correct set; am I right?) You added the correct result type to types.tcl - that's good. You appear to have missed a few places that have to be adapted to the new codes: callframe.tcl (callFrameMovesAfter): Operations that return FAIL have to be called out here. Ignore the 'default' case - the mention of 'directSet' and friends there is erroneous. (Moreover, I've found a bug there, I think. Will fix,) constfold.tcl {constfold): We know that all the direct variable access operations cannot be subject to constant folding. That's the default behaviour, but there's a noisy warning message that will be silenced by enumerating the instructions here. deadcode.tcl (unkillable): Operations with side effects such as modifying nonlocal variables cannot be removed even if their results are unused, and have to be enumerated here. upvar.tcl (upvarProcEffect): Operations that access nonlocal variables have to be enumerated here. They have to set the 'readsGlobal' and/or 'writesGlobal' attributes of the result as appropriate; the result is no longer 'pure', and if the operation makes the proc have side effects, the result is no longer 'killable'. I'll go in and fix these - they're all easy, except for the bug I spotted in callframe.tcl - but I'd have appreciated a note to the mailing list about what's going on! Moving forward with array accesses - What you're doing is kind of a half-fix. I don't think we're painting ourselves into a corner with it, exactly, quite, but we do need to think about it moving forward, given the number of things we've already implemented with the replacement of arrays with dicts. What concerns me here is the other end of code generation, where someone says 'gets stdin line($lineno)'. That's not going to get fixed with a simple rule that says 'direct accesses are actual arrays, other accesses are dicts.' The good news is that I already have the logic at least to identify that the 'gets' will be accessing an unknown var in the callframe. (I have more information than that, that I'm not using, because of course the variable name is the result of 'strcat' that could be deconstructed to determine that it *is* an array and the array name is constant. But that's a bridge too far initially.) I'm wondering if The Right Thing is to say that arrays may be demoted to dicts if (a) they are callframe-local, (b) there's nothing about, anywhere in the proc, that causes unknown callframe vars (or specifically those named vars) to be modified. We'd have translate.tcl generate the array operations always initially, and then a compiler pass (to be designed) could do the rewrite to use dict operations when it's known to be safe to do so. The safety analysis winds up spilling over into interprocedural analysis as well. I've not put a lot of thought into it yet, but in the common case where procedure A calls procedure B, passing the name of a local variable that is an array, we want to be able to generated a version of B that will accept "array as dict" if possible, and have A call that. This would be done with the usual chaotic iteration in the specializer: initially, every proc would accept any of its args with 'array as dict' unless there's a local reason not to do so, and then procs would retract their 'array as dict' contract if they are detected to call anything that precludes it. Retraction of that contract implies that their callers will have to be checked and issue their own retractions if necessary. This is all good - it's how type analysis works, how we track that calling a procedure might affect nonlocal variables or scribble in the callframe, and so on. The whole stack of additional analysis makes the project kind of nasty. We've put this off too long and piled too much other stuff on top of the existing logic. But that's the way of "do the simplest thing that could possibly work." |