use System.Diagnostics use System.Reflection class ClrBackEnd inherits BackEnd var _objectTypeProxy as AbstractTypeProxy var _typeTypeProxy as AbstractTypeProxy cue init(compiler as Compiler) base.init(compiler) _objectTypeProxy = ClrTypeProxy(Object) _typeTypeProxy = ClrTypeProxy(Type) _name = 'c#-clr' _runTimeLibFileName = 'Cobra.Core.dll' _runTimeLibNativeSourceFileName = 'Native.cs' # backEnd source file containing native code support for Cobra.Core # using .NET 4.0 compiler # if not compiler.options['native-compiler'].length or compiler.options['native-compiler'] contains '4' _additionalRunTimeLibs = ['System.Core.dll'] # on .NET 4.0 _tagToTypeName = { 'Object' : 'System.Object', 'Type' : 'System.Type', 'String' : 'System.String', 'Exception' : 'System.Exception', 'Delegate' : 'System.Delegate', 'Attribute' : 'System.Attribute', 'ICloneable': 'System.ICloneable', 'IEnumerable': 'System.Collections.IEnumerable', 'IEnumerator': 'System.Collections.IEnumerator', 'IEnumerable' : 'System.Collections.Generic.IEnumerable', 'IEnumerator' : 'System.Collections.Generic.IEnumerator', 'IDictionaryEnumerator' : 'System.Collections.IDictionaryEnumerator', 'ICollection': 'System.Collections.ICollection', 'ICollection': 'System.Collections.Generic.ICollection', 'IList' : 'System.Collections.IList', 'IList' : 'System.Collections.Generic.IList', 'List': 'System.Collections.Generic.List', 'IDictionary': 'System.Collections.IDictionary', 'IDictionary': 'System.Collections.Generic.IDictionary', 'Dictionary' : 'System.Collections.Generic.Dictionary', 'KeyValuePair':'System.Collections.Generic.KeyValuePair', 'Set': 'Cobra.Core.Set', 'bool' : 'System.Boolean', 'char' : 'System.Char', 'decimal': 'System.Decimal', 'single': 'System.Single', 'double': 'System.Double', 'sbyte' : 'System.SByte', 'int16' : 'System.Int16', 'int32' : 'System.Int32', 'int64' : 'System.Int64', 'byte' : 'System.Byte', 'uint16': 'System.UInt16', 'uint32': 'System.UInt32', 'uint64': 'System.UInt64', } def makePhases(phases as IList) is override phases.add(GenerateSharpCodePhase(.compiler)) phases.add(CompileSharpCodePhase(.compiler)) def getRecommendedBuiltInType(parentNameSpace as NameSpace?, name as String) as String? is override n = nil to String? if parentNameSpace and parentNameSpace.fullName == 'System' branch name on 'Boolean', n = 'bool' on 'SByte', n = 'int8' on 'Byte', n = 'uint8' on 'Int16', n = 'int16' on 'UInt16', n = 'uint16' on 'Int32', n = 'int32' on 'UInt32', n = 'uint32' on 'Int64', n = 'int64' on 'UInt64', n = 'uint64' on 'Char', n = 'char' on 'Single', n = 'float32' on 'Double', n = 'float' on 'Decimal', n = 'decimal' return n def computeOutName as String is override return .compiler.computeOutNameSharp def genNativeModule(file as FileSpec, verbosity as int) as Module? is override m as Module? = nil if file.path and file.path.endsWith('.cs') if verbosity, print 'Noting [file.path] as SharpModule' # extra space to line up with 'Parsing [filename]' m = SharpModule(file, verbosity) return m get baseExeName as String is override """Resulting executable file name for compiled file(s) sans extension.""" return .compiler.clrBaseExeFileName get fullExeName as String is override """Resulting full executable file name (pathname+extn) for compiled file(s).""" return .compiler.clrFullExeFileName def setupRunProcess(baseExe as String, fullExe as String) as Process is override p = Process() branch .compiler.platform on PlatformEnum.Microsoft p.startInfo.fileName = baseExe on PlatformEnum.Novell p.startInfo.fileName = 'mono' args = '' # mono also needs --debug when running if .compiler.options.getDefault('debug', '') not in ['', '-'] args += '--debug ' args += '"[fullExe]"' p.startInfo.arguments = args + ' ' else throw FallThroughException(.compiler.platform) return p def setDefaultUseDirectives(ns as NameSpace) is override useToken = Token('(implicit)', 1, 1, 1, 'USE', 'use', nil) # TODO: make an "implicit" token ns.addUseDirective(UseDirective(useToken, ['System'])) ns.addUseDirective(UseDirective(useToken, ['System', 'Collections', 'Generic'])) ns.addUseDirective(UseDirective(useToken, ['System', 'IO'])) ns.addUseDirective(UseDirective(useToken, ['System', 'Text'])) ns.addUseDirective(UseDirective(useToken, ['Cobra', 'Core'])) #ns.addUseDirective(UseDirective(useToken, ['Cobra', 'Extn'])) # to-do: what is this? def fixLibExtension(libRef as String) as String is override """ Augment the given library filename reference with backend extension if not already have one. """ or require libRef.length and ensure result.endsWith('.dll') or result.endsWith('.exe') if not libRef.endsWith('.dll') and not libRef.endsWith('.exe') libRef += '.dll' return libRef def loadLibReference(reference as String) as String? is override return .compiler.clrLoadReference(reference) # in ScanClrType def readSystemTypes is override # TODO: Move the called support methods below out of Compiler clrProfile = .compiler.options.getDefault('clr-profile', '') to String if clrProfile <> '' if clrProfile.contains('MonoTouch') ver = Assembly.getAssembly(Object).imageRuntimeVersion if ver.startsWith('v'), ver = ver[1:] msg = 'You should be running Cobra on CLR 4 or higher when targeting MonoTouch.' # realistically, the warning may never be displayed due to an exception when trying # to load the assembly. so print it now: print 'cobra: warning:', msg if ver[0] in '123', .compiler.warning(CobraWarning('You should be running Cobra on CLR 4 or higher when targeting MonoTouch.')) for libName in ['mscorlib.dll', 'System.dll'] path = Path.combine(clrProfile, libName) a = Assembly.loadFile(path) to ! .compiler.clrReadAssembly(a) else # TODO: support targeting a specific CLR version, but not below 2.0 .compiler.clrReadAssembly(Assembly.load('mscorlib.dll') to !) # TODO: .readAssembly(Assembly.loadFrom('System.dll') to !) # gives: Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'System.dll' or one of its dependencies. The system cannot find the file specified. t = System.Diagnostics.Process.getType .compiler.clrReadAssembly(t.assembly) # System.dll def fixMemberSigs is override .compiler.dotNetFixNilableMemberSigs # in ScanClrType def isRunnableFile(fullExeFileName as String) as bool is override """Test if filename is runnable ( vs a library or something else) """ return fullExeFileName.endsWith('.exe') # Types get objectTypeProxy from var is override """Type proxy for BE root of Object hierarchy.""" get typeTypeProxy from var is override """Type proxy for BE notion of a class describing a Type.""" def cobraNameForNativeBoxName(nativeBoxName as String) as String is override return ClrTypeProxy.cobraNameForSharpBoxName(nativeBoxName) def nativeTypeProxy(type as NativeType) as NativeTypeProxy is override return ClrTypeProxy(type) def nativeType(type as dynamic) as NativeType is override return ClrNativeType(type) def nativeTypeByName(qualifiedNameOrTag as String) as NativeType is override qualifiedName = .resolveTypeTag(qualifiedNameOrTag) return ClrNativeType(.compiler.clrTypeByName(qualifiedName)) /# These are the type tags used directly by cobra code. bool 'System.Boolean' char 'System.Char' decimal 'System.Decimal' single 'System.Single' double 'System.Double' sbyte 'System.SByte' int16 'System.Int16' int32 'System.Int32' int64 'System.Int64' byte 'System.Byte' uint16 'System.UInt16' uint32 'System.UInt32' uint64 'System.UInt64' #/ def installNativeMethods(box as Box, nativeType as NativeType) is override .compiler.installClrNativeMethods(box, nativeType to ClrNativeType) # in ScanClrType def prepSystemObjectClass(box as Box) is override box.prepSystemObjectClassClr def scanGenericArgs(box as Box) is override box.scanGenericArgsClr def scanNativeType(box as Box) is override """ Do scan/Load of Types from a dll """ box.scanNativeTypeClr def scanNativeType(edcl as EnumDecl) is override edcl.scanNativeTypeClr def setUnderlyingType(edcl as EnumDecl) is override edcl.setUnderlyingTypeClr def determineExtnNativeType(extn as Extension, nativeType as NativeType) as NativeType is override return extn.clrExtnNativeType(nativeType) # ScanClrType def handleNameSpaceNameCollision(ns as NameSpace, token as IToken, name as String) as NameSpace is override """Clr doesnt allow colliding names.""" throw Exception('In [ns.name] there is a already non-namespace declaration named "[name]".') def getEnumeratorMember(box as Box) as IMember? is override """ Find enumerator method member in given Box.""" return box.getEnumeratorMemberClr def getEnumeratorMemberType(box as Box, enumResultType as IType) as IType? is override """Return type from lookup of enumerator 'current' field from in given Box.""" return box.getEnumeratorMemberTypeClr(enumResultType) def validatePrintDestType(t as IType, n as Stmt) is override """ Check that the given Type is a valid destination for a print statement redirection. If not record an error message """ if not t.isDescendantOf(.compiler.libraryType('System.IO.TextWriter')) # actually only needs a write/writeLine call n.recordError('Invalid destination of type "[t.name]" for "print". Use a TextWriter or subclass thereof instead.') class GenerateSharpCodePhase inherits Phase cue init(c as Compiler) base.init(c) get description as String is override return 'Generating C# code' def innerRun is override c = .compiler v = c.verbosity nativeCompiler = c.options.getDefault('native-compiler', '') to String if nativeCompiler == 'auto' if CobraCore.isRunningOnMono nativeCompiler = 'provider' entryAssemblyDir = Path.getDirectoryName(Assembly.getEntryAssembly.location) for candidateDllName in _candidateDllNames cobraSharp = Path.combine(entryAssemblyDir, candidateDllName) if File.exists(cobraSharp) if v >= 2, print '-native-compiler:auto ... Found [cobraSharp]' nativeCompiler = cobraSharp break else if v >= 2, print '-native-compiler:auto ... Not running on Mono' nativeCompiler = 'provider' c.nativeCompiler = nativeCompiler c.willWriteSharpToDisk = not nativeCompiler.endsWith('.dll') # only Cobra.Sharp.*.dll will take in-memory source code c.writeSharp # extension method if c.willWriteTestInvocation c.writeSharpTestInvocation def _candidateDllNames as String* is private # .monoVersionString could be '2.6.7' or 'Cobra.Sharp.2_8 (tarball Mon Oct 11 00:24:15 PDT 2010).dll' monoVer = CobraCore.monoVersionString.split(c' ')[0].trim if '.' in monoVer parts = monoVer.split(c'.') if parts.length >= 2 ver = parts[0] + '_' + parts[1] # ex: '2.4', '2.6', '2.7' name = 'Cobra.Sharp.' + ver + '.dll' yield name yield 'Cobra.Sharp.dll' class CompileSharpCodePhase inherits Phase cue init(c as Compiler) base.init(c) get description as String is override return 'Compiling C# code' def innerRun is override .compiler.compileSharp