Example #1
0
        public void ProcessVarDefinition(DMASTObjectVarDefinition varDefinition)
        {
            DMObject   oldObject = _currentObject;
            DMVariable variable;

            _currentObject = DMObjectTree.GetDMObject(varDefinition.ObjectPath);

            if (varDefinition.IsGlobal)
            {
                variable = _currentObject.CreateGlobalVariable(varDefinition.Type, varDefinition.Name, varDefinition.IsConst);
            }
            else
            {
                variable = new DMVariable(varDefinition.Type, varDefinition.Name, false, varDefinition.IsConst);
                _currentObject.Variables[variable.Name] = variable;
            }

            try {
                SetVariableValue(variable, varDefinition.Value, varDefinition.ValType);
            } catch (CompileErrorException e) {
                DMCompiler.Error(e.Error);
            }

            _currentObject = oldObject;
        }
Example #2
0
        public void ProcessVarOverride(DMASTObjectVarOverride varOverride)
        {
            DMObject oldObject = _currentObject;

            _currentObject = DMObjectTree.GetDMObject(varOverride.ObjectPath);

            try {
                if (varOverride.VarName == "parent_type")
                {
                    DMASTConstantPath parentType = varOverride.Value as DMASTConstantPath;

                    if (parentType == null)
                    {
                        throw new CompileErrorException(varOverride.Location, "Expected a constant path");
                    }
                    _currentObject.Parent = DMObjectTree.GetDMObject(parentType.Value.Path);
                }
                else
                {
                    DMVariable variable = new DMVariable(null, varOverride.VarName, false, false);

                    SetVariableValue(variable, varOverride.Value);
                    _currentObject.VariableOverrides[variable.Name] = variable;
                }
            } catch (CompileErrorException e) {
                DMCompiler.Error(e.Error);
            }

            _currentObject = oldObject;
        }
