internal override IEnumerable <NameExpression> Walk() { Type = RedwoodType.Make(this); base.Walk(); DeclaredVariable.KnownType = RedwoodType.GetForCSharpType(typeof(RedwoodType)); DeclaredVariable.DefinedConstant = true; DeclaredVariable.ConstantValue = Type; List <NameExpression> freeVars = new List <NameExpression>(); List <Variable> declaredVars = new List <Variable>(); // The set of variables which must be supplied when creating the interface List <Variable> varsSupplied = new List <Variable>(); This = new Variable { Name = "this", KnownType = null, // Dynamic since the reference isn't necessarily our own type }; declaredVars.Add(This); varsSupplied.Add(This); foreach (FunctionDefinition method in Methods) { // Make sure that the method is a stub if (method.Body != null) { throw new NotImplementedException(); } freeVars.AddRange(method.Walk()); // As in the ClassDefinition, these need to be closured variables method.DeclaredVariable.Closured = true; varsSupplied.Add(method.DeclaredVariable); } // For every raw function and the this variable, // we're going to need to take is as an argument // for building the interface. Each of these should // live on the stack as they are variables. ArgumentVariables = varsSupplied .Select(variable => new Variable { Name = variable.Name } ) .ToList(); SuppliedVariables = varsSupplied; Overloads = Compiler.GenerateOverloads(Methods.ToList()); declaredVars.AddRange(Overloads.Select(o => o.variable)); foreach (Variable variable in declaredVars) { variable.Closured = true; } Variables = declaredVars; // There is no need to match against the fields of the class as // all methods are stubs, and no code is closured against the // interface itself. return(freeVars); }
internal override IEnumerable <NameExpression> Walk() { Type = RedwoodType.Make(this); base.Walk(); DeclaredVariable.KnownType = RedwoodType.GetForCSharpType(typeof(RedwoodType)); DeclaredVariable.DefinedConstant = true; DeclaredVariable.ConstantValue = Type; List <NameExpression> freeVars = new List <NameExpression>(); List <Variable> declaredVars = new List <Variable>(); InterfaceImplicitConversionVars = new List <Variable>(); int maxConstructorArgs = 0; This = new Variable { Name = "this", KnownType = Type }; declaredVars.Add(This); if (ParameterFields != null) { maxConstructorArgs = ParameterFields.Length; foreach (ParameterDefinition param in ParameterFields) { freeVars.AddRange(param.Walk()); declaredVars.Add(param.DeclaredVariable); } } foreach (TypeSyntax interfaceType in Interfaces) { freeVars.AddRange(interfaceType.Walk()); // TODO: What if we inherit an implicit, or if we // a function that is meant to represent this, or // an implicit declared function? InterfaceImplicitConversionVars.Add( new Variable { Name = RuntimeUtil.GetNameOfConversionToType(interfaceType.TypeName.Name), Closured = true, DefinedConstant = true } ); } foreach (LetDefinition field in InstanceFields) { freeVars.AddRange(field.Walk()); declaredVars.Add(field.DeclaredVariable); } foreach (FunctionDefinition constructor in Constructors) { freeVars.AddRange(constructor.Walk()); maxConstructorArgs = Math.Max(maxConstructorArgs, constructor.Parameters.Length); } TempArgumentVariables = new List <Variable>(); for (int i = 0; i < maxConstructorArgs; i++) { TempArgumentVariables.Add(new Variable { Temporary = true }); } foreach (FunctionDefinition method in Methods) { freeVars.AddRange(method.Walk()); // Closure these variables even though they aren't in the // object's map so that they can be directly accessed method.DeclaredVariable.Closured = true; } Overloads = Compiler.GenerateOverloads(Methods.ToList()); declaredVars.AddRange(Overloads.Select(o => o.variable)); declaredVars.AddRange(InterfaceImplicitConversionVars); MemberVariables = declaredVars; // Make sure that all of our variables end up in the closure that // makes up our RedwoodObject foreach (Variable member in declaredVars) { member.Closured = true; } // Treat the class as a closure that can be populated and then // updated by all methods. Compiler.MatchVariables(freeVars, declaredVars); // When it comes to static methods, we don't want to match to // our own instance variables. foreach (FunctionDefinition method in StaticMethods) { freeVars.AddRange(method.Walk()); } StaticOverloads = Compiler.GenerateOverloads(StaticMethods.ToList()); return(freeVars); }