in src/resolver/client.js [480:820]
renderGrammerValue(valGrammer, object, expectedType = null, canCast = false) {
if (!valGrammer) {
valGrammer = new GrammerValue();
}
if (!valGrammer.value && object.type === 'object') {
valGrammer.value = [];
}
if (object.type === 'variable') {
if (object.needCast) {
let grammerVar = new GrammerVar(object.id.lexeme, this.resolveTypeItem(object.inferred));
valGrammer.type = 'behavior';
grammerVar.belong = valGrammer.index;
const behaviorToMap = new BehaviorToMap(grammerVar, object.inferred);
behaviorToMap.belong = valGrammer.index;
valGrammer.value = behaviorToMap;
} else {
valGrammer.type = 'var';
let grammerVar;
if (object.id.type === 'model') {
const name = `#${object.id.lexeme}`;
const type = this.resolveTypeItem(object.inferred);
type.objectName = name;
grammerVar = new GrammerVar(object.id.lexeme, type);
grammerVar.varType = 'static_class';
grammerVar.name = name;
} else if (object.type === 'variable') {
grammerVar = new GrammerVar(object.id.lexeme, this.resolveTypeItem(object.inferred));
grammerVar.varType = 'var';
grammerVar.needCast = canCast;
grammerVar.expected = expectedType ? this.resolveTypeItem(expectedType) : null;
}
valGrammer.value = grammerVar;
}
} else if (object.type === 'object') {
object.fields.forEach(field => {
var val = null;
var type = field.expr.type;
if (field.expr.type === 'object') {
val = [];
type = 'map';
}
var exprChild = new GrammerValue(type, val);
if (field.type === 'expandField') {
exprChild.isExpand = true;
}
if (field.fieldName && (field.fieldName.lexeme || field.fieldName.string)) {
exprChild.key = field.fieldName.lexeme || _string(field.fieldName);
}
this.renderGrammerValue(exprChild, field.expr, expectedType, true);
this.findComments(valGrammer, field);
valGrammer.value.push(exprChild);
this.findComments(valGrammer, field.expr, 'back');
});
valGrammer.type = 'map';
valGrammer.dataType = this.resolveTypeItem(object.inferred);
valGrammer.expected = expectedType ? this.resolveTypeItem(expectedType) : null;
} else if (object.type === 'string') {
valGrammer.type = 'string';
valGrammer.value = object.value.string;
} else if (object.type === 'property_access') {
let last_path_type = this.resolveTypeItem(object.id.inferred || object.inferred);
let call = new GrammerCall('prop', [], [], last_path_type);
var model = false;
if (object.id.lexeme !== '__request' && object.id.lexeme !== '__response') {
model = canCast;
}
call.addPath({ type: 'object', name: object.id.lexeme, dataType: last_path_type, needCast: model });
object.propertyPath.forEach((item, i) => {
var path_name = item.lexeme;
let path_type = this.resolveTypeItem(object.propertyPathTypes[i]);
let call_type = 'prop';
if (is.array(last_path_type)) {
call_type = 'list';
} else if (is.map(last_path_type)) {
call_type = 'map';
} else if (is.object(last_path_type)) {
call_type = 'prop';
} else {
debug.stack(last_path_type);
}
var resolve = false;
if (i !== (object.propertyPath.length - 1) && object.id.lexeme !== '__request' && object.id.lexeme !== '__response') {
resolve = true;
}
call.addPath({ type: call_type, name: path_name, dataType: path_type, needCast: resolve });
last_path_type = path_type;
});
valGrammer.type = 'call';
valGrammer.value = call;
if (object.needCast) {
valGrammer.type = 'behavior';
valGrammer.value = new BehaviorToMap(valGrammer.value, object.inferred);
}
valGrammer.needCast = model;
} else if (object.type === 'number') {
valGrammer.type = 'number';
valGrammer.value = object.value.value;
valGrammer.dataType = this.resolveTypeItem(object.inferred);
} else if (object.type === 'virtualVariable') {
valGrammer.type = 'call';
let call = new GrammerCall('prop', [
{ type: 'parent', name: '' },
{ type: 'prop', name: object.vid.lexeme },
]);
// call.isOptional = true;
valGrammer.needCast = canCast;
valGrammer.value = call;
} else if (object.type === 'template_string') {
valGrammer.type = 'behavior';
let behaviorTamplateString = new BehaviorTamplateString();
object.elements.forEach(ele => {
if (ele.type !== 'element') {
behaviorTamplateString.addItem(this.renderGrammerValue(null, ele.expr, null, true));
} else {
behaviorTamplateString.addItem(new GrammerValue('string', ele.value.string, new TypeString()));
}
});
valGrammer.value = behaviorTamplateString;
} else if (object.type === 'null') {
valGrammer.type = 'null';
valGrammer.value = null;
} else if (object.type === 'construct_model') {
let objectName = object.aliasId.lexeme ? object.aliasId.lexeme : '';
if (object.propertyPath && object.propertyPath.length > 0) {
if (object.propertyPath.length > 0 && objectName !== '') {
objectName = objectName + '.';
}
object.propertyPath.forEach((p, i) => {
objectName += p.lexeme;
if (i !== object.propertyPath.length - 1) {
objectName += '.';
}
});
}
objectName = `#${objectName}`;
valGrammer.type = 'instance';
let params = [];
if (object.object) {
params = this.renderGrammerValue(null, object.object);
if (params.value.length === 0) {
this.findComments(params, object.object, 'between');
}
if (object.object.inferred.type === 'map') {
params.type = 'model_construct_params';
}
}
valGrammer.value = new GrammerNewObject(objectName, params);
} else if (object.type === 'call') {
let call_type = 'method';
valGrammer.type = 'call';
if (object.left && object.left.id && object.left.id.type === 'module') {
if (systemPackage.indexOf(object.left.id.lexeme) > -1) {
call_type = 'sys_func';
}
} else {
valGrammer.type = 'call';
call_type = 'method';
}
let call = new GrammerCall(call_type, undefined, undefined, undefined, object.hasThrow, object.isAsync, object.isStatic, object.isOptional);
if (object.left) {
let isStatic = object.isStatic ? true : false;
let callType = isStatic ? '_static' : '';
if (object.left.type === 'method_call') {
if (isStatic) {
call.addPath({ type: 'class', name: '' });
}
call.addPath({ type: 'call' + callType, name: object.left.id.lexeme });
} else if (object.left.type === 'instance_call') {
if (object.left && object.left.id && object.left.id.lexeme) {
if (object.left.id.type === 'variable') {
call.addPath({ type: 'object' + callType, name: object.left.id.lexeme });
} else if (typeof object.left.id.type === 'undefined' && object.left.id.lexeme.indexOf('@') > -1) {
call.addPath({ type: 'parent', name: '' });
call.addPath({ type: 'prop', name: object.left.id.lexeme, needCast: true });
} else {
debug.stack('Unsupported object.left.id.type : ' + object.left.id.type, object);
}
}
} else if (object.left.type === 'static_call') {
if (object.left.id.type === 'module') {
call.addPath({ type: 'object_static', name: `^${object.left.id.lexeme}` });
isStatic = true;
} else {
// call.addPath({ type: 'call_static', name: object.left.id.lexeme });
debug.stack(object);
}
} else {
debug.stack(object.left);
}
if (object.left.propertyPath) {
object.left.propertyPath.forEach(p => {
call.addPath({
type: 'call' + callType,
name: p.lexeme
});
});
}
}
if (object.args) {
object.args.forEach(arg => {
const grammerValue = this.renderGrammerValue(null, arg, null, true);
grammerValue.belong = call.index;
call.addParams(grammerValue);
});
}
call.returnType = this.resolveTypeItem(object.inferred);
valGrammer.value = call;
} else if (object.type === 'construct') {
valGrammer.type = 'instance';
const objectName = `^${object.aliasId.lexeme}`;
valGrammer.value = new GrammerNewObject(objectName);
object.args.forEach(item => {
valGrammer.value.addParam(this.renderGrammerValue(null, item));
});
} else if (object.type === 'boolean') {
valGrammer.type = 'bool';
valGrammer.value = object.value;
} else if (object.type === 'not') {
valGrammer.type = 'not';
valGrammer.value = this.renderGrammerValue(null, object.expr);
} else if (object.type === 'array') {
valGrammer.type = 'array';
valGrammer.value = [];
if (object.items.length > 0) {
object.items.forEach(field => {
this.findComments(valGrammer, field);
var exprChild = this.renderGrammerValue(null, field, expectedType);
valGrammer.value.push(exprChild);
this.findComments(valGrammer, field, 'back');
});
} else {
this.findComments(valGrammer, object, 'between');
}
valGrammer.type = 'array';
valGrammer.expected = expectedType ? this.resolveTypeItem(expectedType) : null;
} else if (object.type === 'property') {
object.type = 'property_access';
this.renderGrammerValue(valGrammer, object, null, canCast);
} else if (object.type === 'super') {
valGrammer.type = 'call';
let call = new GrammerCall('super', undefined, undefined, undefined, object.hasThrow, object.isAsync);
object.args.forEach(arg => {
call.addParams(this.renderGrammerValue(null, arg));
});
valGrammer.value = call;
} else if (object.type === 'map_access') {
valGrammer.type = 'call';
let accessKey;
if (object.accessKey.inferred) {
accessKey = this.renderGrammerValue(null, object.accessKey, null, true);
} else if (object.accessKey.type === 'variable') {
accessKey = object.accessKey.id.lexeme;
} else if (object.accessKey.type === 'string') {
accessKey = object.accessKey.value.string;
} else if (object.accessKey.value && object.accessKey.value.lexeme) {
accessKey = object.accessKey.value.lexeme;
} else {
debug.stack(object);
}
let current = object.id.inferred;
let call = new GrammerCall('key');
call.addPath({ type: 'object', name: object.id.lexeme });
if (object.propertyPathTypes) {
for (let i = 0; i < object.propertyPath.length; i++) {
if (current.type === 'model') {
call.type = 'prop';
call.addPath({ type: 'prop', name: object.propertyPath[i].lexeme, needCast: canCast });
} else if (current.type === 'array') {
call.addPath({ type: 'list', name: object.propertyPath[i].lexeme, needCast: canCast });
} else {
call.addPath({ type: 'map', name: object.propertyPath[i].lexeme, needCast: canCast });
}
current = object.propertyPathTypes[i];
}
}
call.addPath({ type: 'map', name: accessKey });
if (object.inferred) {
let inferred = object.inferred;
if (object.propertyPathTypes && object.propertyPathTypes.length) {
if (object.propertyPathTypes[object.propertyPathTypes.length - 1].type === 'map') {
inferred = object.propertyPathTypes[object.propertyPathTypes.length - 1].keyType;
}
}
call.returnType = this.resolveTypeItem(inferred);
}
valGrammer.value = call;
valGrammer.needCast = canCast;
} else if (object.type === 'array_access') {
valGrammer.type = 'call';
let accessKey;
if (object.accessKey.inferred) {
accessKey = this.renderGrammerValue(null, object.accessKey);
} else if (object.accessKey.type === 'number') {
accessKey = object.accessKey.value.value;
} else if (object.accessKey.type === 'variable') {
accessKey = object.accessKey.id.lexeme;
} else {
debug.stack(object);
}
let current = object.id.inferred;
let call = new GrammerCall('key');
call.addPath({ type: 'object', name: object.id.lexeme });
if (object.propertyPathTypes) {
for (let i = 0; i < object.propertyPath.length; i++) {
if (current.type === 'model') {
call.type = 'prop';
call.addPath({ type: 'prop', name: object.propertyPath[i].lexeme });
} else if (current.type === 'array') {
call.addPath({ type: 'list', name: object.propertyPath[i].lexeme });
} else {
call.addPath({ type: 'map', name: object.propertyPath[i].lexeme });
}
current = object.propertyPathTypes[i];
}
}
call.addPath({ type: 'list', name: accessKey, isVar: object.accessKey.type === 'variable' });
if (object.inferred) {
call.returnType = this.resolveTypeItem(object.inferred);
}
valGrammer.value = call;
} else if (['and', 'or', 'not'].indexOf(object.type) > -1) {
valGrammer.type = 'expr';
valGrammer.value = this.visitIfConfition(object);
} else {
debug.stack('unimpelemented : ' + object.type, object);
}
if (object.inferred) {
valGrammer.dataType = this.resolveTypeItem(object.inferred);
}
if (object.needToReadable) {
valGrammer.needToReadable = true;
}
if (!valGrammer.dataType) {
debug.stack('Invalid GrammerValue.dataType', valGrammer, object);
}
return valGrammer;
}