authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-02 03:38:45-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-02 03:38:45-07:00
log968b85ad77892da945d478799d4e775222248f1f
treed7ad6b71f1f80e27d5443c9faee41e480705757b
parent724dcdd384c6c00b9e39ed67867d364287e45f0a

closer to guess number example working


11 files changed, 359 insertions(+), 20 deletions(-)

doc/langref.md+2-2
...@@ -34,7 +34,7 @@ Root : many(TopLevelDecl) token(EOF)...@@ -34,7 +34,7 @@ Root : many(TopLevelDecl) token(EOF)
3434
35TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration35TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration
3636
37VariableDeclaration : (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))37VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))
3838
39StructDecl : many(Directive) token(Struct) token(Symbol) token(LBrace) many(StructField) token(RBrace)39StructDecl : many(Directive) token(Struct) token(Symbol) token(LBrace) many(StructField) token(RBrace)
4040
...@@ -150,7 +150,7 @@ ArrayAccessExpression : token(LBracket) Expression token(RBracket)...@@ -150,7 +150,7 @@ ArrayAccessExpression : token(LBracket) Expression token(RBracket)
150150
151PrefixOp : token(Not) | token(Dash) | token(Tilde) | (token(Ampersand) option(token(Const)))151PrefixOp : token(Not) | token(Dash) | token(Tilde) | (token(Ampersand) option(token(Const)))
152152
153PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression153PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression
154154
155StructValueExpression : token(Type) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace)155StructValueExpression : token(Type) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace)
156156
example/guess_number/main.zig+19-4
...@@ -2,19 +2,33 @@ export executable "guess_number";...@@ -2,19 +2,33 @@ export executable "guess_number";
22
3use "std.zig";3use "std.zig";
44
5fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {5// TODO don't duplicate these; implement pub const
6const stdout_fileno : isize = 1;
7const stderr_fileno : isize = 2;
8
9pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
6 print_str("Welcome to the Guess Number Game in Zig.\n");10 print_str("Welcome to the Guess Number Game in Zig.\n");
711
8 var seed : u32;12 var seed : u32;
9 ok_or_panic(os_get_random_bytes(&seed, 4));13 if (os_get_random_bytes(&seed as &u8, 4) != 0) {
14 // TODO full error message
15 fprint_str(stderr_fileno, "unable to get random bytes");
16 return 1;
17 }
18
19 print_str("Seed: ");
20 print_u64(seed);
21 print_str("\n");
22
23 /*
10 var rand_state = rand_init(seed);24 var rand_state = rand_init(seed);
1125
12 const answer = rand_int(&rand_state, 0, 100) + 1;26 const answer = rand_int(&rand_state, 0, 100) + 1;
1327
14 while true {28 while (true) {
15 const line = readline("\nGuess a number between 1 and 100: ");29 const line = readline("\nGuess a number between 1 and 100: ");
1630
17 if const guess ?= parse_number(line) {31 if (const guess ?= parse_number(line)) {
18 if (guess > answer) {32 if (guess > answer) {
19 print_str("Guess lower.\n");33 print_str("Guess lower.\n");
20 } else if (guess < answer) {34 } else if (guess < answer) {
...@@ -27,6 +41,7 @@ fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -27,6 +41,7 @@ fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
27 print_str("Invalid number format.\n");41 print_str("Invalid number format.\n");
28 }42 }
29 }43 }
44 */
3045
31 return 0;46 return 0;
32}47}
src/analyze.cpp+29-9
...@@ -38,6 +38,7 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -38,6 +38,7 @@ static AstNode *first_executing_node(AstNode *node) {
38 case NodeTypeCastExpr:38 case NodeTypeCastExpr:
39 case NodeTypeNumberLiteral:39 case NodeTypeNumberLiteral:
40 case NodeTypeStringLiteral:40 case NodeTypeStringLiteral:
41 case NodeTypeCharLiteral:
41 case NodeTypeUnreachable:42 case NodeTypeUnreachable:
42 case NodeTypeSymbol:43 case NodeTypeSymbol:
43 case NodeTypePrefixOpExpr:44 case NodeTypePrefixOpExpr:
...@@ -588,6 +589,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -588,6 +589,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
588 case NodeTypeArrayAccessExpr:589 case NodeTypeArrayAccessExpr:
589 case NodeTypeNumberLiteral:590 case NodeTypeNumberLiteral:
590 case NodeTypeStringLiteral:591 case NodeTypeStringLiteral:
592 case NodeTypeCharLiteral:
591 case NodeTypeUnreachable:593 case NodeTypeUnreachable:
592 case NodeTypeVoid:594 case NodeTypeVoid:
593 case NodeTypeBoolLiteral:595 case NodeTypeBoolLiteral:
...@@ -659,6 +661,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {...@@ -659,6 +661,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
659 case NodeTypeArrayAccessExpr:661 case NodeTypeArrayAccessExpr:
660 case NodeTypeNumberLiteral:662 case NodeTypeNumberLiteral:
661 case NodeTypeStringLiteral:663 case NodeTypeStringLiteral:
664 case NodeTypeCharLiteral:
662 case NodeTypeUnreachable:665 case NodeTypeUnreachable:
663 case NodeTypeVoid:666 case NodeTypeVoid:
664 case NodeTypeBoolLiteral:667 case NodeTypeBoolLiteral:
...@@ -891,6 +894,17 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont...@@ -891,6 +894,17 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont
891 return expected_type;894 return expected_type;
892 }895 }
893896
897 // implicit non-const to const
898 if (expected_type->id == TypeTableEntryIdPointer &&
899 actual_type->id == TypeTableEntryIdPointer &&
900 expected_type->data.pointer.is_const &&
901 !actual_type->data.pointer.is_const)
902 {
903 return resolve_type_compatibility(g, context, node,
904 expected_type->data.pointer.child_type,
905 actual_type->data.pointer.child_type);
906 }
907
894 add_node_error(g, node,908 add_node_error(g, node,
895 buf_sprintf("expected type '%s', got '%s'",909 buf_sprintf("expected type '%s', got '%s'",
896 buf_ptr(&expected_type->name),910 buf_ptr(&expected_type->name),
...@@ -1013,6 +1027,9 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i...@@ -1013,6 +1027,9 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
1013 Buf *name = &node->data.field_access_expr.field_name;1027 Buf *name = &node->data.field_access_expr.field_name;
1014 if (buf_eql_str(name, "len")) {1028 if (buf_eql_str(name, "len")) {
1015 return_type = g->builtin_types.entry_usize;1029 return_type = g->builtin_types.entry_usize;
1030 } else if (buf_eql_str(name, "ptr")) {
1031 // TODO determine whether the pointer should be const
1032 return_type = get_pointer_to_type(g, struct_type->data.array.child_type, false);
1016 } else {1033 } else {
1017 add_node_error(g, node,1034 add_node_error(g, node,
1018 buf_sprintf("no member named '%s' in '%s'", buf_ptr(name),1035 buf_sprintf("no member named '%s' in '%s'", buf_ptr(name),
...@@ -1160,6 +1177,11 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -1160,6 +1177,11 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
1160 codegen_num_lit->resolved_type = wanted_type;1177 codegen_num_lit->resolved_type = wanted_type;
1161 cast_node->op = CastOpNothing;1178 cast_node->op = CastOpNothing;
1162 return wanted_type;1179 return wanted_type;
1180 } else if (actual_type->id == TypeTableEntryIdPointer &&
1181 wanted_type->id == TypeTableEntryIdPointer)
1182 {
1183 cast_node->op = CastOpPointerReinterpret;
1184 return wanted_type;
1163 } else {1185 } else {
1164 add_node_error(g, node,1186 add_node_error(g, node,
1165 buf_sprintf("invalid cast from type '%s' to '%s'",1187 buf_sprintf("invalid cast from type '%s' to '%s'",
...@@ -1286,6 +1308,9 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,...@@ -1286,6 +1308,9 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
1286 }1308 }
1287 case BinOpTypeAdd:1309 case BinOpTypeAdd:
1288 case BinOpTypeSub:1310 case BinOpTypeSub:
1311 case BinOpTypeMult:
1312 case BinOpTypeDiv:
1313 case BinOpTypeMod:
1289 {1314 {
1290 AstNode *op1 = node->data.bin_op_expr.op1;1315 AstNode *op1 = node->data.bin_op_expr.op1;
1291 AstNode *op2 = node->data.bin_op_expr.op2;1316 AstNode *op2 = node->data.bin_op_expr.op2;
...@@ -1294,15 +1319,6 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,...@@ -1294,15 +1319,6 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
12941319
1295 return resolve_peer_type_compatibility(g, context, node, op1, op2, lhs_type, rhs_type);1320 return resolve_peer_type_compatibility(g, context, node, op1, op2, lhs_type, rhs_type);
1296 }1321 }
1297 case BinOpTypeMult:
1298 case BinOpTypeDiv:
1299 case BinOpTypeMod:
1300 {
1301 // TODO: don't require i32
1302 analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.bin_op_expr.op1);
1303 analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.bin_op_expr.op2);
1304 return g->builtin_types.entry_i32;
1305 }
1306 case BinOpTypeInvalid:1322 case BinOpTypeInvalid:
1307 zig_unreachable();1323 zig_unreachable();
1308 }1324 }
...@@ -1746,6 +1762,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -1746,6 +1762,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
1746 return_type = get_array_type(g, g->builtin_types.entry_u8, buf_len(&node->data.string_literal.buf));1762 return_type = get_array_type(g, g->builtin_types.entry_u8, buf_len(&node->data.string_literal.buf));
1747 }1763 }
1748 break;1764 break;
1765 case NodeTypeCharLiteral:
1766 return_type = g->builtin_types.entry_u8;
1767 break;
1749 case NodeTypeUnreachable:1768 case NodeTypeUnreachable:
1750 return_type = g->builtin_types.entry_unreachable;1769 return_type = g->builtin_types.entry_unreachable;
1751 break;1770 break;
...@@ -1959,6 +1978,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,...@@ -1959,6 +1978,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
1959 case NodeTypeArrayAccessExpr:1978 case NodeTypeArrayAccessExpr:
1960 case NodeTypeNumberLiteral:1979 case NodeTypeNumberLiteral:
1961 case NodeTypeStringLiteral:1980 case NodeTypeStringLiteral:
1981 case NodeTypeCharLiteral:
1962 case NodeTypeUnreachable:1982 case NodeTypeUnreachable:
1963 case NodeTypeVoid:1983 case NodeTypeVoid:
1964 case NodeTypeBoolLiteral:1984 case NodeTypeBoolLiteral:
src/analyze.hpp+1
...@@ -277,6 +277,7 @@ enum CastOp {...@@ -277,6 +277,7 @@ enum CastOp {
277 CastOpIntWidenOrShorten,277 CastOpIntWidenOrShorten,
278 CastOpArrayToString,278 CastOpArrayToString,
279 CastOpMaybeWrap,279 CastOpMaybeWrap,
280 CastOpPointerReinterpret,
280};281};
281282
282struct CastNode {283struct CastNode {
src/codegen.cpp+4
...@@ -390,6 +390,8 @@ static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_v...@@ -390,6 +390,8 @@ static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_v
390 }390 }
391 case CastOpPtrToInt:391 case CastOpPtrToInt:
392 return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");392 return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
393 case CastOpPointerReinterpret:
394 return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");
393 case CastOpIntWidenOrShorten:395 case CastOpIntWidenOrShorten:
394 if (actual_type->size_in_bits == wanted_type->size_in_bits) {396 if (actual_type->size_in_bits == wanted_type->size_in_bits) {
395 return expr_val;397 return expr_val;
...@@ -1236,6 +1238,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {...@@ -1236,6 +1238,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
1236 LLVMValueRef ptr_val = LLVMBuildInBoundsGEP(g->builder, str_val, indices, 2, "");1238 LLVMValueRef ptr_val = LLVMBuildInBoundsGEP(g->builder, str_val, indices, 2, "");
1237 return ptr_val;1239 return ptr_val;
1238 }1240 }
1241 case NodeTypeCharLiteral:
1242 return LLVMConstInt(LLVMInt8Type(), node->data.char_literal.value, false);
1239 case NodeTypeSymbol:1243 case NodeTypeSymbol:
1240 {1244 {
1241 VariableTableEntry *variable = find_variable(1245 VariableTableEntry *variable = find_variable(
src/parser.cpp+66-2
...@@ -102,6 +102,8 @@ const char *node_type_str(NodeType node_type) {...@@ -102,6 +102,8 @@ const char *node_type_str(NodeType node_type) {
102 return "NumberLiteral";102 return "NumberLiteral";
103 case NodeTypeStringLiteral:103 case NodeTypeStringLiteral:
104 return "StringLiteral";104 return "StringLiteral";
105 case NodeTypeCharLiteral:
106 return "CharLiteral";
105 case NodeTypeUnreachable:107 case NodeTypeUnreachable:
106 return "Unreachable";108 return "Unreachable";
107 case NodeTypeSymbol:109 case NodeTypeSymbol:
...@@ -313,6 +315,11 @@ void ast_print(AstNode *node, int indent) {...@@ -313,6 +315,11 @@ void ast_print(AstNode *node, int indent) {
313 buf_ptr(&node->data.string_literal.buf));315 buf_ptr(&node->data.string_literal.buf));
314 break;316 break;
315 }317 }
318 case NodeTypeCharLiteral:
319 {
320 fprintf(stderr, "%s '%c'\n", node_type_str(node->type), node->data.char_literal.value);
321 break;
322 }
316 case NodeTypeUnreachable:323 case NodeTypeUnreachable:
317 fprintf(stderr, "Unreachable\n");324 fprintf(stderr, "Unreachable\n");
318 break;325 break;
...@@ -575,6 +582,55 @@ static void parse_asm_template(ParseContext *pc, AstNode *node) {...@@ -575,6 +582,55 @@ static void parse_asm_template(ParseContext *pc, AstNode *node) {
575 }582 }
576}583}
577584
585static uint8_t parse_char_literal(ParseContext *pc, Token *token) {
586 // skip the single quotes at beginning and end
587 // convert escape sequences
588 bool escape = false;
589 int return_count = 0;
590 uint8_t return_value;
591 for (int i = token->start_pos + 1; i < token->end_pos - 1; i += 1) {
592 uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + i);
593 if (escape) {
594 switch (c) {
595 case '\\':
596 return_value = '\\';
597 return_count += 1;
598 break;
599 case 'r':
600 return_value = '\r';
601 return_count += 1;
602 break;
603 case 'n':
604 return_value = '\n';
605 return_count += 1;
606 break;
607 case 't':
608 return_value = '\t';
609 return_count += 1;
610 break;
611 case '\'':
612 return_value = '\'';
613 return_count += 1;
614 break;
615 default:
616 ast_error(pc, token, "invalid escape character");
617 }
618 escape = false;
619 } else if (c == '\\') {
620 escape = true;
621 } else {
622 return_value = c;
623 return_count += 1;
624 }
625 }
626 if (return_count == 0) {
627 ast_error(pc, token, "character literal too short");
628 } else if (return_count > 1) {
629 ast_error(pc, token, "character literal too long");
630 }
631 return return_count;
632}
633
578static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, bool *out_c_str,634static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, bool *out_c_str,
579 ZigList<SrcPos> *offset_map)635 ZigList<SrcPos> *offset_map)
580{636{
...@@ -620,6 +676,9 @@ static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, bool...@@ -620,6 +676,9 @@ static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, bool
620 buf_append_char(buf, '"');676 buf_append_char(buf, '"');
621 if (offset_map) offset_map->append(pos);677 if (offset_map) offset_map->append(pos);
622 break;678 break;
679 default:
680 ast_error(pc, token, "invalid escape character");
681 break;
623 }682 }
624 escape = false;683 escape = false;
625 } else if (c == '\\') {684 } else if (c == '\\') {
...@@ -1136,7 +1195,7 @@ static AstNode *ast_parse_struct_val_expr(ParseContext *pc, int *token_index) {...@@ -1136,7 +1195,7 @@ static AstNode *ast_parse_struct_val_expr(ParseContext *pc, int *token_index) {
1136}1195}
11371196
1138/*1197/*
1139PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression1198PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression
1140*/1199*/
1141static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {1200static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {
1142 Token *token = &pc->tokens->at(*token_index);1201 Token *token = &pc->tokens->at(*token_index);
...@@ -1151,6 +1210,11 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool...@@ -1151,6 +1210,11 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
1151 parse_string_literal(pc, token, &node->data.string_literal.buf, &node->data.string_literal.c, nullptr);1210 parse_string_literal(pc, token, &node->data.string_literal.buf, &node->data.string_literal.c, nullptr);
1152 *token_index += 1;1211 *token_index += 1;
1153 return node;1212 return node;
1213 } else if (token->id == TokenIdCharLiteral) {
1214 AstNode *node = ast_create_node(pc, NodeTypeCharLiteral, token);
1215 node->data.char_literal.value = parse_char_literal(pc, token);
1216 *token_index += 1;
1217 return node;
1154 } else if (token->id == TokenIdKeywordUnreachable) {1218 } else if (token->id == TokenIdKeywordUnreachable) {
1155 AstNode *node = ast_create_node(pc, NodeTypeUnreachable, token);1219 AstNode *node = ast_create_node(pc, NodeTypeUnreachable, token);
1156 *token_index += 1;1220 *token_index += 1;
...@@ -1733,7 +1797,7 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m...@@ -1733,7 +1797,7 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m
1733}1797}
17341798
1735/*1799/*
1736VariableDeclaration : (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))1800VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))
1737*/1801*/
1738static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory) {1802static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory) {
1739 Token *var_or_const_tok = &pc->tokens->at(*token_index);1803 Token *var_or_const_tok = &pc->tokens->at(*token_index);
src/parser.hpp+6
...@@ -35,6 +35,7 @@ enum NodeType {...@@ -35,6 +35,7 @@ enum NodeType {
35 NodeTypeCastExpr,35 NodeTypeCastExpr,
36 NodeTypeNumberLiteral,36 NodeTypeNumberLiteral,
37 NodeTypeStringLiteral,37 NodeTypeStringLiteral,
38 NodeTypeCharLiteral,
38 NodeTypeUnreachable,39 NodeTypeUnreachable,
39 NodeTypeSymbol,40 NodeTypeSymbol,
40 NodeTypePrefixOpExpr,41 NodeTypePrefixOpExpr,
...@@ -289,6 +290,10 @@ struct AstNodeStringLiteral {...@@ -289,6 +290,10 @@ struct AstNodeStringLiteral {
289 bool c;290 bool c;
290};291};
291292
293struct AstNodeCharLiteral {
294 uint8_t value;
295};
296
292enum NumLit {297enum NumLit {
293 NumLitF32,298 NumLitF32,
294 NumLitF64,299 NumLitF64,
...@@ -359,6 +364,7 @@ struct AstNode {...@@ -359,6 +364,7 @@ struct AstNode {
359 AstNodeStructDecl struct_decl;364 AstNodeStructDecl struct_decl;
360 AstNodeStructField struct_field;365 AstNodeStructField struct_field;
361 AstNodeStringLiteral string_literal;366 AstNodeStringLiteral string_literal;
367 AstNodeCharLiteral char_literal;
362 AstNodeNumberLiteral number_literal;368 AstNodeNumberLiteral number_literal;
363 AstNodeStructValueExpr struct_val_expr;369 AstNodeStructValueExpr struct_val_expr;
364 AstNodeStructValueField struct_val_field;370 AstNodeStructValueField struct_val_field;
src/tokenizer.cpp+19
...@@ -103,6 +103,7 @@ enum TokenizeState {...@@ -103,6 +103,7 @@ enum TokenizeState {
103 TokenizeStateFloatExponentUnsigned, // "123.456e", "123e", "0x123p"103 TokenizeStateFloatExponentUnsigned, // "123.456e", "123e", "0x123p"
104 TokenizeStateFloatExponentNumber, // "123.456e-", "123.456e5", "123.456e5e-5"104 TokenizeStateFloatExponentNumber, // "123.456e-", "123.456e5", "123.456e5e-5"
105 TokenizeStateString,105 TokenizeStateString,
106 TokenizeStateCharLiteral,
106 TokenizeStateSawStar,107 TokenizeStateSawStar,
107 TokenizeStateSawSlash,108 TokenizeStateSawSlash,
108 TokenizeStateSawPercent,109 TokenizeStateSawPercent,
...@@ -307,6 +308,10 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -307,6 +308,10 @@ void tokenize(Buf *buf, Tokenization *out) {
307 begin_token(&t, TokenIdStringLiteral);308 begin_token(&t, TokenIdStringLiteral);
308 t.state = TokenizeStateString;309 t.state = TokenizeStateString;
309 break;310 break;
311 case '\'':
312 begin_token(&t, TokenIdCharLiteral);
313 t.state = TokenizeStateCharLiteral;
314 break;
310 case '(':315 case '(':
311 begin_token(&t, TokenIdLParen);316 begin_token(&t, TokenIdLParen);
312 end_token(&t);317 end_token(&t);
...@@ -773,6 +778,16 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -773,6 +778,16 @@ void tokenize(Buf *buf, Tokenization *out) {
773 break;778 break;
774 }779 }
775 break;780 break;
781 case TokenizeStateCharLiteral:
782 switch (c) {
783 case '\'':
784 end_token(&t);
785 t.state = TokenizeStateStart;
786 break;
787 default:
788 break;
789 }
790 break;
776 case TokenizeStateZero:791 case TokenizeStateZero:
777 switch (c) {792 switch (c) {
778 case 'b':793 case 'b':
...@@ -912,6 +927,9 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -912,6 +927,9 @@ void tokenize(Buf *buf, Tokenization *out) {
912 case TokenizeStateString:927 case TokenizeStateString:
913 tokenize_error(&t, "unterminated string");928 tokenize_error(&t, "unterminated string");
914 break;929 break;
930 case TokenizeStateCharLiteral:
931 tokenize_error(&t, "unterminated character literal");
932 break;
915 case TokenizeStateSymbol:933 case TokenizeStateSymbol:
916 case TokenizeStateSymbolFirst:934 case TokenizeStateSymbolFirst:
917 case TokenizeStateZero:935 case TokenizeStateZero:
...@@ -993,6 +1011,7 @@ static const char * token_name(Token *token) {...@@ -993,6 +1011,7 @@ static const char * token_name(Token *token) {
993 case TokenIdLBracket: return "LBracket";1011 case TokenIdLBracket: return "LBracket";
994 case TokenIdRBracket: return "RBracket";1012 case TokenIdRBracket: return "RBracket";
995 case TokenIdStringLiteral: return "StringLiteral";1013 case TokenIdStringLiteral: return "StringLiteral";
1014 case TokenIdCharLiteral: return "CharLiteral";
996 case TokenIdSemicolon: return "Semicolon";1015 case TokenIdSemicolon: return "Semicolon";
997 case TokenIdNumberLiteral: return "NumberLiteral";1016 case TokenIdNumberLiteral: return "NumberLiteral";
998 case TokenIdPlus: return "Plus";1017 case TokenIdPlus: return "Plus";
src/tokenizer.hpp+1
...@@ -44,6 +44,7 @@ enum TokenId {...@@ -44,6 +44,7 @@ enum TokenId {
44 TokenIdLBracket,44 TokenIdLBracket,
45 TokenIdRBracket,45 TokenIdRBracket,
46 TokenIdStringLiteral,46 TokenIdStringLiteral,
47 TokenIdCharLiteral,
47 TokenIdSemicolon,48 TokenIdSemicolon,
48 TokenIdNumberLiteral,49 TokenIdNumberLiteral,
49 TokenIdPlus,50 TokenIdPlus,
std/errno.zig created+146
...@@ -0,0 +1,146 @@
1pub const EPERM = 1; // Operation not permitted
2pub const ENOENT = 2; // No such file or directory
3pub const ESRCH = 3; // No such process
4pub const EINTR = 4; // Interrupted system call
5pub const EIO = 5; // I/O error
6pub const ENXIO = 6; // No such device or address
7pub const E2BIG = 7; // Arg list too long
8pub const ENOEXEC = 8; // Exec format error
9pub const EBADF = 9; // Bad file number
10pub const ECHILD = 10; // No child processes
11pub const EAGAIN = 11; // Try again
12pub const ENOMEM = 12; // Out of memory
13pub const EACCES = 13; // Permission denied
14pub const EFAULT = 14; // Bad address
15pub const ENOTBLK = 15; // Block device required
16pub const EBUSY = 16; // Device or resource busy
17pub const EEXIST = 17; // File exists
18pub const EXDEV = 18; // Cross-device link
19pub const ENODEV = 19; // No such device
20pub const ENOTDIR = 20; // Not a directory
21pub const EISDIR = 21; // Is a directory
22pub const EINVAL = 22; // Invalid argument
23pub const ENFILE = 23; // File table overflow
24pub const EMFILE = 24; // Too many open files
25pub const ENOTTY = 25; // Not a typewriter
26pub const ETXTBSY = 26; // Text file busy
27pub const EFBIG = 27; // File too large
28pub const ENOSPC = 28; // No space left on device
29pub const ESPIPE = 29; // Illegal seek
30pub const EROFS = 30; // Read-only file system
31pub const EMLINK = 31; // Too many links
32pub const EPIPE = 32; // Broken pipe
33pub const EDOM = 33; // Math argument out of domain of func
34pub const ERANGE = 34; // Math result not representable
35pub const EDEADLK = 35; // Resource deadlock would occur
36pub const ENAMETOOLONG = 36; // File name too long
37pub const ENOLCK = 37; // No record locks available
38pub const ENOSYS = 38; // Function not implemented
39pub const ENOTEMPTY = 39; // Directory not empty
40pub const ELOOP = 40; // Too many symbolic links encountered
41pub const EWOULDBLOCK = EAGAIN; // Operation would block
42pub const ENOMSG = 42; // No message of desired type
43pub const EIDRM = 43; // Identifier removed
44pub const ECHRNG = 44; // Channel number out of range
45pub const EL2NSYNC = 45; // Level 2 not synchronized
46pub const EL3HLT = 46; // Level 3 halted
47pub const EL3RST = 47; // Level 3 reset
48pub const ELNRNG = 48; // Link number out of range
49pub const EUNATCH = 49; // Protocol driver not attached
50pub const ENOCSI = 50; // No CSI structure available
51pub const EL2HLT = 51; // Level 2 halted
52pub const EBADE = 52; // Invalid exchange
53pub const EBADR = 53; // Invalid request descriptor
54pub const EXFULL = 54; // Exchange full
55pub const ENOANO = 55; // No anode
56pub const EBADRQC = 56; // Invalid request code
57pub const EBADSLT = 57; // Invalid slot
58
59pub const EBFONT = 59; // Bad font file format
60pub const ENOSTR = 60; // Device not a stream
61pub const ENODATA = 61; // No data available
62pub const ETIME = 62; // Timer expired
63pub const ENOSR = 63; // Out of streams resources
64pub const ENONET = 64; // Machine is not on the network
65pub const ENOPKG = 65; // Package not installed
66pub const EREMOTE = 66; // Object is remote
67pub const ENOLINK = 67; // Link has been severed
68pub const EADV = 68; // Advertise error
69pub const ESRMNT = 69; // Srmount error
70pub const ECOMM = 70; // Communication error on send
71pub const EPROTO = 71; // Protocol error
72pub const EMULTIHOP = 72; // Multihop attempted
73pub const EDOTDOT = 73; // RFS specific error
74pub const EBADMSG = 74; // Not a data message
75pub const EOVERFLOW = 75; // Value too large for defined data type
76pub const ENOTUNIQ = 76; // Name not unique on network
77pub const EBADFD = 77; // File descriptor in bad state
78pub const EREMCHG = 78; // Remote address changed
79pub const ELIBACC = 79; // Can not access a needed shared library
80pub const ELIBBAD = 80; // Accessing a corrupted shared library
81pub const ELIBSCN = 81; // .lib section in a.out corrupted
82pub const ELIBMAX = 82; // Attempting to link in too many shared libraries
83pub const ELIBEXEC = 83; // Cannot exec a shared library directly
84pub const EILSEQ = 84; // Illegal byte sequence
85pub const ERESTART = 85; // Interrupted system call should be restarted
86pub const ESTRPIPE = 86; // Streams pipe error
87pub const EUSERS = 87; // Too many users
88pub const ENOTSOCK = 88; // Socket operation on non-socket
89pub const EDESTADDRREQ = 89; // Destination address required
90pub const EMSGSIZE = 90; // Message too long
91pub const EPROTOTYPE = 91; // Protocol wrong type for socket
92pub const ENOPROTOOPT = 92; // Protocol not available
93pub const EPROTONOSUPPORT = 93; // Protocol not supported
94pub const ESOCKTNOSUPPORT = 94; // Socket type not supported
95pub const EOPNOTSUPP = 95; // Operation not supported on transport endpoint
96pub const EPFNOSUPPORT = 96; // Protocol family not supported
97pub const EAFNOSUPPORT = 97; // Address family not supported by protocol
98pub const EADDRINUSE = 98; // Address already in use
99pub const EADDRNOTAVAIL = 99; // Cannot assign requested address
100pub const ENETDOWN = 100; // Network is down
101pub const ENETUNREACH = 101; // Network is unreachable
102pub const ENETRESET = 102; // Network dropped connection because of reset
103pub const ECONNABORTED = 103; // Software caused connection abort
104pub const ECONNRESET = 104; // Connection reset by peer
105pub const ENOBUFS = 105; // No buffer space available
106pub const EISCONN = 106; // Transport endpoint is already connected
107pub const ENOTCONN = 107; // Transport endpoint is not connected
108pub const ESHUTDOWN = 108; // Cannot send after transport endpoint shutdown
109pub const ETOOMANYREFS = 109; // Too many references: cannot splice
110pub const ETIMEDOUT = 110; // Connection timed out
111pub const ECONNREFUSED = 111; // Connection refused
112pub const EHOSTDOWN = 112; // Host is down
113pub const EHOSTUNREACH = 113; // No route to host
114pub const EALREADY = 114; // Operation already in progress
115pub const EINPROGRESS = 115; // Operation now in progress
116pub const ESTALE = 116; // Stale NFS file handle
117pub const EUCLEAN = 117; // Structure needs cleaning
118pub const ENOTNAM = 118; // Not a XENIX named type file
119pub const ENAVAIL = 119; // No XENIX semaphores available
120pub const EISNAM = 120; // Is a named type file
121pub const EREMOTEIO = 121; // Remote I/O error
122pub const EDQUOT = 122; // Quota exceeded
123
124pub const ENOMEDIUM = 123; // No medium found
125pub const EMEDIUMTYPE = 124; // Wrong medium type
126
127// nameserver query return codes
128pub const ENSROK = 0; // DNS server returned answer with no data
129pub const ENSRNODATA = 160; // DNS server returned answer with no data
130pub const ENSRFORMERR = 161; // DNS server claims query was misformatted
131pub const ENSRSERVFAIL = 162; // DNS server returned general failure
132pub const ENSRNOTFOUND = 163; // Domain name not found
133pub const ENSRNOTIMP = 164; // DNS server does not implement requested operation
134pub const ENSRREFUSED = 165; // DNS server refused query
135pub const ENSRBADQUERY = 166; // Misformatted DNS query
136pub const ENSRBADNAME = 167; // Misformatted domain name
137pub const ENSRBADFAMILY = 168; // Unsupported address family
138pub const ENSRBADRESP = 169; // Misformatted DNS reply
139pub const ENSRCONNREFUSED = 170; // Could not contact DNS servers
140pub const ENSRTIMEOUT = 171; // Timeout while contacting DNS servers
141pub const ENSROF = 172; // End of file
142pub const ENSRFILE = 173; // Error reading file
143pub const ENSRNOMEM = 174; // Out of memory
144pub const ENSRDESTRUCTION = 175; // Application terminated lookup
145pub const ENSRQUERYDOMAINTOOLONG = 176; // Domain name is too long
146pub const ENSRCNAMELOOP = 177; // Domain name is too long
std/std.zig+66-3
...@@ -1,6 +1,9 @@...@@ -1,6 +1,9 @@
1const SYS_write : isize = 1;1const SYS_write : isize = 1;
2const SYS_exit : isize = 60;2const SYS_exit : isize = 60;
3const SYS_getrandom : isize = 278;
4
3const stdout_fileno : isize = 1;5const stdout_fileno : isize = 1;
6const stderr_fileno : isize = 2;
47
5fn syscall1(number: isize, arg1: isize) -> isize {8fn syscall1(number: isize, arg1: isize) -> isize {
6 asm volatile ("syscall"9 asm volatile ("syscall"
...@@ -16,6 +19,12 @@ fn syscall3(number: isize, arg1: isize, arg2: isize, arg3: isize) -> isize {...@@ -16,6 +19,12 @@ fn syscall3(number: isize, arg1: isize, arg2: isize, arg3: isize) -> isize {
16 : "rcx", "r11")19 : "rcx", "r11")
17}20}
1821
22/*
23pub fn getrandom(buf: &u8, count: usize, flags: u32) -> isize {
24 return syscall3(SYS_getrandom, buf as isize, count as isize, flags as isize);
25}
26*/
27
19pub fn write(fd: isize, buf: &const u8, count: usize) -> isize {28pub fn write(fd: isize, buf: &const u8, count: usize) -> isize {
20 return syscall3(SYS_write, fd, buf as isize, count as isize);29 return syscall3(SYS_write, fd, buf as isize, count as isize);
21}30}
...@@ -25,8 +34,62 @@ pub fn exit(status: i32) -> unreachable {...@@ -25,8 +34,62 @@ pub fn exit(status: i32) -> unreachable {
25 unreachable;34 unreachable;
26}35}
2736
37/*
38fn digit_to_char(digit: u64) -> u8 { '0' + (digit as u8) }
39
40const max_u64_base10_digits: usize = 20;
41
42fn buf_print_u64(out_buf: &u8, x: u64) -> usize {
43 // TODO use max_u64_base10_digits instead of hardcoding 20
44 var buf: [u8; 20];
45 var a = x;
46 var index = max_u64_base10_digits;
47
48 while (true) {
49 const digit = a % 10;
50 index -= 1;
51 buf[index] = digit_to_char(digit);
52 a /= 10;
53 if (a == 0)
54 break;
55 }
56
57 const len = max_u64_base10_digits - index;
58
59 // TODO memcpy intrinsic
60 var i: usize = 0;
61 while (i < len) {
62 out_buf[i] = buf[index + i];
63 i += 1;
64 }
65
66 return len;
67}
68
69// TODO handle buffering and flushing (mutex protected)
70// TODO error handling
71pub fn print_u64(x: u64) -> isize {
72 // TODO use max_u64_base10_digits instead of hardcoding 20
73 var buf: [u8; 20];
74 const len = buf_print_u64(buf.ptr, x);
75 return write(stdout_fileno, buf.ptr, len);
76}
77*/
78
79
80// TODO error handling
81// TODO handle buffering and flushing (mutex protected)
82pub fn print_str(str: string) -> isize { fprint_str(stdout_fileno, str) }
83
84// TODO error handling
85// TODO handle buffering and flushing (mutex protected)
86pub fn fprint_str(fd: isize, str: string) -> isize {
87 return write(fd, str.ptr, str.len);
88}
89
90/*
28// TODO error handling91// TODO error handling
29// TODO handle buffering and flushing92pub fn os_get_random_bytes(buf: &u8, count: usize) -> isize {
30pub fn print_str(str : string) -> isize {93 return getrandom(buf, count, 0);
31 return write(stdout_fileno, str.ptr, str.len);
32}94}
95*/