Waldek Hebisch wrote:
Frank Heckenbach wrote:
Yes, it refers to a `System' unit. But built-in identifiers are not declared in a `System' unit (which would violate EP where `System' is not a special name), but at "level 0" as Chuck calls it (I don't know if the standard has a term for it, I think it just talks of "required procedures and functions" and that they have a "definingÂpoint not contained by the programÂblock").
One could consider whether to add such a facility, but especially for built-in routines with special syntax (such as `WriteLn') this will probably not be easy, so I don't really like the idea.
Special syntax make this feature valuable: there is no way to emulate built-in syntax via wrappers. Also, it is one of biggest remaining BP incompatibilities.
Concerning implementation: I do not see how to do really nice implementation. But IMHO there are two reasonbly easy ways.
One is to check for "magic" module name in the lexer and then do a lookahead for dot and routine name.
BTW, not only routines, also constants such as `MaxInt', types such as `Integer' and variables such as `Output' (which is particularly strange given the standard properties of `Output', being a program parameter or imported from `StandardOutput').
If there is a match generate apropriate "builtin" token. Of course, one needs an extra state machine in the lexer to avoid false positives. And extra logic in the parser to reject such names in places were qualified names are not allowed
Or perhaps leave the last part to the parser, i.e. let the lexer return LEX_BUILTIN_MODULE (or whatever), and in the parser recognize `LEX_BUILTIN_MODULE '.' p_New' where `p_New' is allowed.
However, this would conflict with our use of a `System' unit (module) to define some really ugly BP stuff I don't want to build in.
Another way is to put GLR parser to an extreme: remove special treatment for builtins from the lexer and generate both normal parse and a parse as a builtion. Then use merge action to choose correct one.
As I write this yet another idea: parse everthing like `writeln' (it seem to be the most general form of a call)
Syntactically yes. But `New' and `Dispose' with object con-/destructors also require special handling while parsing(!) (since con-/destructor names must be made visible for the second argument, see current_structor_object_type).
`Addr' and `Assigned' do because they need to suppress function calls (though we might be able to get rid of this special case if we reorganize function calls as discussed recently).
And don't forget `System.Fail', `System.Continue', `System.Break' and `System.Exit'. (Yes, BP does allow these!) (Well, actually, the first three are implemented like normal built-ins in GPC, but `Exit' not because of new the UCSD/Mac Pascal syntax, also `Return' not (not BP compatible, but to be consequent ...)
AFAICS, these problems would also preclude the GLR suggestion since such things as `Addr' are syntactically the same. So one at best make two equivalent parse rules and "merge" them (which I'd consider almost an abuse of GLR).
And if, I think we'd have to use dprec rather than merge since merge first evalutes both variants which might lead to spurious errors.
and then check in sematic actions if the routine identifier resolve to built-in. If no then reject calls using extended syntax. Structured value constructors work in similar way. Such approach can even make the compiler simpler then it is now.
If we get rid of all the special cases I mentioned, perhaps, but ATM I don't see how we could.
Frank