From cb8620b1ff3bf267a22dcb8db15f0f7e48783d1d Mon Sep 17 00:00:00 2001 From: Daniel Jones Date: Wed, 5 Feb 2014 21:19:34 -0800 Subject: [PATCH] Add labels and gotos. (Fixes #101) --- base/base.jl | 8 ++++++++ base/exports.jl | 4 +++- src/alloc.c | 1 + src/interpreter.c | 28 +++++++++++++++++++++++++++- src/jltypes.c | 2 ++ src/julia-syntax.scm | 25 ++++++++++++++++++++----- src/julia.h | 1 + 7 files changed, 62 insertions(+), 7 deletions(-) diff --git a/base/base.jl b/base/base.jl index f68f5dce25b1b3..29816e8b327e96 100644 --- a/base/base.jl +++ b/base/base.jl @@ -203,6 +203,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 317baac6352425..b5054468606e17 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1357,4 +1357,6 @@ export @deprecate, @boundscheck, @inbounds, - @simd + @simd, + @label, + @goto diff --git a/src/alloc.c b/src/alloc.c index 1c59431460a5fe..b6ed6f90ce83f3 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -77,6 +77,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 4587803921c9e3..a4d80218e816d1 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -1,4 +1,5 @@ #include +#include #include #include #ifdef _OS_WINDOWS_ @@ -470,6 +471,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); @@ -489,7 +509,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 858686d9ff87f7..4f90ab96cb094a 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -3224,6 +3224,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 e4381831fa6d43..e25c977c5b16b0 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2996,6 +2996,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))) @@ -3164,11 +3177,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 @@ -3179,6 +3192,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 8de35e900a5e25..42be62a1e4f4bc 100644 --- a/src/julia.h +++ b/src/julia.h @@ -414,6 +414,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;