CLanguage by praeclarum

<PackageReference Include="CLanguage" Version="0.5.26" />

 FunctionContext

using CLanguage.Syntax; using CLanguage.Types; using System; using System.Collections.Generic; using System.Linq; namespace CLanguage.Interpreter { internal class FunctionContext : EmitContext { private class BlockLocals { public int StartIndex; public int Length; } private Executable exe; private CompiledFunction fexe; private EmitContext context; private List<Block> blocks; private Dictionary<Block, BlockLocals> blockLocals; private List<CompiledVariable> allLocals; public IEnumerable<CompiledVariable> LocalVariables => allLocals; public FunctionContext(Executable exe, CompiledFunction fexe, EmitContext context) : base(context.MachineInfo, context.Report, fexe) { this.exe = exe; this.fexe = fexe; this.context = context; blocks = new List<Block>(); blockLocals = new Dictionary<Block, BlockLocals>(); allLocals = new List<CompiledVariable>(); } public override ResolvedVariable ResolveVariable(string name, CType[] argTypes) { for (int i = 0; i < fexe.FunctionType.Parameters.Count; i++) { CFunctionType.Parameter parameter = fexe.FunctionType.Parameters[i]; if (parameter.Name == name) return new ResolvedVariable(VariableScope.Arg, parameter.Offset, fexe.FunctionType.Parameters[i].ParameterType); } foreach (Block item in Enumerable.Reverse(blocks)) { BlockLocals blockLocals = this.blockLocals[item]; for (int j = 0; j < blockLocals.Length; j++) { int index = blockLocals.StartIndex + j; if (allLocals[index].Name == name) return new ResolvedVariable(VariableScope.Local, allLocals[index].Offset, allLocals[index].VariableType); } } for (int k = 0; k < exe.Globals.Count; k++) { if (exe.Globals[k].Name == name) return new ResolvedVariable(VariableScope.Global, exe.Globals[k].Offset, exe.Globals[k].VariableType); } BaseFunction baseFunction = null; int address = -1; int num = 0; for (int l = 0; l < exe.Functions.Count; l++) { BaseFunction baseFunction2 = exe.Functions[l]; if (baseFunction2.Name == name && string.IsNullOrEmpty(baseFunction2.NameContext)) { int num2 = baseFunction2.FunctionType.ScoreParameterTypeMatches(argTypes); if (num2 > num) { baseFunction = baseFunction2; address = l; num = num2; } } } if (baseFunction != null) return new ResolvedVariable(baseFunction, address); context.Report.Error(103, "The name '" + name + "' does not exist in the current context"); return null; } public override ResolvedVariable ResolveMethodFunction(CStructType structType, CStructMethod method) { CFunctionType otherType; if ((otherType = (method.MemberType as CFunctionType)) != null) { string nameContext = structType.Name; ((IEnumerable<BaseFunction>)exe.Functions).Select((Func<BaseFunction, int, (BaseFunction, int)>)((BaseFunction f, int i) => (f, i))).Where((Func<(BaseFunction, int), bool>)delegate((BaseFunction f, int i) x) { if (x.f.NameContext == nameContext) return x.f.Name == method.Name; return false; }); for (int j = 0; j < exe.Functions.Count; j++) { BaseFunction baseFunction = exe.Functions[j]; if (baseFunction.NameContext == nameContext && baseFunction.Name == method.Name && baseFunction.FunctionType.ParameterTypesEqual(otherType)) return new ResolvedVariable(baseFunction, j); } } context.Report.Error(9000, $"""{structType.Name}""{method.Name}"""); return null; } public override void BeginBlock(Block b) { blocks.Add(b); BlockLocals value = new BlockLocals { StartIndex = allLocals.Count, Length = b.Variables.Count }; blockLocals[b] = value; allLocals.AddRange(b.Variables); int num = 0; foreach (CompiledVariable allLocal in allLocals) { allLocal.Offset = num; num += allLocal.VariableType.NumValues; } } public override void EndBlock() { blocks.RemoveAt(blocks.Count - 1); } public override Label DefineLabel() { return new Label(); } public override void EmitLabel(Label l) { l.Index = fexe.Instructions.Count; } public override void Emit(Instruction instruction) { fexe.Instructions.Add(instruction); } public override Value GetConstantMemory(string stringConstant) { return exe.GetConstantMemory(stringConstant); } } }