implemented switch ... case .. default ..
This commit is contained in:
parent
846cbcf951
commit
fac4aa7af5
22
README.md
22
README.md
@ -476,7 +476,9 @@ The following words are reserved and cannot be used as a variable name, a parame
|
|||||||
- BEGIN
|
- BEGIN
|
||||||
- END
|
- END
|
||||||
- break
|
- break
|
||||||
|
- case
|
||||||
- continue
|
- continue
|
||||||
|
- default
|
||||||
- delete
|
- delete
|
||||||
- do
|
- do
|
||||||
- else
|
- else
|
||||||
@ -494,6 +496,7 @@ The following words are reserved and cannot be used as a variable name, a parame
|
|||||||
- printf
|
- printf
|
||||||
- return
|
- return
|
||||||
- while
|
- while
|
||||||
|
- switch
|
||||||
|
|
||||||
However, some of these words not beginning with `@` can be used as normal names in the context of a module call. For example, `mymod::break`. In practice, the predefined names used for built-in commands, functions, and variables are treated as if they are reserved since you can't create another definition with the same name.
|
However, some of these words not beginning with `@` can be used as normal names in the context of a module call. For example, `mymod::break`. In practice, the predefined names used for built-in commands, functions, and variables are treated as if they are reserved since you can't create another definition with the same name.
|
||||||
|
|
||||||
@ -633,7 +636,7 @@ BEGIN {
|
|||||||
|
|
||||||
Hawk supports various control structures for flow control and iteration, similar to those found in awk.
|
Hawk supports various control structures for flow control and iteration, similar to those found in awk.
|
||||||
|
|
||||||
The `if` statement in Hawk follows the same syntax as in awk and other programming languages. It allows you to execute a block of code conditionally based on a specified condition.
|
The `if` statement follows the same syntax as in awk and other programming languages. It allows you to execute a block of code conditionally based on a specified condition.
|
||||||
|
|
||||||
```awk
|
```awk
|
||||||
if (condition) {
|
if (condition) {
|
||||||
@ -645,7 +648,18 @@ if (condition) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The `while` loop in Hawk is used to repeatedly execute a block of code as long as a specific condition is true.
|
The `switch` statement allows the result of an expression to be tested against a list of values.
|
||||||
|
```awk
|
||||||
|
switch (expression) {
|
||||||
|
case value:
|
||||||
|
## statements
|
||||||
|
...
|
||||||
|
default:
|
||||||
|
## statements
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `while` loop is used to repeatedly execute a block of code as long as a specific condition is true.
|
||||||
```awk
|
```awk
|
||||||
while (condition) {
|
while (condition) {
|
||||||
# statements
|
# statements
|
||||||
@ -659,13 +673,13 @@ do {
|
|||||||
} while (condition)
|
} while (condition)
|
||||||
```
|
```
|
||||||
|
|
||||||
The `for` loop in Hawk follows the same syntax as in awk and allows you to iterate over a range of values or an array.
|
The `for` loop follows the same syntax as in awk and allows you to iterate over a range of values or an array.
|
||||||
```awk
|
```awk
|
||||||
for (initialization; condition; increment/decrement) {
|
for (initialization; condition; increment/decrement) {
|
||||||
## statements
|
## statements
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
You can also use the for loop to iterate over the elements of an array:
|
You can also use the `fo`r loop to iterate over the elements of an array:
|
||||||
```awk
|
```awk
|
||||||
for (index in array) {
|
for (index in array) {
|
||||||
## statements using array[index]
|
## statements using array[index]
|
||||||
|
@ -539,6 +539,15 @@ static void print_usage (FILE* out, const hawk_bch_t* argv0, const hawk_bch_t* r
|
|||||||
{
|
{
|
||||||
fprintf (out, " --%-18s on/off %s\n", opttab[j].name, opttab[j].desc);
|
fprintf (out, " --%-18s on/off %s\n", opttab[j].name, opttab[j].desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!real_argv0)
|
||||||
|
{
|
||||||
|
fprintf (out, "\n");
|
||||||
|
fprintf (out, "Special mode switching options(must be specified first to take effect):\n");
|
||||||
|
fprintf (out, " --hawk/--awk run in the hawk mode\n");
|
||||||
|
fprintf (out, " --cut run in the cut mode\n");
|
||||||
|
fprintf (out, " --sed run in the sed mode\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
@ -76,6 +76,7 @@ const hawk_ooch_t* hawk_dfl_errstr (hawk_errnum_t errnum)
|
|||||||
HAWK_T("left brace expected"),
|
HAWK_T("left brace expected"),
|
||||||
HAWK_T("left parenthesis expected"),
|
HAWK_T("left parenthesis expected"),
|
||||||
HAWK_T("right parenthesis expected"),
|
HAWK_T("right parenthesis expected"),
|
||||||
|
HAWK_T("right brace expected"),
|
||||||
HAWK_T("right bracket expected"),
|
HAWK_T("right bracket expected"),
|
||||||
HAWK_T("comma expected"),
|
HAWK_T("comma expected"),
|
||||||
HAWK_T("semicolon expected"),
|
HAWK_T("semicolon expected"),
|
||||||
@ -88,6 +89,8 @@ const hawk_ooch_t* hawk_dfl_errstr (hawk_errnum_t errnum)
|
|||||||
|
|
||||||
HAWK_T("keyword 'function' expected"),
|
HAWK_T("keyword 'function' expected"),
|
||||||
HAWK_T("keyword 'while' expected"),
|
HAWK_T("keyword 'while' expected"),
|
||||||
|
HAWK_T("keyword 'case' expected"),
|
||||||
|
HAWK_T("multiple 'default' labels"),
|
||||||
HAWK_T("invalid assignment statement"),
|
HAWK_T("invalid assignment statement"),
|
||||||
HAWK_T("identifier expected"),
|
HAWK_T("identifier expected"),
|
||||||
HAWK_T("not a valid function name"),
|
HAWK_T("not a valid function name"),
|
||||||
|
@ -940,6 +940,7 @@ enum hawk_errnum_t
|
|||||||
HAWK_ELBRACE, /**< left brace expected */
|
HAWK_ELBRACE, /**< left brace expected */
|
||||||
HAWK_ELPAREN, /**< left parenthesis expected */
|
HAWK_ELPAREN, /**< left parenthesis expected */
|
||||||
HAWK_ERPAREN, /**< right parenthesis expected */
|
HAWK_ERPAREN, /**< right parenthesis expected */
|
||||||
|
HAWK_ERBRACE, /**< right brace expected */
|
||||||
HAWK_ERBRACK, /**< right bracket expected */
|
HAWK_ERBRACK, /**< right bracket expected */
|
||||||
HAWK_ECOMMA, /**< comma expected */
|
HAWK_ECOMMA, /**< comma expected */
|
||||||
HAWK_ESCOLON, /**< semicolon expected */
|
HAWK_ESCOLON, /**< semicolon expected */
|
||||||
@ -952,6 +953,8 @@ enum hawk_errnum_t
|
|||||||
|
|
||||||
HAWK_EKWFNC, /**< keyword 'function' expected */
|
HAWK_EKWFNC, /**< keyword 'function' expected */
|
||||||
HAWK_EKWWHL, /**< keyword 'while' expected */
|
HAWK_EKWWHL, /**< keyword 'while' expected */
|
||||||
|
HAWK_EKWCASE, /**< keyword 'case' expected */
|
||||||
|
HAWK_EMULDFL, /**< multiple 'default' labels */
|
||||||
HAWK_EASSIGN, /**< assignment statement expected */
|
HAWK_EASSIGN, /**< assignment statement expected */
|
||||||
HAWK_EIDENT, /**< identifier expected */
|
HAWK_EIDENT, /**< identifier expected */
|
||||||
HAWK_EFUNNAM, /**< not a valid function name */
|
HAWK_EFUNNAM, /**< not a valid function name */
|
||||||
|
@ -278,6 +278,7 @@ struct hawk_t
|
|||||||
hawk_oow_t loop;
|
hawk_oow_t loop;
|
||||||
hawk_oow_t expr; /* expression */
|
hawk_oow_t expr; /* expression */
|
||||||
hawk_oow_t incl;
|
hawk_oow_t incl;
|
||||||
|
hawk_oow_t swtch; /* switch */
|
||||||
} depth;
|
} depth;
|
||||||
|
|
||||||
/* current pragma values */
|
/* current pragma values */
|
||||||
|
@ -398,6 +398,8 @@ enum hawk_nde_type_t
|
|||||||
/* statement */
|
/* statement */
|
||||||
HAWK_NDE_BLK,
|
HAWK_NDE_BLK,
|
||||||
HAWK_NDE_IF,
|
HAWK_NDE_IF,
|
||||||
|
HAWK_NDE_SWITCH,
|
||||||
|
HAWK_NDE_CASE,
|
||||||
HAWK_NDE_WHILE,
|
HAWK_NDE_WHILE,
|
||||||
HAWK_NDE_DOWHILE,
|
HAWK_NDE_DOWHILE,
|
||||||
HAWK_NDE_FOR,
|
HAWK_NDE_FOR,
|
||||||
|
@ -41,7 +41,9 @@ enum hawk_kwid_t
|
|||||||
HAWK_KWID_BEGIN,
|
HAWK_KWID_BEGIN,
|
||||||
HAWK_KWID_END,
|
HAWK_KWID_END,
|
||||||
HAWK_KWID_BREAK,
|
HAWK_KWID_BREAK,
|
||||||
|
HAWK_KWID_CASE,
|
||||||
HAWK_KWID_CONTINUE,
|
HAWK_KWID_CONTINUE,
|
||||||
|
HAWK_KWID_DEFAULT,
|
||||||
HAWK_KWID_DELETE,
|
HAWK_KWID_DELETE,
|
||||||
HAWK_KWID_DO,
|
HAWK_KWID_DO,
|
||||||
HAWK_KWID_ELSE,
|
HAWK_KWID_ELSE,
|
||||||
@ -58,6 +60,7 @@ enum hawk_kwid_t
|
|||||||
HAWK_KWID_PRINT,
|
HAWK_KWID_PRINT,
|
||||||
HAWK_KWID_PRINTF,
|
HAWK_KWID_PRINTF,
|
||||||
HAWK_KWID_RETURN,
|
HAWK_KWID_RETURN,
|
||||||
|
HAWK_KWID_SWITCH,
|
||||||
HAWK_KWID_WHILE
|
HAWK_KWID_WHILE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
288
lib/parse.c
288
lib/parse.c
@ -35,10 +35,13 @@
|
|||||||
#define FMT_EKWFNC HAWK_T("keyword 'function' expected in place of '%.*js'")
|
#define FMT_EKWFNC HAWK_T("keyword 'function' expected in place of '%.*js'")
|
||||||
#define FMT_EKWIN HAWK_T("keyword 'in' expected in place of '%.*js'")
|
#define FMT_EKWIN HAWK_T("keyword 'in' expected in place of '%.*js'")
|
||||||
#define FMT_EKWWHL HAWK_T("keyword 'while' expected in place of '%.*js'")
|
#define FMT_EKWWHL HAWK_T("keyword 'while' expected in place of '%.*js'")
|
||||||
|
#define FMT_EKWCASE HAWK_T("keyword 'case' expected in place of '%.*js'")
|
||||||
|
#define FMT_EMULDFL HAWK_T("multiple '%.*js' labels")
|
||||||
#define FMT_ELBRACE HAWK_T("left brace expected in place of '%.*js'")
|
#define FMT_ELBRACE HAWK_T("left brace expected in place of '%.*js'")
|
||||||
#define FMT_ELPAREN HAWK_T("left parenthesis expected in place of '%.*js'")
|
#define FMT_ELPAREN HAWK_T("left parenthesis expected in place of '%.*js'")
|
||||||
#define FMT_ENOENT_GBL_HS HAWK_T("no such global variable - %.*hs")
|
#define FMT_ENOENT_GBL_HS HAWK_T("no such global variable - %.*hs")
|
||||||
#define FMT_ENOENT_GBL_LS HAWK_T("no such global variable - %.*ls")
|
#define FMT_ENOENT_GBL_LS HAWK_T("no such global variable - %.*ls")
|
||||||
|
#define FMT_ERBRACE HAWK_T("right brace expected in place of '%.*js'")
|
||||||
#define FMT_ERBRACK HAWK_T("right bracket expected in place of '%.*js'")
|
#define FMT_ERBRACK HAWK_T("right bracket expected in place of '%.*js'")
|
||||||
#define FMT_ERPAREN HAWK_T("right parenthesis expected in place of '%.*js'")
|
#define FMT_ERPAREN HAWK_T("right parenthesis expected in place of '%.*js'")
|
||||||
#define FMT_ESCOLON HAWK_T("semicolon expected in place of '%.*js'")
|
#define FMT_ESCOLON HAWK_T("semicolon expected in place of '%.*js'")
|
||||||
@ -48,6 +51,8 @@
|
|||||||
|
|
||||||
#define TOK_FLAGS_LPAREN_CLOSER (1 << 0)
|
#define TOK_FLAGS_LPAREN_CLOSER (1 << 0)
|
||||||
|
|
||||||
|
#define PARSE_BLOCK_FLAG_IS_TOP (1 << 0)
|
||||||
|
|
||||||
enum tok_t
|
enum tok_t
|
||||||
{
|
{
|
||||||
TOK_EOF,
|
TOK_EOF,
|
||||||
@ -140,6 +145,9 @@ enum tok_t
|
|||||||
TOK_WHILE,
|
TOK_WHILE,
|
||||||
TOK_FOR,
|
TOK_FOR,
|
||||||
TOK_DO,
|
TOK_DO,
|
||||||
|
TOK_SWITCH,
|
||||||
|
TOK_CASE,
|
||||||
|
TOK_DEFAULT,
|
||||||
TOK_BREAK,
|
TOK_BREAK,
|
||||||
TOK_CONTINUE,
|
TOK_CONTINUE,
|
||||||
TOK_RETURN,
|
TOK_RETURN,
|
||||||
@ -200,17 +208,15 @@ static int parse_progunit (hawk_t* hawk);
|
|||||||
static hawk_t* collect_globals (hawk_t* hawk);
|
static hawk_t* collect_globals (hawk_t* hawk);
|
||||||
static void adjust_static_globals (hawk_t* hawk);
|
static void adjust_static_globals (hawk_t* hawk);
|
||||||
static hawk_oow_t find_global (hawk_t* hawk, const hawk_oocs_t* name);
|
static hawk_oow_t find_global (hawk_t* hawk, const hawk_oocs_t* name);
|
||||||
static hawk_t* collect_locals (hawk_t* hawk, hawk_oow_t nlcls, int istop);
|
static hawk_t* collect_locals (hawk_t* hawk, hawk_oow_t nlcls, int flags);
|
||||||
|
|
||||||
static hawk_nde_t* parse_function (hawk_t* hawk);
|
static hawk_nde_t* parse_function (hawk_t* hawk);
|
||||||
static hawk_nde_t* parse_begin (hawk_t* hawk);
|
static hawk_nde_t* parse_begin (hawk_t* hawk);
|
||||||
static hawk_nde_t* parse_end (hawk_t* hawk);
|
static hawk_nde_t* parse_end (hawk_t* hawk);
|
||||||
static hawk_chain_t* parse_action_block (hawk_t* hawk, hawk_nde_t* ptn, int blockless);
|
static hawk_chain_t* parse_action_block (hawk_t* hawk, hawk_nde_t* ptn, int blockless);
|
||||||
|
|
||||||
static hawk_nde_t* parse_block_dc (hawk_t* hawk, const hawk_loc_t* xloc, int istop);
|
static hawk_nde_t* parse_block_dc (hawk_t* hawk, const hawk_loc_t* xloc, int flags);
|
||||||
|
|
||||||
static hawk_nde_t* parse_statement (hawk_t* hawk, const hawk_loc_t* xloc);
|
static hawk_nde_t* parse_statement (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||||
|
|
||||||
static hawk_nde_t* parse_expr_withdc (hawk_t* hawk, const hawk_loc_t* xloc);
|
static hawk_nde_t* parse_expr_withdc (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||||
|
|
||||||
static hawk_nde_t* parse_logical_or (hawk_t* hawk, const hawk_loc_t* xloc);
|
static hawk_nde_t* parse_logical_or (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||||
@ -233,6 +239,7 @@ static hawk_nde_t* parse_unary_exp (hawk_t* hawk, const hawk_loc_t* xloc);
|
|||||||
static hawk_nde_t* parse_increment (hawk_t* hawk, const hawk_loc_t* xloc);
|
static hawk_nde_t* parse_increment (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||||
static hawk_nde_t* parse_primary (hawk_t* hawk, const hawk_loc_t* xloc);
|
static hawk_nde_t* parse_primary (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||||
static hawk_nde_t* parse_primary_ident (hawk_t* hawk, const hawk_loc_t* xloc);
|
static hawk_nde_t* parse_primary_ident (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||||
|
static hawk_nde_t* parse_primary_literal (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||||
static hawk_nde_t* parse_hashidx (hawk_t* hawk, const hawk_oocs_t* name, const hawk_loc_t* xloc);
|
static hawk_nde_t* parse_hashidx (hawk_t* hawk, const hawk_oocs_t* name, const hawk_loc_t* xloc);
|
||||||
|
|
||||||
#define FNCALL_FLAG_NOARG (1 << 0) /* no argument */
|
#define FNCALL_FLAG_NOARG (1 << 0) /* no argument */
|
||||||
@ -281,7 +288,9 @@ static kwent_t kwtab[] =
|
|||||||
{ { HAWK_T("BEGIN"), 5 }, TOK_BEGIN, HAWK_PABLOCK },
|
{ { HAWK_T("BEGIN"), 5 }, TOK_BEGIN, HAWK_PABLOCK },
|
||||||
{ { HAWK_T("END"), 3 }, TOK_END, HAWK_PABLOCK },
|
{ { HAWK_T("END"), 3 }, TOK_END, HAWK_PABLOCK },
|
||||||
{ { HAWK_T("break"), 5 }, TOK_BREAK, 0 },
|
{ { HAWK_T("break"), 5 }, TOK_BREAK, 0 },
|
||||||
|
{ { HAWK_T("case"), 4 }, TOK_CASE, 0 },
|
||||||
{ { HAWK_T("continue"), 8 }, TOK_CONTINUE, 0 },
|
{ { HAWK_T("continue"), 8 }, TOK_CONTINUE, 0 },
|
||||||
|
{ { HAWK_T("default"), 7 }, TOK_DEFAULT, 0 },
|
||||||
{ { HAWK_T("delete"), 6 }, TOK_DELETE, 0 },
|
{ { HAWK_T("delete"), 6 }, TOK_DELETE, 0 },
|
||||||
{ { HAWK_T("do"), 2 }, TOK_DO, 0 },
|
{ { HAWK_T("do"), 2 }, TOK_DO, 0 },
|
||||||
{ { HAWK_T("else"), 4 }, TOK_ELSE, 0 },
|
{ { HAWK_T("else"), 4 }, TOK_ELSE, 0 },
|
||||||
@ -298,6 +307,7 @@ static kwent_t kwtab[] =
|
|||||||
{ { HAWK_T("print"), 5 }, TOK_PRINT, HAWK_RIO },
|
{ { HAWK_T("print"), 5 }, TOK_PRINT, HAWK_RIO },
|
||||||
{ { HAWK_T("printf"), 6 }, TOK_PRINTF, HAWK_RIO },
|
{ { HAWK_T("printf"), 6 }, TOK_PRINTF, HAWK_RIO },
|
||||||
{ { HAWK_T("return"), 6 }, TOK_RETURN, 0 },
|
{ { HAWK_T("return"), 6 }, TOK_RETURN, 0 },
|
||||||
|
{ { HAWK_T("switch"), 6 }, TOK_SWITCH, 0 },
|
||||||
{ { HAWK_T("while"), 5 }, TOK_WHILE, 0 }
|
{ { HAWK_T("while"), 5 }, TOK_WHILE, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1665,7 +1675,7 @@ static hawk_chain_t* parse_action_block (hawk_t* hawk, hawk_nde_t* ptn, int bloc
|
|||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop)
|
static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int flags)
|
||||||
{
|
{
|
||||||
hawk_nde_t* head, * curr, * nde;
|
hawk_nde_t* head, * curr, * nde;
|
||||||
hawk_nde_blk_t* block;
|
hawk_nde_blk_t* block;
|
||||||
@ -1715,7 +1725,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop)
|
|||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (collect_locals(hawk, nlcls_outer, istop) == HAWK_NULL)
|
if (collect_locals(hawk, nlcls_outer, flags) == HAWK_NULL)
|
||||||
{
|
{
|
||||||
hawk_arr_delete (hawk->parse.lcls, nlcls_outer, HAWK_ARR_SIZE(hawk->parse.lcls) - nlcls_outer);
|
hawk_arr_delete (hawk->parse.lcls, nlcls_outer, HAWK_ARR_SIZE(hawk->parse.lcls) - nlcls_outer);
|
||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
@ -1761,8 +1771,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop)
|
|||||||
{
|
{
|
||||||
int once;
|
int once;
|
||||||
|
|
||||||
if (hawk->opt.depth.s.incl > 0 &&
|
if (hawk->opt.depth.s.incl > 0 && hawk->parse.depth.incl >= hawk->opt.depth.s.incl)
|
||||||
hawk->parse.depth.incl >= hawk->opt.depth.s.incl)
|
|
||||||
{
|
{
|
||||||
hawk_seterrnum(hawk, &hawk->ptok.loc, HAWK_EINCLTD);
|
hawk_seterrnum(hawk, &hawk->ptok.loc, HAWK_EINCLTD);
|
||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
@ -1845,7 +1854,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop)
|
|||||||
and merged to top-level block */
|
and merged to top-level block */
|
||||||
|
|
||||||
/* migrate all block-local variables to the outermost block */
|
/* migrate all block-local variables to the outermost block */
|
||||||
if (istop)
|
if (flags & PARSE_BLOCK_FLAG_IS_TOP)
|
||||||
{
|
{
|
||||||
HAWK_ASSERT (nlcls_outer == 0 && nlcls_max == 0);
|
HAWK_ASSERT (nlcls_outer == 0 && nlcls_max == 0);
|
||||||
block->nlcls = hawk->parse.nlcls_max - nlcls_outer;
|
block->nlcls = hawk->parse.nlcls_max - nlcls_outer;
|
||||||
@ -1863,7 +1872,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop)
|
|||||||
return (hawk_nde_t*)block;
|
return (hawk_nde_t*)block;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hawk_nde_t* parse_block_dc (hawk_t* hawk, const hawk_loc_t* xloc, int istop)
|
static hawk_nde_t* parse_block_dc (hawk_t* hawk, const hawk_loc_t* xloc, int flags)
|
||||||
{
|
{
|
||||||
hawk_nde_t* nde;
|
hawk_nde_t* nde;
|
||||||
|
|
||||||
@ -1876,7 +1885,7 @@ static hawk_nde_t* parse_block_dc (hawk_t* hawk, const hawk_loc_t* xloc, int ist
|
|||||||
}
|
}
|
||||||
|
|
||||||
hawk->parse.depth.block++;
|
hawk->parse.depth.block++;
|
||||||
nde = parse_block(hawk, xloc, istop);
|
nde = parse_block(hawk, xloc, flags);
|
||||||
hawk->parse.depth.block--;
|
hawk->parse.depth.block--;
|
||||||
|
|
||||||
return nde;
|
return nde;
|
||||||
@ -2330,7 +2339,7 @@ static hawk_t* collect_globals (hawk_t* hawk)
|
|||||||
return hawk;
|
return hawk;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hawk_t* collect_locals (hawk_t* hawk, hawk_oow_t nlcls, int istop)
|
static hawk_t* collect_locals (hawk_t* hawk, hawk_oow_t nlcls, int flags)
|
||||||
{
|
{
|
||||||
if (MATCH(hawk,TOK_NEWLINE))
|
if (MATCH(hawk,TOK_NEWLINE))
|
||||||
{
|
{
|
||||||
@ -2361,7 +2370,7 @@ static hawk_t* collect_locals (hawk_t* hawk, hawk_oow_t nlcls, int istop)
|
|||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (istop)
|
if (flags & PARSE_BLOCK_FLAG_IS_TOP)
|
||||||
{
|
{
|
||||||
/* check if it conflicts with a parameter name.
|
/* check if it conflicts with a parameter name.
|
||||||
* the first level declaration is treated as the same
|
* the first level declaration is treated as the same
|
||||||
@ -2525,6 +2534,214 @@ oops:
|
|||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static hawk_nde_case_t* alloc_nde_case (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||||
|
{
|
||||||
|
hawk_nde_case_t* nde;
|
||||||
|
|
||||||
|
nde = (hawk_nde_case_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde));
|
||||||
|
if (HAWK_UNLIKELY(!nde))
|
||||||
|
{
|
||||||
|
ADJERR_LOC(hawk, xloc);
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
nde->type = HAWK_NDE_CASE;
|
||||||
|
nde->loc = *xloc;
|
||||||
|
nde->val = HAWK_NULL;
|
||||||
|
nde->action = HAWK_NULL;
|
||||||
|
|
||||||
|
return nde;
|
||||||
|
|
||||||
|
oops:
|
||||||
|
return HAWK_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hawk_nde_t* parse_switch (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||||
|
{
|
||||||
|
hawk_nde_switch_t* nde;
|
||||||
|
hawk_nde_t* test = HAWK_NULL; /* test to switch */
|
||||||
|
hawk_nde_t* case_val = HAWK_NULL; /* value after case */
|
||||||
|
hawk_nde_t* case_first = HAWK_NULL;
|
||||||
|
hawk_nde_t* case_last = HAWK_NULL;
|
||||||
|
hawk_nde_t* default_part = HAWK_NULL;
|
||||||
|
hawk_loc_t eloc;
|
||||||
|
|
||||||
|
if (!MATCH(hawk,TOK_LPAREN))
|
||||||
|
{
|
||||||
|
hawk_seterrfmt(hawk, &hawk->tok.loc, HAWK_ELPAREN, FMT_ELPAREN, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
|
||||||
|
return HAWK_NULL;
|
||||||
|
}
|
||||||
|
if (get_token(hawk) <= -1) return HAWK_NULL;
|
||||||
|
|
||||||
|
eloc = hawk->tok.loc;
|
||||||
|
test = parse_expr_withdc(hawk, &eloc);
|
||||||
|
if (HAWK_UNLIKELY(!test)) goto oops;
|
||||||
|
|
||||||
|
if (!MATCH(hawk,TOK_RPAREN))
|
||||||
|
{
|
||||||
|
hawk_seterrfmt(hawk, &hawk->tok.loc, HAWK_ERPAREN, FMT_ERPAREN, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_token(hawk) <= -1) goto oops;
|
||||||
|
|
||||||
|
while (MATCH(hawk,TOK_NEWLINE))
|
||||||
|
{
|
||||||
|
if (get_token(hawk) <= -1) goto oops;
|
||||||
|
}
|
||||||
|
if (!MATCH(hawk,TOK_LBRACE))
|
||||||
|
{
|
||||||
|
hawk_seterrfmt(hawk, &hawk->tok.loc, HAWK_ELBRACE, FMT_ELBRACE, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_token(hawk) <= -1) goto oops;
|
||||||
|
|
||||||
|
while (!MATCH(hawk, TOK_RBRACE))
|
||||||
|
{
|
||||||
|
while (MATCH(hawk,TOK_NEWLINE))
|
||||||
|
{
|
||||||
|
if (get_token(hawk) <= -1) goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MATCH(hawk, TOK_CASE) || MATCH(hawk, TOK_DEFAULT))
|
||||||
|
{
|
||||||
|
hawk_nde_case_t* vv;
|
||||||
|
hawk_nde_t* action_first = HAWK_NULL;
|
||||||
|
hawk_nde_t* action_last = HAWK_NULL;
|
||||||
|
|
||||||
|
if (MATCH(hawk, TOK_CASE))
|
||||||
|
{
|
||||||
|
if (get_token(hawk) <= -1) goto oops;
|
||||||
|
eloc = hawk->tok.loc;
|
||||||
|
case_val = parse_primary_literal(hawk, &eloc);
|
||||||
|
if (HAWK_UNLIKELY(!case_val)) goto oops;
|
||||||
|
}
|
||||||
|
else /* MATCH(hawk, TOK_DEFAULT) */
|
||||||
|
{
|
||||||
|
if (default_part)
|
||||||
|
{
|
||||||
|
hawk_seterrfmt(hawk, &hawk->tok.loc, HAWK_EMULDFL, FMT_EMULDFL, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
case_val = HAWK_NULL;
|
||||||
|
if (get_token(hawk) <= -1) goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MATCH(hawk, TOK_COLON))
|
||||||
|
{
|
||||||
|
hawk_seterrfmt(hawk, &hawk->tok.loc, HAWK_ECOLON, FMT_ECOLON, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
if (get_token(hawk) <= -1) goto oops;
|
||||||
|
|
||||||
|
while (MATCH(hawk,TOK_NEWLINE))
|
||||||
|
{
|
||||||
|
if (get_token(hawk) <= -1) goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!MATCH(hawk, TOK_CASE) && !MATCH(hawk, TOK_DEFAULT) && !MATCH(hawk, TOK_RBRACE))
|
||||||
|
{
|
||||||
|
hawk_nde_t* v;
|
||||||
|
|
||||||
|
eloc = hawk->tok.loc;
|
||||||
|
hawk->parse.depth.swtch++;
|
||||||
|
v = parse_statement(hawk, &eloc);
|
||||||
|
hawk->parse.depth.swtch--;
|
||||||
|
if (!v) {
|
||||||
|
if (action_first) hawk_clrpt(hawk, action_first);
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!action_first)
|
||||||
|
{
|
||||||
|
action_first = v;
|
||||||
|
action_last = v;
|
||||||
|
}
|
||||||
|
else if (v->type == HAWK_NDE_NULL && v->type == action_last->type)
|
||||||
|
{
|
||||||
|
/* skip a successive null statement */
|
||||||
|
hawk_freemem(hawk, v);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
action_last->next = v;
|
||||||
|
action_last = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (MATCH(hawk,TOK_NEWLINE))
|
||||||
|
{
|
||||||
|
if (get_token(hawk) <= -1) goto oops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vv = alloc_nde_case(hawk, &eloc);
|
||||||
|
if (!vv)
|
||||||
|
{
|
||||||
|
if (action_first) hawk_clrpt(hawk, action_first);
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
vv->val = case_val;
|
||||||
|
vv->action = action_first;
|
||||||
|
|
||||||
|
if (!case_val) default_part = (hawk_nde_t*)vv;
|
||||||
|
else case_val = HAWK_NULL;
|
||||||
|
|
||||||
|
if (!case_first)
|
||||||
|
{
|
||||||
|
case_first = (hawk_nde_t*)vv;
|
||||||
|
case_last = (hawk_nde_t*)vv;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
case_last->next = (hawk_nde_t*)vv;
|
||||||
|
case_last = (hawk_nde_t*)vv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hawk_seterrfmt(hawk, &hawk->tok.loc, HAWK_EKWCASE, FMT_EKWCASE, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (MATCH(hawk,TOK_NEWLINE))
|
||||||
|
{
|
||||||
|
if (get_token(hawk) <= -1) goto oops;
|
||||||
|
}
|
||||||
|
if (!MATCH(hawk, TOK_RBRACE))
|
||||||
|
{
|
||||||
|
hawk_seterrfmt(hawk, &hawk->tok.loc, HAWK_ERBRACE, FMT_ERBRACE, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_token(hawk) <= -1) goto oops;
|
||||||
|
|
||||||
|
|
||||||
|
nde = (hawk_nde_switch_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde));
|
||||||
|
if (HAWK_UNLIKELY(!nde))
|
||||||
|
{
|
||||||
|
ADJERR_LOC(hawk, xloc);
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
nde->type = HAWK_NDE_SWITCH;
|
||||||
|
nde->loc = *xloc;
|
||||||
|
nde->test = test;
|
||||||
|
nde->case_part = case_first;
|
||||||
|
nde->default_part = default_part;
|
||||||
|
|
||||||
|
return (hawk_nde_t*)nde;
|
||||||
|
|
||||||
|
oops:
|
||||||
|
if (case_val) hawk_clrpt(hawk, case_val);
|
||||||
|
if (case_first) hawk_clrpt(hawk, case_first);
|
||||||
|
/*if (default_part) hawk_clrpt(hawk, default_part); no need to crear it as it is in the case_first chanin */
|
||||||
|
if (test) hawk_clrpt(hawk, test);
|
||||||
|
return HAWK_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static hawk_nde_t* parse_while (hawk_t* hawk, const hawk_loc_t* xloc)
|
static hawk_nde_t* parse_while (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||||
{
|
{
|
||||||
hawk_nde_t* test = HAWK_NULL;
|
hawk_nde_t* test = HAWK_NULL;
|
||||||
@ -2676,7 +2893,6 @@ static hawk_nde_t* parse_for (hawk_t* hawk, const hawk_loc_t* xloc)
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
hawk_loc_t eloc;
|
hawk_loc_t eloc;
|
||||||
|
|
||||||
eloc = hawk->tok.loc;
|
eloc = hawk->tok.loc;
|
||||||
incr = parse_expr_withdc(hawk, &eloc);
|
incr = parse_expr_withdc(hawk, &eloc);
|
||||||
if (HAWK_UNLIKELY(!incr)) goto oops;
|
if (HAWK_UNLIKELY(!incr)) goto oops;
|
||||||
@ -2791,7 +3007,7 @@ static hawk_nde_t* parse_break (hawk_t* hawk, const hawk_loc_t* xloc)
|
|||||||
hawk_nde_break_t* nde;
|
hawk_nde_break_t* nde;
|
||||||
|
|
||||||
HAWK_ASSERT (hawk->ptok.type == TOK_BREAK);
|
HAWK_ASSERT (hawk->ptok.type == TOK_BREAK);
|
||||||
if (hawk->parse.depth.loop <= 0)
|
if (hawk->parse.depth.loop <= 0 && hawk->parse.depth.swtch <= 0)
|
||||||
{
|
{
|
||||||
hawk_seterrnum(hawk, xloc, HAWK_EBREAK);
|
hawk_seterrnum(hawk, xloc, HAWK_EBREAK);
|
||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
@ -3256,8 +3472,7 @@ oops:
|
|||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hawk_nde_t* parse_statement_nb (
|
static hawk_nde_t* parse_statement_nb (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||||
hawk_t* hawk, const hawk_loc_t* xloc)
|
|
||||||
{
|
{
|
||||||
/* parse a non-block statement */
|
/* parse a non-block statement */
|
||||||
hawk_nde_t* nde;
|
hawk_nde_t* nde;
|
||||||
@ -3268,6 +3483,11 @@ static hawk_nde_t* parse_statement_nb (
|
|||||||
if (get_token(hawk) <= -1) return HAWK_NULL;
|
if (get_token(hawk) <= -1) return HAWK_NULL;
|
||||||
return parse_if(hawk, xloc);
|
return parse_if(hawk, xloc);
|
||||||
}
|
}
|
||||||
|
else if (MATCH(hawk, TOK_SWITCH))
|
||||||
|
{
|
||||||
|
if (get_token(hawk) <= -1) return HAWK_NULL;
|
||||||
|
return parse_switch(hawk, xloc);
|
||||||
|
}
|
||||||
else if (MATCH(hawk,TOK_WHILE))
|
else if (MATCH(hawk,TOK_WHILE))
|
||||||
{
|
{
|
||||||
if (get_token(hawk) <= -1) return HAWK_NULL;
|
if (get_token(hawk) <= -1) return HAWK_NULL;
|
||||||
@ -3485,7 +3705,6 @@ static hawk_nde_t* parse_expr_basic (hawk_t* hawk, const hawk_loc_t* xloc)
|
|||||||
nde = parse_logical_or(hawk, xloc);
|
nde = parse_logical_or(hawk, xloc);
|
||||||
if (nde == HAWK_NULL) return HAWK_NULL;
|
if (nde == HAWK_NULL) return HAWK_NULL;
|
||||||
|
|
||||||
if (MATCH(hawk,TOK_QUEST))
|
|
||||||
if (MATCH(hawk,TOK_QUEST))
|
if (MATCH(hawk,TOK_QUEST))
|
||||||
{
|
{
|
||||||
hawk_loc_t eloc;
|
hawk_loc_t eloc;
|
||||||
@ -5200,6 +5419,39 @@ oops:
|
|||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static hawk_nde_t* parse_primary_literal (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||||
|
{
|
||||||
|
switch (hawk->tok.type)
|
||||||
|
{
|
||||||
|
case TOK_CHAR:
|
||||||
|
return parse_primary_char(hawk, xloc);
|
||||||
|
|
||||||
|
case TOK_BCHR:
|
||||||
|
return parse_primary_bchr(hawk, xloc);
|
||||||
|
|
||||||
|
case TOK_INT:
|
||||||
|
return parse_primary_int(hawk, xloc);
|
||||||
|
|
||||||
|
case TOK_FLT:
|
||||||
|
return parse_primary_flt(hawk, xloc);
|
||||||
|
|
||||||
|
case TOK_STR:
|
||||||
|
return parse_primary_str(hawk, xloc);
|
||||||
|
|
||||||
|
case TOK_MBS:
|
||||||
|
return parse_primary_mbs(hawk, xloc);
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
hawk_tok_t* xtok;
|
||||||
|
|
||||||
|
xtok = MATCH(hawk,TOK_NEWLINE)? &hawk->ptok: &hawk->tok;
|
||||||
|
hawk_seterrfmt(hawk, &xtok->loc, HAWK_EEXPRNR, HAWK_T("literal expression not recognized around '%.*js'"), HAWK_OOECS_LEN(xtok->name), HAWK_OOECS_PTR(xtok->name));
|
||||||
|
return HAWK_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static hawk_nde_t* parse_primary_nopipe (hawk_t* hawk, const hawk_loc_t* xloc)
|
static hawk_nde_t* parse_primary_nopipe (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||||
{
|
{
|
||||||
switch (hawk->tok.type)
|
switch (hawk->tok.type)
|
||||||
|
193
lib/run.c
193
lib/run.c
@ -78,7 +78,7 @@ static int init_rtx (hawk_rtx_t* rtx, hawk_t* hawk, hawk_rio_cbs_t* rio);
|
|||||||
static void fini_rtx (hawk_rtx_t* rtx, int fini_globals);
|
static void fini_rtx (hawk_rtx_t* rtx, int fini_globals);
|
||||||
|
|
||||||
static int init_globals (hawk_rtx_t* rtx);
|
static int init_globals (hawk_rtx_t* rtx);
|
||||||
static void refdown_globals (hawk_rtx_t* run, int pop);
|
static void refdown_globals (hawk_rtx_t* rtx, int pop);
|
||||||
|
|
||||||
static int run_pblocks (hawk_rtx_t* rtx);
|
static int run_pblocks (hawk_rtx_t* rtx);
|
||||||
static int run_pblock_chain (hawk_rtx_t* rtx, hawk_chain_t* cha);
|
static int run_pblock_chain (hawk_rtx_t* rtx, hawk_chain_t* cha);
|
||||||
@ -86,6 +86,7 @@ static int run_pblock (hawk_rtx_t* rtx, hawk_chain_t* cha, hawk_oow_t bno);
|
|||||||
static int run_block (hawk_rtx_t* rtx, hawk_nde_blk_t* nde);
|
static int run_block (hawk_rtx_t* rtx, hawk_nde_blk_t* nde);
|
||||||
static int run_statement (hawk_rtx_t* rtx, hawk_nde_t* nde);
|
static int run_statement (hawk_rtx_t* rtx, hawk_nde_t* nde);
|
||||||
static int run_if (hawk_rtx_t* rtx, hawk_nde_if_t* nde);
|
static int run_if (hawk_rtx_t* rtx, hawk_nde_if_t* nde);
|
||||||
|
static int run_switch (hawk_rtx_t* rtx, hawk_nde_switch_t* nde);
|
||||||
static int run_while (hawk_rtx_t* rtx, hawk_nde_while_t* nde);
|
static int run_while (hawk_rtx_t* rtx, hawk_nde_while_t* nde);
|
||||||
static int run_for (hawk_rtx_t* rtx, hawk_nde_for_t* nde);
|
static int run_for (hawk_rtx_t* rtx, hawk_nde_for_t* nde);
|
||||||
static int run_forin (hawk_rtx_t* rtx, hawk_nde_forin_t* nde);
|
static int run_forin (hawk_rtx_t* rtx, hawk_nde_forin_t* nde);
|
||||||
@ -1979,7 +1980,7 @@ static int run_pblocks (hawk_rtx_t* rtx)
|
|||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
#define ADJUST_ERROR(run) \
|
#define ADJUST_ERROR(rtx) \
|
||||||
if (rtx->hawk->tree.chain != HAWK_NULL) \
|
if (rtx->hawk->tree.chain != HAWK_NULL) \
|
||||||
{ \
|
{ \
|
||||||
if (rtx->hawk->tree.chain->pattern != HAWK_NULL) \
|
if (rtx->hawk->tree.chain->pattern != HAWK_NULL) \
|
||||||
@ -1989,7 +1990,7 @@ static int run_pblocks (hawk_rtx_t* rtx)
|
|||||||
} \
|
} \
|
||||||
else if (rtx->hawk->tree.end != HAWK_NULL) \
|
else if (rtx->hawk->tree.end != HAWK_NULL) \
|
||||||
{ \
|
{ \
|
||||||
ADJERR_LOC (run, &rtx->hawk->tree.end->loc); \
|
ADJERR_LOC(rtx, &rtx->hawk->tree.end->loc); \
|
||||||
}
|
}
|
||||||
|
|
||||||
rtx->inrec.buf_pos = 0;
|
rtx->inrec.buf_pos = 0;
|
||||||
@ -2279,6 +2280,17 @@ static int run_statement (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
|||||||
xret = run_if(rtx, (hawk_nde_if_t*)nde);
|
xret = run_if(rtx, (hawk_nde_if_t*)nde);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HAWK_NDE_SWITCH:
|
||||||
|
xret = run_switch(rtx, (hawk_nde_switch_t*)nde);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HAWK_NDE_CASE:
|
||||||
|
/* this must never happen - run_swtich must handle this part */
|
||||||
|
HAWK_ASSERT (!"should never happen - HAWK_NDE_CASE must not be fed to run_statement");
|
||||||
|
hawk_rtx_seterrnum(rtx, &nde->loc, HAWK_EINTERN);
|
||||||
|
xret = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
case HAWK_NDE_WHILE:
|
case HAWK_NDE_WHILE:
|
||||||
case HAWK_NDE_DOWHILE:
|
case HAWK_NDE_DOWHILE:
|
||||||
xret = run_while(rtx, (hawk_nde_while_t*)nde);
|
xret = run_while(rtx, (hawk_nde_while_t*)nde);
|
||||||
@ -2378,6 +2390,119 @@ static int run_if (hawk_rtx_t* rtx, hawk_nde_if_t* nde)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int run_switch (hawk_rtx_t* rtx, hawk_nde_switch_t* nde)
|
||||||
|
{
|
||||||
|
hawk_val_t* test;
|
||||||
|
hawk_val_t* v;
|
||||||
|
hawk_nde_case_t* case_part;
|
||||||
|
hawk_nde_case_t* default_part;
|
||||||
|
int eval_true = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* the test expression for the if statement cannot have
|
||||||
|
* chained expressions. this should not be allowed by the
|
||||||
|
* parser first of all */
|
||||||
|
HAWK_ASSERT (nde->test->next == HAWK_NULL);
|
||||||
|
|
||||||
|
test = eval_expression(rtx, nde->test);
|
||||||
|
if (HAWK_UNLIKELY(!test)) return -1;
|
||||||
|
|
||||||
|
hawk_rtx_refupval(rtx, test);
|
||||||
|
|
||||||
|
HAWK_ASSERT(nde->type == HAWK_NDE_CASE);
|
||||||
|
case_part = (hawk_nde_case_t*)nde->case_part;
|
||||||
|
default_part = (hawk_nde_case_t*)nde->default_part;
|
||||||
|
|
||||||
|
while (case_part)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
|
||||||
|
if (eval_true) goto skip_eval;
|
||||||
|
if (case_part->val) // skip the default part.
|
||||||
|
{
|
||||||
|
v = eval_expression(rtx, case_part->val);
|
||||||
|
hawk_rtx_refupval(rtx, v);
|
||||||
|
x = hawk_rtx_cmpval(rtx, test, v, &ret);
|
||||||
|
hawk_rtx_refdownval(rtx, v);
|
||||||
|
if (x <= -1)
|
||||||
|
{
|
||||||
|
hawk_rtx_refdownval(rtx, test);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
skip_eval:
|
||||||
|
eval_true = 1;
|
||||||
|
if (case_part->action)
|
||||||
|
{
|
||||||
|
hawk_nde_t* action;
|
||||||
|
|
||||||
|
action = case_part->action;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (run_statement(rtx, action) <= -1)
|
||||||
|
{
|
||||||
|
ret = -1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rtx->exit_level == EXIT_BREAK) /* if 'break' has been executed */
|
||||||
|
{
|
||||||
|
rtx->exit_level = EXIT_NONE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else if (rtx->exit_level != EXIT_NONE) goto done;
|
||||||
|
|
||||||
|
action = action->next;
|
||||||
|
}
|
||||||
|
while(action);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case_part = (hawk_nde_case_t*)case_part->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eval_true && default_part)
|
||||||
|
{
|
||||||
|
case_part = default_part;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (case_part->action)
|
||||||
|
{
|
||||||
|
hawk_nde_t* action;
|
||||||
|
|
||||||
|
action = case_part->action;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (run_statement(rtx, action) <= -1)
|
||||||
|
{
|
||||||
|
ret = -1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rtx->exit_level == EXIT_BREAK) /* if 'break' has been executed */
|
||||||
|
{
|
||||||
|
rtx->exit_level = EXIT_NONE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else if (rtx->exit_level != EXIT_NONE) goto done;
|
||||||
|
|
||||||
|
action = action->next;
|
||||||
|
}
|
||||||
|
while (action);
|
||||||
|
}
|
||||||
|
case_part = (hawk_nde_case_t*)case_part->next;
|
||||||
|
}
|
||||||
|
while (case_part);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
hawk_rtx_refdownval(rtx, test);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int run_while (hawk_rtx_t* rtx, hawk_nde_while_t* nde)
|
static int run_while (hawk_rtx_t* rtx, hawk_nde_while_t* nde)
|
||||||
{
|
{
|
||||||
hawk_val_t* test;
|
hawk_val_t* test;
|
||||||
@ -2749,9 +2874,9 @@ done1:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_break (hawk_rtx_t* run, hawk_nde_break_t* nde)
|
static int run_break (hawk_rtx_t* rtx, hawk_nde_break_t* nde)
|
||||||
{
|
{
|
||||||
run->exit_level = EXIT_BREAK;
|
rtx->exit_level = EXIT_BREAK;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6200,60 +6325,60 @@ static hawk_val_t* eval_binop_match0 (
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hawk_val_t* eval_binop_ma (hawk_rtx_t* run, hawk_nde_t* left, hawk_nde_t* right)
|
static hawk_val_t* eval_binop_ma (hawk_rtx_t* rtx, hawk_nde_t* left, hawk_nde_t* right)
|
||||||
{
|
{
|
||||||
hawk_val_t* lv, * rv, * res;
|
hawk_val_t* lv, * rv, * res;
|
||||||
|
|
||||||
HAWK_ASSERT (left->next == HAWK_NULL);
|
HAWK_ASSERT (left->next == HAWK_NULL);
|
||||||
HAWK_ASSERT (right->next == HAWK_NULL);
|
HAWK_ASSERT (right->next == HAWK_NULL);
|
||||||
|
|
||||||
lv = eval_expression(run, left);
|
lv = eval_expression(rtx, left);
|
||||||
if (HAWK_UNLIKELY(!lv)) return HAWK_NULL;
|
if (HAWK_UNLIKELY(!lv)) return HAWK_NULL;
|
||||||
|
|
||||||
hawk_rtx_refupval(run, lv);
|
hawk_rtx_refupval(rtx, lv);
|
||||||
|
|
||||||
rv = eval_expression0(run, right);
|
rv = eval_expression0(rtx, right);
|
||||||
if (HAWK_UNLIKELY(!rv))
|
if (HAWK_UNLIKELY(!rv))
|
||||||
{
|
{
|
||||||
hawk_rtx_refdownval(run, lv);
|
hawk_rtx_refdownval(rtx, lv);
|
||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hawk_rtx_refupval(run, rv);
|
hawk_rtx_refupval(rtx, rv);
|
||||||
|
|
||||||
res = eval_binop_match0(run, lv, rv, &left->loc, &right->loc, 1);
|
res = eval_binop_match0(rtx, lv, rv, &left->loc, &right->loc, 1);
|
||||||
|
|
||||||
hawk_rtx_refdownval(run, rv);
|
hawk_rtx_refdownval(rtx, rv);
|
||||||
hawk_rtx_refdownval(run, lv);
|
hawk_rtx_refdownval(rtx, lv);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hawk_val_t* eval_binop_nm (hawk_rtx_t* run, hawk_nde_t* left, hawk_nde_t* right)
|
static hawk_val_t* eval_binop_nm (hawk_rtx_t* rtx, hawk_nde_t* left, hawk_nde_t* right)
|
||||||
{
|
{
|
||||||
hawk_val_t* lv, * rv, * res;
|
hawk_val_t* lv, * rv, * res;
|
||||||
|
|
||||||
HAWK_ASSERT (left->next == HAWK_NULL);
|
HAWK_ASSERT (left->next == HAWK_NULL);
|
||||||
HAWK_ASSERT (right->next == HAWK_NULL);
|
HAWK_ASSERT (right->next == HAWK_NULL);
|
||||||
|
|
||||||
lv = eval_expression(run, left);
|
lv = eval_expression(rtx, left);
|
||||||
if (HAWK_UNLIKELY(!lv)) return HAWK_NULL;
|
if (HAWK_UNLIKELY(!lv)) return HAWK_NULL;
|
||||||
|
|
||||||
hawk_rtx_refupval(run, lv);
|
hawk_rtx_refupval(rtx, lv);
|
||||||
|
|
||||||
rv = eval_expression0(run, right);
|
rv = eval_expression0(rtx, right);
|
||||||
if (HAWK_UNLIKELY(!rv))
|
if (HAWK_UNLIKELY(!rv))
|
||||||
{
|
{
|
||||||
hawk_rtx_refdownval(run, lv);
|
hawk_rtx_refdownval(rtx, lv);
|
||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hawk_rtx_refupval(run, rv);
|
hawk_rtx_refupval(rtx, rv);
|
||||||
|
|
||||||
res = eval_binop_match0(run, lv, rv, &left->loc, &right->loc, 0);
|
res = eval_binop_match0(rtx, lv, rv, &left->loc, &right->loc, 0);
|
||||||
|
|
||||||
hawk_rtx_refdownval(run, rv);
|
hawk_rtx_refdownval(rtx, rv);
|
||||||
hawk_rtx_refdownval(run, lv);
|
hawk_rtx_refdownval(rtx, lv);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -6613,22 +6738,22 @@ static hawk_val_t* eval_incpst (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hawk_val_t* eval_cnd (hawk_rtx_t* run, hawk_nde_t* nde)
|
static hawk_val_t* eval_cnd (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||||
{
|
{
|
||||||
hawk_val_t* tv, * v;
|
hawk_val_t* tv, * v;
|
||||||
hawk_nde_cnd_t* cnd = (hawk_nde_cnd_t*)nde;
|
hawk_nde_cnd_t* cnd = (hawk_nde_cnd_t*)nde;
|
||||||
|
|
||||||
HAWK_ASSERT (cnd->test->next == HAWK_NULL);
|
HAWK_ASSERT (cnd->test->next == HAWK_NULL);
|
||||||
|
|
||||||
tv = eval_expression(run, cnd->test);
|
tv = eval_expression(rtx, cnd->test);
|
||||||
if (HAWK_UNLIKELY(!tv)) return HAWK_NULL;
|
if (HAWK_UNLIKELY(!tv)) return HAWK_NULL;
|
||||||
|
|
||||||
hawk_rtx_refupval(run, tv);
|
hawk_rtx_refupval(rtx, tv);
|
||||||
|
|
||||||
HAWK_ASSERT (cnd->left->next == HAWK_NULL && cnd->right->next == HAWK_NULL);
|
HAWK_ASSERT (cnd->left->next == HAWK_NULL && cnd->right->next == HAWK_NULL);
|
||||||
v = (hawk_rtx_valtobool(run, tv))? eval_expression(run, cnd->left): eval_expression(run, cnd->right);
|
v = (hawk_rtx_valtobool(rtx, tv))? eval_expression(rtx, cnd->left): eval_expression(rtx, cnd->right);
|
||||||
|
|
||||||
hawk_rtx_refdownval(run, tv);
|
hawk_rtx_refdownval(rtx, tv);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7984,20 +8109,20 @@ static hawk_val_t* eval_getline (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
|||||||
return ((hawk_nde_getline_t*)nde)->mbs? __eval_getbline(rtx, nde): __eval_getline(rtx, nde);
|
return ((hawk_nde_getline_t*)nde)->mbs? __eval_getbline(rtx, nde): __eval_getline(rtx, nde);
|
||||||
}
|
}
|
||||||
|
|
||||||
static hawk_val_t* eval_print (hawk_rtx_t* run, hawk_nde_t* nde)
|
static hawk_val_t* eval_print (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||||
{
|
{
|
||||||
int n = run_print(run, (hawk_nde_print_t*)nde);
|
int n = run_print(rtx, (hawk_nde_print_t*)nde);
|
||||||
if (n == PRINT_IOERR) n = -1; /* let print return -1 */
|
if (n == PRINT_IOERR) n = -1; /* let print return -1 */
|
||||||
else if (n <= -1) return HAWK_NULL;
|
else if (n <= -1) return HAWK_NULL;
|
||||||
return hawk_rtx_makeintval(run, n);
|
return hawk_rtx_makeintval(rtx, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static hawk_val_t* eval_printf (hawk_rtx_t* run, hawk_nde_t* nde)
|
static hawk_val_t* eval_printf (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||||
{
|
{
|
||||||
int n = run_printf(run, (hawk_nde_print_t*)nde);
|
int n = run_printf(rtx, (hawk_nde_print_t*)nde);
|
||||||
if (n == PRINT_IOERR) n = -1; /* let print return -1 */
|
if (n == PRINT_IOERR) n = -1; /* let print return -1 */
|
||||||
else if (n <= -1) return HAWK_NULL;
|
else if (n <= -1) return HAWK_NULL;
|
||||||
return hawk_rtx_makeintval(run, n);
|
return hawk_rtx_makeintval(rtx, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_record (hawk_rtx_t* rtx)
|
static int read_record (hawk_rtx_t* rtx)
|
||||||
|
@ -75,6 +75,8 @@ typedef struct hawk_nde_fncall_t hawk_nde_fncall_t;
|
|||||||
typedef struct hawk_nde_getline_t hawk_nde_getline_t;
|
typedef struct hawk_nde_getline_t hawk_nde_getline_t;
|
||||||
|
|
||||||
typedef struct hawk_nde_if_t hawk_nde_if_t;
|
typedef struct hawk_nde_if_t hawk_nde_if_t;
|
||||||
|
typedef struct hawk_nde_switch_t hawk_nde_switch_t;
|
||||||
|
typedef struct hawk_nde_case_t hawk_nde_case_t;
|
||||||
typedef struct hawk_nde_while_t hawk_nde_while_t;
|
typedef struct hawk_nde_while_t hawk_nde_while_t;
|
||||||
typedef struct hawk_nde_for_t hawk_nde_for_t;
|
typedef struct hawk_nde_for_t hawk_nde_for_t;
|
||||||
typedef struct hawk_nde_forin_t hawk_nde_forin_t;
|
typedef struct hawk_nde_forin_t hawk_nde_forin_t;
|
||||||
@ -280,6 +282,23 @@ struct hawk_nde_if_t
|
|||||||
hawk_nde_t* else_part; /* optional */
|
hawk_nde_t* else_part; /* optional */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* HAWK_NDE_SWITCH */
|
||||||
|
struct hawk_nde_switch_t
|
||||||
|
{
|
||||||
|
HAWK_NDE_HDR;
|
||||||
|
hawk_nde_t* test;
|
||||||
|
hawk_nde_t* case_part; /* optional */
|
||||||
|
hawk_nde_t* default_part; /* optional */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* HAWK_NDE_CASE */
|
||||||
|
struct hawk_nde_case_t
|
||||||
|
{
|
||||||
|
HAWK_NDE_HDR;
|
||||||
|
hawk_nde_t* val;
|
||||||
|
hawk_nde_t* action;
|
||||||
|
};
|
||||||
|
|
||||||
/* HAWK_NDE_WHILE, HAWK_NDE_DOWHILE */
|
/* HAWK_NDE_WHILE, HAWK_NDE_DOWHILE */
|
||||||
struct hawk_nde_while_t
|
struct hawk_nde_while_t
|
||||||
{
|
{
|
||||||
|
64
lib/tree.c
64
lib/tree.c
@ -969,6 +969,49 @@ static int print_stmt (hawk_t* hawk, hawk_nde_t* p, int depth)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case HAWK_NDE_SWITCH:
|
||||||
|
{
|
||||||
|
hawk_nde_switch_t* px = (hawk_nde_switch_t*)p;
|
||||||
|
|
||||||
|
PRINT_TABS(hawk, depth);
|
||||||
|
hawk_getkwname(hawk, HAWK_KWID_SWITCH, &kw);
|
||||||
|
PUT_SRCSTRN(hawk, kw.ptr, kw.len);
|
||||||
|
PUT_SRCSTR(hawk, HAWK_T(" ("));
|
||||||
|
PRINT_EXPR(hawk, px->test);
|
||||||
|
PUT_SRCSTR(hawk, HAWK_T(")"));
|
||||||
|
PUT_NL(hawk);
|
||||||
|
PRINT_TABS(hawk, depth);
|
||||||
|
PUT_SRCSTR(hawk, HAWK_T("{"));
|
||||||
|
PUT_NL(hawk);
|
||||||
|
if (px->case_part) PRINT_STMTS(hawk, px->case_part, depth);
|
||||||
|
/* default_part is one of the case_parts. no explicit printing is needed */
|
||||||
|
/*if (px->default_part) PRINT_STMTS(hawk, px->default_part, depth);*/
|
||||||
|
PUT_NL(hawk);
|
||||||
|
PRINT_TABS(hawk, depth);
|
||||||
|
PUT_SRCSTR(hawk, HAWK_T("}"));
|
||||||
|
PUT_NL(hawk);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case HAWK_NDE_CASE:
|
||||||
|
{
|
||||||
|
/* this is not a real statement and is subject to the owning switch statement. */
|
||||||
|
hawk_nde_case_t* px = (hawk_nde_case_t*)p;
|
||||||
|
|
||||||
|
PRINT_TABS(hawk, depth);
|
||||||
|
hawk_getkwname(hawk, (px->val? HAWK_KWID_CASE: HAWK_KWID_DEFAULT), &kw);
|
||||||
|
PUT_SRCSTRN(hawk, kw.ptr, kw.len);
|
||||||
|
if (px->val)
|
||||||
|
{
|
||||||
|
PUT_SRCSTR(hawk, HAWK_T(" "));
|
||||||
|
PRINT_EXPR(hawk, px->val);
|
||||||
|
}
|
||||||
|
PUT_SRCSTR(hawk, HAWK_T(":"));
|
||||||
|
PUT_NL(hawk);
|
||||||
|
if (px->action) PRINT_STMTS(hawk, px->action, depth + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case HAWK_NDE_WHILE:
|
case HAWK_NDE_WHILE:
|
||||||
{
|
{
|
||||||
hawk_nde_while_t* px = (hawk_nde_while_t*)p;
|
hawk_nde_while_t* px = (hawk_nde_while_t*)p;
|
||||||
@ -988,6 +1031,7 @@ static int print_stmt (hawk_t* hawk, hawk_nde_t* p, int depth)
|
|||||||
{
|
{
|
||||||
PRINT_STMTS(hawk, px->body, depth + 1);
|
PRINT_STMTS(hawk, px->body, depth + 1);
|
||||||
}
|
}
|
||||||
|
PUT_NL(hawk);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1288,6 +1332,26 @@ void hawk_clrpt (hawk_t* hawk, hawk_nde_t* tree)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case HAWK_NDE_SWITCH:
|
||||||
|
{
|
||||||
|
hawk_nde_switch_t* px = (hawk_nde_switch_t*)p;
|
||||||
|
hawk_clrpt(hawk, px->test);
|
||||||
|
if (px->case_part) hawk_clrpt(hawk, px->case_part);
|
||||||
|
/* px->default_part is one of the case parts. explicit clean up isn't required */
|
||||||
|
/*if (px->default_part) hawk_clrpt(hawk, px->default_part);*/
|
||||||
|
hawk_freemem(hawk, p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case HAWK_NDE_CASE:
|
||||||
|
{
|
||||||
|
hawk_nde_case_t* px = (hawk_nde_case_t*)p;
|
||||||
|
if (px->val) hawk_clrpt(hawk, px->val);
|
||||||
|
if (px->action) hawk_clrpt(hawk, px->action);
|
||||||
|
hawk_freemem(hawk, p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case HAWK_NDE_WHILE:
|
case HAWK_NDE_WHILE:
|
||||||
case HAWK_NDE_DOWHILE:
|
case HAWK_NDE_DOWHILE:
|
||||||
{
|
{
|
||||||
|
108
t/h-002.hawk
108
t/h-002.hawk
@ -665,6 +665,29 @@ function main()
|
|||||||
f = test10
|
f = test10
|
||||||
tap_ensure (f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 55, @SCRIPTNAME, @SCRIPTLINE);
|
tap_ensure (f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 55, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
tap_ensure(test12(2,5), -3, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(test12(3,5), 8, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
tap_ensure(test13(1), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(test13(2), 2, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(test13(3), 3, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(test13(4), 4, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(test13(5), 5, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(test13(6), 1005, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
tap_ensure(test14("hello"), "world", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(test14("donkey"), "rankey", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(test14("speed"), "unknown", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
tap_ensure(test15("hello"), "world", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(test15("donkey"), "[rankey012]", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(test15("skunk"), "stinks", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(test15("speed"), "unknown", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
tap_end ();
|
tap_end ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -709,3 +732,88 @@ function test10(...) {
|
|||||||
function test11(...) {
|
function test11(...) {
|
||||||
return (3 in @argv);
|
return (3 in @argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test12(...) {
|
||||||
|
switch(@argv[0] * @argv[1]) {
|
||||||
|
case 10:
|
||||||
|
return @argv[0] - @argv[1];
|
||||||
|
|
||||||
|
default:
|
||||||
|
return @argv[0] + @argv[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function test13(x) {
|
||||||
|
@local a;
|
||||||
|
|
||||||
|
a = 0;
|
||||||
|
|
||||||
|
switch(x) {
|
||||||
|
default:
|
||||||
|
a = 1000;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
a++;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
a++;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
a++;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
a++;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
a++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test14(x) {
|
||||||
|
switch(x) {
|
||||||
|
case "hello":
|
||||||
|
return "world";
|
||||||
|
|
||||||
|
case "donkey":
|
||||||
|
return "rankey";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function test15(x) {
|
||||||
|
@local a, i;
|
||||||
|
|
||||||
|
switch(x) {
|
||||||
|
case "hello":
|
||||||
|
a = "world";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "donkey":
|
||||||
|
{
|
||||||
|
@local l;
|
||||||
|
a = "rankey";
|
||||||
|
l = length(a);
|
||||||
|
for (i = 0; i < l; i++) {
|
||||||
|
if (i == 3) break;
|
||||||
|
a = sprintf("%s%d", a, i);
|
||||||
|
}
|
||||||
|
a = sprintf("[%s]", a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (x == "skunk") a = "stinks";
|
||||||
|
else a = "unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user