private IEnumerable <AstConstantDeclaration> SplitConstantDeclaration(AstConstantDeclaration v) { v.Pattern.SetFlag(ExprFlags.IsDeclarationPattern, true); switch (v.Pattern) { case AstCompCallExpr cc when cc.Name.Name == "id": cc.AttachTo(v); v.Name = InferType(cc, null) as AstIdExpr; break; case AstIdExpr name: // ok, do nothing v.Name = name; break; case AstTupleExpr t: v.Name = new AstIdExpr(GetUniqueName(t.ToString()), false, t); // create new declarations for sub patterns var index = 0; foreach (var subPattern in t.Values) { var init = new AstArrayAccessExpr( new AstConstantRef(v, v.Initializer), new AstNumberExpr(NumberData.FromBigInt(index), Location: v.Initializer)); var sub = new AstConstantDeclaration(subPattern, null, init, v.Documentation, null, Location: v); sub.Scope = v.Scope; sub.SetFlags(v.GetFlags()); yield return(sub); index += 1; } v.Pattern = v.Name; break; default: ReportError(v.Pattern, $"Invalid pattern in variable declaration"); break; } }
private IEnumerable <AstVariableDecl> SplitVariableDeclaration(AstVariableDecl v) { v.Pattern.SetFlag(ExprFlags.IsDeclarationPattern, true); switch (v.Pattern) { case AstCompCallExpr cc when cc.Name.Name == "id": cc.AttachTo(v); v.Name = InferType(cc, null) as AstIdExpr; break; case AstIdExpr name: // ok, do nothing v.Name = name; break; case AstTupleExpr t: { v.Name = new AstIdExpr(GetUniqueName(t.ToString()), false, t); v.Pattern = v.Name; //var initClone = v.Initializer.Clone(); //initClone.AttachTo(v); //initClone.SetFlag(ExprFlags.ValueRequired, true); //initClone = InferType(initClone, null); //AstVariableDecl CreateSub(int index, string name) //{ // var init = mCompiler.ParseExpression( // $"@{name}(§init)", // new Dictionary<string, AstExpression> // { // { "init", new AstVariableRef(v, v.Initializer) } // }); // var sub = new AstVariableDecl(t.Values[index], null, init, Location: v); // sub.Scope = v.Scope; // sub.SetFlags(v.GetFlags()); // return sub; //} //if (initClone.Type is PointerType pt1 && pt1.TargetType is AnyType) //{ // // create new declarations for sub patterns // yield return CreateSub(0, "ptr_of_any"); // yield return CreateSub(1, "type_info_of_any"); // break; //} //else if (initClone.Type is PointerType pt2 && pt2.TargetType is TraitType) //{ // // create new declarations for sub patterns // yield return CreateSub(0, "ptr_of_trait"); // yield return CreateSub(1, "vtable_of_trait"); // break; //} //else //{ // create new declarations for sub patterns var index = 0; foreach (var subPattern in t.Values) { var init = new AstArrayAccessExpr( new AstVariableRef(v, v.Initializer), new AstNumberExpr(NumberData.FromBigInt(index), Location: v.Initializer)); var sub = new AstVariableDecl(subPattern, null, init, v.Mutable, v.Documentation, Location: v); sub.Scope = v.Scope; sub.SetFlags(v.GetFlags()); yield return(sub); index += 1; } break; //} } default: ReportError(v.Pattern, $"Invalid pattern in variable declaration"); break; } }
private void ComputeEnumMembers(AstEnumTypeExpr expr) { if (expr.MembersComputed) { return; } expr.MembersComputed = true; BigInteger value = 0; var usedValues = new Dictionary <BigInteger, AstEnumMemberNew>(); foreach (var mem in expr.Members) { var memDecl = mem.Decl; if (!(memDecl.Pattern is AstIdExpr memName)) { ReportError(memDecl.Pattern, $"Only single names allowed"); continue; } if (memDecl.Directives != null) { foreach (var dir in memDecl.Directives) { InferTypeAttributeDirective(dir, memDecl, memDecl.Scope); } } if (memDecl.TypeExpr != null) { memDecl.TypeExpr.AttachTo(memDecl); memDecl.TypeExpr = ResolveTypeNow(memDecl.TypeExpr, out var t); memDecl.Type = t; // @todo: check if type is valid as enum member, eg no void } if (memDecl.Initializer != null) { memDecl.Initializer.AttachTo(memDecl); memDecl.Initializer = InferType(memDecl.Initializer, expr.TagType); ConvertLiteralTypeToDefaultType(memDecl.Initializer, expr.TagType); memDecl.Initializer = CheckType(memDecl.Initializer, expr.TagType); if (memDecl.Initializer.Type is IntType i) { if (memDecl.Initializer.IsCompTimeValue) { value = ((NumberData)memDecl.Initializer.Value).IntValue; CheckValueRangeForType(i, memDecl.Initializer.Value, memDecl.Initializer); } else { ReportError(memDecl.Initializer, $"Value of enum member has to be an constant integer"); } } } if (!expr.IsPolymorphic && expr.EnumType.IsCopy && (!memDecl.Type?.IsCopy ?? false)) { ReportError(memDecl, "Member is not copyable"); } if (usedValues.TryGetValue(value, out var other)) { if (other.AssociatedType != mem.AssociatedType) { ReportError(memDecl, $"Member has value {value} which is already being used by another member with different type", ("Other member here:", other.Location)); } } else { usedValues.Add(value, mem); } if (memDecl.Type != null) { ComputeTypeMembers(memDecl.Type); } if (expr.IsFlags && memDecl.Initializer == null && value != 0 && !value.IsPowerOfTwo()) { ReportError(memDecl, $"Member would have a value of '{value}', but this is not a power of two, so please provide a custom value for this member"); } mem.Value = NumberData.FromBigInt(value); if (expr.IsFlags) { if (value == 0) { value += 1; } else if (value.IsPowerOfTwo()) { value *= 2; } } else { value += 1; } } if (expr.IsReprC) { foreach (var mem in expr.Members) { if (mem.AssociatedType != null) { ReportError(mem.Location, $"Member can't have an associated value in repr c enum"); } } } }