visitDeclare()

in lib/generator.js [3404:3515]


  visitDeclare(ast, level, env) {
    var id = _name(ast.id);
    var expected = ast.expectedType || {};
    const expr = ast.expr;
    let varDealFunc, setFunc;
    if (expr.type === 'call') {
      var argHasThrowFunc = this.visitFunctionNested(expr, level, env);
    }
    
    var hasThrowCall = (expr.type === 'call' &&
      expr.hasThrow) || expr.type === 'construct';
    const yieldAssign = _isIterator(ast.expr.inferred) && ast.expr.type === 'call';
    env.yieldErrDeal = yieldAssign && !env.yieldFunc;
    if(yieldAssign) {
      this.emit(`${id} := make(chan `, level);
      this.visitType(ast.expr.inferred.valueType, level);
      this.emit(', 1)\n');
      if((!env.hasThrow && hasThrowCall) || (env.hasThrow && !env.yieldFunc)) {
        this.emit(`_yieldErr := make(chan error, 1)\n`, level);
      }

      ast.expr.args.push({
        yieldArg: true,
        ast: {
          left: {
            type: 'variable',
            id: ast.id
          },
          expr: ast.expr,
        },
      });
    } else {
      if (hasThrowCall) {
        varDealFunc = this.getVarDealFunc(expr, expected);
        let tmpName = id;
        if (varDealFunc) { 
          tmpName = tmpName + 'Tmp';
        }
        if(env && env.local) {
          env.local.set(tmpName, true);
        }
        this.emit(`${tmpName}, _err := `, level);
      } else if (expr.type === 'null') {
        this.emit(`var ${id} `, level);
        this.visitType(ast.expectedType, level);
        this.emit('\n');
        return;
      } else {
        this.emit(`${id} := `, level);
        
        if(expr && expr.type === 'call') {
          let dealFunc = this.getVarDealFunc(expr, expected);
          setFunc = dealFunc && dealFunc(_name(expr.inferred));
        }
        
        if(setFunc) {
          this.emit(`${setFunc}`);
        }
      }
    }
    expected.pointer = false;
    if (ast.expectedType) {
      if ((_name(ast.expectedType) === 'number' || _name(ast.expectedType) === 'integer') && expr.inferred.name === 'int32') {
        this.emit(`int(`);
        this.visitExpr(expr, level, env, expected, argHasThrowFunc);
        this.emit(`)`);
      } else if (
        (expr.type !== 'number' && (expr.inferred.name === 'number' || expr.inferred.name === 'integer') 
        || expr.type === 'number') && _name(ast.expectedType) === 'int32') {
        this.emit(`int32(`);
        this.visitExpr(expr, level, env, expected, argHasThrowFunc);
        this.emit(`)`);
      } else {
        this.visitExpr(expr, level, env, expected, argHasThrowFunc);
      }
    } else {
      this.visitExpr(expr, level, env, expected, argHasThrowFunc);
      if(setFunc) { 
        this.emit(')');
      }
    }
    this.emit('\n');

    if(varDealFunc) {
      this.emit(`${id} := `, level);
      this.emit(`${varDealFunc(_name(expr.inferred))}`);
      this.emit(`${id}Tmp)\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(`return\n`, level + 1);
        this.emit(`}\n\n`, level);
      } else if(env.try) {
        const tryStmt = env.try;
        env.try = null;
        this.visitCatch(tryStmt, level, env);
      } 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);
      }
    }
  }