Hi Dave,
thanks for your response
On Wed, 18 Oct 2023 at 12:04, Dave Mitchell <davem@iabyn.com> wrote:
> On Thu, Oct 12, 2023 at 03:50:53PM +0200, Branislav Zahradník wrote:
> > On Thu, 12 Oct 2023 at 14:07, Dave Mitchell <davem@iabyn.com> wrote:
> > >
> > > I still don't really understand.
> > >
> > > Perl's existing namespaces are intimately tied to the lexer and parser,
> > > and their current state. For example, when the compiler sees '$foo', it
> > > searches through the chain of pads currently in scope for a '$foo'
> entry;
> > > if none are found, it searches for a 'foo' entry in the current stash,
> > > then looks for a scalar entry in that typeglob.
> > >
> >
> > > How would these new namespaces be used? What syntax and mechanisms
> would
> > > be in place to make use of these new namespaces?
> > >
> >
> > One question is missing: how to import/export these new symbols ?
> >
> > Very short answer:
> >
> > - typeglob will be changed to contain (dynamic) array for symbols in
> > particular symbol space
> > eg (demonstration of approach):
> > #define GvCV(gv) ((CV*)GvGP(gv)->gp_cv)
> > will be changed to:
> > #define GvCV(gv) ((CV*)GvGP(gv)->gp_symbols[SYMBOL_SPACE_CV])
> >
> > - pad - that I don't know yet, that's open question
> >
> > - lexer
> > - every usage of external symbol space is prefixed by distinct token
> > - new statement: declare
> > - new expression: declared
> > - new prototype similar to &;@ ... $<Symbol::Space::Identifier>
> > - symbol space behaviour will be attached to context via attributes
> > - symbol spaces provide their own pluggable grammar to parse their
> > declaration
> >
> > Mental model:
> > sigils in perl already behaves like symbol space switch, for example:
> > $foo = new value;
> > can be treated as
> > declared scalar foo = new value;
> > More at
> >
> https://github.com/happy-barney/perl-wish-list/tree/master/independent-symbol-spaces
>
> Ok, I've your email above, I've looked at that web page, and I still
> don't understand.
>
> First, I'm going to make a very general point here.
>
> From time to time you post on p5p about a proposal or whatever, and I
> rarely have any idea what you mean. This may be because I don't
> understand the subject area, or because you're not clear at explaining
> things, or maybe a combination of the two. But for whatever reason, the
> net affect is that such discussions don't go anywhere. I suspect that
> other Porters are in the same boat as me. This is something you need to be
> aware of in any future discussions.
>
Most likely it's me not being clear enough - I can describe end usage, I
can describe
how to achieve abstraction, but I cannot so far describe well that
abstraction
(I'd love to learn that).
So yes, I'm aware of that :-(
>
> Now back to the subject of namespaces. I understand the general concept of
> multiple namespaces, but don't understand how you propose to implement and
> use them in perl.
>
> So far I get the vague idea that perl will be extended to allow
> for sigil-ness names to be recognised by the parser in some fashion.
> Then when someone wants to add a particular new syntactic feature to perl,
> such as named regexes, they can tell the parser this in some fashion, so
> that when the parser sees 'pattern foo ...', it knows to look up 'foo'
> in a separate namespace associated with regexes. Is that right so far?
>
more or less yes, only difference is parser needs to see `declared pattern
foo`
>
> These namespaces would be declared by what - at the perl level? Or in the
> core? Or both? Or what? Is that what the 'declare' statement is for?
>
Both.
Yes, at perl level, that's for `declare` statement is for, with declaring
new symbol
in namespace `symbol_space`.
> And what does the parser do with a name? Currently when the parser sees
> '$foo' or 'sub foo' or ''package foo', it is very specific about how 'foo'
> is interpreted - so in addition to looking up the symbol in the correct
> namespace, it it interpreted as a sub or package name or whatever and
> parsing proceeds accordingly.
>
First, let me correct one term - instead of parser say "perl parser" - aka
perly.y and toke.c.
Perl parser will see them only in special contexts:
- declare statement
- declared expression
- and prototype extension
When it will see "declare <namespace> <symbol> as <content>"
abstract behaviour will be still same, let me use reverse examples, how
existing symbols
can be declared using this new statement.
$foo;
declare perl_scalar foo;
my $foo = 'bar';
my declare perl_scalar foo = 'bar';
sub foo ($self) { bar };
declare perl_sub foo as ($self) { bar };
Now anwser can continue in multiple branches, so first I'll address how
names should be handled.
Behaviour of guts (typeglob or pad) will be similar, except instead of
using restricted
set of namespaces there will be dynamic data structure to store them.
Re restricted set of namespaces:
- typeglob uses struct with pointer per existing namespace
- pad uses sigil in name to make name unique
Both should be adapted to be able to handle unlimited number of namespaces,
for example:
- typeglob - add dynamic array to GV
- pad - lookup key will be constructed eg as: chr (symbol table id) .
symbol name, with symbol table ids:
- 36 for scalars
- 64 for arrays
- 37 for hashes
- 256 for first non-internal symbol space
Names will be handled "perl way" independently on namespace they belong to:
$Some::Package::foo;
declared perl_scalar Some::Package::foo;
&Some::Package::foo;
declared perl_sub Some::Package::foo;
declared data_contract Some::Package::foo;
Second branch is how to handle scope.
Perl is great for providing multiple scopes - my, our, local, state, field,
...
(plus multiple implementations of global scope - keywords, misc built-ins -
attributes, UNIVERSAL, builtin package)
So providing these scopes for any kind of symbols will only make their
usage native.
Using example with possible data contracts.
# import some contracts
use My::Data::Contracts :contract(Foo, Bar);
# declare package-wide contract
declare contract Foo_Or_Bar as Foo | Bar;
sub foo {
# declare my contract Bar
my declare contract Bar as ! My::Data::Contracts::Bar;
# override Foo
local declare contract My::Data::Contracts::Foo as ...;
}
Third branch is syntax after 'as'.
That one is symbol space specific expression handled by pluggable grammar.
How result will be treated internally is open question.
Let's use imaginary placeholder YV* for now.
> From your descriptions you seem to be taking about effectively parallel
> namespaces within the existing namespace structure. So one particular
> name would be interpreted as a 'package global' symbol and be looked up
> the same way as package globals (such as $foo::bar would), but once the
> name is resolved, it uses a further level of indirection, based on the
> context (such as pattern names) to choose from an array of GPs in that GV?
>
> And similar behaviour would apply for lexically-scoped names?
>
> Note that both typeblobs and lexicals have a lot of run-time behaviour.
> E.g. for typeglobs:
>
> *x = \$y; # alias the SV slot in the GP
> *x = *y; # alias the GP
> $foo::{x} = $bar::{y}; # alias the GV
>
As far as naming resolution is up to perl this should work for any kind of
symbol space:
eg:
*x = \ declared contract Foo;
>
> And lexicals get insanely complex. There can be multiple lexicals of the
> same name within the same scope:
>
> {
> my $x = 1;
> my $f1 = sub { $x }
> my $x = 2;
> my $f2 = sub { $x }
> say $f1->(), $f2->(); # prints "12"
> }
>
>
same, imagine your code written as
{
my declare perl_scalar x = 1;
my declare perl_scalar f1 = sub { declared perl_scalar x };
my declare perl_scalar x = 2;
my declare perl_scalar f2 = sub { declared perl_scalar x };
say declared scalar f1->(), declared scalar f2->();
}
You can just imagine "declare <symbol space>" and "declared <symbol space>"
as sigils
(in some way)
And the same name can bind to different SVs at various points during
> compilation and execution, for example:
>
> my $x;
> sub {
> sub f {
> $x;
> eval 'sub g { sub { BEGIN print $x } }';
> }
> }->();
>
> What does it mean to look up a lexical regex name in a similar
> environment:
>
> pattern x = ....;
> sub {
> sub f {
> x->match();
> eval 'sub g { sub { BEGIN print x->match() } }';
> }
> }->();
>
>
Two answers here:
scoping - that one will by still same
syntax
independent symbols are not visible to perl grammar unless
- they are part of declare/declared
- used in symbol space attribute
- used in part of grammar which understands them (in this case regexp
parser)
So your code will be working only as:
declare pattern x as ...;
sub {
sub f {
m/(?&x)/;
# or
declared pattern x ->match ();
... same for eval part
}
}
> do these parallel lexical namespaces do all the closure-related behaviour
> that 'my' vars do? What about 'state' behaviour?
>
> And so on.
>
>
This is really shame on me, I tried to explicitly express this :-(
Yes, everything you can do with existing symbols you should be able to do
with independent symbols.
Independent symbols must always be prefixed with introductory syntax
(declare / declared / symbol space attribute),
otherwise it may be treated as sub / glob / format ... whatever Perl finds
suitable.
>
> --
> In England there is a special word which means the last sunshine
> of the summer. That word is "spring".
>