visitAssign()

in lib/generator.js [3276:3391]


  visitAssign(ast, level, env) {
    assert.equal(ast.type, 'assign');
    let pointer = false;
    let newVar = false;
    let setFunc;
    var hasThrowCall = (ast.expr.type === 'call' &&
      ast.expr.hasThrow) || ast.expr.type === 'construct';
    const yieldAssign = _isIterator(ast.expr.inferred) && ast.expr.type === 'call';
    env.yieldErrDeal = yieldAssign && !env.yieldFunc;
    if(yieldAssign) {
      ast.expr.args.push({
        yieldArg: true,
        ast,
      });
    } else {
      if (ast.left.type === 'property_assign' || ast.left.type === 'property') {
        this.emit(``, level);
        pointer = true;
        this.visitPropertyAccess(ast.left, level, env, { needCast: 'false', type: 'pointer', pointer });
      } else if (ast.left.type === 'variable') {
        const name = _name(ast.left.id);
        pointer = env.pointerParams && env.pointerParams.includes(name);
        this.emit(`${name}`, level);
        if(hasThrowCall){
          let dealFunc = this.getVarDealFunc(ast.expr,  { pointer });
          setFunc = dealFunc && dealFunc(_name(ast.expr.inferred));
          if(setFunc) {
            this.emit('Tmp');
            if(!env || !env.local || !env.local.has(`${name}Tmp`)) {
              newVar = true;
            }
          }
        }
      } else if (ast.left.type === 'virtualVariable') {
        pointer = true;
        this.emit(`${_vid(_avoidVariableKeywords(_format(_name(ast.left.vid))))}`, level);
      } else if (ast.left.type === 'map_access') {
        this.emit(``, level);
        pointer = true;
        this.visitMapAccess(ast.left, level, env, { pointer });
      } else if (ast.left.type === 'array_access') {
        this.emit(``, level);
        pointer = true;
        this.visitArrayAccess(ast.left, level, env, { pointer });
      } else {
        throw new Error('unimpelemented');
      }
  
      if (hasThrowCall) {
        this.emit(`, _err ${newVar ? ':' : ''}= `);
      } else {
        this.emit(` = `);
      }
    }

    if (ast.expr.needToReadable) {
      this.emit(`dara.ToReader(`);
      this.visitExpr(ast.expr, level, env, { needCast: 'false', pointer: true });
      this.emit(`)`);
    } else if (ast.expr.type === 'object' && ast.left.inferred &&
      ast.left.inferred.type === 'map' &&
      _name(ast.left.inferred.valueType) === 'any') {
      this.visitObject(ast.expr, level, env, 'map[string]interface{}');
    } else {
      if ((ast.left.inferred.name === 'number' || ast.left.inferred.name === 'integer') && ast.expr.inferred.name === 'int32') {
        this.emit(`${pointer ? 'dara.ToInt(' : 'int('}`);
        this.visitExpr(ast.expr, level, env, { pointer });
        this.emit(`)`);
      } else if (ast.expr.type !== 'number' && (ast.expr.inferred.name === 'number' || ast.expr.inferred.name === 'integer') && ast.left.inferred.name === 'int32') {
        this.emit(`${pointer ? 'dara.ToInt32(' : 'int32('}`);
        this.visitExpr(ast.expr, level, env, { pointer });
        this.emit(`)`);
      } else if(ast.expr.type === 'call'){
        if(hasThrowCall && ast.left.type === 'variable') {
          this.visitExpr(ast.expr, level, env, { pointer });
          if(setFunc) {
            this.emit('\n');
            let name = _name(ast.left.id);
            this.emit(`${name} = ${setFunc}${name}Tmp)`, level);
          }
        } else {
          let dealFunc = this.getVarDealFunc(ast.expr,  { pointer });
          setFunc = dealFunc && dealFunc(_name(ast.expr.inferred));
          if(setFunc) {
            this.emit(`${setFunc}`);
          }

          this.visitExpr(ast.expr, level, env, { pointer });

          if(setFunc) { 
            this.emit(')');
          }
        }
      } else {
        this.visitExpr(ast.expr, level, env, { pointer });
      }
    }
    this.emit(`\n`);
    if (hasThrowCall && !yieldAssign) {
      if(env.runtimeBody){
        this.visitAPIErrCatch(level, env);
      } else if(env.yieldFunc) {
        this.emit(`if _err != nil {\n`, level);
        this.emit(`_yieldErr <- _err\n`, level + 1);
        this.emit(`}\n\n`, level);
      } else if (env.returnType && _name(env.returnType) !== 'void') {
        this.emit(`if _err != nil {\n`, level);
        this.emit(`return _result, _err\n`, level + 1);
        this.emit(`}\n\n`, level);
      } else {
        this.emit(`if _err != nil {\n`, level);
        this.emit(`return _err\n`, level + 1);
        this.emit(`}\n\n`, level);
      }
    }
  }