In Umple state machines' guards, I'm missing an "in state" predicate that returns true if the state machine is in a given state.
Does this function exists?
Yes, there is. Call the get function on the state machine to get the state, and then compare the result to the enumeration whose name is the state machine followed by a dot followed by the state. See below for an example where a query is being done in method m1()
class X {
sm {
s1 {
a-> s2;
}
s2 {}
}
public m1 () {
if(getSm()==Sm.s1) {
// do something
}
}
}
It is a good point that this should be documented in the user manual
Related
I am originally a C-developer and I am now getting familiar with DML. I often need to write state machines and I always design them very C-stylish. I suspect that I am not utilizing the DML language to its full extent. Could someone port this traffic light C-implementation to modern DML?
enum TRAFFIC_LIGHT {
RED,
YELLOW,
GREEN,
}
int state;
timer_t timer;
int redTimeMs = 15000;
int greenTimeMs = 10000;
int transitionTimeMs = 1000;
void start_transition_to_green() {
start_timer(transitionTimeMs, tick_to_green);
}
void start_transition_to_red() {
start_timer(transitionTimeMs, tick_to_red);
}
void tick_to_green() {
switch (state) {
case RED:
state = YELLOW;
start_timer(transitionTimeMs, tick_to_green);
break;
case YELLOW:
state = GREEN;
start_timer(transitionTimeMs, tick_to_green);
break;
case GREEN:
start_timer(greenTimeMs, start_transition_to_red);
break;
}
}
void tick_to_red() {
switch (state) {
case GREEN:
state = YELLOW;
start_timer(transitionTimeMs, tick_to_red);
break;
case YELLOW:
state = RED;
start_timer(transitionTimeMs, tick_to_red);
break;
case RED:
start_timer(redTimeMs, start_transition_to_green);
break;
}
}
void main(void) {
state = RED;
start_transition_to_green();
}
I am expecting a DML implementation that is checkpointable.
The easy translation is of "start_timer" to the 'after' construct. This will give you checkpointing of both the "direction" of change (towards green/red) and the time until next change for free.
Enums do not exist (as such) in DML, instead we can define the states as instances of a common template type. Additionally; a template type is serializable so we can store this in a 'saved' variable and obtain the checkpointing for free.
The 'after' can only accepts a delay in cycles or seconds, so I have pre-divided the constants by 1000 and stored them as top-level parameters.
dml 1.4;
device traffic_light;
param desc = "traffic light state machine";
param documentation = "switches red-yellow-green-yellow-red etc...";
// Defines behavior of a traffic light state
// The instantiation if 'name' here is necessary if we want inspection
// as it will put the object name into the template type
template traffic_state is name {
method enter() default {
log info, 2: "Entered %s", name;
current_light_state = this;
}
method tick_to_green();
method tick_to_red();
}
saved traffic_state current_light_state;
param red_time_s = 15;
param green_time_s = 10;
param transition_time_s = 1;
After this, we define each state as a 'group' instantiating our template type. Implementing the correct behavior for ticking into/out-of them.
group red is traffic_state {
method tick_to_red() {
enter();
after red_time_s s: tick_to_green();
}
method tick_to_green() {
after transition_time_s s: yellow.tick_to_green();
}
}
group yellow is traffic_state {
method tick_to_red() {
enter();
after transition_time_s s: red.tick_to_red();
}
method tick_to_green() {
enter();
after transition_time_s s: green.tick_to_green();
}
}
group green is traffic_state {
method tick_to_red() {
after transition_time_s s: yellow.tick_to_red();
}
method tick_to_green() {
enter();
after green_time_s s: tick_to_red();
}
}
Then, we need to start up the chain of 'after' calls exactly once upon creating the device. And additionally since the next after call will be checkpointed we must guard against setting it up again when loading a checkpoint. Using 'SIM_is_restoring_state' on our device object allows us to only execute code while not loading a checkpoint. (note: we need to do this in 'post_init' and not 'init'. This is because the 'queue' attribute that 'after' statements rely on is not yet set on the device object)
method post_init() {
if (!SIM_is_restoring_state(dev.obj)) {
red.enter();
red.tick_to_green();
}
}
Finally, if we want to inspect the state from the simulator we need to expose it as an attribute. Suitably done with a "read-only" (setting state from simulator would be more complicated) and "pseudo" (does not contain state) atribute.
attribute current_light is (pseudo_attr, read_only_attr) {
param type = "s";
method get() -> (attr_value_t) {
return SIM_make_attr_string(current_light_state.name);
}
}
For example, consider the following C# code:
interface IBase { void f(int); }
interface IDerived : IBase { /* inherits f from IBase */ }
...
void SomeFunction()
{
IDerived o = ...;
o.f(5);
}
I know how to get a MethodDefinition object corresponding to SomeFunction.
I can then loop through MethodDefinition.Instructions:
var methodDef = GetMethodDefinitionOfSomeFunction();
foreach (var instruction in methodDef.Body.Instructions)
{
switch (instruction.Operand)
{
case MethodReference mr:
...
break;
}
yield return memberRef;
}
And this way I can find out that the method SomeFunction calls the function IBase.f
Now I would like to know the declared type of the object on which the function f is called, i.e. the declared type of o.
Inspecting mr.DeclaringType does not help, because it returns IBase.
This is what I have so far:
TypeReference typeRef = null;
if (instruction.OpCode == OpCodes.Callvirt)
{
// Identify the type of the object on which the call is being made.
var objInstruction = instruction;
if (instruction.Previous.OpCode == OpCodes.Tail)
{
objInstruction = instruction.Previous;
}
for (int i = mr.Parameters.Count; i >= 0; --i)
{
objInstruction = objInstruction.Previous;
}
if (objInstruction.OpCode == OpCodes.Ldloc_0 ||
objInstruction.OpCode == OpCodes.Ldloc_1 ||
objInstruction.OpCode == OpCodes.Ldloc_2 ||
objInstruction.OpCode == OpCodes.Ldloc_3)
{
var localIndex = objInstruction.OpCode.Op2 - OpCodes.Ldloc_0.Op2;
typeRef = locals[localIndex].VariableType;
}
else
{
switch (objInstruction.Operand)
{
case FieldDefinition fd:
typeRef = fd.DeclaringType;
break;
case VariableDefinition vd:
typeRef = vd.VariableType;
break;
}
}
}
where locals is methodDef.Body.Variables
But this is, of course, not enough, because the arguments to a function can be calls to other functions, like in f(g("hello")). It looks like the case above where I inspect previous instructions must repeat the actions of the virtual machine when it actually executes the code. I do not execute it, of course, but I need to recognize function calls and replace them and their arguments with their respective returns (even if placeholders). It looks like a major pain.
Is there a simpler way? Maybe there is something built-in already?
I am not aware of an easy way to achieve this.
The "easiest" way I can think of is to walk the stack and find where the reference used as the target of the call is pushed.
Basically, starting from the call instruction go back one instruction at a time taking into account how each one affects the stack; this way you can find the exact instruction that pushes the reference used as the target of the call (a long time ago I wrote something like that; you can use the code at https://github.com/lytico/db4o/blob/master/db4o.net/Db4oTool/Db4oTool/Core/StackAnalyzer.cs as inspiration).
You'll need also to consider scenarios in which the pushed reference is produced through a method/property; for example, SomeFunction().f(5). In this case you may need to evaluate that method to find out the actual type returned.
Keep in mind that you'll need to handle a lot of different cases; for example, imagine the code bellow:
class Utils
{
public static T Instantiate<T>() where T : new() => new T();
}
class SomeType
{
public void F(int i) {}
}
class Usage
{
static void Main()
{
var o = Utils.Instantiate<SomeType>();
o.F(1);
}
}
while walking the stack you'll find that o is the target of the method call; then you'll evaluate Instantiate<T>() method and will find that it returns new T() and knowing that T is SomeType in this case, that is the type you're looking for.
So the answer of Vagaus helped me come up with a working implementation.
I published it on github - https://github.com/MarkKharitonov/MonoCecilExtensions
Included many unit tests, but I am sure I missed some cases.
I wonder howto access an object's attribute dynamically via a name as a Str at runtime in Raku. Instead of:
#!/usr/bin/rakudo
class c0 {
has $!a0 = 1;
has $!a1 = 2;
method access(Str $m) {
if ($m eq "a0") { return $!a0; }
if ($m eq "a1") { return $!a1; }
}
method set(Str $m, $v) {
if ($m eq "a0") { $!a0 = $v; }
if ($m eq "a1") { $!a1 = $v; }
}
}
my $c = c0.new();
$c.set("a0", 3);
$c.set("a1", 4);
say $c.access("a0");
say $c.access("a1");
I would like to use something that would look in pseudocode:
class c0 {
...
method access(Str $m) {
return self.$m;
}
method set(Str $m, $v) {
self.$m = $v;
}
}
Is this possible in Raku? Which construct do I need to use?
As a backgrounder I was thinking how to implement a role that adds associativity functionality to the class, to transparently access a member. The attribute name would be parametrized: If I have a class class ports { has #!ports_; ... } and an instance my $p = ports.new() then I want to be able to use the subscript syntax to access #ports_ via $p[...] . I try to figure out weather I can define role acc [ Str $member] does Associative[Cool,Str] { ... } and then define ports via class ports does acc["ports_"] { ... }
where the AT-KEY and EXISTS-KEY in role acc are implemented using dynamic attribute access (if that is possible).
I dont want to use "EVAL".
This is possible with some introspection of the attributes. However, I would like to point out that it is the exact intention of private attributes to be private. Creating a workaround to handle them as public attributes is an anti-pattern, and introduces needless complexity.
class c0 {
has $.a0 = 1;
has $.a1 = 2;
method access (Str $m) {
my $attribute = self.^attributes.first({ ~$_ eq '$!' ~ $m });
return unless $attribute;
$attribute.get_value(self); # 1
}
}
my $c = c0.new;
say $c.access('a0');
For setting the value, you can use the .set_value method on the attribute.
method set (Str $m, $v) {
...
$attribute.set_value(self, $v);
}
Old answer left here for historic purposes.
Yes, something like this is possible in Raku. You don't even need to explicitly define the access method.
class c0 {
has $.a0 = 1;
has $a.1 = 2;
}
my $c = $c0.new;
say $c.'a0'(); # 1
This works because Raku creates an accessor method for public variables for your classes, which is called when you use .'a0'(). The () are required for using a quoted method name.
You changed your post to add a question about how to do something like this:
role acc [ Str $member] does Associative[Cool,Str] { ... }
class ports does acc["ports_"] { has #!ports_; ... }
The answer is of course, don't do that.
I mean you can, but you really shouldn't.
I mean you really really shouldn't.
Also you indicate that you want to use [] for indexing.
The thing is that is Positional not Associative.
(I'm ignoring the fact that there is no point to add _ to the end of the attribute name. Usually in Perl or Python adding _ indicated private, but we don't need to do that in Raku.)
The right way to do that is to have the array inside of the role.
role Array::Access [::OF = Cool] does Positional[OF] {
has OF #!array-access handles < AT-POS >;
}
class Ports does Array::Access {
# allows you to access it as self!ports inside of this class
method !ports () is raw { #!array-access }
}
Which shows that adding a role to do that is probably overkill.
class Ports does Positional[Cool] {
has Cool #!ports handles < AT-POS >;
}
If you really, really want to do it they way you asked for, the following works.
role Inner::Array::Access [ Str:D \name, ::OF = Cool ] does Positional[OF] {
# a way to quickly access the attribute
# (hopefully no-one tries to add an attribute of this name to their class)
has $!inner-array handles < AT-POS >;
# set $!inner-array
submethod TWEAK (){
$!inner-array := self.^attributes.first(name).get_value(self);
}
}
class Ports does Inner::Array::Access['#!ports'] {
has #!ports;
# a quick way to add a way to set #!ports for our test
submethod BUILD( :#!ports ){}
}
my Ports $v = ports => [0,10,20,30];
say $v[2]; # 20
Probably what you were thinking is embed the self.^attributes thing into AT-POS.
role Inner::Array::Access [ Str:D \name, ::OF = Cool ] does Positional[OF] {
method AT-POS ( \index ) is raw {
self.^attributes.first(name).get_value(self).AT-POS(index);
}
}
That would be slow, because it has to do all of those lookups everytime you access a single element.
I am completely baffled. I am essentially trying to do foo["x"]="y" and getting the most baffling of exceptions. I actually made a minimal working example, and I had to nest Maps and Lists for the thing to break. I have no idea what's going on.
Map fixprobset(Map P) {
print(P);
if(!P.containsKey("name")) {
final foo = P["tileset"].join(" ");
P["name"] = foo;
}
if(P.containsKey("children")) {
for(var k=0; k<P["children"].length;k++) fixprobset(P["children"][k]);
}
return P;
}
void main() {
Map problemset = fixprobset({
"name": "Jingle Jangle",
"children": [
{
"tileset": ["1","2","3"]
}
]
});
print(problemset);
}
Click here and gaze in wonder on the bafflement
OK so now I understand what's going on. Objects have a runtimeType, and even though P has the unassuming type declaration Map, P.runtimeType could be e.g. Map<String,List<String>>. Once that happens, a Map can no longer store heterogeneous objects. Getting around this was quite hard for me, the type declarations Map<String,dynamic> P or Map<String,Object> P really don't help, the undesirable runtimeType is there to stay. I've filed this as a "bug" although perhaps it will be deemed a (mis)feature.
This gist has the workaround.
You problems comes from the fact that your are fighting against the type system in Dart. As you have discovered, there are something about the runtimeType which seems to be automatically assigned to some other type than dynamic.
I have made this example which works:
Map fixprobset(Map<dynamic, dynamic> P) {
print(P);
if (!P.containsKey("name")) {
final foo = (P["tileset"] as List).join(" ");
P["name"] = foo;
}
if (P.containsKey("children")) {
for (var k = 0; k < (P["children"] as List).length; k++) {
fixprobset((P["children"] as List)[k] as Map);
}
}
return P;
}
void main() {
final problemset = fixprobset(<dynamic, dynamic>{
"name": "Jingle Jangle",
"children": <dynamic>[
<dynamic, dynamic>{
"tileset": <dynamic>["1", "2", "3"]
}
]
});
print(problemset);
}
As you can see, the automatically assigned types comes from your input data which gets assigned types which makes sense at the start of the program. Your problem is then, that you don't wants this automatically assigned types but want to change them after creation. So you want to change a List<String> into a List<dynamic> but to do that, you need to create a new object since you cannot change the type of an object after its creation.
So my "solution" fixes this by setting the type at the time of the creation of the lists and maps in the input of the first call to fixprobset.
Still trying out swift, and I came across this problem (not sure if it really classifies as one)
So we have a protocol, and a structure that inherits it.
protocol ExampleProtocol {
var simpleDescription: String { get }
func adjust()
}
struct SimpleStructure : ExampleProtocol{
var simpleDescription = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
func adjust() { //I created this second method just to conform to the protocol
}
}
var b = SimpleStructure()
b.adjust() //This generates a compiler error mentioning Ambiguity (Correct)
Question is how do I call the mutating adjust() not the adjust from the protocol. i.e. I know if I declare b as a protocol and initialized it to the struct it will call adjust from protocol, but how do I call the first adjust ? or is it not possible? Or Am I using it wrongly ?
Cheers,
Your code doesn't compile, but the error is in redefining the adjust method by adding the mutating attribute - that doesn't create an overloaded version of adjust.
In my opinion this is the correct code:
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
struct SimpleStructure : ExampleProtocol{
var simpleDescription = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
}
which means: you have to define the adjust function as mutating in the protocol.