Subject: Comments on the P Language

From: Geetha Manjunath <[email-masked]>
Date: Wed, 08 Oct 2003 16:02:03 +0530

Hi,

Please find my comments on the internet draft on P language below. It
also has some suggestions for new constructs for the 'P' language.

* Section 2, Syntax: While several operators are listed out along with
their precedence, it may be helpful to support the commonly used
parenthesized expression with an additional rule : 
expression = '(' expression ')'

* Section 3.3 Operators: Even I did not like the use of case to
distinguish operator attributes (such as case sensitivity) eg: EqualS,
ContainS.
On the contrary, I think it would be nice to have the operators
themselves case insensitive, so EQUAL = equal = EquaL . Use of equal_i
and equal_s is preferable.

* Section 3.6 Assignments: I like the single assignment approach of P.
However, I feel the need for a few additional statements (or Core
services) to manipulate the scope of a name - for eg: 'kill' a name in
the current scope. Some uses of such a construct would be:
 ** We could essentially acheive a private name space when modules are
imported. This can be done by killing all the private variables from a 
module before exiting the module ( if the module is written in P). 
 ** This is will also help in reducing name clashes that may result in
use of same names from 2 different modules. The case of 
        smtp := import "..";
        http := import "..";
	kill SMTP.message ;
        meth = message.method;
 ** "kill moduleName " could unload a module too.
 ** Another useful scope manipulation statement would be something like
"inline Http" (or "use Http")  statement that makes references to be
resolved in the context of module Http  (instead of the default
behaviour of resolving in the context of *all* the modules being
imported)

* Section 4.1: Interpreter-module interface.
** I think we should at the minimum specify a minumum interface that
must be supported by a module, such as -  isDefined("membername") and so
on - which could typically be provided a default behaviour by the
interpreter (based on the semantics of the import statement).
** There is also a need to specify the characterisitics of the service
being returned by the imported module. (or give a reference to where
this info is available)
 *** What is the interface expected of this service? Is it a proxylet?
Web service?
 *** How does it get access to the request/response being manipulated?
 *** What is the semantics of the Services.applyone(service)?  Will it
modify the response/request to be used further on?
 *** Will the interpreter employ the call-out protocol at this point? If
so, does it send the response or the request? For example, in the ICAP
case, is it RESPMOD or REQMOD?
 ** How does one specify the vectoring point (equivalent of 1,2,3,4 in
IRML)?

* Section 4.2: In my opinion, the case of module being a P program needs
to be further thrashed out. For example: which are the valid members of
a module defined using P. All the names in the program ?

* Finally, with my small exposure of writing an IRML parser that
generates a python rule engine, I feel this language 'P' is very well
suited to be implemented in Python. In fact, if we excuse the syntactic
changes, P can straight away be expressed in Python! and that's nice.

Hope this helps.

Incidently, are there any efforts underway to implement this language?

Thanks and regards
Geetha

> A New Internet-Draft is available from the on-line Internet-Drafts
> directories.
> This draft is a work item of the Open Pluggable Edge Services Working Group
> of the IETF.
> 
>         Title           : P: Message Processing Language
>         Author(s)       : A. Beck, A. Rousskov
>         Filename        : draft-ietf-opes-rules-p-01.txt
>         Pages           : 30
>         Date            : 2003-9-22
>         
> P is a simple configuration language designed for specification of
> message processing instructions at application proxies. P can be used
> to instruct an intermediary how to manipulate the application message
> being proxied. Such instructions are needed in an Open Pluggable Edge
> Services (OPES) context.
>

---

From: Alex Rousskov <[email-masked]>
Date: Wed, 8 Oct 2003 15:38:13 -0600 (MDT)

On Wed, 8 Oct 2003, Geetha Manjunath wrote:

> Please find my comments on the internet draft on P language below.
> It also has some suggestions for new constructs for the 'P'
> language.

Appreciate the comments!

> * Section 2, Syntax: While several operators are listed out along
> with their precedence, it may be helpful to support the commonly
> used parenthesized expression with an additional rule :  expression
> = '(' expression ')'

Mea culpa. Now fixed at http://www.measurement-factory.com/tmp/opes/

> and equal_s is preferable.

I agree that using case to distinguish operators is a bad idea. I have
a better(?), not yet documented, idea. String should have case
sensitivity attached to them by module methods that produce them.
String constants would default to case-sensitive. This will make it
possible to compare, say, HTTP request method with "GET" or "connect"
constants and always get "correct" result depending on protocol
sensitivity rules.

This is a big problem with string comparison in the current spec --
one have to be very careful to use the right comparison operator. With
sensitive strings (rather than operators), the module authors would
take care of most common cases by returning strings with appropriate
sensitivity.

case_sensitive() and case_insensitive() Core methods are provided to
force particular sensitivity mode when needed. Comparing a case
sensitive string with a case insensitive string will result in case
insensitive comparison.

This needs further thought/polishing. Have you seen sensitive strings
anywhere? Do you think this approach will work?

> * Section 3.6 Assignments: I like the single assignment approach of
> P. However, I feel the need for a few additional statements (or Core
> services) to manipulate the scope of a name - for eg: 'kill' a name
> in the current scope.

I have rejected scope for the sake of simplicity. I could not find
convincing examples where it would be really needed. With
single-assignment approach, global scope is needed to name expressions
based on external conditions:

	if (condition) {
		name = value1;
	} else {
		name = value2;
	}

> Some uses of such a construct would be:

