public override bool VisitStructLevelMethod([NotNull] GamaParser.StructLevelMethodContext context) { var fndef = context.topLevelFuncDef(); var name = fndef.Symbol().GetText(); GamaFunctionList fnlist = null; if (name == "new") { fnlist = StructType.Meta.Constructors; } else { fnlist = StructType.Meta.GetMethod(name); } if (fnlist == null) { fnlist = new GamaFunctionList(name); StructType.Meta.Methods.Add(fnlist); } var retty = InstanceTypes.Void; var tyname = fndef.typeName(); if (tyname != null) { retty = Parent.NamespaceContext.FindTypeRefGlobal(tyname); if (retty == null) { Parent.GlobalContext.AddError(new ErrorTypeNotFound(tyname)); return(false); } } var stplist = fndef.symbolTypePairList(); var paramlist = new GamaParamList(); paramlist.Add("this", new GamaPointer(StructType)); // add self as a pointer since this is a method if (stplist != null) { var pairs = stplist.symbolTypePair(); foreach (var p in pairs) { var ty = Parent.NamespaceContext.FindTypeRefGlobal(p.typeName()); if (ty == null) { Parent.GlobalContext.AddError(new ErrorTypeNotFound(p.typeName())); return(false); } if (!paramlist.Add(p.Symbol().GetText(), ty)) { Parent.GlobalContext.AddError(new ErrorDuplicateParameter(p)); return(false); } } } if (fnlist.FindFunction(paramlist) != null) { Parent.GlobalContext.AddError(new ErrorDuplicateMethod(fndef)); return(false); } var modty = new GamaFunction(retty, paramlist.Parameters.Select(p => p.Type).ToArray(), LLVMTypeRef.CreateFunction(retty.UnderlyingType, paramlist.Parameters.Select(p => p.Type.UnderlyingType).ToArray())); var modfn = Parent.GlobalContext.Module.AddFunction($"{ StructType.Name }.{ name }", modty.UnderlyingType); var fn = new GamaFunctionRef(retty, paramlist, modty, modfn, true); /* Parameters are added to top frame of the target function, but they are not treated as conventional variables */ var unit = new GamaFunctionCompiler(Parent.NamespaceContext, fn); foreach (var p in paramlist.Parameters) { unit.Top.AddValue(p.Name, new GamaValueRef(p.Type, modfn.GetParam(p.Index), false)); } unit.Visit(fndef.block()); if (unit.Finish() == 0) { // TODO: handle type method attributes fnlist.AddFunction(fn); } else { ; } return(true); }
public override bool VisitTopLevelFuncDef([NotNull] GamaParser.TopLevelFuncDefContext context) { var name = context.Symbol().GetText(); var fnlist = NamespaceContext.FindFunctionRef(name); var attrs = context.funcAttr(); // New function if (fnlist == null) { fnlist = new GamaFunctionList(name); var stplist = context.symbolTypePairList(); var parms = new GamaParamList(); var parmTypes = new GamaTypeRef[0]; var parmTypesNative = new LLVMTypeRef[0]; if (stplist != null) { var list = stplist.symbolTypePair(); parmTypes = new GamaTypeRef[list.Length]; parmTypesNative = new LLVMTypeRef[list.Length]; for (int i = 0; i < list.Length; i++) { var stp = list[i]; var sym = stp.Symbol(); var type = NamespaceContext.FindTypeRefGlobal(stp.typeName()); if (type == null) { GlobalContext.AddError(new ErrorTypeNotFound(stp.typeName())); return(false); } /* Since functions are not first-class types, we need to wrap them around with a pointer */ if (type is GamaFunction) { type = new GamaPointer(type); } if (!parms.Add(sym.GetText(), type)) { GlobalContext.AddError(new ErrorDuplicateParameter(stp)); return(false); // TODO: fix error library. } parmTypesNative[i] = type.UnderlyingType; parmTypes[i] = type; } } /* Determine type */ var rettypefqtn = context.typeName(); var retty = InstanceTypes.Void; // If function has a non-void type if (rettypefqtn != null) { // Find it retty = NamespaceContext.FindTypeRefGlobal(rettypefqtn); if (retty == null) { GlobalContext.AddError(new ErrorTypeNotFound(rettypefqtn)); return(false); } } /* LLVM */ var modty = new GamaFunction(retty, parmTypes, LLVMTypeRef.CreateFunction(retty.UnderlyingType, parmTypesNative)); var modfn = NamespaceContext.This.Context.Module.AddFunction(name, modty.UnderlyingType); var fn = new GamaFunctionRef(retty, parms, modty, modfn, false); var unit = new GamaFunctionCompiler(NamespaceContext, fn); /* Parameters are added to top frame of the target function, but they are not treated as conventional variables */ foreach (var p in parms.Parameters) { unit.Top.AddValue(p.Name, new GamaValueRef(p.Type, modfn.GetParam(p.Index), false)); } unit.Visit(context.block()); if (unit.Finish() == 0) { // First add ident, if it fails you fail too. if (attrs != null) { var attributes = new GamaAttributeCompiler(this).Visit(attrs); if (attributes != null) { fn.Attributes = attributes; } else { return(false); } } fnlist.AddFunction(fn); NamespaceContext.This.Functions.Add(fnlist); } else { ; // ?gnihtemos oD :ODOT (TODO:) } return(true); } // An override function else { var stplist = context.symbolTypePairList(); var parms = new GamaParamList(); if (stplist != null) { var list = stplist.symbolTypePair(); for (int i = 0; i < list.Length; i++) { var stp = list[i]; var sym = stp.Symbol(); var type = NamespaceContext.FindTypeRefGlobal(stp.typeName()); if (type == null) { GlobalContext.AddError(new ErrorTypeNotFound(stp.typeName())); return(false); } if (type is GamaFunction) { if (!parms.Add(sym.GetText(), new GamaPointer(type))) { GlobalContext.AddError(new ErrorDuplicateParameter(stp)); return(false); // TODO: fix error library. } continue; } if (!parms.Add(sym.GetText(), type)) { GlobalContext.AddError(new ErrorDuplicateParameter(stp)); return(false); } } } // Duplicate function if two functions have same type of parameters if (fnlist.FindFunction(parms) != null) { GlobalContext.AddError(new ErrorDuplicateFunction(context)); return(false); } /* Determine type */ var rettypefqtn = context.typeName(); var retty = InstanceTypes.Void; // If function has a non-void type if (rettypefqtn != null) { // Find it retty = NamespaceContext.FindTypeRefGlobal(rettypefqtn); if (retty == null) { GlobalContext.AddError(new ErrorTypeNotFound(rettypefqtn)); return(false); } } var modty = new GamaFunction(retty, parms.Parameters.Select(p => p.Type).ToArray(), LLVMTypeRef.CreateFunction(retty.UnderlyingType, parms.Parameters.Select(p => p.Type.UnderlyingType).ToArray())); var modfn = GlobalContext.Module.AddFunction(name, modty.UnderlyingType); var fn = new GamaFunctionRef(retty, parms, modty, modfn, false); var unit = new GamaFunctionCompiler(NamespaceContext, fn); unit.Visit(context.block()); if (unit.Finish() == 0) { if (attrs != null) { var attributes = new GamaAttributeCompiler(this).Visit(attrs); if (attributes != null) { fn.Attributes = attributes; } else { return(false); } } fnlist.AddFunction(fn); } else { ; // TODO: } return(true); } }