Example #1
0
 public BuiltInUnaryOperator(string name, CheezType resType, CheezType sub, ComptimeExecution exe = null)
 {
     Name           = name;
     ResultType     = resType;
     SubExprType    = sub;
     this.Execution = exe;
 }
Example #2
0
        private bool ComputeSizeAndAlignmentOfRemainingTypes()
        {
            bool changes = false;

            while (true)
            {
                var typesWithMissingProperties = CheezType.TypesWithMissingProperties;
                if (typesWithMissingProperties.Count() == 0)
                {
                    break;
                }

                changes = true;

                CheezType.ClearAllTypes();
                foreach (var type in typesWithMissingProperties)
                {
                    {
                        if (type is AbstractType || type.IsErrorType || type.IsPolyType)
                        {
                            continue;
                        }

                        // force computation of all types sizes
                        GetSizeOfType(type);
                        IsTypeDefaultConstructable(type);
                    }
                }
            }

            return(changes);
        }
Example #3
0
 public NodeFinderResult(Scope s, AstExpression expr = null, AstStatement stmt = null, CheezType type = null)
 {
     Scope = s;
     Expr  = expr;
     Stmt  = stmt;
     Type  = type;
 }
Example #4
0
 public BuiltInBinaryOperator(string name, CheezType resType, CheezType lhs, CheezType rhs, ComptimeExecution exe = null)
 {
     Name       = name;
     ResultType = resType;
     LhsType    = lhs;
     RhsType    = rhs;
     Execution  = exe;
 }
Example #5
0
 public int Accepts(CheezType lhs, CheezType rhs)
 {
     if (lhs is FunctionType f1 && rhs is FunctionType f2 && f1 == f2)
     {
         return(0);
     }
     return(-1);
 }
Example #6
0
 public int Accepts(CheezType sub)
 {
     if (SubExprType == sub)
     {
         return(0);
     }
     return(-1);
 }
Example #7
0
 public int Accepts(CheezType lhs, CheezType rhs)
 {
     if (lhs == rhs && lhs == EnumType)
     {
         return(0);
     }
     return(-1);
 }
Example #8
0
 public int Accepts(CheezType lhs, CheezType rhs)
 {
     if (lhs is TraitType && rhs == PointerType.NullLiteralType)
     {
         return(0);
     }
     return(-1);
 }
Example #9
0
 public int Accepts(CheezType lhs, CheezType rhs)
 {
     if (lhs is PointerType lt && rhs is PointerType rt)
     {
         return(0);
     }
     return(-1);
 }
Example #10
0
        /// <summary>
        /// Returns a list of all impl blocks which apply to a given type
        ///
        /// </summary>
        /// <param name="type"></param>
        /// <param name="trait"></param>
        /// <returns></returns>
        public List <AstImplBlock> GetImplsForType(CheezType type, CheezType trait = null)
        {
            var impls = GetImplsForTypeHelper(type);

            if (trait != null)
            {
                return(impls.Where(i => i.Trait == trait).ToList());
            }
            return(impls.ToList());
        }
Example #11
0
        private int GetAlignOfType(CheezType type)
        {
            if (type.GetSize() >= 0)
            {
                return(type.GetAlignment());
            }
            var path = new List <CheezType>();

            return(ComputeSizeAndAlignmentOfType(type, path).alignment);
        }
Example #12
0
        private bool IsTypeDefaultConstructable(CheezType type)
        {
            if (type.IsDefaultConstructableComputed())
            {
                return(type.GetIsDefaultConstructable());
            }
            var path = new List <CheezType>();

            return(ComputeIsDefaultConstructableOfType(type, path));
        }
