private bool ValidateSource(List <InitStatus> statusList, Core.DataAccess source) { var initialized = CheckSourceRecursive(statusList, source); if (!initialized && !this.alreadyReportedSet.Contains(source.span)) { this.foundErrors = true; this.alreadyReportedSet.Add(source.span); var srcReg = source as Core.DataAccessRegister; if (srcReg != null && srcReg.registerIndex == 0) { this.session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.UninitializedUse, "not returning a value but expecting '" + funct.GetReturnType().GetString(session) + "'", source.span); } else { this.session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.UninitializedUse, "use of possibly uninitialized value", source.span); } } return(initialized); }
private bool CheckSourceRecursive(List <InitStatus> statusList, Core.DataAccess access) { var accessField = access as Core.DataAccessField; if (accessField != null) { return(CheckSourceRecursive(statusList, accessField.baseAccess)); } var accessReg = access as Core.DataAccessRegister; if (accessReg != null) { return(statusList[accessReg.registerIndex].IsInitialized()); } var accessDeref = access as Core.DataAccessDereference; if (accessDeref != null) { return(CheckSourceRecursive(statusList, accessDeref.innerAccess)); } return(false); }
private void ResolveExprCall(Grammar.ASTNodeExprCall exprCall, ref int curSegment, Core.DataAccess output) { // Parse called expression. var callTargetReg = Core.DataAccessRegister.ForRegister( exprCall.calledExpr.GetSpan(), funct.CreateRegister(new Core.TypePlaceholder(), false)); ResolveExpr(exprCall.calledExpr, ref curSegment, callTargetReg); // Parse argument expressions. var argumentRegs = new Core.DataAccess[exprCall.argumentExprs.Count]; for (var i = 0; i < exprCall.argumentExprs.Count; i++) { argumentRegs[i] = Core.DataAccessRegister.ForRegister( exprCall.argumentExprs[i].GetSpan(), funct.CreateRegister(new Core.TypePlaceholder(), false)); ResolveExpr(exprCall.argumentExprs[i], ref curSegment, argumentRegs[i]); } // Generate call instruction. funct.AddInstruction(curSegment, Core.InstructionMoveCallResult.For(exprCall.GetSpan(), output, callTargetReg, argumentRegs)); }
private string GenerateDataAccess(Core.DataAccess access, Core.DeclFunct funct) { var accessReg = access as Core.DataAccessRegister; if (accessReg != null) { return("var" + accessReg.registerIndex); } var accessDeref = access as Core.DataAccessDereference; if (accessDeref != null) { return("*(" + GenerateDataAccess(accessDeref.innerAccess, funct) + ")"); } var accessField = access as Core.DataAccessField; if (accessField != null) { var baseType = Semantics.TypeResolver.GetDataAccessType(this.session, funct, accessField.baseAccess); var fieldName = Semantics.TypeResolver.GetFieldName(this.session, baseType, accessField.fieldIndex); return("(" + GenerateDataAccess(accessField.baseAccess, funct) + ")." + fieldName.GetString()); } return("??"); }
private void ResolveExpr(Grammar.ASTNodeExpr expr, ref int curSegment, Core.DataAccess outputReg) { if (expr is Grammar.ASTNodeExprParenthesized) { this.ResolveExpr(((Grammar.ASTNodeExprParenthesized)expr).innerExpr, ref curSegment, outputReg); } else if (expr is Grammar.ASTNodeExprBlock) { this.ResolveExprBlock((Grammar.ASTNodeExprBlock)expr, ref curSegment, outputReg); } else if (expr is Grammar.ASTNodeExprLet) { this.ResolveExprLet((Grammar.ASTNodeExprLet)expr, ref curSegment, outputReg); } else if (expr is Grammar.ASTNodeExprIf) { this.ResolveExprIf((Grammar.ASTNodeExprIf)expr, ref curSegment, outputReg); } else if (expr is Grammar.ASTNodeExprWhile) { this.ResolveExprWhile((Grammar.ASTNodeExprWhile)expr, ref curSegment, outputReg); } else if (expr is Grammar.ASTNodeExprReturn) { this.ResolveExprReturn((Grammar.ASTNodeExprReturn)expr, ref curSegment, outputReg); } else if (expr is Grammar.ASTNodeExprCall) { this.ResolveExprCall((Grammar.ASTNodeExprCall)expr, ref curSegment, outputReg); } else if (expr is Grammar.ASTNodeExprUnaryOp) { this.ResolveExprUnaryOp((Grammar.ASTNodeExprUnaryOp)expr, ref curSegment, outputReg); } else if (expr is Grammar.ASTNodeExprBinaryOp) { this.ResolveExprBinaryOp((Grammar.ASTNodeExprBinaryOp)expr, ref curSegment, outputReg); } else if (expr is Grammar.ASTNodeExprName) { this.ResolveExprName((Grammar.ASTNodeExprName)expr, ref curSegment, outputReg); } else if (expr is Grammar.ASTNodeExprLiteralBool) { this.ResolveExprLiteralBool((Grammar.ASTNodeExprLiteralBool)expr, ref curSegment, outputReg); } else if (expr is Grammar.ASTNodeExprLiteralInt) { this.ResolveExprLiteralInt((Grammar.ASTNodeExprLiteralInt)expr, ref curSegment, outputReg); } else if (expr is Grammar.ASTNodeExprLiteralStruct) { this.ResolveExprLiteralStruct((Grammar.ASTNodeExprLiteralStruct)expr, ref curSegment, outputReg); } else { throw new System.NotImplementedException(); } }
private string GenerateDataStore(Core.DataAccess dest, Core.DeclFunct funct) { var destType = Semantics.TypeResolver.GetDataAccessType(this.session, funct, dest); if (destType.IsZeroSized(this.session)) { return(""); } return(GenerateDataAccess(dest, funct) + " = "); }
private bool ApplyToDataAccess(Core.DataAccess access, Core.Type type) { var regAccess = access as Core.DataAccessRegister; if (regAccess != null) { this.funct.registerTypes[regAccess.registerIndex] = type; return(true); } return(false); }
private void ResolveExprIf(Grammar.ASTNodeExprIf exprIf, ref int curSegment, Core.DataAccess output) { // Parse condition. var conditionReg = Core.DataAccessRegister.ForRegister( exprIf.conditionExpr.GetSpan(), funct.CreateRegister(Core.TypeStruct.Of(session.PrimitiveBool), false)); this.ResolveExpr( exprIf.conditionExpr, ref curSegment, conditionReg); var flowBranch = new Core.SegmentFlowBranch { conditionReg = conditionReg }; funct.SetSegmentFlow(curSegment, flowBranch); // Parse true branch. var trueSegment = funct.CreateSegment(exprIf.trueBranchExpr.GetSpan().JustBefore()); flowBranch.destinationSegmentIfTaken = trueSegment; ResolveExpr(exprIf.trueBranchExpr, ref trueSegment, output); // Parse false branch, if there is one. if (exprIf.falseBranchExpr != null) { var falseSegment = funct.CreateSegment(exprIf.falseBranchExpr.GetSpan().JustBefore()); flowBranch.destinationSegmentIfNotTaken = falseSegment; ResolveExpr(exprIf.falseBranchExpr, ref falseSegment, output); var afterSegment = funct.CreateSegment(exprIf.GetSpan().JustAfter()); funct.SetSegmentFlow(trueSegment, Core.SegmentFlowGoto.To(afterSegment)); funct.SetSegmentFlow(falseSegment, Core.SegmentFlowGoto.To(afterSegment)); curSegment = afterSegment; } // Or else, just route the false segment path to the next segment. else { var afterSegment = funct.CreateSegment(exprIf.GetSpan().JustAfter()); funct.SetSegmentFlow(trueSegment, Core.SegmentFlowGoto.To(afterSegment)); flowBranch.destinationSegmentIfNotTaken = afterSegment; curSegment = afterSegment; } }
private void MarkTakenMutAddrRecursive(List <InitStatus> statusList, Core.DataAccess access) { var accessField = access as Core.DataAccessField; if (accessField != null) { MarkTakenMutAddrRecursive(statusList, accessField.baseAccess); return; } var accessReg = access as Core.DataAccessRegister; if (accessReg != null) { statusList[accessReg.registerIndex].takenMutAddr = true; return; } }
private void CheckMove(Core.DataAccess destination, Core.Type srcType, Diagnostics.Span srcSpan) { if (!TypeResolver.ValidateDataAccess(this.session, this.funct, destination)) { this.foundErrors = true; return; } var destType = TypeResolver.GetDataAccessType(this.session, this.funct, destination); if (destType == null) { return; } if (!srcType.IsConvertibleTo(destType) && ShouldDiagnose(srcType) && ShouldDiagnose(destType)) { this.foundErrors = true; var destReg = destination as Core.DataAccessRegister; if (destReg != null && destReg.registerIndex == 0) { this.session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.IncompatibleTypes, "returning '" + srcType.GetString(this.session) + "' " + "but expecting '" + destType.GetString(this.session) + "'", srcSpan, destination.span); } else { this.session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.IncompatibleTypes, "moving '" + srcType.GetString(this.session) + "' " + "into '" + destType.GetString(this.session) + "'", srcSpan, destination.span); } } }
public static Core.Type GetDataAccessType( Core.Session session, Core.DeclFunct funct, Core.DataAccess access) { var regAccess = access as Core.DataAccessRegister; if (regAccess != null) { return(funct.registerTypes[regAccess.registerIndex]); } var regField = access as Core.DataAccessField; if (regField != null) { return(GetFieldType( session, GetDataAccessType(session, funct, regField.baseAccess), regField.fieldIndex)); } var regDeref = access as Core.DataAccessDereference; if (regDeref != null) { var innerType = GetDataAccessType(session, funct, regDeref.innerAccess); var innerPtr = innerType as Core.TypePointer; if (innerPtr == null) { return(new Core.TypeError()); } return(innerPtr.pointedToType); } var regDiscard = access as Core.DataAccessDiscard; if (regDiscard != null) { return(Core.TypeTuple.Empty()); } return(new Core.TypeError()); }
public static bool GetDataAccessMutability( Core.Session session, Core.DeclFunct funct, Core.DataAccess access) { var regAccess = access as Core.DataAccessRegister; if (regAccess != null) { return(funct.registerMutabilities[regAccess.registerIndex]); } var regField = access as Core.DataAccessField; if (regField != null) { return(GetDataAccessMutability(session, funct, regField.baseAccess)); } var regDeref = access as Core.DataAccessDereference; if (regDeref != null) { var innerType = GetDataAccessType(session, funct, regDeref.innerAccess); var innerPtr = innerType as Core.TypePointer; if (innerPtr == null) { return(false); } if (!innerPtr.mutable) { return(false); } return(true); } return(false); }
public static bool ValidateDataAccess( Core.Session session, Core.DeclFunct funct, Core.DataAccess access) { var regDeref = access as Core.DataAccessDereference; if (regDeref != null) { var innerType = GetDataAccessType(session, funct, regDeref.innerAccess); var innerPtr = innerType as Core.TypePointer; if (innerPtr == null) { session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.CannotDereferenceType, "dereferencing '" + innerType.GetString(session) + "'", access.span); return(false); } } return(true); }
private void CheckAndInitDestinationRecursive(List <InitStatus> statusList, Core.DataAccess access) { var accessField = access as Core.DataAccessField; if (accessField != null) { if (ValidateSource(statusList, accessField.baseAccess)) { CheckAndInitDestinationRecursive(statusList, accessField.baseAccess); } return; } var accessReg = access as Core.DataAccessRegister; if (accessReg != null) { var status = statusList[accessReg.registerIndex]; if (status.IsInitialized()) { var destMut = TypeResolver.GetDataAccessMutability(this.session, this.funct, accessReg); if (!destMut) { this.foundErrors = true; this.session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.IncompatibleMutability, "value is not mutable", accessReg.span); } } status.SetStatus(true); status.IncrementCounter(); return; } var accessDeref = access as Core.DataAccessDereference; if (accessDeref != null) { if (ValidateSource(statusList, accessDeref.innerAccess)) { var destType = TypeResolver.GetDataAccessType(this.session, this.funct, accessDeref.innerAccess); var destPtr = destType as Core.TypePointer; if (destPtr != null && !destPtr.mutable) { this.foundErrors = true; this.session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.IncompatibleMutability, "value through pointer is not mutable", accessDeref.innerAccess.span); } } return; } }
private void CheckAndInitDestination(List <InitStatus> statusList, Core.DataAccess destination) { CheckAndInitDestinationRecursive(statusList, destination); }
private void ResolveExprName(Grammar.ASTNodeExprName exprName, ref int curSegment, Core.DataAccess output) { var name = NameResolver.Resolve(((Grammar.ASTNodeExprNameConcrete)exprName).name); // Try to find a local with the same name. var bindingIndex = FindLocalBinding(name); if (bindingIndex >= 0) { funct.AddInstruction(curSegment, Core.InstructionMoveData.Of( exprName.GetSpan(), output, Core.DataAccessRegister.ForRegister( exprName.GetSpan(), funct.localBindings[bindingIndex].registerIndex))); return; } // Try to find a group of functs with the same name. var functList = session.GetDeclsWithUseDirectives(name, false, useDirectives); if (session.ValidateSingleDecl(functList, name, exprName.GetSpan()) && session.ValidateAsFunct(functList[0], name, exprName.GetSpan())) { funct.AddInstruction(curSegment, Core.InstructionMoveLiteralFunct.With(exprName.GetSpan(), output, functList[0].index)); return; } this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.Unknown, "unknown '" + name.GetString() + "'", exprName.GetSpan()); throw new Core.CheckException(); }
private void ResolveExprWhile(Grammar.ASTNodeExprWhile exprWhile, ref int curSegment, Core.DataAccess output) { var registerIndexBefore = funct.registerTypes.Count; var conditionSegment = funct.CreateSegment(exprWhile.conditionExpr.GetSpan()); funct.SetSegmentFlow(curSegment, Core.SegmentFlowGoto.To(conditionSegment)); // Parse condition. var conditionReg = Core.DataAccessRegister.ForRegister( exprWhile.conditionExpr.GetSpan(), funct.CreateRegister(Core.TypeStruct.Of(session.PrimitiveBool), false)); this.ResolveExpr( exprWhile.conditionExpr, ref conditionSegment, conditionReg); var flowBranch = new Core.SegmentFlowBranch { conditionReg = conditionReg }; funct.SetSegmentFlow(conditionSegment, flowBranch); // Parse body. var bodySegment = funct.CreateSegment(exprWhile.bodyExpr.GetSpan().JustBefore()); flowBranch.destinationSegmentIfTaken = bodySegment; ResolveExpr(exprWhile.bodyExpr, ref bodySegment, output); // Deinit inner registers. for (var i = funct.registerTypes.Count - 1; i >= registerIndexBefore; i--) { funct.AddInstruction(bodySegment, Core.InstructionDeinit.ForRegister(i)); } // Route segments. var afterSegment = funct.CreateSegment(exprWhile.GetSpan().JustAfter()); funct.SetSegmentFlow(bodySegment, Core.SegmentFlowGoto.To(conditionSegment)); flowBranch.destinationSegmentIfNotTaken = afterSegment; curSegment = afterSegment; }
private void ResolveExprLet(Grammar.ASTNodeExprLet exprLet, ref int curSegment, Core.DataAccess output) { // Create a new storage location and name binding. var registerIndex = funct.CreateRegister(new Core.TypePlaceholder(), exprLet.mutable); var name = NameResolver.Resolve(((Grammar.ASTNodeExprNameConcrete)exprLet.name).name); funct.CreateBinding( name, registerIndex, exprLet.name.GetSpan()); localScopeLivenesses.Add(true); // Parse type annotation, if there is one. if (exprLet.type != null) { funct.registerTypes[registerIndex] = TypeResolver.Resolve(session, exprLet.type, useDirectives, false); } // Parse init expression, if there is one. if (exprLet.initExpr != null) { ResolveExpr(exprLet.initExpr, ref curSegment, Core.DataAccessRegister.ForRegister(exprLet.name.GetSpan(), registerIndex)); } // Generate a void store. funct.AddInstruction(curSegment, Core.InstructionMoveLiteralTuple.Empty(exprLet.GetSpan(), output)); }
private void ResolveExprLiteralStruct(Grammar.ASTNodeExprLiteralStruct exprLiteralStruct, ref int curSegment, Core.DataAccess output) { var type = TypeResolver.ResolveStruct(session, exprLiteralStruct.name, useDirectives, true); if (!type.IsResolved()) { return; } var typeStruct = type as Core.TypeStruct; var fieldNum = TypeResolver.GetFieldNum(this.session, typeStruct); var fieldDestSpans = new Diagnostics.Span?[fieldNum]; var fieldRegs = new int[fieldNum]; for (var i = 0; i < fieldNum; i++) { fieldRegs[i] = funct.CreateRegister( TypeResolver.GetFieldType(this.session, typeStruct, i), false); } var fieldRegAccesses = new Core.DataAccess[fieldNum]; for (var i = 0; i < fieldNum; i++) { fieldRegAccesses[i] = Core.DataAccessRegister.ForRegister(exprLiteralStruct.name.GetSpan(), fieldRegs[i]); } foreach (var fieldInit in exprLiteralStruct.fields) { var name = NameResolver.Resolve(fieldInit.name); int fieldIndex; if (!this.session.GetStruct(typeStruct.structIndex).fieldNames.FindByName(name, out fieldIndex)) { this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.Unknown, "unknown field '" + name.GetString() + "' in '" + type.GetString(this.session) + "'", fieldInit.name.GetSpan()); continue; } if (fieldDestSpans[fieldIndex].HasValue) { this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.Unknown, "duplicate field '" + name.GetString() + "' initialization", fieldInit.name.GetSpan(), fieldDestSpans[fieldIndex].Value); continue; } fieldRegAccesses[fieldIndex].span = fieldInit.name.GetSpan(); fieldDestSpans[fieldIndex] = fieldInit.name.GetSpan(); this.ResolveExpr(fieldInit.expr, ref curSegment, fieldRegAccesses[fieldIndex]); } var missingFields = new List <int>(); for (var i = 0; i < fieldNum; i++) { if (!fieldDestSpans[i].HasValue) { missingFields.Add(i); } } if (missingFields.Count > 0) { Core.Name fieldName; session.GetStruct(typeStruct.structIndex).fieldNames.FindByValue(missingFields[0], out fieldName); this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.Unknown, "missing initializer" + (missingFields.Count > 1 ? "s" : "") + " for field '" + fieldName.GetString() + "'" + (missingFields.Count > 1 ? " and other " + (missingFields.Count - 1) : ""), exprLiteralStruct.GetSpan()); } else { var finalFieldDestSpans = new Diagnostics.Span[fieldNum]; for (var i = 0; i < fieldNum; i++) { finalFieldDestSpans[i] = fieldDestSpans[i].Value; } funct.AddInstruction(curSegment, Core.InstructionMoveLiteralStruct.Of( exprLiteralStruct.GetSpan(), output, typeStruct.structIndex, fieldRegAccesses, finalFieldDestSpans)); } }
private void ResolveExprCall(Grammar.ASTNodeExprCall exprCall, ref int curSegment, Core.DataAccess output) { // Parse called expression. var callTargetReg = Core.DataAccessRegister.ForRegister( exprCall.calledExpr.GetSpan(), funct.CreateRegister(new Core.TypePlaceholder(), false)); ResolveExpr(exprCall.calledExpr, ref curSegment, callTargetReg); // Parse argument expressions. var argumentRegs = new Core.DataAccess[exprCall.argumentExprs.Count]; for (var i = 0; i < exprCall.argumentExprs.Count; i++) { argumentRegs[i] = Core.DataAccessRegister.ForRegister( exprCall.argumentExprs[i].GetSpan(), funct.CreateRegister(new Core.TypePlaceholder(), false)); ResolveExpr(exprCall.argumentExprs[i], ref curSegment, argumentRegs[i]); } // Generate call instruction. funct.AddInstruction(curSegment, Core.InstructionMoveCallResult.For(exprCall.GetSpan(), output, callTargetReg, argumentRegs)); }
private void ResolveExprBinaryOp(Grammar.ASTNodeExprBinaryOp exprBinOp, ref int curSegment, Core.DataAccess output) { if (exprBinOp.oper == Grammar.ASTNodeExprBinaryOp.Operator.Equal) { var access = ResolveDataAccess(exprBinOp.lhsOperand, ref curSegment, false, false); if (access == null) { return; } // Parse right-hand side expression. ResolveExpr( exprBinOp.rhsOperand, ref curSegment, access); // Generate a void store. funct.AddInstruction( curSegment, Core.InstructionMoveLiteralTuple.Empty(exprBinOp.GetSpan(), output)); return; } else if (exprBinOp.oper == Grammar.ASTNodeExprBinaryOp.Operator.Dot) { var access = ResolveDataAccess(exprBinOp, ref curSegment, false, false); if (access == null) { return; } funct.AddInstruction(curSegment, Core.InstructionMoveData.Of( exprBinOp.GetSpan(), output, access)); return; } throw new System.NotImplementedException(); }
private void ResolveExprUnaryOp(Grammar.ASTNodeExprUnaryOp exprUnOp, ref int curSegment, Core.DataAccess output) { if (exprUnOp.oper == Grammar.ASTNodeExprUnaryOp.Operator.Asterisk || exprUnOp.oper == Grammar.ASTNodeExprUnaryOp.Operator.AsteriskMut) { var mutable = (exprUnOp.oper == Grammar.ASTNodeExprUnaryOp.Operator.AsteriskMut); // Parse addressed expression. var access = ResolveDataAccess(exprUnOp.operand, ref curSegment, true, mutable); if (access == null) { return; } // Store pointer. funct.AddInstruction( curSegment, Core.InstructionMoveAddr.Of(exprUnOp.GetSpan(), output, access, mutable)); return; } else if (exprUnOp.oper == Grammar.ASTNodeExprUnaryOp.Operator.At) { // Parse addressed expression. var access = ResolveDataAccess(exprUnOp, ref curSegment, true, false); if (access == null) { return; } // Store pointer. funct.AddInstruction( curSegment, Core.InstructionMoveData.Of(exprUnOp.GetSpan(), output, access)); return; } throw new System.NotImplementedException(); }
private void MarkTakenMutAddr(List <InitStatus> statusList, Core.DataAccess destination) { MarkTakenMutAddrRecursive(statusList, destination); }
private void ResolveExprBlock(Grammar.ASTNodeExprBlock exprBlock, ref int curSegment, Core.DataAccess outputReg) { // Generate an empty tuple store if there are no subexpressions. if (exprBlock.subexprs.Count == 0) { funct.AddInstruction(curSegment, Core.InstructionMoveLiteralTuple.Empty(exprBlock.GetSpan().Displace(1, -1), outputReg)); return; } // Store the indices marking inner locals/registers. var localScopeIndexBefore = localScopeLivenesses.Count; var registerIndexBefore = funct.registerTypes.Count; for (int i = 0; i < exprBlock.subexprs.Count; i++) { try { var subexprOutput = outputReg; if (i < exprBlock.subexprs.Count - 1) { subexprOutput = new Core.DataAccessDiscard(); } this.ResolveExpr(exprBlock.subexprs[i], ref curSegment, subexprOutput); } catch (Core.CheckException) { } } // Mark inner locals as out-of-scope. for (var i = localScopeIndexBefore; i < localScopeLivenesses.Count; i++) { localScopeLivenesses[i] = false; } // Deinit inner registers. for (var i = funct.registerTypes.Count - 1; i >= registerIndexBefore; i--) { funct.AddInstruction(curSegment, Core.InstructionDeinit.ForRegister(i)); } }
private void ResolveExprLiteralBool(Grammar.ASTNodeExprLiteralBool exprLiteralBool, ref int curSegment, Core.DataAccess output) { funct.AddInstruction(curSegment, Core.InstructionMoveLiteralBool.Of( exprLiteralBool.GetSpan(), output, exprLiteralBool.value)); }
private void ResolveExprReturn(Grammar.ASTNodeExprReturn exprRet, ref int curSegment, Core.DataAccess output) { // Generate a void store. funct.AddInstruction(curSegment, Core.InstructionMoveLiteralTuple.Empty(exprRet.GetSpan(), output)); // Parse returned expr, if there is one. if (exprRet.expr != null) { ResolveExpr(exprRet.expr, ref curSegment, Core.DataAccessRegister.ForRegister(exprRet.expr.GetSpan(), 0)); funct.SetSegmentFlow(curSegment, new Core.SegmentFlowEnd()); } // Else, return a void. else { funct.AddInstruction(curSegment, Core.InstructionMoveLiteralTuple.Empty( exprRet.GetSpan(), Core.DataAccessRegister.ForRegister(exprRet.expr.GetSpan(), 0))); funct.SetSegmentFlow(curSegment, new Core.SegmentFlowEnd()); } // Create next unlinked segment. curSegment = funct.CreateSegment(exprRet.GetSpan().JustAfter()); }
private void ResolveExprLiteralStruct(Grammar.ASTNodeExprLiteralStruct exprLiteralStruct, ref int curSegment, Core.DataAccess output) { var type = TypeResolver.ResolveStruct(session, exprLiteralStruct.name, useDirectives, true); if (!type.IsResolved()) return; var typeStruct = type as Core.TypeStruct; var fieldNum = TypeResolver.GetFieldNum(this.session, typeStruct); var fieldDestSpans = new Diagnostics.Span?[fieldNum]; var fieldRegs = new int[fieldNum]; for (var i = 0; i < fieldNum; i++) { fieldRegs[i] = funct.CreateRegister( TypeResolver.GetFieldType(this.session, typeStruct, i), false); } var fieldRegAccesses = new Core.DataAccess[fieldNum]; for (var i = 0; i < fieldNum; i++) { fieldRegAccesses[i] = Core.DataAccessRegister.ForRegister(exprLiteralStruct.name.GetSpan(), fieldRegs[i]); } foreach (var fieldInit in exprLiteralStruct.fields) { var name = NameResolver.Resolve(fieldInit.name); int fieldIndex; if (!this.session.GetStruct(typeStruct.structIndex).fieldNames.FindByName(name, out fieldIndex)) { this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.Unknown, "unknown field '" + name.GetString() + "' in '" + type.GetString(this.session) + "'", fieldInit.name.GetSpan()); continue; } if (fieldDestSpans[fieldIndex].HasValue) { this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.Unknown, "duplicate field '" + name.GetString() + "' initialization", fieldInit.name.GetSpan(), fieldDestSpans[fieldIndex].Value); continue; } fieldRegAccesses[fieldIndex].span = fieldInit.name.GetSpan(); fieldDestSpans[fieldIndex] = fieldInit.name.GetSpan(); this.ResolveExpr(fieldInit.expr, ref curSegment, fieldRegAccesses[fieldIndex]); } var missingFields = new List<int>(); for (var i = 0; i < fieldNum; i++) { if (!fieldDestSpans[i].HasValue) missingFields.Add(i); } if (missingFields.Count > 0) { Core.Name fieldName; session.GetStruct(typeStruct.structIndex).fieldNames.FindByValue(missingFields[0], out fieldName); this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.Unknown, "missing initializer" + (missingFields.Count > 1 ? "s" : "") + " for field '" + fieldName.GetString() + "'" + (missingFields.Count > 1 ? " and other " + (missingFields.Count - 1) : ""), exprLiteralStruct.GetSpan()); } else { var finalFieldDestSpans = new Diagnostics.Span[fieldNum]; for (var i = 0; i < fieldNum; i++) { finalFieldDestSpans[i] = fieldDestSpans[i].Value; } funct.AddInstruction(curSegment, Core.InstructionMoveLiteralStruct.Of( exprLiteralStruct.GetSpan(), output, typeStruct.structIndex, fieldRegAccesses, finalFieldDestSpans)); } }
private void ResolveExprLiteralInt(Grammar.ASTNodeExprLiteralInt exprLiteralInt, ref int curSegment, Core.DataAccess output) { funct.AddInstruction(curSegment, Core.InstructionMoveLiteralInt.Of( exprLiteralInt.GetSpan(), output, Core.TypeStruct.Of(session.PrimitiveInt), System.Convert.ToInt64(exprLiteralInt.GetExcerpt()))); }