ResolvedVariable
using CLanguage.Interpreter;
using CLanguage.Types;
using System;
using System.Runtime.CompilerServices;
namespace CLanguage.Compiler
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public class ResolvedVariable
{
public VariableScope Scope { get; }
public int Address { get; }
public CType VariableType { get; }
[System.Runtime.CompilerServices.Nullable(2)]
[field: System.Runtime.CompilerServices.Nullable(2)]
public BaseFunction Function {
[System.Runtime.CompilerServices.NullableContext(2)]
get;
}
public Value Constant { get; }
public ResolvedVariable(VariableScope scope, int address, CType variableType)
{
Scope = scope;
Address = address;
VariableType = variableType;
}
public ResolvedVariable(BaseFunction function, int address)
{
Scope = VariableScope.Function;
Function = function;
Address = address;
VariableType = Function.FunctionType;
}
public ResolvedVariable(Value constantValue, CType variableType)
{
Scope = VariableScope.Constant;
Constant = constantValue;
Address = 0;
VariableType = variableType;
}
public void Emit(EmitContext ec)
{
switch (Scope) {
case VariableScope.Function:
ec.Emit(OpCode.LoadConstant, Value.Pointer(Address));
break;
case VariableScope.Global:
ec.Emit(OpCode.LoadGlobal, Value.Pointer(Address));
break;
case VariableScope.Arg:
ec.Emit(OpCode.LoadArg, Value.Pointer(Address));
break;
case VariableScope.Local:
ec.Emit(OpCode.LoadLocal, Value.Pointer(Address));
break;
case VariableScope.Constant:
ec.Emit(OpCode.LoadConstant, 0);
break;
default:
throw new NotSupportedException("Cannot get value of variable scope '" + Scope.ToString() + "'");
}
}
public void EmitPointer(EmitContext ec)
{
switch (Scope) {
case VariableScope.Function:
ec.Emit(OpCode.LoadConstant, Value.Pointer(Address));
break;
case VariableScope.Global:
ec.Emit(OpCode.LoadConstant, Value.Pointer(Address));
break;
case VariableScope.Arg:
ec.Emit(OpCode.LoadConstant, Value.Pointer(Address));
ec.Emit(OpCode.LoadFramePointer);
ec.Emit(OpCode.OffsetPointer);
break;
case VariableScope.Local:
ec.Emit(OpCode.LoadConstant, Value.Pointer(Address));
ec.Emit(OpCode.LoadFramePointer);
ec.Emit(OpCode.OffsetPointer);
break;
case VariableScope.Constant:
ec.Emit(OpCode.LoadConstant, 0);
break;
default:
throw new NotSupportedException("Cannot get address of variable scope '" + Scope.ToString() + "'");
}
}
}
}