First, kudos and compliments to Klaas-Jan Stol on the excellent PCT tutorial. I have some comments; the minor ones (typos, etc.) I'll send off-list, but others may merit some discussion and PCT implementation changes so I'll put them here.
This message has to do with scope handling of variables in Episode 6 of the tutorial (the 'identifier' method for Squaak). The tutorial points out an area where PCT doesn't yet work the way I had envisioned and solicits opinions on possible fixes. My intention for PCT is that an action method for a simple variable reference could look something like: method identifier($/) { my $name := ~$<ident>; make PAST::Var.new( :name($name), :viviself('Undef'), :node($/) ); } Note that in this idealized version the PAST::Var node doesn't need to carry an explicit :scope attribute, because we expect to retrieve the appropriate scope from an outer block's symbol table. This works just fine for languages like Perl 6 where all variables are declared before use, and therefore have entries in an outer block's symbol table. It doesn't quite work for other languages where undeclared variables are valid and have some assumed scope (such as 'global'). In these cases PCT throws an exception of "no 'scope' attribute found" and thus the compiler writer has to write code to search outer blocks for the symbol and default a scope if not present. In Squaak, undeclared variables are assumed to have package scope, thus it has: $scope := 'package'; for @?BLOCK { if $_.symbol($name) { $scope := 'lexical'; } } I think that PAST ought to be sophisticated enough to handle scoping for undeclared variables without requiring an action method to perform an explicit scope search as above. In other words, there should be something that says that any PAST::Var nodes that don't otherwise have a 'scope' value should default to 'package' scope. Approach #1: Default 'scope' to 'package' This is the approach that the original PAST-pm took -- any PAST::Var node that didn't provide a scope attribute was automatically assumed to be 'package' scope. This would likely solve the problem for most languages (including Squaak) where variables don't have to be predeclared before use. However, defaulting to 'package' feels a bit arbitrary (some languages might prefer a different default), which leads me to ... Approach #2: Define default scope values somewhere in the PAST tree. A slightly more flexible approach would be to allow the PAST tree itself to specify a default scope value for PAST::Var nodes. Overall I like this better (as it provides more flexibility), but I'm not sure where such a 'default' value should be held. It could be an explicit attribute of PAST::Block, or perhaps we should have a place in PAST::Block's symbol table for storing "default" values for things within the block. I somewhat like this latter approach. For example, the top-level block in a program could have $?BLOCK.symbol( '*', :scope('package'), :viviself('Undef') ); This would tell the PAST compiler that the default scope is 'package' and the default vivification is 'Undef'. Nested PAST::Var and PAST::Block nodes would then only need to have scope attributes for variables that differ from these default values. Of course, the above approach implies that '*' is not otherwise being used as a variable identifier -- perhaps using the null string to mean "default values" would be better: $?BLOCK.symbol( '', :scope('package'), :viviself('Undef') ); Comments, suggestions? Pm