예제 #1
0
        public override bool VisitTopLevelStructDef([NotNull] GamaParser.TopLevelStructDefContext context)
        {
            var symtype = context.symbolTypePairList();

            if (symtype == null)
            {
                GlobalContext.AddError(new ErrorEmptyStruct(context));
                return(false);
            }
            var structname = context.Symbol().GetText();

            if (NamespaceContext.FindTypeRef(structname) != null)
            {
                GlobalContext.AddError(new ErrorDuplicateType(context));
                return(false);
            }

            var pairs  = symtype.symbolTypePair();
            var fields = new Dictionary <string, GamaFieldRef>(pairs.Length);
            var types  = new LLVMTypeRef[pairs.Length];
            var packed = context.Packed() != null;

            for (int i = 0; i < pairs.Length; i++)
            {
                var p    = pairs[i];
                var name = p.Symbol().GetText();
                if (fields.ContainsKey(name))
                {
                    GlobalContext.AddError(new ErrorDuplicateField(p));
                    return(false);
                }
                var ty = NamespaceContext.FindTypeRefGlobal(p.typeName());
                if (ty == null)
                {
                    GlobalContext.AddError(new ErrorTypeNotFound(p.typeName()));
                    return(false);
                }
                fields[name] = new GamaFieldRef(name, i, ty);
                types[i]     = ty.UnderlyingType;
            }

            LLVMTypeRef nativety;

            unsafe {
                nativety = LLVM.StructCreateNamed(GlobalContext.Context, structname.GetSbytePtr());
                nativety.StructSetBody(types, packed);
            }
            var structty = new GamaTypeRef(structname, nativety);

            structty.Meta.Fields.AddRange(fields.Values);
            NamespaceContext.This.Types.Add(structty);

            return(true);
        }
예제 #2
0
        public override bool VisitTopLevelImpl([NotNull] GamaParser.TopLevelImplContext context)
        {
            var ty = NamespaceContext.FindTypeRefGlobal(context.fqtn());

            if (ty == null)
            {
                GlobalContext.AddError(new ErrorTypeNotFound(context.fqtn()));
                return(false);
            }
            new GamaStructCompiler(this, ty).Visit(context);
            return(true);
        }
예제 #3
0
        public override bool VisitTopLevelDelegate([NotNull] GamaParser.TopLevelDelegateContext context)
        {
            var name = context.Symbol().GetText();

            if (NamespaceContext.FindTypeRef(name) != null)
            {
                GlobalContext.AddError(new ErrorDuplicateType(context));
                return(false);
            }

            var retty = InstanceTypes.Void;

            var rettyfqtn = context.fqtn();

            if (rettyfqtn != null)
            {
                retty = NamespaceContext.FindTypeRefGlobal(rettyfqtn);
                if (retty == null)
                {
                    GlobalContext.AddError(new ErrorTypeNotFound(context.fqtn()));
                    return(false);
                }
            }

            var parms       = new GamaTypeRef[0];
            var parmsnative = new LLVMTypeRef[0];
            var parmsctx    = context.fqtnList();

            if (parmsctx != null)
            {
                var fqtns = parmsctx.fqtn();
                parms       = new GamaTypeRef[fqtns.Length];
                parmsnative = new LLVMTypeRef[fqtns.Length];
                for (int i = 0; i < fqtns.Length; i++)
                {
                    var ty = NamespaceContext.FindTypeRefGlobal(fqtns[i]);
                    if (ty == null)
                    {
                        GlobalContext.AddError(new ErrorTypeNotFound(fqtns[i]));
                        return(false);
                    }
                    parms[i]       = ty;
                    parmsnative[i] = ty.UnderlyingType;
                }
            }
            NamespaceContext.This.Types.Add(new GamaFunction(name, retty, parms, LLVMTypeRef.CreateFunction(retty.UnderlyingType, parmsnative)));
            return(true);
        }
예제 #4
0
        public override bool VisitStmtVarDefNull([NotNull] GamaParser.StmtVarDefNullContext context)
        {
            var name = context.Symbol().GetText();
            var val  = Top.FindValue(name);

            if (val != null)
            {
                NamespaceContext.Context.AddError(new ErrorDuplicateVariable(context));
                return(false);
            }
            var ty = NamespaceContext.FindTypeRefGlobal(context.typeName());

            if (ty == null)
            {
                NamespaceContext.Context.AddError(new ErrorTypeNotFound(context.typeName()));
                return(false);
            }
            if (ty == InstanceTypes.Void)
            {
                NamespaceContext.Context.AddError(new ErrorVariableVoid(context.typeName()));
                return(false);
            }

            /* LLVM */
            CurrentBlock.PositionBuilderAtEnd(Builder);
            if (ty is GamaFunction) // Functionals are not allocated directly, instead a pointer is allocateds
            {
                var ptr   = new GamaPointer(ty);
                var alloc = Builder.BuildAlloca(ptr.UnderlyingType, name);
                Builder.BuildStore(LLVMValueRef.CreateConstPointerNull(ptr.UnderlyingType), alloc);

                Top.AddValue(name, new GamaValueRef(ty, alloc, true));
            }
            else
            {
                var alloc = Builder.BuildAlloca(ty.UnderlyingType, name);
                // TODO: maybe add an option to not null initialize these variable definitions
                // Possible speed boost
                Builder.BuildStore(LLVMValueRef.CreateConstNull(ty.UnderlyingType), alloc);

                Top.AddValue(name, new GamaValueRef(ty, alloc, true));
            }

            return(true);
        }
