Prothon Lang Dev Wiki
Laurent Dube <[email protected]>
| Newsgroups | gmane.comp.lang.prothon.user |
|---|---|
| Organization | DEI |
| Message-ID | <[email protected]> |
The process we are engaged into at this point is one of discussion.
The vehicle used for these discussions has been a mailing list.
I'm suggesting we consider a wiki as a container for our discussions.
Here are some advantages of a discussion wiki:
- serves as discussion archive with intelligence built in, better than
archived mailing list
- intelligence is in the form of sequencing and insertion of contributions
(mailing list is awkward for referencing)
- avoids duplication of replied-to quoted text found in mailing list format;
in a wiki, all replies are magically put in the correct place by their
respective writers
- lightens mailing list traffic, reserves it for other purposes
- open, no supervision, no nothing to do other than hosting the wiki software
- the format invites novel ways of discussing
- the format encourages clarity and explicitness
- the format is flexible, yet orderliness may prevail
Open question: selection of wiki software.
The design of a discussion wiki would consist in defining:
- its structure
- the format of each discussion
- navigation in the set
- cross-referencing among discussions
Navigation and cross-referencing can be based on the relatedness of the discussions.
- each discussion has a list of predecessors it took inspiration from
- each discussion has a list of successors it inspired
Data of a discussion
header:
- id # an integer would do
- label # used as title and in referencing
- creation date
- last modif date
- predecessors # list of inspirational predecessor discussions
- successors # list of discussions inspired by this discussion
- contributors # list of contributors
contributions:
- id # contributor id
- contents # as inserted by each contributor
- hierarchy # explicit, indented
Real-life example 1, flavor 1:
Discussion 346
Questions about security
Created
2004.06.08
Modified
2004.06.08
Predecessors
Undefined
Successors
Undefined
Contributors
Serge
Serge Orlov somb at pobox.ru
Mark
Mark Hahn mark at prothon.org
Ben
Ben Collins bcollins at debian.org
| Serge:
| 1. Does it handle memory allocation limiting? It seems to be
| not very difficult for Prothon code but what about C extensions,
| that you use malloc? malloc prohibited?
|
| | Mark:
| | Security is only aimed at Prothon language users. Anyone writing in C
| | language could obviously crash the entire system with no problem.
| |
| | | Serge:
| | | Sorry about being not clear but when I wrote "C extension" I meant
| | | C module like Re or SQLite. You can handle things like Prothon
| | | expression [0]*10000000000000 but what about re.compile("some arcane
| | | regular expression exploing dark corners of complicated re algorithm").
| | |
| | | | Ben:
| | | | That's brokeness in the regex library and/or implementation. Just like
| | | | the old glob problem, it's not really us that needs to fix it, and you
| | | | surely can't account for all problems this way.
| | |
| | | | Mark:
| | | | So you are not talking about the Prothon object security feature I put in
| | | | that controls user acess. You are talking about program robustness due to
| | | | error handling, right?
| | | |
| | | | | Serge:
| | | | | Yes. But also situations when you want to serve 10000 users and
| | | | | typical requests take 1Kb. Where as a malicious request can take 100Kb
| | | | | without exploiting any bugs only because you didn't anticipated it.
| | | |
| | | | Prothon has no control over what module programmers code in C. They are
| | | | responsible for the reliability of their code.
| | | |
| | | | | Serge:
| | | | | That means that before Re is thoroughly audited you can't use it for
| | | | | importing where security is very important. I'm not sure about Windows but
| | | | | on Unix you can restrict how much memory a process will take. Seems like
| | | | | processes are more robust way to deal with C code. For example they
| | | | | are used in vsftpd (Very Secure ftp Daemon) http://vsftpd.beasts.org/DESIGN
| | | | | Granted you may not want such a robust architecture, because it's not
| | | | | fast on Windows for example. But on Unix it's better than threads.
| | | | | Also what about Prothon itself? Doesn't it has bugs in parser code?
| | | | | I mean, in C, bugs are everywhere :) And processes deal with them better than
| | | | | threads.
Real-life example 1, flavor 2:
Serge:
1. Does it handle memory allocation limiting? It seems to be
not very difficult for Prothon code but what about C extensions,
that you use malloc? malloc prohibited?
Mark:
Security is only aimed at Prothon language users. Anyone writing in C
language could obviously crash the entire system with no problem.
Serge:
Sorry about being not clear but when I wrote "C extension" I meant
C module like Re or SQLite. You can handle things like Prothon
expression [0]*10000000000000 but what about re.compile("some arcane
regular expression exploing dark corners of complicated re algorithm").
Ben:
That's brokeness in the regex library and/or implementation. Just like
the old glob problem, it's not really us that needs to fix it, and you
surely can't account for all problems this way.
Mark:
So you are not talking about the Prothon object security feature I put in
that controls user acess. You are talking about program robustness due to
error handling, right?
Serge:
Yes. But also situations when you want to serve 10000 users and
typical requests take 1Kb. Where as a malicious request can take 100Kb
without exploiting any bugs only because you didn't anticipated it.
Prothon has no control over what module programmers code in C. They are
responsible for the reliability of their code.
Serge:
That means that before Re is thoroughly audited you can't use it for
importing where security is very important. I'm not sure about Windows but
on Unix you can restrict how much memory a process will take. Seems like
processes are more robust way to deal with C code. For example they
are used in vsftpd (Very Secure ftp Daemon) http://vsftpd.beasts.org/DESIGN
Granted you may not want such a robust architecture, because it's not
fast on Windows for example. But on Unix it's better than threads.
Also what about Prothon itself? Doesn't it has bugs in parser code?
I mean, in C, bugs are everywhere :) And processes deal with them better than
threads.
Flavor 2 loses in the case of a mid-paragraph insertion, as tab width could play with alignment clarity.
Using spaces instead of tabs loses too, in case of viewing text with non-proportional font.
To see how it scales up, here is real real-life example 2:
Discussion 403
Class proposal 2
Created
2004.06.23
Modified
2004.06.24
Predecessors
397 Class proposal
Successors
404 What is "class behavior"
Contributors
Mark
Mark Hahn mark at prothon.org
Chris
Christian Tismer tismer at stackless.com
Greg
Greg Ewing greg at cosc.canterbury.ac.nz
Paul
Paul Prescod paul at prescod.net
Serge
Serge Orlov somb at pobox.ru
Michael
Lucius, Michael mlucius at concordefs.com
| Mark:
| I hope you'll forgive all these postings, but I don't have a day job like
| the rest of you :-)
|
| I've got a two-tier class proposal that is more concrete than my old one.
| It is mostly based on Serge's proposal but I feel Paul's thinking is
| incorporated. As always feel free to shoot holes in it.
|
| | Greg:
| | This looks interesting, but something doesn't seem quite right about
| | it. If class methods are to be methods of the class in the same way
| | that instance methods are methods of the instance, they should be kept
| | in the instance-method-area of the class's class, not in the class.
| |
| | Classes in this proposal don't seem to have classes. In other words,
| | they're not themselves objects within their own paradigm.
| |
| | | Mark:
| | | Would having them be objects in the prototype paradigm be good enough? We
| | | need to think through some usage cases.
| | |
| | | I think one of the advantages of this class proposal is it's simplicity and
| | | how it ties in with the simple prototypes. I'd love to keep that
| | | simplicity.
| |
| | In this
| | respect, they're more like old-style Python classes. To a Python
| | person, this will seem like a backward step.
| |
| | | Serge:
| | | The missing link is type. I've been pitching "right" types
| | | since I realized how types in 1-tier system should work,
| | | http://www.prothon.org/pipermail/prothon-user/2004-June/001805.html
| | | later I realized the same applies to 2-tier systems.
| | |
| | | Every class should have Type type:
| | |
| | | | Mark:
| | | | If this is true, then things are getting too complex and I don't want to add
| | | | classes.
| | | |
| | | | I'm going to continue to search for the holy grail of simple classes that
| | | | work with prototypes.
| | |
| | | class Type:
| | | class:
| | | type_ = Type
| | | ....
| | |
| | | class X:
| | | class:
| | | type_ = Type
| | | instance:
| | | type = X
| | |
| | | Besides all new class proposals break except statement, if
| | | you try to write
| | |
| | | except X:
| | |
| | | it won't work because except is walking prototype chain and
| | | the chain will lead you to X.instance_ prototype which is
| | | not equal to X. Types solve that.
| | |
| | | | Mark:
| | | | Actually in my last proposal Klass was the prototype of the instance
| | | | Klass(). I had thought that through. That was one of the reasons I turned
| | | | your proposal inside out.
| |
| | | Mark:
| | | I knew someone would ask for metaclasses. :-)
| | |
| | | I"ll see if I can fix my proposal to add this property. Feel free to help
| | | me out here.
| | |
| | | | Serge:
| | | | metaclasses:
| | | |
| | | | class X(Y):
| | | | class(myMetaClass):
| | | | ...
| | | | instance:
| | | | ...
| | | |
| | | | By default myMetaClass is Type. It is also equal to:
| | | |
| | | | class X(Y):
| | | | class:
| | | | type_ = myMetaClass
| | | | ...
| | | | instance:
| | | | ...
|
| There will be a class object for each class.
|
| | Paul:
| | I have mixed feelings about having BOTH prototypes AND classes in the
| | same language...
| |
| | | Mark:
| | | Can you elaborate on your concerns? Is it confusion? Performance? Lack of
| | | focus?
| | |
| | | | Paul:
| | | | Lack of focus. Lack of simplicity. The argument in favor of prototypes
| | | | was that they were simpler and now we are importing the complexity of
| | | | classes (and soon metaclasses) on top of prototypes.
| | | |
| | | | | Mark:
| | | | | I am convinced that metaclassses are not needed since classes have
| | | | | prototypes. This whole class proposal needs a lot more work. It needs more
| | | | | work to become simpler and more contract-like.
| | | |
| | | | Every time people
| | | | create a type they'll have to decide whether to make it a class or
| | | | prototype. And based on what criteria: just whether they are comfortable
| | | | with one or the other? There will be no code consistency.
| | | |
| | | | | Mark:
| | | | | The behavior of the two are so closely linked that once they are defined
| | | | | there should be no real difference.
| | | |
| | | | Which will be the standard model used by the standard library?
| | | |
| | | | | Mark:
| | | | | If and when we ever get any Prothon language std libs, they would be
| | | | | specified with classes. (I am assuming more contract-like).
| | |
| | | I've already given my arguments for why I want classes included,
| | | even though I personally would use naked prototypes for most applications.
| | | I find no conflict between prototypes and classes just as Python found no
| | | conflicts between functions and methods.
| | |
| | | | Paul:
| | | | Functions and methods do different things. They aren't just there to
| | | | make different people feel comfortable.
| | | |
| | | | | Mark:
| | | | | I take back what I said. If classes are implemented properly as a contract
| | | | | type thing I would use them.
|
| This class object will have
| the traditional OOPS meaning of blueprint for an instance of the class. It
| will be implemented as a prototype for the instance objects with methods
| that instances delegate to. It's prototype list will point to other classes
| giving the normal class inheritance heirarchy.
|
| | Michael:
| | I assume you mean the class object will have the same protoypes as the
| | instance object.
| |
| | | Mark:
| | | No the instance object would have only one prototype, which is the class
| | | object. Then the class object would have the references to the other
| | | classes.
| |
| | This means the class object will be an extension of the same prototypes as
| | the instance object and so the class instance will not have access to the
| | instance's methods/data. Or is 'self' going to be set to be the instance?
| |
| | | Mark:
| | | Self will always refer to the actual instance object.
|
| There will also be a factory object for each class. Ironically this object
| will represent the class itself instead of the instances even though it is
| not the "class object". Class methods and class variables will be stored
| here especially the "call_" method that implements the "Class()"
| constructor. I will explain how this works in a moment. This gives a
| seperate namespace for class attributes.
|
| | Paul:
| | What about inheritance between class attributes? Is there any?
| |
| | | Mark:
| | | Good question. By definition they would have prototypes, but these would
| | | only matter if you looked up a missing attribute of the attribute. I would
| | | assume this wouldn't happen so it would be a non-issue. Methods might have
| | | doc strings and stuff, but nothing that should invoke inheritance.
| | |
| | | | Paul:
| | | | class foo:
| | | | class:
| | | | x = 5
| | | |
| | | | class bar(foo):
| | | | class:
| | | | pass
| | | |
| | | | Does bar.x do anything? Does bar().x do anything?
| | | |
| | | | | Mark:
| | | | | Oh you meant data inheritance. Yes data would be inherited also. That is a
| | | | | side effect of classes being implemented on prototypes. This will not
| | | | | affect code ported over because code would not try to access such vars.
|
| If the Class object is called "Klass", then the factory object would be
| stored in it's attribute as "Klass.class".
|
| | Paul:
| | I wouldn't call it a factory because the overall class is the factory.
| | It is really the container for class attributes.
| |
| | | Mark:
| | | I only called it a factory in this message. Nothing is called factory in
| | | the objects themselves. I'll stop calling it that. (But Klass.class is the
| | | object that has the call_() method that creates the instances so I thought
| | | that would make it the factory).
| | |
| | | | Paul:
| | | | Well maybe you are right.
|
| Access to class methods inside a
| normal method or inside a class definition would be through the normal
| "Klass.class.method()" or through new syntax sugar that makes use of the
| class keyword as a prefix "class.method()".
|
| | Michael:
| | How about the other way around? Is there a special way for class methods to
| | access 'normal' methods that are defined in the instance or is this not
| | allowed? Or must class methods access other class methods in a special way?
| |
| | | Mark:
| | | Now you are getting into an area that is screwed up in my proposal. In
| | | Python you can say Klass.method() to access an instance method but that
| | | wouldn't work in my proposal,
| | |
| | | | Greg:
| | | | If you insist on that working, I think it pretty much
| | | | forces class attributes and instance methods to be in
| | | | the same namespace.
| | |
| | | | | Mark:
| | | | | So are dual namespaces a good thing or a bad thing?
| | | | |
| | | | | I was confusing having classes and working like Python. How do you think
| | | | | classes should work in Prothon, if at all?
| | |
| | | even though instance methods are attributes of
| | | Klass. My weird lookup rule would screw that up.
|
| Likewise Class variables could
| be stored as "Klass.class.x" or using the new prefix "class.x".
|
| The interpreter would have special knowledge of attributes named "class."
| This is not surprising since keywords aren't usually allowed as attribute
| names. In all attribute lookups a special rule will be used:
|
| --- "class" attribute special lookup rule ---
|
| --- When an attribute is first being looked up in an immediate object, not
| an ancestor, and a attribute named "class" exists in the immediate object,
| that class attribute object is used in the object's place for the
| lookup. ---
|
| | Paul:
| | What does "first being looked up" mean? What exactly is the order of
| | lookup? Klass.class.foo and then Klass.foo? Or just Klass.class.foo?
| |
| | | Mark:
| | | Whenever you look up an attribute, you first look it up in an immediate
| | | target object and you only start looking at the prototype chain prototypes
| | | if the attribute is not found in the immediate object. So "first looked up"
| | | means the first search in the target immediate object. In "obj.attr", obj
| | | is the immediate object that is searched when the attribute is "first looked
| | | up".
| | |
| | | Klass.method() # first lookup in Klass -> Klass.class
| | | kls = Klass() # first lookup in Klass -> Klass.class
| | | kls.method() # first lookup in kls fails, second -> Klass
| | |
| | | As you can see, the delegation from the kls instance in the last example
| | | causes the lookup in Klass to not be "the first lookup" so the rule is not
| | | invoked and the instance kls gets the normal instance method.
| | |
| | | Darn, I just found a flaw in my scheme. When one says Klass.method() in
| | | order to do a directed call of an instance method, they will get
| | | Klass.class.method(), not the Klass.method() like they should. I need to
| | | work on this. Once again directed method calling is busting my chops.
| |
| | Do the instance objects inherit the "class" at all? Or is it just gone?
| |
| | | Mark:
| | | I'm not sure what you mean. The instances inherit the methods from their
| | | Class object ("Klass" in the example). They do not inherit anything from
| | | "Klass.class". (We need to come up with names for these objects since you
| | | took away the factory name).
| | |
| | | | Paul:
| | | | Klass.class exists as an attribute.
| | | | Does Klass().class exist as an attribute? Is it identical to:
| | | | Klass().protos_[0].class
| | | |
| | | | | Mark:
| | | | | Klass() is the instance and it has no attributes when first created.
| | | | | However Klass().class will work yielding the "factory" object
| | | | | (Klass().protos_[0].class) through data inheritance since Klass() has one
| | | | | prototype, namely Klass.
| |
| | One of the nice things about Python is that str_ and call_ for classes
| | do the "right thing" by default no matter what happens for instances.
| | Does your proposal have that feature?
| |
| | | Mark:
| | | If I understand you correctly you mean that Klass().class.call_() should
| | | create an instance of Klass by default and Klass.class.str_() should print
| | | the name of the class even if no methods are defined in a class: section.
| | | Yes, the code proposal at the end of the message that I stole from Serge
| | | does exactly that. I don't know if I made it clear but that code is
| | | actually implemented by the interpreter for all classes, so it will by
| | | default create instances and print class names.
|
| | Michael:
| | So under certain circumstances a special 'class scope' is inserted at the
| | head
| | (or near the head) of the scope chain?
| |
| | > class Klass(Parent1, Parent2):
| | > """Class document string"""
| | >
| | > class:
| |
| | Can 'class:' be used in an 'object' block or only in a 'class' block?
| |
| | | Mark:
| | | I would think only in a class block.
| |
| | Here is my proposal:
| |
| | When defining an Object Klass:
| | add a function class_() that defines an inner class.
| | This inner class has Klass as its prototype and defines call_(), str_()
| | and whatever else the class needs and returns that object. This inserts the
| | 'class scope' as your proposal does by using existing
| | functionality and does not require anything special be done in the language.
| |
| | Then you have:
| | KlassFactory = Klass.class_() # returns Klass object that acts like
| | a class
| | newKlass = KlassFactory() # uses call_() from 'class scope'
| | KlassFactory.str_() # uses str_() fron 'class scope'
| |
| | | Mark:
| | | Your solution solves the dual namespace problem in a much cleaner way than
| | | mine. It doesn't solve the problem of how to allow call_ and str_ to be
| | | used at the same time for both classes and instances though. Mine doesn't
| | | either since I found out my solution is broken. Without such a solution
| | | both of our proposals are just programming techniques, not language
| | | features.
| |
| | Note that KlassFactory has access to all Klass methods/data just like
| | any instance has access to its prototype(s) methods and data.
| |
| | However the object returned by class_() can:
| | Override any Klass methods (e.g. call_() str_())
| | Add any new data/methods it needs
| | Intercept method calls to do something special
| |
| | Klass() will do want you want if call_() for the instance is defined as:
| | def call_(args):
| | return (self.class_())(args) # not sure of the syntax!
| |
| | Of course this behaviour can be modified by the programmer.
| |
| | Klass.str_() # invokes instance str_()
| | Klass.class_().str_() # invokes class str_()
| | KlassFactory.str_() # also invokes class str_()
| |
| | When defining a class Klass:
| | add a function object_() which defines the behavior as an object instance.
| | So object_() is like the above class_() but behaves like a regular instance.
| | This means that the default behaviour is class behaviour and
| | Klass.object_() returns an object that has put instance methods/data at
| | the head of the scope chain.
| |
| | This introduces a difference between object and class.
| | object: acts like an instance by default, but can be used as a class if
| | desired.
| | class: acts like a class by default, but can easily used as an instance.
| |
| | I think this leverages the ability of protoypes to delegate automatically
| |
| | | Mark:
| | | This I don't understand. It seems to me you are just interchanging the
| | | names. The behaviour of your Class inside an object is identical to your
| | | object inside a Class.
|
| This rule is the only special interpreter hook needed for class behavior.
| It will redirect class attribute lookups to the class factory object and
| allow instance method calls to continue to go to the class object. Thus the
| construcor call "Klass()" will work using "Klass.class.call_()" and "kls.()"
| will work from an instance kls using "Klass.call_()".
|
| Now for the syntax. This is pretty much just the object structure outlined
| above. Here is an example:
|
| class Klass(Parent1, Parent2):
| """Class document string"""
|
| class:
| name = 'KlassType'
| instanceCount = 0
| def str_():
| print '<class Klass>'
| def count():
| return instanceCount
|
| | Chris:
| | Eeek: Does this then still work?
| |
| | | Mark:
| | | Well actually nothing works yet :-)
| |
| | class A(parents):
| | """__doc__"""
| |
| | class localClass(otherParents):
| | pass # whatever you like here
| |
| | So a class statement without a class name is a class section?
| |
| | | Mark:
| | | Yes. I was a bit concerned about reusing the class keyword but I think it
| | | is readable and unambiguous. I can always make up a new keyword but the
| | | class one fits so well.
| |
| | Just wanted you to be aware of class nesting. :-)
| |
| | | Mark:
| | | I wasn't aware of class nesting. I knew about nested functions. What
| | | happens with nested classes? Is the inner one just an attribute of the
| | | outer one?
| | |
| | | | Greg:
| | | | In Python, yes. In Prothon there may be some implications for
| | | | scoping.
| | |
| | | If so, then I have to think about how the nested objects work
| | | with the new nested class/factory objects.
|
| def init_(x, y):
| self.x = x
| self.y = y
| class.instanceCount += 1
|
| def str_():
| print '<Klass:'+self.x+'/'+self.y+'>'
|
|
| Note that I really get a lot of use out of the class keyword in this
| proposal! :-)
|
| This is just like the Python class statement except that there is an
| optional class section with a compound-body of class methods and class
| variables. The class variable "name" would actually be produced
| automatically without the explicit statement here.
|
| This is inside-out from serge's proposal which had the class object inside
| the factory object. I think my ordering is important because we need to be
| able to use the directed "Klass.method()" call syntax which wouldn't work
| with the factory as the class name.
|
| Serge's implementation code will still work with some tweaking:
|
| object Klass(Parent1, Parent2):
| """Class document string"""
| <outer class: compound-block>
| object class:
| name = "{KlassName}Type"
| def call_(*args, **kwargs):
| instance = newObject(self.container_) #
| container == Klass
| instance.init_(*args, **kwargs)
| return instance
| def str_():
| return name
| <inner class: compound-block>
|
| Note that the Klass.class "name", "call_", and "str_" attributes can be
| overriden in the inner class block. class.container_ is automatically
| created by the compiler to point back to the Klass object.
|
| Comments? Votes?
| ______________________________________________________________________
| Mark appended on 2004.06.24:
|
| First of all, let me say that this new scheme with the attribute lookup
| interpreter rule has a fundamental problem I don't think can be overcome.
| Basing behavior on how the attributes are looked up falls apart when you
| start to consider all the method calling requirements. So arguing about
| this proposal is somewhat academic, although not useless.
|
| I have also decided that my proposal is too complex ansd I want to make it
| more "contract-like". Or you could consider it more "interface-like" or
| "adapter-like".
Laurent Dube