internal override IList <Executable> Resolve(Parser parser) { ConstantResolutionState resolutionState = parser.ConstantAndEnumResolutionState[this]; if (resolutionState == ConstantResolutionState.RESOLVED) { return(new Executable[0]); } if (resolutionState == ConstantResolutionState.RESOLVING) { throw new ParserException(this.FirstToken, "The resolution of this enum creates a cycle."); } parser.ConstantAndEnumResolutionState[this] = ConstantResolutionState.RESOLVING; this.Expression = this.Expression.Resolve(parser); if (this.Expression is IntegerConstant || this.Expression is BooleanConstant || this.Expression is FloatConstant || this.Expression is StringConstant) { // that's fine. } else { throw new ParserException(this.FirstToken, "Invalid value for const. Expression must resolve to a constant at compile time."); } parser.ConstantAndEnumResolutionState[this] = ConstantResolutionState.RESOLVED; return(new Executable[0]); }
internal override Expression Resolve(ParserContext parser) { ConstantResolutionState resolutionState = parser.ConstantAndEnumResolutionState[this.EnumDefinition]; if (resolutionState != ConstantResolutionState.RESOLVED) { this.EnumDefinition.Resolve(parser); } if (this.EnumDefinition.IntValue.ContainsKey(this.Field)) { return(new IntegerConstant(this.FirstToken, this.EnumDefinition.IntValue[this.Field], this.Owner)); } throw new ParserException(this.FieldToken, "The enum '" + this.EnumDefinition.Name + "' does not contain a definition for '" + this.Field + "'"); }
internal override void Resolve(Parser parser) { ConstantResolutionState resolutionState = parser.ConstantAndEnumResolutionState[this]; if (resolutionState == ConstantResolutionState.RESOLVED) { return; } if (resolutionState == ConstantResolutionState.RESOLVING) { throw new ParserException(this.FirstToken, "The resolution of this enum creates a cycle."); } parser.ConstantAndEnumResolutionState[this] = ConstantResolutionState.RESOLVING; this.Expression = this.Expression.Resolve(parser); if (!(this.Expression is IConstantValue)) { throw new ParserException(this.FirstToken, "Invalid value for const. Expression must resolve to a constant at compile time."); } parser.ConstantAndEnumResolutionState[this] = ConstantResolutionState.RESOLVED; }
internal override Expression Resolve(Parser parser) { this.Root = this.Root.Resolve(parser); string step = this.StepToken.Value; if (this.Root is EnumReference) { EnumDefinition enumDef = ((EnumReference)this.Root).EnumDefinition; ConstantResolutionState resolutionState = parser.ConstantAndEnumResolutionState[enumDef]; if (resolutionState != ConstantResolutionState.RESOLVED) { enumDef.Resolve(parser); } switch (step) { case "length": return(new IntegerConstant(this.FirstToken, enumDef.IntValue.Count, this.Owner)); case "max": return(new SpecialEntity.EnumMaxFunction(this.FirstToken, enumDef, this.Owner)); case "values": return(new SpecialEntity.EnumValuesFunction(this.FirstToken, enumDef, this.Owner)); } if (enumDef.IntValue.ContainsKey(step)) { return(new IntegerConstant(this.FirstToken, enumDef.IntValue[step], this.Owner)); } else { throw new ParserException(this.StepToken, "The enum '" + enumDef.Name + "' does not contain a definition for '" + step + "'"); } } if (this.Root is BaseKeyword) { return(new BaseMethodReference(this.Root.FirstToken, this.DotToken, this.StepToken, this.Owner).Resolve(parser)); } if (this.Root is StringConstant) { if (step == "join") { throw new ParserException(this.StepToken, "There is no join method on strings. Did you mean to do list.join(string) instead?"); } else if (step == "size") { throw new ParserException(this.StepToken, "String size is indicated by string.length."); } else if (step == "length") { int length = ((StringConstant)this.Root).Value.Length; return(new IntegerConstant(this.FirstToken, length, this.Owner)); } } return(this); }
internal override void Resolve(ParserContext parser) { ConstantResolutionState resolutionState = parser.ConstantAndEnumResolutionState[this]; if (resolutionState == ConstantResolutionState.RESOLVED) { return; } if (resolutionState == ConstantResolutionState.RESOLVING) { throw new ParserException(this, "The resolution of this enum creates a cycle."); } parser.ConstantAndEnumResolutionState[this] = ConstantResolutionState.RESOLVING; HashSet <int> consumed = new HashSet <int>(); for (int i = 0; i < this.Items.Length; ++i) { string itemName = this.Items[i].Value; if (itemName == "length") { throw new ParserException(this.Items[i], "The name 'length' is not allowed as an enum value as it is a reserved field. In general, enum members should be in ALL CAPS anyway."); } if (this.IntValue.ContainsKey(itemName)) { throw new ParserException(this.Items[i], "Duplicate item in same enum. "); } this.IntValue[itemName] = -1; if (this.Values[i] != null) { IntegerConstant ic = this.Values[i].Resolve(parser) as IntegerConstant; if (ic == null) { throw new ParserException(this.Values[i], "Enum values must be integers or left blank."); } this.Values[i] = ic; if (consumed.Contains(ic.Value)) { throw new ParserException(this.Values[i], "This integer value has already been used in the same enum."); } consumed.Add(ic.Value); this.IntValue[itemName] = ic.Value; } } parser.ConstantAndEnumResolutionState[this] = ConstantResolutionState.RESOLVED; int next = 0; for (int i = 0; i < this.Items.Length; ++i) { if (this.Values[i] == null) { while (consumed.Contains(next)) { ++next; } this.IntValue[this.Items[i].Value] = next; consumed.Add(next); } } }