CLanguage by praeclarum

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

 VariableExpression

using CLanguage.Compiler; using CLanguage.Interpreter; using CLanguage.Types; using System; using System.Runtime.CompilerServices; namespace CLanguage.Syntax { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public class VariableExpression : Expression { public string VariableName { get; set; } public override bool CanEmitPointer => true; public VariableExpression(string val, Location loc, Location endLoc) { VariableName = val; base.Location = loc; base.EndLocation = endLoc; } public override CType GetEvaluatedCType(EmitContext ec) { return ec.ResolveVariable(this, null).VariableType; } protected override void DoEmit(EmitContext ec) { ResolvedVariable resolvedVariable = ec.ResolveVariable(this, null); if (resolvedVariable != null) { VariableScope scope; if (resolvedVariable.Scope == VariableScope.Function) ec.Emit(OpCode.LoadConstant, Value.Pointer(resolvedVariable.Address)); else if (resolvedVariable.VariableType is CBasicType || resolvedVariable.VariableType is CPointerType || resolvedVariable.VariableType is CEnumType) { if (resolvedVariable.Scope == VariableScope.Arg) ec.Emit(OpCode.LoadArg, resolvedVariable.Address); else if (resolvedVariable.Scope == VariableScope.Global) { ec.Emit(OpCode.LoadGlobal, resolvedVariable.Address); } else if (resolvedVariable.Scope == VariableScope.Local) { ec.Emit(OpCode.LoadLocal, resolvedVariable.Address); } else { if (resolvedVariable.Scope != VariableScope.Constant) { scope = resolvedVariable.Scope; throw new NotSupportedException("Cannot evaluate variable scope '" + scope.ToString() + "'"); } ec.Emit(OpCode.LoadConstant, resolvedVariable.Constant); } } else { if (!(resolvedVariable.VariableType is CArrayType)) throw new NotSupportedException("Cannot evaluate variable type '" + resolvedVariable.VariableType?.ToString() + "'"); if (resolvedVariable.Scope == VariableScope.Arg) { ec.Emit(OpCode.LoadConstant, Value.Pointer(resolvedVariable.Address)); ec.Emit(OpCode.LoadFramePointer); ec.Emit(OpCode.OffsetPointer); } else if (resolvedVariable.Scope == VariableScope.Global) { ec.Emit(OpCode.LoadConstant, Value.Pointer(resolvedVariable.Address)); } else { if (resolvedVariable.Scope != VariableScope.Local) { scope = resolvedVariable.Scope; throw new NotSupportedException("Cannot evaluate array variable scope '" + scope.ToString() + "'"); } ec.Emit(OpCode.LoadConstant, Value.Pointer(resolvedVariable.Address)); ec.Emit(OpCode.LoadFramePointer); ec.Emit(OpCode.OffsetPointer); } } } else ec.Emit(OpCode.LoadConstant, 0); } protected override void DoEmitPointer(EmitContext ec) { ResolvedVariable resolvedVariable = ec.ResolveVariable(this, null); if (resolvedVariable != null) resolvedVariable.EmitPointer(ec); else ec.Emit(OpCode.LoadConstant, 0); } public override string ToString() { return VariableName.ToString(); } public override Value EvalConstant(EmitContext ec) { ResolvedVariable resolvedVariable = ec.ResolveVariable(this, null); if (resolvedVariable != null && resolvedVariable.Scope == VariableScope.Constant) return resolvedVariable.Constant; return base.EvalConstant(ec); } } }