예제 #5
0
        public override bool VisitStmtVarDefFull([NotNull] GamaParser.StmtVarDefFullContext context)
        {
            var name = context.Symbol().GetText();
            var val  = Top.FindValue(name);

            if (val != null)
            {
                NamespaceContext.Context.AddError(new ErrorDuplicateVariable(context));
                return(false);
            }
            var ty = NamespaceContext.FindTypeRefGlobal(context.typeName());

            if (ty == null)
            {
                NamespaceContext.Context.AddError(new ErrorTypeNotFound(context.typeName()));
                return(false);
            }
            if (ty == InstanceTypes.Void)
            {
                NamespaceContext.Context.AddError(new ErrorVariableVoid(context.typeName()));
                return(false);
            }
            val = VisitExpression(ty, context.expr());
            if (val == null)
            {
                return(false);
            }
            // If expression compiler returns a function then it's impossible for a type mismatch to happen
            // Expression compiler checks for type mismatches when evaluating function pointers
            // Alsp no need to check if 'ty' is a GamaFunction either, expressiom compiler already did that
            if (val.Type is GamaFunction valtyfn)
            {
                var tyfn = new GamaPointer(ty as GamaFunction);
                /* LLVM */
                CurrentBlock.PositionBuilderAtEnd(Builder);
                var alloc = Builder.BuildAlloca(tyfn.UnderlyingType, name);
                Builder.BuildStore(val.Value, alloc);

                Top.AddValue(name, new GamaValueRef(ty, alloc, true));
                return(true);
            }

            // If not function, there might be a mismatch. Check it and error if it mismatches
            if (val.Type != ty)
            {
                NamespaceContext.Context.AddError(new ErrorTypeMismatch(context.expr()));
                return(false);
            }

            /* LLVM */
            // One block above to avoid dumb C# error message saying 'alloc' is already defined (SOMEHOW)
            {
                CurrentBlock.PositionBuilderAtEnd(Builder);
                var alloc = Builder.BuildAlloca(ty.UnderlyingType, name);
                Builder.BuildStore(val.Value, alloc);

                Top.AddValue(name, new GamaValueRef(ty, alloc, true));
            }

            return(true);
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
        public override bool VisitTopLevelExternDef([NotNull] GamaParser.TopLevelExternDefContext context)
        {
            var name = context.Symbol().GetText();
            var list = NamespaceContext.FindFunctionRefGlobal(name);

            if (list == null)
            {
                list = new GamaFunctionList(name);
                NamespaceContext.This.Functions.Add(list);
            }

            var retty = InstanceTypes.Void;

            var rettyfqtn = context.typeName();

            if (rettyfqtn != null)
            {
                retty = NamespaceContext.FindTypeRefGlobal(rettyfqtn);
                if (retty == null)
                {
                    GlobalContext.AddError(new ErrorTypeNotFound(context.typeName()));
                    return(false);
                }
            }

            var ellipsis       = context.ellipsis() != null;
            var parmslist      = new GamaParamList();
            var argtypes       = new GamaTypeRef[0];
            var argtypesnative = new LLVMTypeRef[0];
            var fqtnlist       = context.typeList();

            if (fqtnlist != null)
            {
                var types = fqtnlist.typeName();
                argtypesnative = new LLVMTypeRef[types.Length];
                argtypes       = new GamaTypeRef[types.Length];
                for (int i = 0; i < types.Length; i++)
                {
                    var ty = NamespaceContext.FindTypeRefGlobal(types[i]);
                    if (ty == null)
                    {
                        GlobalContext.AddError(new ErrorTypeNotFound(types[i]));
                        return(false);
                    }
                    parmslist.Add(i.ToString(), ty); // Adding parameter with a numeric name, doesn't matter since this is a extern.
                    argtypes[i]       = ty;
                    argtypesnative[i] = ty.UnderlyingType;
                }
            }

            if (list.FindFunction(parmslist) != null)
            {
                GlobalContext.AddError(new ErrorDuplicateFunction(context));
                return(false);
            }

            var fnty  = new GamaFunction(retty, argtypes, LLVMTypeRef.CreateFunction(retty.UnderlyingType, argtypesnative, ellipsis), ellipsis);
            var modfn = GlobalContext.Module.AddFunction(name, fnty.UnderlyingType);

            var fnref = new GamaFunctionRef(retty, parmslist, fnty, modfn, false);

            list.AddFunction(fnref);

            return(true);
        }