/// <summary> /// Create a new SmalltalkObject for a given SmalltalkClass. /// </summary> /// <param name="cls">The SmalltalkClass that this object will be instance of.</param> public SmalltalkObject(SmalltalkClass cls) { if (cls == null) throw new ArgumentNullException(); this.Class = cls; this.InstanceVariables = new object[cls.InstanceSize]; }
public SmalltalkDynamicMetaObject(Expression expression, BindingRestrictions restrictions, SmalltalkClass cls, object value) : base(expression, restrictions, value) { if (cls == null) throw new ArgumentNullException("cls"); this.Class = cls; }
/// <summary> /// Look-up a method implementation starting with the given class. /// </summary> /// <param name="cls">Class where to start searching for the method (unless superLookupScope) is set.</param> /// <param name="superLookupScope">If set, start the lookup from the superclass of this class.</param> /// <param name="lookupFunction">Function to perform the method lookup.</param> /// <returns>Returns the compiled method for the given selector or null if none was found.</returns> public static CompiledMethod LookupMethod(ref SmalltalkClass cls, Symbol superLookupScope, Func <SmalltalkClass, CompiledMethod> lookupFunction) { if (lookupFunction == null) { throw new ArgumentNullException("lookupFunction"); } while (cls != null) { if (superLookupScope == null) { CompiledMethod method = lookupFunction(cls); if (method != null) { return(method); } } else { if (cls.Name == superLookupScope) { superLookupScope = null; } } cls = cls.Superclass; } // No method ... no luck; return(null); }
public ClassRelatedBindingScope(SmalltalkClass cls, BindingScope outerScope) : base(outerScope) { if (cls == null) throw new ArgumentNullException(); this.Class = cls; }
public Expression CompileMethod(MethodNode parseTree, SmalltalkClass cls, Expression self, Expression executionContext, Expression[] arguments) { if (parseTree == null) { throw new ArgumentNullException("parseTree"); } if (cls == null) { throw new ArgumentNullException("cls"); } if (self == null) { throw new ArgumentNullException("self"); } if (arguments == null) { throw new ArgumentNullException("arguments"); } RootCompilationContext context = this.GetCompilationContext(parseTree, cls, self, executionContext, arguments); MethodVisitor visitor = new MethodVisitor(context); Expression code = parseTree.Accept(visitor); return(code); }
public NativeCompiledMethod(SmalltalkClass cls, Symbol selector, MethodType methodType, MethodInfo nativeMethod) : base(cls, selector, methodType) { if (nativeMethod == null) { throw new ArgumentNullException("nativeMethod"); } this.NativeMethod = nativeMethod; }
public ClassVariableBinding(string name, SmalltalkClass cls, RTB.ClassVariableBinding binding) : base(name, binding) { if (cls == null) { throw new ArgumentNullException("cls"); } this.Class = cls; }
public ClassRelatedBindingScope(SmalltalkClass cls, BindingScope outerScope) : base(outerScope) { if (cls == null) { throw new ArgumentNullException(); } this.Class = cls; }
public RuntimeCompiledMethod(SmalltalkClass cls, Symbol selector, MethodType methodType, MethodNode parseTree, IDebugInfoService debugInfoService) : base(cls, selector, methodType) { if (parseTree == null) { throw new ArgumentNullException(); } this.ParseTree = parseTree; this.DebugInfoService = debugInfoService; }
private static bool InheritsFrom(SmalltalkClass self, SmalltalkClass cls) { while (self != null) { if (self.Superclass == cls) { return(true); } self = self.Superclass; } return(false); }
void IDefinitionInstallerContext.RegisterNewClass(SmalltalkClass cls, ISourceReference sourceReference) { if (cls == null) { throw new ArgumentNullException("cls"); } if (sourceReference == null) { throw new ArgumentNullException("sourceReference"); } this._newClasses.Add(new Tuple <SmalltalkClass, ISourceReference>(cls, sourceReference)); }
/// <summary> /// Look-up for a class method implementation given a method selector and a class. /// </summary> /// <param name="selector">Method selector to look for.</param> /// <param name="cls">Class where to start searching for the method (unless superLookupScope) is set.</param> /// <param name="superLookupScope">If set, start the lookup from the superclass of this class.</param> /// <returns>Returns the compiled method for the given selector or null if none was found.</returns> /// <remarks>If the method is not found, this functions does not searches the instance side of the class.</remarks> public static CompiledMethod LookupClassMethod(Symbol selector, ref SmalltalkClass cls, Symbol superLookupScope) { return(MethodLookupHelper.LookupMethod(ref cls, superLookupScope, c => { CompiledMethod method; if (c.ClassBehavior.TryGetValue(selector, out method)) { return method; } return null; })); }
public override IDiscreteBinding GetBinding(ExecutionContext executionContext) { SmalltalkClass cls = executionContext.Runtime.GetClass(this.ClassName); if (cls == null) { return(null); } ClassVariableBinding binding = null; cls.ClassVariableBindings.TryGetValue(this.VariableName, out binding); return(binding); }
/// <summary> /// Create a new CompiledMethod. /// </summary> /// <param name="cls">The class that defines the method.</param> /// <param name="selector">The selector of the method.</param> /// <param name="methodType">The type of method - either a class or an instance method.</param> protected CompiledMethod(SmalltalkClass cls, Symbol selector, MethodType methodType) { if (cls == null) { throw new ArgumentNullException("cls"); } if (selector == null) { throw new ArgumentNullException("selector"); } this.Class = cls; this.Selector = selector; this.Type = methodType; }
public static string GetMoniker(SmalltalkClass cls, ClassVariableBinding binding) { if (cls == null) { throw new ArgumentNullException("cls"); } if (binding == null) { throw new ArgumentNullException("binding"); } return(DiscreteBindingCallSiteBinderBase.GetMoniker( DiscreteBindingCallSiteBinderBase.ClassVariablePrefix, cls.Name.Value, binding.Name.Value)); }
public static BindingScope ForClassInitializer(SmalltalkClass cls, SmalltalkNameScope globalNameScope) { if (cls == null) { throw new ArgumentNullException("cls"); } if (globalNameScope == null) { throw new ArgumentNullException("globalNameScope"); } //statement_scope := class_funtion_scope + local_scope + reserved_scope // Class Initializer - X3J20:3.4.3 //home_context_scope := class_funtion_scope return(new ClassFunctionScope(cls, new ClassScope(cls, new PoolVariableScope(cls, new GlobalScope(globalNameScope))))); }
public static BindingScope ForClassMethod(SmalltalkClass cls, SmalltalkNameScope globalNameScope) { if (cls == null) { throw new ArgumentNullException("cls"); } if (globalNameScope == null) { throw new ArgumentNullException("globalNameScope"); } //class_scope := (global_scope + pool_variable_scope) + inheritable_class_variable_scope // X3J20:3.3.2.3 //class_funtion_scope := class_scope + class_instance_variable_scope // X3J20:3.3.2.3 return(new ClassFunctionScope(cls, new ClassScope(cls, new PoolVariableScope(cls, new GlobalScope(globalNameScope))))); }
protected MethodGenerator(NativeCompiler compiler, SmalltalkClass cls, MethodDictionary methods) : base(compiler) { if (cls == null) { throw new ArgumentNullException("cls"); } if (methods == null) { throw new ArgumentNullException("methods"); } this.Class = cls; this.Methods = methods; this.LiteralEncodingStrategy = new NativeLiteralEncodingStrategy(this); this.DynamicCallStrategy = new NativeDynamicCallStrategy(this); this.DiscreteBindingEncodingStrategy = new NativeDiscreteBindingEncodingStrategy(this); }
protected override NameBinding ResolveBinding(string name) { // inheritable_class_variable_scope SmalltalkClass cls = this.Class; RTB.ClassVariableBinding binding; while (cls != null) { cls.ClassVariableBindings.TryGetValue(name, out binding); if (binding != null) { return(new ClassVariableBinding(name, cls, binding)); } cls = cls.Superclass; } return(null); // null means try outer scope. }
public LambdaExpression CompileMethodLambda(MethodNode parseTree, SmalltalkClass cls, string methodName) { if (parseTree == null) { throw new ArgumentNullException("parseTree"); } // Declare parameter expression for each argument .... ParameterExpression[] arguments = MethodCompiler.CreateParametersForMethod(parseTree); // Compile the method !!! Expression body = this.CompileMethod(parseTree, cls, arguments[0], arguments[1], arguments.Skip(2).Cast <Expression>().ToArray()); // Finally, create a lambda expression out of it. return(Expression.Lambda( body, methodName, true, // always compile the rules with tail call optimization, arguments)); }
private ClassMethodGenerator(NativeCompiler compiler, SmalltalkClass cls, MethodDictionary methods) : base(compiler, cls, methods) { }
private bool InheritsFrom(SmalltalkClass self, SmalltalkClass cls) { while (self != null) { if (self.Superclass == cls) return true; self = self.Superclass; } return false; }
public static BindingScope ForInstanceMethod(SmalltalkClass cls, SmalltalkNameScope globalNameScope) { if (cls == null) throw new ArgumentNullException("cls"); if (globalNameScope == null) throw new ArgumentNullException("globalNameScope"); //class_scope := (global_scope + pool_variable_scope) + inheritable_class_variable_scope // X3J20:3.3.2.3 //instance_function_scope := class_scope + instance_variable_scope // X3J20:3.3.2.3 return new InstanceFunctionScope(cls, new ClassScope(cls, new PoolVariableScope(cls, new GlobalScope(globalNameScope)))); }
/// <summary> /// Look-up for an instance method implementation given a method selector and a class. /// </summary> /// <param name="selector">Method selector to look for.</param> /// <param name="cls">Class where to start searching for the method (unless superLookupScope) is set.</param> /// <param name="superLookupScope">If set, start the lookup from the superclass of this class.</param> /// <returns>Returns the compiled method for the given selector or null if none was found.</returns> public static CompiledMethod LookupInstanceMethod(Symbol selector, ref SmalltalkClass cls, ref Symbol superLookupScope) { return MethodLookupHelper.LookupMethod(ref cls, ref superLookupScope, delegate(SmalltalkClass c) { CompiledMethod method; if (c.InstanceBehavior.TryGetValue(selector, out method)) return method; return null; }); }
/// <summary> /// Validate that the definition of the class object does not break any rules set by the Smalltalk standard. /// </summary> /// <param name="installer">Context within which the validation is to be performed.</param> /// <returns>Returns true if successful, otherwise false.</returns> protected internal override bool ValidateObject(IDefinitionInstallerContext installer) { if (installer == null) { throw new ArgumentNullException(); } // 1. Get the binding to the global Symbol name = installer.Runtime.GetSymbol(this.Name.Value); ClassBinding binding = installer.GetLocalClassBinding(name); // 2. Check consistency that we didn't mess up in the implementation. if (binding == null) { throw new InvalidOperationException("Should have found a binding, because CreateGlobalBinding() created it!"); } if (binding.Value == null) { throw new InvalidOperationException("Should not be an empty binding, because CreateGlobalObject() just created it!"); } // 3. Get the class object. SmalltalkClass cls = binding.Value; // 4. Validate that superclass is correct List <Symbol> classes = new List <Symbol>(); classes.Add(cls.Name); SmalltalkClass tmp = cls.Superclass; while (tmp != null) { if (classes.IndexOf(tmp.Name) != -1) { return(installer.ReportError(this.SuperclassName, String.Format( InstallerErrors.ClassCircularReference, this.SuperclassName.Value, this.Name.Value))); } classes.Add(tmp.Name); tmp = tmp.Superclass; } if (cls.InstanceState != SmalltalkClass.InstanceStateEnum.ByteIndexable) { tmp = cls; while (tmp != null) { if (tmp.InstanceState == SmalltalkClass.InstanceStateEnum.ByteIndexable) { return(installer.ReportError(this.InstanceState, InstallerErrors.ClassCannotChangeInstanceState)); } tmp = tmp.Superclass; } } foreach (PoolBinding pool in cls.ImportedPoolBindings) { if (pool.Value == null) { SourceReference <string> src = this.ImportedPoolNames.SingleOrDefault(sr => sr.Value == pool.Name.Value); if (src == null) { throw new InvalidOperationException("Should not be null, cause we just added this pool in CreateGlobalObject()."); } return(installer.ReportError(src, InstallerErrors.ClassMissingPoolDefinition)); } } // NB: We must give some source reference, but since we don't have for the whole class, we use the name. installer.RegisterNewClass(cls, this.Name); return(true); // OK }
public static BindingScope ForClassInitializer(SmalltalkClass cls, SmalltalkNameScope globalNameScope) { if (cls == null) throw new ArgumentNullException("cls"); if (globalNameScope == null) throw new ArgumentNullException("globalNameScope"); //statement_scope := class_funtion_scope + local_scope + reserved_scope // Class Initializer - X3J20:3.4.3 //home_context_scope := class_funtion_scope return new ClassFunctionScope(cls, new ClassScope(cls, new PoolVariableScope(cls, new GlobalScope(globalNameScope)))); }
public PoolVariableScope(SmalltalkClass cls, GlobalScope outerScope) : base(cls, outerScope) { }
public override InitializerCompilationResult CompileClassInitializer(SmalltalkRuntime runtime, SmalltalkClass cls) { return this.CompileClassInitializer(runtime, cls, runtime.GlobalScope); }
protected override bool InternalValidateMethod(IInstallerContext installer, SmalltalkClass cls, IIntermediateCodeValidationErrorSink errorSink) { return this.IntermediateCode.ValidateClassMethod(cls, installer.NameScope, errorSink); }
/// <summary> /// Register a .Net type identified by its type-name to be mapped to the given Smalltalk class. /// </summary> /// <param name="cls">Required. Smalltalk class to map to.</param> /// <param name="typeName">Required. Type-name of the .Net type to be mapped to Smalltalk class. See remarks.</param> /// <remarks> /// The type-name can be one of: /// - Reserved name: "true", "false", "null", "nil", "native", "class", "symbol", "pool", "type" /// - C# alias, e.g. "string", "bool", "int", "float" etc. /// - IronSmalltak type prefixed with "_", e.g. "_SmalltalkRuntime". /// - mscorlib type (without any prefixes), e.g. "System.DateTime". /// - Any other type using assembly qualified name, e.g. "System.Numerics.BigInteger, System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /// </remarks> public void RegisterClass(SmalltalkClass cls, string typeName) { if (cls == null) throw new ArgumentNullException("cls"); if (System.String.IsNullOrWhiteSpace(typeName)) throw new SmalltalkDefinitionException(System.String.Format( "Invalid type name. Check native type mapping for class {0}", cls.Name), new ArgumentNullException("typeName")); // Special case handling for Smalltalk specific classes. if (typeName == "true") { this.True = cls; return; } if (typeName == "false") { this.False = cls; return; } if ((typeName == "null") || (typeName == "nil")) { this.UndefinedObject = cls; return; } if (typeName == "native") { this.Native = cls; return; } if (typeName == "class") { this.Class = cls; return; } if (typeName == "symbol") { this.Symbol = cls; return; } if (typeName == "pool") { this.Pool = cls; return; } if (typeName == "type") { this.SystemType = cls; return; } //struct, enum, delegate, event ... do we need to handle those? // Generic classes ... remap C# convenience names to FCL names. Type type; if (typeName.StartsWith(NativeTypeClassMap.IstTypenamePrefix)) { type = NativeTypeClassMap.GetIstType(typeName); } else { typeName = NativeTypeClassMap.RemapTypeName(typeName); try { type = Type.GetType(typeName, true, false); } catch (Exception ex) { throw new SmalltalkDefinitionException(System.String.Format( "Cannot find type {0}. Check native type mapping for class {1}", typeName, cls.Name), ex); } } // Some very common types are cached directly if (type == typeof(object)) this.Object = cls; else if (type == typeof(int)) this.SmallInteger = cls; else if (type == typeof(char)) this.Character = cls; else if (type == typeof(string)) this.String = cls; else if (type == typeof(double)) this.Float = cls; else if (type == typeof(decimal)) this.SmallDecimal = cls; else if (type == typeof(BigInteger)) this.BigInteger = cls; else if (type == typeof(BigDecimal)) this.BigDecimal = cls; // Add the type to the map ... this.TypeClassMap[type] = cls; }
protected override bool InternalAddMethod(IInstallerContext installer, SmalltalkClass cls) { Symbol selector = installer.Runtime.GetSymbol(this.Selector.Value); cls.ClassBehavior[selector] = new CompiledMethod(selector, this.IntermediateCode); return true; }
protected override CompiledMethod GetMethod(SmalltalkClass cls) { CompiledMethod result; cls.ClassBehavior.TryGetValue(this.Selector.Value, out result); return result; }
/// <summary> /// Create a new ByteIndexable SmalltalkObject for a given SmalltalkClass. /// </summary> /// <param name="cls">The SmalltalkClass that this object will be instance of.</param> /// <param name="objectSize">Number of unnamed instance variables.</param> public ByteIndexableSmalltalkObject(SmalltalkClass cls, int objectSize) : base(cls) { if (cls.InstanceState != SmalltalkClass.InstanceStateEnum.ByteIndexable) throw new ArgumentOutOfRangeException("Expected a ByteIndexable class"); if (objectSize < 0) throw new ArgumentOutOfRangeException("objectSize"); this.Contents = new byte[objectSize]; }
public ClassFunctionScope(SmalltalkClass cls, ClassScope outerScope) : base(cls, outerScope) { }
protected override RootCompilationContext GetCompilationContext(MethodNode parseTree, SmalltalkClass cls, Expression self, Expression executionContext, Expression[] arguments) { SmalltalkNameScope globalNameScope = this.CompilerOptions.GlobalNameScope ?? this.Runtime.GlobalScope; BindingScope globalScope = BindingScope.ForClassMethod(cls, globalNameScope); BindingScope reservedScope = ReservedScope.ForClassMethod(); return(new RootCompilationContext(this, globalScope, reservedScope, self, executionContext, arguments, cls.Name, parseTree.Selector)); }
protected abstract bool InternalAddMethod(IDefinitionInstallerContext installer, SmalltalkClass cls);
private InitializerCompilationResult CompileClassInitializer(SmalltalkRuntime runtime, SmalltalkClass cls, SmalltalkNameScope globalNameScope) { return this.Compile(runtime, BindingScope.ForClassInitializer(cls, globalNameScope), ReservedScope.ForClassInitializer()); }
protected abstract bool InternalValidateMethod(IDefinitionInstallerContext installer, SmalltalkClass cls, ICodeValidationErrorSink errorSink);
public override bool ValidateClassInitializer(SmalltalkNameScope globalNameScope, SmalltalkClass cls, IIntermediateCodeValidationErrorSink errorSink) { return this.Validate(globalNameScope, errorSink, rt => this.CompileClassInitializer(rt, cls, globalNameScope)); }
private Expression <Func <object, ExecutionContext, object> > CompileClassInitializer(SmalltalkRuntime runtime, SmalltalkNameScope globalNameScope, SmalltalkClass cls) { return(this.Compile(runtime, BindingScope.ForClassInitializer(cls, globalNameScope), ReservedScope.ForClassInitializer(), String.Format("{0} initializer", this.Binding.Name.Value))); }
public static BindingScope ForClassInitializer(SmalltalkClass cls) { return BindingScope.ForClassInitializer(cls, cls.Runtime.GlobalScope); }
void IInstallerContext.RegisterNewClass(SmalltalkClass cls) { if (cls == null) throw new ArgumentNullException(); this._newClasses.Add(cls); }
public static BindingScope ForInstanceMethod(SmalltalkClass cls) { return BindingScope.ForInstanceMethod(cls, cls.Runtime.GlobalScope); }
protected override bool InternalAddMethod(IDefinitionInstallerContext installer, SmalltalkClass cls) { CompiledMethod method = this.Factory.CreateMethod(this, installer, cls, CompiledMethod.MethodType.Instance); if (method == null) { return(false); } System.Diagnostics.Debug.Assert(this.Selector.Value == method.Selector.Value); cls.InstanceBehavior[method.Selector] = method; this.CompiledCode = method; return(true); }
/// <summary> /// Look-up a method implementation starting with the given class. /// </summary> /// <param name="cls">Class where to start searching for the method (unless superLookupScope) is set.</param> /// <param name="superLookupScope">If set, start the lookup from the superclass of this class.</param> /// <param name="lookupFunction">Function to perform the method lookup.</param> /// <returns>Returns the compiled method for the given selector or null if none was found.</returns> public static CompiledMethod LookupMethod(ref SmalltalkClass cls, ref Symbol superLookupScope, Func<SmalltalkClass, CompiledMethod> lookupFunction) { if (lookupFunction == null) throw new ArgumentNullException("lookupFunction"); while (cls != null) { if (superLookupScope == null) { CompiledMethod method = lookupFunction(cls); if (method != null) return method; } else { if (cls.Name == superLookupScope) superLookupScope = null; } cls = cls.Superclass; } // No method ... no luck; return null; }
protected override bool InternalValidateMethod(IDefinitionInstallerContext installer, SmalltalkClass cls, ICodeValidationErrorSink errorSink) { return(this.Factory.ValidateMethod(this, installer, cls, CompiledMethod.MethodType.Instance, errorSink)); }
/// <summary> /// This method is the core of the dynamic method lookup system. /// It determines the class of an object and looks-up the method implementation /// for a given method selector. /// </summary> /// <param name="runtime">Required.</param> /// <param name="selector">Required.</param> /// <param name="superLookupScope">Optional.</param> /// <param name="receiver">Optional.</param> /// <param name="self">Required.</param> /// <param name="arguments">Required (currently not used).</param> /// <param name="receiverClass">Must Return!</param> /// <param name="restrictions">Must Return!</param> /// <param name="executableCode">Return null if missing.</param> public static void GetMethodInformation(SmalltalkRuntime runtime, Symbol selector, Symbol superLookupScope, object receiver, DynamicMetaObject self, DynamicMetaObject[] arguments, out SmalltalkClass receiverClass, out BindingRestrictions restrictions, out Expression executableCode) { restrictions = null; SmalltalkClass cls = null; // Special case for Smalltalk classes, because we want the class behavior first ... if (receiver is SmalltalkClass) { cls = (SmalltalkClass)receiver; if (cls.Runtime == runtime) { receiverClass = runtime.NativeTypeClassMap.Class; if (receiverClass == null) receiverClass = runtime.NativeTypeClassMap.Object; // Lookup method in class behavior CompiledMethod mth = MethodLookupHelper.LookupClassMethod(selector, ref cls, ref superLookupScope); if (mth != null) { // A class method, special restrictions restrictions = BindingRestrictions.GetInstanceRestriction(self.Expression, receiver); var compilationResult = mth.Code.CompileClassMethod(runtime, cls, self, arguments, superLookupScope); if (compilationResult == null) { executableCode = null; } else { executableCode = compilationResult.ExecutableCode; restrictions = compilationResult.MergeRestrictions(restrictions); } return; } // Not in class behavior ... fallback to instance / Object behavior cls = receiverClass; restrictions = BindingRestrictions.GetTypeRestriction(self.Expression, typeof(SmalltalkClass)); } } if ((cls == null) || (restrictions == null)) cls = GetClassAndRestrictions(runtime, receiver, self, arguments, out restrictions); receiverClass = cls; // Look-up the method CompiledMethod method = MethodLookupHelper.LookupInstanceMethod(selector, ref cls, ref superLookupScope); if (method == null) { executableCode = null; } else { var compilationResult = method.Code.CompileInstanceMethod(runtime, cls, self, arguments, superLookupScope); if (compilationResult == null) { executableCode = null; } else { executableCode = compilationResult.ExecutableCode; restrictions = compilationResult.MergeRestrictions(restrictions); } } }
public ClassScope(SmalltalkClass cls, PoolVariableScope outerScope) : base(cls, outerScope) { }
public bool ValidateClassInitializer(GlobalInitializer definition, SmalltalkClass cls, IDefinitionInstallerContext installer, ICodeValidationErrorSink errorSink) { return(((RuntimeGlobalInitializer)this.CreateInitializer(definition, installer)).Validate(installer.NameScope, this.GetErrorSink(errorSink))); }
public InstanceFunctionScope(SmalltalkClass cls, ClassScope outerScope) : base(cls, outerScope) { }
/// <summary> /// This method is the core of the dynamic method lookup system. /// It determines the class of an object and looks-up the method implementation /// for a given method selector. /// </summary> /// <param name="runtime">Required.</param> /// <param name="selector">Required.</param> /// <param name="superLookupScope">Optional.</param> /// <param name="receiver">Optional.</param> /// <param name="self">Required.</param> /// <param name="executionContext">Required.</param> /// <param name="arguments">Required.</param> /// <param name="receiverClass">Must Return!</param> /// <param name="methodClass">Return null if missing.</param> /// <param name="restrictions">Must Return!</param> /// <param name="executableCode">Return null if missing.</param> public static void GetMethodInformation(SmalltalkRuntime runtime, Symbol selector, Symbol superLookupScope, object receiver, Expression self, Expression executionContext, IEnumerable <Expression> arguments, out SmalltalkClass receiverClass, out SmalltalkClass methodClass, out BindingRestrictions restrictions, out Expression executableCode) { restrictions = null; SmalltalkClass cls = null; // Special case for Smalltalk classes, because we want the class behavior first ... if (receiver is SmalltalkClass) { cls = (SmalltalkClass)receiver; if (cls.Runtime == runtime) { // The class of a SmalltalkClass object is a special class known by the runtime. receiverClass = runtime.NativeTypeClassMap.Class; if (receiverClass == null) { // And in case it's not set (not normal), we default to object receiverClass = runtime.NativeTypeClassMap.Object; } // Lookup method in class behavior CompiledMethod mth = MethodLookupHelper.LookupClassMethod(selector, ref cls, superLookupScope); if (mth != null) { // A class method, special restrictions methodClass = cls; restrictions = BindingRestrictions.GetInstanceRestriction(self, receiver); executableCode = mth.GetExpression(self, executionContext, arguments); if (executableCode != null) { return; } } // Not in class behavior ... fallback to instance / Object behavior cls = receiverClass; superLookupScope = null; // IMPROVE: May need to add Runtime Restrictions too. restrictions = BindingRestrictions.GetTypeRestriction(self, typeof(SmalltalkClass)); } } if ((cls == null) || (restrictions == null)) // Will not run for receivers of type SmalltalkClass { cls = MethodLookupHelper.GetClassAndRestrictions(runtime, receiver, self, arguments, out restrictions); } receiverClass = cls; // Look-up the method CompiledMethod method = MethodLookupHelper.LookupInstanceMethod(selector, ref cls, superLookupScope); methodClass = cls; if (method == null) { executableCode = null; } else { executableCode = method.GetExpression(self, executionContext, arguments); } }