示例#1
0
文件: Codegen.cs 项目: hww/VARP
        private int GenerateLambda(AstLambda ast)
        {
            // create empty lambda function.
            // there are no any arguments
            var lambda = new CodeGenerator(ast.ArgList.Length);

            // update list of arguments
            lambda.DefineArguments(ast.ArgList);

            /// R(A) := closure(KPROTO[Bx], R(A), ... , R(A + n))
            var temp = -1;

            // now generate the code, and get target register
            foreach (var v in ast.BodyExpression)
            {
                temp = lambda.Generate(v.AsAST());
                //if (tgt != temp)
                //    lambda.AddAB(OpCode.MOVE, temp, (byte)tgt);
            }
            lambda.GenerateReturn(temp);

            // now lets create template from dummy lambda
            var template = lambda.GetTemplate();

            // -----------------------------------------
            // now generate code for current function
            // -----------------------------------------
            temp = Push();
            var closureId = DefineLiteral(new Value(template));

            AddABX(OpCode.CLOSURE, temp, closureId);
            template.ResultIdx = temp;
            return(temp);
        }
示例#2
0
文件: let.cs 项目: hww/VARP
        // (let () ...)
        public static AST Expand(Syntax stx, Environment env)
        {
            var list = stx.AsLinkedList <Value>();
            var argc = GetArgsCount(list);

            AssertArgsMinimum("let", "arity mismatch", 2, argc, list, stx);

            var keyword   = list[0].AsSyntax();   // let arguments
            var arguments = list[1].AsSyntax();   // let arguments

            if (!arguments.IsExpression)
            {
                throw SchemeError.SyntaxError("let", "bad syntax (missing name or binding pairs)", stx);
            }

            var localEnv = ArgumentsParser.ParseLet(stx, arguments.AsLinkedList <Value>(), env);

            AST lambda = new AstLambda(stx, keyword, localEnv, AstBuilder.ExpandListElements(list, 2, localEnv));

            var result = new LinkedList <Value>();

            result.AddLast(lambda.ToValue());
            foreach (var v in localEnv)
            {
                if (v is ArgumentBinding)
                {
                    var arg = v as ArgumentBinding;
                    if (arg.ArgType == ArgumentBinding.Type.Required)
                    {
                        result.AddLast(new Value(arg.Initializer));
                    }
                }
            }
            return(new AstApplication(stx, result));
        }
示例#3
0
        void InstrumentFunction(AstLambda lambda)
        {
            if (lambda.Source == null)
            {
                InstrumentBlock(ref lambda.Body);
                return;
            }

            var idx  = _owner.LastIndex++;
            var call = new AstCall(new AstSymbolRef(_owner.FncNameStatement));

            call.Args.Add(new AstNumber(idx));
            lambda.Body.Insert(0) = new AstSimpleStatement(call);
            _owner.GetForFile(lambda.Source)
            .AddInfo(new InstrumentedInfo(InstrumentedInfoType.Function, idx, lambda.Start, lambda.End));
            var input = new StructList <AstNode>();

            input.TransferFrom(ref lambda.Body);
            lambda.Body.Reserve(input.Count * 2 - 1);
            lambda.Body.Add(input[0]);
            for (var i = 1; i < input.Count; i++)
            {
                var ii = input[i];
                if (ShouldStatementCover(ii))
                {
                    if (i != 1)
                    {
                        idx  = _owner.LastIndex++;
                        call = new AstCall(new AstSymbolRef(_owner.FncNameStatement));
                        call.Args.Add(new AstNumber(idx));
                        lambda.Body.Add(new AstSimpleStatement(call));
                    }

                    _owner.GetForFile(ii.Source !)
                    .AddInfo(new InstrumentedInfo(InstrumentedInfoType.Statement, idx, ii.Start, ii.End));
                }

                ii = Transform(ii);
                lambda.Body.Add(ii);
            }
        }
        private Expression CompileLambda(AstLambda l)
        {
            var ps = l.ParameterList.Parameters;

            // The parser currently doesn't parse default values so this shouldn't happen,
            // so this check is for if the parser is changed in the future
            if (ps.Any(p => p.OptionalValue != null))
            {
                Error(l.Source, ErrorCode.E0000, "Lambda parameters cannot have default values");
            }

            if (ps.Count > 0)
            {
                var hasType = ps[0].OptionalType != null;
                if (ps.Any(p => (p.OptionalType != null) != hasType))
                {
                    Error(l.Source, ErrorCode.E0748,
                          "Inconsistent lambda parameter usage; all parameter types must either be explicit or implicit");
                }
            }

            // We defer compiling the lambda until it is implicitly cast to a delegate type
            return(new UncompiledLambda(l.Source, l));
        }
