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")); } } }
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)); }
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); } }
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); }
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)); }