Exemple #1
0
        public static FileVariable Create(IScriptFile file, AccessModifier access, string @namespace, string name, TypeReference type, bool readOnly,
                                          int line, int column, int codeHash,
                                          VariableContainerAction resetter,
                                          VariableContainerAction creator,
                                          VariableContainerAction initializer)
        {
            var vcOwnerAccess = VariableContainer.Create(@namespace, name, type, readOnly);

            vcOwnerAccess.FileLine   = line;
            vcOwnerAccess.FileColumn = column;
            vcOwnerAccess.CodeHash   = codeHash;
            vcOwnerAccess.Tag        = new Dictionary <Type, Object>();
            if (resetter != null)
            {
                vcOwnerAccess.DataResetter = resetter;
            }
            if (creator != null)
            {
                vcOwnerAccess.DataCreator = creator;
            }
            if (initializer != null)
            {
                vcOwnerAccess.DataInitializer = initializer;
            }
            return(new FileVariable(file, access, line, null, @namespace, name, vcOwnerAccess, vcOwnerAccess.Container.UniqueID));
        }
Exemple #2
0
        internal int CreateOrGetFileVariable(
            string @namespace,
            AccessModifier access,
            string name,
            TypeReference datatype,
            bool @readonly,
            int line,
            int column,
            int codeHash,
            VariableContainerAction resetter    = null,
            VariableContainerAction creator     = null,
            VariableContainerAction initializer = null,
            PropertyBlock customSetupData       = null)
        {
            var existing = m_fileScopeVariablesBefore.FirstOrDefault(
                v => (String.Equals(v.VariableOwnerAccess.Container.Name, name, StringComparison.InvariantCulture) &&
                      v.VariableOwnerAccess.Container.DataType.Type == datatype.Type));

            if (existing != null)
            {
                existing.VariableOwnerAccess.InitNeeded = (existing.VariableOwnerAccess.CodeHash != codeHash);
                m_fileScopeVariables.Add(existing);
                m_fileScopeVariablesBefore.RemoveAt(m_fileScopeVariablesBefore.IndexOf(existing));
                if (resetter != null)
                {
                    existing.VariableOwnerAccess.DataResetter = resetter;
                }
                if (creator != null)
                {
                    existing.VariableOwnerAccess.DataCreator = creator;
                }
                if (initializer != null)
                {
                    existing.VariableOwnerAccess.DataInitializer = initializer;
                }
                existing.VariableOwnerAccess.CodeHash = codeHash;
                if (customSetupData != null)
                {
                    SetFileVariableCustomData(existing, customSetupData);
                }
                return(existing.ID);
            }

            var vc = FileVariable.Create(this, access, @namespace, name, datatype, @readonly, line, column, codeHash, resetter, creator, initializer);

            if (customSetupData != null)
            {
                SetFileVariableCustomData(vc, customSetupData);
            }
            m_fileScopeVariables.Add(vc);
            this.ObjectContainerListChanged?.Invoke(this, EventArgs.Empty);
            return(vc.ID);
        }
