The .NET Framework and all its tools form a two-part system: it has a compiler that compiles a language such as C# into an assembly with CIL code, and a just-in-time (JIT) compiler that compiles the CIL to machine code.
A big advantage of the CLR is that you can specify any type you want just by using its fully qualified name. In addition, the assembly specifies in which assemblies such types can be found. Then when later the JIT compiler comes along, it will look at the fully qualified type name, load the referenced assembly that contains the type, and use that. The type does not have to be known beforehand, and there is never an issue with circular references. So if you put some types in a core library, all you have to do is to make sure the CLR assemblies generated from your language reference your core library, and then the types in them are instantly available for use.
The JIT compiler includes only logic to handle some primitive types (32-bit integer, 64-bit integer, float, managed references and managed pointers) and knows about some very special object classes (Object
, Enum
, ValueType
, Delegate
, ...). Almost all other functionality is either simulated with the primitive types (e.g. boolean true
is any integer with a non-zero value) or supported through (virtual or non-virtual) method calls (properties, methods, overloaded operators, coercions and conversions all use method calls internally). Only some core functionality that cannot be expressed (efficiently) in a managed language (such as adding integers, or allocating arrays) is integrated in the JIT compiler.