Subject: Re: Decision on Rules Language

From: "Anwar M. Haneef" <[email-masked]>
Date: Tue, 16 Sep 2003 19:52:01 -0500

Hi Alex,

Thanks for your answers, they really helped clarify things. I had some more
suggestions, I hope it doesn't overwhelm you:

Sugestion 1:
************
(Section 3.6 ?) nil Object

The (Core.)nil object is a special object that is the result of a failed
expression or statement. Operations on the nil object results in a nil
object, except in the case of the '==' operator in which case a semantic
comparision is made to see if the compared expression also results in a nil
object.

The nil object cannot be used in the assignments, and would result in a
fault if used. The result of a nil object being used as a condition in a
conditional statement such as an if-statement results in a failure
generation.

The failure of finding or applying a service correctly results in nil
returned as the result of the operation. In case of a situation such as:

	service := Services.find("opes://services/tran/german/french");

this will result in a failure generated as a result of applying the nil
object in an assignment as previously mentioned.

Suggestion 2:
*************
XXX: Code blocks and inclusion of libraries:

The P language code is divided into blocks of code, with a default intial
block name of 'main'. (Members of a code block may be accessed using the '.'
operator.) For example:

	my_freq_rule_library -> {
		some_older_useful_code;
		quick_expression -> {
			code;
		};
	};

Blocks of code from other files may be included in a P language program
using the 'include' statement. For example:

	include <my_freq_rule_library.p>

include-ing the P language file will perform the same function as writing
the included script inline. Inclusion of external scripts need to be done
prior to the primary code block of the program. For example:

	include <my_freq_rule_library.p>

	main -> {
		my_new_code;
		my_freq_rule_library.quick_expression;
	}

is equivalent to:

	my_freq_rule_library -> {
		some_older_useful_code;
		quick_expression -> {
			code;
		};
	}

	main -> {
		my_new_code;
		my_freq_rule_library.quick_expression;
	}

XXX: Failure within Code Block:

Failures caught within a code block results in the program flow exiting from
the current code block. For example:

	quick_check -> {
		if(Http.response.language_is("german"))
		{
	   		service := Services.find("opes://services/tran/german/french");
	   		service.toDialect("southern");
   			Services.applyOne(service, Http.request.headers);
	   	}
	};

	main -> {
		my_freq_rule_library.quick_check;
		more_code;
	};

A failure in the service related operations would result in the program flow
continuing to the next expression in the 'main' block as opposed to quiting
the entire P program.

Suggestions 3:
**************

XXX: Document lookup conflict resolution ((Section 4)

The modules as part of the interpretor's native language are registered and
given unique identifiers during the instantiation of the interpretor. For
instance, in case of a Java interpretor, the Http modules may be registered
to org.ietf.opes.PHttpModule. This way a unique mapping between module names
to native entities is maintained and prevents a possibility of conflict.
Modules may be added at runtime, but need to be registered with the registry
within the interpretor.

Thanks,
Anwar

-----Original Message-----
From: [email-masked]
[mailto:[email-masked]]On Behalf Of Alex Rousskov
Sent: Monday, September 15, 2003 8:12 PM
To: Anwar M. Haneef
Cc: OPES Group
Subject: RE: Decision on Rules Language

On Mon, 15 Sep 2003, Anwar M. Haneef wrote:

> I had a few notes (mostly half or quarter-baked) in addition to your
> last posting:

You will find mostly half-baked answers below :-)

> Scope:
> - Do we need to define the scope of code within which identifiers are
> recognized ? Can there be a case such as :
> 	h := Http.makeHeader("Client-IP");
> 	quick_code := {
> 		h := Http.makeHeader("Server-IP");
> 		contact_server(h);
> 		};

P uses global scope. There is no big benefit from a local scope
because we do not have user-defined functions. Global scope makes it
easy to support/interpret/explain single-assignment. This is not yet
documented.

> Single assignment/Or not?:
> - Should we be able to de-assign a variable (I guess this goes against the
> very definition of single-assignment)?

Yes, this goes against the very definition/purpose of a
single-assignment. You will get a lot more complexity and fewer easy
optimizations with multiple assignments (true variables). Single
assignment along with lazy evaluation allows you to treat assignments
as macros -- very easy to support and relatively easy to optimize.

> - Is there any specific reason we would want single-assignment ?

