/// <summary> /// Type check and gather top-level information about a method. This includes /// checking the return type, formal parameter types, and creating a scope for the /// method. /// </summary> /// <param name="n"></param> public override void VisitDeclMethod(ASTDeclarationMethod n) { var methodScope = _scopeMgr.PushScope(string.Format("method {0}", n.Name)); var func = new TypeFunction(n.Name); var formalDescriptors = CollectFormals(n.Formals, func); var returnType = CheckSubTree(n.ReturnType); func.ReturnType = returnType; func.Scope = methodScope; var mods = GatherModifiers(n); _scopeMgr.PopScope(); var methodDesc = _scopeMgr.AddMethod(n.Name, func, _currentClass, mods); n.Descriptor = methodDesc; n.Type = func; foreach (var formal in formalDescriptors) { methodDesc.Formals.Add(formal); } }
private List <string> GatherModifiers(ASTDeclarationMethod n) { var names = new List <String>(); var mods = n.Modifiers; while (!mods.IsEmpty) { names.Add(mods.Modifier); mods = mods.Tail; } return(names); }
private MethodAttributes MethodAccessibility(ASTDeclarationMethod n) { //todo: this is a hack if (n.Name == CodeGenerator.MainMethodName) { return(MethodAttributes.Public | MethodAttributes.Static); } else { return(MethodAttributes.Public); } }
public void AddMethod(string typeName, ASTDeclarationMethod n) { TypeBuilderInfo info = TypeBuilderMap[typeName]; //we need to know the CIL type for the return type and arguments Type returnType = LookupCilType(n.ReturnType); TypeFunction function = n.Type as TypeFunction; MethodBuilder methodBuilder = info.Builder.DefineMethod(n.Name, MethodAccessibility(n), returnType, ArgumentTypes(function)); //store this MethodBuilder, keyed off its name info.MethodMap.Add(n.Name, new MethodBuilderInfo(methodBuilder, BuildFormalMap(n.Descriptor.Formals))); }
/// <summary> /// Restores the method's scope, and adds a new scope for local variables. /// Walks the body of the function and pops the two scopes. /// </summary> /// <param name="n"></param> public override void VisitDeclMethod(ASTDeclarationMethod n) { //if the method is tagged as readonly, this translates to all of its formals being readonly var func = _scopeMgr.Find(n.Name, p => p is MethodDescriptor) as MethodDescriptor; if (func.Modifiers.Contains("readonly", StringComparer.OrdinalIgnoreCase)) { foreach (var formal in func.Formals) { formal.Modifier = "readonly"; } } VisitMethodBody(string.Format("body {0}", n.Name), n.Body, n.Type as TypeFunction); if ((_currentMethod.ReturnType is TypeVoid == false) && (!_currentMethod.AllCodePathsReturn())) { ReportError(n.Location, "Not all code paths of method '{0}' return a value.", n.Name); } }
public override void VisitDeclMethod(ASTDeclarationMethod n) { n.Modifiers.Visit(this); MethodBuilderInfo methodInfo = _typeManager.GetMethodBuilderInfo(_currentTypeBuilder.Name, n.Name); //store a reference so we can access locals, arguments, and stuff about the current method we're working on. _currentMethodBuilder = methodInfo; _gen = methodInfo.Builder.GetILGenerator(); //is this the entry point if (n.Name == MainMethodName) { _assemblyBuilder.SetEntryPoint(methodInfo.Builder); } n.Body.Visit(this); //we need to explicitly put a return statement for voids if (_typeManager.LookupCilType(n.ReturnType) == typeof(void)) { _gen.Emit(OpCodes.Ret); } }
public override void VisitDeclMethod(ASTDeclarationMethod n) { _mgr.AddMethod(_currentType, n); }