예제 #1
0
        private void VisitFunction(FunctionNode func, ILFunction dstFunc, ModulePage inContext)
        {
            var genContext = new ILGeneratorContext()
            {
                Errors   = Errors,
                Context  = Context,
                Module   = inContext.Module,
                Page     = inContext,
                Function = dstFunc
            };

            foreach (var expr in func.Body.Children)
            {
                expr.Emit(genContext);
            }

            dstFunc.CommitBlocks();

            if (!dstFunc.IsTerminated)
            {
                // void type? just emit an implicit return at the end
                if (dstFunc.ReturnType is VoidTypeInfo)
                {
                    dstFunc.Current.EmitRet();
                }
                else
                {
                    Errors.Add(new CompileError(func.Source, "Not all codepaths return a value"));
                }
            }
        }
예제 #2
0
        private ILFunction CreateFunction(FunctionNode func, ModulePage inContext, ILModule dstModule)
        {
            List <VarInfo> args = new List <VarInfo>();

            foreach (var param in func.Parameters)
            {
                var t = Context.GetType(param.Type, inContext) ?? Context.GlobalTypes.GetType("void");

                args.Add(new VarInfo()
                {
                    Name = $"{param.Identifier}",
                    Type = t
                });
            }

            var    retType  = Context.GetType(func.Type, inContext) ?? Context.GlobalTypes.GetType("void");
            string funcName = $"{func.Identifier}";

            // *technically* we're also spitting out a const here that contains a reference to the function
            // kinda silly? but means we get to reuse const resolution for function names
            // and that also means templated functions will be able to take function refs just like any other const input
            inContext.Module.Constants.Add(funcName, new FuncRef()
            {
                InModule     = dstModule,
                FunctionName = funcName
            });
            return(dstModule.CreateFunction(funcName, args.ToArray(), retType));
        }
예제 #3
0
        public void AddPage(ModulePage page)
        {
            page.Module = this;
            Pages.Add(page);

            // store a list of declared consts
            // we don't actually initialize them yet, instead they're lazy initialized as we visit expressions that reference them
            foreach (var constNode in page.Consts)
            {
                declaredConsts.Add(constNode.Identifier.Source.Value.ToString(), constNode);
            }
        }
예제 #4
0
        private static ModulePage VisitModule(ModuleNode module, List <CompileError> outErrors)
        {
            ModulePage moduleInfo = new ModulePage(module.Identifier.Source.Value);

            foreach (var expr in module.Body.Children)
            {
                if (expr is StructNode structNode)
                {
                    moduleInfo.Structs.Add(structNode);
                }
                else if (expr is InterfaceNode interfaceNode)
                {
                    moduleInfo.Interfaces.Add(interfaceNode);
                }
                else if (expr is ImplementNode implementNode)
                {
                    moduleInfo.Implements.Add(implementNode);
                }
                else if (expr is FunctionNode functionNode)
                {
                    moduleInfo.Functions.Add(functionNode);
                }
                else if (expr is ConstDeclarationNode constNode)
                {
                    moduleInfo.Consts.Add(constNode);
                }
                else if (expr is VarDeclarationNode varNode)
                {
                    moduleInfo.Globals.Add(varNode);
                }
                else
                {
                    outErrors.Add(new CompileError(expr.Source, "Expression not valid here!"));
                }
            }

            return(moduleInfo);
        }
예제 #5
0
        private ILFunction CreateMemberFunction(ImplementNode implementBlock, FunctionNode func, ModulePage inContext, ILModule dstModule)
        {
            List <VarInfo> args = new List <VarInfo>();

            TypeInfo implementType;

            if (Context.TryGetType(inContext.Module.Name, $"{implementBlock.StructID}", out implementType))
            {
                args.Add(new VarInfo()
                {
                    Name = "this",
                    Type = new PointerTypeInfo(implementType)
                });
            }
            else if (Context.GlobalTypes.TryGetType($"{implementBlock.StructID}", out implementType))
            {
                args.Add(new VarInfo()
                {
                    Name = "this",
                    Type = new PointerTypeInfo(implementType)
                });
            }
            else
            {
                Errors.Add(new CompileError(implementBlock.StructID.Source, "Could not resolve type name"));
            }

            foreach (var param in func.Parameters)
            {
                var t = Context.GetType(param.Type, inContext) ?? Context.GlobalTypes.GetType("void");

                args.Add(new VarInfo()
                {
                    Name = $"{param.Identifier}",
                    Type = t
                });
            }

            // it seems a little silly, but we give the function a name that isn't actually a valid identifier
            // this makes the auto-generated function impossible to call outside of the intended context

            var    retType  = Context.GetType(func.Type, inContext) ?? Context.GlobalTypes.GetType("void");
            string funcName = $"::{inContext.Module.Name}.{implementBlock.StructID}.{func.Identifier}";

            inContext.Module.Constants.Add(funcName, new FuncRef()
            {
                InModule     = dstModule,
                FunctionName = funcName
            });
            return(dstModule.CreateFunction(funcName, args.ToArray(), retType));
        }