Simplicity and performance. Single assignment allows you to manipulate
large protocol structures with little overhead. Without variables, you
cannot reuse computed values. With true variables, you get into all
sorts of complexity and memory management problems, even if you do not
want to optimize. Single-assignment makes slow interpreters simple and
complex interpreters fast.

Single assignment allows you to reuse code as well. See current draft
(the retry example: A or A or A).

> Processing Point Identification:
> - Mechanism for identifying the processing points identifier (PPID) as the
> points of activity  for the rule

This is application-specific, IMO. Each module like "HTTP" would
define its own notion of processing points. You should be able to find
my rant about this on the OPES list archives ("Subject: processing
points in draft-beck-opes-irml-03").

> - Something such as interpretor.processingPoint("X"){} could be defined ->
> This info can be used by the interpretor to classify the rules based on
> PPIDs for quicker retrieval by the OPES processor. Or else allow something
> like:
> 	Core.PPID("X")
> 	{
> 		code;
> 	}
> to deliniate the processing point associated with the code.

See above. Also, I believe that in many situations, the rules will be
assigned to a processing point by a higher-level interface. Again,
processing point is not a uniform concept that Core should support,
IMO.

> Primitive types:
> - Could we include support for arrays or lists of elements/objects ?

Not explicitly because there would be no way to iterate them. Remember
that there are no loops in P. However, modules can implement
structures and containers of any complexity; they would need to
provide appropriate access methods, of course (find, for_each, etc.)

For example, Services module is, essentially, a searchable map of
services.

> - Can we modify the 'identifier' to be defined as (for us C/Java
programmers
> who prefer using this for global static variables):
> 	identifier = "_"/ALPHA *(ALPHA/DIGIT/"_")

Yes. Please remind me if I forget.

> Loops and Iterators:
> - This is a powerful feature P-language could easily integrate but
difficult
> in an XML-based  language
> - 'for each element in <Y>', 'while (expression){code}', 'do-while'

I agree that it would be relatively easy to add loops to P.

The rationale for not including explicit loops is that they are
error/leak prone and difficult to check for correctness. We want to
reduce chances that some P code loops forever or starves the proxy to
death. I think this is a weak argument because time-based and
memory-based limits for rule execution must be implemented at the
proxy anyway. But, I guess, we do not want to push too far. See my
comment about module-defined structures above as well.

> Subsystems:
> - I am assuming the IRML subsytem equivalent for extended functionality
> would be encompassed  by the Core.import("M") functionality

Yes.

> Failure detection/capture:
> - Should we have a structure similar to 'try-catch-final' in contemporary
> languages like Java/C# etc ?

See current draft for how it is handled today (section "Failures"):
	http://www.measurement-factory.com/tmp/opes/

> - What happens in case a service cannot be found when doing 'Service.find'
> ? - see notes on the interpretor below.

In this case, find() returns some kind of an "undefined"/"nil"
object. If used, this object will result in a failed expression or
statement. This needs to be documented, of course. We also need a way
to test for nil values (and for member presence, for that matter).

> - What happens in case a method called in an object does not
> exist/fails/throws an error/returns invalid value

... the corresponding expression fails. See section Failures in current
draft at the above URL.

> Interpretor & Security:
> - Should the specs for the interpretor be defined or is it left for the
> implementor?

We already have a few interpreter-specific MUSTs. Is that what you
mean by the "specs for the interpreter"? P draft _is_ the specs for
the interpreter, is it not?

> - Should security be enforced by the interpretor that does the
> underlying processing based on P language commands?

Not sure what you mean. What is your threat model?

> - IMHO, If we assume that the P language runs via the interpretor
> that acts as a 'Virtual Machine', all security/error
> handling/authentication features are delegated to the interpretor.

I think that should be implementation-dependent, but I am not sure I
understand the issue fully. Note that extension modules are _not_
(cannot be) written in P so it is impossible to do what Java tries to
achieve with its security model. This is a good thing -- we do not
want to invent a new general-purpose language to write modules! Does
that answer your question?

Thank you,

Alex.

---

From: Alex Rousskov <[email-masked]>
Date: Tue, 16 Sep 2003 22:36:11 -0600 (MDT)

> Sugestion 1:

While we might need a concept of an undefined value, I think we should
be able to get away without the nil object as a magic constant/value.
Perl does that, for example. Nil objects seem to be required only when
you support pointers, and P has no pointers. Please see below for more
specifics.

> The (Core.)nil object is a special object that is the result of a
> failed expression or statement. Operations on the nil object results
> in a nil object, except in the case of the '==' operator in which
> case a semantic comparision is made to see if the compared
> expression also results in a nil object.

I think we can simplify quite a bit: Any use of an undefined value
must result in a failure (and not not another nil object). This makes
it easy to catch errors and abort early if needed. It also has a more
clear/uniform/straightforward semantics.

To make this interface complete, we would then need an unary operator
to test both for nil objects and member presence:
	if (exists service) { ... };
	if (exists Http.message.requestLine) { ... };
or
	if (defined service) { ... };
	if (defined Http.message.requestLine) { ... };

Note that the operator takes a name as input, it does not use the
value the name represents. No need for a special "nil"
constant/token!

Did I miss any use cases?

BTW, which name (exists or defined or something else) would you
prefer? I wish one could type the existential predicate using
ASCII :).

