CLanguage by praeclarum

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

 EmitContext

public class 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 }); } } } } }