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 ConvertStructDecl(Grammar.ASTNodeDeclStruct structNode, Core.Name curNamespace, List <Core.UseDirective> useDirectives) { var name = curNamespace.Concatenate(NameResolver.Resolve(structNode.name)); if (!ValidateName(name, structNode.name.GetSpan())) { return; } var structIndex = this.session.CreateStruct(name, structNode); foreach (var structUseNode in structNode.useDirectives) { useDirectives.Add(UseDirectiveResolver.Resolve(structUseNode)); } this.structWorkData.Add(new StructWorkData { name = name, declNode = structNode, declIndex = structIndex, useDirectives = useDirectives.ToArray() }); foreach (var structUseNode in structNode.useDirectives) { useDirectives.RemoveAt(useDirectives.Count - 1); } }
private void ConvertNamespaceDecl(Grammar.ASTNodeDeclNamespace namespaceNode, Core.Name curNamespace, List <Core.UseDirective> useDirectives) { var innerNamespace = curNamespace.Concatenate(NameResolver.ResolvePath(namespaceNode.path)); for (var i = 0; i < namespaceNode.path.identifiers.Count; i++) { useDirectives.Add(new Core.UseDirectiveAll { name = curNamespace.ConcatenateIdentifier(namespaceNode.path.identifiers[i].GetExcerpt()) }); } this.ConvertDeclGroup(namespaceNode.innerGroup, innerNamespace, useDirectives); for (var i = 0; i < namespaceNode.path.identifiers.Count; i++) { useDirectives.RemoveAt(useDirectives.Count - 1); } }
private void ConvertFunctDecl(Grammar.ASTNodeDeclFunct functNode, Core.Name curNamespace, List <Core.UseDirective> useDirectives) { var name = curNamespace.Concatenate(NameResolver.Resolve(functNode.name)); if (!ValidateName(name, functNode.name.GetSpan())) { return; } var functIndex = this.session.CreateFunct(name); this.functWorkData.Add(new FunctWorkData { name = name, declNode = functNode, declIndex = functIndex, useDirectives = useDirectives.ToArray() }); }
public static Core.Type ResolveStruct( Core.Session session, Grammar.ASTNodeName nameNode, IList <Core.UseDirective> useDirectives, bool mustBeResolved) { var name = NameResolver.Resolve(nameNode); var foundDecls = session.GetDeclsWithUseDirectives(name, nameNode.path.isRooted, useDirectives); if (!session.ValidateSingleDecl(foundDecls, name, nameNode.GetSpan())) { return(new Core.TypeError()); } if (!session.ValidateAsType(foundDecls[0], name, nameNode.GetSpan())) { return(new Core.TypeError()); } return(Core.TypeStruct.Of(foundDecls[0].index)); }
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 Core.DataAccess ResolveDataAccess(Grammar.ASTNodeExpr expr, ref int curSegment, bool allowInnerExpr, bool mutInnerExpr) { while (true) { var exprParenthesized = expr as Grammar.ASTNodeExprParenthesized; if (exprParenthesized != null) { expr = exprParenthesized.innerExpr; } else { break; } } var exprConcreteName = expr as Grammar.ASTNodeExprNameConcrete; if (exprConcreteName != null) { var name = NameResolver.Resolve(exprConcreteName.name); var bindingIndex = FindLocalBinding(name); if (bindingIndex >= 0) { var localRegisterIndex = funct.localBindings[bindingIndex].registerIndex; return(Core.DataAccessRegister.ForRegister(expr.GetSpan(), localRegisterIndex)); } else { this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.Unknown, "unknown '" + name.GetString() + "'", expr.GetSpan()); return(null); } } var exprDereference = expr as Grammar.ASTNodeExprUnaryOp; if (exprDereference != null && exprDereference.oper == Grammar.ASTNodeExprUnaryOp.Operator.At) { var innerAccess = ResolveDataAccess(exprDereference.operand, ref curSegment, true, false); return(Core.DataAccessDereference.Of(exprDereference.GetSpan(), innerAccess)); } var exprDotOp = expr as Grammar.ASTNodeExprBinaryOp; if (exprDotOp != null && exprDotOp.oper == Grammar.ASTNodeExprBinaryOp.Operator.Dot) { var baseAccess = ResolveDataAccess(exprDotOp.lhsOperand, ref curSegment, true, false); // Left-hand side expr type must be resolved for field access. FunctTypeInferencer.DoInference(this.session, this.funct); if (!TypeResolver.ValidateDataAccess(this.session, this.funct, baseAccess)) { this.foundErrors = true; return(null); } var lhsType = TypeResolver.GetDataAccessType(this.session, this.funct, baseAccess); var lhsStruct = lhsType as Core.TypeStruct; if (lhsStruct != null && lhsType.IsResolved()) { var rhsFieldName = exprDotOp.rhsOperand as Grammar.ASTNodeExprNameConcrete; if (rhsFieldName == null) { this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.Expected, "expected field name", exprDotOp.rhsOperand.GetSpan()); return(null); } var name = NameResolver.Resolve(rhsFieldName.name); int fieldIndex; if (!this.session.GetStruct(lhsStruct.structIndex).fieldNames.FindByName( name, out fieldIndex)) { this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.Unknown, "unknown field '" + name.GetString() + "' in '" + lhsType.GetString(this.session) + "'", exprDotOp.rhsOperand.GetSpan(), exprDotOp.lhsOperand.GetSpan()); return(null); } return(Core.DataAccessField.Of(exprDotOp.GetSpan(), baseAccess, fieldIndex)); } var lhsTuple = lhsType as Core.TypeTuple; if (lhsTuple != null) { var rhsFieldIndex = exprDotOp.rhsOperand as Grammar.ASTNodeExprLiteralInt; if (rhsFieldIndex == null) { this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.Expected, "expected field index", exprDotOp.rhsOperand.GetSpan()); return(null); } var fieldIndex = System.Convert.ToInt32(rhsFieldIndex.value); if (fieldIndex < 0 || fieldIndex >= lhsTuple.elementTypes.Length) { this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.Unknown, "invalid field index for '" + lhsType.GetString(this.session) + "'", exprDotOp.rhsOperand.GetSpan(), exprDotOp.lhsOperand.GetSpan()); return(null); } return(Core.DataAccessField.Of(exprDotOp.GetSpan(), baseAccess, fieldIndex)); } if (!lhsType.IsError() && !lhsType.IsResolved()) { this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.EarlyInferenceFailed, "type must be known but inference up to this point failed", exprDotOp.lhsOperand.GetSpan()); return(null); } this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.WrongFieldAccess, "attempted field access on '" + lhsType.GetString(this.session) + "'", exprDotOp.lhsOperand.GetSpan()); return(null); } if (allowInnerExpr) { // Generate a new register for inner expression. var registerIndex = this.funct.CreateRegister(new Core.TypePlaceholder(), mutInnerExpr); var access = Core.DataAccessRegister.ForRegister(expr.GetSpan(), registerIndex); ResolveExpr(expr, ref curSegment, access); // Create a new access for the same register, in case there's an outer // access modifier. access = Core.DataAccessRegister.ForRegister(expr.GetSpan(), registerIndex); return(access); } this.foundErrors = true; session.AddMessage( Diagnostics.MessageKind.Error, Diagnostics.MessageCode.InvalidAccess, "expression has no address", expr.GetSpan()); return(null); }
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)); } }