From 8780bc0b8ebd3492c58f1ce221e0d87de170c6ac Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Mon, 7 Jul 2014 16:03:32 -0500 Subject: [PATCH] Better check for lib has only functions (fix #138) --- compile.c | 10 ++++++++++ compile.h | 2 ++ execute.c | 2 ++ opcode_list.h | 2 ++ parser.y | 10 +++++++--- 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/compile.c b/compile.c index 2a1b8b89..b3e58041 100644 --- a/compile.c +++ b/compile.c @@ -441,6 +441,16 @@ block gen_definedor(block a, block b) { tail); } +int block_has_main(block top) { + return top.first && top.first->op == TOP; +} + +int block_is_funcdef(block b) { + if (b.first != NULL && b.first->op == CLOSURE_CREATE) + return 1; + return 0; +} + block gen_condbranch(block iftrue, block iffalse) { iftrue = BLOCK(iftrue, gen_op_target(JUMP, iffalse)); return BLOCK(gen_op_target(JUMP_F, iftrue), iftrue, iffalse); diff --git a/compile.h b/compile.h index 0640a961..9ad732a2 100644 --- a/compile.h +++ b/compile.h @@ -48,6 +48,8 @@ block gen_cbinding(const struct cfunction* functions, int nfunctions, block b); void block_append(block* b, block b2); block block_join(block a, block b); int block_has_only_binders(block, int bindflags); +int block_has_main(block); +int block_is_funcdef(block b); block block_bind(block binder, block body, int bindflags); block block_bind_referenced(block binder, block body, int bindflags); diff --git a/execute.c b/execute.c index f384420e..7b8f8f8e 100644 --- a/execute.c +++ b/execute.c @@ -315,6 +315,8 @@ jv jq_next(jq_state *jq) { switch (opcode) { default: assert(0 && "invalid instruction"); + case TOP: break; + case LOADK: { jv v = jv_array_get(jv_copy(frame_current(jq)->bc->constants), *pc++); assert(jv_is_valid(v)); diff --git a/opcode_list.h b/opcode_list.h index b3b0f2e5..284c3686 100644 --- a/opcode_list.h +++ b/opcode_list.h @@ -34,3 +34,5 @@ OP(CLOSURE_PARAM, DEFINITION, 0, 0) OP(CLOSURE_REF, CLOSURE_REF_IMM, 0, 0) OP(CLOSURE_CREATE, DEFINITION, 0, 0) OP(CLOSURE_CREATE_C, DEFINITION, 0, 0) + +OP(TOP, NONE, 0, 0) diff --git a/parser.y b/parser.y index 7c53d285..6abcb473 100644 --- a/parser.y +++ b/parser.y @@ -206,7 +206,7 @@ static block gen_update(block object, block val, int optype) { %% TopLevel: Exp { - *answer = $1; + *answer = BLOCK(gen_op_simple(TOP), $1); } | FuncDefs { *answer = $1; @@ -222,7 +222,10 @@ FuncDef FuncDefs { Exp: FuncDef Exp %prec ';' { - $$ = block_bind($1, $2, OP_IS_CALL_PSEUDO); + if (block_is_funcdef($2)) + $$ = block_bind($1, $2, OP_IS_CALL_PSEUDO); + else + $$ = block_bind($1, BLOCK(gen_op_simple(TOP), $2), OP_IS_CALL_PSEUDO); } | Term "as" '$' IDENT '|' Exp { @@ -682,9 +685,10 @@ int jq_parse(struct locfile* locations, block* answer) { int jq_parse_library(struct locfile* locations, block* answer) { int errs = jq_parse(locations, answer); if (errs) return errs; - if (!block_has_only_binders(*answer, OP_IS_CALL_PSEUDO)) { + if (block_has_main(*answer)) { locfile_locate(locations, UNKNOWN_LOCATION, "error: library should only have function definitions, not a main expression"); return 1; } + assert(block_has_only_binders(*answer, OP_IS_CALL_PSEUDO)); return 0; }