コード例 #1
0
ファイル: ASTConverter.cs プロジェクト: MasterQ32/psi
        private Type ConvertType(TranslationUnit unit, IScope scope, AstType asttype)
        {
            if (asttype is LiteralType lt)
            {
                if (lt == LiteralType.Void)
                {
                    return(Type.VoidType);
                }
                else if (lt == LiteralType.Unknown)
                {
                    return(Type.UnknownType);
                }
                else
                {
                    throw new NotSupportedException("Unknown literal type!");
                }
            }
            else if (asttype is NamedTypeLiteral ntl)
            {
                var sym = scope.FindNamedSymbol(ntl.Name, Type.MetaType, true);
                if (sym != null)
                {
                    return(sym.GetValue <Type>());
                }
                else
                {
                    return(null);
                }
            }
            else if (asttype is EnumTypeLiteral etl)
            {
                return(new EnumType(etl.Items));
            }
            else if (asttype is ArrayTypeLiteral atl)
            {
                var type = new ArrayType
                {
                    Dimensions = atl.Dimensions
                };
                unit.AddTask(() =>
                {
                    type.ElementType = ConvertType(unit, scope, atl.ElementType);
                    if (type.ElementType == null)
                    {
                        return(Error.UnresolvableType(atl.ElementType));
                    }
                    return(CompilerError.None);
                });
                return(type);
            }
            else if (asttype is RecordTypeLiteral rtl)
            {
                var type = new RecordType();
                type.Members = new List <RecordMember>();
                foreach (var m in rtl.Fields)
                {
                    var mem = new RecordMember(type, m.Name);
                    unit.AddTask(() =>
                    {
                        var ftype = ConvertType(unit, scope, m.Type);
                        if (ftype == null)
                        {
                            return(Error.UnresolvableType(m.Type));
                        }
                        var member = new RecordMember(type, m.Name)
                        {
                            Type = ftype,
                        };
                        return(Error.None);
                    });
                    if (m.Value != null)
                    {
                        unit.AddTask(() =>
                        {
                            mem.Initializer = ConvertExpression(unit, scope, m.Value).Single();
                            if (mem.Initializer == null)
                            {
                                return(Error.InvalidExpression(m.Value));
                            }
                            return(Error.None);
                        });
                    }
                    type.Members.Add(mem);
                }
                return(type);
            }
            else if (asttype is ReferenceTypeLiteral rftl)
            {
                var type = new ReferenceType();
                unit.AddTask(() =>
                {
                    type.ObjectType = ConvertType(unit, scope, rftl.ObjectType);
                    if (type.ObjectType == null)
                    {
                        return(Error.UnresolvableType(rftl.ObjectType));
                    }
                    return(CompilerError.None);
                });
                return(type);
            }
            else if (asttype is FunctionTypeLiteral ftl)
            {
                var type = new FunctionType();
                unit.AddTask(() =>
                {
                    type.ReturnType = ConvertType(unit, scope, ftl.ReturnType);
                    if (type.ReturnType == null)
                    {
                        return(Error.UnresolvableType(ftl.ReturnType));
                    }
                    return(CompilerError.None);
                });
                var @params = new Parameter[ftl.Parameters.Count];
                for (int i = 0; i < ftl.Parameters.Count; i++)
                {
                    var par = ftl.Parameters[i];
                    var p   = new Parameter(type, par.Name, i)
                    {
                        Flags = par.Prefix,
                    };
                    // Set "in" as default if neither in nor out is given
                    if (!p.Flags.HasFlag(ParameterFlags.In) && !p.Flags.HasFlag(ParameterFlags.Out))
                    {
                        p.Flags |= ParameterFlags.In;
                    }
                    if (par.Type != null)
                    {
                        unit.AddTask(() =>
                        {
                            p.Type = ConvertType(unit, scope, par.Type);
                            if (p.Type == null)
                            {
                                return(Error.UnresolvableType(par.Type));
                            }
                            return(CompilerError.None);
                        });
                    }
                    if (par.Value != null)
                    {
                        unit.AddTask(() =>
                        {
                            p.Initializer = ConvertExpression(unit, scope, par.Value).Single();
                            if (p.Initializer == null)
                            {
                                return(Error.InvalidExpression(par.Value));
                            }
                            return(CompilerError.None);
                        });
                    }
                    @params[i] = p;
                }

                type.Parameters = @params;

                return(type);
            }
            else
            {
                throw new NotSupportedException($"{asttype.GetType().Name} is not supported yet!");
            }
        }