View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000061 | LDMud 3.5 | LPC Compiler/Preprocessor | public | 2004-05-18 19:31 | 2011-02-14 16:46 |
Reporter | Assigned To | ||||
Priority | normal | Severity | feature | Reproducibility | N/A |
Status | new | Resolution | open | ||
Summary | 0000061: 'use' directive to replace most uses of prototypes. | ||||
Description | Sometimes it is desirable to let a module "/std/module/room" use functions from a different module "/std/module/props" with directly inheriting it. The traditional solution is to use prototypes, which can make debugging more difficult. A directive use "/std/module/props"; could import all function declarations from "/std/module/props" as if defined by prototypes. Possible extended uses: - The imported declarations would be flagged with their origination, so that any collision by another 'use' or explicite prototype could be detected. - The name of "/std/module/props" could be stored in the program, so if at runtime an unresolved crossreference is detected, the compiler could give hints as to what could be missing. This can't be done at load time as in this case "/std/module/room" is necessarily incomplete, yet is loaded during the inheritance handling. Other names for 'use' could be used, as long as they are different enough to 'inherit'. This excludes 'import', but 'require' could work (it has slightly different implied semantics, though). | ||||
Additional Information | Bardioc suggested a version of extern <prototype> by "<module>"; which could be added for ad-hoc uses. The attached file implements the grammar for these. | ||||
Tags | No tags attached. | ||||
Attached Files | bardioc.diff (1,466 bytes)
--- lex.c 2004-05-07 03:34:25.000000000 +0000 +++ /ETMSUsers4/lduening/tmp/lex.c 2004-05-18 14:12:37.000000000 +0000 @@ -494,6 +494,8 @@ , { "virtual", L_VIRTUAL } , { "void", L_VOID } , { "while", L_WHILE } + , { "by", L_BY } + , { "extern", L_EXTERN } }; /*-------------------------------------------------------------------------*/ --- prolang.y 2004-05-01 04:04:23.000000000 +0000 +++ /ETMSUsers4/lduening/tmp/prolang.y 2004-05-18 14:12:33.000000000 +0000 @@ -5152,6 +5152,8 @@ %token L_VIRTUAL %token L_VOID %token L_WHILE +%token L_BY +%token L_EXTERN /* Textbook solution to the 'dangling else' shift/reduce conflict. */ @@ -5525,6 +5527,32 @@ #endif /* USE_NEW_INLINES */ } + | L_EXTERN type optional_star L_IDENTIFIER + + { + $2.typeflags |= $3; +#ifdef USE_NEW_INLINES + def_function_typecheck($2, $4, MY_FALSE); +#else /* USE_NEW_INLINES */ + def_function_typecheck($2, $4); +#endif /* USE_NEW_INLINES */ + } + + '(' argument ')' + + { +#ifdef USE_NEW_INLINES + def_function_prototype($7, MY_FALSE); +#else /* USE_NEW_INLINES */ + def_function_prototype($7); +#endif /* USE_NEW_INLINES */ + } + + L_BY string_constant ';' + + { + } + | type name_list ';' /* Variable definition */ { if ($1.typeflags == 0) | ||||
|
Ok, I can imagine quite a number of applications for this as well. The one drawback I see: using #include and prototypes you can select specific prototypes to be declared, which might be good idea, if you need only a few out of hundreds. But as you don't have to use this feature... I guess we have anyway some stuff to do in the compiler, so moving to 3.5. We can decide then if we want to implement it. |
|
Doesn't this try to solve the same problem that virtual inherits were supposed to solve? Assuming that virtual inherits work why not virtual inherit "/std/module/props" instead of 'use' it? |
|
Mhmm. Yes, you probably can solve these problems with virtual inherits. With use or include you get a compilable, but mostly not executable object only for inheriting it (which is often completely fine). With the virtual inherits it seems to be a much more complicated process for compiling and for resolving the functions and there are limitations like 'in case of replace_program() a program containing virtually inherited variables must be inherit first'. And I might be wrong, but I have something in memory about merging or resolving the wrong variables and functions in complex trees. Some time ago we had 3-4 objects virtually inheriting and we had problems re-loading them and part of the ineritance tree without errors, so we fell back to the 'include the right prototypes' method (Im sorry, at that time I was not involved here, so I did not report that.) Or maybe it is a documentation issue which causes my disfavor. I don't know if there is any difference in memory consumption or execution time between both methods. |
|
The memory problem (double variables) is exactly the problem that we wanted to address with this. If you mess up the virtual inheritance, you end up with an o-file that includes multiple values for the same variable. Consider this example: A <- B <- C A <- D <- C So both B and D inherit A. If you do NOT virtually inherit A in B and D, you get twice the variables of A, thus a method call in B that modifies the variables of A will not be reflected by a query method in D that queries the variables of A. Hope that I made my point clear here. You are right, prototyps are completely fine, but if you change the fucntion definition you have to adapt all prototypes, thats why the extern definition came to my mind. |
|
I would support this. Slightly offtopic: Is there a way to get "use" to include struct definitions into multiple files without directly inheriting the file defining the struct? (as a sort of virtual inheritance for struct definitions). Sharing struct definitions in a complex inheritance tree requires the definition to be inheritted multiple times. |
|
xtian as far as I know, and I talked about this with Lars structs are compile time structures that are program-based, thus if you define a structure foo in file a.c and in file b.c, they are NOT the same at run time, leading sometimes to weird errors like struct foo #33434 vs. struct foo #343434 To actually make "use" working for structures the need to be shared among programs, and the defining program would need to be reloaded in case it is gone. I'm not sure how much work this involves. |
|
Structs are shared by defining them in a common inherit in LPC. The same diagram as above applies, where A defines the struct: A <- B <- C A <- D <- C B and D can exchange data typecast as their shared struct over function calls (type-safe btw). But C needs to have the same inherit (A) twice. |
|
The problem is not the data typecast, but mainly the access to struct members ... the only thing a "use" for structs would be useful in your way is that a function prototyp will not lead to a compile error ... but in case a method uses the struct and accesses a member, the full definition is necessary to validate the member exists (and I would not want to pass on this). I doubt that the only knowledge about the struct's name is useful, so I would vote for a maybe changed structure handling that introduces an own global namespace for structs rather than a program-based approach like it is now. |
|
Gnomi suggest quite a time ago, that we should think of improving virtual inherits as an alternative. So I will relate some issues of virtual inherits with this issue to have an idea, what we should think of in this case. |
|
As a comment: it still sounds easier to me to implement a 'use' which just imports all the public and protected/static functions as prototypes into the newly compiled program than 'fixing' the virtual inheritance. Not only in terms of code, but also conceptually. That said, I would be happy to have both. One method results in a usable/cloneable object, the other just compiles, is smaller and can be used for inheritance... |
Date Modified | Username | Field | Change |
---|---|---|---|
2004-05-18 19:31 |
|
New Issue | |
2004-05-18 19:31 |
|
File Added: bardioc.diff | |
2009-01-08 06:20 | zesstra | Project | LDMud 3.3 => LDMud 3.5 |
2009-01-08 06:25 | zesstra | Note Added: 0000865 | |
2009-01-08 07:30 | Gnomi | Note Added: 0000872 | |
2009-01-08 08:17 | zesstra | Note Added: 0000874 | |
2009-01-15 14:04 | Bardioc | Note Added: 0000893 | |
2009-01-16 12:22 | _xtian_ | Note Added: 0000905 | |
2009-01-19 11:12 | Bardioc | Note Added: 0000934 | |
2009-01-20 05:52 | _xtian_ | Note Added: 0000935 | |
2009-01-21 12:25 | Bardioc | Note Added: 0000936 | |
2009-10-02 03:02 | zesstra | Note Added: 0001399 | |
2009-10-02 03:02 | zesstra | Relationship added | related to 0000233 |
2009-10-02 03:03 | zesstra | Relationship added | related to 0000151 |
2009-10-02 03:03 | zesstra | Relationship added | related to 0000153 |
2009-10-02 03:03 | zesstra | Relationship deleted | related to 0000151 |
2009-10-02 03:04 | zesstra | Relationship added | related to 0000152 |
2011-02-14 16:46 | zesstra | Note Added: 0001986 |