示例#1
0
        public GamaFunctionCompiler(GamaNamespaceContext ctx, GamaFunctionRef fn)
        {
            NamespaceContext = ctx;
            Self             = fn;
            Frame            = new GamaStackFrame();
            Builder          = ctx.This.Context.Context.CreateBuilder();

            ExpressionCompiler = new GamaExpressionCompiler(this);

            // This compiler is responsible for compiling most of the function related code
            // This is why this unit needs to add a block always
            // All blocks contain a special character in them (such as '.') to avoid mixing user code and compiler generated code
            // Compiler always works with single block at a time and compiler is single threaded. So this code won't hurt compiler.
            SetBlock(fn.AddBlock("code"));
        }
示例#2
0
        public override GamaValueRef VisitExprOpLogic([NotNull] GamaParser.ExprOpLogicContext context)
        {
            var lhs = Visit(context.expr(0));
            var rhs = Visit(context.expr(1));
            var op  = context.opLogic().GetText();

            GamaFunctionList oplist;

            if (op == "&&")
            {
                oplist = lhs.Type.Meta.Operators.And;
            }
            else if (op == "||")
            {
                oplist = lhs.Type.Meta.Operators.Or;
            }
            else
            {
                oplist = lhs.Type.Meta.Operators.Xor;
            }

            var target = !IsEmptyTT ? TopTT : null;

            GamaFunctionRef fnref = null;

            if (target == null)
            {
                fnref = oplist.FindFunction(new[] { lhs.Type, rhs.Type });
            }
            else
            {
                fnref = oplist.FindFunction(target, new[] { lhs.Type, rhs.Type });
            }

            if (fnref == null)
            {
                GamaCompiledFunctionList coplist;
                if (op == "&&")
                {
                    coplist = lhs.Type.Meta.CompiledOperators.And;
                }
                else if (op == "||")
                {
                    coplist = lhs.Type.Meta.CompiledOperators.Or;
                }
                else
                {
                    coplist = lhs.Type.Meta.CompiledOperators.Xor;
                }

                GamaCompiledFunctionRef cfnref = null;
                if (target == null)
                {
                    cfnref = coplist.FindFunction(lhs.Type, rhs.Type);
                }
                else
                {
                    cfnref = coplist.FindFunction(target, new[] { lhs.Type, rhs.Type });
                }

                if (cfnref == null)
                {
                    Parent.NamespaceContext.Context.AddError(new ErrorNoViableOperator(context));
                    return(null);
                }
                var cbuilder = Parent.Builder;
                Parent.CurrentBlock.PositionBuilderAtEnd(cbuilder);
                return(cfnref.Call(cbuilder, lhs, rhs));
            }

            /* LLVM */
            var block   = Parent.CurrentBlock;
            var builder = Parent.Builder;

            block.PositionBuilderAtEnd(builder);
            var result = builder.BuildCall(fnref.Value, new LLVMValueRef[] { lhs.Value, rhs.Value });

            return(new GamaValueRef(fnref.ReturnType, result, false));
        }
示例#3
0
        public override GamaValueRef VisitExprOpComp([NotNull] GamaParser.ExprOpCompContext context)
        {
            var lhs = Visit(context.expr(0));
            var rhs = Visit(context.expr(1));
            var op  = context.opComp().GetText();

            GamaFunctionList oplist;

            if (op == ">")
            {
                oplist = lhs.Type.Meta.Operators.Gt;
            }
            else if (op == "<")
            {
                oplist = lhs.Type.Meta.Operators.Lt;
            }
            else if (op == ">=")
            {
                oplist = lhs.Type.Meta.Operators.Ge;
            }
            else if (op == "<=")
            {
                oplist = lhs.Type.Meta.Operators.Le;
            }
            else if (op == "==")
            {
                oplist = lhs.Type.Meta.Operators.Eq;
            }
            else
            {
                oplist = lhs.Type.Meta.Operators.Neq;
            }

            GamaFunctionRef fnref = oplist.FindFunction(InstanceTypes.Bool, new[] { lhs.Type, rhs.Type });

            if (fnref == null)
            {
                GamaCompiledFunctionList coplist;
                if (op == ">")
                {
                    coplist = lhs.Type.Meta.CompiledOperators.Gt;
                }
                else if (op == "<")
                {
                    coplist = lhs.Type.Meta.CompiledOperators.Lt;
                }
                else if (op == ">=")
                {
                    coplist = lhs.Type.Meta.CompiledOperators.Ge;
                }
                else if (op == "<=")
                {
                    coplist = lhs.Type.Meta.CompiledOperators.Le;
                }
                else if (op == "==")
                {
                    coplist = lhs.Type.Meta.CompiledOperators.Eq;
                }
                else
                {
                    coplist = lhs.Type.Meta.CompiledOperators.Neq;
                }

                GamaCompiledFunctionRef cfnref = coplist.FindFunction(InstanceTypes.Bool, new[] { lhs.Type, rhs.Type });

                if (cfnref == null)
                {
                    Parent.NamespaceContext.Context.AddError(new ErrorNoViableOperator(context));
                    return(null);
                }
                var cbuilder = Parent.Builder;
                Parent.CurrentBlock.PositionBuilderAtEnd(cbuilder);
                return(cfnref.Call(cbuilder, lhs, rhs));
            }

            /* LLVM */
            var block   = Parent.CurrentBlock;
            var builder = Parent.Builder;

            block.PositionBuilderAtEnd(builder);
            var result = builder.BuildCall(fnref.Value, new LLVMValueRef[] { lhs.Value, rhs.Value });

            return(new GamaValueRef(fnref.ReturnType, result, false));
        }
示例#4
0
        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);
        }
示例#5
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);
            }
        }
示例#6
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);
        }