Exemple #3
0
        internal VariableContainerAction CreateVariableContainerObjectInitAction(
            Type objectType, PropertyBlock properties, ErrorCollector errors, IToken startToken)
        {
            VariableContainerAction action = null;

            var resolver = new DefaultContractResolver();
            var contract = resolver.ResolveContract(objectType) as JsonObjectContract;

            var dataSetters     = new List <Expression>();
            var objectReference = Expression.Variable(objectType);

            foreach (var entry in properties)
            {
                if (entry.BlockEntryType == PropertyBlockEntryType.Value)
                {
                    var valueEntry = entry as PropertyBlockValue;
                    if (String.IsNullOrEmpty(valueEntry.SpecifiedTypeName))
                    {
                        var objectProperty = contract.Properties.FirstOrDefault(p => String.Equals(entry.Name, p.PropertyName, StringComparison.InvariantCulture));
                        if (objectProperty != null)
                        {
                            entry.Tag = "Property";
                            bool dataError = false;
                            System.Diagnostics.Debug.WriteLine($"Property type: {objectProperty.PropertyType.Name}");
                            Expression valueExpression = null;
                            object     value           = valueEntry.Value;
                            if (value != null)
                            {
                                if (objectProperty.PropertyType.IsEnum)
                                {
                                    if (value is Identifier)
                                    {
                                        value = ((Identifier)value).Name;
                                    }
                                    if (value is string)
                                    {
                                        if (((string)value).StartsWith(objectProperty.PropertyType.Name + ".", StringComparison.InvariantCulture))
                                        {
                                            value = ((string)value).Substring(objectProperty.PropertyType.Name.Length + 1);
                                        }
                                        try
                                        {
                                            value = Enum.Parse(objectProperty.PropertyType, (string)value);
                                        }
                                        catch
                                        {
                                            dataError = true;
                                            errors.SymanticError(startToken.Line, startToken.Column, false, $"Unknown value for property \"{entry.Name}\".");
                                        }
                                    }
                                    else if (value is long)
                                    {
                                    }
                                    else
                                    {
                                        dataError = true;
                                        errors.SymanticError(startToken.Line, startToken.Column, false, $"Unsupported value for property \"{entry.Name}\".");
                                    }
                                }
                                else if (objectProperty.PropertyType == typeof(string))
                                {
                                    if (value is Identifier)
                                    {
                                        value = ((Identifier)value).Name;
                                    }
                                }
                                else if (!objectProperty.PropertyType.IsPrimitive && objectProperty.PropertyType != typeof(TimeSpan) && objectProperty.PropertyType != typeof(DateTime))
                                {
                                    if (value is Identifier)
                                    {
                                        value = ((Identifier)value).Name;
                                        var resolved = this.ResolveIdentifierForGetOperation(
                                            (string)value,
                                            false,
                                            new TypeReference(objectProperty.PropertyType));
                                        if (resolved != null)
                                        {
                                            if (objectProperty.PropertyType.IsAssignableFrom(resolved.DataType.Type))
                                            {
                                                valueExpression = resolved.ExpressionCode;
                                            }
                                            else
                                            {
                                                dataError = true;
                                                errors.SymanticError(startToken.Line, startToken.Column, false, $"Unresolved value for property \"{entry.Name}\": '{(string)value}'.");
                                            }
                                        }
                                        else
                                        {
                                            dataError = true;
                                            errors.SymanticError(startToken.Line, startToken.Column, false, $"Unresolved value for property \"{entry.Name}\": '{(string)value}'.");
                                        }
                                    }
                                    else
                                    {
                                        dataError = true;
                                        errors.SymanticError(startToken.Line, startToken.Column, false, $"Unsupported value type for property \"{entry.Name}\": '{(string)value.GetType().Name}'.");
                                    }
                                }
                            }
                            if (!dataError)
                            {
                                var vt = (valueExpression != null) ? valueExpression.Type : value?.GetType();
                                if (vt != null && !objectProperty.PropertyType.IsAssignableFrom(vt))
                                {
                                    errors.IncompatibleDataType(startToken.Line, startToken.Column, vt.Name, objectProperty.PropertyType.Name);
                                }
                                else
                                {
                                    if (valueExpression == null)
                                    {
                                        valueExpression = Expression.Constant(value, objectProperty.PropertyType);
                                    }
                                    dataSetters.Add(Expression.Assign(
                                                        Expression.Property(objectReference, objectProperty.UnderlyingName),
                                                        valueExpression));
                                }
                            }
                        }
                        else
                        {
                            errors.SymanticError(startToken.Line, startToken.Column, false, $"The object has no property named \"{entry.Name}\".");
                        }
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
                else
                {
                    // Not handled yet; just let it fall through.
                }
            }
            if (dataSetters.Count > 0)
            {
                try
                {
                    LabelTarget returnLabel           = Expression.Label(typeof(bool));
                    var         parameterContainer    = Expression.Parameter(typeof(IValueContainerOwnerAccess), "container");
                    var         parameterLogger       = Expression.Parameter(typeof(ILogger), "logger");
                    var         getContainerReference = Expression.Property(
                        parameterContainer,
                        typeof(IValueContainerOwnerAccess).GetProperty(nameof(IValueContainerOwnerAccess.Container)));
                    var getObjectReference = Expression.Call(
                        getContainerReference,
                        typeof(IValueContainer).GetMethod(nameof(IValueContainer.GetValue), new Type[] { typeof(ILogger) }),
                        parameterLogger);
                    var objectReferenceAssignment = Expression.Assign(
                        objectReference,
                        Expression.Convert(getObjectReference, objectType));
                    var expressions = new List <Expression>(dataSetters);
                    expressions.Insert(0, objectReferenceAssignment);

                    if (objectType.GetInterface(nameof(ISettableFromPropertyBlock)) != null)
                    {
                        var setterHelper = typeof(ExecutionHelperMethods).GetMethod(
                            nameof(ExecutionHelperMethods.SetupObjectWithPropertyBlock));

                        var propertyBlockSetter = Expression.Call(setterHelper, parameterLogger, parameterContainer);
                        expressions.Add(propertyBlockSetter);
                    }

                    expressions.Add(Expression.Label(returnLabel, Expression.Constant(true)));

                    var lambdaExpr = Expression.Lambda(
                        typeof(VariableContainerAction),
                        Expression.Block(new ParameterExpression[] { objectReference }, expressions),
                        parameterContainer,
                        parameterLogger);
                    var @delegate = lambdaExpr.Compile();
                    action = (VariableContainerAction)@delegate;
                }
                catch (Exception)
                {
                    throw;
                }
            }
            return(action);
        }
Exemple #4
0
        public override void ExitFileVariableWithPropertyBlock([NotNull] SBP.FileVariableWithPropertyBlockContext context)
        {
            TypeReference type = m_variableType;

            if (type == null)
            {
                return;
            }
            var props = m_lastElementPropertyBlock;
            VariableContainerAction createAction = null;
            VariableContainerAction initAction   = null;
            VariableContainerAction resetAction  = null;

            if (m_variableType.Type.IsValueType || m_variableType.Type == typeof(string))
            {
                var code = Expression.Constant(Activator.CreateInstance(type.Type), type.Type);
                createAction = CreateVariableContainerValueAssignAction(code);
                resetAction  = createAction;
            }
            else
            {
                #region Creator Action
                var ctor = type.Type.GetConstructor(new Type[] { });
                if (ctor != null)
                {
                    var code = Expression.New(ctor);
                    createAction = CreateVariableContainerValueAssignAction(code);
                }
                else
                {
                    var createMethods =
                        type.Type.GetMethods().Where(
                            m => String.Equals(m.Name, "Create", StringComparison.InvariantCulture) && m.IsStatic).ToArray();
                    throw new NotImplementedException();
                }
                #endregion
                #region Reset Action
                var resettable = type.Type.GetInterface(nameof(IResettable));
                if (resettable != null)
                {
                    LabelTarget returnLabel = Expression.Label(typeof(bool));

                    var parameterContainer = Expression.Parameter(typeof(IValueContainerOwnerAccess), "container");
                    var parameterLogger    = Expression.Parameter(typeof(ILogger), "logger");

                    var callSetValue = Expression.Call(
                        typeof(ExecutionHelperMethods).GetMethod(nameof(ExecutionHelperMethods.ResetFileVariable), new Type[] { typeof(IValueContainerOwnerAccess), typeof(ILogger) }),
                        parameterContainer,
                        parameterLogger);

                    var lambdaExpr = Expression.Lambda(
                        typeof(VariableContainerAction),
                        Expression.Block(
                            callSetValue,
                            Expression.Label(returnLabel, Expression.Constant(true))),
                        parameterContainer,
                        parameterLogger);

                    var @delegate = lambdaExpr.Compile();
                    resetAction = (VariableContainerAction)@delegate;
                }
                #endregion
            }

            PropertyBlock customProperties = null;
            if (props != null && props.Count > 0)
            {
                initAction = this.CreateVariableContainerObjectInitAction(type.Type, props, m_errors, context.Start);
                if (props.Count(e => e.Tag == null) > 0)
                {
                    customProperties = new PropertyBlock(context.Start.Line);
                    customProperties.AddRange(props.Where(e => e.Tag == null));
                }
            }

            var codeHash = context.GetText().GetHashCode();
            var id       = m_file.CreateOrGetFileVariable(
                m_currentNamespace, m_fileElementModifier, m_variableName, type, true,
                context.Start.Line, context.Start.Column, codeHash,
                resetter: resetAction,
                creator: createAction,
                initializer: initAction,
                customSetupData: customProperties);
            m_file.SetFileVariableModifier(id, m_fileElementModifier);

            m_variableName = null;
        }