Moreover, we may be able to get rid of the whole "undefined value"
concept and use failures instead: if anything goes wrong, the code
fails. Failed code can be detected/caught using "or" operator. The
latter part is already documented.

To detect and substitute for missing services, for example, one would
write:

	{ service := Services.find("A"); } or
	{ service := Services.find("B"); }

Even a simpler expression below can probably be supported within the
current design, perhaps after defining "or" operator more clearly:

	service := Services.find("A") or Services.find("B");

Do you think using failures like that is sufficient?

> The nil object cannot be used in the assignments, and would result
> in a fault if used. The result of a nil object being used as a
> condition in a conditional statement such as an if-statement results
> in a failure generation.
>
> The failure of finding or applying a service correctly results in
> nil returned as the result of the operation. In case of a situation
> such as:
>
> this will result in a failure generated as a result of applying the
> nil object in an assignment as previously mentioned.

Agreed. The above no-undefined-use rule covers all these cases, IMO
(but using failure feature instead seems cleaner). What do you think?

> Suggestion 2:

I am probably missing something important, but how is that different
from the current mechanism of assigning a piece of code?

	my_freq_rule_library := {
		some_older_useful_code;
		quick_expression := ...;
	};

Did you overlook that hidden(?) possibility or can your proposal do
more than name a piece of code?

> 	include <my_freq_rule_library.p>

This is already supported, I believe:

	my_freq_rule_library := Core.import("my_freq_rule_library.p");

The algorithm to find module using its string name
("my_freq_rule_library.p") is Core implementation-dependent. I would
suggest that environments that support loading modules from P files,
use more explicit name syntax:

	Core.import("file://my_freq_rule_library.p");

or some such. Http and other well-known module names should probably
be URIs (you talk about a similar requirement below).

> Failures caught within a code block results in the program flow
> exiting from the current code block. For example:

That is the current requirement as well, except the failure is
propagated until caught with an "or" trap. See current draft.

> A failure in the service related operations would result in the
> program flow continuing to the next expression in the 'main' block
> as opposed to quiting the entire P program.

The "next expression" part may not be desirable because it would leave
certain failures undetected. Programmers must be explicit if they want
to ignore an error:

	{ /* code that may fail */ } or {};

I believe current failure rules are close to exceptions in modern
programming languages. Do you agree that the current failure design is
sufficient to address your needs or do you see any missing
pieces/flaws?

> The modules as part of the interpretor's native language are
> registered and given unique identifiers during the instantiation of
> the interpretor. For instance, in case of a Java interpretor, the
> Http modules may be registered to org.ietf.opes.PHttpModule. This
> way a unique mapping between module names to native entities is
> maintained and prevents a possibility of conflict. Modules may be
> added at runtime, but need to be registered with the registry within
> the interpretor.

Yes, I agree that modules should be identified by
[unique-per-interpreter-invocation] URIs and that those URIs have to
be known to the interpretor (or it would not know which module to
import!). This is indeed undocumented but needs to be.

Thanks for discovering more missing pieces and suggesting specific
improvements. I will try to incorporate all "undocumented but needs to
be" features you recently pointed out into the next draft release.
Please answer the above questions to resolve remaining issues.

Thank you,

Alex.

P.S. Current P draft (already submitted for publication as a WG
document) is at http://www.measurement-factory.com/tmp/opes/

---

From: "Anwar M. Haneef" <[email-masked]>
Date: Wed, 17 Sep 2003 13:17:54 -0500

