diff --git a/base/base.jl b/base/base.jl index b53d127179183..8dc3e6f4ca11d 100644 --- a/base/base.jl +++ b/base/base.jl @@ -156,6 +156,14 @@ macro inbounds(blk) :(@boundscheck false $(esc(blk))) end +macro label(name::Symbol) + Expr(:symboliclabel, name) +end + +macro goto(name::Symbol) + Expr(:symbolicgoto, name) +end + # NOTE: Base shares Array with Core so we can add definitions to it Array{T,N}(::Type{T}, d::NTuple{N,Int}) = diff --git a/base/exports.jl b/base/exports.jl index 5e50c21823f6c..be33892215355 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1319,4 +1319,6 @@ export @sprintf, @deprecate, @boundscheck, - @inbounds + @inbounds, + @label, + @goto diff --git a/src/alloc.c b/src/alloc.c index 913966772e4e1..c5239ddc3ca1c 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -73,6 +73,7 @@ jl_sym_t *line_sym; jl_sym_t *jl_incomplete_sym; // head symbols for each expression type jl_sym_t *goto_sym; jl_sym_t *goto_ifnot_sym; jl_sym_t *label_sym; jl_sym_t *return_sym; +jl_sym_t *symboliclabel_sym; jl_sym_t *symbolicgoto_sym; jl_sym_t *lambda_sym; jl_sym_t *assign_sym; jl_sym_t *null_sym; jl_sym_t *body_sym; jl_sym_t *macro_sym; jl_sym_t *method_sym; diff --git a/src/interpreter.c b/src/interpreter.c index b7ef108e8f656..2be14732b6718 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -1,4 +1,5 @@ #include +#include #include #include #ifdef _OS_WINDOWS_ @@ -461,6 +462,25 @@ static int label_idx(jl_value_t *tgt, jl_array_t *stmts) return j; } +static int symboliclabel_idx(jl_value_t *tgt, jl_array_t *stmts) +{ + size_t j; + jl_sym_t* stgt = (jl_sym_t*)tgt; + assert(jl_is_symbol(tgt)); + for(j=0; j < stmts->nrows; j++) { + jl_value_t *l = jl_cellref(stmts,j); + if (jl_is_expr(l) && ((jl_expr_t*)l)->head == symboliclabel_sym) { + assert(jl_array_len(((jl_expr_t*)l)->args)); + jl_value_t* labeltgt = jl_cellref(((jl_expr_t*)l)->args, 0); + if (jl_is_symbol(labeltgt) && (jl_sym_t*)labeltgt == stgt) { + break; + } + } + } + assert(j < stmts->nrows); + return j; +} + jl_value_t *jl_toplevel_eval_body(jl_array_t *stmts) { return eval_body(stmts, NULL, 0, 0, 1); @@ -480,7 +500,13 @@ static jl_value_t *eval_body(jl_array_t *stmts, jl_value_t **locals, size_t nl, } if (jl_is_expr(stmt)) { jl_sym_t *head = ((jl_expr_t*)stmt)->head; - if (head == goto_ifnot_sym) { + if (head == symbolicgoto_sym) { + assert(jl_array_len(((jl_expr_t*)stmt)->args) == 1); + i = symboliclabel_idx(jl_cellref(((jl_expr_t*)stmt)->args, 0), + stmts); + continue; + } + else if (head == goto_ifnot_sym) { jl_value_t *cond = eval(jl_exprarg(stmt,0), locals, nl); if (cond == jl_false) { i = label_idx(jl_exprarg(stmt,1), stmts); diff --git a/src/jltypes.c b/src/jltypes.c index 42adf8fc167b0..4f518275b614a 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -3099,6 +3099,8 @@ void jl_init_types(void) goto_sym = jl_symbol("goto"); goto_ifnot_sym = jl_symbol("gotoifnot"); label_sym = jl_symbol("label"); + symboliclabel_sym = jl_symbol("symboliclabel"); + symbolicgoto_sym = jl_symbol("symbolicgoto"); return_sym = jl_symbol("return"); lambda_sym = jl_symbol("lambda"); macro_sym = jl_symbol("macro"); diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index fca5717b4ba73..0617e31ece72f 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2960,6 +2960,19 @@ So far only the second case can actually occur. (let ((l (make&mark-label))) (set! label-map (cons (cons (cadr e) l) label-map)))))) + ((symboliclabel) (let ((m (assq (cadr e) label-map))) + (if m + (emit `(label ,(cdr m))) + (let ((l (make&mark-label))) + (set! label-map + (cons (cons (cadr e) l) label-map)))))) + ((symbolicgoto) (let ((m (assq (cadr e) label-map))) + (if m + (emit `(goto ,(cdr m))) + (let ((l (make-label))) + (set! label-map + (cons (cons (cadr e) l) label-map)) + (emit `(goto ,l)))))) ((type_goto) (let ((m (assq (cadr e) label-map))) (if m (emit `(type_goto ,(cdr m) ,@(cddr e))) @@ -3128,11 +3141,11 @@ So far only the second case can actually occur. (define (resolve-expansion-vars- e env m inarg) (cond ((or (eq? e 'true) (eq? e 'false) (eq? e 'end)) e) - ((symbol? e) - (let ((a (assq e env))) - (if a (cdr a) - (if m `(|.| ,m (quote ,e)) - e)))) + ((symbol? e) + (let ((a (assq e env))) + (if a (cdr a) + (if m `(|.| ,m (quote ,e)) + e)))) ((or (not (pair? e)) (quoted? e)) e) (else @@ -3143,6 +3156,8 @@ So far only the second case can actually occur. `(macrocall ,.(map (lambda (x) (resolve-expansion-vars- x env m inarg)) (cdr e)))) + ((symboliclabel) e) + ((symbolicgoto) e) ((type) `(type ,(cadr e) ,(resolve-expansion-vars- (caddr e) env m inarg) ;; type has special behavior: identifiers inside are diff --git a/src/julia.h b/src/julia.h index f584069f1be19..e427d96815a98 100644 --- a/src/julia.h +++ b/src/julia.h @@ -415,6 +415,7 @@ extern jl_sym_t *export_sym; extern jl_sym_t *import_sym; extern jl_sym_t *importall_sym; extern jl_sym_t *using_sym; extern jl_sym_t *goto_sym; extern jl_sym_t *goto_ifnot_sym; extern jl_sym_t *label_sym; extern jl_sym_t *return_sym; +extern jl_sym_t *symboliclabel_sym; extern jl_sym_t *symbolicgoto_sym; extern jl_sym_t *lambda_sym; extern jl_sym_t *assign_sym; extern jl_sym_t *null_sym; extern jl_sym_t *body_sym; extern jl_sym_t *macro_sym; extern jl_sym_t *method_sym;