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