private static bool CheckField( Core.Session session, int structIndex, int fieldIndex, Core.Type innerType, Stack <int> seenStructs) { var fieldStruct = innerType as Core.TypeStruct; if (fieldStruct == null) { return(false); } var st = session.GetStruct(structIndex); Core.Name fieldName; st.fieldNames.FindByValue(fieldIndex, out fieldName); session.PushContext( "in struct '" + session.GetStructName(structIndex).GetString() + "', " + "field '" + fieldName.GetString() + "'", st.GetFieldNameSpan(fieldIndex)); var err = false; if (seenStructs.Contains(fieldStruct.structIndex)) { err = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.StructRecursion, "struct recursion", session.GetStruct(fieldStruct.structIndex).GetNameSpan(), st.GetFieldNameSpan(fieldIndex)); } if (!err) { CheckStruct(session, fieldStruct.structIndex, seenStructs); } session.PopContext(); return(err); }
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); }
public static Core.Type ResolveStruct( Core.Session session, Grammar.ASTNodeExprName nameNode, IList <Core.UseDirective> useDirectives, bool mustBeResolved) { var nameConcreteNode = nameNode as Grammar.ASTNodeExprNameConcrete; if (nameConcreteNode == null) { if (mustBeResolved) { session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.Expected, "type must be known", nameNode.GetSpan()); } return(new Core.TypeError()); } return(ResolveStruct(session, nameConcreteNode.name, useDirectives, mustBeResolved)); }
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)); } }
public static Core.Type Resolve( Core.Session session, Grammar.ASTNodeType typeNode, IList <Core.UseDirective> useDirectives, bool mustBeResolved) { var typePlaceholderNode = typeNode as Grammar.ASTNodeTypePlaceholder; if (typePlaceholderNode != null) { if (mustBeResolved) { session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.Expected, "type must be known", typeNode.GetSpan()); return(new Core.TypeError()); } return(new Core.TypePlaceholder()); } var typeStructNode = typeNode as Grammar.ASTNodeTypeStruct; if (typeStructNode != null) { return(ResolveStruct(session, typeStructNode.name, useDirectives, mustBeResolved)); } var typeTupleNode = typeNode as Grammar.ASTNodeTypeTuple; if (typeTupleNode != null) { var elementTypes = new Core.Type[typeTupleNode.elements.Count]; for (var i = 0; i < typeTupleNode.elements.Count; i++) { elementTypes[i] = Resolve(session, typeTupleNode.elements[i], useDirectives, mustBeResolved); } return(Core.TypeTuple.Of(elementTypes)); } var typeFunctNode = typeNode as Grammar.ASTNodeTypeFunct; if (typeFunctNode != null) { var returnType = Resolve(session, typeFunctNode.returnType, useDirectives, mustBeResolved); var parameterTypes = new Core.Type[typeFunctNode.parameters.Count]; for (var i = 0; i < typeFunctNode.parameters.Count; i++) { parameterTypes[i] = Resolve(session, typeFunctNode.parameters[i], useDirectives, mustBeResolved); } return(Core.TypeFunct.Of(returnType, parameterTypes)); } var typeRefNode = typeNode as Grammar.ASTNodeTypePointer; if (typeRefNode != null) { return(Core.TypePointer.Of( typeRefNode.mutable, Resolve(session, typeRefNode.referenced, useDirectives, mustBeResolved))); } throw new System.NotImplementedException(); }
public static TokenCollection Tokenize(Core.Session session, Core.TextInput input) { var output = new TokenCollection(); // Iterate through all characters in input. var index = 0; while (index < input.Length()) { // Skip whitespace. if (IsWhitespace(input[index])) { index++; continue; } // Match next characters to a token, and add it to the output. var match = TryMatchModelToken(input, index) ?? TryMatchVaryingToken(input, index) ?? new TokenMatch(new string(input[index], 1), TokenKind.Error); var span = new Span(input, index, index + match.representation.Length); // Signal errors. if (match.kind == TokenKind.Error) { session.AddMessage(MessageKind.Error, MessageCode.UnexpectedChar, "unexpected character", span); } // Skip line comments. else if (match.kind == TokenKind.DoubleSlash) { while (index < input.Length() && input[index] != '\n') { index++; } continue; } // Skip multiline comments. else if (match.kind == TokenKind.SlashAsterisk) { var nesting = 1; index += 2; while (index < input.Length() - 1) { if (input[index] == '*' && input[index + 1] == '/') { nesting--; index += 2; if (nesting == 0) { break; } } else if (input[index] == '/' && input[index + 1] == '*') { nesting++; index += 2; } else { index++; } } if (nesting > 0) { session.AddMessage(MessageKind.Error, MessageCode.UnexpectedChar, "unterminated comment", span); } continue; } output.tokens.Add(new Token(match.kind, span)); index += match.representation.Length; } output.tokenAfterEnd = new Token(TokenKind.Error, new Diagnostics.Span(input, index, index)); return(output); }