public override IPStmt VisitGotoStmt(PParser.GotoStmtContext context) { PParser.StateNameContext stateNameContext = context.stateName(); string stateName = stateNameContext.state.GetText(); IStateContainer current = machine; foreach (PParser.IdenContext token in stateNameContext._groups) { current = current?.GetGroup(token.GetText()); if (current == null) { throw handler.MissingDeclaration(token, "group", token.GetText()); } } AST.States.State state = current?.GetState(stateName); if (state == null) { throw handler.MissingDeclaration(stateNameContext.state, "state", stateName); } PLanguageType expectedType = state.Entry?.Signature.ParameterTypes.ElementAtOrDefault(0) ?? PrimitiveType.Null; IPExpr[] rvaluesList = TypeCheckingUtils.VisitRvalueList(context.rvalueList(), exprVisitor).ToArray(); foreach (IPExpr arg in rvaluesList) { if (arg is LinearAccessRefExpr linearArg && linearArg.LinearType == LinearType.Swap) { throw handler.InvalidSwap(linearArg, "swap not allowed on goto"); } } IPExpr payload; if (rvaluesList.Length == 0) { payload = null; } else if (rvaluesList.Length == 1) { payload = rvaluesList[0]; } else { payload = new UnnamedTupleExpr(context, rvaluesList); } PLanguageType payloadType = payload?.Type ?? PrimitiveType.Null; if (!expectedType.IsAssignableFrom(payloadType)) { throw handler.TypeMismatch(context, payloadType, expectedType); } method.CanChangeState = true; return(new GotoStmt(context, state, payload)); }
public override IPStmt VisitReceiveStmt(PParser.ReceiveStmtContext context) { if (machine?.IsSpec == true) { throw handler.IllegalMonitorOperation(context, context.RECEIVE().Symbol, machine); } Dictionary <PEvent, Function> cases = new Dictionary <PEvent, Function>(); foreach (PParser.RecvCaseContext caseContext in context.recvCase()) { Function recvHandler = new Function(caseContext.anonEventHandler()) { Scope = table.MakeChildScope(), Owner = method.Owner, ParentFunction = method, Role = FunctionRole.ReceiveHandler }; if (caseContext.anonEventHandler().funParam() is PParser.FunParamContext param) { Variable paramVar = recvHandler.Scope.Put(param.name.GetText(), param, VariableRole.Param); paramVar.Type = TypeResolver.ResolveType(param.type(), recvHandler.Scope, handler); recvHandler.Signature.Parameters.Add(paramVar); } FunctionBodyVisitor.PopulateMethod(handler, recvHandler); foreach (PParser.EventIdContext eventIdContext in caseContext.eventList().eventId()) { if (!table.Lookup(eventIdContext.GetText(), out PEvent pEvent)) { throw handler.MissingDeclaration(eventIdContext, "event", eventIdContext.GetText()); } if (cases.ContainsKey(pEvent)) { throw handler.DuplicateReceiveCase(eventIdContext, pEvent); } PLanguageType expectedType = recvHandler.Signature.ParameterTypes.ElementAtOrDefault(0) ?? PrimitiveType.Null; if (!expectedType.IsAssignableFrom(pEvent.PayloadType)) { throw handler.TypeMismatch(caseContext.anonEventHandler(), expectedType, pEvent.PayloadType); } cases.Add(pEvent, recvHandler); } } method.CanReceive = true; return(new ReceiveStmt(context, cases)); }
public override IPExpr VisitCastExpr(PParser.CastExprContext context) { IPExpr subExpr = Visit(context.expr()); PLanguageType oldType = subExpr.Type; PLanguageType newType = TypeResolver.ResolveType(context.type(), table, handler); if (context.cast.Text.Equals("as")) { if (!newType.IsAssignableFrom(oldType) && !oldType.IsAssignableFrom(newType)) { throw handler.IncomparableTypes(context, oldType, newType); } return(new CastExpr(context, subExpr, newType)); } if (context.cast.Text.Equals("to")) { if (oldType.IsSameTypeAs(PrimitiveType.Int)) { if (newType.IsSameTypeAs(PrimitiveType.Int)) { return(subExpr); } if (newType.IsSameTypeAs(PrimitiveType.Float) || PLanguageType.TypeIsOfKind(newType, TypeKind.Enum)) { return(new CoerceExpr(context, subExpr, newType)); } } else if (oldType.IsSameTypeAs(PrimitiveType.Float)) { if (newType.IsSameTypeAs(PrimitiveType.Float)) { return(subExpr); } if (newType.IsSameTypeAs(PrimitiveType.Int)) { return(new CoerceExpr(context, subExpr, newType)); } } else if (PLanguageType.TypeIsOfKind(oldType, TypeKind.Enum)) { // TODO: are enum-to-enum coersions allowed? if (newType.IsSameTypeAs(oldType)) { return(subExpr); } if (newType.IsSameTypeAs(PrimitiveType.Int)) { return(new CoerceExpr(context, subExpr, newType)); } } throw handler.IncomparableTypes(context, oldType, newType); } throw new ArgumentException(nameof(context)); }
private (VariableAccessExpr, IPStmt) SaveInTemporary(IPExpr expr, PLanguageType tempType) { Antlr4.Runtime.ParserRuleContext location = expr.SourceLocation; Variable temp = function.Scope.Put($"$tmp{numTemp++}", location, VariableRole.Local | VariableRole.Temp); Debug.Assert(tempType.IsAssignableFrom(expr.Type)); temp.Type = tempType; function.AddLocalVariable(temp); AssignStmt stmt = new AssignStmt(location, new VariableAccessExpr(location, temp), expr); return(new VariableAccessExpr(location, temp), stmt); }
public static void CheckArgument(ITranslationErrorHandler handler, ParserRuleContext context, PLanguageType argumentType, IPExpr arg) { if (arg is ILinearRef linearRef) { if (linearRef.LinearType.Equals(LinearType.Swap) && !arg.Type.IsSameTypeAs(argumentType)) { throw handler.TypeMismatch(context, arg.Type, argumentType); } } if (!argumentType.IsAssignableFrom(arg.Type)) { throw handler.TypeMismatch(context, arg.Type, argumentType); } }
public override IPExpr VisitFunCallExpr(PParser.FunCallExprContext context) { string funName = context.fun.GetText(); if (!table.Lookup(funName, out Function function)) { throw handler.MissingDeclaration(context.fun, "function", funName); } // Check the arguments IPExpr[] arguments = TypeCheckingUtils.VisitRvalueList(context.rvalueList(), this).ToArray(); ISet <Variable> linearVariables = new HashSet <Variable>(); if (function.Signature.Parameters.Count != arguments.Length) { throw handler.IncorrectArgumentCount(context, arguments.Length, function.Signature.Parameters.Count); } for (int i = 0; i < arguments.Length; i++) { IPExpr argument = arguments[i]; PLanguageType paramType = function.Signature.Parameters[i].Type; if (!paramType.IsAssignableFrom(argument.Type)) { throw handler.TypeMismatch(context.rvalueList().rvalue(i), argument.Type, paramType); } if (argument is ILinearRef linearRef) { if (linearRef.LinearType == LinearType.Swap && !linearRef.Type.IsSameTypeAs(paramType)) { throw handler.TypeMismatch(context, linearRef.Type, paramType); } if (linearVariables.Contains(linearRef.Variable)) { throw handler.RelinquishedWithoutOwnership(linearRef); } linearVariables.Add(linearRef.Variable); } } method.AddCallee(function); return(new FunCallExpr(context, function, arguments)); }
public override IPStmt VisitReceiveStmt(PParser.ReceiveStmtContext context) { // TODO: can receive statements have event variables as their cases? var cases = new Dictionary <PEvent, Function>(); foreach (PParser.RecvCaseContext caseContext in context.recvCase()) { var recvHandler = new Function(caseContext.anonEventHandler()) { Scope = table.MakeChildScope(), Owner = method.Owner, Role = FunctionRole.ReceiveHandler }; if (caseContext.anonEventHandler().funParam() is PParser.FunParamContext param) { Variable paramVar = recvHandler.Scope.Put(param.name.GetText(), param, VariableRole.Param); paramVar.Type = TypeResolver.ResolveType(param.type(), recvHandler.Scope, handler); recvHandler.Signature.Parameters.Add(paramVar); } FunctionBodyVisitor.PopulateMethod(handler, recvHandler); foreach (PParser.EventIdContext eventIdContext in caseContext.eventList().eventId()) { if (!table.Lookup(eventIdContext.GetText(), out PEvent pEvent)) { throw handler.MissingDeclaration(eventIdContext, "event", eventIdContext.GetText()); } if (cases.ContainsKey(pEvent)) { throw handler.IssueError(eventIdContext, $"duplicate case for event {pEvent.Name} in receive"); } PLanguageType expectedType = recvHandler.Signature.ParameterTypes.ElementAtOrDefault(0) ?? PrimitiveType.Null; if (!expectedType.IsAssignableFrom(pEvent.PayloadType)) { throw handler.TypeMismatch(caseContext.anonEventHandler().funParam(), expectedType, pEvent.PayloadType); } cases.Add(pEvent, recvHandler); } } return(new ReceiveStmt(context, cases)); }
public override IPStmt VisitGotoStmt(PParser.GotoStmtContext context) { PParser.StateNameContext stateNameContext = context.stateName(); string stateName = stateNameContext.state.GetText(); IStateContainer current = machine; foreach (PParser.IdenContext token in stateNameContext._groups) { current = current?.GetGroup(token.GetText()); if (current == null) { throw handler.MissingDeclaration(token, "group", token.GetText()); } } State state = current?.GetState(stateName); if (state == null) { throw handler.MissingDeclaration(stateNameContext.state, "state", stateName); } IPExpr payload = null; PLanguageType expectedType = state.Entry.Signature.ParameterTypes.ElementAtOrDefault(0) ?? PrimitiveType.Null; if (context.rvalueList()?.rvalue() is PParser.RvalueContext[] rvalues) { if (rvalues.Length == 1) { payload = exprVisitor.Visit(rvalues[0]); } else { IPExpr[] tupleFields = rvalues.Select(exprVisitor.Visit).ToArray(); payload = new UnnamedTupleExpr(context, tupleFields, new TupleType(tupleFields.Select(f => f.Type).ToList())); } } PLanguageType payloadType = payload?.Type ?? PrimitiveType.Null; if (!expectedType.IsAssignableFrom(payloadType)) { throw handler.TypeMismatch(context, payloadType, expectedType); } return(new GotoStmt(context, state, payload)); }
public override IPExpr VisitFunCallExpr(PParser.FunCallExprContext context) { string funName = context.fun.GetText(); if (!table.Lookup(funName, out Function function)) { throw handler.MissingDeclaration(context.fun, "function", funName); } // Check the arguments // TODO: linearly typed arguments var arguments = (context.rvalueList()?.rvalue().Select(Visit) ?? Enumerable.Empty <IPExpr>()).ToArray(); ISet <Variable> linearVariables = new HashSet <Variable>(); for (var i = 0; i < arguments.Length; i++) { IPExpr argument = arguments[i]; PLanguageType paramType = function.Signature.Parameters[i].Type; if (!paramType.IsAssignableFrom(argument.Type)) { throw handler.TypeMismatch(context.rvalueList().rvalue(i), argument.Type, paramType); } if (argument is ILinearRef linearRef) { if (linearRef.LinearType == LinearType.Swap && !linearRef.Type.IsSameTypeAs(paramType)) { throw handler.TypeMismatch(context, linearRef.Type, paramType); } if (linearVariables.Contains(linearRef.Variable)) { throw handler.RelinquishedWithoutOwnership(linearRef); } linearVariables.Add(linearRef.Variable); } } return(new FunCallExpr(context, function, arguments)); }
public bool IsSameTypeAs(PLanguageType otherType) { return(IsAssignableFrom(otherType) && otherType.IsAssignableFrom(this)); }
public override IPExpr VisitCastExpr(PParser.CastExprContext context) { IPExpr subExpr = Visit(context.expr()); PLanguageType oldType = subExpr.Type; PLanguageType newType = TypeResolver.ResolveType(context.type(), table, handler); if (context.cast.Text.Equals("as")) { if (!newType.IsAssignableFrom(oldType) && !oldType.IsAssignableFrom(newType)) { throw handler.IncomparableTypes(context, oldType, newType); } return(new CastExpr(context, subExpr, newType)); } if (context.cast.Text.Equals("to")) { if (!(newType is PermissionType || newType.IsSameTypeAs(PrimitiveType.Int) || newType.IsSameTypeAs(PrimitiveType.Float))) { throw handler.IllegalTypeInCoerceExpr(context); } if (oldType.IsSameTypeAs(PrimitiveType.Int)) { if (newType.IsSameTypeAs(PrimitiveType.Int)) { return(subExpr); } if (newType.IsSameTypeAs(PrimitiveType.Float) || PLanguageType.TypeIsOfKind(newType, TypeKind.Enum)) { return(new CoerceExpr(context, subExpr, newType)); } } else if (oldType.IsSameTypeAs(PrimitiveType.Float)) { if (newType.IsSameTypeAs(PrimitiveType.Float)) { return(subExpr); } if (newType.IsSameTypeAs(PrimitiveType.Int)) { return(new CoerceExpr(context, subExpr, newType)); } } else if (PLanguageType.TypeIsOfKind(oldType, TypeKind.Enum)) { // TODO: are enum-to-enum coersions allowed? if (newType.IsSameTypeAs(oldType)) { return(subExpr); } if (newType.IsSameTypeAs(PrimitiveType.Int)) { return(new CoerceExpr(context, subExpr, newType)); } } else if (oldType.IsSameTypeAs(PrimitiveType.Machine) || oldType is PermissionType) { if (newType.IsSameTypeAs(oldType)) { return(subExpr); } if (newType is PermissionType) { if (oldType.IsSameTypeAs(PrimitiveType.Machine)) { return(new CoerceExpr(context, subExpr, newType)); } if (oldType is PermissionType) { if (newType.AllowedPermissions.Value.Any(x => !oldType.AllowedPermissions.Value.Contains(x)) ) { throw handler.IllegalInterfaceCoerce(context, oldType, newType); } return(new CoerceExpr(context, subExpr, newType)); } } } throw handler.IncomparableTypes(context, oldType, newType); } throw handler.InternalError(context, new ArgumentOutOfRangeException(nameof(context), "invalid cast")); }