VariableExpression
using CLanguage.Interpreter;
using CLanguage.Types;
using System;
namespace CLanguage.Syntax
{
public class VariableExpression : Expression
{
public string VariableName { get; set; }
public VariableExpression(string val)
{
VariableName = val;
}
public override CType GetEvaluatedCType(EmitContext ec)
{
ResolvedVariable resolvedVariable = ec.ResolveVariable(VariableName, null);
if (resolvedVariable != null)
return resolvedVariable.VariableType;
return CBasicType.SignedInt;
}
protected override void DoEmit(EmitContext ec)
{
ResolvedVariable resolvedVariable = ec.ResolveVariable(VariableName, null);
if (resolvedVariable != null) {
if (resolvedVariable.Scope == VariableScope.Function)
ec.Emit(OpCode.LoadConstant, Value.Pointer(resolvedVariable.Address));
else if (resolvedVariable.VariableType is CBasicType || resolvedVariable.VariableType is CPointerType) {
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)
throw new NotSupportedException("Cannot evaluate variable scope '" + resolvedVariable.Scope + "'");
ec.Emit(OpCode.LoadLocal, resolvedVariable.Address);
}
} else {
if (!(resolvedVariable.VariableType is CArrayType))
throw new NotSupportedException("Cannot evaluate variable type '" + resolvedVariable.VariableType + "'");
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)
throw new NotSupportedException("Cannot evaluate array variable scope '" + resolvedVariable.Scope + "'");
ec.Emit(OpCode.LoadConstant, Value.Pointer(resolvedVariable.Address));
ec.Emit(OpCode.LoadFramePointer);
ec.Emit(OpCode.OffsetPointer);
}
}
} else {
ec.Report.Error(103, $"""{VariableName}""");
ec.Emit(OpCode.LoadConstant, 0);
}
}
protected override void DoEmitPointer(EmitContext ec)
{
ResolvedVariable resolvedVariable = ec.ResolveVariable(VariableName, null);
if (resolvedVariable != null)
resolvedVariable.Emit(ec);
else {
ec.Report.Error(103, $"""{VariableName}""");
ec.Emit(OpCode.LoadConstant, 0);
}
}
public override string ToString()
{
return VariableName.ToString();
}
}
}