Hi Alex,

>clear/uniform/straightforward semantics.

I agree with this.

>prefer? I wish one could type the existential predicate using

I would go with defined, since it goes with the term 'undefined' (even if we
decide to get rid of the 'undefined value' concept).

>Do you think using failures like that is sufficient?

I would think that we should stay with maintaining the "{}" brackets before
the or for clarity - especially for cases with multiple statements within
the blocks. Also in section 2, we would need to add:

Section 2:
   expression =
   	name / function-call / "{" code "}" *( "or {" code "}" )

>(but using failure feature instead seems cleaner). What do you think?

Yes, I would agree with this as well.

>from the current mechanism of assigning a piece of code?

The key difference here was unique identification of the 'member code'
within a block. By 'member code', I refer to the ability to identify the
block of code assigned to 'quick_expression' within the larger block,
'my_freq_rule_library'. This might be useful when including libraries where
there might be conflicts due single assignment. Included libraries are
identifed by a unique code-block name, preventing conflict of names. This
might make large rule files more structured similar to 'rule' blocks
("<rule></rule>") in IRML deliniated rules.

>more than name a piece of code?

I wasn't sure if the assignment of code with a name was intended to do this
as well.

>	my_freq_rule_library := Core.import("my_freq_rule_library.p");

True, I hadn't thought of Core.import being used that way. I agree that the
algorithm to find module using its string name is  left to the Core
implementation. Although, I would suggest that we do mention how the code is
imported and appended to the program that is including this.

>	Core.import("file://my_freq_rule_library.p");

Should these suggestions be mentioned in the draft as 'recommended
practices' ?

>sufficient to address your needs or do you see any missing

This seems sufficient.

>be" features you recently pointed out into the next draft release.

Glad to be of help.

Thanks,
Anwar

---

From: Alex Rousskov <[email-masked]>
Date: Wed, 17 Sep 2003 14:14:20 -0600 (MDT)

On Wed, 17 Sep 2003, Anwar M. Haneef wrote:

> >To detect and substitute for missing services, for example, one
> >would write:
> >
> >Even a simpler expression below can probably be supported within
> >the current design, perhaps after defining "or" operator more
> >clearly:
> >
> I would think that we should stay with maintaining the "{}" brackets
> before the or for clarity - especially for cases with multiple
> statements within the blocks. Also in section 2, we would need to
> add:
>
> Section 2:
>    expression =

Not exactly. The "... ; more to be defined (logical and arithmetic
expressions)" part in the current BNF just needs to be defined.
Roughly,

	expression = name / function-call / "{" code "}"
		unaryOp expression /
		expression binaryOp expression

	binaryOp = "and" / "or" / ...

Code {block} is just one of the expression atoms, no special treatment
is needed in BNF or in the interpreter.

What is missing though, is cblock in the statement definition:

	statement = assignment / function-call / if-statement / cblock
	cblock = "{" code "}"

Will add.

> The key difference here was unique identification of the 'member
> code' within a block. By 'member code', I refer to the ability to
> identify the block of code assigned to 'quick_expression' within the
> larger block, 'my_freq_rule_library'.

Do you want to refer to my_freq_rule_library.quick_expression from
outside of the my_freq_rule_library block? If you do not, then this is
already supported. If you do, then this is equivalent to user-defined
structures which, I would argue, is a too-heavy feature for P.

> This might be useful when including libraries where there might be
> conflicts due single assignment. Included libraries are identifed by
> a unique code-block name, preventing conflict of names.

But libraries are already identified by a unique name on the left hand
side of the assignment, when they are imported:

	uniqueName := Core.import(module_id);

Thus, importing a module cannot lead to name conflicts because all
references to the module would be via uniqueName. Aggressive use of
Core.lookup() can lead to multiple objects potentially accessible
under the same name. There are several known solutions:

	- remove Core.lookup functionality
	  (but I do not want to write "Http." all the time
	  if all I use is the HTTP module)

	- last applicable module in Core.lookup() order wins
	  (but that may bring big surprises when a newer
	   version of the last module includes names that
	   match already used names from the previous module
		Core.lookup(m0);
		Core.lookup(m1);
		if (foo) { ... } /* used to be m0.foo, now m1.foo */
	   )

	- all names are visible, but interpreter fails
	  if there is a conflict
	  (ugly because it is difficult to predict whether
	  there will be conflicts ahead of time -- we may
	  not know all the names that some module will
	  imports in the future)

