ietf-openproxy
[Top] [All Lists]

Re: Decision on Rules Language

2003-09-16 17:52:05


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: owner-ietf-openproxy(_at_)mail(_dot_)imc(_dot_)org
[mailto:owner-ietf-openproxy(_at_)mail(_dot_)imc(_dot_)org]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.



<Prev in Thread] Current Thread [Next in Thread>