示例#1
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;
        }
示例#2
0
        public void ProcessStatementTryCatch(DMASTProcStatementTryCatch tryCatch)
        {
            string catchLabel = _proc.NewLabelName();
            string endLabel   = _proc.NewLabelName();

            _proc.StartScope();
            ProcessBlockInner(tryCatch.TryBody);
            _proc.EndScope();
            _proc.Jump(endLabel);

            if (tryCatch.CatchParameter != null)
            {
                //TODO set the value to what is thrown in try
                var param = tryCatch.CatchParameter as DMASTProcStatementVarDeclaration;
                if (!_proc.TryAddLocalVariable(param.Name, param.Type))
                {
                    DMCompiler.Error(new CompilerError(param.Location, $"Duplicate var {param.Name}"));
                }
            }

            //TODO make catching actually work
            _proc.AddLabel(catchLabel);
            if (tryCatch.CatchBody != null)
            {
                _proc.StartScope();
                ProcessBlockInner(tryCatch.CatchBody);
                _proc.EndScope();
            }
            _proc.AddLabel(endLabel);
        }
示例#3
0
        public override void EmitPushValue(DMObject dmObject, DMProc proc)
        {
            switch (_expr)
            {
            case Field field:
                field.EmitPushIsSaved(proc);
                return;

            case Dereference dereference:
                dereference.EmitPushIsSaved(dmObject, proc);
                return;

            case Local:
                proc.PushFloat(0);
                return;

            case ListIndex:
                proc.PushFloat(0);
                // Silent in BYOND
                DMCompiler.Warning(new CompilerWarning(_expr.Location, "calling issaved() on a list index is always false"));
                return;

            default:
                throw new CompileErrorException(Location, $"can't get saved value of {_expr}");
            }
        }
示例#4
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;
        }
示例#5
0
文件: Procs.cs 项目: ZeWaka/OpenDream
 public override (DMReference Reference, bool Conditional) EmitReference(DMObject dmObject, DMProc proc)
 {
     if (!proc.IsOverride)
     {
         DMCompiler.Warning(new CompilerWarning(Location, "Calling parents via ..() in a proc definition does nothing"));
     }
     return(DMReference.SuperProc, false);
 }
示例#6
0
 public override bool TryAsJsonRepresentation(out object json)
 {
     json = null;
     if (!DMCompiler.Settings.SuppressUnimplementedWarnings)
     {
         DMCompiler.Warning(new CompilerWarning(Location, "DMM overrides for newlist() are not implemented"));
     }
     return(true); //TODO
 }
示例#7
0
 public override void EmitPushInitial(DMObject dmObject, DMProc proc)
 {
     // This happens silently in BYOND
     // TODO Support "vars" actually pushing initial() correctly
     if (_expr is Dereference deref && deref.PropertyName != "vars")
     {
         DMCompiler.Warning(new CompilerWarning(Location, "calling initial() on a list index returns the current value"));
     }
     EmitPushValue(dmObject, proc);
 }
示例#8
0
 public void ProcessBlockInner(DMASTBlockInner blockInner)
 {
     foreach (DMASTStatement statement in blockInner.Statements)
     {
         try {
             ProcessStatement(statement);
         } catch (CompileErrorException e) {
             DMCompiler.Error(e.Error);
         }
     }
 }
示例#9
0
 public void ProcessBlockInner(DMASTProcBlockInner block)
 {
     foreach (DMASTProcStatement statement in block.Statements)
     {
         try {
             ProcessStatement(statement);
         } catch (CompileErrorException e) { //Retreat from the statement when there's an error
             DMCompiler.Error(e.Error);
         }
     }
 }
示例#10
0
        public void ProcessObjectDefinition(DMASTObjectDefinition objectDefinition)
        {
            DMObject oldObject = _currentObject;

            DMCompiler.VerbosePrint($"Generating {objectDefinition.Path}");
            _currentObject = DMObjectTree.GetDMObject(objectDefinition.Path);
            if (objectDefinition.InnerBlock != null)
            {
                ProcessBlockInner(objectDefinition.InnerBlock);
            }
            _currentObject = oldObject;
        }