Example #13
0
        private bool SizeOfTypeDependsOnSelfType(CheezType type)
        {
            switch (type)
            {
            case SelfType _:
                return(true);

            case StructType str:
                ComputeStructMembers(str.Declaration);
                return(str.Declaration.Members.Any(m => SizeOfTypeDependsOnSelfType(m.Type)));

            case TupleType t:
                return(t.Members.Any(m => SizeOfTypeDependsOnSelfType(m.type)));

            case EnumType en:
                ComputeEnumMembers(en.Declaration);
                return(en.Declaration.Members.Any(m => m.AssociatedType != null ? SizeOfTypeDependsOnSelfType(m.AssociatedType) : false));

            case ArrayType t:
                return(SizeOfTypeDependsOnSelfType(t.TargetType));

            case RangeType r:
                return(SizeOfTypeDependsOnSelfType(r.TargetType));

            case ReferenceType _:
            case PointerType _:
            case SliceType _:
            case FunctionType _:
            case TraitType _:
            case VoidType _:
            case PolyType _:
            case IntType _:
            case FloatType _:
            case BoolType _:
            case CharType _:
            case StringType _:
                return(false);

            case CheezTypeType _:
                return(false);

            case GenericStructType _:
            case GenericEnumType _:
            case GenericTraitType _:
            case GenericFunctionType _:
                return(false);

            case ErrorType _:
                return(false);

            default:
                throw new NotImplementedException();
            }
        }
Example #14
0
 public int Accepts(CheezType lhs, CheezType rhs)
 {
     if (lhs is PolyValueType && rhs is PolyValueType)
     {
         return(0);
     }
     if (lhs is PolyValueType || rhs is PolyValueType)
     {
         return(1);
     }
     return(-1);
 }
Example #15
0
        public int Accepts(CheezType lhs, CheezType rhs)
        {
            var ml = LhsType.Match(lhs, null);
            var mr = RhsType.Match(rhs, null);

            if (ml == -1 || mr == -1)
            {
                return(-1);
            }

            return(ml + mr);
        }
Example #16
0
        public int Accepts(CheezType sub)
        {
            Dictionary <string, (CheezType type, object value)> polyTypes = null;

            // TODO: necessary?
            //if (SubExprType.IsPolyType)
            //{
            //    polyTypes = new Dictionary<string, CheezType>();
            //    Workspace.CollectPolyTypes(SubExprType, lhs, polyTypes);
            //}


            return(SubExprType.Match(sub, polyTypes));
        }
Example #17
0
        private AstExpression InferTypeGenericExpr(AstGenericExpr expr, CheezType expected, TypeInferenceContext context)
        {
            foreach (var param in expr.Parameters)
            {
                param.Scope = expr.Scope;
                param.TypeExpr.AttachTo(expr);
                param.TypeExpr = InferTypeHelper(param.TypeExpr, null, context);
                param.Type     = param.TypeExpr.Value as CheezType;
                if (!ValidatePolymorphicParameterType(param.Location, param.Type))
                {
                    return(expr);
                }
            }

            expr.Type  = new GenericType(expr);
            expr.Value = new PolyValue("generic");
            return(expr);
        }
Example #18
0
        public int Accepts(CheezType lhs, CheezType rhs)
        {
            Dictionary <string, (CheezType type, object value)> polyTypes = null;

            if (LhsType.IsPolyType || RhsType.IsPolyType)
            {
                polyTypes = new Dictionary <string, (CheezType type, object value)>();
                Workspace.CollectPolyTypes(LhsType, lhs, polyTypes);
                Workspace.CollectPolyTypes(RhsType, rhs, polyTypes);
            }


            var ml = LhsType.Match(lhs, polyTypes);
            var mr = RhsType.Match(rhs, polyTypes);

            if (ml == -1 || mr == -1)
            {
                return(-1);
            }
            return(ml + mr);
        }
Example #19
0
        private HashSet <AstImplBlock> GetImplsForTypeHelper(CheezType type)
        {
            if (type.IsErrorType)
            {
                WellThatsNotSupposedToHappen();
            }

            if (m_typeImplMap == null)
            {
                UpdateTypeImplMap();
            }

            if (m_typeImplMap.TryGetValue(type, out var _list))
            {
                return(_list.impls);
            }

            m_typeImplMap[type] = new TypeImplList(mAllImpls);

            UpdateTypeImplMap();

            return(m_typeImplMap[type].impls);
        }
