<commit_before>// Functions for building ASTs, without having to fuss with spans.
//
// To start with, it will be use dummy spans, but it might someday do
// something smarter.

use ast::{ident, node_id};
use ast_util::respan;
use codemap::span;
use ext::base::mk_ctxt;

// Transitional reexports so qquote can find the paths it is looking for
mod syntax {
    #[legacy_exports];
    pub use ext;
    pub use parse;
}

fn path(ids: ~[ident], span: span) -> @ast::path {
    @{span: span,
      global: false,
      idents: ids,
      rp: None,
      types: ~[]}
}

fn empty_span() -> span {
    {lo: 0, hi: 0, expn_info: None}
}

trait append_types {
    fn add_ty(ty: @ast::Ty) -> @ast::path;
    fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path;
}

impl @ast::path: append_types {
    fn add_ty(ty: @ast::Ty) -> @ast::path {
        @{types: vec::append_one(self.types, ty),
          .. *self}
    }

    fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path {
        @{types: vec::append(self.types, tys),
          .. *self}
    }
}

trait ext_ctxt_ast_builder {
    fn ty_param(id: ast::ident, +bounds: ~[ast::ty_param_bound])
        -> ast::ty_param;
    fn arg(name: ident, ty: @ast::Ty) -> ast::arg;
    fn expr_block(e: @ast::expr) -> ast::blk;
    fn fn_decl(+inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl;
    fn item(name: ident, span: span, +node: ast::item_) -> @ast::item;
    fn item_fn_poly(name: ident,
                    +inputs: ~[ast::arg],
                    output: @ast::Ty,
                    +ty_params: ~[ast::ty_param],
                    +body: ast::blk) -> @ast::item;
    fn item_fn(name: ident,
               +inputs: ~[ast::arg],
               output: @ast::Ty,
               +body: ast::blk) -> @ast::item;
    fn item_enum_poly(name: ident,
                      span: span,
                      +enum_definition: ast::enum_def,
                      +ty_params: ~[ast::ty_param]) -> @ast::item;
    fn item_enum(name: ident, span: span,
                 +enum_definition: ast::enum_def) -> @ast::item;
    fn variant(name: ident, span: span, +tys: ~[@ast::Ty]) -> ast::variant;
    fn item_mod(name: ident, span: span, +items: ~[@ast::item]) -> @ast::item;
    fn ty_path_ast_builder(path: @ast::path) -> @ast::Ty;
    fn item_ty_poly(name: ident,
                    span: span,
                    ty: @ast::Ty,
                    +params: ~[ast::ty_param]) -> @ast::item;
    fn item_ty(name: ident, span: span, ty: @ast::Ty) -> @ast::item;
    fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::Ty];
    fn ty_field_imm(name: ident, ty: @ast::Ty) -> ast::ty_field;
    fn ty_rec(+v: ~[ast::ty_field]) -> @ast::Ty;
    fn field_imm(name: ident, e: @ast::expr) -> ast::field;
    fn rec(+v: ~[ast::field]) -> @ast::expr;
    fn block(+stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk;
    fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt;
    fn stmt_expr(e: @ast::expr) -> @ast::stmt;
    fn block_expr(b: ast::blk) -> @ast::expr;
    fn empty_span() -> span;
    fn ty_option(ty: @ast::Ty) -> @ast::Ty;
}

impl ext_ctxt: ext_ctxt_ast_builder {
    fn ty_option(ty: @ast::Ty) -> @ast::Ty {
        self.ty_path_ast_builder(path(~[self.ident_of(~"Option")],
                                      self.empty_span())
                                 .add_ty(ty))
    }

    fn empty_span() -> span {
        {lo: 0, hi: 0, expn_info: self.backtrace()}
    }

    fn block_expr(b: ast::blk) -> @ast::expr {
        @{id: self.next_id(),
          callee_id: self.next_id(),
          node: ast::expr_block(b),
          span: self.empty_span()}
    }

    fn stmt_expr(e: @ast::expr) -> @ast::stmt {
        @{node: ast::stmt_expr(e, self.next_id()),
          span: self.empty_span()}
    }

    fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt {
        // If the quasiquoter could interpolate idents, this is all
        // we'd need.
        //
        //let ext_cx = self;
        //#ast[stmt] { let $(ident) = $(e) }

        @{node: ast::stmt_decl(@{node: ast::decl_local(~[
            @{node: {is_mutbl: false,
                     ty: self.ty_infer(),
                     pat: @{id: self.next_id(),
                            node: ast::pat_ident(ast::bind_by_implicit_ref,
                                                 path(~[ident],
                                                      self.empty_span()),
                                                 None),
                            span: self.empty_span()},
                     init: Some({op: ast::init_move,
                                 expr: e}),
                     id: self.next_id()},
              span: self.empty_span()}]),
                               span: self.empty_span()}, self.next_id()),
         span: self.empty_span()}
    }

    fn field_imm(name: ident, e: @ast::expr) -> ast::field {
        {node: {mutbl: ast::m_imm, ident: name, expr: e},
         span: self.empty_span()}
    }

    fn rec(+fields: ~[ast::field]) -> @ast::expr {
        @{id: self.next_id(),
          callee_id: self.next_id(),
          node: ast::expr_rec(fields, None),
          span: self.empty_span()}
    }

    fn ty_field_imm(name: ident, ty: @ast::Ty) -> ast::ty_field {
        {node: {ident: name, mt: { ty: ty, mutbl: ast::m_imm } },
          span: self.empty_span()}
    }

    fn ty_rec(+fields: ~[ast::ty_field]) -> @ast::Ty {
        @{id: self.next_id(),
          node: ast::ty_rec(fields),
          span: self.empty_span()}
    }

