Beispiel #1
0
        /* Todo, perhaps: Add function which allows C# to add static functions later. Could help C#-Pebble communication.
         * public Variable AddStaticLiteralAfterFinalization(ExecContext context, string name, ITypeDef typeDef, object value) {
         *      Variable variable = new Variable(name, typeDef);
         *      staticVars.Add(variable);
         *      variable.value = value;
         *      return variable;
         * }
         */

        // Use to add an override of a member function.
        // Caller is responsible for checking that...
        //	1) we have a parent
        //	2) it has a function with this name.
        public void AddFunctionOverride(string name, ITypeDef typeDef, IExpr initializer = null)
        {
            var member = new ClassMember(name, typeDef, initializer, false);

            //var mr = GetMemberRef(name);
            member.index = _memberFuncs.Set(name, member);
        }
Beispiel #2
0
        // Returns true if it succeeds, false if there was a name conflict.
        public bool AddMember(string name, ITypeDef typeDef, IExpr initializer = null, bool isStatic = false, bool isFunctionVariable = false, bool isGetonly = false)
        {
            // Fail if a member with that name already exists.
            if (DoesFieldExist(name, SEARCH.EITHER))
            {
                return(false);
            }

            var member = new ClassMember(name, typeDef, initializer, isGetonly);

            // This logic is weird but works because the language currently
            // doesn't allow static member functions.
            if (isStatic)
            {
                member.index = _statics.Add(member.name, member);
                staticVars.Add(new Variable(member.name, typeDef, null));
            }
            else if (!isFunctionVariable && typeDef is TypeDef_Function)
            {
                member.index = _memberFuncs.Add(member.name, member);
            }
            else
            {
                member.index = _fields.Add(member.name, member);
            }

            return(true);
        }
Beispiel #3
0
        public string GetDebugString()
        {
            string result = "class " + name + ":\n";

            for (int ii = 0; ii < _statics.Count; ++ii)
            {
                ClassMember member = _statics.Get(ii);
                result += "  static ";
                if (member.typeDef is TypeDef_Function)
                {
                    result += ((TypeDef_Function)member.typeDef).GetDebugString(member.name);
                }
                else
                {
                    result += member.typeDef.ToString() + " " + member.name + " = " + (null == staticVars[ii].value ? "null" : staticVars[ii].value) + ";\n";
                }
            }
            for (int ii = 0; ii < _fields.Count; ++ii)
            {
                ClassMember member = _fields.Get(ii);
                result += "  " + member.typeDef.ToString() + " " + member.name + ";\n";
            }
            for (int ii = 0; ii < _memberFuncs.Count; ++ii)
            {
                ClassMember member = _memberFuncs.Get(ii);
                result += "  " + ((TypeDef_Function)member.typeDef).GetDebugString(member.name);
            }

            return(result);
        }
Beispiel #4
0
        // Call this after creating the class and adding members to it.
        public bool FinalizeClass(ExecContext context)
        {
            Pb.Assert(0 == context.control.flags);

            // Only initializing the members that this class has added is a cool idea, but
            // leaves us f****d when it comes to overrridden functions.
            // So, I'm being lazy here and initializing them all.
            for (int ii = 0; ii < _memberFuncs.Count; ++ii)
            {
                ClassMember member = _memberFuncs.Get(ii);

                if (null != member.initializer && (member.initializer is Expr_Literal || member.initializer is Expr_Value))
                {
                    // Make sure vftableVars has a slot for this function.
                    while (vftableVars.Count < ii + 1)
                    {
                        vftableVars.Add(null);
                    }

                    object initValue = member.initializer.Evaluate(context);
                    if (context.IsRuntimeErrorSet())
                    {
                        return(false);
                    }

                    // Create the variable for the function.
                    vftableVars[ii] = new Variable(member.name, member.typeDef, initValue);
                }
            }

            // Initialize the static members. Populates the staticVars list.
            for (int ii = 0; ii < _statics.Count; ++ii)
            {
                ClassMember member    = _statics.Get(ii);
                object      initValue = null;
                if (null != member.initializer)
                {
                    initValue = member.initializer.Evaluate(context);
                    if (context.IsRuntimeErrorSet())
                    {
                        context.engine.LogCompileError(ParseErrorType.StaticMemberEvaluationError, name + "::" + member.name + " - " + context.GetRuntimeErrorString());
                        return(false);
                    }
                }
                staticVars[ii] = new Variable(member.name, member.typeDef, initValue);
            }

            return(true);
        }
