private static bool AssertDecodeTypeAndName( LNode parentAndName, DecoderState state, out IType parentType, out SimpleName name) { if (!FeedbackHelpers.AssertArgCount(parentAndName, 2, state.Log)) { parentType = null; name = null; return(false); } parentType = state.DecodeType(parentAndName.Args[0]); if (parentType != ErrorType.Instance && state.AssertDecodeSimpleName(parentAndName.Args[1], out name)) { return(true); } else { parentType = null; name = null; return(false); } }
private static NewDelegatePrototype DecodeNewDelegate(IReadOnlyList <LNode> data, DecoderState state) { return(NewDelegatePrototype.Create( state.DecodeType(data[0]), state.DecodeMethod(data[1]), state.DecodeBoolean(data[2]), state.DecodeMethodLookup(data[3]))); }
/// <summary> /// Creates a Flame IR field from an appropriately-encoded /// LNode. /// </summary> /// <param name="node">The node to decode.</param> /// <param name="decoder">The decoder to use.</param> private IrField(LNode node, DecoderState decoder) : base(node, decoder) { this.isStaticCache = new Lazy <bool>(() => decoder.DecodeBoolean(node.Args[1])); this.fieldTypeCache = new Lazy <IType>(() => decoder.DecodeType(node.Args[2])); }
private static IntrinsicPrototype DecodeIntrinsic(IReadOnlyList <LNode> data, DecoderState state) { // TODO: decode exception specifications. return(IntrinsicPrototype.Create( FeedbackHelpers.AssertIsId(data[0], state.Log) ? data[0].Name.Name : "error", state.DecodeType(data[1]), data[2].Args.EagerSelect <LNode, IType>(state.DecodeType))); }
private static StorePrototype DecodeStore(IReadOnlyList <LNode> data, DecoderState state) { if (data.Count >= 3) { return(StorePrototype.Create( state.DecodeType(data[0]), state.DecodeBoolean(data[1]), state.DecodeAlignment(data[2]))); } else if (data.Count >= 2) { return(StorePrototype.Create( state.DecodeType(data[0]), state.DecodeBoolean(data[1]))); } else { return(StorePrototype.Create(state.DecodeType(data[0]))); } }
private static ReinterpretCastPrototype DecodeReinterpretCast(IReadOnlyList <LNode> data, DecoderState state) { var targetType = state.DecodeType(data[0]); if (targetType is PointerType) { return(ReinterpretCastPrototype.Create((PointerType)targetType)); } else { state.Log.LogSyntaxError( data[0], new Text("expected a pointer type.")); return(null); } }
private static ConstantPrototype DecodeConstant(IReadOnlyList <LNode> data, DecoderState state) { return(ConstantPrototype.Create(state.DecodeConstant(data[0]), state.DecodeType(data[1]))); }
private static BoxPrototype DecodeBox(IReadOnlyList <LNode> data, DecoderState state) { return(BoxPrototype.Create(state.DecodeType(data[0]))); }
private static SizeOfPrototype DecodeSizeOf(IReadOnlyList <LNode> data, DecoderState state) { return(SizeOfPrototype.Create(state.DecodeType(data[0]), state.DecodeType(data[1]))); }
private static AllocaPrototype DecodeAlloca(IReadOnlyList <LNode> data, DecoderState state) { return(AllocaPrototype.Create(state.DecodeType(data[0]))); }
private static IndirectCallPrototype DecodeIndirectCall(IReadOnlyList <LNode> data, DecoderState state) { return(IndirectCallPrototype.Create( state.DecodeType(data[0]), data[1].Args.EagerSelect <LNode, IType>(state.DecodeType))); }
private static StorePrototype DecodeStore(IReadOnlyList <LNode> data, DecoderState state) { return(StorePrototype.Create(state.DecodeType(data[0]))); }
private static LoadPrototype DecodeLoad(IReadOnlyList <LNode> data, DecoderState state) { return(LoadPrototype.Create(state.DecodeType(data[0]))); }
/// <inheritdoc/> public override IType Decode(LNode data, DecoderState state) { if (data.Calls(pointerSymbol)) { if (!FeedbackHelpers.AssertArgCount(data, 2, state.Log)) { return(ErrorType.Instance); } var elemType = state.DecodeType(data.Args[0]); PointerKind kind; if (AssertDecodePointerKind(data.Args[1], state, out kind)) { return(elemType.MakePointerType(kind)); } else { return(ErrorType.Instance); } } else if (data.Calls(genericParameterSymbol)) { if (!FeedbackHelpers.AssertArgCount(data, 2, state.Log)) { return(ErrorType.Instance); } IGenericMember parent; SimpleName name; if (state.AssertDecodeGenericMember(data.Args[0], out parent) && state.AssertDecodeSimpleName(data.Args[1], out name)) { var types = state.TypeResolver.ResolveGenericParameters(parent, name); if (AssertSingleChildType(types, data, state, "generic declaration")) { return(types[0]); } } return(ErrorType.Instance); } else if (data.Calls(CodeSymbols.Of)) { if (!FeedbackHelpers.AssertMinArgCount(data, 2, state.Log)) { return(ErrorType.Instance); } var genericDecl = state.DecodeType(data.Args[0]); var genericArgs = data.Args.Slice(1).EagerSelect <LNode, IType>(state.DecodeType); int count = genericDecl.GenericParameters.Count; if (count != genericArgs.Count) { FeedbackHelpers.LogSyntaxError( state.Log, data, FeedbackHelpers.QuoteEven( "type ", FeedbackHelpers.Print(data.Args[0]), " is instantiated with ", genericArgs.Count.ToString(), " arguments but has only ", count.ToString(), " parameters.")); return(ErrorType.Instance); } return(genericDecl.MakeGenericType(genericArgs)); } else if (data.Calls(CodeSymbols.Dot)) { if (!FeedbackHelpers.AssertArgCount(data, 2, state.Log)) { return(ErrorType.Instance); } SimpleName childName; if (!state.AssertDecodeSimpleName(data.Args[1], out childName)) { return(ErrorType.Instance); } var parentType = state.DecodeType(data.Args[0]); if (parentType == ErrorType.Instance) { // Make sure that we don't log an additional error // just because the parent type was wrong. return(ErrorType.Instance); } var childTypes = state.TypeResolver.ResolveNestedTypes(parentType, childName); if (AssertSingleChildType(childTypes, data, state, "type")) { return(childTypes[0]); } else { return(ErrorType.Instance); } } else { QualifiedName fullName; if (state.AssertDecodeQualifiedName(data, out fullName)) { var types = state.TypeResolver.ResolveTypes(fullName); if (AssertSingleGlobalType(types, data, state)) { return(types[0]); } else { return(ErrorType.Instance); } } else { return(ErrorType.Instance); } } }
/// <summary> /// Decodes an LNode as a constant value. /// </summary> /// <param name="node">The node to decode.</param> /// <param name="state">The decoder state to use.</param> /// <returns>A decoded constant.</returns> public override Constant Decode(LNode node, DecoderState state) { // Default-value constants. if (node.IsIdNamed(CodeSymbols.Default)) { return(DefaultConstant.Instance); } // Type/field/method token constants. if (node.Calls(CodeSymbols.Typeof, 1)) { return(new TypeTokenConstant(state.DecodeType(node.Args[0]))); } else if (node.Calls(fieldofSymbol, 1)) { return(new FieldTokenConstant(state.DecodeField(node.Args[0]))); } else if (node.Calls(methodofSymbol, 1)) { return(new MethodTokenConstant(state.DecodeMethod(node.Args[0]))); } if (!FeedbackHelpers.AssertIsLiteral(node, state.Log)) { return(null); } object value; Symbol typeMarker; // Custom literals. if (TryDecomposeCustomLiteral(node, out value, out typeMarker)) { // Arbitrary-width integer literals. IntegerSpec spec; if (IntegerSpec.TryParse(typeMarker.Name, out spec)) { BigInteger integerVal; if (BigInteger.TryParse(value.ToString(), out integerVal)) { return(new IntegerConstant(integerVal, spec)); } else { FeedbackHelpers.LogSyntaxError( state.Log, node, FeedbackHelpers.QuoteEven( "cannot parse ", value.ToString(), " as an integer.")); return(null); } } else { FeedbackHelpers.LogSyntaxError( state.Log, node, FeedbackHelpers.QuoteEven( "unknown custom literal type ", typeMarker.Name, ".")); return(null); } } value = node.Value; // Miscellaneous constants: null, strings, Booleans. if (value == null) { return(NullConstant.Instance); } else if (value is string) { return(new StringConstant((string)value)); } else if (value is bool) { return(BooleanConstant.Create((bool)value)); } // Floating-point numbers. else if (value is float) { return(new Float32Constant((float)value)); } else if (value is double) { return(new Float64Constant((double)value)); } // Fixed-width integer constants and characters. else if (value is char) { return(new IntegerConstant((char)value)); } else if (value is sbyte) { return(new IntegerConstant((sbyte)value)); } else if (value is short) { return(new IntegerConstant((short)value)); } else if (value is int) { return(new IntegerConstant((int)value)); } else if (value is long) { return(new IntegerConstant((long)value)); } else if (value is byte) { return(new IntegerConstant((byte)value)); } else if (value is ushort) { return(new IntegerConstant((ushort)value)); } else if (value is uint) { return(new IntegerConstant((uint)value)); } else if (value is ulong) { return(new IntegerConstant((ulong)value)); } FeedbackHelpers.LogSyntaxError( state.Log, node, new Text("unknown literal type.")); return(null); }
/// <inheritdoc/> public override ITypeMember Decode(LNode data, DecoderState state) { if (data.Calls(accessorSymbol)) { if (!FeedbackHelpers.AssertArgCount(data, 2, state.Log) || !FeedbackHelpers.AssertIsId(data.Args[1], state.Log)) { return(null); } var property = state.DecodeProperty(data.Args[0]); if (property == null) { return(null); } else { var kindName = data.Args[1].Name.Name; var accessor = property.Accessors.FirstOrDefault( acc => accessorKindEncodings[acc.Kind] == kindName); if (accessor == null) { FeedbackHelpers.LogSyntaxError( state.Log, data.Args[1], Quotation.QuoteEvenInBold( "property ", FeedbackHelpers.Print(data.Args[0]), " does not define a ", kindName, " accessor.")); } return(accessor); } } else if (data.Calls(CodeSymbols.Dot)) { // Simple dot indicates a field. IType parentType; SimpleName name; if (!AssertDecodeTypeAndName(data, state, out parentType, out name)) { return(null); } var candidates = state.TypeMemberIndex .GetAll(parentType, name) .OfType <IField>() .ToArray(); return(CheckSingleCandidate( candidates, data.Args[0], data.Args[1], "field", state)); } else if (data.CallsMin(CodeSymbols.IndexBracks, 1)) { IType parentType; SimpleName name; if (!AssertDecodeTypeAndName(data.Args[0], state, out parentType, out name)) { return(null); } var indexTypes = data.Args .Slice(1) .EagerSelect(state.DecodeType); var candidates = state.TypeMemberIndex .GetAll(parentType, name) .OfType <IProperty>() .Where(prop => prop.IndexerParameters .Select(p => p.Type) .SequenceEqual(indexTypes)) .ToArray(); return(CheckSingleCandidate( candidates, data.Args[0].Args[0], data, "property", state)); } else if (data.Calls(CodeSymbols.Lambda)) { IType parentType; SimpleName name; if (!FeedbackHelpers.AssertArgCount(data, 2, state.Log) || !FeedbackHelpers.AssertIsCall(data.Args[0], state.Log) || !AssertDecodeTypeAndName(data.Args[0].Target, state, out parentType, out name)) { return(null); } // TODO: implement generic parameter decoding, use generic // parameters in resolution process. var paramTypes = data.Args[0].Args .EagerSelect(state.DecodeType); var retType = state.DecodeType(data.Args[1]); var candidates = state.TypeMemberIndex .GetAll(parentType, name) .OfType <IMethod>() .Where(method => method.Parameters .Select(p => p.Type) .SequenceEqual(paramTypes) && object.Equals( method.ReturnParameter.Type, retType)) .ToArray(); return(CheckSingleCandidate( candidates, data.Args[0].Target.Args[0], data, "method", state)); } else if (data.Calls(CodeSymbols.Of)) { if (!FeedbackHelpers.AssertMinArgCount(data, 1, state.Log)) { return(null); } var func = state.DecodeMethod(data.Args[0]); var args = data.Args.Slice(1).EagerSelect(state.DecodeType); if (func.GenericParameters.Count == args.Count) { return(func.MakeGenericMethod(args)); } else { state.Log.LogSyntaxError( data, Quotation.QuoteEvenInBold( "generic arity mismatch; expected ", func.GenericParameters.Count.ToString(), " parameters but got ", args.Count.ToString(), ".")); return(null); } } else { state.Log.LogSyntaxError( data, Quotation.QuoteEvenInBold( "cannot interpret ", FeedbackHelpers.Print(data), " as a type member; expected a call to one of ", accessorSymbol.Name, ", ", CodeSymbols.Dot.Name, ", ", CodeSymbols.IndexBracks.Name, ", ", CodeSymbols.Of.Name, " or ", CodeSymbols.Lambda.Name)); return(null); } }