Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler crash in mixset processing and activation #1467

Open
TimLethbridge opened this issue Jun 27, 2019 · 6 comments

Comments

Projects
None yet
2 participants
@TimLethbridge
Copy link
Member

commented Jun 27, 2019

The following code results in a compiler crash. The use statements at the end are OK if only f1, f2 and f3 are activated. But f4 and/or f5 result in compiler crash. This example is in the user manual in the traits with associations section (except that there are no use statements). It is also in a recently submitted paper.

interface I1 { void m1(); }
  
trait SuperT {
  isA I1;
  mixset f5 {e;}
  void m1() {
    System.out.println("impl of m1");
 } }

trait T1 {
  isA SuperT;
  Integer c;
  Integer d;
  mixset f6 {[c > d]}
  after setC {
     System.out.println("SetC has happened from T1");
  }
  mixset f1 {1 -- 1..* C4;}
}

trait T2 {
  after setC {
    System.out.println("setC has happened from T2");
} }

trait T3 {
  void m2() {
    System.out.println("M2 is executing");
  }
  stateMachine1 {
    state1 { event -> state2; }
    state2 { }
} }

trait T4 {
  isA T3<stateMachine1 as stateMachine2,
      *.event() as event1>;
}

class C1 {
  isA T1, I1;
  mixset f1 {1 -- * C3;}
}

mixset f5 class C2 {
  mixset f4 {1 -- 1..* C3;}
  isA C1, T2;
  void m1() {
    System.out.println("Overriding impl of m1");
} }  

class C3 {}

mixset f4 class C4 {
  isA T4;
  mixset f5 {after custom m2() 
     {System.out.println("m2 occurred");}   }
  after event1 {
    System.out.printlin("event event1 occurred");}
}
use f3; use f2; use f1; use f5; use f4;

The failure is:

Error on line 0 : Compiler Error (Analysis). Could not analyze Umple model.
Stack Trace Follows. 
Exception java.lang.NullPointerException
at cruise.umple.compiler.UmpleInternalParser.getMixsetFragmentWithEnclosingElement(UmpleInternalParser.java:15275)
at cruise.umple.compiler.UmpleInternalParser.getMixsetFragmentWithEnclosingElement(UmpleInternalParser.java:15303)
at cruise.umple.compiler.UmpleInternalParser.getMixsetFragmentWithEnclosingElement(UmpleInternalParser.java:15303)
at cruise.umple.compiler.UmpleInternalParser.getMixsetFragmentWithEnclosingElement(UmpleInternalParser.java:15303)
at cruise.umple.compiler.UmpleInternalParser.analyzeMixsetBodyToken(UmpleInternalParser.java:15262)
at cruise.umple.compiler.UmpleInternalParser.analyzeClassToken(UmpleInternalParser.java:2022)
at cruise.umple.compiler.UmpleInternalParser.analyzeToken(UmpleInternalParser.java:1311)
at cruise.umple.compiler.UmpleInternalParser.analyzeAllTokens(UmpleInternalParser.java:1267) 
at cruise.umple.compiler.UmpleInternalParser.analyzeClass(UmpleInternalParser.java:2958)
at cruise.umple.compiler.UmpleInternalParser.analyzeClassToken(UmpleInternalParser.java:1854) 
at cruise.umple.compiler.UmpleInternalParser.analyzeToken(UmpleInternalParser.java:1289)
at cruise.umple.compiler.UmpleInternalParser.analyzeAllTokens(UmpleInternalParser.java:1240) 
at cruise.umple.compiler.UmpleInternalParser.parseMixsetWaitingFragment(UmpleInternalParser.java:15410)
at cruise.umple.compiler.UmpleInternalParser.analyzeMixset(UmpleInternalParser.java:15487) 
at cruise.umple.compiler.UmpleInternalParser.analyzeMixsetToken(UmpleInternalParser.java:15424)
at cruise.umple.compiler.UmpleInternalParser.analyzeToken(UmpleInternalParser.java:1298)
at cruise.umple.compiler.UmpleInternalParser.analyzeAllTokens(UmpleInternalParser.java:1240) 
at cruise.umple.compiler.UmpleInternalParser.analyze(UmpleInternalParser.java:1129)
at cruise.umple.compiler.UmpleModel.run(UmpleModel.java:1594)
at cruise.umple.PlaygroundMain.processCommand(PlaygroundMain.java:763)
at cruise.umple.PlaygroundMain.handleMessageFromClient(PlaygroundMain.java:459)
at cruise.umple.AbstractServer.receiveMessageFromClient(AbstractServer.java:556)
at cruise.umple.ConnectionToClient.run(ConnectionToClient.java:335) 

