Пример #1
0
        public Expression Store(Variable v, Expression value)
        {
            Field field;

            if (VariableFields.TryGetValue(v, out field))
            {
                return(new StoreField(Source.Unknown, Expression, field, value));
            }

            if (Parent == null)
            {
                throw new InvalidOperationException("ClosureConversionTransform: No matching closure field for local " + v);
            }

            return(Parent.Store(v, value));
        }
Пример #2
0
        Closure CreateClosure(Closure parent, HashSet <Variable> locals)
        {
            if (parent != null && locals.Count == 0)
            {
                return(parent);
            }

            var type = new ClassType(
                Source.Unknown,
                Function.DeclaringType,
                Function.Name + " lambda closure",
                Modifiers.Private | Modifiers.Generated,
                Function.DeclaringType.GetUniqueIdentifier(Function.Name + "_$closure"));

            type.SetBase(Essentials.Object);

            var constrBody = new Scope(
                Source.Unknown,
                new CallConstructor(Source.Unknown, Essentials.Object.TryGetConstructor()));

            type.Constructors.Add(
                new Constructor(
                    Source.Unknown,
                    type,
                    "",
                    Modifiers.Public | Modifiers.Generated,
                    ParameterList.Empty,
                    constrBody));

            Function.DeclaringType.NestedTypes.Add(type);
            _generatedTypes.Add(type);

            var decl = new VariableDeclaration(
                Source.Unknown,
                Function,
                Function.DeclaringType.GetUniqueIdentifier("generated_closure"),
                type,
                optionalValue: ILFactory.NewObject(type));

            var statements = new List <Statement>();

            statements.Add(decl);

            var result = new Closure(type, statements, new LoadLocal(Source.Unknown, decl.Variable), parent);

            // The root closure gets 'this' and the params
            if (parent == null)
            {
                if (_closureVars.This)
                {
                    var field = new Field(
                        Source.Unknown,
                        type,
                        type.GetUniqueIdentifier("self"),
                        "",
                        Modifiers.Public | Modifiers.Generated,
                        0,
                        Function.DeclaringType);

                    type.Fields.Add(field);

                    statements.Add(result.StoreThis(new This(Function.DeclaringType)));
                }

                foreach (var p in _closureVars.Params)
                {
                    var field = new Field(
                        p.Source,
                        type,
                        type.GetUniqueIdentifier(p.Name),
                        "",
                        Modifiers.Public | Modifiers.Generated,
                        0,
                        p.Type);

                    type.Fields.Add(field);
                    result.ParameterFields[p] = field;
                    statements.Add(result.Store(p, new LoadArgument(Source.Unknown, Function, ParamIndex(p))));
                }
            }
            // Non-root closures get a parent field for the parent closure
            else
            {
                type.Fields.Add(
                    new Field(
                        Source.Unknown,
                        type,
                        type.GetUniqueIdentifier("parent"),
                        "",
                        Modifiers.Public | Modifiers.Generated,
                        0,
                        parent.Type));
                statements.Add(result.StoreParent(parent.Expression));
            }

            foreach (var v in locals)
            {
                var field = new Field(
                    v.Source,
                    type,
                    type.GetUniqueIdentifier(v.Name),
                    "",
                    Modifiers.Public | Modifiers.Generated,
                    0,
                    v.ValueType);

                type.Fields.Add(field);
                result.VariableFields[v] = field;
            }

            return(result);
        }