/** * The class GamlCompatibilityConverter. Performs a series of transformations between the EObject * based representation of GAML models and the representation based on SyntacticElements in GAMA. * * @author drogoul * @since 16 mars 2013 */ public class GamlCompatibilityConverter { static final List<Integer> STATEMENTS_WITH_ATTRIBUTES = Arrays.asList( ISymbolKind.SPECIES, ISymbolKind.EXPERIMENT, ISymbolKind.OUTPUT, ISymbolKind.MODEL); // private static final Set<String> EXTS = GamaFileType.extensionsToFullType.keySet(); public static SyntacticModelElement buildSyntacticContents( final EObject root, final Set<Diagnostic> errors) { if (!(root instanceof Model)) { return null; } ModelImpl m = (ModelImpl) root; Object[] imps; if (m.eIsSet(GamlPackage.MODEL__IMPORTS)) { List<Import> imports = m.getImports(); imps = new Object[imports.size()]; for (int i = 0; i < imps.length; i++) { URI uri = URI.createURI(imports.get(i).getImportURI(), false); imps[i] = uri; } } else { imps = null; } SyntacticModelElement model = (SyntacticModelElement) SyntacticFactory.create(MODEL, m, EGaml.hasChildren(m), imps); model.setFacet(NAME, convertToLabel(null, m.getName())); convStatements(model, EGaml.getStatementsOf(m), errors); return model; } private static boolean doesNotDefineAttributes(final String keyword) { SymbolProto p = DescriptionFactory.getProto(keyword, null); if (p == null) { return true; } int kind = p.getKind(); return !STATEMENTS_WITH_ATTRIBUTES.contains(kind); } private static void addWarning( final String message, final EObject object, final Set<Diagnostic> errors) { if (!GamaPreferences.WARNINGS_ENABLED.getValue()) { return; } Diagnostic d = new EObjectDiagnosticImpl(Severity.WARNING, "", message, object, null, 0, null); errors.add(d); } private static void addInfo( final String message, final EObject object, final Set<Diagnostic> errors) { Diagnostic d = new EObjectDiagnosticImpl(Severity.INFO, "", message, object, null, 0, null); errors.add(d); } private static final ISyntacticElement convStatement( final ISyntacticElement upper, final Statement stm, final Set<Diagnostic> errors) { // We catch its keyword String keyword = EGaml.getKey.caseStatement(stm); if (keyword == null) { throw new NullPointerException( "Trying to convert a statement with a null keyword. Please debug to understand the cause."); } else if (keyword.equals(ENTITIES)) { convertBlock(stm, upper, errors); return null; } else { keyword = convertKeyword(keyword, upper.getKeyword()); } final ISyntacticElement elt = SyntacticFactory.create(keyword, stm, EGaml.hasChildren(stm)); if (keyword.equals(ENVIRONMENT)) { convertBlock(stm, upper, errors); } else if (stm instanceof S_Assignment) { keyword = convertAssignment((S_Assignment) stm, keyword, elt, stm.getExpr(), errors); // } else if ( stm instanceof S_Definition && !SymbolProto.nonTypeStatements.contains(keyword) // ) { } else if (stm instanceof S_Definition && !DescriptionFactory.isStatementProto(keyword)) { S_Definition def = (S_Definition) stm; // If we define a variable with this statement TypeRef t = (TypeRef) def.getTkey(); // 20/01/14: The type is now passed plainly if (t != null) { addFacet(elt, TYPE, convExpr(t, errors), errors); } // convertType(elt, t, errors); if (t != null && doesNotDefineAttributes(upper.getKeyword())) { // Translation of "type var ..." to "let var type: type ..." if we are not in a // top-level statement (i.e. not in the declaration of a species or an experiment) elt.setKeyword(LET); // addFacet(elt, TYPE, convertToConstantString(null, keyword), errors); keyword = LET; } else { // Translation of "type1 ID1 (type2 ID2, type3 ID3) {...}" to // "action ID1 type: type1 { arg ID2 type: type2; arg ID3 type: type3; ...}" Block b = def.getBlock(); if (b != null && b.getFunction() == null) { elt.setKeyword(ACTION); // addFacet(elt, TYPE, convertToConstantString(null, keyword), errors); keyword = ACTION; } convertArgs(def.getArgs(), elt, errors); } } else if (stm instanceof S_Do) { // Translation of "stm ID (ID1: V1, ID2:V2)" to "stm ID with:(ID1: V1, ID2:V2)" Expression e = stm.getExpr(); addFacet(elt, ACTION, convertToLabel(e, EGaml.getKeyOf(e)), errors); if (e instanceof Function) { addFacet(elt, INTERNAL_FUNCTION, convExpr(e, errors), errors); Function f = (Function) e; Parameters p = f.getParameters(); if (p != null) { addFacet(elt, WITH, convExpr(p, errors), errors); } else { ExpressionList list = f.getArgs(); if (list != null) { addFacet(elt, WITH, convExpr(list, errors), errors); } } } } else if (stm instanceof S_If) { // If the statement is "if", we convert its potential "else" part and put it as a child // of the syntactic element (as GAML expects it) convElse((S_If) stm, elt, errors); } else if (stm instanceof S_Action) { // Conversion of "action ID (type1 ID1 <- V1, type2 ID2)" to // "action ID {arg ID1 type: type1 default: V1; arg ID2 type: type2}" convertArgs(((S_Action) stm).getArgs(), elt, errors); } else if (stm instanceof S_Reflex) { // We add the "when" facet to reflexes and inits if necessary S_Reflex ref = (S_Reflex) stm; if (ref.getExpr() != null) { addFacet(elt, WHEN, convExpr(ref.getExpr(), errors), errors); } } else if (stm instanceof S_Solve) { Expression e = stm.getExpr(); addFacet(elt, EQUATION, convertToLabel(e, EGaml.getKeyOf(e)), errors); } // We apply some conversions to the facets expressed in the statement convertFacets(stm, keyword, elt, errors); if (stm instanceof S_Var && (keyword.equals(CONST) || keyword.equals(VAR))) { // We modify the "var", "const" declarations in order to replace the // keyword by the type IExpressionDescription type = elt.getExpressionAt(TYPE); if (type == null) { addWarning("Facet 'type' is missing, set by default to 'unknown'", stm, errors); elt.setKeyword(UNKNOWN); } else { // WARNING FALSE (type is now more TypeRef) elt.setKeyword(type.toString()); } if (keyword.equals(CONST)) { IExpressionDescription constant = elt.getExpressionAt(CONST); if (constant != null && constant.toString().equals(FALSE)) { addWarning("Is this variable constant or not ?", stm, errors); } elt.setFacet(CONST, ConstantExpressionDescription.create(true)); } } else if (stm instanceof S_Experiment) { // We do it also for experiments, and change their name IExpressionDescription type = elt.getExpressionAt(TYPE); if (type == null) { addInfo("Facet 'type' is missing, set by default to 'gui'", stm, errors); elt.setFacet(TYPE, ConstantExpressionDescription.create(GUI_)); } // if ( type == null ) { // addWarning("Facet 'type' is missing, set by default to 'gui'", stm, errors); // elt.setFacet(TYPE, ConstantExpressionDescription.create(GUI_)); // elt.setKeyword(GUI_); // } else { // elt.setKeyword(type); // } // We modify the names of experiments so as not to confuse them with species String name = elt.getName(); elt.setFacet(TITLE, convertToLabel(null, "Experiment " + name)); elt.setFacet(NAME, convertToLabel(null, name)); } else // TODO Change this by implementing only one class of methods (that delegates to // others) if (keyword.equals(METHOD)) { // We apply some conversion for methods (to get the name instead of the "method" // keyword) String type = elt.getName(); if (type != null) { elt.setKeyword(type); } } else if (stm instanceof S_Equations) { convStatements(elt, EGaml.getEquationsOf((S_Equations) stm), errors); } // We add the dependencies (only for variable declarations) assignDependencies(stm, keyword, elt, errors); // We convert the block of statements (if any) convertBlock(stm, elt, errors); return elt; } private static void convertBlock( final Statement stm, final ISyntacticElement elt, final Set<Diagnostic> errors) { Block block = stm.getBlock(); if (block != null) { Expression function = block.getFunction(); if (function != null) { // If it is a function (and not a regular block), we add it as a facet addFacet(elt, FUNCTION, convExpr(function, errors), errors); } else { convStatements(elt, EGaml.getStatementsOf(block), errors); } } } private static void addFacet( final ISyntacticElement e, final String key, final IExpressionDescription expr, final Set<Diagnostic> errors) { if (e.hasFacet(key)) { // if ( key.equals(TYPE) ) { // GuiUtils.debug("GamlCompatibilityConverter.addFacet:"); // } addWarning( "Double definition of facet " + key + ". Only the last one will be considered", e.getElement(), errors); } e.setFacet(key, expr); } private static void assignDependencies( final Statement stm, final String keyword, final ISyntacticElement elt, final Set<Diagnostic> errors) { // COMPATIBILITY with the definition of environment // if ( !SymbolProto.nonTypeStatements.contains(keyword) ) { if (!DescriptionFactory.isStatementProto(keyword)) { Set<String> s = varDependenciesOf(stm); if (s != null && !s.isEmpty()) { elt.setFacet(DEPENDS_ON, new StringListExpressionDescription(s)); } // 25/01/14: this test is cancelled for the moment, as the facet type is now defined earlier // when dealing // with type var_name; // if ( !(stm instanceof S_Var) ) { // IExpressionDescription type = elt.getExpressionAt(TYPE); // if ( type != null ) { // if ( type.toString().equals(keyword) ) { // addWarning("Duplicate declaration of type", stm, errors); // } else { // addWarning("Conflicting declaration of type (" + type + " and " + keyword + // "), only the last one will be considered", stm, errors); // } // } // } } } private static void convElse( final S_If stm, final ISyntacticElement elt, final Set<Diagnostic> errors) { EObject elseBlock = stm.getElse(); if (elseBlock != null) { ISyntacticElement elseElt = SyntacticFactory.create(ELSE, elseBlock, EGaml.hasChildren(elseBlock)); if (elseBlock instanceof Statement) { elseElt.addChild(convStatement(elt, (Statement) elseBlock, errors)); } else { convStatements(elseElt, EGaml.getStatementsOf((Block) elseBlock), errors); } elt.addChild(elseElt); } } private static void convertArgs( final ActionArguments args, final ISyntacticElement elt, final Set<Diagnostic> errors) { if (args != null) { for (ArgumentDefinition def : EGaml.getArgsOf(args)) { ISyntacticElement arg = SyntacticFactory.create(ARG, def, false); addFacet(arg, NAME, convertToLabel(null, def.getName()), errors); EObject type = def.getType(); addFacet(arg, TYPE, convExpr(type, errors), errors); // addFacet(arg, TYPE, convertToConstantString(null, EGaml.getKey.caseTypeRef(type)), // errors); // convertType(arg, type, errors); Expression e = def.getDefault(); if (e != null) { addFacet(arg, DEFAULT, convExpr(e, errors), errors); } elt.addChild(arg); } } } private static String convertAssignment( final S_Assignment stm, String keyword, final ISyntacticElement elt, final Expression expr, final Set<Diagnostic> errors) { IExpressionDescription value = convExpr(stm.getValue(), errors); if (keyword.endsWith("<-") || keyword.equals(SET)) { // Translation of "container[index] <- value" to // "put item: value in: container at: index" // 20/1/14: Translation of container[index] +<- value" to // "add item: value in: container at: index" if (expr instanceof Access && expr.getOp().equals("[")) { String kw = keyword.equals("+<-") ? ADD : PUT; String to = keyword.equals("+<-") ? TO : IN; elt.setKeyword(kw); addFacet(elt, ITEM, value, errors); addFacet(elt, to, convExpr(expr.getLeft(), errors), errors); List<Expression> args = EGaml.getExprsOf(((Access) expr).getArgs()); if (args.size() == 0) { // Add facet all: true when no index is provided addFacet(elt, ALL, ConstantExpressionDescription.create(true), errors); } else { if (args.size() == 1) { // Integer index addFacet(elt, AT, convExpr(args.get(0), errors), errors); } else { // Point index IExpressionDescription p = new OperatorExpressionDescription( POINT, convExpr(args.get(0), errors), convExpr(args.get(1), errors)); addFacet(elt, AT, p, errors); } } keyword = kw; } else { // Translation of "var <- value" to "set var value: value" elt.setKeyword(SET); addFacet(elt, VALUE, value, errors); keyword = SET; } } else if (keyword.startsWith("<<") || keyword.equals("<+")) { // Translation of "container <+ item" or "container << item" to "add item: item to: container" // 08/01/14: Addition of the "<<+" (add all) elt.setKeyword(ADD); addFacet(elt, TO, convExpr(expr, errors), errors); addFacet(elt, ITEM, value, errors); if (keyword.equals("<<+")) { addFacet(elt, ALL, ConstantExpressionDescription.create(true), errors); } keyword = ADD; } else if (keyword.startsWith(">>") || keyword.equals(">-")) { // Translation of "container >> item" or "container >- item" to // "remove item: item from: container" // 08/01/14: Addition of the ">>-" keyword (remove all) elt.setKeyword(REMOVE); // 20/01/14: Addition of the access [] to remove from the index if (expr instanceof Access && expr.getOp().equals("[") && EGaml.getExprsOf(((Access) expr).getArgs()).size() == 0) { addFacet(elt, FROM, convExpr(expr.getLeft(), errors), errors); addFacet(elt, INDEX, value, errors); } else { addFacet(elt, FROM, convExpr(expr, errors), errors); addFacet(elt, ITEM, value, errors); } if (keyword.equals(">>-")) { addFacet(elt, ALL, ConstantExpressionDescription.create(true), errors); } keyword = REMOVE; } else if (keyword.equals(EQUATION_OP)) { // conversion of left member (either a var or a function) IExpressionDescription left = null; if (expr instanceof VariableRef) { left = new OperatorExpressionDescription(ZERO, convExpr(expr, errors)); } else { left = convExpr(expr, errors); } addFacet(elt, EQUATION_LEFT, left, errors); // Translation of right member addFacet(elt, EQUATION_RIGHT, value, errors); } return keyword; } private static void convertFacets( final Statement stm, final String keyword, final ISyntacticElement elt, final Set<Diagnostic> errors) { SymbolProto p = DescriptionFactory.getProto(keyword, null); for (Facet f : EGaml.getFacetsOf(stm)) { String fname = EGaml.getKey.caseFacet(f); // We change the "<-" and "->" symbols into full names if (fname.equals("<-")) { fname = keyword.equals(LET) || keyword.equals(SET) ? VALUE : INIT; } else if (fname.equals("->")) { fname = FUNCTION; } // We compute (and convert) the expression attached to the facet boolean label = p == null ? false : p.isLabel(fname); IExpressionDescription fexpr = convExpr(f, label, errors); addFacet(elt, fname, fexpr, errors); } // We add the "default" (or omissible) facet to the syntactic element String def = stm.getFirstFacet(); if (def != null) { if (def.endsWith(":")) { def = def.substring(0, def.length() - 1); } } else { def = DescriptionFactory.getOmissibleFacetForSymbol(keyword); } if (def != null && !def.isEmpty() && !elt.hasFacet(def)) { IExpressionDescription ed = findExpr(stm, errors); if (ed != null) { elt.setFacet(def, ed); } } } private static String convertKeyword(final String k, final String upper) { String keyword = k; if ((upper.equals(BATCH) || upper.equals(EXPERIMENT)) && keyword.equals(SAVE)) { keyword = SAVE_BATCH; } else if (upper.equals(OUTPUT) && keyword.equals(FILE)) { keyword = OUTPUT_FILE; } else if (upper.equals(DISPLAY) || upper.equals(POPULATION)) { if (keyword.equals(SPECIES)) { keyword = POPULATION; } else if (keyword.equals(GRID)) { keyword = GRID_POPULATION; } } return keyword; } private static final IExpressionDescription convExpr( final EObject expr, final Set<Diagnostic> errors) { if (expr == null) { return null; } IExpressionDescription result = EcoreBasedExpressionDescription.create(expr, errors); return result; } private static final IExpressionDescription convExpr( final Facet facet, final boolean label, final Set<Diagnostic> errors) { if (facet != null) { Expression expr = facet.getExpr(); if (expr != null) { return label ? convertToLabel(expr, EGaml.getKeyOf(expr)) : convExpr(expr, errors); } String name = facet.getName(); // TODO Verify the use of "facet" if (name != null) { return convertToLabel(null, name); } } return null; } static final IExpressionDescription convertToLabel(final EObject target, final String string) { IExpressionDescription ed = LabelExpressionDescription.create(string); ed.setTarget(target); if (target != null) { DescriptionFactory.setGamlDocumentation(target, ed.getExpression()); } return ed; } static final void convStatements( final ISyntacticElement elt, final List<? extends Statement> ss, final Set<Diagnostic> errors) { for (final Statement stm : ss) { ISyntacticElement child = convStatement(elt, stm, errors); if (child != null) { elt.addChild(child); } } } private static final IExpressionDescription findExpr( final Statement stm, final Set<Diagnostic> errors) { if (stm == null) { return null; } // The order below should be important String name = EGaml.getNameOf(stm); if (name != null) { return convertToLabel(stm, name); } Expression expr = stm.getExpr(); if (expr != null) { return convExpr(expr, errors); } return null; } private static final Set<String> varDependenciesOf(final Statement s) { Set<String> list = new HashSet(); for (Facet facet : EGaml.getFacetsOf(s)) { Expression expr = facet.getExpr(); if (expr != null) { if (expr instanceof VariableRef) { list.add(EGaml.getKey.caseVariableRef((VariableRef) expr)); } else { for (TreeIterator<EObject> tree = expr.eAllContents(); tree.hasNext(); ) { EObject obj = tree.next(); if (obj instanceof VariableRef) { list.add(EGaml.getKey.caseVariableRef((VariableRef) obj)); } } } } } if (list.isEmpty()) { return null; } return list; } }
/** * The Class FsmStateStatement. * * @author drogoul */ @symbol( name = FsmStateStatement.STATE, kind = ISymbolKind.BEHAVIOR, with_sequence = true, unique_name = true) @inside( symbols = IKeyword.FSM, kinds = {ISymbolKind.SPECIES, ISymbolKind.EXPERIMENT, ISymbolKind.MODEL}) @facets( value = { @facet( name = FsmStateStatement.INITIAL, type = IType.BOOL, optional = true, doc = @doc("specifies whether the state is the initial one (default value = false)")), @facet( name = FsmStateStatement.FINAL, type = IType.BOOL, optional = true, doc = @doc( "specifies whether the state is a final one (i.e. there is no transition from this state to another state) (default value= false)")), @facet( name = IKeyword.NAME, type = IType.ID, optional = false, doc = @doc("the identifier of the state")) }, omissible = IKeyword.NAME) @validator(StateValidator.class) @doc( value = "A state, like a reflex, can contains several statements that can be executed at each time step by the agent.", usages = { @usage( value = "Here is an exemple integrating 2 states and the statements in the FSM architecture:", examples = { @example(value = " state s_init initial: true {", isExecutable = false), @example(value = " enter { write \"Enter in\" + state; }", isExecutable = false), @example(value = " write \"Enter in\" + state;", isExecutable = false), @example(value = " }", isExecutable = false), @example(value = "", isExecutable = false), @example(value = " write state;", isExecutable = false), @example(value = "", isExecutable = false), @example(value = " transition to: s1 when: (cycle > 2) {", isExecutable = false), @example(value = " write \"transition s_init -> s1\";", isExecutable = false), @example(value = " }", isExecutable = false), @example(value = "", isExecutable = false), @example(value = " exit {", isExecutable = false), @example(value = " write \"EXIT from \"+state;", isExecutable = false), @example(value = " }", isExecutable = false), @example(value = " }", isExecutable = false), @example(value = " state s1 {", isExecutable = false), @example(value = "", isExecutable = false), @example(value = " enter {write 'Enter in '+state;}", isExecutable = false), @example(value = "", isExecutable = false), @example(value = " write state;", isExecutable = false), @example(value = "", isExecutable = false), @example(value = " exit {write 'EXIT from '+state;}", isExecutable = false), @example(value = "}", isExecutable = false) }) }, see = {FsmStateStatement.ENTER, FsmStateStatement.EXIT, FsmTransitionStatement.TRANSITION}) public class FsmStateStatement extends AbstractStatementSequence { static List<String> AllowedArchitectures = Arrays.asList( IKeyword.USER_CONTROLLED, IKeyword.USER_FIRST, IKeyword.USER_INIT, IKeyword.USER_LAST, IKeyword.USER_ONLY); public static class StateValidator implements IDescriptionValidator { /** * Method validate() * * @see msi.gaml.compilation.IDescriptionValidator#validate(msi.gaml.descriptions.IDescription) */ @Override public void validate(final IDescription description) { // Verify that the state is inside a species with fsm control SpeciesDescription species = description.getSpeciesContext(); String keyword = description.getKeyword(); IArchitecture control = species.getControl(); // String control = species.getControlName(); if (!(control instanceof FsmArchitecture)) { if (keyword.equals(STATE)) { description.error( "A state can only be defined in an fsm-controlled or user-controlled species", IGamlIssue.WRONG_CONTEXT); return; } else if (control.getClass() == FsmArchitecture.class) { description.error( "A " + description.getKeyword() + " can only be defined in a user-controlled species (one of" + AllowedArchitectures + ")", IGamlIssue.WRONG_CONTEXT); return; } } if (!Assert.nameIsValid(description)) { return; } Facets ff = description.getFacets(); IExpression expr = ff.getExpr(INITIAL); if (IExpressionFactory.TRUE_EXPR.equals(expr)) { assertNoOther(description, INITIAL); } else { expr = ff.getExpr(FINAL); if (IExpressionFactory.TRUE_EXPR.equals(expr)) { assertNoOther(description, FINAL); } else { assertAtLeastOne(description, INITIAL); } } } private void assertNoOther(final IDescription desc, final String facet) { final IDescription sd = desc.getEnclosingDescription(); if (!(sd instanceof SpeciesDescription)) { return; } for (final IDescription child : ((SpeciesDescription) sd).getBehaviors()) { if (child.equals(desc) || !child.getKeyword().equals(STATE)) { continue; } IExpression expr = child.getFacets().getExpr(facet); if (IExpressionFactory.TRUE_EXPR.equals(expr)) { final String error = "Only one " + facet + " state is allowed."; child.error(error, IGamlIssue.DUPLICATE_DEFINITION, facet, TRUE); } } } private void assertAtLeastOne(final IDescription desc, final String facet) { final IDescription sd = desc.getEnclosingDescription(); if (!(sd instanceof SpeciesDescription)) { return; } for (final IDescription child : ((SpeciesDescription) sd).getBehaviors()) { String s = child.getKeyword(); if (s.equals(STATE) || s.equals(USER_PANEL)) { final IExpression expr = child.getFacets().getExpr(facet); if (expr == null) { continue; } if (IExpressionFactory.TRUE_EXPR.equals(expr)) { return; } } } final String error = "No " + facet + " state defined"; sd.error( error, IGamlIssue.MISSING_DEFINITION, sd.getUnderlyingElement(null), desc.getKeyword(), facet, TRUE); } } public static final String STATE_MEMORY = "state_memory"; public static final String INITIAL = "initial"; public static final String FINAL = "final"; protected static final String STATE = "state"; public static final String ENTER = "enter"; public static final String EXIT = "exit"; private FsmEnterStatement enterActions = null; private FsmExitStatement exitActions = null; List<FsmTransitionStatement> transitions = new ArrayList(); private int transitionsSize; boolean isInitial; boolean isFinal; public FsmStateStatement(final IDescription desc) { super(desc); setName(getLiteral(IKeyword.NAME)); // A VOIR isInitial = Cast.asBool(null, getLiteral(FsmStateStatement.INITIAL)); isFinal = Cast.asBool(null, getLiteral(FsmStateStatement.FINAL)); } @Override public void setChildren(final List<? extends ISymbol> children) { for (final ISymbol c : children) { if (c instanceof FsmEnterStatement) { enterActions = (FsmEnterStatement) c; } else if (c instanceof FsmExitStatement) { exitActions = (FsmExitStatement) c; } else if (c instanceof FsmTransitionStatement) { transitions.add((FsmTransitionStatement) c); } } children.remove(enterActions); children.remove(exitActions); children.removeAll(transitions); transitionsSize = transitions.size(); super.setChildren(children); } protected boolean beginExecution(final IScope scope) throws GamaRuntimeException { final IAgent agent = scope.getAgentScope(); if (scope.interrupted()) { return false; } final Boolean enter = (Boolean) agent.getAttribute(ENTER); Map<String, Object> memory = (Map) agent.getAttribute(STATE_MEMORY); if (enter || memory == null) { memory = new THashMap(); agent.setAttribute(STATE_MEMORY, memory); } else { for (final Map.Entry<String, Object> entry : memory.entrySet()) { scope.addVarWithValue(entry.getKey(), entry.getValue()); } } if (enter) { if (enterActions != null) { enterActions.executeOn(scope); } if (agent.dead()) { return false; } agent.setAttribute(ENTER, false); } return true; } protected Object bodyExecution(final IScope scope) throws GamaRuntimeException { return super.privateExecuteIn(scope); } protected String evaluateTransitions(final IScope scope) throws GamaRuntimeException { final IAgent agent = scope.getAgentScope(); for (int i = 0; i < transitionsSize; i++) { final FsmTransitionStatement transition = transitions.get(i); if (transition.evaluatesTrueOn(scope)) { final String futureState = transition.getName(); haltOn(scope); transition.executeOn(scope); scope.setAgentVarValue(agent, STATE, futureState); return futureState; } } if (!agent.dead()) { scope.saveAllVarValuesIn((Map) agent.getAttribute(STATE_MEMORY)); } return name; } @Override public Object privateExecuteIn(final IScope scope) throws GamaRuntimeException { if (!beginExecution(scope)) { return null; } bodyExecution(scope); return evaluateTransitions(scope); } public void haltOn(final IScope scope) throws GamaRuntimeException { if (exitActions != null) { exitActions.executeOn(scope); } } public FsmExitStatement getExitStatement() { return exitActions; } public boolean hasExitActions() { return exitActions != null; } public boolean isInitial() { return isInitial; } public boolean isFinal() { return isFinal; } }