TimLethbridge added a commit that referenced this issue Jun 27, 2019

@TimLethbridge

This comment has been minimized.

Copy link
Member Author

commented Jun 27, 2019

Fixed by #1469

@TimLethbridge

This comment has been minimized.

Copy link
Member Author

commented Jun 27, 2019

The fix worked on the test. But here is another test that fails. Code is almost the same! So @gublan24 I have re-opened the issue

interface I1 {
  void m1();
}

trait SuperT {
  isA I1;
  mixset f5 {e;}
  void m1() {
    System.out.println("impl of m1");
  }
}

trait T1 {
  isA SuperT;
  Integer c;
  Integer d;
  mixset f6 {[c > d]}
  after setC {
     System.out.println("SetC has happened from T1");
  }
  mixset f1 {1 -- 1..* C4;}
}

trait T2 {
  after setC {
    System.out.println("setC has happened from T2");
  }
}

trait T3 {
  void m2() {
    System.out.println("M2 is executing");
  }
  sm1 {
    s1 {
      e -> s2;
    }
    s2 {
    }
  }
}

trait T4 {
  isA T3;
}

class C1 {
  isA T1, I1;
  mixset f1 {1 -- * C3;}
}

mixset f5 class C2 {
  mixset f4 {1 -- 1..* C3;}
  isA C1, T2;
  void m1() {
    System.out.println("Overriding impl of m1");
  }  
}

class C3 {
}

mixset f4 class C4 {
  isA T4;
  mixset f5 after custom m2() {System.out.println("m2 occurred");}
  after e1 {System.out.printlin("event e1 occurred");}
}

use f4;
@gublan24

This comment has been minimized.

Copy link
Member

commented Jun 27, 2019

The error is caused by the line mixset f5 after custom m2() {System.out.println("m2 occurred");}
I am working on it to resolve the issue.

@TimLethbridge

This comment has been minimized.

Copy link
Member Author

commented Jun 27, 2019

Aha! I see. The other example had curly brackets around it! I guess options are:

  1. Just make sure it fails to parse

  2. Actually raise an error saying that the only things that can appear after 'mixset name' are curly bracket or attribute declaration or class or trait or interface (and anything else that can).

  3. Allow other such as before and after statements to have mixset keyword before them.

@gublan24

This comment has been minimized.

Copy link
Member

commented Jun 28, 2019

I would recommend to go with option 2.

Option 3 has some drawbacks; I've investigated the change required to implement option 3. This kind of syntactic sugar can be implemented as you said by extending the grammar of [[mixsetInlineDefinition]] such that it accepts [[codeInjection]]. So, the grammar will be:
[[mixsetInlineDefinition]] : [[codeInjection]] | ...
Such addition has three issues:
Concept violation: Umple parser do a tokenization as a first step then it analyzes all umple entities except mixsets unless they are used. when [[CodeInjuction]] becomes part of inline mixset, umple parser will tokenize the content of the [[CodeInjuction]]. This violates the general concept of mixsets.

Implementation complexity: Mixset fragments are currently stored in umple model as string. The addition of [[codeInjection]] to inline mixsets requires addition of another type of fragment such as List <Token>TokenizedFragment. This is doable. However, it requires some modification for the tokens that umple analyzes. We need to strip out tokens that belong to inline mixsets (which are not used) from the list of tokens that umple parses, and then store it in the fragment list. Having two representations of mixsets' fragments may not be a bad thing, however, removal of certain tokens out of the list of tokens that UmpleInternalParser has is not too convenient.

Uniformity issue : one may argue that inline mixsets should accept almost all Umple entities such that: [[mixsetInlineDefinition]] : [[codeInjection]] | [[associationClassDefinition]] | [[abstract]].... . So, Its better to allow inline mixsets to only the few cases that we already have. Those cases are straightforward and do not require invasive change to UmpleInternalParser.

@TimLethbridge

This comment has been minimized.

Copy link
Member Author

commented Jun 28, 2019

Right. Agreed. Point out in the error message manual page examples of things that can't go in an inline mixset and things that can. Have the parser detect the cases that can't.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.