Beispiel #5
0
        // Only called by the context.
        public void Initialize()
        {
            if (null != _fields)
            {
                return;
            }

            // 1) fields.
            _fields = new MemberList();
            if (null != parent)
            {
                for (int ii = 0; ii < parent._fields.Count; ++ii)
                {
                    ClassMember member       = parent._fields.Get(ii);
                    bool        modified     = false;
                    ITypeDef    resolvedType = parent.IsGeneric() ? member.typeDef.ResolveTemplateTypes(typeDef.genericTypes, ref modified) : member.typeDef;
                    ClassMember newMember    = new ClassMember(member.name, resolvedType, member.initializer, member.isGetonly);
                    newMember.index = _fields.Add(member.name, newMember);
                }
            }

            // 2) Functions
            _memberFuncs = new MemberList();
            if (null != parent)
            {
                for (int ii = 0; ii < parent._memberFuncs.Count; ++ii)
                {
                    ClassMember member       = parent._memberFuncs.Get(ii);
                    bool        modified     = false;
                    ITypeDef    resolvedType = parent.IsGeneric() ? member.typeDef.ResolveTemplateTypes(typeDef.genericTypes, ref modified) : member.typeDef;
                    ClassMember newMember    = new ClassMember(member.name, resolvedType, member.initializer, member.isGetonly);
                    newMember.index = _memberFuncs.Add(member.name, newMember);
                }

                vftableVars = new List <Variable>(parent.vftableVars);
            }
            else
            {
                vftableVars = new List <Variable>();
            }

            // 3) Statics aren't copied.
            _statics   = new MemberList();
            staticVars = new List <Variable>();
        }
Beispiel #6
0
        // Create a new instance of the class.
        public ClassValue Allocate(ExecContext context)
        {
            ClassValue result = childAllocator();

            result.classDef  = this;
            result.debugName = name + " Inst";

            bool scopePushed = false;

            for (int ii = 0; ii < _fields.Count; ++ii)
            {
                ClassMember member = _fields.Get(ii);

                object value = null;
                if (null != member.initializer)
                {
                    if (!scopePushed)
                    {
                        scopePushed = true;
                        if (!context.stack.PushClassScope(result, context))
                        {
                            context.SetRuntimeError(RuntimeErrorType.StackOverflow, "ClassValue.Allocate - stack overflow.");
                            return(null);
                        }
                    }

                    value = member.initializer.Evaluate(context);
                }
                else if (!member.typeDef.IsReference())                         // don't instantiate class refs automatically
                {
                    value = member.typeDef.GetDefaultValue(context);
                }

                Variable newVar = new Variable(member.name, member.typeDef, value);
                result.fieldVars.Add(newVar);
            }

            if (null != constructor)
            {
                if (context.IsRuntimeErrorSet())
                {
                    return(null);
                }

                if (!scopePushed)
                {
                    scopePushed = true;
                    if (!context.stack.PushClassScope(result, context))
                    {
                        context.SetRuntimeError(RuntimeErrorType.StackOverflow, "ClassValue.Allocate - stack overflow.");
                        return(null);
                    }
                }

                constructor.Evaluate(context);
                if (context.IsRuntimeErrorSet())
                {
                    return(null);
                }
            }

            if (scopePushed)
            {
                context.stack.PopScope();
            }

            return(result);
        }
Beispiel #7
0
        // Compile-time lookup of MemberRef.
        public MemberRef GetMemberRef(ExecContext context, string name, SEARCH searchType, ref ITypeDef typeDef)
        {
            // If there is an error during compliation then we can have an uninitialized
            // class on the stack. This check prevents us from throwing an exception
            // when that happens.
            // Kind of a kludge but handling errors during compilation is pretty chaotic
            // and I don't know what I could do other than to just abort on the first error.
            if (null == _fields)
            {
                return(MemberRef.invalid);
            }

            if (SEARCH.NORMAL == searchType || SEARCH.EITHER == searchType)
            {
                if (_fields.Exists(name))
                {
                    var member = _fields.Get(name);
                    typeDef = member.typeDef;

                    // If this member is getonly and we are not in this class's context, the type becomes const.
                    if (null != context && member.isGetonly)
                    {
                        ClassDef current = context.stack.GetCurrentClassDef();
                        if (null == current || (current != this && !current.IsChildOf(this)))
                        {
                            typeDef = TypeFactory.GetConstVersion(typeDef);
                        }
                    }

                    return(new MemberRef(member.index));
                }

                if (_memberFuncs.Exists(name))
                {
                    var member = _memberFuncs.Get(name);
                    typeDef = member.typeDef;
                    return(new MemberRef(this, MemberType.FUNCTION, member.index));
                }
            }

            if (SEARCH.STATIC == searchType || SEARCH.EITHER == searchType)
            {
                ClassDef def = this;
                while (null != def)
                {
                    if (def._statics.Exists(name))
                    {
                        ClassMember member = def._statics.Get(name);
                        typeDef = member.typeDef;

                        // If this member is getonly and we are not in this class's context, the type becomes const.
                        if (null != context && member.isGetonly)
                        {
                            ClassDef current = context.stack.GetCurrentClassDef();
                            if (null == current || (current != this && !current.IsChildOf(this)))
                            {
                                typeDef = TypeFactory.GetConstVersion(typeDef);
                            }
                        }

                        return(new MemberRef(def, MemberType.STATIC, member.index));
                    }
                    def = def.parent;
                }
            }

            return(MemberRef.invalid);
        }