EmitContext
using CLanguage.Syntax;
using CLanguage.Types;
using System;
using System.Linq;
namespace CLanguage.Interpreter
{
public class EmitContext
{
public CompiledFunction FunctionDecl { get; set; }
public Report Report { get; set; }
public MachineInfo MachineInfo { get; set; }
public EmitContext(MachineInfo machineInfo, Report report, CompiledFunction fdecl = null)
{
if (machineInfo == null)
throw new ArgumentNullException("machineInfo");
if (report == null)
throw new ArgumentNullException("report");
MachineInfo = machineInfo;
Report = report;
FunctionDecl = fdecl;
}
public virtual CType ResolveTypeName(TypeName typeName)
{
return MakeCType(typeName.Specifiers, typeName.Declarator, null, null);
}
public virtual ResolvedVariable ResolveVariable(string name, CType[] argTypes)
{
return null;
}
public virtual ResolvedVariable ResolveMethodFunction(CStructType structType, CStructMethod method)
{
return null;
}
public virtual void BeginBlock(Block b)
{
}
public virtual void EndBlock()
{
}
public virtual Label DefineLabel()
{
return new Label();
}
public virtual void EmitLabel(Label l)
{
}
public void EmitCast(CType fromType, CType toType)
{
if (!fromType.Equals(toType)) {
CBasicType cBasicType = fromType as CBasicType;
CBasicType cBasicType2 = toType as CBasicType;
CArrayType cArrayType;
CPointerType cPointerType;
if (cBasicType != null && cBasicType2 != null) {
int instructionOffset = GetInstructionOffset(cBasicType);
int instructionOffset2 = GetInstructionOffset(cBasicType2);
OpCode op = (OpCode)(121 + (instructionOffset * 10 + instructionOffset2));
Emit(op);
} else if ((cBasicType == null || !cBasicType.IsIntegral || !(toType is CPointerType) || cBasicType.NumValues != toType.NumValues) && ((cArrayType = (fromType as CArrayType)) == null || (cPointerType = (toType as CPointerType)) == null || cArrayType.ElementType.NumValues != cPointerType.InnerType.NumValues)) {
Report.Error(30, "Cannot convert type '" + fromType + "' to '" + toType + "'");
}
}
}
public void EmitCastToBoolean(CType fromType)
{
EmitCast(fromType, CBasicType.Bool);
}
public virtual void Emit(Instruction instruction)
{
}
public void Emit(OpCode op, Value x)
{
Emit(new Instruction(op, x));
}
public void Emit(OpCode op, Label label)
{
Emit(new Instruction(op, label));
}
public void Emit(OpCode op)
{
Emit(op, 0);
}
public virtual Value GetConstantMemory(string stringConstant)
{
throw new NotSupportedException("Cannot get constant memory from this context");
}
public int GetInstructionOffset(CBasicType aType)
{
int byteSize = aType.GetByteSize(this);
if (!aType.IsIntegral) {
switch (byteSize) {
case 4:
return 8;
case 8:
return 9;
}
} else {
switch (byteSize) {
case 1:
if (aType.Signedness != Signedness.Signed)
return 1;
return 0;
case 2:
if (aType.Signedness != Signedness.Signed)
return 3;
return 2;
case 4:
if (aType.Signedness != Signedness.Signed)
return 5;
return 4;
case 8:
if (aType.Signedness != Signedness.Signed)
return 7;
return 6;
}
}
throw new NotSupportedException("Arithmetic on type '" + aType + "'");
}
public CType MakeCType(DeclarationSpecifiers specs, Declarator decl, Initializer init, Block block)
{
CType type = MakeCType(specs, block);
return MakeCType(type, decl, init, block);
}
private CType MakeCType(CType type, Declarator decl, Initializer init, Block block)
{
if (!(decl is IdentifierDeclarator)) {
if (decl is PointerDeclarator) {
PointerDeclarator pointerDeclarator = (PointerDeclarator)decl;
bool flag = false;
if (pointerDeclarator.StrongBinding) {
type = MakeCType(type, pointerDeclarator.InnerDeclarator, null, block);
flag = (type is CFunctionType);
}
for (Pointer pointer = pointerDeclarator.Pointer; pointer != null; pointer = pointer.NextPointer) {
type = new CPointerType(type);
type.TypeQualifiers = pointer.TypeQualifiers;
}
if (!pointerDeclarator.StrongBinding)
type = MakeCType(type, pointerDeclarator.InnerDeclarator, null, block);
if (flag)
type = ((CPointerType)type).InnerType;
} else if (decl is ArrayDeclarator) {
ArrayDeclarator arrayDeclarator = (ArrayDeclarator)decl;
while (arrayDeclarator != null) {
int? nullable = null;
ConstantExpression constantExpression;
StructuredInitializer structuredInitializer;
if ((constantExpression = (arrayDeclarator.LengthExpression as ConstantExpression)) != null)
nullable = Convert.ToInt32(constantExpression.Value);
else if ((structuredInitializer = (init as StructuredInitializer)) != null) {
nullable = structuredInitializer.Initializers.Count;
} else {
nullable = 0;
Report.Error(2057, "Expected constant expression");
}
type = new CArrayType(type, nullable);
arrayDeclarator = (arrayDeclarator.InnerDeclarator as ArrayDeclarator);
if (arrayDeclarator != null && arrayDeclarator.InnerDeclarator != null && !(arrayDeclarator.InnerDeclarator is IdentifierDeclarator) && !(arrayDeclarator.InnerDeclarator is ArrayDeclarator))
type = MakeCType(type, arrayDeclarator.InnerDeclarator, null, block);
}
} else if (decl is FunctionDeclarator) {
type = MakeCFunctionType(type, decl, block);
}
}
return type;
}
private CType MakeCFunctionType(CType returnType, Declarator decl, Block block)
{
FunctionDeclarator functionDeclarator = (FunctionDeclarator)decl;
IdentifierDeclarator identifierDeclarator;
bool isInstance = (identifierDeclarator = (decl.InnerDeclarator as IdentifierDeclarator)) != null && identifierDeclarator.Context.Count > 0;
string declaredIdentifier = decl.DeclaredIdentifier;
CFunctionType cFunctionType = new CFunctionType(returnType, isInstance);
foreach (ParameterDeclaration parameter in functionDeclarator.Parameters) {
CType cType = MakeCType(parameter.DeclarationSpecifiers, parameter.Declarator, null, block);
if (!cType.IsVoid)
cFunctionType.AddParameter(parameter.Name, cType);
}
return MakeCType(cFunctionType, functionDeclarator.InnerDeclarator, null, block);
}
public CType MakeCType(DeclarationSpecifiers specs, Block block)
{
TypeSpecifier typeSpecifier = specs.TypeSpecifiers.FirstOrDefault((TypeSpecifier x) => x.Kind == TypeSpecifierKind.Builtin);
if (typeSpecifier != null) {
if (typeSpecifier.Name == "void")
return CType.Void;
Signedness signedness = Signedness.Signed;
string text = "";
TypeSpecifier typeSpecifier2 = null;
foreach (TypeSpecifier typeSpecifier4 in specs.TypeSpecifiers) {
if (typeSpecifier4.Name == "unsigned")
signedness = Signedness.Unsigned;
else if (typeSpecifier4.Name == "signed") {
signedness = Signedness.Signed;
} else if (typeSpecifier4.Name == "short" || typeSpecifier4.Name == "long") {
text = ((text.Length != 0) ? (text + " " + typeSpecifier4.Name) : typeSpecifier4.Name);
} else {
typeSpecifier2 = typeSpecifier4;
}
}
string text2 = (typeSpecifier2 == null) ? "int" : typeSpecifier2.Name;
object obj;
switch (text2) {
default:
obj = new CIntType(text2, signedness, text);
break;
case "bool":
obj = CBasicType.Bool;
break;
case "double":
obj = CBasicType.Double;
break;
case "float":
obj = CBasicType.Float;
break;
}
((CType)obj).TypeQualifiers = specs.TypeQualifiers;
return (CType)obj;
}
TypeSpecifier typeSpecifier3 = specs.TypeSpecifiers.FirstOrDefault(delegate(TypeSpecifier x) {
if (x.Kind != TypeSpecifierKind.Struct)
return x.Kind == TypeSpecifierKind.Class;
return true;
});
if (typeSpecifier3 != null) {
if (typeSpecifier3.Body != null) {
CStructType cStructType = new CStructType();
cStructType.Name = typeSpecifier3.Name;
{
foreach (Statement statement in typeSpecifier3.Body.Statements) {
AddStructMember(cStructType, statement, block);
}
return cStructType;
}
}
string name = typeSpecifier3.Name;
if (block.Structures.TryGetValue(name, out CStructType value))
return value;
Report.Error(246, "The struct '{0}' could not be found", name);
return CBasicType.SignedInt;
}
throw new NotImplementedException();
}
private void AddStructMember(CStructType st, Statement s, Block block)
{
MultiDeclaratorStatement multiDeclaratorStatement;
if ((multiDeclaratorStatement = (s as MultiDeclaratorStatement)) == null)
throw new NotSupportedException($"""{s}""");
if (multiDeclaratorStatement.InitDeclarators != null) {
foreach (InitDeclarator initDeclarator in multiDeclaratorStatement.InitDeclarators) {
CType cType = MakeCType(multiDeclaratorStatement.Specifiers, initDeclarator.Declarator, initDeclarator.Initializer, block);
if (!(cType is CFunctionType))
throw new NotSupportedException($"""{initDeclarator}""");
string declaredIdentifier = initDeclarator.Declarator.DeclaredIdentifier;
st.Members.Add(new CStructMethod {
Name = declaredIdentifier,
MemberType = cType
});
}
}
}
}
}