Expression
using CLanguage.Compiler;
using CLanguage.Types;
using System;
using System.Runtime.CompilerServices;
namespace CLanguage.Syntax
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public abstract class Expression
{
public Location Location { get; set; }
public Location EndLocation { get; set; }
public bool HasError { get; set; }
public virtual bool CanEmitPointer => false;
public void Emit(EmitContext ec)
{
DoEmit(ec);
}
public void EmitPointer(EmitContext ec)
{
DoEmitPointer(ec);
}
public abstract CType GetEvaluatedCType(EmitContext ec);
protected abstract void DoEmit(EmitContext ec);
protected virtual void DoEmitPointer(EmitContext ec)
{
throw new NotSupportedException($"""{GetType().Name}""{this}""");
}
protected static CType GetPromotedType(Expression expr, string op, EmitContext ec)
{
CType evaluatedCType = expr.GetEvaluatedCType(ec);
CBasicType cBasicType = evaluatedCType as CBasicType;
if (cBasicType != null)
return cBasicType.IntegerPromote(ec);
CArrayType cArrayType = evaluatedCType as CArrayType;
if (cArrayType != null)
return cArrayType.ElementType.Pointer;
if (evaluatedCType is CPointerType)
return evaluatedCType;
ec.Report.Error(19, "'" + op + "' cannot be applied to operand of type '" + evaluatedCType?.ToString() + "'");
return CBasicType.SignedInt;
}
protected static CType GetArithmeticType(Expression leftExpr, Expression rightExpr, string op, EmitContext ec)
{
CType evaluatedCType = leftExpr.GetEvaluatedCType(ec);
CType evaluatedCType2 = rightExpr.GetEvaluatedCType(ec);
CBasicType cBasicType = evaluatedCType as CBasicType;
CBasicType cBasicType2 = evaluatedCType2 as CBasicType;
if (cBasicType != null && cBasicType2 != null)
return cBasicType.ArithmeticConvert(cBasicType2, ec);
CPointerType cPointerType = evaluatedCType as CPointerType;
if (cPointerType != null && cBasicType2 != null)
return cPointerType;
CArrayType cArrayType = evaluatedCType as CArrayType;
if (cArrayType != null && cBasicType2 != null)
return cArrayType.ElementType.Pointer;
CPointerType cPointerType2 = evaluatedCType2 as CPointerType;
if (cPointerType2 != null && cBasicType != null)
return cPointerType2;
CArrayType cArrayType2 = evaluatedCType2 as CArrayType;
if (cArrayType2 != null && cBasicType != null)
return cArrayType2.ElementType.Pointer;
ec.Report.Error(19, "'" + op + "' cannot be applied to operands of type '" + evaluatedCType?.ToString() + "' and '" + evaluatedCType2?.ToString() + "'");
return CBasicType.SignedInt;
}
public virtual Value EvalConstant(EmitContext ec)
{
ec.Report.Error(133, $"""{this}""");
return 0;
}
}
}