The non-trivial use case I would like to support is this:

	Smtp := Core.import("SMTP");
	Http := Core.import("HTTP");

	/* handle SMTP */
	{
		Core.lookup(Smtp);
		...
	}

	/* handle HTTP */
	{
		Core.lookup(Http);
		...
	}

The above should lead to no conflicts regardless of what SMTP and HTTP
modules import or export.

I also do not like the recursive nature of this:
	Core.lookup(Core);
I suspect that the lookup facility needs to be handled at the language
level, not Core module level. I though I can get away without it, but
this does not look good.

This problem is common to all languages that support namespaces. Would
you care to research the namespace issue in other languages (XML, C++,
Java) and tell us what the common solution seems to be, if any.

> This might make large rule files more structured similar to 'rule'
> blocks ("<rule></rule>") in IRML deliniated rules.

Is the "{ code }" construct equivalent to "<rule></rule>"?
What

> True, I hadn't thought of Core.import being used that way. I agree
> that the algorithm to find module using its string name is left to
> the Core implementation. Although, I would suggest that we do
> mention how the code is imported and appended to the program that is
> including this.

Agreed.

> Should these suggestions be mentioned in the draft as 'recommended

I think they should be defined/required explicitly. I suspect some RFC
defines URI schemes applicable in this context. If not, we would have
to document ourselves. Care to research if any RFC defines URIs
suitable for a "include this resource" command?

Thank you,

Alex.

---

From: "Anwar M. Haneef" <[email-masked]>
Date: Fri, 19 Sep 2003 02:37:50 -0500

More comments on the latest to-do:

Do we need a 'switch' statement in P ? - after all, this is a rules language
with lots of if-else statments...
++++++++++++++++++++++++++++++++

Native support for Regular Expressions?

These would be used a lot in a rules language. I would think one fo the
concerns in a debate for having it or not would be  the potential
performance issue - which would be advisable? - having a pure native
implementation that is loaded as part of a  module or interpreting the REGEX
engine that is part of the P language interpretor. Performance-wise I might
assume that the  native implementation might be more optimized, while on the
other hand having it as part of the language would make the REGEX  syntax
more standard and easier to migrate P code.

++++++++++++++++++++++++++++++++
Section 2. Escape sequences for the grammar (from C++):

escape-sequence:
	basic-escape-sequence/
	octal-escape-sequence/
	hex-escape-sequence

basic-escape-sequence:
	\'
	\"
	\?
	\\
	\a
	\b
	\f
	\n
	\r
	\t
	\v

octal-escape-sequence:
	\octal-digit
	\octal-digit octal-digit
	\octal-digit octal-digit octal-digit

hex-escape-sequence:
	\x hex-digit
	hex-escape-sequence hex-digit

octal-digit:
	0 / 1 / 2 / 3 / 4 / 5 / 6 / 7

hex-digit:
	0 / 1 / 2 / 3 / 4 / 5 / 6 / 7 / 8 / 9 / a / b / c / d / e / f / A / B / C /
D / E / F

Regards,
Anwar

-----Original Message-----
From: [email-masked]
[mailto:[email-masked]]On Behalf Of Anwar M. Haneef
Sent: Friday, September 19, 2003 1:07 AM
To: OPES Group
Subject: RE: Decision on Rules Language

Alex,

>level, not Core module level. I though I can get away without it, but

In case of Java, the virtual machine is launched (equivalent to our
intepretor) is launched with a default Class Loader,  System Class Loader.
This Class Loader is responsible for loading all the classes to run the
program. This usually picks up  class files from the classpath defined by
the system. Users may customize the Class Loader to their needs in terms of
loading  the classes (such as from a database/HTTP URL etc). This may be
defined when the VM is launched (its a system property, or you can write
your custom class loader as the starting point of your program), in which
case the System Class Loader is over-ridden or in case a  Custom Class
Loader is invoked in a program, it runs as a child of the System Class
Loader, loading classes that the System  Class Loader cannot locate.

P could have  similar 'system class loader' or 'System Module Loader' which
launches the Core module and launches subsequent  modules. This would need
to be implemented at the interpretor and not as part of the Core module.
Users may be given the  option of defining custom loaders of modules (later
?). This loader would need to be written native to the interpretor, and not
in P.