示例#11
0
        public bool IsSaved()
        {
            // Silent in BYOND
            // TODO Support "vars" actually pushing issaved() correctly
            if (_expr is Dereference deref && deref.PropertyName != "vars")
            {
                DMCompiler.Warning(new CompilerWarning(_expr.Location, "calling issaved() on a list index is always false"));
                return(false);
            }

            return(true);
        }
示例#12
0
        public void ProcessStatementVarDeclaration(DMASTProcStatementVarDeclaration varDeclaration)
        {
            if (varDeclaration.IsGlobal)
            {
                return;
            }                                        //Currently handled by DMObjectBuilder

            DMExpression value;

            if (varDeclaration.Value != null)
            {
                try {
                    value = DMExpression.Create(_dmObject, _proc, varDeclaration.Value, varDeclaration.Type);
                } catch (CompileErrorException e) {
                    DMCompiler.Error(e.Error);
                    value = new Expressions.Null(varDeclaration.Location);
                }
            }
            else
            {
                value = new Expressions.Null(varDeclaration.Location);
            }

            bool successful;

            if (varDeclaration.IsConst)
            {
                if (!value.TryAsConstant(out var constValue))
                {
                    DMCompiler.Error(new CompilerError(varDeclaration.Location, "Const var must be set to a constant"));
                    return;
                }

                successful = _proc.TryAddLocalConstVariable(varDeclaration.Name, varDeclaration.Type, constValue);
            }
            else
            {
                successful = _proc.TryAddLocalVariable(varDeclaration.Name, varDeclaration.Type);
            }

            if (!successful)
            {
                DMCompiler.Error(new CompilerError(varDeclaration.Location, $"Duplicate var {varDeclaration.Name}"));
                return;
            }

            value.EmitPushValue(_dmObject, _proc);
            _proc.Assign(_proc.GetLocalVariableReference(varDeclaration.Name));
            _proc.Pop();
        }
示例#13
0
        public void VisitDereference(DMASTDereference dereference)
        {
            var expr = DMExpression.Create(_dmObject, _proc, dereference.Expression, _inferredPath);

            if (dereference.Type == DMASTDereference.DereferenceType.Direct && !Dereference.DirectConvertable(expr, dereference))
            {
                if (expr.Path == null)
                {
                    throw new CompileErrorException(dereference.Location, $"Invalid property \"{dereference.Property}\"");
                }

                DMObject dmObject = DMObjectTree.GetDMObject(expr.Path.Value, false);
                if (dmObject == null)
                {
                    throw new CompileErrorException(dereference.Location, $"Type {expr.Path.Value} does not exist");
                }

                var property = dmObject.GetVariable(dereference.Property);
                if (property != null)
                {
                    Result = new Expressions.Dereference(dereference.Location, property.Type, expr, dereference.Conditional, dereference.Property);
                }
                else
                {
                    var globalId = dmObject.GetGlobalVariableId(dereference.Property);
                    if (globalId != null)
                    {
                        property = DMObjectTree.Globals[globalId.Value];
                        Result   = new Expressions.GlobalField(dereference.Location, property.Type, globalId.Value);
                    }
                }

                if (property == null)
                {
                    throw new CompileErrorException(dereference.Location, $"Invalid property \"{dereference.Property}\" on type {dmObject.Path}");
                }

                if ((property.Value?.ValType & DMValueType.Unimplemented) == DMValueType.Unimplemented && !DMCompiler.Settings.SuppressUnimplementedWarnings)
                {
                    DMCompiler.Warning(new CompilerWarning(dereference.Location, $"{dmObject.Path}.{dereference.Property} is not implemented and will have unexpected behavior"));
                }
            }
            else
            {
                Result = new Expressions.Dereference(dereference.Location, null, expr, dereference.Conditional, dereference.Property);
            }
        }