示例#5
0
        // (define x ...)
        // (define (x) ...)
        public static AST Expand(Syntax stx, Environment env)
        {
            var list = stx.AsLinkedList <Value>();
            var argc = GetArgsCount(list);

            AssertArgsMinimum("define", "arity mismatch", 2, argc, list, stx);

            var def_stx = list[0].AsSyntax();        // define
            var var_stx = list[1].AsSyntax();        // ()

            if (var_stx.IsIdentifier)
            {
                AssertArgsMaximum("define", "arity mismatch", 2, argc, list, stx);
                var val_stx = list[2].AsSyntax();

                // ----------------------------------------------------------------
                // identifier aka: (define x ...)
                // ----------------------------------------------------------------
                var value   = AstBuilder.ExpandInternal(val_stx, env);
                var var_id  = var_stx.AsIdentifier();
                var binding = env.LookupAst(var_id);

                if (binding == null)
                {
                    // Global variable
                    return(new AstSet(stx, var_stx, value, -1, -1, -1));
                }
                else if (binding is UpBinding)
                {
                    // Up-value variable
                    var ubind = binding as UpBinding;
                    return(new AstSet(stx, var_stx, value, binding.VarIdx, ubind.UpEnvIdx, ubind.UpVarIdx));
                }
                else
                {
                    // Local variable
                    return(new AstSet(stx, var_stx, value, binding.VarIdx, 0, 0));
                }
            }
            else if (var_stx.IsExpression)
            {
                // ----------------------------------------------------------------
                // identifier aka: (define (x ...) ...) as result lambda expression
                // ----------------------------------------------------------------
                var args_list = var_stx.AsLinkedList <Value>();

                var newenv = ArgumentsParser.ParseLambda(stx, args_list, env);

                var lambda_body = AstBuilder.ExpandListElements(list, 2, newenv);
                var lambda      = new AstLambda(stx, def_stx, newenv, lambda_body);

                var identifier_stx = args_list[0].AsSyntax();
                var identifier     = identifier_stx.AsIdentifier();
                var binding        = env.LookupAst(identifier);

                if (binding == null)
                {
                    /// Global variable
                    return(new AstSet(stx, var_stx, lambda, -1, -1, -1));
                }
                else if (binding is UpBinding)
                {
                    /// Up-value variable
                    var ubind = binding as UpBinding;
                    return(new AstSet(stx, var_stx, lambda, binding.VarIdx, ubind.UpEnvIdx, ubind.UpVarIdx));
                }
                else
                {
                    /// Local variable
                    return(new AstSet(stx, var_stx, lambda, binding.VarIdx, 0, 0));
                }
            }
            else
            {
                throw SchemeError.ArgumentError("define", "symbol? or list?", var_stx);
            }
        }
示例#6
0
 public UncompiledLambda(Source src, AstLambda astLambda) : base(src)
 {
     AstLambda = astLambda;
 }
示例#7
0
    void InstrumentFunction(AstLambda lambda)
    {
        if (lambda is AstArrow arrow)
        {
            if (arrow.Body.Count == 1 && arrow.Body.Last.IsExpression())
            {
                var original = arrow.Body[0];
                arrow.Body[0] = new AstBlock(original)
                {
                    Body = new() { new AstReturn(original)
                                   {
                                       Value = original
                                   } }
                };
            }
        }
        if (lambda.Source == null)
        {
            InstrumentBlock(ref lambda.Body);
            return;
        }

        var idx  = _owner.LastIndex++;
        var call = new AstCall(new AstSymbolRef(_owner.FncNameStatement));

        call.Args.Add(new AstNumber(idx));
        lambda.Body.Insert(0) = new AstSimpleStatement(call);
        _owner.GetForFile(lambda.Source)
        .AddInfo(new InstrumentedInfo(InstrumentedInfoType.Function, idx, lambda.Start, lambda.End));
        var input = new StructList <AstNode>();

        input.TransferFrom(ref lambda.Body);
        lambda.Body.Reserve(input.Count * 2 - 1);
        lambda.Body.Add(input[0]);
        for (var i = 1; i < input.Count; i++)
        {
            var ii = input[i];
            if (ShouldStatementCover(ii))
            {
                if (i != 1)
                {
                    idx  = _owner.LastIndex++;
                    call = new AstCall(new AstSymbolRef(_owner.FncNameStatement));
                    call.Args.Add(new AstNumber(idx));
                    lambda.Body.Add(new AstSimpleStatement(call));
                }

                _owner.GetForFile(ii.Source !)
                .AddInfo(new InstrumentedInfo(InstrumentedInfoType.Statement, idx, ii.Start, ii.End));
            }

            ii = Transform(ii);
            lambda.Body.Add(ii);
        }
    }

    AstNode InstrumentExpression(AstNode node)
    {
        if (node is AstSequence)
        {
            return(node);
        }
        if (node.Source == null)
        {
            return(node);
        }
        var res  = new AstSequence(node);
        var idx  = _owner.LastIndex++;
        var call = new AstCall(new AstSymbolRef(_owner.FncNameStatement));

        call.Args.Add(new AstNumber(idx));
        res.Expressions.Add(call);
        res.Expressions.Add(node);
        _owner.GetForFile(node.Source)
        .AddInfo(new InstrumentedInfo(InstrumentedInfoType.Statement, idx, node.Start, node.End));
        return(res);
    }

    void InstrumentBlock(ref StructList <AstNode> block, bool seq = false)
    {
        var input = new StructList <AstNode>();

        input.TransferFrom(ref block);
        block.Reserve(input.Count * 2);
        for (var i = 0; i < input.Count; i++)
        {
            var ii = input[i];
            if (ShouldStatementCover(ii))
            {
                var idx  = _owner.LastIndex++;
                var call = new AstCall(new AstSymbolRef(_owner.FncNameStatement));
                call.Args.Add(new AstNumber(idx));
                if (seq)
                {
                    block.Add(call);
                }
                else
                {
                    block.Add(new AstSimpleStatement(call));
                }

                _owner.GetForFile(ii.Source !)
                .AddInfo(new InstrumentedInfo(InstrumentedInfoType.Statement, idx, ii.Start, ii.End));
            }

            ii = Transform(ii);
            block.Add(ii);
        }
    }
示例#8
0
 public void WriteLambda(AstLambda a)
 {
     Write(a.Source);
     WriteParameterList(a.ParameterList);
     Write(a.Body);
 }