private void WriteTree(IPAST tree) { switch (tree) { case Function function: if (string.IsNullOrEmpty(function.Name)) { return; } WriteStmt("fun ", function, "(", WriteParams(function.Signature.Parameters), ") : ", function.Signature.ReturnType); WriteStmt("{"); Indent(); foreach (var localVariable in function.LocalVariables) { WriteTree(localVariable); } WriteTree(function.Body); Dedent(); WriteStmt("}"); break; case Interface @interface: WriteStmt("interface ", @interface, "(", @interface.PayloadType, ") receives ", WriteEventSet(@interface.ReceivableEvents), ";"); break; case Machine machine: WriteStmt(machine.IsSpec ? "spec " : "", "machine ", machine); var machineAssume = machine.Assume?.ToString() ?? "max"; var machineAssert = machine.Assert?.ToString() ?? "max"; WriteStmt(" assert ", machineAssert, " assume ", machineAssume); WriteStmt(" receives ", WriteEventSet(machine.Receives)); WriteStmt(" sends ", WriteEventSet(machine.Sends)); if (machine.IsSpec) { WriteStmt(" observes ", WriteEventSet(machine.Observes)); } WriteStmt("{"); Indent(); foreach (var machineField in machine.Fields) { WriteTree(machineField); } foreach (var machineMethod in machine.Methods) { WriteTree(machineMethod); } foreach (var machineGroup in machine.Groups) { WriteTree(machineGroup); } foreach (var machineState in machine.States) { WriteTree(machineState); } Dedent(); WriteStmt("}"); break; case NamedEventSet namedEventSet: WriteStmt("eventset ", namedEventSet, " = { ", string.Join(", ", namedEventSet.Events.Select(x => x.Name)), " };"); break; case PEnum pEnum: WriteStmt("enum ", pEnum, " = { ", pEnum.Values.Select(x => $"{x.Name} = {x.Value}"), " };"); break; case PEvent pEvent: WriteStmt("event ", pEvent, " assert ", pEvent.Assert, " assume ", pEvent.Assume, " : ", pEvent.PayloadType, ";"); break; case TypeDef typeDef: WriteStmt("type ", typeDef, " = ", typeDef.Type, ";"); break; case Variable variable: WriteStmt("var ", variable, " : ", variable.Type, ";"); break; case AnnounceStmt announceStmt: WriteStmt("announce ", announceStmt.PEvent, ", ", announceStmt.Payload, ";"); break; case AssertStmt assertStmt: WriteStmt("assert ", assertStmt.Assertion, ", \"", assertStmt.Message, "\";"); break; case AssignStmt assignStmt: WriteStmt(assignStmt.Location, " = ", assignStmt.Value, ";"); break; case CompoundStmt compoundStmt: foreach (var stmt in compoundStmt.Statements) { WriteTree(stmt); } break; case CtorStmt ctorStmt: WriteStmt("new ", ctorStmt.Interface, "(", ctorStmt.Arguments, ");"); break; case FunCallStmt funCallStmt: WriteStmt(funCallStmt.Function, "(", funCallStmt.ArgsList, ");"); break; case GotoStmt gotoStmt: WriteStmt("goto ", gotoStmt.State, ", ", gotoStmt.Payload, ";"); break; case IfStmt ifStmt: WriteStmt("if (", ifStmt.Condition, ")"); WriteStmt("{"); Indent(); WriteTree(ifStmt.ThenBranch); Dedent(); WriteStmt("}"); WriteStmt("else"); WriteStmt("{"); Indent(); WriteTree(ifStmt.ElseBranch); Dedent(); WriteStmt("}"); break; case InsertStmt insertStmt: WriteStmt(insertStmt.Variable, " += (", insertStmt.Index, ", ", insertStmt.Value, ");"); break; case MoveAssignStmt moveAssignStmt: WriteStmt(moveAssignStmt.ToLocation, " <- ", moveAssignStmt.FromVariable, " move;"); break; case NoStmt _: WriteStmt("; // no action"); break; case PopStmt _: WriteStmt("pop;"); break; case PrintStmt printStmt: WriteStmt("print \"", printStmt.Message, "\", ", printStmt.Args, ";"); break; case RaiseStmt raiseStmt: WriteStmt("raise ", raiseStmt.PEvent, ", ", raiseStmt.Payload, ";"); break; case ReceiveStmt receiveStmt: WriteStmt("receive {"); Indent(); foreach (var recvCase in receiveStmt.Cases) { WriteStmt("case ", recvCase.Key, " : (", WriteParams(recvCase.Value.Signature.Parameters), ") {"); Indent(); WriteTree(recvCase.Value.Body); Dedent(); WriteStmt("}"); } Dedent(); WriteStmt("}"); break; case RemoveStmt removeStmt: WriteStmt(removeStmt.Variable, " -= ", removeStmt.Value, ";"); break; case ReturnStmt returnStmt: WriteStmt("return ", returnStmt.ReturnValue, ";"); break; case SendStmt sendStmt: WriteStmt("send ", sendStmt.MachineExpr, ", ", sendStmt.Evt, ", ", sendStmt.Arguments, ";"); break; case SwapAssignStmt swapAssignStmt: WriteStmt(swapAssignStmt.NewLocation, " = ", swapAssignStmt.OldLocation, " swap; //swap assign"); break; case WhileStmt whileStmt: WriteStmt("while (", whileStmt.Condition, ")"); WriteStmt("{"); Indent(); WriteTree(whileStmt.Body); Dedent(); WriteStmt("}"); break; case EventDefer eventDefer: WriteStmt("defer ", eventDefer.Trigger, ";"); break; case EventDoAction eventDoAction: WriteParts(Padding, "on ", eventDoAction.Trigger, " do "); PrintFunctionRef(eventDoAction.Target); break; case EventGotoState eventGotoState: WriteStmt("on ", eventGotoState.Trigger, " goto ", eventGotoState.Target, " with "); PrintFunctionRef(eventGotoState.TransitionFunction); break; case EventIgnore eventIgnore: WriteStmt("ignore ", eventIgnore.Trigger, ";"); break; case EventPushState eventPushState: WriteStmt("on ", eventPushState.Trigger, " push ", eventPushState.Target, ";"); break; case State state: var start = state.IsStart ? "start " : ""; var temp = state.Temperature.Equals(StateTemperature.Cold) ? "cold " : state.Temperature.Equals(StateTemperature.Hot) ? "hot " : "warm "; WriteStmt(start, temp, "state ", state); WriteStmt("{"); Indent(); if (!string.IsNullOrEmpty(state.Entry?.Name)) { WriteStmt("entry ", state.Entry, ";"); } else { WriteStmt("entry"); WriteStmt("{"); Indent(); if (state.Entry is Function stateEntry) { foreach (var localVariable in stateEntry.LocalVariables) { WriteTree(localVariable); } WriteTree(stateEntry.Body); } else { WriteTree(new NoStmt(state.SourceLocation)); } Dedent(); WriteStmt("}"); } if (!string.IsNullOrEmpty(state.Exit?.Name)) { WriteStmt("exit ", state.Exit, ";"); } else { WriteStmt("exit"); WriteStmt("{"); Indent(); if (state.Exit is Function stateExit) { foreach (var localVariable in stateExit.LocalVariables) { WriteTree(localVariable); } WriteTree(stateExit.Body); } else { WriteTree(new NoStmt(state.SourceLocation)); } Dedent(); WriteStmt("}"); } foreach (var handler in state.AllEventHandlers) { WriteTree(handler.Value); } Dedent(); WriteStmt("}"); break; case StateGroup stateGroup: WriteStmt("group ", stateGroup); WriteStmt("{"); Indent(); foreach (var subGroup in stateGroup.Groups) { WriteTree(subGroup); } foreach (var state in stateGroup.States) { WriteTree(state); } Dedent(); WriteStmt("}"); break; case EnumElem _: break; default: WriteStmt($"// UNKNOWN declaration {tree.GetType().FullName}"); break; } }
public SourceLocation GetLocation(IPAST node) { return(GetLocation(node.SourceLocation)); }
private static IEnumerable <Interface> InferCreates(IPAST tree, ITranslationErrorHandler handler) { switch (tree) { case Function function: if (function.IsForeign) { return(function.CreatesInterfaces); } return(InferCreates(function.Body, handler)); case AddStmt addStmt: return(InferCreatesForExpr(addStmt.Variable, handler) .Union(InferCreatesForExpr(addStmt.Value, handler))); case AnnounceStmt announce: return(InferCreatesForExpr(announce.PEvent, handler) .Union(InferCreatesForExpr(announce.Payload, handler))); case AssertStmt assertStmt: return(InferCreatesForExpr(assertStmt.Assertion, handler)); case AssignStmt assignStmt: return(InferCreatesForExpr(assignStmt.Location, handler) .Union(InferCreatesForExpr(assignStmt.Value, handler))); case CompoundStmt compoundStmt: return(compoundStmt.Statements.SelectMany(tree1 => InferCreates(tree1, handler))); case CtorStmt ctorStmt: Interface[] res = new[] { ctorStmt.Interface }; return(res.Union(ctorStmt.Arguments.SelectMany(expr => InferCreatesForExpr(expr, handler)))); case FunCallStmt funCallStmt: return(InferCreates(funCallStmt.Function, handler) .Union(funCallStmt.ArgsList.SelectMany(expr => InferCreatesForExpr(expr, handler)))); case GotoStmt gotoStmt: return(InferCreatesForExpr(gotoStmt.Payload, handler)); case IfStmt ifStmt: return(InferCreatesForExpr(ifStmt.Condition, handler) .Union(InferCreates(ifStmt.ThenBranch, handler)) .Union(InferCreates(ifStmt.ElseBranch, handler))); case InsertStmt insertStmt: return(InferCreatesForExpr(insertStmt.Variable, handler) .Union(InferCreatesForExpr(insertStmt.Index, handler)) .Union(InferCreatesForExpr(insertStmt.Value, handler))); case MoveAssignStmt moveAssignStmt: return(InferCreatesForExpr(moveAssignStmt.ToLocation, handler)); case NoStmt _: return(Enumerable.Empty <Interface>()); case PopStmt _: return(Enumerable.Empty <Interface>()); case PrintStmt printStmt: return(printStmt.Args.SelectMany(expr => InferCreatesForExpr(expr, handler))); case RaiseStmt raiseStmt: return(InferCreatesForExpr(raiseStmt.PEvent, handler) .Union(raiseStmt.Payload.SelectMany(expr => InferCreatesForExpr(expr, handler)))); case ReceiveStmt receiveStmt: return(receiveStmt.Cases.SelectMany(x => InferCreates(x.Value, handler))); case RemoveStmt removeStmt: return(InferCreatesForExpr(removeStmt.Variable, handler) .Union(InferCreatesForExpr(removeStmt.Value, handler))); case ReturnStmt returnStmt: return(InferCreatesForExpr(returnStmt.ReturnValue, handler)); case StringAssignStmt stringAssignStmt: return(InferCreatesForExpr(stringAssignStmt.Location, handler) .Union(stringAssignStmt.Args.SelectMany(expr => InferCreatesForExpr(expr, handler)))); case BreakStmt breakStmt: return(Enumerable.Empty <Interface>()); case ContinueStmt continueStmt: return(Enumerable.Empty <Interface>()); case SendStmt sendStmt: return(InferCreatesForExpr(sendStmt.MachineExpr, handler) .Union(InferCreatesForExpr(sendStmt.Evt, handler)) .Union(sendStmt.Arguments.SelectMany(expr => InferCreatesForExpr(expr, handler)))); case SwapAssignStmt swapAssignStmt: return(InferCreatesForExpr(swapAssignStmt.NewLocation, handler)); case WhileStmt whileStmt: return(InferCreatesForExpr(whileStmt.Condition, handler) .Union(InferCreates(whileStmt.Body, handler))); default: throw handler.InternalError(tree.SourceLocation, new ArgumentOutOfRangeException(nameof(tree))); } }