/// <summary> /// Creates a decoder. /// </summary> /// <param name="log">A log to use for error and warning messages.</param> /// <param name="typeResolver">A read-only type resolver for resolving types.</param> /// <param name="codec">A Flame IR codec.</param> public DecoderState( ILog log, ReadOnlyTypeResolver typeResolver, IrCodec codec) : this(log, typeResolver, codec, TypeParent.Nothing) { }
/// <summary> /// Creates a type system based on a core library type resolver. /// </summary> /// <param name="corlibTypeResolver"> /// A type resolver for the core library, which supplies the /// types in the type system. /// </param> public CorlibTypeEnvironment(ReadOnlyTypeResolver corlibTypeResolver) { this.CorlibTypeResolver = corlibTypeResolver; this.arrayTypeCache = new InterningCache <ClrArrayType>( new RankClrArrayTypeComparer()); this.createArrayBaseTypes = new Lazy <Func <int, IGenericParameter, IReadOnlyList <IType> > >( ResolveArrayBaseTypes); this.signedIntegerTypes = new Lazy <Dictionary <int, IType> >(ResolveSignedIntegerTypes); this.unsignedIntegerTypes = new Lazy <Dictionary <int, IType> >(ResolveUnsignedIntegerTypes); this.voidType = new Lazy <IType>(() => ResolveSystemType(nameof(Void))); this.float32Type = new Lazy <IType>(() => ResolveSystemType(nameof(Single))); this.float64Type = new Lazy <IType>(() => ResolveSystemType(nameof(Double))); this.charType = new Lazy <IType>(() => ResolveSystemType(nameof(Char))); this.stringType = new Lazy <IType>(() => ResolveSystemType(nameof(String))); this.intPtrType = new Lazy <IType>(() => ResolveSystemType(nameof(IntPtr))); this.uintPtrType = new Lazy <IType>(() => ResolveSystemType(nameof(UIntPtr))); this.objectType = new Lazy <IType>(() => ResolveSystemType(nameof(Object))); this.typeTokenType = new Lazy <IType>(() => ResolveSystemType(nameof(RuntimeTypeHandle))); this.fieldTokenType = new Lazy <IType>(() => ResolveSystemType(nameof(RuntimeFieldHandle))); this.methodTokenType = new Lazy <IType>(() => ResolveSystemType(nameof(RuntimeMethodHandle))); this.capturedExceptionType = new Lazy <IType>( () => CorlibTypeResolver.ResolveTypes( new SimpleName("ExceptionDispatchInfo") .Qualify("ExceptionServices") .Qualify("Runtime") .Qualify("System")) .FirstOrDefault()); }
/// <summary> /// Creates CIL prototype exception specification rules. /// </summary> /// <param name="corlibTypeResolver"> /// A type resolver for the core library (corlib.dll) that /// defines well-known exception types. /// </param> /// <returns>Prototype exception specification rules.</returns> public static RuleBasedPrototypeExceptionSpecs Create( ReadOnlyTypeResolver corlibTypeResolver) { var result = new RuleBasedPrototypeExceptionSpecs( RuleBasedPrototypeExceptionSpecs.Default); // We know the type of exception thrown by null checks: // it's System.NullReferenceException. var nullRefException = corlibTypeResolver.ResolveTypes( new SimpleName(nameof(NullReferenceException)) .Qualify(nameof(System))) .Single(); // Resolve other well-known exception types. var outOfRangeException = corlibTypeResolver.ResolveTypes( new SimpleName(nameof(IndexOutOfRangeException)) .Qualify(nameof(System))) .Single(); var arrayTypeMismatchException = corlibTypeResolver.ResolveTypes( new SimpleName(nameof(ArrayTypeMismatchException)) .Qualify(nameof(System))) .Single(); // Refine null check exception types. result.Register <GetFieldPointerPrototype>( new NullCheckExceptionSpecification(0, nullRefException)); result.Register <NewDelegatePrototype>( proto => proto.Lookup == MethodLookup.Virtual ? new NullCheckExceptionSpecification(0, nullRefException) : ExceptionSpecification.NoThrow); result.Register <UnboxPrototype>( new NullCheckExceptionSpecification(0, nullRefException)); // Array intrinsics are worth refining, too. result.Register( ArrayIntrinsics.Namespace.GetIntrinsicName(ArrayIntrinsics.Operators.GetElementPointer), ExceptionSpecification.Union.Create( new NullCheckExceptionSpecification(0, nullRefException), ExceptionSpecification.Exact.Create(outOfRangeException), ExceptionSpecification.Exact.Create(arrayTypeMismatchException))); result.Register( ArrayIntrinsics.Namespace.GetIntrinsicName(ArrayIntrinsics.Operators.LoadElement), ExceptionSpecification.Union.Create( new NullCheckExceptionSpecification(0, nullRefException), ExceptionSpecification.Exact.Create(outOfRangeException))); result.Register( ArrayIntrinsics.Namespace.GetIntrinsicName(ArrayIntrinsics.Operators.StoreElement), ExceptionSpecification.Union.Create( new NullCheckExceptionSpecification(0, nullRefException), ExceptionSpecification.Exact.Create(outOfRangeException), ExceptionSpecification.Exact.Create(arrayTypeMismatchException))); result.Register( ArrayIntrinsics.Namespace.GetIntrinsicName(ArrayIntrinsics.Operators.GetLength), new NullCheckExceptionSpecification(0, nullRefException)); return(result); }
/// <summary> /// Creates a decoder. /// </summary> /// <param name="log">A log to use for error and warning messages.</param> /// <param name="typeResolver">A read-only type resolver for resolving types.</param> /// <param name="codec">A Flame IR codec.</param> /// <param name="scope">The decoder's scope.</param> private DecoderState( ILog log, ReadOnlyTypeResolver typeResolver, IrCodec codec, TypeParent scope) { this.Log = log; this.TypeResolver = typeResolver; this.Codec = codec; this.Scope = scope; this.typeCache = new ConcurrentDictionary <LNode, IType>(); this.TypeMemberIndex = new Index <IType, UnqualifiedName, ITypeMember>( type => type.Fields .Concat <ITypeMember>(type.Properties) .Concat <ITypeMember>(type.Methods) .Select(member => new KeyValuePair <UnqualifiedName, ITypeMember>( member.Name, member))); }
/// <summary> /// Creates a decoder that relies on the default codec. /// </summary> /// <param name="log">A log to use for error and warning messages.</param> /// <param name="typeResolver">A read-only type resolver for resolving types.</param> public DecoderState(ILog log, ReadOnlyTypeResolver typeResolver) : this(log, typeResolver, IrCodec.Default) { }
/// <summary> /// Resolves dependencies that Brainfuck programs use to accept input and produce output. /// </summary> /// <param name="environment"> /// The type environment to resolve dependencies in. /// </param> /// <param name="binder"> /// A type resolver for resolving dependencies with. /// </param> /// <param name="log">A log to send messages to.</param> /// <returns> /// Brainfuck IO dependencies. /// </returns> public static Dependencies Resolve( TypeEnvironment environment, ReadOnlyTypeResolver binder, ILog log) { var consoleType = binder.ResolveTypes(new SimpleName("Console").Qualify("System")).FirstOrDefault(); if (consoleType == null) { log.Log( new LogEntry( Severity.Warning, "console not found", "no class named 'System.Console' was not found. IO calls will be replaced with constants.")); return(new Dependencies(environment, null, null)); } else { var writeMethod = consoleType.Methods.FirstOrDefault( method => method.Name.ToString() == "Write" && method.IsStatic && method.ReturnParameter.Type == environment.Void && method.Parameters.Count == 1 && method.Parameters[0].Type == environment.Char); var readMethod = consoleType.Methods.FirstOrDefault( method => method.Name.ToString() == "Read" && method.IsStatic && method.ReturnParameter.Type == environment.Int32 && method.Parameters.Count == 0); if (writeMethod != null) { log.Log( new LogEntry( Severity.Info, "output method found", "found 'void System.Console.Write(char)'.")); } else { log.Log( new LogEntry( Severity.Warning, "output method not found", "couldn't find 'void System.Console.Write(char)'. No output will be written.")); } if (readMethod != null) { log.Log( new LogEntry( Severity.Info, "input method found", "found 'int System.Console.Read()'.")); } else { log.Log( new LogEntry( Severity.Warning, "input method not found", "couldn't find 'char System.Console.Read()'. No input will be read.")); } return(new Dependencies(environment, readMethod, writeMethod)); } }