Example #20
0
        private AstExpression ResolveTypeHelper(AstExpression expr, out CheezType type)
        {
            expr = InferType(expr, CheezType.Type);
            if (expr.Type.IsErrorType)
            {
                type       = CheezType.Error;
                expr.Value = CheezType.Error;
                return(expr);
            }

            if (expr.Type != CheezType.Type)
            {
                ReportError(expr, $"Expected type");
                type       = CheezType.Error;
                expr.Value = CheezType.Error;
                return(expr);
            }
            else
            {
                type = expr.Value as CheezType;
            }
            return(expr);
        }
Example #21
0
        private bool Move(CheezType targetType, AstExpression expr, SymbolStatusTable symStatTable, ILocation location)
        {
            //if (!(targetType is ReferenceType) && expr.Type is ReferenceType r && !r.TargetType.IsCopy)
            //{
            //    ReportError(location, $"Can't move out of reference, the type '{r.TargetType}' can't be copied");
            //    return false;
            //}

            switch (expr)
            {
            //case AstTempVarExpr tmp:
            //    {
            //        return Move(targetType, tmp.Expr, symStatTable, location);
            //    }

            case AstDotExpr dot:
            {
                if (dot.Left.Type is EnumType)
                {
                    Move(targetType, dot.Left, symStatTable, location);
                    return(true);
                }
                else if (!dot.Type.IsCopy)
                {
                    ReportError(location ?? expr, $"Can't move out of '{dot}' because type {dot.Type} is not copy");
                    return(false);
                }
                return(true);
            }

            case AstDereferenceExpr d when(!(targetType is ReferenceType) && d.Reference):
            {
                return(Move(targetType, d.SubExpression, symStatTable, location));
            }

            case AstIdExpr id:
            {
                if (symStatTable.TryGetSymbolStatus(id.Symbol, out var status))
                {
                    if (status.kind != SymbolStatus.Kind.initialized)
                    {
                        ReportError(location ?? expr, $"Can't move out of '{id.Name}' because it is {status.kind}",
                                    ("Moved here:", status.location));
                        return(false);
                    }
                    else
                    {
                        // check if type is move or copy
                        var type = (id.Symbol as ITypedSymbol).Type;
                        if (!type.IsCopy)
                        {
                            symStatTable.UpdateSymbolStatus(id.Symbol, SymbolStatus.Kind.moved, expr);
                        }
                    }
                }
                else if (id.Symbol is Using use)
                {
                    return(Move(targetType, use.Expr, symStatTable, id.Location));
                }
                return(true);
            }

            //case AstStructValueExpr _:
            //    // TODO: move arguments
            //    break;

            default:
                return(true);
            }
        }
Example #22
0
 public override int Match(CheezType concrete, Dictionary <string, (CheezType type, object value)> polyTypes)
Example #23
0
 private AstExpression ResolveTypeNow(AstExpression expr, out CheezType type, bool resolvePolyExprToConcreteType = false, HashSet <AstDecl> dependencies = null, bool forceInfer = false)
 {
     expr = InferType(expr, CheezType.Type, resolvePolyExprToConcreteType, dependencies, forceInfer);
     return(ResolveTypeHelper(expr, out type));
 }
Example #24
0
 private AstExpression ResolveType(AstExpression expr, List <AstDecl> newPolyDecls, out CheezType type)
 {
     expr = InferTypeHelper(expr, CheezType.Type, new TypeInferenceContext
     {
         newPolyDeclarations = newPolyDecls
     });
     return(ResolveTypeHelper(expr, out type));
 }
Example #25
0
 private AstExpression ResolveType(AstExpression expr, TypeInferenceContext context, out CheezType type)
 {
     expr = InferTypeHelper(expr, CheezType.Type, context);
     return(ResolveTypeHelper(expr, out type));
 }
