Esempio n. 1
0
File: ast.c Progetto: ararslan/julia
JL_DLLEXPORT jl_value_t *jl_copy_ast(jl_value_t *expr)
{
    if (expr && jl_is_expr(expr)) {
        jl_expr_t *e = (jl_expr_t*)expr;
        size_t i, l = jl_array_len(e->args);
        jl_expr_t *ne = jl_exprn(e->head, l);
        JL_GC_PUSH2(&ne, &expr);
        for (i = 0; i < l; i++) {
            jl_value_t *a = jl_exprarg(e, i);
            jl_exprargset(ne, i, jl_copy_ast(a));
        }
        JL_GC_POP();
        return (jl_value_t*)ne;
    }
    return expr;
}
Esempio n. 2
0
jl_value_t *jl_resolve_globals(jl_value_t *expr, jl_lambda_info_t *lam)
{
    if (jl_is_symbol(expr)) {
        if (lam->def->module == NULL)
            return expr;
        return jl_module_globalref(lam->def->module, (jl_sym_t*)expr);
    }
    else if (jl_is_expr(expr)) {
        jl_expr_t *e = (jl_expr_t*)expr;
        if (jl_is_toplevel_only_expr(expr) || e->head == const_sym || e->head == copyast_sym ||
            e->head == global_sym || e->head == quote_sym || e->head == inert_sym ||
            e->head == line_sym || e->head == meta_sym || e->head == inbounds_sym ||
            e->head == boundscheck_sym || e->head == simdloop_sym) {
        }
        else {
            if (e->head == call_sym && jl_expr_nargs(e) == 3 && jl_is_quotenode(jl_exprarg(e,2)) &&
                lam->def->module != NULL) {
                // replace getfield(module_expr, :sym) with GlobalRef
                jl_value_t *s = jl_fieldref(jl_exprarg(e,2),0);
                jl_value_t *fe = jl_exprarg(e,0);
                if (jl_is_symbol(s) && jl_is_globalref(fe)) {
                    jl_value_t *f = jl_static_eval(fe, NULL, lam->def->module, lam, 0, 0);
                    if (f == jl_builtin_getfield) {
                        jl_value_t *me = jl_exprarg(e,1);
                        if (jl_is_globalref(me) ||
                            (jl_is_symbol(me) && jl_binding_resolved_p(lam->def->module, (jl_sym_t*)me))) {
                            jl_value_t *m = jl_static_eval(me, NULL, lam->def->module, lam, 0, 0);
                            if (m && jl_is_module(m))
                                return jl_module_globalref((jl_module_t*)m, (jl_sym_t*)s);
                        }
                    }
                }
            }
            size_t i = 0;
            if (e->head == method_sym || e->head == abstracttype_sym || e->head == compositetype_sym ||
                e->head == bitstype_sym || e->head == module_sym)
                i++;
            for(; i < jl_array_len(e->args); i++) {
                jl_exprargset(e, i, jl_resolve_globals(jl_exprarg(e,i), lam));
            }
        }
    }
    return expr;
}
Esempio n. 3
0
JL_DLLEXPORT jl_value_t *jl_copy_ast(jl_value_t *expr)
{
    if (expr == NULL) {
        return NULL;
    }
    else if (jl_is_expr(expr)) {
        jl_expr_t *e = (jl_expr_t*)expr;
        size_t i, l = jl_array_len(e->args);
        jl_expr_t *ne = NULL;
        JL_GC_PUSH2(&ne, &expr);
        ne = jl_exprn(e->head, l);
        if (l == 0) {
            ne->args = jl_alloc_vec_any(0);
            jl_gc_wb(ne, ne->args);
        }
        else {
            for(i=0; i < l; i++) {
                jl_exprargset(ne, i, jl_copy_ast(jl_exprarg(e,i)));
            }
        }
        JL_GC_POP();
        return (jl_value_t*)ne;
    }
    else if (jl_typeis(expr,jl_array_any_type)) {
        jl_array_t *a = (jl_array_t*)expr;
        size_t i, l = jl_array_len(a);
        jl_array_t *na = NULL;
        JL_GC_PUSH2(&na, &expr);
        na = jl_alloc_vec_any(l);
        for(i=0; i < l; i++)
            jl_array_ptr_set(na, i, jl_copy_ast(jl_array_ptr_ref(a,i)));
        JL_GC_POP();
        return (jl_value_t*)na;
    }
    return expr;
}
Esempio n. 4
0
File: ast.c Progetto: ararslan/julia
static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, struct macroctx_stack *macroctx, int onelevel)
{
    if (!expr || !jl_is_expr(expr))
        return expr;
    jl_expr_t *e = (jl_expr_t*)expr;
    if (e->head == inert_sym ||
        e->head == module_sym ||
        //e->head == toplevel_sym || // TODO: enable this once julia-expand-macroscope is fixed / removed
        e->head == meta_sym) {
        return expr;
    }
    if (e->head == quote_sym && jl_expr_nargs(e) == 1) {
        expr = jl_call_scm_on_ast("julia-bq-macro", jl_exprarg(e, 0), inmodule);
        JL_GC_PUSH1(&expr);
        if (macroctx) {
            // in a macro, `quote` also implies `escape`
            jl_expr_t *e2 = jl_exprn(escape_sym, 1);
            jl_array_ptr_set(e2->args, 0, expr);
            expr = (jl_value_t*)e2;
        }
        expr = jl_expand_macros(expr, inmodule, macroctx, onelevel);
        JL_GC_POP();
        return expr;
    }
    if (e->head == hygienicscope_sym && jl_expr_nargs(e) == 2) {
        struct macroctx_stack newctx;
        newctx.m = (jl_module_t*)jl_exprarg(e, 1);
        JL_TYPECHK(hygienic-scope, module, (jl_value_t*)newctx.m);
        newctx.parent = macroctx;
        jl_value_t *a = jl_exprarg(e, 0);
        jl_value_t *a2 = jl_expand_macros(a, inmodule, &newctx, onelevel);
        if (a != a2)
            jl_array_ptr_set(e->args, 0, a2);
        return expr;
    }
    if (e->head == macrocall_sym) {
        struct macroctx_stack newctx;
        newctx.m = macroctx ? macroctx->m : inmodule;
        newctx.parent = macroctx;
        jl_value_t *result = jl_invoke_julia_macro(e->args, inmodule, &newctx.m);
        jl_value_t *wrap = NULL;
        JL_GC_PUSH3(&result, &wrap, &newctx.m);
        // copy and wrap the result in `(hygienic-scope ,result ,newctx)
        if (jl_is_expr(result) && ((jl_expr_t*)result)->head == escape_sym)
            result = jl_exprarg(result, 0);
        else
            wrap = (jl_value_t*)jl_exprn(hygienicscope_sym, 2);
        result = jl_copy_ast(result);
        if (!onelevel)
            result = jl_expand_macros(result, inmodule, wrap ? &newctx : macroctx, onelevel);
        if (wrap) {
            jl_exprargset(wrap, 0, result);
            jl_exprargset(wrap, 1, newctx.m);
            result = wrap;
        }
        JL_GC_POP();
        return result;
    }
    if (e->head == escape_sym && macroctx) {
        macroctx = macroctx->parent;
    }

    size_t i;
    for (i = 0; i < jl_array_len(e->args); i++) {
        jl_value_t *a = jl_array_ptr_ref(e->args, i);
        jl_value_t *a2 = jl_expand_macros(a, inmodule, macroctx, onelevel);
        if (a != a2)
            jl_array_ptr_set(e->args, i, a2);
    }
    return expr;
}
Esempio n. 5
0
DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_value_t *bp_owner,
                                    jl_binding_t *bnd,
                                    jl_svec_t *argdata, jl_function_t *f, jl_value_t *isstaged,
                                    jl_value_t *call_func, int iskw)
{
    jl_module_t *module = (bnd ? bnd->owner : NULL);
    // argdata is svec({types...}, svec(typevars...))
    jl_tupletype_t *argtypes = (jl_tupletype_t*)jl_svecref(argdata,0);
    jl_svec_t *tvars = (jl_svec_t*)jl_svecref(argdata,1);
    jl_value_t *gf = NULL;
    JL_GC_PUSH4(&gf, &tvars, &argtypes, &f);

    if (bnd && bnd->value != NULL && !bnd->constp) {
        jl_errorf("cannot define function %s; it already has a value", bnd->name->name);
    }

    if (*bp != NULL) {
        gf = *bp;
        if (!jl_is_gf(gf)) {
            if (jl_is_datatype(gf)) {
                // DataType: define `call`, for backwards compat with outer constructors
                if (call_func == NULL)
                    call_func = (jl_value_t*)jl_module_call_func(jl_current_module);
                size_t na = jl_nparams(argtypes);
                jl_svec_t *newargtypes = jl_alloc_svec(1 + na);
                jl_lambda_info_t *new_linfo = NULL;
                JL_GC_PUSH2(&newargtypes, &new_linfo);
                new_linfo = jl_copy_lambda_info(f->linfo);
                f = jl_new_closure(f->fptr, f->env, new_linfo);
                size_t i=0;
                if (iskw) {
                    assert(na > 0);
                    // for kw sorter, keep container argument first
                    jl_svecset(newargtypes, 0, jl_tparam(argtypes, 0));
                    i++;
                }
                jl_svecset(newargtypes, i, jl_wrap_Type(gf));
                i++;
                for(; i < na+1; i++) {
                    jl_svecset(newargtypes, i, jl_tparam(argtypes, i-1));
                }
                argtypes = jl_apply_tuple_type(newargtypes);
                JL_GC_POP();
                gf = call_func;
                name = call_sym;
                // edit args, insert type first
                if (!jl_is_expr(f->linfo->ast)) {
                    f->linfo->ast = jl_uncompress_ast(f->linfo, f->linfo->ast);
                    jl_gc_wb(f->linfo, f->linfo->ast);
                }
                else {
                    // Do not mutate the original ast since it might
                    // be reused somewhere else
                    f->linfo->ast = jl_copy_ast(f->linfo->ast);
                    jl_gc_wb(f->linfo, f->linfo->ast);
                }
                jl_array_t *al = jl_lam_args((jl_expr_t*)f->linfo->ast);
                if (jl_array_len(al) == 0) {
                    al = jl_alloc_cell_1d(1);
                    jl_exprargset(f->linfo->ast, 0, (jl_value_t*)al);
                }
                else {
                    jl_array_grow_beg(al, 1);
                }
                if (iskw) {
                    jl_cellset(al, 0, jl_cellref(al, 1));
                    jl_cellset(al, 1, (jl_value_t*)jl_gensym());
                }
                else {
                    jl_cellset(al, 0, (jl_value_t*)jl_gensym());
                }
            }
            if (!jl_is_gf(gf)) {
                jl_errorf("cannot define function %s; it already has a value", name->name);
            }
        }
        if (iskw) {
            jl_methtable_t *mt = jl_gf_mtable(gf);
            assert(!module);
            module = mt->module;
            bp = (jl_value_t**)&mt->kwsorter;
            bp_owner = (jl_value_t*)mt;
            gf = *bp;
        }
    }

    // TODO
    size_t na = jl_nparams(argtypes);
    for(size_t i=0; i < na; i++) {
        jl_value_t *elt = jl_tparam(argtypes,i);
        if (!jl_is_type(elt) && !jl_is_typevar(elt)) {
            jl_lambda_info_t *li = f->linfo;
            jl_exceptionf(jl_argumenterror_type, "invalid type for argument %s in method definition for %s at %s:%d",
                          jl_lam_argname(li,i)->name, name->name, li->file->name, li->line);
        }
    }

    int ishidden = !!strchr(name->name, '#');
    for(size_t i=0; i < jl_svec_len(tvars); i++) {
        jl_value_t *tv = jl_svecref(tvars,i);
        if (!jl_is_typevar(tv))
            jl_type_error_rt(name->name, "method definition", (jl_value_t*)jl_tvar_type, tv);
        if (!ishidden && !type_contains((jl_value_t*)argtypes, tv)) {
            jl_printf(JL_STDERR, "WARNING: static parameter %s does not occur in signature for %s",
                      ((jl_tvar_t*)tv)->name->name, name->name);
            print_func_loc(JL_STDERR, f->linfo);
            jl_printf(JL_STDERR, ".\nThe method will not be callable.\n");
        }
    }

    if (bnd) {
        bnd->constp = 1;
    }
    if (*bp == NULL) {
        gf = (jl_value_t*)jl_new_generic_function(name, module);
        *bp = gf;
        if (bp_owner) jl_gc_wb(bp_owner, gf);
    }
    assert(jl_is_function(f));
    assert(jl_is_tuple_type(argtypes));
    assert(jl_is_svec(tvars));

    jl_add_method((jl_function_t*)gf, argtypes, f, tvars, isstaged == jl_true);
    if (jl_boot_file_loaded &&
        f->linfo && f->linfo->ast && jl_is_expr(f->linfo->ast)) {
        jl_lambda_info_t *li = f->linfo;
        li->ast = jl_compress_ast(li, li->ast);
        jl_gc_wb(li, li->ast);
    }
    JL_GC_POP();
    return gf;
}
Esempio n. 6
0
DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_value_t *bp_owner,
                                    jl_binding_t *bnd,
                                    jl_tuple_t *argtypes, jl_function_t *f, jl_value_t *isstaged,
                                    jl_value_t *call_func, int iskw)
{
    // argtypes is a tuple ((types...), (typevars...))
    jl_tuple_t *t = (jl_tuple_t*)jl_t1(argtypes);
    argtypes = (jl_tuple_t*)jl_t0(argtypes);
    jl_value_t *gf=NULL;
    JL_GC_PUSH3(&gf, &argtypes, &t);

    if (bnd && bnd->value != NULL && !bnd->constp) {
        jl_errorf("cannot define function %s; it already has a value", bnd->name->name);
    }

    if (*bp != NULL) {
        gf = *bp;
        if (!jl_is_gf(gf)) {
            if (jl_is_datatype(gf)) {
                // DataType: define `call`, for backwards compat with outer constructors
                if (call_func == NULL)
                    call_func = (jl_value_t*)jl_module_call_func(jl_current_module);
                size_t na = jl_tuple_len(argtypes);
                jl_tuple_t *newargtypes = jl_alloc_tuple(1 + na);
                JL_GC_PUSH1(&newargtypes);
                size_t i=0;
                if (iskw) {
                    assert(na > 0);
                    // for kw sorter, keep container argument first
                    jl_tupleset(newargtypes, 0, jl_tupleref(argtypes, 0));
                    i++;
                }
                jl_tupleset(newargtypes, i, jl_wrap_Type(gf));
                i++;
                for(; i < na+1; i++) {
                    jl_tupleset(newargtypes, i, jl_tupleref(argtypes, i-1));
                }
                argtypes = newargtypes;
                JL_GC_POP();
                gf = call_func;
                name = call_sym;
                // edit args, insert type first
                if (!jl_is_expr(f->linfo->ast)) {
                    f->linfo->ast = jl_uncompress_ast(f->linfo, f->linfo->ast);
                    gc_wb(f->linfo, f->linfo->ast);
                }
                jl_array_t *al = jl_lam_args((jl_expr_t*)f->linfo->ast);
                if (jl_array_len(al) == 0) {
                    al = jl_alloc_cell_1d(1);
                    jl_exprargset(f->linfo->ast, 0, (jl_value_t*)al);
                }
                else {
                    jl_array_grow_beg(al, 1);
                }
                if (iskw) {
                    jl_cellset(al, 0, jl_cellref(al, 1));
                    jl_cellset(al, 1, (jl_value_t*)jl_gensym());
                }
                else {
                    jl_cellset(al, 0, (jl_value_t*)jl_gensym());
                }
            }
            if (!jl_is_gf(gf)) {
                jl_errorf("cannot define function %s; it already has a value", name->name);
            }
        }
        if (iskw) {
            bp = (jl_value_t**)&((jl_methtable_t*)((jl_function_t*)gf)->env)->kwsorter;
            bp_owner = (jl_value_t*)((jl_function_t*)gf)->env;
            gf = *bp;
        }
    }

    size_t na = jl_tuple_len(argtypes);
    for(size_t i=0; i < na; i++) {
        jl_value_t *elt = jl_tupleref(argtypes,i);
        if (!jl_is_type(elt) && !jl_is_typevar(elt)) {
            jl_lambda_info_t *li = f->linfo;
            jl_exceptionf(jl_argumenterror_type, "invalid type for argument %s in method definition for %s at %s:%d",
                          jl_lam_argname(li,i)->name, name->name, li->file->name, li->line);
        }
    }

    int ishidden = !!strchr(name->name, '#');
    for(size_t i=0; i < jl_tuple_len(t); i++) {
        jl_value_t *tv = jl_tupleref(t,i);
        if (!jl_is_typevar(tv))
            jl_type_error_rt(name->name, "method definition", (jl_value_t*)jl_tvar_type, tv);
        if (!ishidden && !type_contains((jl_value_t*)argtypes, tv)) {
            jl_printf(JL_STDERR, "Warning: static parameter %s does not occur in signature for %s",
                      ((jl_tvar_t*)tv)->name->name, name->name);
            print_func_loc(JL_STDERR, f->linfo);
            jl_printf(JL_STDERR, ".\nThe method will not be callable.\n");
        }
    }

    if (bnd) {
        bnd->constp = 1;
    }
    if (*bp == NULL) {
        gf = (jl_value_t*)jl_new_generic_function(name);
        *bp = gf;
        if (bp_owner) gc_wb(bp_owner, gf);
    }
    assert(jl_is_function(f));
    assert(jl_is_tuple(argtypes));
    assert(jl_is_tuple(t));

    jl_add_method((jl_function_t*)gf, argtypes, f, t, isstaged == jl_true);
    if (jl_boot_file_loaded &&
        f->linfo && f->linfo->ast && jl_is_expr(f->linfo->ast)) {
        jl_lambda_info_t *li = f->linfo;
        li->ast = jl_compress_ast(li, li->ast);
        gc_wb(li, li->ast);
    }
    JL_GC_POP();
    return gf;
}
Esempio n. 7
0
jl_value_t *jl_resolve_globals(jl_value_t *expr, jl_module_t *module, jl_svec_t *sparam_vals)
{
    if (jl_is_symbol(expr)) {
        if (module == NULL)
            return expr;
        return jl_module_globalref(module, (jl_sym_t*)expr);
    }
    else if (jl_is_expr(expr)) {
        jl_expr_t *e = (jl_expr_t*)expr;
        if (e->head == global_sym) {
            // execute the side-effects of "global x" decl immediately:
            // creates uninitialized mutable binding in module for each global
            jl_toplevel_eval_flex(module, expr, 0, 1);
            expr = jl_nothing;
        }
        if (jl_is_toplevel_only_expr(expr) || e->head == const_sym || e->head == copyast_sym ||
            e->head == quote_sym || e->head == inert_sym ||
            e->head == meta_sym || e->head == inbounds_sym ||
            e->head == boundscheck_sym || e->head == simdloop_sym) {
            // ignore these
        }
        else {
            if (e->head == call_sym && jl_expr_nargs(e) == 3 &&
                    jl_is_quotenode(jl_exprarg(e, 2)) && module != NULL) {
                // replace getfield(module_expr, :sym) with GlobalRef
                jl_value_t *s = jl_fieldref(jl_exprarg(e, 2), 0);
                jl_value_t *fe = jl_exprarg(e, 0);
                if (jl_is_symbol(s) && jl_is_globalref(fe)) {
                    jl_binding_t *b = jl_get_binding(jl_globalref_mod(fe), jl_globalref_name(fe));
                    jl_value_t *f = NULL;
                    if (b && b->constp) {
                        f = b->value;
                    }
                    if (f == jl_builtin_getfield) {
                        jl_value_t *me = jl_exprarg(e, 1);
                        jl_module_t *me_mod = NULL;
                        jl_sym_t *me_sym = NULL;
                        if (jl_is_globalref(me)) {
                            me_mod = jl_globalref_mod(me);
                            me_sym = jl_globalref_name(me);
                        }
                        else if (jl_is_symbol(me) && jl_binding_resolved_p(module, (jl_sym_t*)me)) {
                            me_mod = module;
                            me_sym = (jl_sym_t*)me;
                        }
                        if (me_mod && me_sym) {
                            jl_binding_t *b = jl_get_binding(me_mod, me_sym);
                            if (b && b->constp) {
                                jl_value_t *m = b->value;
                                if (m && jl_is_module(m)) {
                                    return jl_module_globalref((jl_module_t*)m, (jl_sym_t*)s);
                                }
                            }
                        }
                    }
                }
            }
            size_t i = 0, nargs = jl_array_len(e->args);
            if (e->head == foreigncall_sym) {
                JL_NARGSV(ccall method definition, 5); // (fptr, rt, at, cc, narg)
                jl_value_t *rt = jl_exprarg(e, 1);
                jl_value_t *at = jl_exprarg(e, 2);
                if (!jl_is_type(rt)) {
                    JL_TRY {
                        rt = jl_interpret_toplevel_expr_in(module, rt, NULL, sparam_vals);
                    }
                    JL_CATCH {
                        if (jl_typeis(jl_exception_in_transit, jl_errorexception_type))
                            jl_error("could not evaluate ccall return type (it might depend on a local variable)");
                        else
                            jl_rethrow();
                    }
                    jl_exprargset(e, 1, rt);
                }
                if (!jl_is_svec(at)) {
                    JL_TRY {
                        at = jl_interpret_toplevel_expr_in(module, at, NULL, sparam_vals);
                    }
                    JL_CATCH {
                        if (jl_typeis(jl_exception_in_transit, jl_errorexception_type))
                            jl_error("could not evaluate ccall argument type (it might depend on a local variable)");
                        else
                            jl_rethrow();
                    }
                    jl_exprargset(e, 2, at);
                }
                if (jl_is_svec(rt))
                    jl_error("ccall: missing return type");
                JL_TYPECHK(ccall method definition, type, rt);
                JL_TYPECHK(ccall method definition, simplevector, at);
                JL_TYPECHK(ccall method definition, quotenode, jl_exprarg(e, 3));
                JL_TYPECHK(ccall method definition, symbol, *(jl_value_t**)jl_exprarg(e, 3));
                JL_TYPECHK(ccall method definition, long, jl_exprarg(e, 4));
            }