Example #3
0
        private void SetVariableValue(DMVariable variable, DMASTExpression value, DMValueType valType = DMValueType.Anything)
        {
            DMVisitorExpression._scopeMode = variable.IsGlobal ? "static" : "normal";
            DMExpression expression = DMExpression.Create(_currentObject, variable.IsGlobal ? DMObjectTree.GlobalInitProc : null, value, variable.Type);

            DMVisitorExpression._scopeMode = "normal";
            expression.ValType             = valType;

            if (expression.TryAsConstant(out var constant))
            {
                variable.Value = constant;
                return;
            }

            if (variable.IsConst)
            {
                throw new CompileErrorException(value.Location, "Value of const var must be a constant");
            }

            //Whether this should be initialized at runtime
            bool isValid = expression switch {
                //TODO: A better way of handling procs evaluated at compile time
                Expressions.ProcCall procCall => procCall.GetTargetProc(_currentObject).Proc?.Name switch {
                    "rgb" => true,
                    "generator" => true,
                    "matrix" => true,
                    "icon" => true,
                    "file" => true,
                    "sound" => true,
                    _ => variable.IsGlobal
                },
Example #4
0
        private static void SaveJson(List <DreamMapJson> maps, string interfaceFile, string outputFile)
        {
            DreamCompiledJson compiledDream = new DreamCompiledJson();

            compiledDream.Strings   = DMObjectTree.StringTable;
            compiledDream.Maps      = maps;
            compiledDream.Interface = interfaceFile;
            compiledDream.Types     = DMObjectTree.CreateJsonRepresentation();
            if (DMObjectTree.GlobalInitProc.Bytecode.Length > 0)
            {
                compiledDream.GlobalInitProc = DMObjectTree.GlobalInitProc.GetJsonRepresentation();
            }

            if (DMObjectTree.Globals.Count > 0)
            {
                GlobalListJson globalListJson = new GlobalListJson();
                globalListJson.GlobalCount = DMObjectTree.Globals.Count;

                // Approximate capacity (4/285 in tgstation, ~3%)
                globalListJson.Globals = new Dictionary <int, object>((int)(DMObjectTree.Globals.Count * 0.03));

                for (int i = 0; i < DMObjectTree.Globals.Count; i++)
                {
                    DMVariable global = DMObjectTree.Globals[i];
                    if (!global.TryAsJsonRepresentation(out var globalJson))
                    {
                        throw new Exception($"Failed to serialize global {global.Name}");
                    }

                    if (globalJson != null)
                    {
                        globalListJson.Globals.Add(i, globalJson);
                    }
                }
                compiledDream.Globals = globalListJson;
            }

            if (DMObjectTree.GlobalProcs.Count > 0)
            {
                compiledDream.GlobalProcs = new(DMObjectTree.GlobalProcs.Count);

                foreach (KeyValuePair <string, DMProc> globalProc in DMObjectTree.GlobalProcs)
                {
                    string name = globalProc.Key;
                    DMProc proc = globalProc.Value;

                    compiledDream.GlobalProcs[name] = proc.GetJsonRepresentation();
                }
            }

            string json = JsonSerializer.Serialize(compiledDream, new JsonSerializerOptions()
            {
                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
            });

            File.WriteAllText(outputFile, json);
            Console.WriteLine("Saved to " + outputFile);
        }
Example #5
0
        private static string SaveJson(List <DreamMapJson> maps, string interfaceFile, string outputFile)
        {
            DreamCompiledJson compiledDream = new DreamCompiledJson();

            compiledDream.Strings   = DMObjectTree.StringTable;
            compiledDream.Maps      = maps;
            compiledDream.Interface = interfaceFile;
            var jsonRep = DMObjectTree.CreateJsonRepresentation();

            compiledDream.Types = jsonRep.Item1;
            compiledDream.Procs = jsonRep.Item2;
            if (DMObjectTree.GlobalInitProc.Bytecode.Length > 0)
            {
                compiledDream.GlobalInitProc = DMObjectTree.GlobalInitProc.GetJsonRepresentation();
            }

            if (DMObjectTree.Globals.Count > 0)
            {
                GlobalListJson globalListJson = new GlobalListJson();
                globalListJson.GlobalCount = DMObjectTree.Globals.Count;

                // Approximate capacity (4/285 in tgstation, ~3%)
                globalListJson.Globals = new Dictionary <int, object>((int)(DMObjectTree.Globals.Count * 0.03));

                for (int i = 0; i < DMObjectTree.Globals.Count; i++)
                {
                    DMVariable global = DMObjectTree.Globals[i];
                    if (!global.TryAsJsonRepresentation(out var globalJson))
                    {
                        DMCompiler.Error(new CompilerError(global.Value.Location, $"Failed to serialize global {global.Name}"));
                    }

                    if (globalJson != null)
                    {
                        globalListJson.Globals.Add(i, globalJson);
                    }
                }
                compiledDream.Globals = globalListJson;
            }

            if (DMObjectTree.GlobalProcs.Count > 0)
            {
                compiledDream.GlobalProcs = DMObjectTree.GlobalProcs.Values.ToList();
            }

            string json = JsonSerializer.Serialize(compiledDream, new JsonSerializerOptions()
            {
                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
            });

            // Successful serialization
            if (ErrorCount == 0)
            {
                File.WriteAllText(outputFile, json);
                return("Saved to " + outputFile);
            }
            return(string.Empty);
        }
Example #6
0
        public override bool TryAsConstant(out Constant constant)
        {
            DMVariable global = DMObjectTree.Globals[Id];

            if (global.IsConst)
            {
                return(global.Value.TryAsConstant(out constant));
            }

            constant = null;
            return(false);
        }
Example #7
0
        private void SetVariableValue(DMVariable variable, DMASTExpression value, DMValueType valType = DMValueType.Anything)
        {
            DMVisitorExpression._scopeMode = variable.IsGlobal ? "static" : "normal";
            DMExpression expression = DMExpression.Create(_currentObject, variable.IsGlobal ? DMObjectTree.GlobalInitProc : null, value, variable.Type);

            DMVisitorExpression._scopeMode = "normal";
            expression.ValType             = valType;

            if (expression.TryAsConstant(out var constant))
            {
                variable.Value = constant;
                return;
            }

            if (variable.IsConst)
            {
                throw new CompileErrorException(value.Location, "Value of const var must be a constant");
            }

            switch (expression)
            {
            case Expressions.List:
            case Expressions.NewList:
            case Expressions.NewPath:

            //TODO: A better way of handling procs evaluated at compile time
            case Expressions.ProcCall procCall when procCall.GetTargetProc(_currentObject).Proc?.Name == "rgb":
                variable.Value = new Expressions.Null(Location.Unknown);

                EmitInitializationAssign(variable, expression);
                break;

            case Expressions.ProcCall procCall when procCall.GetTargetProc(_currentObject).Proc?.Name == "generator":
                variable.Value = new Expressions.Null(Location.Unknown);

                EmitInitializationAssign(variable, expression);
                break;

            case Expressions.StringFormat:
            case Expressions.ProcCall:
                if (!variable.IsGlobal)
                {
                    throw new CompileErrorException(value.Location, $"Invalid initial value for \"{variable.Name}\"");
                }

                variable.Value = new Expressions.Null(Location.Unknown);
                EmitInitializationAssign(variable, expression);
                break;

            default:
                throw new CompileErrorException(value.Location, $"Invalid initial value for \"{variable.Name}\"");
            }
        }
Example #8
0
        private void EmitInitializationAssign(DMVariable variable, DMExpression expression)
        {
            if (variable.IsGlobal)
            {
                int?globalId = _currentObject.GetGlobalVariableId(variable.Name);
                if (globalId == null)
                {
                    throw new Exception($"Invalid global {_currentObject.Path}.{variable.Name}");
                }

                DMObjectTree.AddGlobalInitAssign(_currentObject, globalId.Value, expression);
            }
            else
            {
                Expressions.Field      field  = new Expressions.Field(Location.Unknown, variable);
                Expressions.Assignment assign = new Expressions.Assignment(Location.Unknown, field, expression);

                _currentObject.InitializationProcExpressions.Add(assign);
            }
        }
Example #9
0
        public void ProcessVarOverride(DMASTObjectVarOverride varOverride)
        {
            DMObject oldObject = _currentObject;

            _currentObject = DMObjectTree.GetDMObject(varOverride.ObjectPath);

            try
            {
                switch (varOverride.VarName)
                {
                case "parent_type":
                {
                    DMASTConstantPath parentType = varOverride.Value as DMASTConstantPath;

                    if (parentType == null)
                    {
                        throw new CompileErrorException(varOverride.Location, "Expected a constant path");
                    }
                    _currentObject.Parent = DMObjectTree.GetDMObject(parentType.Value.Path);
                    break;
                }

                case "tag":
                    DMCompiler.Error(new CompilerError(varOverride.Location, "tag: may not be set at compile-time"));
                    break;

                default:
                {
                    DMVariable variable = new DMVariable(null, varOverride.VarName, false, false);

                    SetVariableValue(variable, varOverride.Value);
                    _currentObject.VariableOverrides[variable.Name] = variable;
                    break;
                }
                }
            } catch (CompileErrorException e) {
                DMCompiler.Error(e.Error);
            }

            _currentObject = oldObject;
        }
Example #10
0
 public Field(Location location, DMVariable variable)
     : base(location, variable.Type)
 {
     Variable = variable;
 }
Example #11
0
        public void ProcessProcDefinition(DMASTProcDefinition procDefinition)
        {
            string   procName = procDefinition.Name;
            DMObject dmObject = _currentObject;

            try {
                if (procDefinition.ObjectPath.HasValue)
                {
                    dmObject = DMObjectTree.GetDMObject(_currentObject.Path.Combine(procDefinition.ObjectPath.Value));
                }

                if (!procDefinition.IsOverride && dmObject.HasProc(procName))
                {
                    throw new CompileErrorException(procDefinition.Location, $"Type {dmObject.Path} already has a proc named \"{procName}\"");
                }

                DMProc proc;

                if (procDefinition.ObjectPath == null)
                {
                    if (DMObjectTree.TryGetGlobalProc(procDefinition.Name, out _))
                    {
                        throw new CompileErrorException(new CompilerError(procDefinition.Location, $"proc {procDefinition.Name} is already defined in global scope"));
                    }

                    proc = DMObjectTree.CreateDMProc(dmObject, procDefinition);
                    DMObjectTree.AddGlobalProc(proc.Name, proc.Id);
                }
                else
                {
                    proc = DMObjectTree.CreateDMProc(dmObject, procDefinition);
                    dmObject.AddProc(procName, proc);
                }

                if (procDefinition.Body != null)
                {
                    foreach (var stmt in GetStatements(procDefinition.Body))
                    {
                        // TODO multiple var definitions.
                        if (stmt is DMASTProcStatementVarDeclaration varDeclaration && varDeclaration.IsGlobal)
                        {
                            DMVariable variable = proc.CreateGlobalVariable(varDeclaration.Type, varDeclaration.Name, varDeclaration.IsConst);
                            variable.Value = new Expressions.Null(varDeclaration.Location);

                            if (varDeclaration.Value != null)
                            {
                                DMVisitorExpression._scopeMode = "static";
                                DMExpression expression = DMExpression.Create(dmObject, proc, varDeclaration.Value, varDeclaration.Type);
                                DMVisitorExpression._scopeMode = "normal";
                                DMObjectTree.AddGlobalInitAssign(dmObject, proc.GetGlobalVariableId(varDeclaration.Name).Value, expression);
                            }
                        }
                    }
                }

                if (procDefinition.IsVerb && (dmObject.IsSubtypeOf(DreamPath.Atom) || dmObject.IsSubtypeOf(DreamPath.Client)) && !DMCompiler.Settings.NoStandard)
                {
                    Expressions.Field  field    = new Expressions.Field(Location.Unknown, dmObject.GetVariable("verbs"));
                    DreamPath          procPath = new DreamPath(".proc/" + procName);
                    Expressions.Append append   = new Expressions.Append(Location.Unknown, field, new Expressions.Path(Location.Unknown, procPath));

                    dmObject.InitializationProcExpressions.Add(append);
                }
            } catch (CompileErrorException e) {
                DMCompiler.Error(e.Error);
            }
        }