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!"); } }