""" Abstract Base class for defining items that have different implementations for each back end. Used in Compiler, Backends defined/implemented in BackEnd/BackEnd e.g. BackEndJvm/JvmBackEnd.cobra, BackendClr/ClrBackEnd Still subject to change. """ use System.Diagnostics class BackEnd is abstract """ Holder for items and actions specific to the backEnd implementation """ var _tagToTypeName = Dictionary() """ Map from Typename tags used in compiler to backend specific qualified Type name. """ var _additionalRunTimeLibs = List() get name from _name as String """ Name of this backend: format is 'language-platform' e.g 'c#-clr'. """ get cobraRuntimeLibFileName from _runTimeLibFileName as String """ Name of the Cobra RunTime Library file for this backend. """ get runTimeLibNativeSourceFileName from _runTimeLibNativeSourceFileName as String """ Name of the backEnd source file containing any native code support for Cobra.Core. """ get additionalRunTimeLibs from var """ Names of additional (System) libs to always reference with ert or not. """ get compiler from __compiler as Compiler cue init(compiler as Compiler) base.init _name = '' # these two are unused defaults, overidden in concrete classes _runTimeLibFileName = 'rtl' _runTimeLibNativeSourceFileName = 'rtlSrc.ext' __compiler = compiler get tagToTypeName from var """ Map from TypeName tags used in compiler to backend specific qualified TypeName""" def resolveTypeTag(qualifiedNameOrTag as String) as String """Turn qualified type name or a type tag into backEnd className.""" if qualifiedNameOrTag.contains('.') qualifiedName = qualifiedNameOrTag else qualifiedName = .tagToTypeName[qualifiedNameOrTag] # type tag to backend qualifiedName return qualifiedName def makePhases(phases as IList) is abstract """ Given a list of core phases for compilation complete it with additions (or even removals and rearrangements if necessary) for this given backend. """ def getRecommendedBuiltInType(parentNameSpace as NameSpace?, name as String) as String? is abstract """ If parentNameSpace is the main system namespace and name is a back-end builtin type return the Cobra equivalent language type name (or nil). """ def computeOutName as String is abstract """ Return the binary file output name for compilation of files for this backend. """ get baseExeName as String """Resulting executable file name for compiled file(s) sans extension.""" return '' get fullExeName as String """Resulting executable file name (pathname+extn) for compiled file(s).""" return '' def genNativeModule(file as FileSpec, verbosity as int) as Module? is abstract """ Check if a file is a Native module and if so generate and return the Native module type for it, otherwise return nil. """ def setupRunProcess(baseExe as String, fullExe as String) as Process is abstract """ Create and initialise the process to run the compiled program post compilation setup varies on the backend (.Clr/Jvm) and platform. """ def setDefaultUseDirectives(ns as NameSpace) is abstract """ Set the default Use directives into the given Namespace (usually topNamespace) for this backend. """ def fixLibExtension(libRef as String) as String is abstract """ Augment given lib reference string with backend extension if not already have one. """ def loadLibReference(reference as String) as String? is abstract """ Load the given library reference file using the current backend paradigms. Returns an error message, or nil if the reference was loaded correctly. """ def readSystemTypes is abstract """ Read and Load the System Types for this backend for the compiler to make available.""" def fixMemberSigs is abstract """ Most backends dont natively support nilablility, this marks/fixes the common backend class signatures that should be marked nilable. """ def installNativeMethods(box as Box, nativeType as NativeType) is abstract """ Setup so that static methods (on Primitives and some others) get installed/treated as normal methods on the instance. """ def isRunnableFile( fullExeFileName as String) as bool is abstract """Test if given filename is an executable ( vs a library or something else) """ ## Native Types access def cobraNameForNativeBoxName(name as String) as String is abstract """ Returns name from backend library entries converted to cobra naming form. """ get objectTypeProxy as AbstractTypeProxy is abstract """Return backEnd TypeProxy for root of back end Object hierarchy.""" get typeTypeProxy as AbstractTypeProxy is abstract """Return backEnd TypeProxy for BackEnd notion of a class describing a Type.""" def nativeTypeProxy(type as NativeType) as NativeTypeProxy is abstract """ Return a proxy placeHolder for a BackEnd Native Type. """ def nativeType(type as dynamic) as NativeType is abstract """ Return a Native Type wrapped so we can use it without explicitly knowing what it is anywhere else but the providing back end. Used by the backends to generate Types from Libraries. """ def nativeTypeByName(qualifiedName as String) as NativeType is abstract """ Return a Native Type corresponding to the fully qualified name. Abstract Type literal tags used in the compiler directly can also be obtained through this otherwise the qualified names are expected to conform to the platform back end naming. """ def prepSystemObjectClass(box as Box) is abstract """Setup additional or convenience members on the System Object class. """ def scanGenericArgs(box as Box) is abstract """Scan a loaded Dll (generic) type and translate from native any generic Args.""" def scanNativeType(box as Box) is abstract """Scan a loaded Dll type and convert its native Type info to Cobras form """ def scanNativeType(edcl as EnumDecl) is abstract """Scan a loaded Dll Enum type and convert its native info to Cobras form """ def setUnderlyingType(edcl as EnumDecl) is abstract """Set underlying Storage Type of the value of an Enum.""" def determineExtnNativeType(extn as Extension, nativeType as NativeType) as NativeType """ The real extended type is the type of the first argument of any method. Find and make that type from the param list. """ throw Exception('Need implementation of determineExtnNativeType for backend to determine type for an extension') def handleNameSpaceNameCollision(ns as NameSpace, token as IToken, name as String) as NameSpace """ What to do if a namespace name collides with an existing symbol. Some backends disallow this situation so its an error. Others keep namespace and symbol tables separate so its perfectly allowable. """ throw Exception('In [ns.name] there is a already non-namespace declaration named "[name]".') def getEnumeratorMember(box as Box) as IMember? is abstract """Find enumerator/iterator method member in given Box.""" def getEnumeratorMemberType(box as Box, rt as IType) as IType? is abstract """ Return the type from lookup of enumerator/iterator 'next-item' field for provided enumerator/iterator (rt) from iterator for given Box. """ def validatePrintDestType(t as IType, s as Stmt) is abstract """ Validate the given Type as a valid destination for a print statement redirection. If not record an error message against the stmt node. """ class FakeBackEnd inherits BackEnd """ Stub BackEnd for tests. """ cue init(compiler as Compiler) base.init(compiler) _name = 'c#-clr(test)' _runTimeLibFileName = 'cobraRTL.libext' _runTimeLibNativeSourceFileName = 'cobraRTL.ext' _tagToTypeName = { 'Object': 'System.Object', 'Type' : 'System.Type', } def makePhases(phases as IList) is override pass def getRecommendedBuiltInType(parentNameSpace as NameSpace?, name as String) as String? is override return nil def computeOutName as String is override return 'FakeOut' def genNativeModule(file as FileSpec, verbosity as int) as Module? is override return nil def setupRunProcess(baseExe as String, fullExe as String) as Process is override p = Process() p.startInfo.fileName = 'echo' p.startInfo.arguments = 'basic BackEnd process - [fullExe]' return p def setDefaultUseDirectives(ns as NameSpace) is override pass def fixLibExtension(libRef as String) as String is override if not libRef.endsWith('.libext') libRef += '.libext' return libRef def loadLibReference(reference as String) as String? is override return nil def readSystemTypes is override pass def fixMemberSigs is override pass def installNativeMethods(box as Box, nativeType as NativeType) is override pass def isRunnableFile(fullExeFileName as String) as bool is override return true # Native Type access def cobraNameForNativeBoxName(name as String) as String is override return name + '_BBE' def prepSystemObjectClass(box as Box) is override pass def scanGenericArgs(box as Box) is override pass def scanNativeType(box as Box) is override pass def scanNativeType(edcl as EnumDecl) is override pass def setUnderlyingType(edcl as EnumDecl) is override pass # Types get objectTypeProxy as AbstractTypeProxy is override return ClrTypeProxy(Object) # for testing get typeTypeProxy as AbstractTypeProxy is override return ClrTypeProxy(Type )# for testing def nativeTypeProxy(type as NativeType) as NativeTypeProxy is override return ClrTypeProxy(type) #TODO: fix this to something non BE specific Tmp def nativeType(type) as NativeType is override return ClrNativeType(type) #TODO: fix this to something non BE specific Tmp def nativeTypeByName(qualifiedName as String) as NativeType is override return ClrNativeType(System.Object) #TODO: fix this to something non BE specific Tmp def getEnumeratorMember(box as Box) as IMember? is override return nil def getEnumeratorMemberType(box as Box, rt as IType) as IType? is override return nil def validatePrintDestType(t as IType, s as Stmt) is override pass