in src/langs/cpp/combinator.js [1448:1944]
grammerValue(emitter, gram, layer = 0) {
if (is.annotation(gram)) {
this.emitAnnotation(emitter, gram);
return;
}
if (gram.type === 'map' || gram.type === 'model_construct_params') {
if (gram.type === 'model_construct_params' && this.emitType(gram.dataType) !== 'map<string, boost::any>') {
gram.dataType = new TypeMap(
new TypeString(), new TypeGeneric()
);
}
this.emitMap(emitter, gram, layer);
} else if (gram.type === 'string') {
emitter.emit(`"${gram.value}"`);
} else if (gram.type === 'null') {
emitter.emit('nullptr');
} else if (gram.type === 'behavior' || gram.type === 'call'
|| gram.type === 'var' || gram.type === 'instance') {
this.grammer(emitter, gram.value, false, false);
} else if (gram.type === 'number' || gram.type === 'param' || gram.type === 'bool') {
emitter.emit(gram.value);
} else if (gram.type === 'expr') {
if (Array.isArray(gram.value)) {
gram.value.forEach(gramItem => {
this.grammer(emitter, gramItem, false, false);
});
} else {
this.grammer(emitter, gram.value, false, false);
}
} else if (gram.type === 'array') {
let itemType = this.emitType(gram.dataType.itemType);
if (gram.value.length) {
emitter.emitln(`vector<${itemType}>({`);
this.levelUp();
gram.value.forEach((item, i) => {
if (item instanceof AnnotationItem) {
this.emitAnnotation(emitter, item);
return;
}
emitter.emit('', this.level);
this.grammerValue(emitter, item, false, false);
if (i < gram.value.length - 1) {
emitter.emitln(',');
} else {
emitter.emitln();
}
});
this.levelDown();
emitter.emit('})', this.level);
} else {
emitter.emit(`vector<${itemType}>()`);
}
} else if (gram.type === 'not') {
emitter.emit(_symbol(Symbol.reverse()));
this.grammerValue(emitter, gram.value);
} else {
debug.stack(gram);
}
}
grammerCall(emitter, gram) {
if (gram.type === 'sys_func' || gram.type === 'method') {
const resolve_method = _resolveGrammerCall(gram, this.dependencies);
if (resolve_method !== null) {
if (!modules[resolve_method]) {
debug.stack(`Unsupported method : ${resolve_method}`);
}
modules[resolve_method].call(this, emitter, gram);
return;
}
let params = gram.params.length > 0 ? this.resolveParams(gram) : '';
emitter.emit(this.resolveCallPath(gram.path, params, gram));
} else if (gram.type === 'prop') {
emitter.emit(this.resolveCallPath(gram.path, '', gram));
} else if (gram.type === 'key') {
emitter.emit(this.resolveCallPath(gram.path, '', gram));
} else {
debug.stack(gram);
}
}
grammerExpr(emitter, gram) {
if (gram.opt === Symbol.concat()) {
// implement by behaviorTamplateString
debug.stack(gram);
}
this.exprIsAssignToPtr = this.isPointerVar(gram.left);
if (!gram.left && !gram.right) {
// only emit symbol
emitter.emit(` ${_symbol(gram.opt)} `);
this.exprIsAssignToPtr = null;
return;
}
// emit left of expr
if (gram.opt !== Symbol.assign() && this.exprIsAssignToPtr) {
emitter.emit('*');
}
this.grammer(emitter, gram.left, false, false);
if (gram.right.type === 'null') {
// not emit symbol&right if right of expr is null
this.exprIsAssignToPtr = null;
if (gram.left instanceof GrammerVar) { return; }
}
// emit right of expr
if (gram.opt === Symbol.assign()) {
let isNewObject = false;
let right = null;
if (gram.right instanceof GrammerValue && gram.right.type === 'instance' && gram.right.value instanceof GrammerNewObject) {
isNewObject = true;
right = gram.right.value;
} else if (gram.right instanceof GrammerNewObject) {
isNewObject = true;
right = gram.right;
}
if (isNewObject) {
this.exprIsAssignToPtr = this.isPointerVar(gram.left);
// is new object
if (this.isPointerVar(gram.left)) {
// new object to ptr property
emitter.emit(` ${_symbol(gram.opt)} `); // emit symbol of expr
this.grammerNewObject(emitter, right, true, true);
this.exprIsAssignToPtr = null;
return;
}
this.grammerNewObject(emitter, right, false);
this.exprIsAssignToPtr = null;
return;
}
emitter.emit(` ${_symbol(gram.opt)} `); // emit symbol of expr
let toStream = false;
let leftIsPointer;
let leftDataType = this.resolveDataType(gram.left);
if (leftDataType !== 'Darabonba::Stream' && gram.left instanceof GrammerValue && gram.left.type === 'call' && gram.left.value.path[1].name === 'body') {
const k = gram.left.value.path.map(item => item.name).join('.');
toStream = k === '__request.body' && is.string(gram.right.dataType);
leftIsPointer = true;
} else {
toStream = leftDataType === 'Darabonba::Stream';
leftIsPointer = this.isPointerVar(gram.left);
}
let rightIsPointer = this.isPointerVar(gram.right);
if (toStream) {
emitter.emit(`${this.config.tea.converter.name}::toStream(`);
}
let dataType = this.resolveDataType(gram.right);
if (dataType === null) {
dataType = this.resolveDataType(gram.left);
}
if (leftIsPointer && rightIsPointer) {
if (toStream) {
emitter.emit('*');
}
this.exprIsAssignToPtr = true;
this.grammer(emitter, gram.right, false, false);
} else if (leftIsPointer && !rightIsPointer) {
this.exprIsAssignToPtr = true;
if (toStream) {
this.grammer(emitter, gram.right, false, false);
} else {
emitter.emit(this.emitMakeShared(dataType, gram.right));
}
} else if (!leftIsPointer && rightIsPointer) {
emitter.emit('*');
this.grammer(emitter, gram.right, false, false);
} else {
this.grammer(emitter, gram.right, false, false);
}
if (toStream) {
emitter.emit(')');
}
this.exprIsAssignToPtr = null;
return;
}
emitter.emit(` ${_symbol(gram.opt)} `); // emit symbol of expr
this.grammer(emitter, gram.right, false, false);
this.exprIsAssignToPtr = null;
}
grammerLoop(emitter, gram) {
this.pushInclude('algorithm');
if (gram.type === 'foreach') {
emitter.emit('for(auto ');
this.grammerVar(emitter, gram.item, false, false);
emitter.emit(' : ');
if (this.isPointerVar(gram.source)) {
emitter.emit('*');
}
this.grammer(emitter, gram.source, false, false);
emitter.emitln(') {');
}
this.levelUp();
gram.body.forEach(node => {
this.grammer(emitter, node);
});
this.levelDown();
emitter.emitln('}', this.level);
}
grammerBreak(emitter, gram) {
emitter.emit('break');
}
grammerCondition(emitter, gram) {
if (gram.type === 'elseif') {
emitter.emit('else if');
} else {
emitter.emit(`${gram.type}`);
}
if (gram.type !== 'else') {
emitter.emit(' (');
let emit = new Emitter(this.config);
gram.conditionBody.forEach(condition => {
this.grammer(emitter, condition, false, false);
});
emitter.emit(`${emit.output})`);
}
emitter.emitln(' {');
this.levelUp();
gram.body.forEach(node => {
this.grammer(emitter, node);
});
this.levelDown();
emitter.emitln('}', this.level);
if (gram.elseItem.length && gram.elseItem.length > 0) {
gram.elseItem.forEach(e => {
this.grammer(emitter, e);
});
}
}
grammerTryCatch(emitter, gram) {
emitter.emitln('try {');
this.levelUp();
gram.body.forEach(node => {
this.grammer(emitter, node);
});
this.levelDown();
emitter.emitln('}', this.level);
gram.catchBody.forEach(node => {
assert.strictEqual(true, node instanceof GrammerCatch);
this.grammerCatch(emitter, node);
});
if (gram.finallyBody) {
this.grammerFinally(emitter, gram.finallyBody);
}
}
grammerCatch(emitter, gram) {
let emitterVar = new Emitter(this.config);
this.grammerVar(emitterVar, gram.exceptions.exceptionVar, false);
let varName = emitterVar.output;
emitter.emit(`catch (${this.emitType(gram.exceptions.type)} &`, this.level);
this.addStatement(varName, gram.exceptions.type, false);
emitter.emit(varName);
emitter.emitln(') {');
this.levelUp();
gram.body.forEach(childGram => {
this.grammer(emitter, childGram);
});
this.levelDown();
emitter.emitln('}', this.level);
}
grammerFinally(emitter, gram) {
emitter.emitln('catch(std::exception &e) {', this.level);
this.levelUp();
gram.body.forEach(childGram => {
this.grammer(emitter, childGram);
});
this.levelDown();
emitter.emitln('}', this.level);
}
grammerContinue(emitter, gram) {
emitter.emit('continue');
}
grammerThrows(emitter, gram) {
this.pushInclude('throw_exception');
emitter.emit('BOOST_THROW_EXCEPTION(');
// emit exception_begin
if (gram.exception) {
let isException = is.object(gram.exception) && gram.exception.objectName === '$Exception';
if (isException) {
emitter.emit('std::runtime_error(');
} else {
emitter.emit(`${this.emitType(gram.exception)}(`);
}
}
// emit exception_body
if (!gram.params.length) {
let msg = gram.message ? `"${gram.message}"` : '';
emitter.emit(msg);
} else if (gram.params.length === 1) {
let isError = is.object(gram.exception) && gram.exception.objectName === '$Error';
if (isError) {
let dataType = this.resolveDataType(gram.params[0]);
emitter.emit(`${dataType}(`);
this.grammerValue(emitter, gram.params[0]);
emitter.emit(')');
} else {
this.grammerValue(emitter, gram.params[0]);
}
} else {
let tmp = [];
gram.params.forEach(p => {
let emit = new Emitter(this.config);
this.grammerValue(emit, p);
tmp.push(emit.output);
});
emitter.emit(tmp.join(', '));
}
// emit exception_end
if (gram.exception) {
emitter.emit(')');
}
emitter.emit(')'); // close BOOST_THROW_EXCEPTION
}
grammerNewObject(emitter, gram, isAssign = true, isPtrParam = false) {
let objectName = gram.name;
if (!this.exprIsAssignToPtr && isAssign) {
emitter.emit(`${this.resolveName(objectName)}(`);
} else if (isAssign) {
emitter.emit(`make_shared<${this.resolveName(objectName)}>(`);
}
let tmp = [];
let params;
if (Array.isArray(gram.params)) {
params = gram.params;
} else {
params = [gram.params];
}
if (params.length) {
params.forEach(p => {
if (p instanceof GrammerValue && p.type === 'model_construct_params' && !p.value.length) {
return;
} else if (p instanceof GrammerValue && p.type === 'model_construct_params') {
isPtrParam = false;
}
let emit = new Emitter(this.config);
if (isPtrParam && !this.isPointerVar(p)) {
emit.emit(this.emitMakeShared(p.dataType ? p.dataType : p.type, p));
} else {
this.grammerValue(emit, p, false, false);
}
tmp.push(emit.output);
});
// emitter.emit(tmp.join(', '));
}
if (isAssign) {
emitter.emit(tmp.join(', '));
emitter.emit(')');
} else if (tmp.length) {
emitter.emit('(');
emitter.emit(tmp.join(', '));
emitter.emit(')');
}
}
grammerReturn(emitter, gram) {
if (is.void(this.funcReturnType)) {
emitter.emit('return');
return;
}
emitter.emit('return ');
if (gram.type === 'null') {
this.grammerValue(emitter, new GrammerValue('null'), false, false);
} else if (gram.type === 'grammer') {
let returnPointer = this.isPointerType(this.funcReturnType);
if (this.isPointerVar(gram.expr) && !returnPointer) {
emitter.emit('*');
}
this.grammer(emitter, gram.expr, false, false);
} else if (gram.type === 'string') {
emitter.emit('string("")');
} else {
this.grammer(emitter, gram.expr, false, false);
}
}
/**************************************** behavior ****************************************/
behaviorTimeNow(emitter, behavior) {
emitter.emit('0');
}
behaviorDoAction(emitter, behavior) {
emitter.emit('', this.level);
this.grammerVar(emitter, behavior.var);
emitter.emit(` = make_shared<${this.addInclude('$Response')}>(${this.addInclude('$Core')}::${this.config.tea.core.doAction}(`);
let params = [];
behavior.params.forEach(p => {
let emit = new Emitter(this.config);
if (this.isPointerVar(p)) {
emit.emit('*');
}
this.grammerValue(emit, p);
params.push(emit.output);
});
emitter.emit(params.join(', '));
emitter.emitln('));');
behavior.body.forEach(node => {
this.grammer(emitter, node);
});
}
behaviorToMap(emitter, behavior) {
const grammer = behavior.grammer;
if (grammer instanceof GrammerCall) {
grammer.path.push({
type: 'call',
name: 'toMap'
});
this.grammerCall(emitter, grammer);
} else if (grammer instanceof GrammerVar) {
const grammerCall = new GrammerCall('method');
grammerCall.path.push({
type: 'object',
name: grammer.name
});
grammerCall.path.push({
type: 'call',
name: 'toMap'
});
this.grammerCall(emitter, grammerCall);
} else {
debug.stack(grammer);
}
}
behaviorToModel(emitter, behavior) {
emitter.emit(`${behavior.expected}(`);
let type = this.resolveDataType(behavior.grammer);
if (type === 'map<string, string>') {
emitter.emit(`${this.config.tea.converter.name}::toGenericMap(`);
this.grammer(emitter, behavior.grammer, false, false);
emitter.emit(')');
} else {
behavior.grammer.type = 'model_construct_params';
this.grammer(emitter, behavior.grammer, false, false);
}
emitter.emit(')');
}
behaviorSetMapItem(emitter, behavior) {
let emit = new Emitter(this.config);
this.grammerCall(emit, behavior.call);
this.pushInclude('map');
let paths = behavior.call.path;
let key = super.resolveName(behavior.key);
if (this.isPointerPath(paths.length - 1, paths)) {
emitter.emit(`${emit.output}->insert(pair<string, ${this.emitType(behavior.value.dataType)}>("${key}", `, this.level);
} else {
emitter.emit(`${emit.output}.insert(pair<string, ${this.emitType(behavior.value.dataType)}>("${key}", `, this.level);
}
if (this.isPointerVar(behavior.value)) {
emitter.emit('*');
}
this.grammerValue(emitter, behavior.value);
emitter.emitln('));');
}
behaviorRetry(emitter, behavior) {
emitter.emitln(`throw ${this.addInclude('$Error')}(${this.config.request}, ${this.config.response});`, this.level);
}
behaviorTamplateString(emitter, behavior) {
let tmp = [];
behavior.items.forEach(item => {
let emit = new Emitter(this.config);
if (this.isPointerVar(item) && !is.any(item.dataType)) {
emit.emit('*');
}
if (is.string(item.dataType)) {
this.grammer(emit, item, false, false);
} else if (is.any(item.dataType)) {
this.pushInclude('darabonba_core');
emit.emit(`${this.config.tea.converter.name}::toString(`);
this.grammer(emit, item, false, false);
emit.emit(')');
} else {
this.pushInclude('cast');
emit.emit('boost::lexical_cast<string>(');
this.grammer(emit, item, false, false);
emit.emit(')');
}
tmp.push(emit.output);
});
emitter.emit(`${tmp.filter(s => s !== '""').map(s => `string(${s})`).join(' + ')}`);
}
}