/// <summary> /// Decodes an id node using a symbol-to-value mapping. /// An error is reported if the node cannot be decoded. /// </summary> /// <param name="node">A node to decode.</param> /// <param name="decodeMap"> /// A mapping of symbols to values that is used for /// decoding the node. /// </param> /// <param name="enumDescription"> /// A short description of the type of value that is being /// decoded, e.g., "method lookup strategy". /// </param> /// <param name="result"> /// The decoded value, if any. /// </param> /// <returns> /// <c>true</c> if the node could be decoded; otherwise, <c>false</c>. /// </returns> public bool AssertDecodeEnum <T>( LNode node, IReadOnlyDictionary <Symbol, T> decodeMap, string enumDescription, out T result) { if (!node.IsId) { Log.LogSyntaxError( node, FeedbackHelpers.QuoteEven( "expected " + enumDescription + " (", FeedbackHelpers.SpellNodeKind(LNodeKind.Id), " node) but got ", FeedbackHelpers.SpellNodeKind(node), " node.")); result = default(T); return(false); } if (decodeMap.TryGetValue(node.Name, out result)) { return(true); } else { // Create a sorted list of all admissible values. var sortedKeys = new List <string>(); foreach (var item in decodeMap.Keys) { sortedKeys.Add(item.Name); } sortedKeys.Sort(); // Generate a lengthy message that details exactly what // is admissible. var message = new List <MarkupNode>(); message.Add("unknown " + enumDescription + " "); message.Add(node.Name.Name); message.Add("; expected "); for (int i = 0; i < sortedKeys.Count - 1; i++) { message.Add(sortedKeys[i]); if (i < sortedKeys.Count - 2) { message.Add(", "); } else { message.Add(" or "); } } message.Add(sortedKeys[sortedKeys.Count - 1]); message.Add("."); Log.LogSyntaxError( node, FeedbackHelpers.QuoteEven(message.ToArray())); return(false); } }
/// <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); }