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 committed Feb 25, 2014
1 parent 7975b98 commit f6fdb83
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 8 deletions.
8 changes: 8 additions & 0 deletions base/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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}) =
Expand Down
4 changes: 3 additions & 1 deletion base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1303,4 +1303,6 @@ export
@sprintf,
@deprecate,
@boundscheck,
@inbounds
@inbounds,
@label,
@goto
7 changes: 7 additions & 0 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,13 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int)
print(io, "))")
end

show_unquoted(io::IO, ex::LineNumberNode) = show_linenumber(io, ex.line)
show_unquoted(io::IO, ex::LabelNode) = print(io, ex.label, ": ")
show_unquoted(io::IO, ex::GotoNode) = print(io, "goto ", ex.label)
show_unquoted(io::IO, ex::TopNode) = print(io, "top(", ex.name, ')')
show_unquoted(io::IO, ex::QuoteNode, ind::Int) = show_indented(io,ex.value,ind)
function show_unquoted(io::IO, ex::SymbolNode)
print(io, ex.name)
show_expr_type(io, ex.typ)
end

Expand Down
1 change: 1 addition & 0 deletions src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -1216,7 +1216,7 @@ void jl_init_serializer(void)
jl_box_int32(51), jl_box_int32(52), jl_box_int32(53),
jl_box_int32(54), jl_box_int32(55), jl_box_int32(56),
jl_box_int32(57), jl_box_int32(58), jl_box_int32(59),
jl_box_int32(60), jl_box_int32(61),
jl_box_int32(60), jl_box_int32(61)

This comment has been minimized.

Copy link
@kmsquire

kmsquire Feb 26, 2014

Is this intentional? It looks like the comma still belongs there.

This comment has been minimized.

Copy link
@dcjones

dcjones Feb 26, 2014

Author Owner

Not intentional, thanks for catching that.

#endif
jl_box_int64(0), jl_box_int64(1), jl_box_int64(2),
jl_box_int64(3), jl_box_int64(4), jl_box_int64(5),
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 @@ -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);
Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2905,6 +2905,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 @@ -2942,6 +2942,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 @@ -3103,11 +3116,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 @@ -3118,6 +3131,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
3 changes: 3 additions & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -515,6 +516,8 @@ extern jl_sym_t *boundscheck_sym; extern jl_sym_t *copyast_sym;
#define jl_is_getfieldnode(v) jl_typeis(v,jl_getfieldnode_type)
#define jl_is_labelnode(v) jl_typeis(v,jl_labelnode_type)
#define jl_is_gotonode(v) jl_typeis(v,jl_gotonode_type)
#define jl_is_symboliclabelnode(v) jl_typeis(v,jl_symboliclabelnode_type)
#define jl_is_symbolicgotonode(v) jl_typeis(v,jl_symbolicgotonode_type)
#define jl_is_quotenode(v) jl_typeis(v,jl_quotenode_type)
#define jl_is_newvarnode(v) jl_typeis(v,jl_newvarnode_type)
#define jl_is_topnode(v) jl_typeis(v,jl_topnode_type)
Expand Down

0 comments on commit f6fdb83

Please sign in to comment.