示例#14
0
        public override void EmitPushValue(DMObject dmObject, DMProc proc)
        {
            bool weighted = false;

            foreach (PickValue pickValue in _values)
            {
                if (pickValue.Weight != null)
                {
                    weighted = true;
                    break;
                }
            }

            if (weighted)
            {
                if (_values.Length == 1)
                {
                    DMCompiler.Warning(new CompilerWarning(Location, "Weighted pick() with one argument"));
                }

                foreach (PickValue pickValue in _values)
                {
                    DMExpression weight = pickValue.Weight ?? DMExpression.Create(dmObject, proc, new DMASTConstantInteger(Location, 100)); //Default of 100

                    weight.EmitPushValue(dmObject, proc);
                    pickValue.Value.EmitPushValue(dmObject, proc);
                }

                proc.PickWeighted(_values.Length);
            }
            else
            {
                foreach (PickValue pickValue in _values)
                {
                    if (pickValue.Value is Arglist args)
                    {
                        args.EmitPushArglist(dmObject, proc);
                    }
                    else
                    {
                        pickValue.Value.EmitPushValue(dmObject, proc);
                    }
                }

                proc.PickUnweighted(_values.Length);
            }
        }
示例#15
0
        public void ProcessStatementForList(DMASTProcStatementForList statementForList)
        {
            DMExpression.Emit(_dmObject, _proc, statementForList.List);
            _proc.CreateListEnumerator();
            _proc.StartScope();
            {
                if (statementForList.Initializer != null)
                {
                    ProcessStatement(statementForList.Initializer);
                }

                string loopLabel = _proc.NewLabelName();
                _proc.LoopStart(loopLabel);
                {
                    DMExpression outputVariable = DMExpression.Create(_dmObject, _proc, statementForList.Variable);
                    (DMReference outputRef, _) = outputVariable.EmitReference(_dmObject, _proc);
                    _proc.Enumerate(outputRef);
                    _proc.BreakIfFalse();

                    DMASTProcStatementVarDeclaration varDeclaration = statementForList.Initializer as DMASTProcStatementVarDeclaration;
                    if (varDeclaration != null && varDeclaration.Type != null)
                    {
                        //This is terrible but temporary
                        //TODO: See https://github.com/wixoaGit/OpenDream/issues/50
                        var obj = DMObjectTree.GetDMObject(varDeclaration.Type.Value);
                        if (statementForList.List is DMASTIdentifier list && list.Identifier == "world" && !obj.IsSubtypeOf(DreamPath.Atom))
                        {
                            var warn = new CompilerWarning(statementForList.Location, "Cannot currently loop 'in world' for non-ATOM types");
                            DMCompiler.Warning(warn);
                        }
                        DMExpression.Emit(_dmObject, _proc, statementForList.Variable);
                        _proc.PushPath(varDeclaration.Type.Value);
                        _proc.IsType();

                        _proc.ContinueIfFalse();
                    }

                    ProcessBlockInner(statementForList.Body);

                    _proc.LoopContinue(loopLabel);
                    _proc.LoopJumpToStart(loopLabel);
                }
                _proc.LoopEnd();
            }
            _proc.EndScope();
            _proc.DestroyEnumerator();
        }