    fn ty_infer() -> @ast::Ty {<commit_msg>Don't generate move-by-init in AST builder<commit_after>// Functions for building ASTs, without having to fuss with spans.
//
// To start with, it will be use dummy spans, but it might someday do
// something smarter.

use ast::{ident, node_id};
use ast_util::respan;
use codemap::span;
use ext::base::mk_ctxt;

// Transitional reexports so qquote can find the paths it is looking for
mod syntax {
    #[legacy_exports];
    pub use ext;
    pub use parse;
}

fn path(ids: ~[ident], span: span) -> @ast::path {
    @{span: span,
      global: false,
      idents: ids,
      rp: None,
      types: ~[]}
}

fn empty_span() -> span {
    {lo: 0, hi: 0, expn_info: None}
}

trait append_types {
    fn add_ty(ty: @ast::Ty) -> @ast::path;
    fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path;
}

impl @ast::path: append_types {
    fn add_ty(ty: @ast::Ty) -> @ast::path {
        @{types: vec::append_one(self.types, ty),
          .. *self}
    }

    fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path {
        @{types: vec::append(self.types, tys),
          .. *self}
    }
}

trait ext_ctxt_ast_builder {
    fn ty_param(id: ast::ident, +bounds: ~[ast::ty_param_bound])
        -> ast::ty_param;
    fn arg(name: ident, ty: @ast::Ty) -> ast::arg;
    fn expr_block(e: @ast::expr) -> ast::blk;
    fn fn_decl(+inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl;
    fn item(name: ident, span: span, +node: ast::item_) -> @ast::item;
    fn item_fn_poly(name: ident,
                    +inputs: ~[ast::arg],
                    output: @ast::Ty,
                    +ty_params: ~[ast::ty_param],
                    +body: ast::blk) -> @ast::item;
    fn item_fn(name: ident,
               +inputs: ~[ast::arg],
               output: @ast::Ty,
               +body: ast::blk) -> @ast::item;
    fn item_enum_poly(name: ident,
                      span: span,
                      +enum_definition: ast::enum_def,
                      +ty_params: ~[ast::ty_param]) -> @ast::item;
    fn item_enum(name: ident, span: span,
                 +enum_definition: ast::enum_def) -> @ast::item;
    fn variant(name: ident, span: span, +tys: ~[@ast::Ty]) -> ast::variant;
    fn item_mod(name: ident, span: span, +items: ~[@ast::item]) -> @ast::item;
    fn ty_path_ast_builder(path: @ast::path) -> @ast::Ty;
    fn item_ty_poly(name: ident,
                    span: span,
                    ty: @ast::Ty,
                    +params: ~[ast::ty_param]) -> @ast::item;
    fn item_ty(name: ident, span: span, ty: @ast::Ty) -> @ast::item;
    fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::Ty];
    fn ty_field_imm(name: ident, ty: @ast::Ty) -> ast::ty_field;
    fn ty_rec(+v: ~[ast::ty_field]) -> @ast::Ty;
    fn field_imm(name: ident, e: @ast::expr) -> ast::field;
    fn rec(+v: ~[ast::field]) -> @ast::expr;
    fn block(+stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk;
    fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt;
    fn stmt_expr(e: @ast::expr) -> @ast::stmt;
    fn block_expr(b: ast::blk) -> @ast::expr;
    fn empty_span() -> span;
    fn ty_option(ty: @ast::Ty) -> @ast::Ty;
}

impl ext_ctxt: ext_ctxt_ast_builder {
    fn ty_option(ty: @ast::Ty) -> @ast::Ty {
        self.ty_path_ast_builder(path(~[self.ident_of(~"Option")],
                                      self.empty_span())
                                 .add_ty(ty))
    }

    fn empty_span() -> span {
        {lo: 0, hi: 0, expn_info: self.backtrace()}
    }

    fn block_expr(b: ast::blk) -> @ast::expr {
        @{id: self.next_id(),
          callee_id: self.next_id(),
          node: ast::expr_block(b),
          span: self.empty_span()}
    }

    fn move_expr(e: @ast::expr) -> @ast::expr {
        @{id: self.next_id(),
          callee_id: self.next_id(),
          node: ast::expr_unary_move(e),
          span: e.span}
    }

    fn stmt_expr(e: @ast::expr) -> @ast::stmt {
        @{node: ast::stmt_expr(e, self.next_id()),
          span: self.empty_span()}
    }

    fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt {
        // If the quasiquoter could interpolate idents, this is all
        // we'd need.
        //
        //let ext_cx = self;
        //#ast[stmt] { let $(ident) = $(e) }

        @{node: ast::stmt_decl(@{node: ast::decl_local(~[
            @{node: {is_mutbl: false,
                     ty: self.ty_infer(),
                     pat: @{id: self.next_id(),
                            node: ast::pat_ident(ast::bind_by_implicit_ref,
                                                 path(~[ident],
                                                      self.empty_span()),
                                                 None),
                            span: self.empty_span()},
                     init: Some(self.move_expr(e)),
                     id: self.next_id()},
              span: self.empty_span()}]),
                               span: self.empty_span()}, self.next_id()),
         span: self.empty_span()}
    }

    fn field_imm(name: ident, e: @ast::expr) -> ast::field {
        {node: {mutbl: ast::m_imm, ident: name, expr: e},
         span: self.empty_span()}
    }

    fn rec(+fields: ~[ast::field]) -> @ast::expr {
        @{id: self.next_id(),
          callee_id: self.next_id(),
          node: ast::expr_rec(fields, None),
          span: self.empty_span()}
    }

    fn ty_field_imm(name: ident, ty: @ast::Ty) -> ast::ty_field {
        {node: {ident: name, mt: { ty: ty, mutbl: ast::m_imm } },
          span: self.empty_span()}
    }

    fn ty_rec(+fields: ~[ast::ty_field]) -> @ast::Ty {
        @{id: self.next_id(),
          node: ast::ty_rec(fields),
          span: self.empty_span()}
    }

    fn ty_infer() -> @ast::Ty {
{'fraction_non_alphanumeric': 0.18190722108449828, 'fraction_numerical': 0.0007123141305315644, 'mean_word_length': 1.9706426871198095, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 86, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 17, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6704799', 'n_tokens_mistral': 3968, 'n_tokens_neox': 3869, 'n_words': 862}