internal override void ResolveTypes(VariableScope varScope, PastelCompiler compiler) { this.Condition = this.Condition.ResolveType(varScope, compiler); if (!this.Condition.ResolvedType.IsIdentical(PType.INT)) { throw new ParserException(this.Condition.FirstToken, "Only ints can be used in switch statements."); } // consider it all one scope for (int i = 0; i < this.Chunks.Length; ++i) { SwitchChunk chunk = this.Chunks[i]; for (int j = 0; j < chunk.Cases.Length; ++j) { Expression ex = chunk.Cases[j]; if (ex != null) { ex = ex.ResolveType(varScope, compiler); chunk.Cases[j] = ex; if (ex.ResolvedType.RootValue != "int") { throw new ParserException(ex.FirstToken, "Only ints may be used."); } } } Executable.ResolveTypes(chunk.Code, varScope, compiler); } }
internal override void ResolveTypes(VariableScope varScope, PastelCompiler compiler) { this.Condition = this.Condition.ResolveType(varScope, compiler); PType conditionType = this.Condition.ResolvedType; bool isInt = conditionType.IsIdentical(compiler, PType.INT); bool isChar = !isInt && conditionType.IsIdentical(compiler, PType.CHAR); if (!isInt && !isChar) { throw new ParserException(this.Condition.FirstToken, "Only ints and chars can be used in switch statements."); } // consider it all one scope for (int i = 0; i < this.Chunks.Length; ++i) { SwitchChunk chunk = this.Chunks[i]; for (int j = 0; j < chunk.Cases.Length; ++j) { Expression ex = chunk.Cases[j]; if (ex != null) { ex = ex.ResolveType(varScope, compiler); chunk.Cases[j] = ex; if ((isInt && ex.ResolvedType.RootValue != "int") || (isChar && ex.ResolvedType.RootValue != "char")) { throw new ParserException(ex.FirstToken, isInt ? "Only ints may be used." : "Only chars may be used."); } } } Executable.ResolveTypes(chunk.Code, varScope, compiler); } }
internal override Executable ResolveWithTypeContext(PastelCompiler compiler) { this.Condition = this.Condition.ResolveWithTypeContext(compiler); for (int i = 0; i < this.Chunks.Length; ++i) { SwitchChunk chunk = this.Chunks[i]; for (int j = 0; j < chunk.Cases.Length; ++j) { if (chunk.Cases[j] != null) { chunk.Cases[j] = chunk.Cases[j].ResolveWithTypeContext(compiler); } } Executable.ResolveWithTypeContext(compiler, chunk.Code); } return(this); }
public override Executable ResolveNamesAndCullUnusedCode(PastelCompiler compiler) { this.Condition = this.Condition.ResolveNamesAndCullUnusedCode(compiler); for (int i = 0; i < this.Chunks.Length; ++i) { SwitchChunk chunk = this.Chunks[i]; for (int j = 0; j < chunk.Cases.Length; ++j) { if (chunk.Cases[j] != null) { chunk.Cases[j] = chunk.Cases[j].ResolveNamesAndCullUnusedCode(compiler); } } chunk.Code = Executable.ResolveNamesAndCullUnusedCodeForBlock(chunk.Code, compiler).ToArray(); } return(this); }
internal override Executable ResolveWithTypeContext(PastelCompiler compiler) { this.Condition = this.Condition.ResolveWithTypeContext(compiler); HashSet <int> values = new HashSet <int>(); for (int i = 0; i < this.Chunks.Length; ++i) { SwitchChunk chunk = this.Chunks[i]; for (int j = 0; j < chunk.Cases.Length; ++j) { if (chunk.Cases[j] != null) { chunk.Cases[j] = chunk.Cases[j].ResolveWithTypeContext(compiler); InlineConstant ic = chunk.Cases[j] as InlineConstant; if (ic == null) { throw new ParserException(chunk.Cases[j].FirstToken, "Only constants may be used as switch cases."); } int value; if (ic.ResolvedType.RootValue == "char") { value = (char)ic.Value; } else { value = (int)ic.Value; } if (values.Contains(value)) { throw new ParserException(chunk.Cases[j].FirstToken, "This cases appears multiple times."); } values.Add(value); } } Executable.ResolveWithTypeContext(compiler, chunk.Code); } return(this); }