in src/resolver/client.js [822:1044]
visitStmt(obj, stmt, belong) {
let node;
let renderByGrammerValueTypes = [
'construct_model',
'property_access',
'map_access',
'boolean',
'super',
'not',
];
if (renderByGrammerValueTypes.indexOf(stmt.type) > -1) {
node = this.renderGrammerValue(null, stmt);
} else if (stmt.type === 'declare') {
let type = null;
if (stmt.expr && stmt.expr.inferred) {
let inferred = stmt.expr.inferred;
if (stmt.expr.propertyPathTypes && stmt.expr.propertyPathTypes.length) {
if (stmt.expr.propertyPathTypes[stmt.expr.propertyPathTypes.length - 1].type === 'map') {
inferred = stmt.expr.propertyPathTypes[stmt.expr.propertyPathTypes.length - 1].keyType;
}
}
type = this.resolveTypeItem(inferred);
} else if (stmt.expectedType) {
type = this.resolveTypeItem(stmt.expectedType);
} else {
debug.stack(stmt);
}
let expectedType = stmt.expectedType ? stmt.expectedType : null;
assert.strictEqual(true, type instanceof TypeItem);
let variate = new GrammerVar(stmt.id.lexeme, type);
if (stmt.expr.type === 'null') {
variate.isOptional = true;
}
let value = this.renderGrammerValue(null, stmt.expr, expectedType, true);
node = new GrammerExpr(variate, Symbol.assign(), value);
} else if (stmt.type === 'requestAssign') {
let variate = new GrammerCall('prop', [
{ type: 'object', name: this.config.request },
{ type: 'prop', name: stmt.left.id.lexeme }
]);
let value = this.renderGrammerValue(null, stmt.expr);
if (stmt.left.type === 'request_property_assign') {
let key = '';
stmt.left.propertyPath.forEach((p, i) => {
if (i === stmt.left.propertyPath.length - 1) {
key = p.lexeme;
} else {
variate.addPath({ type: 'map', name: p.lexeme });
}
});
node = new BehaviorSetMapItem(variate, key, value);
} else {
node = new GrammerExpr(variate, Symbol.assign(), value);
}
} else if (stmt.type === 'ifRequestAssign' || stmt.type === 'if') {
node = this.visitIfElse(stmt, 'if');
} else if (stmt.type === 'elseIfRequestAssign') {
node = this.visitIfElse(stmt, 'elseif');
} else if (stmt.type === 'return') {
node = new GrammerReturn();
if (typeof stmt.expr === 'undefined') {
node.type = 'null';
} else if (stmt.expr.type === 'null') {
node.type = 'null';
} else if (stmt.expr.type === 'call') {
let val = this.renderGrammerValue(null, stmt.expr, null, true);
node.expr = val;
node.type = 'grammer';
} else if (_isBasicType(stmt.expr.type)) {
node.type = stmt.expr.type;
node.expr = this.renderGrammerValue(null, stmt.expr);
} else {
node.expr = this.renderGrammerValue(null, stmt.expr, null, true);
node.type = 'grammer';
}
if (stmt.expectedType && stmt.expectedType.type === 'model') {
let expected = '';
if (stmt.expectedType.moduleName) {
expected += `${stmt.expectedType.moduleName}.`;
}
expected += stmt.expectedType.name;
node.expr = new BehaviorToModel(node.expr, expected);
}
} else if (stmt.type === 'throw') {
this.currThrows['$Error'] = errorType;
node = new GrammerThrows(errorType);
if (Array.isArray(stmt.expr)) {
stmt.expr.forEach(e => {
node.addParam(this.renderGrammerValue(null, e));
});
} else {
node.addParam(this.renderGrammerValue(null, stmt.expr));
}
} else if (stmt.type === 'virtualCall') {
let val = this.renderGrammerValue(null, stmt);
node = val.value;
} else if (stmt.type === 'while') {
node = new GrammerCondition('while');
if (Array.isArray(stmt.condition)) {
stmt.condition.forEach(c => {
node.addCondition(this.renderGrammerValue(null, c));
});
} else {
node.addCondition(this.renderGrammerValue(null, stmt.condition));
}
if (stmt.stmts) {
stmt.stmts.stmts.forEach(s => {
this.visitStmt(node, s, node.index);
});
}
} else if (stmt.type === 'for') {
node = new GrammerLoop('foreach');
node.item = new GrammerVar(stmt.id.lexeme, this.resolveTypeItem(stmt.list.inferred.itemType));
node.source = this.renderGrammerValue(null, stmt.list);
if (stmt.stmts) {
stmt.stmts.stmts.forEach(s => {
this.visitStmt(node, s, node.index);
});
}
} else if (stmt.type === 'assign') {
let hasMapAccess = false;
let expectedType = stmt.expectedType ? stmt.expectedType : stmt.left.inferred ? stmt.left.inferred.name || stmt.left.inferred : null;
let needCast = true;
if (stmt.left.type === 'virtualVariable' || stmt.left.type === 'property') {
needCast = false;
if (stmt.left.id && (stmt.left.id.lexeme === '__request' || stmt.left.id.lexeme === '__response')) {
needCast = true;
}
}
const right = this.renderGrammerValue(null, stmt.expr, expectedType, needCast);
if (stmt.left.type === 'property') {
hasMapAccess = stmt.left.propertyPathTypes.some(item => item.type === 'map');
if (hasMapAccess) {
const grammerValue = this.renderGrammerValue(null, stmt.left);
const call = grammerValue.value;
let lastIndex = 0;
for (let i = 0; i < stmt.left.propertyPathTypes.length; i++) {
const propertyPathType = stmt.left.propertyPathTypes[i];
if (propertyPathType.type === 'map') {
lastIndex = i;
break;
}
}
if (lastIndex + 1 < stmt.left.propertyPathTypes.length) {
call.type = 'prop';
call.path = call.path.splice(0, lastIndex + 2);
const key = stmt.left.propertyPath[lastIndex + 1].lexeme;
node = new BehaviorSetMapItem(call, key, right);
} else {
hasMapAccess = false;
}
}
} else if (stmt.left.type === 'map_access') {
hasMapAccess = true;
const grammerValue = this.renderGrammerValue(null, stmt.left);
const call = grammerValue.value;
call.type = 'prop';
call.path = call.path.splice(0, call.path.length - 1);
node = new BehaviorSetMapItem(call, stmt.left.accessKey.value.string, right);
}
if (!hasMapAccess) {
const left = this.renderGrammerValue(null, stmt.left);
let isBehavior = false;
if (left.type === 'call' && left.value instanceof GrammerCall && left.value.type === 'key') {
const keyPath = left.value.path[left.value.path.length - 1];
if (keyPath.type === 'map') {
left.value.path = left.value.path.slice(0, left.value.path.length - 1);
node = new BehaviorSetMapItem(left.value, keyPath.name, right);
isBehavior = true;
}
}
if (!isBehavior) {
node = new GrammerExpr(
left,
Symbol.assign(),
right
);
}
}
} else if (stmt.type === 'call') {
node = this.renderGrammerValue(null, stmt).value;
} else if (stmt.type === 'break') {
node = new GrammerBreak();
} else if (stmt.type === 'retry') {
node = new BehaviorRetry();
} else if (stmt.type === 'try') {
const tryGram = new GrammerTryCatch();
stmt.tryBlock.stmts.forEach(item => {
this.visitStmt(tryGram, item, tryGram.index);
});
if (stmt.catchId) {
const exceptionGram = new GrammerException(
exceptionType,
new GrammerVar(stmt.catchId.lexeme, exceptionType)
);
const catchGram = new GrammerCatch([], exceptionGram);
if (stmt.catchBlock) {
stmt.catchBlock.stmts.forEach(item => {
this.visitStmt(catchGram, item, catchGram.index);
});
}
tryGram.addCatch(catchGram);
}
if (stmt.finallyBlock) {
const finallyGram = new GrammerFinally();
stmt.finallyBlock.stmts.forEach(item => {
this.visitStmt(finallyGram, item, finallyGram.index);
});
tryGram.setFinally(finallyGram);
}
node = tryGram;
} else {
debug.stack(stmt);
}
if (belong) {
node.belong = belong;
}
this.findComments(obj, stmt, belong);
obj.addBodyNode(node);
this.findComments(obj, stmt, belong, 'back');
}