示例#16
0
 public void ProcessBlockInner(DMASTProcBlockInner block)
 {
     // TODO ProcessStatementSet() needs to be before any loops but this is nasty
     foreach (var stmt in block.Statements)
     {
         if (stmt is DMASTProcStatementSet set)
         {
             try
             {
                 ProcessStatementSet(set);
             }
             catch (CompileAbortException e)
             {
                 // The statement's location info isn't passed all the way down so change the error to make it more accurate
                 e.Error.Location = set.Location;
                 DMCompiler.Error(e.Error);
                 return;                       // Don't spam the error that will continue to exist
             }
             catch (CompileErrorException e) { //Retreat from the statement when there's an error
                 DMCompiler.Error(e.Error);
             }
         }
     }
     foreach (DMASTProcStatement statement in block.Statements)
     {
         try
         {
             // see above
             if (statement is DMASTProcStatementSet)
             {
                 continue;
             }
             ProcessStatement(statement);
         }
         catch (CompileAbortException e)
         {
             // The statement's location info isn't passed all the way down so change the error to make it more accurate
             e.Error.Location = statement.Location;
             DMCompiler.Error(e.Error);
             return;                       // Don't spam the error that will continue to exist
         }
         catch (CompileErrorException e) { //Retreat from the statement when there's an error
             DMCompiler.Error(e.Error);
         }
     }
 }
示例#17
0
        public void ProcessProcDefinition(DMASTProcDefinition procDefinition)
        {
            if (procDefinition.Body == null)
            {
                return;
            }

            foreach (DMASTDefinitionParameter parameter in procDefinition.Parameters)
            {
                string parameterName = parameter.Name;

                if (!_proc.TryAddLocalVariable(parameterName, parameter.ObjectType))
                {
                    DMCompiler.Error(new CompilerError(procDefinition.Location, $"Duplicate argument \"{parameterName}\" on {procDefinition.ObjectPath}/proc/{procDefinition.Name}()"));
                    continue;
                }

                if (parameter.Value != null)   //Parameter has a default value
                {
                    string      afterDefaultValueCheck = _proc.NewLabelName();
                    DMReference parameterRef           = _proc.GetLocalVariableReference(parameterName);

                    //Don't set parameter to default if not null
                    _proc.PushReferenceValue(parameterRef);
                    _proc.IsNull();
                    _proc.JumpIfFalse(afterDefaultValueCheck);

                    //Set default
                    try {
                        DMExpression.Emit(_dmObject, _proc, parameter.Value, parameter.ObjectType);
                    } catch (CompileErrorException e) {
                        DMCompiler.Error(e.Error);
                    }
                    _proc.Assign(parameterRef);
                    _proc.Pop();

                    _proc.AddLabel(afterDefaultValueCheck);
                }
            }

            ProcessBlockInner(procDefinition.Body);
            _proc.ResolveLabels();
        }
示例#18
0
 public void ProcessBlockInner(DMASTProcBlockInner block)
 {
     foreach (DMASTProcStatement statement in block.Statements)
     {
         try
         {
             ProcessStatement(statement);
         }
         catch (CompileAbortException e)
         {
             // The statement's location info isn't passed all the way down so change the error to make it more accurate
             e.Error.Location = statement.Location;
             DMCompiler.Error(e.Error);
             return;                       // Don't spam the error that will continue to exist
         }
         catch (CompileErrorException e) { //Retreat from the statement when there's an error
             DMCompiler.Error(e.Error);
         }
     }
 }
示例#19
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;
        }
示例#20
0
 public override void EmitPushInitial(DMObject dmObject, DMProc proc)
 {
     // This happens silently in BYOND
     DMCompiler.Warning(new CompilerWarning(Location, "calling initial() on a local variable returns the current value"));
     EmitPushValue(dmObject, proc);
 }
示例#21
0
 public override bool TryAsJsonRepresentation(out object json)
 {
     json = null;
     DMCompiler.UnimplementedWarning(Location, "DMM overrides for newlist() are not implemented");
     return(true); //TODO
 }