Example #26
0
        private void Pass3TraitImpl(AstImplBlock impl)
        {
            if (!impl.IsPolyInstance)
            {
                impl.SubScope = new Scope($"impl {impl.TraitExpr} for {impl.TargetTypeExpr}", impl.Scope);
                if (impl.Parameters?.Count > 0)
                {
                    impl.IsPolymorphic = true;
                }
            }
            impl.TraitExpr.Scope = impl.SubScope;

            if (impl.IsPolymorphic)
            {
                // setup scopes
                foreach (var param in impl.Parameters)
                {
                    param.Scope          = impl.Scope;
                    param.TypeExpr.Scope = impl.Scope;
                    param.TypeExpr.SetFlag(ExprFlags.ValueRequired, true);
                    param.TypeExpr = ResolveTypeNow(param.TypeExpr, out var newType, forceInfer: true);

                    if (newType is AbstractType)
                    {
                        continue;
                    }

                    param.Type = newType;

                    switch (param.Type)
                    {
                    case CheezTypeType _:
                        param.Value = new PolyType(param.Name.Name, true);
                        if (param.Name != null)
                        {
                            impl.SubScope.DefineTypeSymbol(param.Name.Name, new PolyType(param.Name.Name, true));
                        }
                        break;

                    case IntType _:
                    case FloatType _:
                    case BoolType _:
                    case CharType _:
                        if (param.Name != null)
                        {
                            impl.SubScope.DefineConstant(param.Name.Name, param.Type, new PolyValue(param.Name.Name));
                        }
                        //impl.SubScope.DefineConstant(param.Name.Name, CheezType.PolyValue, new PolyValue(param.Name.Name));
                        break;

                    case ErrorType _:
                        break;

                    default:
                        ReportError(param.TypeExpr, $"The type '{param.Type}' is not allowed here.");
                        break;
                    }
                }
            }

            impl.TraitExpr.SetFlag(ExprFlags.ValueRequired, true);
            impl.TraitExpr = ResolveTypeNow(impl.TraitExpr, out var type, resolvePolyExprToConcreteType: true);


            if (type is TraitType tt)
            {
                impl.Trait = tt;
            }
            else
            {
                if (!type.IsErrorType)
                {
                    ReportError(impl.TraitExpr, $"{type} is not a trait");
                }
                impl.Trait = new TraitErrorType();
                return;
            }

            impl.TargetTypeExpr.SetFlag(ExprFlags.ValueRequired, true);
            impl.TargetTypeExpr.Scope = impl.SubScope;
            impl.TargetTypeExpr       = ResolveTypeNow(impl.TargetTypeExpr, out var t, resolvePolyExprToConcreteType: !impl.IsPolymorphic);
            impl.TargetType           = t;

            if (impl.TargetType is StructType @struct)
            {
                @struct.Declaration.Traits.Add(impl.Trait);
            }

            if (impl.Conditions != null)
            {
                if (impl.Parameters == null)
                {
                    ReportError(new Location(impl.Conditions.First().Location.Beginning, impl.Conditions.Last().Location.End), $"An impl block can't have a condition without parameters");
                }

                foreach (var cond in impl.Conditions)
                {
                    cond.Scope = impl.SubScope;
                }
            }

            if (impl.IsPolymorphic)
            {
                return;
            }

            impl.SubScope.DefineTypeSymbol("Self", impl.TargetType);

            // register impl in trait
            if (impl.Trait.Declaration.Implementations.TryGetValue(impl.TargetType, out var otherImpl))
            {
                ReportError(impl.TargetTypeExpr, $"There already exists an implementation of trait {impl.Trait} for type {impl.TargetType}",
                            ("Other implementation here:", otherImpl.TargetTypeExpr));
            }
            impl.Trait.Declaration.Implementations[impl.TargetType] = impl;

            // @TODO: should not be necessary
            AddTraitForType(impl.TargetType, impl);

            SortDeclarationsIntoImplBlock(impl);

            // handle functions
            foreach (var f in impl.Functions)
            {
                f.Scope      = impl.SubScope;
                f.ConstScope = new Scope($"fn$ {f.Name}", f.Scope);
                f.SubScope   = new Scope($"fn {f.Name}", f.ConstScope);
                f.ImplBlock  = impl;

                InferTypeFuncExpr(f);
                CheckForSelfParam(f);
                impl.Scope.DefineImplFunction(f);
                impl.SubScope.DefineSymbol(f);

                if (f.Body == null)
                {
                    ReportError(f.ParameterLocation, $"Function must have an implementation");
                }
            }

            ComputeTraitMembers(impl.Trait.Declaration);

            // match functions against trait functions
            foreach (var traitFunc in impl.Trait.Declaration.Functions)
            {
                // find matching function
                bool found = false;
                foreach (var func in impl.Functions)
                {
                    if (func.Name != traitFunc.Name)
                    {
                        continue;
                    }

                    func.TraitFunction = traitFunc;
                    found = true;

                    if (func.SelfType != traitFunc.SelfType)
                    {
                        ReportError(func.ParameterLocation,
                                    $"The self parameter of this function doesn't match the trait functions self parameter",
                                    ("Trait function defined here:", traitFunc.ParameterLocation));
                        continue;
                    }

                    if (func.Parameters.Count != traitFunc.Parameters.Count)
                    {
                        ReportError(func.ParameterLocation, $"This function must take the same parameters as the corresponding trait function", ("Trait function defined here:", traitFunc));
                        continue;
                    }

                    int i = 0;
                    // if first param is self param, skip it
                    if (func.SelfType != SelfParamType.None)
                    {
                        i = 1;
                    }

                    for (; i < func.Parameters.Count; i++)
                    {
                        var fp = func.Parameters[i];
                        var tp = traitFunc.Parameters[i];

                        if (tp.Type is SelfType)
                        {
                            if (fp.Type != impl.TargetType)
                            {
                                ReportError(
                                    fp.TypeExpr,
                                    $"Type of parameter '{fp.Type}' must be the implemented type '{impl.TargetType}'",
                                    ("Trait function parameter type defined here:", tp.TypeExpr));
                            }
                        }
                        else if (!CheezType.TypesMatch(fp.Type, tp.Type))
                        {
                            ReportError(
                                fp.TypeExpr,
                                $"Type of parameter '{fp.Type}' must match the type of the trait functions parameter '{tp.Type}'",
                                ("Trait function parameter type defined here:", tp.TypeExpr));
                        }
                    }

                    // check return type
                    if (traitFunc.ReturnType is SelfType)
                    {
                        if (func.ReturnType != impl.TargetType)
                        {
                            ReportError(
                                func.ReturnTypeExpr?.Location ?? func.ParameterLocation,
                                $"Return type '{func.ReturnType}' must be the implemented type '{impl.TargetType}'",
                                ("Trait function parameter type defined here:", traitFunc.ReturnTypeExpr?.Location ?? traitFunc.ParameterLocation));
                        }
                    }
                    else if (!CheezType.TypesMatch(func.ReturnType, traitFunc.ReturnType))
                    {
                        ReportError(
                            func.ReturnTypeExpr?.Location ?? func.ParameterLocation,
                            $"Return type must match the trait functions return type",
                            ("Trait function parameter type defined here:", traitFunc.ReturnTypeExpr?.Location ?? traitFunc.ParameterLocation));
                    }
                }

                if (!found)
                {
                    ReportError(
                        impl.TargetTypeExpr,
                        $"Missing implementation for trait function '{traitFunc.Name}'",
                        ("Trait function defined here:", traitFunc));
                }
            }
        }
Example #27
0
 public ConstSymbol(string name, CheezType type, object value)
 {
     this.Name  = name;
     this.Type  = type;
     this.Value = value;
 }
Example #28
0
 public BuiltInPolyValueBinaryOperator(string name, CheezType resType)
 {
     Name       = name;
     ResultType = resType;
 }
Example #29
0
 public TypeSymbol(string name, CheezType type)
 {
     this.Name = name;
     this.Type = type;
 }
Example #30
0
 public int Accepts(CheezType sub)
 {
     return(SubExprType.Match(sub, null));
 }