aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-24 09:52:09 +0200
committerBad Diode <bd@badd10de.dev>2021-10-24 09:52:09 +0200
commitb743e03fc6042e3e2d55cfa0387c092824de64c5 (patch)
tree1c74213017e20fc5bf675f571de2a264cf104cd3
parentf372586069ea0a92db65bc90cf844c1a35187430 (diff)
downloadbdl-b743e03fc6042e3e2d55cfa0387c092824de64c5.tar.gz
bdl-b743e03fc6042e3e2d55cfa0387c092824de64c5.zip
Add print/display/newline ops
-rw-r--r--examples/arithmetic.bdl58
-rwxr-xr-xsrc/bytecode/compiler.h103
-rwxr-xr-xsrc/bytecode/debug.h35
-rwxr-xr-xsrc/bytecode/lexer.c6
-rwxr-xr-xsrc/bytecode/lexer.h3
-rwxr-xr-xsrc/bytecode/main.c2
-rwxr-xr-xsrc/bytecode/ops.h9
-rwxr-xr-xsrc/bytecode/vm.h31
8 files changed, 192 insertions, 55 deletions
diff --git a/examples/arithmetic.bdl b/examples/arithmetic.bdl
index c3ff230..c313dbb 100644
--- a/examples/arithmetic.bdl
+++ b/examples/arithmetic.bdl
@@ -3,26 +3,58 @@
3;; 3;;
4 4
5;; Addition. 5;; Addition.
6(print "(+ 10 100) -> ") (+ 10 100) 6(print "(+ 10 100) -> ")
7(print "(+ 1 -2 3 4) -> ") (+ 1 -2 3 4) 7(display (+ 10 100))
8(newline)
9
10(print "(+ 1 -2 3 4) -> ")
11(display (+ 1 -2 3 4))
12(newline)
8 13
9;; Substraction. 14;; Substraction.
10(print "(- 100 75) -> ") (- 100 75) 15(print "(- 100 75) -> ")
11(print "(- 10 20 30) -> ") (- 10 20 30) 16(display (- 100 75))
17(newline)
18
19(print "(- 10 20 30) -> ")
20(display (- 10 20 30))
21(newline)
12 22
13;; Multiplication. 23;; Multiplication.
14(print "(* 10 7) -> ") (* 10 7) 24(print "(* 10 7) -> ")
15(print "(* -1 66) -> ") (* -1 66) 25(display (* 10 7))
26(newline)
27
28(print "(* -1 66) -> ")
29(display (* -1 66))
30(newline)
16 31
17;; Division. 32;; Division.
18(print "(/ 45 5) -> ") (/ 45 5) 33(print "(/ 45 5) -> ")
19(print "(/ 10 5 2) -> ") (/ 10 5 2) 34(display (/ 45 5))
35(newline)
36
37(print "(/ 10 5 2) -> ")
38(display (/ 10 5 2))
39(newline)
20 40
21;; Remainder/modulo. 41;; Remainder/modulo.
22(print "(% 45 5) -> ") (% 45 5) 42(print "(% 45 5) -> ")
23(print "(% 45 7) -> ") (% 45 7) 43(display (% 45 5))
24(print "(% 120 45) -> ") (% 120 45) 44(newline)
25(print "(% 120 45 8) -> ") (% 120 45 8) 45
46(print "(% 45 7) -> ")
47(display (% 45 7))
48(newline)
49
50(print "(% 120 45) -> ")
51(display (% 120 45))
52(newline)
53
54(print "(% 120 45 8) -> ")
55(display (% 120 45 8))
56(newline)
26 57
27;; Nesting operations. 58;; Nesting operations.
28(print "(* 20 (+ 100 (- 50 30) (/ 300 3)) 10) -> ") (* 20 (+ 100 (- 50 30) (/ 300 3)) 10) 59(print "(* 20 (+ 100 (- 50 30) (/ 300 3)) 10) -> ")
60(display (* 20 (+ 100 (- 50 30) (/ 300 3)) 10))
diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h
index 02d938f..d404a5a 100755
--- a/src/bytecode/compiler.h
+++ b/src/bytecode/compiler.h
@@ -58,7 +58,7 @@ parse_fixnum(Chunk *chunk, Token tok) {
58void parse_tree(Chunk *chunk, Visitor *vs); 58void parse_tree(Chunk *chunk, Visitor *vs);
59 59
60void 60void
61compile_list_binary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) { 61compile_list_binary_op(Chunk *chunk, Visitor *vs, Token start, Ops op) {
62 size_t n = 0; 62 size_t n = 0;
63 while (has_next_token(vs)) { 63 while (has_next_token(vs)) {
64 Token tok = peek_token(vs); 64 Token tok = peek_token(vs);
@@ -66,8 +66,8 @@ compile_list_binary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) {
66 error_push((Error){ 66 error_push((Error){
67 .type = ERR_TYPE_COMPILER, 67 .type = ERR_TYPE_COMPILER,
68 .value = ERR_UNBALANCED_PAREN, 68 .value = ERR_UNBALANCED_PAREN,
69 .line = list_start.line, 69 .line = start.line,
70 .col = list_start.column, 70 .col = start.column,
71 }); 71 });
72 return; 72 return;
73 } 73 }
@@ -77,8 +77,8 @@ compile_list_binary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) {
77 error_push((Error){ 77 error_push((Error){
78 .type = ERR_TYPE_COMPILER, 78 .type = ERR_TYPE_COMPILER,
79 .value = ERR_NOT_ENOUGH_ARGS, 79 .value = ERR_NOT_ENOUGH_ARGS,
80 .line = list_start.line, 80 .line = start.line,
81 .col = list_start.column, 81 .col = start.column,
82 }); 82 });
83 return; 83 return;
84 } 84 }
@@ -87,12 +87,12 @@ compile_list_binary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) {
87 parse_tree(chunk, vs); 87 parse_tree(chunk, vs);
88 n++; 88 n++;
89 } 89 }
90 emit_constant(chunk, list_start, FIXNUM_VAL(n)); 90 emit_constant(chunk, start, FIXNUM_VAL(n));
91 add_code(chunk, op, list_start.line, list_start.column); 91 add_code(chunk, op, start.line, start.column);
92} 92}
93 93
94void 94void
95compile_list_unary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) { 95compile_list_unary_op(Chunk *chunk, Visitor *vs, Token start, Ops op) {
96 size_t n = 0; 96 size_t n = 0;
97 while (has_next_token(vs)) { 97 while (has_next_token(vs)) {
98 Token tok = peek_token(vs); 98 Token tok = peek_token(vs);
@@ -100,8 +100,8 @@ compile_list_unary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) {
100 error_push((Error){ 100 error_push((Error){
101 .type = ERR_TYPE_COMPILER, 101 .type = ERR_TYPE_COMPILER,
102 .value = ERR_UNBALANCED_PAREN, 102 .value = ERR_UNBALANCED_PAREN,
103 .line = list_start.line, 103 .line = start.line,
104 .col = list_start.column, 104 .col = start.column,
105 }); 105 });
106 return; 106 return;
107 } 107 }
@@ -111,57 +111,94 @@ compile_list_unary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) {
111 error_push((Error){ 111 error_push((Error){
112 .type = ERR_TYPE_COMPILER, 112 .type = ERR_TYPE_COMPILER,
113 .value = ERR_NOT_ENOUGH_ARGS, 113 .value = ERR_NOT_ENOUGH_ARGS,
114 .line = list_start.line, 114 .line = start.line,
115 .col = list_start.column, 115 .col = start.column,
116 }); 116 });
117 } 117 }
118 return; 118 return;
119 } 119 }
120 parse_tree(chunk, vs); 120 parse_tree(chunk, vs);
121 add_code(chunk, op, list_start.line, list_start.column); 121 add_code(chunk, op, start.line, start.column);
122 n++; 122 n++;
123 if (n > 1) { 123 if (n > 1) {
124 error_push((Error){ 124 error_push((Error){
125 .type = ERR_TYPE_COMPILER, 125 .type = ERR_TYPE_COMPILER,
126 .value = ERR_TOO_MANY_ARGS, 126 .value = ERR_TOO_MANY_ARGS,
127 .line = list_start.line, 127 .line = start.line,
128 .col = list_start.column, 128 .col = start.column,
129 }); 129 });
130 } 130 }
131 } 131 }
132 error_push((Error){ 132 error_push((Error){
133 .type = ERR_TYPE_COMPILER, 133 .type = ERR_TYPE_COMPILER,
134 .value = ERR_UNBALANCED_PAREN, 134 .value = ERR_UNBALANCED_PAREN,
135 .line = list_start.line, 135 .line = start.line,
136 .col = list_start.column, 136 .col = start.column,
137 }); 137 });
138} 138}
139 139
140void 140void
141parse_list(Chunk *chunk, Visitor *vs, Token list_start) { 141compile_list_simple_op(Chunk *chunk, Visitor *vs, Token start, Ops op) {
142 if (has_next_token(vs)) {
143 Token tok = peek_token(vs);
144 if (tok.type == TOKEN_EOF) {
145 error_push((Error){
146 .type = ERR_TYPE_COMPILER,
147 .value = ERR_UNBALANCED_PAREN,
148 .line = start.line,
149 .col = start.column,
150 });
151 return;
152 }
153 if (tok.type != TOKEN_RPAREN) {
154 error_push((Error){
155 .type = ERR_TYPE_COMPILER,
156 .value = ERR_TOO_MANY_ARGS,
157 .line = start.line,
158 .col = start.column,
159 });
160 return;
161 }
162 next_token(vs);
163 add_code(chunk, op, start.line, start.column);
164 return;
165 }
166 error_push((Error){
167 .type = ERR_TYPE_COMPILER,
168 .value = ERR_UNBALANCED_PAREN,
169 .line = start.line,
170 .col = start.column,
171 });
172}
173
174void
175parse_list(Chunk *chunk, Visitor *vs, Token start) {
142 if (!has_next_token(vs)) { 176 if (!has_next_token(vs)) {
143 error_push((Error){ 177 error_push((Error){
144 .type = ERR_TYPE_COMPILER, 178 .type = ERR_TYPE_COMPILER,
145 .value = ERR_UNBALANCED_PAREN, 179 .value = ERR_UNBALANCED_PAREN,
146 .line = list_start.line, 180 .line = start.line,
147 .col = list_start.column, 181 .col = start.column,
148 }); 182 });
149 } 183 }
150 Token tok = next_token(vs); 184 Token tok = next_token(vs);
151 switch (tok.type) { 185 switch (tok.type) {
152 case TOKEN_ADD: { compile_list_binary_op(chunk, vs, list_start, OP_SUM); } break; 186 case TOKEN_ADD: { compile_list_binary_op(chunk, vs, start, OP_SUM); } break;
153 case TOKEN_SUB: { compile_list_binary_op(chunk, vs, list_start, OP_SUB); } break; 187 case TOKEN_SUB: { compile_list_binary_op(chunk, vs, start, OP_SUB); } break;
154 case TOKEN_MUL: { compile_list_binary_op(chunk, vs, list_start, OP_MUL); } break; 188 case TOKEN_MUL: { compile_list_binary_op(chunk, vs, start, OP_MUL); } break;
155 case TOKEN_DIV: { compile_list_binary_op(chunk, vs, list_start, OP_DIV); } break; 189 case TOKEN_DIV: { compile_list_binary_op(chunk, vs, start, OP_DIV); } break;
156 case TOKEN_MOD: { compile_list_binary_op(chunk, vs, list_start, OP_MOD); } break; 190 case TOKEN_MOD: { compile_list_binary_op(chunk, vs, start, OP_MOD); } break;
157 case TOKEN_NOT: { compile_list_unary_op(chunk, vs, list_start, OP_NOT); } break; 191 case TOKEN_NOT: { compile_list_unary_op(chunk, vs, start, OP_NOT); } break;
158 case TOKEN_AND: { compile_list_binary_op(chunk, vs, list_start, OP_AND); } break; 192 case TOKEN_AND: { compile_list_binary_op(chunk, vs, start, OP_AND); } break;
159 case TOKEN_OR: { compile_list_binary_op(chunk, vs, list_start, OP_OR); } break; 193 case TOKEN_OR: { compile_list_binary_op(chunk, vs, start, OP_OR); } break;
160 case TOKEN_EQUAL: { compile_list_binary_op(chunk, vs, list_start, OP_EQUAL); } break; 194 case TOKEN_EQUAL: { compile_list_binary_op(chunk, vs, start, OP_EQUAL); } break;
161 case TOKEN_LESS: { compile_list_binary_op(chunk, vs, list_start, OP_LESS); } break; 195 case TOKEN_LESS: { compile_list_binary_op(chunk, vs, start, OP_LESS); } break;
162 case TOKEN_GREATER: { compile_list_binary_op(chunk, vs, list_start, OP_GREATER); } break; 196 case TOKEN_GREATER: { compile_list_binary_op(chunk, vs, start, OP_GREATER); } break;
163 case TOKEN_LESS_EQUAL: { compile_list_binary_op(chunk, vs, list_start, OP_LESS_EQUAL); } break; 197 case TOKEN_LESS_EQUAL: { compile_list_binary_op(chunk, vs, start, OP_LESS_EQUAL); } break;
164 case TOKEN_GREATER_EQUAL: { compile_list_binary_op(chunk, vs, list_start, OP_GREATER_EQUAL); } break; 198 case TOKEN_GREATER_EQUAL: { compile_list_binary_op(chunk, vs, start, OP_GREATER_EQUAL); } break;
199 case TOKEN_PRINT: { compile_list_unary_op(chunk, vs, start, OP_PRINT); } break;
200 case TOKEN_DISPLAY: { compile_list_unary_op(chunk, vs, start, OP_DISPLAY); } break;
201 case TOKEN_NEWLINE: { compile_list_simple_op(chunk, vs, start, OP_NEWLINE); } break;
165 default: { 202 default: {
166 error_push((Error){ 203 error_push((Error){
167 .type = ERR_TYPE_COMPILER, 204 .type = ERR_TYPE_COMPILER,
diff --git a/src/bytecode/debug.h b/src/bytecode/debug.h
index 42b5b93..52cf431 100755
--- a/src/bytecode/debug.h
+++ b/src/bytecode/debug.h
@@ -6,6 +6,33 @@
6void disassemble_chunk(Chunk *chunk, const char *name); 6void disassemble_chunk(Chunk *chunk, const char *name);
7size_t disassemble_instruction(Chunk *chunk, size_t offset); 7size_t disassemble_instruction(Chunk *chunk, size_t offset);
8 8
9static const char* ops_str[] = {
10 // Load/store ops.
11 [OP_CONSTANT] = "OP_CONSTANT",
12 // Arithmetic ops.
13 [OP_SUM] = "OP_SUM",
14 [OP_SUB] = "OP_SUB",
15 [OP_MUL] = "OP_MUL",
16 [OP_DIV] = "OP_DIV",
17 [OP_MOD] = "OP_MOD",
18 // Logic ops.
19 [OP_NOT] = "OP_NOT",
20 [OP_AND] = "OP_AND",
21 [OP_OR] = "OP_OR",
22 // Numerical comparison ops.
23 [OP_EQUAL] = "OP_EQUAL",
24 [OP_LESS] = "OP_LESS",
25 [OP_GREATER] = "OP_GREATER",
26 [OP_LESS_EQUAL] = "OP_LESS_EQUAL",
27 [OP_GREATER_EQUAL] = "OP_GREATER_EQUAL",
28 // Display ops.
29 [OP_DISPLAY] = "OP_DISPLAY",
30 [OP_PRINT] = "OP_PRINT",
31 [OP_NEWLINE] = "OP_NEWLINE",
32 // Return.
33 [OP_RETURN] = "OP_RETURN",
34};
35
9void 36void
10disassemble_chunk(Chunk *chunk, const char *name) { 37disassemble_chunk(Chunk *chunk, const char *name) {
11 printf("== %s ==\n", name); 38 printf("== %s ==\n", name);
@@ -43,14 +70,8 @@ disassemble_instruction(Chunk *chunk, size_t offset) {
43 printf("\n"); 70 printf("\n");
44 return offset + 2; 71 return offset + 2;
45 } break; 72 } break;
46 case OP_SUM: { printf("OP_SUM\n"); return offset + 1; } break;
47 case OP_SUB: { printf("OP_SUB\n"); return offset + 1; } break;
48 case OP_MUL: { printf("OP_MUL\n"); return offset + 1; } break;
49 case OP_DIV: { printf("OP_DIV\n"); return offset + 1; } break;
50 case OP_MOD: { printf("OP_MOD\n"); return offset + 1; } break;
51 case OP_RETURN: { printf("OP_RETURN\n"); return offset + 1; } break;
52 default: { 73 default: {
53 printf("Unknown OP: %d\n", instruction); 74 printf("%s\n", ops_str[instruction]);
54 return offset + 1; 75 return offset + 1;
55 } break; 76 } break;
56 } 77 }
diff --git a/src/bytecode/lexer.c b/src/bytecode/lexer.c
index 207cebb..d157111 100755
--- a/src/bytecode/lexer.c
+++ b/src/bytecode/lexer.c
@@ -16,6 +16,9 @@ static const char* token_str[] = {
16 [TOKEN_DEF] = "TOKEN_DEF", 16 [TOKEN_DEF] = "TOKEN_DEF",
17 [TOKEN_FUN] = "TOKEN_FUN", 17 [TOKEN_FUN] = "TOKEN_FUN",
18 [TOKEN_LAMBDA] = "TOKEN_LAMBDA", 18 [TOKEN_LAMBDA] = "TOKEN_LAMBDA",
19 [TOKEN_DISPLAY] = "TOKEN_DISPLAY",
20 [TOKEN_PRINT] = "TOKEN_PRINT",
21 [TOKEN_NEWLINE] = "TOKEN_NEWLINE",
19 [TOKEN_ADD] = "TOKEN_ADD", 22 [TOKEN_ADD] = "TOKEN_ADD",
20 [TOKEN_SUB] = "TOKEN_SUB", 23 [TOKEN_SUB] = "TOKEN_SUB",
21 [TOKEN_MUL] = "TOKEN_MUL", 24 [TOKEN_MUL] = "TOKEN_MUL",
@@ -146,6 +149,9 @@ find_primitive_type(const StringView value) {
146 if (TOKEN_IS_KEYWORD(value, "def")) { return TOKEN_DEF; } 149 if (TOKEN_IS_KEYWORD(value, "def")) { return TOKEN_DEF; }
147 if (TOKEN_IS_KEYWORD(value, "fun")) { return TOKEN_FUN; } 150 if (TOKEN_IS_KEYWORD(value, "fun")) { return TOKEN_FUN; }
148 if (TOKEN_IS_KEYWORD(value, "lambda")) { return TOKEN_LAMBDA; } 151 if (TOKEN_IS_KEYWORD(value, "lambda")) { return TOKEN_LAMBDA; }
152 if (TOKEN_IS_KEYWORD(value, "display")) { return TOKEN_DISPLAY; }
153 if (TOKEN_IS_KEYWORD(value, "print")) { return TOKEN_PRINT; }
154 if (TOKEN_IS_KEYWORD(value, "newline")) { return TOKEN_NEWLINE; }
149 if (TOKEN_IS_KEYWORD(value, "+")) { return TOKEN_ADD; } 155 if (TOKEN_IS_KEYWORD(value, "+")) { return TOKEN_ADD; }
150 if (TOKEN_IS_KEYWORD(value, "-")) { return TOKEN_SUB; } 156 if (TOKEN_IS_KEYWORD(value, "-")) { return TOKEN_SUB; }
151 if (TOKEN_IS_KEYWORD(value, "*")) { return TOKEN_MUL; } 157 if (TOKEN_IS_KEYWORD(value, "*")) { return TOKEN_MUL; }
diff --git a/src/bytecode/lexer.h b/src/bytecode/lexer.h
index cee2915..7f9eb24 100755
--- a/src/bytecode/lexer.h
+++ b/src/bytecode/lexer.h
@@ -25,6 +25,9 @@ typedef enum TokenType {
25 TOKEN_DEF, 25 TOKEN_DEF,
26 TOKEN_FUN, 26 TOKEN_FUN,
27 TOKEN_LAMBDA, 27 TOKEN_LAMBDA,
28 TOKEN_DISPLAY,
29 TOKEN_PRINT,
30 TOKEN_NEWLINE,
28 31
29 // Arithmetic. 32 // Arithmetic.
30 TOKEN_ADD, 33 TOKEN_ADD,
diff --git a/src/bytecode/main.c b/src/bytecode/main.c
index bad150c..f7d1f74 100755
--- a/src/bytecode/main.c
+++ b/src/bytecode/main.c
@@ -8,7 +8,7 @@
8// Config. 8// Config.
9// 9//
10 10
11#define DEBUG_TRACE_EXECUTION 11// #define DEBUG_TRACE_EXECUTION
12 12
13#include "vm.h" 13#include "vm.h"
14#include "compiler.h" 14#include "compiler.h"
diff --git a/src/bytecode/ops.h b/src/bytecode/ops.h
index b59d65a..348df84 100755
--- a/src/bytecode/ops.h
+++ b/src/bytecode/ops.h
@@ -2,20 +2,29 @@
2#define BDL_OPS_H 2#define BDL_OPS_H
3 3
4typedef enum Ops { 4typedef enum Ops {
5 // Load/store ops.
5 OP_CONSTANT, 6 OP_CONSTANT,
7 // Arithmetic ops.
6 OP_SUM, 8 OP_SUM,
7 OP_SUB, 9 OP_SUB,
8 OP_MUL, 10 OP_MUL,
9 OP_DIV, 11 OP_DIV,
10 OP_MOD, 12 OP_MOD,
13 // Logic ops.
11 OP_NOT, 14 OP_NOT,
12 OP_AND, 15 OP_AND,
13 OP_OR, 16 OP_OR,
17 // Numerical comparison ops.
14 OP_EQUAL, 18 OP_EQUAL,
15 OP_LESS, 19 OP_LESS,
16 OP_GREATER, 20 OP_GREATER,
17 OP_LESS_EQUAL, 21 OP_LESS_EQUAL,
18 OP_GREATER_EQUAL, 22 OP_GREATER_EQUAL,
23 // Display ops.
24 OP_DISPLAY,
25 OP_PRINT,
26 OP_NEWLINE,
27 // Return.
19 OP_RETURN, 28 OP_RETURN,
20} Ops; 29} Ops;
21 30
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h
index b3dd8c3..f1886ec 100755
--- a/src/bytecode/vm.h
+++ b/src/bytecode/vm.h
@@ -159,8 +159,37 @@ vm_interpret(VM *vm, Chunk *chunk) {
159 case OP_GREATER: { FIXNUM_COMPARE_OP(>); } break; 159 case OP_GREATER: { FIXNUM_COMPARE_OP(>); } break;
160 case OP_LESS_EQUAL: { FIXNUM_COMPARE_OP(<=); } break; 160 case OP_LESS_EQUAL: { FIXNUM_COMPARE_OP(<=); } break;
161 case OP_GREATER_EQUAL: { FIXNUM_COMPARE_OP(>=); } break; 161 case OP_GREATER_EQUAL: { FIXNUM_COMPARE_OP(>=); } break;
162 case OP_RETURN: { 162 case OP_DISPLAY: {
163 display(array_pop(vm->stack)); 163 display(array_pop(vm->stack));
164 } break;
165 case OP_PRINT: {
166 Object obj = array_pop(vm->stack);
167 if (!IS_STRING(obj)) {
168 WRONG_ARG_ERR();
169 }
170 StringView scanner = (StringView) {
171 .start = obj.text,
172 .n = array_size(obj.text),
173 };
174 while (scanner.n != 0) {
175 char c = sv_next(&scanner);
176 if (c == '\\' && sv_peek(&scanner) == 'n') {
177 putchar('\n');
178 sv_next(&scanner);
179 continue;
180 }
181 if (c == '\\' && sv_peek(&scanner) == '"') {
182 putchar('"');
183 sv_next(&scanner);
184 continue;
185 }
186 putchar(c);
187 }
188 } break;
189 case OP_NEWLINE: {
190 printf("\n");
191 } break;
192 case OP_RETURN: {
164 printf("\n"); 193 printf("\n");
165 return; 194 return;
166 } break; 195 } break;