示例#22
0
        public void ProcessStatementSet(DMASTProcStatementSet statementSet)
        {
            var attribute = statementSet.Attribute.ToLower();

            // TODO deal with "src"
            if (!DMExpression.TryConstant(_dmObject, _proc, statementSet.Value, out var constant) && attribute != "src")
            {
                throw new CompileErrorException(statementSet.Location, $"{attribute} attribute should be a constant");
            }

            switch (statementSet.Attribute.ToLower())
            {
            case "waitfor": {
                _proc.WaitFor(constant.IsTruthy());
                break;
            }

            case "opendream_unimplemented": {
                if (constant.IsTruthy())
                {
                    _proc.Attributes |= ProcAttributes.Unimplemented;
                }
                else
                {
                    _proc.Attributes &= ~ProcAttributes.Unimplemented;
                }
                break;
            }

            case "hidden":
                if (constant.IsTruthy())
                {
                    _proc.Attributes |= ProcAttributes.Hidden;
                }
                else
                {
                    _proc.Attributes &= ~ProcAttributes.Hidden;
                }
                break;

            case "popup_menu":
                if (constant.IsTruthy())     // The default is to show it so we flag it if it's hidden
                {
                    _proc.Attributes &= ~ProcAttributes.HidePopupMenu;
                }
                else
                {
                    _proc.Attributes |= ProcAttributes.HidePopupMenu;
                }

                DMCompiler.UnimplementedWarning(statementSet.Location, "set popup_menu is not implemented");
                break;

            case "instant":
                if (constant.IsTruthy())
                {
                    _proc.Attributes |= ProcAttributes.Instant;
                }
                else
                {
                    _proc.Attributes &= ~ProcAttributes.Instant;
                }

                DMCompiler.UnimplementedWarning(statementSet.Location, "set instant is not implemented");
                break;

            case "background":
                if (constant.IsTruthy())
                {
                    _proc.Attributes |= ProcAttributes.Background;
                }
                else
                {
                    _proc.Attributes &= ~ProcAttributes.Background;
                }
                break;

            case "name":
                if (constant is not Expressions.String nameStr)
                {
                    throw new CompileErrorException(statementSet.Location, "name attribute must be a string");
                }

                _proc.VerbName = nameStr.Value;
                break;

            case "category":
                _proc.VerbCategory = constant switch {
                    Expressions.String str => str.Value,
                                       Expressions.Null => null,
                                       _ => throw new CompileErrorException(statementSet.Location, "category attribute must be a string or null")
                };

                break;

            case "desc":
                if (constant is not Expressions.String descStr)
                {
                    throw new CompileErrorException(statementSet.Location, "desc attribute must be a string");
                }

                _proc.VerbDesc = descStr.Value;
                DMCompiler.UnimplementedWarning(statementSet.Location, "set desc is not implemented");
                break;

            case "invisibility":
                // The ref says 0-101 for atoms and 0-100 for verbs
                // BYOND doesn't clamp the actual var value but it does seem to treat out-of-range values as their extreme
                if (constant is not Expressions.Number invisNum)
                {
                    throw new CompileErrorException(statementSet.Location, "invisibility attribute must be an int");
                }

                _proc.Invisibility = Convert.ToSByte(Math.Clamp(Math.Floor(invisNum.Value), 0, 100));
                DMCompiler.UnimplementedWarning(statementSet.Location, "set invisibility is not implemented");
                break;

            case "src":
                DMCompiler.UnimplementedWarning(statementSet.Location, "set src is not implemented");
                break;
            }
        }
示例#23
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);
            }
        }