BTW, that brings me to another question - why do we need a Core.lookup(X)
method? Shouldn't we be able to load the namespace of the imported module by
default ? -  such as what is done in Java ? The 'import' feature of the
interpretor should be performing the function of the 'System Module Loader'
and the namespace initiator [similar to 'using namespace' in C++].

In case of namespace conflict resolution, most languages such as Java or C++
would catch the error in case there are multiple  possibilities for a method
or field, during compile time. Conflicting situations would call for
explicit identification of  the method or variable. For example:

	Smtp := import("SMTP");
	Http := import("HTTP");

	httpheader := getHeader();
	senderEmailId := getSenderEmail();

might lead to a conflict in case both the HTTP and SMTP modules have the
same method 'getHeader()' and would lead to  compile-time error
identification. The correct usage should be:

	Smtp := import("SMTP");
	Http := import("HTTP");

	httpheader := Http.getHeader();
	senderEmailId := getSenderEmail();

>suitable for a "include this resource" command?

I'll get back to you on this. But, on a similar discussion as the one above,
in case we let the module loading be a part of the interpretor and allow
users to define custom module loaders - won't it be advisable to let the
designers of these custom loaders/interpretors use whatever scheme is
convinient to them ? Would defaulting to "file://" be restrictive ? Would
there be ppl who would want to retrive their p file libraries from a http
url ? Comments ?

Thanks,
Anwar

---

From: Alex Rousskov <[email-masked]>
Date: Fri, 19 Sep 2003 10:12:31 -0600 (MDT)

Anwar,

	Appreciate the research! Based on your information, and to
keep things correct and simple, I would propose the following:

	- module importing and lookup facilities are
	  implemented by the interpreter (not Core)
	  and cannot be changed (C++ model)

	- imported modules enter name space (Java model)

	- ambiguities lead to interpretation-time errors

	- every module documents the URI it wants to be
	  known as; URI scheme does not, by default,
	  imply access method to the module

	- interpreters MAY support loading of raw P files

	- URIs for loading of raw P files are
	  implementation-dependent and a "file" URI scheme is
	  used as an example for local files

	- the Core module and the Services module are always
	  available as if they were autoloaded internally before
	  user code evaluation

For example, all of the import statements below pollute global name
space, but the first two provide a way for a programmer to resolve
conflicts, if any.

	/* import HTTP module */
	Http := import "http://ietf.org/opes/rules/p/HTTP";

	/* import a local file */
	MyStuff := import "file:/usr/local/myrules.p";

	/* import a local file without naming it */
	import "file:/usr/local/globalrules.p";

Please let me know if there are any better ideas or objections. We
still need to investigate what HTTP module URI should look like from
IETF point of view. The same info is needed for OCP: we need URIs to
identify message parts and other negotiated features.

Thanks,

Alex.

On Fri, 19 Sep 2003, Anwar M. Haneef wrote:

> intepretor) is launched with a default Class Loader, System Class
> Loader. This Class Loader is responsible for loading all the classes
> to run the program. This usually picks up class files from the
> classpath defined by the system. Users may customize the Class
> Loader to their needs in terms of loading the classes (such as from
> a database/HTTP URL etc). This may be defined when the VM is
> launched (its a system property, or you can write your custom class
> loader as the starting point of your program), in which case the
> System Class Loader is over-ridden or in case a Custom Class Loader
> is invoked in a program, it runs as a child of the System Class
> P could have similar 'system class loader' or 'System Module Loader'
> which launches the Core module and launches subsequent modules. This
> would need to be implemented at the interpretor and not as part of
> the Core module. Users may be given the option of defining custom
> loaders of modules (later ?). This loader would need to be written
> native to the interpretor, and not in P.
>
> BTW, that brings me to another question - why do we need a
> Core.lookup(X) method? Shouldn't we be able to load the namespace of
> the imported module by default ? - such as what is done in Java ?
> The 'import' feature of the interpretor should be performing the
> function of the 'System Module Loader' and the namespace initiator
> [similar to 'using namespace' in C++].
>
> In case of namespace conflict resolution, most languages such as
> Java or C++ would catch the error in case there are multiple
> possibilities for a method or field, during compile time.
> Conflicting situations would call for explicit identification of the
> method or variable. For example:
>
> 	Smtp := import("SMTP");
> 	Http := import("HTTP");
>
> might lead to a conflict in case both the HTTP and SMTP modules have
> the same method 'getHeader()' and would lead to compile-time error

