Skip to content

Commit

Permalink
Add labels and gotos. (Fixes JuliaLang#101)
Browse files Browse the repository at this point in the history
  • Loading branch information
dcjones authored and mauro3 committed Jun 19, 2014
1 parent 5da7358 commit cb8620b
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 7 deletions.
8 changes: 8 additions & 0 deletions base/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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}) =
Expand Down
4 changes: 3 additions & 1 deletion base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1357,4 +1357,6 @@ export
@deprecate,
@boundscheck,
@inbounds,
@simd
@simd,
@label,
@goto
1 change: 1 addition & 0 deletions src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
28 changes: 27 additions & 1 deletion src/interpreter.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>
#include <assert.h>
#ifdef _OS_WINDOWS_
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
25 changes: 20 additions & 5 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit cb8620b

Please sign in to comment.