Esempio n. 1
0
        private Type GetPropertyType(
            TypeBuilder typeBuilder,
            string defaultType,
            IdentifierExpression property,
            HashSet <string> imports)
        {
            if (property.Attributes == null || property.Attributes.Count == 0)
            {
                return(Interpreter.InteropTypeResolver.ResolveType(
                           imports,
                           _importsLock,
                           new[] { InteropTypeResolver.Unalias(defaultType) },
                           isType: true));
            }

            var scanner = new AphidAttributeScanner(property);

            scanner.Next();
            var typeName = InteropTypeResolver.Unalias(scanner.CurrentAttribute);

            Type t = typeName == typeBuilder.Name
                ? typeBuilder
                : Interpreter.InteropTypeResolver.ResolveType(
                imports,
                _importsLock,
                new[] { typeName },
                isType: true);

            if (!scanner.Next())
            {
                return(t);
            }

            t = scanner.Match("list")
                ? typeof(List <>).MakeGenericType(t)
                : scanner.Match("set")
                    ? t.MakeArrayType()
                    : throw new AphidParserException(
                          "Invalid property attribute '{0}'.",
                          scanner.CurrentAttribute);

            return(!scanner.EndOfStream()
                ? throw new AphidParserException(
                       "Unexpected property attribute '{0}'.",
                       scanner.CurrentAttribute)
                : t);
        }
Esempio n. 2
0
        public Type CreateType(ObjectExpression type, HashSet <string> imports)
        {
            if (type.Identifier == null || type.Identifier.Attributes.Count == 0)
            {
                throw new InvalidOperationException("ObjectExpression has no type class attributes.");
            }

            var state   = ClassAttributeScanState.Starting;
            var scanner = new AphidAttributeScanner(type.Identifier);

            scanner.Next();
            var  defaultType    = "System.Object";
            var  defaultTypeSet = false;
            var  interfaces     = new List <Type>();
            Type baseType       = null;

            do
            {
                switch (state)
                {
                case ClassAttributeScanState.Starting:
                    scanner.Require(AphidName.Class);
                    state = ClassAttributeScanState.InClass;
                    break;

                case ClassAttributeScanState.InClass:
                    if (scanner.Match(AphidName.Of))
                    {
                        if (defaultTypeSet || scanner.CurrentAttribute == null)
                        {
                            throw Interpreter.CreateRuntimeException("Invalid 'of' attribute.");
                        }

                        defaultType    = scanner.CurrentAttribute;
                        defaultTypeSet = true;
                        scanner.Next();
                        break;
                    }
                    else if (!scanner.EndOfStream())
                    {
                        var superType = ResolveBaseType(scanner.CurrentAttribute);
                        scanner.Next();

                        if (superType == null)
                        {
                            throw Interpreter.CreateRuntimeException(
                                      "Could not resolve base type {0} in class declaration '{1}'.",
                                      scanner.CurrentAttribute,
                                      type.ToString());
                        }
                        else if (superType.IsInterface)
                        {
                            interfaces.Add(superType);
                        }
                        else
                        {
                            baseType = baseType == null
                                    ? superType
                                    : throw Interpreter.CreateRuntimeException(
                                                 "Type is already subclass of {0}, cannot inherit from {1}.",
                                                 baseType,
                                                 superType);
                        }
                    }
                    else
                    {
                        throw Interpreter.CreateRuntimeException(
                                  "Invalid class attribute '{0}'.",
                                  scanner.CurrentAttribute);
                    }
                    break;

                default:
                    throw Interpreter.CreateRuntimeException(
                              "Invalid class attribute '{0}'.",
                              scanner.CurrentAttribute);
                }
            } while (!scanner.EndOfStream());

            if (state != ClassAttributeScanState.InClass)
            {
                throw new AphidParserException("Invalid class attributes.");
            }

            var name = type.Identifier.Identifier;

            TypeBuilder typeBuilder = baseType == null && interfaces.Count == 0
                ? _moduleBuilder.Value.DefineType(
                name,
                TypeAttributes.Public)
                : interfaces.Count == 0
                    ? _moduleBuilder.Value.DefineType(
                name,
                TypeAttributes.Public,
                baseType)
                    : _moduleBuilder.Value.DefineType(
                name,
                TypeAttributes.Public,
                baseType,
                interfaces.ToArray());

            foreach (var kvp in type.Pairs)
            {
                if (kvp.LeftOperand.Type != AphidExpressionType.IdentifierExpression)
                {
                    throw Interpreter.CreateRuntimeException("Invalid class property lhs.");
                }

                if (kvp.RightOperand.Type == AphidExpressionType.IdentifierExpression &&
                    kvp.LeftOperand.ToIdentifier().Identifier == kvp.RightOperand.ToIdentifier().Identifier)
                {
                    AddProperty(typeBuilder, defaultType, kvp.LeftOperand.ToIdentifier(), imports);
                }
                else
                {
                    throw new NotImplementedException();
                }
            }

            var t = typeBuilder.CreateType();

            _types.Add(t.FullName);

            return(t);
        }