Esempio n. 1
0
        public static Lambda CompileFunction(FunctionDefinition function)
        {
            List <Variable> specialMappedTypes = GetSpecialMappedVariables();

            IEnumerable <NameExpression> freeVars = function
                                                    .Walk()
                                                    .ToList()
                                                    .MatchWith(specialMappedTypes);

            if (freeVars.Count() > 0)
            {
                // TODO
                throw new NotImplementedException("Compiling functions with free variables");
            }
            // Binding is needed for the function to know what sort of a stack size
            // is needed by the body, but isn't needed for our purposes here
            function.Bind(new Binder());

            GlobalContext  context        = new GlobalContext();
            InternalLambda functionLambda = new InternalLambda
            {
                closures    = new Closure[0],
                description = function.CompileInner(),
                context     = context
            };

            // TODO: does the context need the function itself?
            return(functionLambda);
        }
        public int Execute(Frame frame)
        {
            InternalLambda[] lambdas = new InternalLambda[descriptions.Length];
            for (int i = 0; i < lambdas.Length; i++)
            {
                lambdas[i] = new InternalLambda
                {
                    closures = frame.closures,
                    context = frame.global,
                    description = descriptions[i]
                };
            }

            frame.result = RuntimeUtil.CanonicalizeLambdas(lambdas);
            return 1;
        }
Esempio n. 3
0
        internal static object Run(InternalLambda lambda, GlobalContext context, object[] args)
        {
            Stack <Frame> frames       = new Stack <Frame>();
            Frame         currentFrame = new Frame(context, lambda);

            frames.Push(currentFrame);

            // TODO: Are the args guaranteed to the be the
            // first variables on the stack?
            for (int i = 0; i < args.Length; i++)
            {
                currentFrame.stack[i] = args[i];
            }

            while (frames.Count > 0)
            {
                // This returns the result of an InternalCallInstruction
                frames.Peek().result = currentFrame.result;
                currentFrame = frames.Pop();
                // If returning from a function, we should continue from
                // where we last ran
                int i = currentFrame.returnAddress;
                while (!currentFrame.shouldExit)
                {
                    i += currentFrame.instructions[i].Execute(currentFrame);
                    if (currentFrame.shouldCall)
                    {
                        // Assume that the instruction correctly outputs a
                        // frame into the result; we will overwrite it on
                        // return
                        frames.Push(currentFrame);
                        currentFrame.returnAddress = i;
                        currentFrame.shouldCall    = false;
                        i            = 0;
                        currentFrame = currentFrame.result as Frame;
                    }
                }
            }

            return(lambda.ReturnType == RedwoodType.Void ? null : currentFrame.result);
        }
Esempio n. 4
0
        public static async Task <GlobalContext> CompileModule(
            TopLevel toplevel,
            IResourceProvider resources)
        {
            // We may have some
            Dictionary <string, TopLevel> modules = new Dictionary <string, TopLevel>();

            modules[toplevel.ModuleName] = toplevel;

            List <Variable> specialMappedTypeVariables = GetSpecialMappedVariables();

            // If it has a dotwalk, it must be an import prefix
            List <ImportDetails> imports = toplevel
                                           .Walk()
                                           .ToList()
                                           .MatchWith(specialMappedTypeVariables)
                                           .Select((NameExpression ne) => new ImportDetails(toplevel.ModuleName, ne))
                                           .ToList();

            for (int i = 0; i < imports.Count; i++)
            {
                // Allow people to compile modules standalone without a
                // compiler, but don't let them compile if there are
                // unresolved modules
                if (resources == null)
                {
                    throw new NotImplementedException();
                }

                // If we haven't already got the module, then we
                // will have to go parse it ourselves
                if (!modules.ContainsKey(imports[i].From))
                {
                    // TODO: Other ways of caching modules?
                    if (!resources.TryGetResource(imports[i].From, out Stream stream))
                    {
                        throw new NotImplementedException();
                    }

                    StreamReader sr = new StreamReader(stream);
                    TopLevel     tl = await new Parser(sr).ParseModule(imports[i].From);
                    imports.AddRange(
                        tl.Walk()
                        .ToList()
                        .MatchWith(specialMappedTypeVariables)
                        .Select((NameExpression ne) => new ImportDetails(imports[i].To, ne))
                        );
                    modules[imports[i].From] = tl;
                }

                Variable variable = modules[imports[i].From]
                                    .DeclaredVariables
                                    .FirstOrDefault(variable => variable.Name == imports[i].Name);

                if (variable == null)
                {
                    throw new NotImplementedException();
                }

                imports[i].Variable = variable;
            }

            // We need to bind twice in order to determine some of
            // the types, such as for a method in a class first,
            // then bind again for its usage
            foreach (TopLevel module in modules.Values)
            {
                module.Bind(new Binder());
            }
            if (toplevel.ModuleName == null)
            {
                toplevel.Bind(new Binder());
            }

            foreach (TopLevel module in modules.Values)
            {
                module.Bind(new Binder());
            }
            if (toplevel.ModuleName == null)
            {
                toplevel.Bind(new Binder());
            }

            Dictionary <string, GlobalContext> contexts =
                new Dictionary <string, GlobalContext>();

            foreach (TopLevel module in modules.Values)
            {
                contexts[module.ModuleName] = BuildContext(module);
            }

            // TODO: what if someone tries to import an import?
            foreach (ImportDetails import in imports)
            {
                contexts[import.To].AssignVariable(
                    import.NameExpression.Variable.Name,
                    contexts[import.From].LookupVariable(import.Name)
                    );
            }
            return(contexts[toplevel.ModuleName]);

            GlobalContext BuildContext(TopLevel toplevel)
            {
                GlobalContext  context = new GlobalContext();
                InternalLambda initializationLambda = new InternalLambda
                {
                    closures    = new Closure[0],
                    description = new InternalLambdaDescription
                    {
                        argTypes = new RedwoodType[0],
                        // All fields should go the global definition, but some
                        // temporary variables may be used to define constructors
                        stackSize    = toplevel.StackSize,
                        closureSize  = 0,
                        instructions = toplevel.Compile().ToArray(),
                        returnType   = null
                    },
                    context = context
                };

                // Populate the global context
                initializationLambda.Run();
                return(context);
            }
        }
Esempio n. 5
0
 internal static object Run(InternalLambda lambda)
 {
     return(Run(lambda, lambda.context));
 }
Esempio n. 6
0
 internal static object Run(InternalLambda lambda, GlobalContext context)
 {
     return(Run(lambda, context, new object[0]));
 }
Esempio n. 7
0
 internal static object Run(InternalLambda lambda, object[] args)
 {
     return(Run(lambda, lambda.context, args));
 }