示例#24
0
        public void ProcessStatementSet(DMASTProcStatementSet statementSet)
        {
            var attribute = statementSet.Attribute.ToLower();

            if (!DMExpression.TryConstant(_dmObject, _proc, statementSet.Value, out var constant))
            {
                throw new CompileErrorException(statementSet.Location, $"{attribute} attribute should be a constant");
            }

            switch (statementSet.Attribute.ToLower())
            {
            case "waitfor": {
                _proc.WaitFor(constant.IsTruthy());
                break;
            }

            case "opendream_unimplemented": {
                if (constant.IsTruthy())
                {
                    _proc.Attributes |= ProcAttributes.Unimplemented;
                }
                else
                {
                    _proc.Attributes &= ~ProcAttributes.Unimplemented;
                }
                break;
            }

            case "hidden":
                if (constant.IsTruthy())
                {
                    _proc.Attributes |= ProcAttributes.Hidden;
                }
                else
                {
                    _proc.Attributes &= ~ProcAttributes.Hidden;
                }

                if (!DMCompiler.Settings.SuppressUnimplementedWarnings)
                {
                    DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set hidden is not implemented"));
                }

                break;

            case "popup_menu":
                if (constant.IsTruthy())     // The default is to show it so we flag it if it's hidden
                {
                    _proc.Attributes &= ~ProcAttributes.HidePopupMenu;
                }
                else
                {
                    _proc.Attributes |= ProcAttributes.HidePopupMenu;
                }

                if (!DMCompiler.Settings.SuppressUnimplementedWarnings)
                {
                    DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set popup_menu is not implemented"));
                }

                break;

            case "instant":
                if (constant.IsTruthy())
                {
                    _proc.Attributes |= ProcAttributes.Instant;
                }
                else
                {
                    _proc.Attributes &= ~ProcAttributes.Instant;
                }

                if (!DMCompiler.Settings.SuppressUnimplementedWarnings)
                {
                    DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set instant is not implemented"));
                }
                break;

            case "background":
                if (constant.IsTruthy())
                {
                    _proc.Attributes |= ProcAttributes.Background;
                }
                else
                {
                    _proc.Attributes &= ~ProcAttributes.Background;
                }

                if (!DMCompiler.Settings.SuppressUnimplementedWarnings)
                {
                    DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set background is not implemented"));
                }
                break;

            case "name":
                DMASTConstantString name = statementSet.Value as DMASTConstantString;
                if (name is null)
                {
                    throw new CompileErrorException(statementSet.Location, "bad text");
                }
                _proc.VerbName = name.Value;

                if (!DMCompiler.Settings.SuppressUnimplementedWarnings)
                {
                    DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set name is not implemented"));
                }

                break;

            case "category":
                DMASTConstantString category = statementSet.Value as DMASTConstantString;
                if (category is null)
                {
                    throw new CompileErrorException(statementSet.Location, "bad text");
                }
                _proc.VerbCategory = category.Value;

                if (!DMCompiler.Settings.SuppressUnimplementedWarnings)
                {
                    DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set category is not implemented"));
                }
                break;

            case "desc":
                DMASTConstantString desc = statementSet.Value as DMASTConstantString;
                if (desc is null)
                {
                    throw new CompileErrorException(statementSet.Location, "bad text");
                }
                _proc.VerbDesc = desc.Value;

                if (!DMCompiler.Settings.SuppressUnimplementedWarnings)
                {
                    DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set desc is not implemented"));
                }
                break;

            case "invisibility":
                // The ref says 0-101 for atoms and 0-100 for verbs
                // BYOND doesn't clamp the actual var value but it does seem to treat out-of-range values as their extreme
                DMASTConstantFloat invisFloat = statementSet.Value as DMASTConstantFloat;
                if (invisFloat is null)
                {
                    DMASTConstantInteger invisInt = statementSet.Value as DMASTConstantInteger;
                    if (invisInt is null)
                    {
                        throw new CompileErrorException(statementSet.Location, "bad num");
                    }
                    _proc.Invisibility = Convert.ToSByte(Math.Clamp(invisInt.Value, 0, 100));
                }
                else
                {
                    _proc.Invisibility = Convert.ToSByte(Math.Clamp(Math.Floor(invisFloat.Value), 0, 100));
                }

                if (!DMCompiler.Settings.SuppressUnimplementedWarnings)
                {
                    DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set invisibility is not implemented"));
                }
                break;

            case "src":
                if (!DMCompiler.Settings.SuppressUnimplementedWarnings)
                {
                    DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set src is not implemented"));
                }
                break;
            }
        }