public void ProcessStatementSet(DMASTProcStatementSet statementSet) { //TODO: Proc attributes switch (statementSet.Attribute.ToLower()) { case "waitfor": { if (!DMExpression.TryConstant(_dmObject, _proc, statementSet.Value, out var constant)) { throw new CompileErrorException(statementSet.Location, $"waitfor attribute should be a constant"); } _proc.WaitFor(constant.IsTruthy()); break; } case "opendream_unimplemented": { if (!DMExpression.TryConstant(_dmObject, _proc, statementSet.Value, out var constant)) { throw new CompileErrorException(statementSet.Location, $"opendream_unimplemented attribute should be a constant"); } _proc.Unimplemented = constant.IsTruthy(); break; } } }
public void VisitUpwardPathSearch(DMASTUpwardPathSearch constant) { DMExpression.TryConstant(_dmObject, _proc, constant.Path, out var pathExpr); if (pathExpr is not Expressions.Path) { throw new CompileErrorException(constant.Location, "Cannot do an upward path search on " + pathExpr); } DreamPath path = ((Expressions.Path)pathExpr).Value; DreamPath?foundPath = DMObjectTree.UpwardSearch(path, constant.Search.Path); if (foundPath == null) { throw new CompileErrorException(constant.Location, $"Invalid path {path}.{constant.Search.Path}"); } Result = new Expressions.Path(constant.Location, foundPath.Value); }
public void ProcessStatementSwitch(DMASTProcStatementSwitch statementSwitch) { string endLabel = _proc.NewLabelName(); List <(string CaseLabel, DMASTProcBlockInner CaseBody)> valueCases = new(); DMASTProcBlockInner defaultCaseBody = null; DMExpression.Emit(_dmObject, _proc, statementSwitch.Value); foreach (DMASTProcStatementSwitch.SwitchCase switchCase in statementSwitch.Cases) { if (switchCase is DMASTProcStatementSwitch.SwitchCaseValues switchCaseValues) { string caseLabel = _proc.NewLabelName(); foreach (DMASTExpression value in switchCaseValues.Values) { if (value is DMASTSwitchCaseRange range) { if (!DMExpression.TryConstant(_dmObject, _proc, range.RangeStart, out var lower)) { throw new CompileErrorException(new CompilerError(range.RangeStart.Location, "Expected a constant")); } if (!DMExpression.TryConstant(_dmObject, _proc, range.RangeEnd, out var upper)) { throw new CompileErrorException(new CompilerError(range.RangeEnd.Location, "Expected a constant")); } lower.EmitPushValue(_dmObject, _proc); upper.EmitPushValue(_dmObject, _proc); _proc.SwitchCaseRange(caseLabel); } else { if (!DMExpression.TryConstant(_dmObject, _proc, value, out var constant)) { throw new CompileErrorException(new CompilerError(value.Location, "Expected a constant")); } constant.EmitPushValue(_dmObject, _proc); _proc.SwitchCase(caseLabel); } } valueCases.Add((caseLabel, switchCase.Body)); } else { defaultCaseBody = ((DMASTProcStatementSwitch.SwitchCaseDefault)switchCase).Body; } } _proc.Pop(); if (defaultCaseBody != null) { _proc.StartScope(); { ProcessBlockInner(defaultCaseBody); } _proc.EndScope(); } _proc.Jump(endLabel); foreach ((string CaseLabel, DMASTProcBlockInner CaseBody)valueCase in valueCases) { _proc.AddLabel(valueCase.CaseLabel); _proc.StartScope(); { ProcessBlockInner(valueCase.CaseBody); } _proc.EndScope(); _proc.Jump(endLabel); } _proc.AddLabel(endLabel); }
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; } }
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; } }