eliminate @trusted hack in dyaml.emitter (#199)

eliminate @trusted hack in dyaml.emitter
merged-on-behalf-of: BBasile <BBasile@users.noreply.github.com>
This commit is contained in:
Cameron Ross 2018-08-31 08:11:57 -02:30 committed by The Dlang Bot
parent 0a4057472a
commit 9c2ae02792

View file

@ -87,11 +87,14 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
///Stream to write to. ///Stream to write to.
Range stream_; Range stream_;
/// Type used for upcoming emitter steps
alias EmitterFunction = void function(typeof(this)*) @safe;
///Stack of states. ///Stack of states.
Appender!(void function() @safe[]) states_; Appender!(EmitterFunction[]) states_;
///Current state. ///Current state.
//WARNING! DO NOT CALL DIRECTLY! Use callNext() instead! EmitterFunction state_;
void function() @safe state_;
///Event queue. ///Event queue.
Queue!Event events_; Queue!Event events_;
@ -172,13 +175,13 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
* lineBreak = Line break character/s. * lineBreak = Line break character/s.
*/ */
this(Range stream, const bool canonical, const int indent, const int width, this(Range stream, const bool canonical, const int indent, const int width,
const LineBreak lineBreak) @trusted const LineBreak lineBreak) @safe
{ {
states_.reserve(32); states_.reserve(32);
indents_.reserve(32); indents_.reserve(32);
stream_ = stream; stream_ = stream;
canonical_ = canonical; canonical_ = canonical;
nextExpected(&expectStreamStart); nextExpected!"expectStreamStart"();
if(indent > 1 && indent < 10){bestIndent_ = indent;} if(indent > 1 && indent < 10){bestIndent_ = indent;}
if(width > bestIndent_ * 2) {bestWidth_ = width;} if(width > bestIndent_ * 2) {bestWidth_ = width;}
@ -201,7 +204,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
private: private:
///Pop and return the newest state in states_. ///Pop and return the newest state in states_.
void function() @safe popState() @safe EmitterFunction popState() @safe
{ {
enforce(states_.data.length > 0, enforce(states_.data.length > 0,
new YAMLException("Emitter: Need to pop a state but there are no states left")); new YAMLException("Emitter: Need to pop a state but there are no states left"));
@ -210,9 +213,9 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
return result; return result;
} }
void pushState(void delegate() @safe func) @trusted void pushState(string D)() @safe
{ {
states_ ~= func.funcptr; states_ ~= mixin("function(typeof(this)* self) { self."~D~"(); }");
} }
///Pop and return the newest indent in indents_. ///Pop and return the newest indent in indents_.
@ -328,7 +331,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
new EmitterException("Expected streamStart, but got " ~ event_.idString)); new EmitterException("Expected streamStart, but got " ~ event_.idString));
writeStreamStart(); writeStreamStart();
nextExpected(&expectDocumentStart!(Yes.first)); nextExpected!"expectDocumentStart!(Yes.first)"();
} }
///Expect nothing, throwing if we still have something. ///Expect nothing, throwing if we still have something.
@ -392,7 +395,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
writeIndicator("---", Yes.needWhitespace); writeIndicator("---", Yes.needWhitespace);
if(canonical_){writeIndent();} if(canonical_){writeIndent();}
} }
nextExpected(&expectRootNode); nextExpected!"expectRootNode"();
} }
else if(event_.id == EventID.streamEnd) else if(event_.id == EventID.streamEnd)
{ {
@ -402,7 +405,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
writeIndent(); writeIndent();
} }
writeStreamEnd(); writeStreamEnd();
nextExpected(&expectNothing); nextExpected!"expectNothing"();
} }
} }
@ -418,13 +421,13 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
writeIndicator("...", Yes.needWhitespace); writeIndicator("...", Yes.needWhitespace);
writeIndent(); writeIndent();
} }
nextExpected(&expectDocumentStart!(No.first)); nextExpected!"expectDocumentStart!(No.first)"();
} }
///Handle the root node of a document. ///Handle the root node of a document.
void expectRootNode() @safe void expectRootNode() @safe
{ {
pushState(&expectDocumentEnd); pushState!"expectDocumentEnd"();
expectNode(Context.root); expectNode(Context.root);
} }
@ -511,7 +514,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
writeIndicator("[", Yes.needWhitespace, Yes.whitespace); writeIndicator("[", Yes.needWhitespace, Yes.whitespace);
++flowLevel_; ++flowLevel_;
increaseIndent(Yes.flow); increaseIndent(Yes.flow);
nextExpected(&expectFlowSequenceItem!(Yes.first)); nextExpected!"expectFlowSequenceItem!(Yes.first)"();
} }
///Handle a flow sequence item. ///Handle a flow sequence item.
@ -532,7 +535,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
} }
static if(!first){writeIndicator(",", No.needWhitespace);} static if(!first){writeIndicator(",", No.needWhitespace);}
if(canonical_ || column_ > bestWidth_){writeIndent();} if(canonical_ || column_ > bestWidth_){writeIndent();}
pushState(&expectFlowSequenceItem!(No.first)); pushState!"expectFlowSequenceItem!(No.first)"();
expectSequenceNode(); expectSequenceNode();
} }
@ -544,7 +547,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
writeIndicator("{", Yes.needWhitespace, Yes.whitespace); writeIndicator("{", Yes.needWhitespace, Yes.whitespace);
++flowLevel_; ++flowLevel_;
increaseIndent(Yes.flow); increaseIndent(Yes.flow);
nextExpected(&expectFlowMappingKey!(Yes.first)); nextExpected!"expectFlowMappingKey!(Yes.first)"();
} }
///Handle a key in a flow mapping. ///Handle a key in a flow mapping.
@ -568,13 +571,13 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
if(canonical_ || column_ > bestWidth_){writeIndent();} if(canonical_ || column_ > bestWidth_){writeIndent();}
if(!canonical_ && checkSimpleKey()) if(!canonical_ && checkSimpleKey())
{ {
pushState(&expectFlowMappingSimpleValue); pushState!"expectFlowMappingSimpleValue"();
expectMappingNode(true); expectMappingNode(true);
return; return;
} }
writeIndicator("?", Yes.needWhitespace); writeIndicator("?", Yes.needWhitespace);
pushState(&expectFlowMappingValue); pushState!"expectFlowMappingValue"();
expectMappingNode(); expectMappingNode();
} }
@ -582,7 +585,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
void expectFlowMappingSimpleValue() @safe void expectFlowMappingSimpleValue() @safe
{ {
writeIndicator(":", No.needWhitespace); writeIndicator(":", No.needWhitespace);
pushState(&expectFlowMappingKey!(No.first)); pushState!"expectFlowMappingKey!(No.first)"();
expectMappingNode(); expectMappingNode();
} }
@ -591,7 +594,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
{ {
if(canonical_ || column_ > bestWidth_){writeIndent();} if(canonical_ || column_ > bestWidth_){writeIndent();}
writeIndicator(":", Yes.needWhitespace); writeIndicator(":", Yes.needWhitespace);
pushState(&expectFlowMappingKey!(No.first)); pushState!"expectFlowMappingKey!(No.first)"();
expectMappingNode(); expectMappingNode();
} }
@ -603,7 +606,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
const indentless = (context_ == Context.mappingNoSimpleKey || const indentless = (context_ == Context.mappingNoSimpleKey ||
context_ == Context.mappingSimpleKey) && !indentation_; context_ == Context.mappingSimpleKey) && !indentation_;
increaseIndent(No.flow, indentless); increaseIndent(No.flow, indentless);
nextExpected(&expectBlockSequenceItem!(Yes.first)); nextExpected!"expectBlockSequenceItem!(Yes.first)"();
} }
///Handle a block sequence item. ///Handle a block sequence item.
@ -618,7 +621,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
writeIndent(); writeIndent();
writeIndicator("-", Yes.needWhitespace, No.whitespace, Yes.indentation); writeIndicator("-", Yes.needWhitespace, No.whitespace, Yes.indentation);
pushState(&expectBlockSequenceItem!(No.first)); pushState!"expectBlockSequenceItem!(No.first)"();
expectSequenceNode(); expectSequenceNode();
} }
@ -628,7 +631,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
void expectBlockMapping() @safe void expectBlockMapping() @safe
{ {
increaseIndent(No.flow); increaseIndent(No.flow);
nextExpected(&expectBlockMappingKey!(Yes.first)); nextExpected!"expectBlockMappingKey!(Yes.first)"();
} }
///Handle a key in a block mapping. ///Handle a key in a block mapping.
@ -644,13 +647,13 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
writeIndent(); writeIndent();
if(checkSimpleKey()) if(checkSimpleKey())
{ {
pushState(&expectBlockMappingSimpleValue); pushState!"expectBlockMappingSimpleValue"();
expectMappingNode(true); expectMappingNode(true);
return; return;
} }
writeIndicator("?", Yes.needWhitespace, No.whitespace, Yes.indentation); writeIndicator("?", Yes.needWhitespace, No.whitespace, Yes.indentation);
pushState(&expectBlockMappingValue); pushState!"expectBlockMappingValue"();
expectMappingNode(); expectMappingNode();
} }
@ -658,7 +661,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
void expectBlockMappingSimpleValue() @safe void expectBlockMappingSimpleValue() @safe
{ {
writeIndicator(":", No.needWhitespace); writeIndicator(":", No.needWhitespace);
pushState(&expectBlockMappingKey!(No.first)); pushState!"expectBlockMappingKey!(No.first)"();
expectMappingNode(); expectMappingNode();
} }
@ -667,7 +670,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
{ {
writeIndent(); writeIndent();
writeIndicator(":", Yes.needWhitespace, No.whitespace, Yes.indentation); writeIndicator(":", Yes.needWhitespace, No.whitespace, Yes.indentation);
pushState(&expectBlockMappingKey!(No.first)); pushState!"expectBlockMappingKey!(No.first)"();
expectMappingNode(); expectMappingNode();
} }
@ -1294,21 +1297,17 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
writeString(prefix); writeString(prefix);
writeLineBreak(); writeLineBreak();
} }
void nextExpected(string D)() @safe
void nextExpected(void delegate() @safe func) @trusted
{ {
state_ = func.funcptr; state_ = mixin("function(typeof(this)* self) { self."~D~"(); }");
} }
void nextExpected(void function() @safe func) @safe void nextExpected(EmitterFunction f) @safe
{ {
state_ = func; state_ = f;
} }
void callNext() @trusted void callNext() @safe
{ {
void delegate() @safe func; state_(&this);
func.funcptr = state_;
func.ptr = &this;
func();
} }
} }