---

From: "Anwar M. Haneef" <[email-masked]>
Date: Fri, 19 Sep 2003 01:06:36 -0500

Alex,

	Smtp := import("SMTP");
	Http := import("HTTP");

	Smtp := import("SMTP");
	Http := import("HTTP");

Thanks,
Anwar

---

From: Alex Rousskov <[email-masked]>
Date: Fri, 19 Sep 2003 10:46:05 -0600 (MDT)

On Fri, 19 Sep 2003, Anwar M. Haneef wrote:

> Do we need a 'switch' statement in P ? - after all, this is a rules
> language with lots of if-else statments...

A "switch" statement is only better than a bunch of "if"s when all
if-statement conditions start with (X == ...). In P, the "=="
operator is defined for booleans and integers only. Booleans do not
count (if-else works better for them). I suspect that it is somewhat
unlikely situation for P rules to iterate through a bunch of integer
values.

IMO, what we need is to improve if-statement syntax to make a bunch of
if-else-if-else-if statements look good. Added to the to-do list.

> Native support for Regular Expressions?

IMO, the problem with REs is not that they may take a long time to
process, but that available libraries cannot be used to bound/control
processing time. Many services will take a long time to process. But
services are designed so that a processor can terminate them if they
take too long. It is difficult to do that with RE libraries without
threads or other heavy mechanisms.

Thus, regular expression support should be optional (but can still be
native if this working group wants them!).

My vote is against native support in P because the majority of
applications would find existing string operators (substring
searching, essentially) and application-specific interfaces
sufficient. (BTW, I will add a length() and index() string functions
to Core).

> These would be used a lot in a rules language.

Can you give a couple of examples where REs would be essential, given
available substring searching operators _and_ ability of
application-specific modules to split application objects (e.g., HTTP
headers) into semantically valid but smaller pieces for you?

> having a pure native implementation that is loaded as part of a
> module or interpreting the REGEX engine that is part of the P
> language interpretor. Performance-wise I might assume that the
> native implementation might be more optimized, while on the other
> hand having it as part of the language would make the REGEX syntax

I think that performance-wise both approaches would be about the same.
Interpreters can use optimized libraries or modules can use optimized
libraries. Native support does allow for somewhat more natural RE
syntax, but it also complicates P syntax.

Yeah, and we would need to add a universal-character-name as a part of
string-char or escape-sequence. This all looks kind of heavy. Is there
a simpler, but still complete solution? Replacing support for
octal-escape-sequence and hex-escape-sequence with
universal-character-name? What does XML have to offer here?

Thank you,

Alex.

---

From: "Anwar M. Haneef" <[email-masked]>
Date: Sat, 20 Sep 2003 11:39:41 -0500

Alex,

> Section 2. Escape sequences for the grammar (from C++):

I haven't had a chance to look at this properly, but I do have a suggestion for the if-statement:

   if-statement =
   	"if" "(" expression ")" "{" code "}" /
   	"if" "(" expression ")" "{" code "}" "else" "{" code "}"

should be:

   if-statement =
   	"if" "(" expression ")" "{" code "}" /
   	if-statement "else" "{" code "}"

Regards,
Anwar

---

From: Alex Rousskov <[email-masked]>
Date: Sun, 21 Sep 2003 13:37:42 -0600 (MDT)

>    	if-statement "else" "{" code "}"

Hmm... This allows for
	if () code else code else code else code
which does not make sense. You probably meant something like this:

	if-statement = if-head *if-alt [if-tail]
	if-head      = "if" "(" expression ")" "{" code "}"
	if-alt       = "elsif" "(" expression ")" "{" code "}"
	if-tail      = "else" "{" code "}"

For example:
	if (cond1) {
		...
	}
	elsif (cond2) {
		...
	}
	elsif (cond3) {
		...
	}
	else {
		...
	}

which is succinct, strict (no guessing which "if" the "else" part applies to),
and common enough (Ada, Modula, Perl, PHP):
http://merd.net/pixel/language-study/syntax-across-languages/CntrFlow.html

Did I get the grammar right?

Thanks,

Alex.

---

From: "Anwar M. Haneef" <[email-masked]>
Date: Mon, 22 Sep 2003 01:14:51 -0500

>Did I get the grammar right?

Yes, I believe you are right. Silly me, I guess I wasn't thinking clear when I sent the mail out.

Thanks,
Anwar