If a name is not used outside the module, the optimizer will remove
it. Thus, the above is only helpful to avoid name collision. If this
becomes a true problem, "local" variables should be introduced into
the language. Personally, I doubt many general-purpose modules would
be written as P programs.

> use of same names from 2 different modules. The case of

I would prefer to see more explicit Http.message.method in the above
case.

>  ** "kill moduleName " could unload a module too.

An optimizer can do that once a module is unused. Again, this seems to
be useful only to avoid name collisions.

> behaviour of resolving in the context of *all* the modules being

Are you talking about the difference between use and require in Perl?
I agree that adding require would be a good solution if many modules
are written in P, but I think to support modules written in P well,
more things like explicit exported or explicit local variables will
need to be added.

> interpreter (based on the semantics of the import statement).

Not sure what general interface functions we can document. Can you
give more examples?

Is isDefined really needed? If something is not defined, P interpreter
will raise a failure. Is that not sufficient to detect undefined
things?

> being returned by the imported module. (or give a reference to where

I agree that service interface needs to be documented.

>  *** What is the interface expected of this service? Is it a proxylet?

Whatever interface the service provides and P implementation host
supports.

>  *** How does it get access to the request/response being manipulated?

Implementation dependent.

> modify the response/request to be used further on?

This needs to be documented. I think the semantics should be apply
once and then continue interpretation. However, we need to document
whether named expressions may change after service invocation:

	a = message.headers.have("Via"); // suppose there is no Via

	if (not a) {
		Services.apply(service); // adds Via
	}

	if (a) {
	       // should this be executed?
	}

My feeling is that the computed (used) value should not change.
Assignment is not a macro.

> case, is it RESPMOD or REQMOD?

It may employ OCP. I think that services need service-specific
configuration parameters that determine mode and what needs to be
supplied (e.g., request, response, or both).

>  ** How does one specify the vectoring point (equivalent of 1,2,3,4 in

Application-dependent. HTTP Adaptation draft or other documents may
document this as a part of HttpProxy module description.

> a module defined using P. All the names in the program ?

Yes, for now. Import simply loads the program into the namespace.
Again, I agree that if P modules in P become popular, more control
would be needed. The current preference is to start with something
small and simple.

> generates a python rule engine, I feel this language 'P' is very
> well suited to be implemented in Python. In fact, if we excuse the
> syntactic changes, P can straight away be expressed in Python! and
> that's nice.

I am not a big fan of languages that do not catch variable name typos,
but I am glad you think that a Python implementation would be simple.
I agree that it may be possible to write a P-to-Python converter.

> Incidently, are there any efforts underway to implement this

Personally, I have not seen any real demand for P (or IRML for that
matter) yet.

Thanks a lot for your feedback. I hope that my "we want to keep it
simpler for now" responses did not discourage you. This is just a
starting point. With sufficient demand and real-world use, we should
be able to polish and enhance the language.

Thank you,

Alex.

---

From: Geetha Manjunath <[email-masked]>
Date: Fri, 10 Oct 2003 13:10:35 +0530

Hello Alex,

Thanks for the quick response.

> Mea culpa. Now fixed at http://www.measurement-factory.com/tmp/opes/
 
That's nice.

> constants and always get "correct" result depending on protocol

I like this idea!
 
> sensitive string with a case insensitive string will result in case

Here I still prefer having different operators for sensitive and
insensitive. However, based on your idea above, we could probably have a
default behaviour defined for comparison (which is based on the
attributes of the string).

> anywhere? Do you think this approach will work?

I cannot recall seeing it anywhere else at the language level ... only
sensitivity at operators/API. But yes, python allows defining regular
expressions that can be optionally case insensitive (compile method), 
similarly Java specifies some classes whose objects can have case
sensitivity as an  attribute for  comparison.
 
> based on external conditions:
Yes, the need for global assignment is clear.

> be written as P programs.

Yes, the scope manipulation statements will only aid in avoiding name
collision. Alternatively, you could always mandate a need to qualify any
member with the module name (ie., name representing the import
statement) as opposed to providing features that may result in name
collision.

I beleive, the optimizer cannot apriori know whether or not the name is
used outside the module. What happens if the current P source file is
imported in another (nested modules!) ?

> I would prefer to see more explicit Http.message.method in the above

But, consider the case wherein a module implements an operation such as
regular expression match. In that case, I would prefer to say
matchRE(expr1,string) rather than re.matchRE(..) 

Nevertheless, it may be better to make that a language restriction
itself and mandate the need to qualify members (as I mentioned in an
earlier point)! 

> more things like explicit exported or explicit local variables will

That would be an alternative way of extending the scope - that would be
more like other languages and would probably be prefered.

> will raise a failure. Is that not sufficient to detect undefined

Yes, some things may be caught with exceptions.. How about
isCaseSensitive(string) ?  Assuming the new attributed string that you
mentioned. I will try and list those one of these days.. As of now, I am
thinking of some methods that provide reflective property.

> Assignment is not a macro.
As per the description in 3.6, the computed value should change! The
alternative semantics can be obtained by

if (not a) {
    Services.apply(service);
}
else {
   /* if not a */
}

> supplied (e.g., request, response, or both).
Don't we then need to specify how to get the request and response from
the Core? Do you assume that the interfaces for the request/response
objects will be provided by the protocol module?

> be able to polish and enhance the language.

Personally, I have seen the need for a conditional expression (at the
minimum with OR and AND) and also need for regular expression match
while using IRML... 

Thanks for making this discussion interesting..

regards
Geetha