www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - pegged: non safe semantic actions

reply Dmitry Ponyatov <dponyatov gmail.com> writes:
What's wrong with using non safe actions which creates and 
modifies some external objects?

```D
class Layer {
     int index;
     string name;
     this(int index, string name) {

class SignalLayer : Layer {
class UserLayer : Layer {

class PCB {
     Layer[] layer;

PT _deflayer(PT)(PT p) {
     auto index = to!int(p.matches[0]);
     switch (p.matches[2]) {
     case "signal":
         pcb.layer ~= new SignalLayer(index, p.matches[1]); break;
     case "user":
         pcb.layer ~= new UserLayer(index, p.matches[1]); break;
     default:
         break;
     }
     return p;
}

mixin(grammar(`
     parser:
         kicad_pcb <  :l :'kicad_pcb' verzion host general page 
layers
         layers    <  :l :'layers' (deflayer {_deflayer})+ :r
         deflayer  <  :l unum layer ('signal'|'user') :r

```
```
../.dub/packages/pegged/0.4.9/pegged/pegged/peg.d(3049,19): 
Error: ` safe` function `pegged.peg.action!(wrapAround, 
_deflayer).action` cannot call ` system` function 
`kicad._deflayer!(ParseTree)._deflayer`
src/kicad.d(27,5):        which calls `kicad.SignalLayer.this`
src/kicad.d(68,4):        `kicad._deflayer!(ParseTree)._deflayer` 
is declared here
src/kicad.d-mixin-83(219,289): Error: template instance 
`pegged.peg.action!(wrapAround, _deflayer)` error instantiating
src/kicad.d-mixin-83(932,7):        instantiated from here: 
`Genericparser!(ParseTree)`
../.dub/packages/pegged/0.4.9/pegged/pegged/peg.d(544,20): Error: 
none of the overloads of `layers` are callable using argument 
types `(GetName)`
src/kicad.d-mixin-83(215,23):        Candidates are: 
`kicad.Genericparser!(ParseTree).Genericparser.parser.layers(ParseTree p)`
src/kicad.d-mixin-83(234,23):                        
`kicad.Genericparser!(ParseTree).Genericparser.parser.layers(string s)`
../.dub/packages/pegged/0.4.9/pegged/pegged/peg.d(1598,24): 
Error: template instance `pegged.peg.getName!(layers)` error 
instantiating
src/kicad.d-mixin-83(183,436):        instantiated from here: 
`wrapAround!(named, layers, named)`
src/kicad.d-mixin-83(932,7):        instantiated from here: 
`Genericparser!(ParseTree)`
```
Dec 08 2023
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Friday, December 8, 2023 10:13:21 AM MST Dmitry Ponyatov via Digitalmars-d-
learn wrote:
 What's wrong with using non safe actions which creates and
 modifies some external objects?

 ```D
 class Layer {
      int index;
      string name;
      this(int index, string name) {

 class SignalLayer : Layer {
 class UserLayer : Layer {

 class PCB {
      Layer[] layer;

 PT _deflayer(PT)(PT p) {
      auto index = to!int(p.matches[0]);
      switch (p.matches[2]) {
      case "signal":
          pcb.layer ~= new SignalLayer(index, p.matches[1]); break;
      case "user":
          pcb.layer ~= new UserLayer(index, p.matches[1]); break;
      default:
          break;
      }
      return p;
 }

 mixin(grammar(`
      parser:
          kicad_pcb <  :l :'kicad_pcb' verzion host general page
 layers
          layers    <  :l :'layers' (deflayer {_deflayer})+ :r
          deflayer  <  :l unum layer ('signal'|'user') :r

 ```
 ```
 ../.dub/packages/pegged/0.4.9/pegged/pegged/peg.d(3049,19):
 Error: ` safe` function `pegged.peg.action!(wrapAround,
 _deflayer).action` cannot call ` system` function
 `kicad._deflayer!(ParseTree)._deflayer`
 src/kicad.d(27,5):        which calls `kicad.SignalLayer.this`
 src/kicad.d(68,4):        `kicad._deflayer!(ParseTree)._deflayer`
 is declared here
 src/kicad.d-mixin-83(219,289): Error: template instance
 `pegged.peg.action!(wrapAround, _deflayer)` error instantiating
 src/kicad.d-mixin-83(932,7):        instantiated from here:
 `Genericparser!(ParseTree)`
 ../.dub/packages/pegged/0.4.9/pegged/pegged/peg.d(544,20): Error:
 none of the overloads of `layers` are callable using argument
 types `(GetName)`
 src/kicad.d-mixin-83(215,23):        Candidates are:
 `kicad.Genericparser!(ParseTree).Genericparser.parser.layers(ParseTree p)`
 src/kicad.d-mixin-83(234,23):
 `kicad.Genericparser!(ParseTree).Genericparser.parser.layers(string s)`
 ../.dub/packages/pegged/0.4.9/pegged/pegged/peg.d(1598,24):
 Error: template instance `pegged.peg.getName!(layers)` error
 instantiating
 src/kicad.d-mixin-83(183,436):        instantiated from here:
 `wrapAround!(named, layers, named)`
 src/kicad.d-mixin-83(932,7):        instantiated from here:
 `Genericparser!(ParseTree)`
 ```
Since I've never used pegged, I can't really comment on the specific semantics of what you're trying to do. However, any function which is marked as safe cannot call any functions that are system. So, if pegged is marking a function as safe, and it is then trying to call your function, your function then needs to be safe or trusted, regardless of what it's actually doing, which means that you need to then make it so that your function either isn't doing anything that's system so that it can be safe, or you need to vet what it's doing to make sure that it's actually memory-safe in spite of the fact that the compiler can't verify it, in which case, you would need to mark it as trusted. The default for functions is system, and none of the code you've shown is marked with safe. Templated functions and functions which return auto will have their attributes inferred, which includes safe, so if _deflayer is not calling any system functions or doing any operations which are system, it will be inferred as safe. However, it looks like the constructors that it's calling are not marked with safe and are not templated. So, they will not infer their attributes and will be system, which will in turn mean that _deflayer gets inferred as system. And if pegged is calling _deflayer from code that's marked with safe, then you're going to get a compilation error. So, based on what I can see here, it looks like you need to be marking your functions with safe where you can, and if any of your code is doing stuff that isn't guaranteed to be memory-safe (and thus can't be safe), then you'll need to make sure that what it's doing is actually memory-safe (in spite of the fact that the compiler can't guarantee it) and mark it with trusted to indicate that you've verified it, and then safe code can call it. - Jonathan M Davis
Dec 08 2023