| author | |
| committer | |
| log | e64c0941f9cff66311c969b85be5fe5575c4ce45 |
| tree | a3417dd85241d55362433f41e00b72d4d2cba435 |
| parent | fa6e3eec464227a2c20ca949e2fd12f3ab649960 |
closes #86 files changed, 177 insertions(+), 56 deletions(-)
doc/langref.md+5-3| ... | @@ -60,9 +60,11 @@ ParamDeclList : token(LParen) list(ParamDecl, token(Comma)) token(RParen) | ... | @@ -60,9 +60,11 @@ ParamDeclList : token(LParen) list(ParamDecl, token(Comma)) token(RParen) |
| 60 | 60 | ||
| 61 | ParamDecl : token(Symbol) token(Colon) Type | token(Ellipsis) | 61 | ParamDecl : token(Symbol) token(Colon) Type | token(Ellipsis) |
| 62 | 62 | ||
| 63 | Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType | MaybeType | CompileTimeFnCall | 63 | Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType | MaybeType | CompilerFnExpr |
| 64 | 64 | ||
| 65 | CompileTimeFnCall : token(NumberSign) token(Symbol) token(LParen) Expression token(RParen) | 65 | CompilerFnExpr : token(NumberSign) token(Symbol) token(LParen) Expression token(RParen) |
| 66 | |||
| 67 | CompilerFnType : token(NumberSign) token(Symbol) token(LParen) Type token(RParen) | ||
| 66 | 68 | ||
| 67 | PointerType : token(Ampersand) option(token(Const)) Type | 69 | PointerType : token(Ampersand) option(token(Const)) Type |
| 68 | 70 | ||
| ... | @@ -152,7 +154,7 @@ ArrayAccessExpression : token(LBracket) Expression token(RBracket) | ... | @@ -152,7 +154,7 @@ ArrayAccessExpression : token(LBracket) Expression token(RBracket) |
| 152 | 154 | ||
| 153 | PrefixOp : token(Not) | token(Dash) | token(Tilde) | (token(Ampersand) option(token(Const))) | 155 | PrefixOp : token(Not) | token(Dash) | token(Tilde) | (token(Ampersand) option(token(Const))) |
| 154 | 156 | ||
| 155 | PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression | 157 | PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression | CompilerFnType |
| 156 | 158 | ||
| 157 | StructValueExpression : token(Type) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace) | 159 | StructValueExpression : token(Type) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace) |
| 158 | 160 |
src/analyze.cpp+55-9| ... | @@ -59,7 +59,8 @@ static AstNode *first_executing_node(AstNode *node) { | ... | @@ -59,7 +59,8 @@ static AstNode *first_executing_node(AstNode *node) { |
| 59 | case NodeTypeStructValueExpr: | 59 | case NodeTypeStructValueExpr: |
| 60 | case NodeTypeStructValueField: | 60 | case NodeTypeStructValueField: |
| 61 | case NodeTypeWhileExpr: | 61 | case NodeTypeWhileExpr: |
| 62 | case NodeTypeCompilerFnCall: | 62 | case NodeTypeCompilerFnExpr: |
| 63 | case NodeTypeCompilerFnType: | ||
| 63 | return node; | 64 | return node; |
| 64 | } | 65 | } |
| 65 | zig_panic("unreachable"); | 66 | zig_panic("unreachable"); |
| ... | @@ -109,6 +110,20 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) { | ... | @@ -109,6 +110,20 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) { |
| 109 | return entry; | 110 | return entry; |
| 110 | } | 111 | } |
| 111 | 112 | ||
| 113 | static TypeTableEntry *get_number_literal_type_unsigned(CodeGen *g, uint64_t x) { | ||
| 114 | NumLit kind; | ||
| 115 | if (x <= UINT8_MAX) { | ||
| 116 | kind = NumLitU8; | ||
| 117 | } else if (x <= UINT16_MAX) { | ||
| 118 | kind = NumLitU16; | ||
| 119 | } else if (x <= UINT32_MAX) { | ||
| 120 | kind = NumLitU32; | ||
| 121 | } else { | ||
| 122 | kind = NumLitU64; | ||
| 123 | } | ||
| 124 | return g->num_lit_types[kind]; | ||
| 125 | } | ||
| 126 | |||
| 112 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) { | 127 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) { |
| 113 | TypeTableEntry **parent_pointer = is_const ? | 128 | TypeTableEntry **parent_pointer = is_const ? |
| 114 | &child_type->pointer_const_parent : | 129 | &child_type->pointer_const_parent : |
| ... | @@ -279,15 +294,16 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry | ... | @@ -279,15 +294,16 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 279 | case AstNodeTypeTypeCompilerExpr: | 294 | case AstNodeTypeTypeCompilerExpr: |
| 280 | { | 295 | { |
| 281 | AstNode *compiler_expr_node = node->data.type.compiler_expr; | 296 | AstNode *compiler_expr_node = node->data.type.compiler_expr; |
| 282 | Buf *fn_name = &compiler_expr_node->data.compiler_fn_call.name; | 297 | Buf *fn_name = &compiler_expr_node->data.compiler_fn_expr.name; |
| 283 | if (buf_eql_str(fn_name, "typeof")) { | 298 | if (buf_eql_str(fn_name, "typeof")) { |
| 284 | return analyze_expression(g, import, context, nullptr, | 299 | type_node->entry = analyze_expression(g, import, context, nullptr, |
| 285 | compiler_expr_node->data.compiler_fn_call.expr); | 300 | compiler_expr_node->data.compiler_fn_expr.expr); |
| 286 | } else { | 301 | } else { |
| 287 | add_node_error(g, node, | 302 | add_node_error(g, node, |
| 288 | buf_sprintf("invalid compiler function: '%s'", buf_ptr(fn_name))); | 303 | buf_sprintf("invalid compiler function: '%s'", buf_ptr(fn_name))); |
| 289 | return g->builtin_types.entry_invalid; | 304 | type_node->entry = g->builtin_types.entry_invalid; |
| 290 | } | 305 | } |
| 306 | return type_node->entry; | ||
| 291 | } | 307 | } |
| 292 | } | 308 | } |
| 293 | zig_unreachable(); | 309 | zig_unreachable(); |
| ... | @@ -625,7 +641,8 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, | ... | @@ -625,7 +641,8 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 625 | case NodeTypeStructField: | 641 | case NodeTypeStructField: |
| 626 | case NodeTypeStructValueExpr: | 642 | case NodeTypeStructValueExpr: |
| 627 | case NodeTypeStructValueField: | 643 | case NodeTypeStructValueField: |
| 628 | case NodeTypeCompilerFnCall: | 644 | case NodeTypeCompilerFnExpr: |
| 645 | case NodeTypeCompilerFnType: | ||
| 629 | zig_unreachable(); | 646 | zig_unreachable(); |
| 630 | } | 647 | } |
| 631 | } | 648 | } |
| ... | @@ -698,7 +715,8 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { | ... | @@ -698,7 +715,8 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 698 | case NodeTypeStructField: | 715 | case NodeTypeStructField: |
| 699 | case NodeTypeStructValueExpr: | 716 | case NodeTypeStructValueExpr: |
| 700 | case NodeTypeStructValueField: | 717 | case NodeTypeStructValueField: |
| 701 | case NodeTypeCompilerFnCall: | 718 | case NodeTypeCompilerFnExpr: |
| 719 | case NodeTypeCompilerFnType: | ||
| 702 | zig_unreachable(); | 720 | zig_unreachable(); |
| 703 | } | 721 | } |
| 704 | } | 722 | } |
| ... | @@ -1580,6 +1598,30 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -1580,6 +1598,30 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import, |
| 1580 | node->data.if_var_expr.then_block, node->data.if_var_expr.else_node, node); | 1598 | node->data.if_var_expr.then_block, node->data.if_var_expr.else_node, node); |
| 1581 | } | 1599 | } |
| 1582 | 1600 | ||
| 1601 | static TypeTableEntry *analyze_compiler_fn_type(CodeGen *g, ImportTableEntry *import, BlockContext *context, | ||
| 1602 | TypeTableEntry *expected_type, AstNode *node) | ||
| 1603 | { | ||
| 1604 | assert(node->type == NodeTypeCompilerFnType); | ||
| 1605 | |||
| 1606 | Buf *name = &node->data.compiler_fn_type.name; | ||
| 1607 | if (buf_eql_str(name, "sizeof")) { | ||
| 1608 | TypeTableEntry *type_entry = resolve_type(g, node->data.compiler_fn_type.type, import, context); | ||
| 1609 | uint64_t size_in_bytes = type_entry->size_in_bits / 8; | ||
| 1610 | |||
| 1611 | TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, size_in_bytes); | ||
| 1612 | |||
| 1613 | NumberLiteralNode *codegen_num_lit = &node->codegen_node->data.num_lit_node; | ||
| 1614 | assert(!codegen_num_lit->resolved_type); | ||
| 1615 | codegen_num_lit->resolved_type = resolve_type_compatibility(g, context, node, expected_type, num_lit_type); | ||
| 1616 | |||
| 1617 | return num_lit_type; | ||
| 1618 | } else { | ||
| 1619 | add_node_error(g, node, | ||
| 1620 | buf_sprintf("invalid compiler function: '%s'", buf_ptr(name))); | ||
| 1621 | return g->builtin_types.entry_invalid; | ||
| 1622 | } | ||
| 1623 | } | ||
| 1624 | |||
| 1583 | static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 1625 | static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1584 | TypeTableEntry *expected_type, AstNode *node) | 1626 | TypeTableEntry *expected_type, AstNode *node) |
| 1585 | { | 1627 | { |
| ... | @@ -1852,6 +1894,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -1852,6 +1894,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 1852 | case NodeTypeStructValueExpr: | 1894 | case NodeTypeStructValueExpr: |
| 1853 | return_type = analyze_struct_val_expr(g, import, context, expected_type, node); | 1895 | return_type = analyze_struct_val_expr(g, import, context, expected_type, node); |
| 1854 | break; | 1896 | break; |
| 1897 | case NodeTypeCompilerFnType: | ||
| 1898 | return_type = analyze_compiler_fn_type(g, import, context, expected_type, node); | ||
| 1899 | break; | ||
| 1855 | case NodeTypeDirective: | 1900 | case NodeTypeDirective: |
| 1856 | case NodeTypeFnDecl: | 1901 | case NodeTypeFnDecl: |
| 1857 | case NodeTypeFnProto: | 1902 | case NodeTypeFnProto: |
| ... | @@ -1866,7 +1911,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -1866,7 +1911,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 1866 | case NodeTypeStructDecl: | 1911 | case NodeTypeStructDecl: |
| 1867 | case NodeTypeStructField: | 1912 | case NodeTypeStructField: |
| 1868 | case NodeTypeStructValueField: | 1913 | case NodeTypeStructValueField: |
| 1869 | case NodeTypeCompilerFnCall: | 1914 | case NodeTypeCompilerFnExpr: |
| 1870 | zig_unreachable(); | 1915 | zig_unreachable(); |
| 1871 | } | 1916 | } |
| 1872 | assert(return_type); | 1917 | assert(return_type); |
| ... | @@ -2015,7 +2060,8 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, | ... | @@ -2015,7 +2060,8 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, |
| 2015 | case NodeTypeStructField: | 2060 | case NodeTypeStructField: |
| 2016 | case NodeTypeStructValueExpr: | 2061 | case NodeTypeStructValueExpr: |
| 2017 | case NodeTypeStructValueField: | 2062 | case NodeTypeStructValueField: |
| 2018 | case NodeTypeCompilerFnCall: | 2063 | case NodeTypeCompilerFnExpr: |
| 2064 | case NodeTypeCompilerFnType: | ||
| 2019 | zig_unreachable(); | 2065 | zig_unreachable(); |
| 2020 | } | 2066 | } |
| 2021 | } | 2067 | } |
src/codegen.cpp+56-26| ... | @@ -1191,6 +1191,58 @@ static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) { | ... | @@ -1191,6 +1191,58 @@ static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) { |
| 1191 | node->codegen_node->expr_node.block_context, false, &init_val); | 1191 | node->codegen_node->expr_node.block_context, false, &init_val); |
| 1192 | } | 1192 | } |
| 1193 | 1193 | ||
| 1194 | static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node, | ||
| 1195 | NumberLiteralNode *codegen_num_lit, AstNodeNumberLiteral *num_lit_node) | ||
| 1196 | { | ||
| 1197 | TypeTableEntry *type_entry = codegen_num_lit->resolved_type; | ||
| 1198 | assert(type_entry); | ||
| 1199 | |||
| 1200 | // override the expression type for number literals | ||
| 1201 | source_node->codegen_node->expr_node.type_entry = type_entry; | ||
| 1202 | |||
| 1203 | if (type_entry->id == TypeTableEntryIdInt) { | ||
| 1204 | // here the union has int64_t and uint64_t and we purposefully read | ||
| 1205 | // the uint64_t value in either case, because we want the twos | ||
| 1206 | // complement representation | ||
| 1207 | |||
| 1208 | return LLVMConstInt(type_entry->type_ref, | ||
| 1209 | num_lit_node->data.x_uint, | ||
| 1210 | type_entry->data.integral.is_signed); | ||
| 1211 | } else if (type_entry->id == TypeTableEntryIdFloat) { | ||
| 1212 | |||
| 1213 | return LLVMConstReal(type_entry->type_ref, | ||
| 1214 | num_lit_node->data.x_float); | ||
| 1215 | } else { | ||
| 1216 | zig_panic("bad number literal type"); | ||
| 1217 | } | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | static LLVMValueRef gen_compiler_fn_type(CodeGen *g, AstNode *node) { | ||
| 1221 | assert(node->type == NodeTypeCompilerFnType); | ||
| 1222 | |||
| 1223 | Buf *name = &node->data.compiler_fn_type.name; | ||
| 1224 | if (buf_eql_str(name, "sizeof")) { | ||
| 1225 | TypeTableEntry *type_entry = get_type_for_type_node(g, node->data.compiler_fn_type.type); | ||
| 1226 | NumberLiteralNode *codegen_num_lit = &node->codegen_node->data.num_lit_node; | ||
| 1227 | AstNodeNumberLiteral num_lit_node; | ||
| 1228 | num_lit_node.kind = type_entry->data.num_lit.kind; | ||
| 1229 | num_lit_node.overflow = false; | ||
| 1230 | num_lit_node.data.x_uint = type_entry->size_in_bits / 8; | ||
| 1231 | return gen_number_literal_raw(g, node, codegen_num_lit, &num_lit_node); | ||
| 1232 | } else { | ||
| 1233 | zig_unreachable(); | ||
| 1234 | } | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | static LLVMValueRef gen_number_literal(CodeGen *g, AstNode *node) { | ||
| 1238 | assert(node->type == NodeTypeNumberLiteral); | ||
| 1239 | |||
| 1240 | NumberLiteralNode *codegen_num_lit = &node->codegen_node->data.num_lit_node; | ||
| 1241 | assert(codegen_num_lit); | ||
| 1242 | |||
| 1243 | return gen_number_literal_raw(g, node, codegen_num_lit, &node->data.number_literal); | ||
| 1244 | } | ||
| 1245 | |||
| 1194 | static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | 1246 | static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1195 | switch (node->type) { | 1247 | switch (node->type) { |
| 1196 | case NodeTypeBinOpExpr: | 1248 | case NodeTypeBinOpExpr: |
| ... | @@ -1228,31 +1280,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -1228,31 +1280,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1228 | case NodeTypeAsmExpr: | 1280 | case NodeTypeAsmExpr: |
| 1229 | return gen_asm_expr(g, node); | 1281 | return gen_asm_expr(g, node); |
| 1230 | case NodeTypeNumberLiteral: | 1282 | case NodeTypeNumberLiteral: |
| 1231 | { | 1283 | return gen_number_literal(g, node); |
| 1232 | NumberLiteralNode *codegen_num_lit = &node->codegen_node->data.num_lit_node; | ||
| 1233 | assert(codegen_num_lit); | ||
| 1234 | TypeTableEntry *type_entry = codegen_num_lit->resolved_type; | ||
| 1235 | assert(type_entry); | ||
| 1236 | |||
| 1237 | // override the expression type for number literals | ||
| 1238 | node->codegen_node->expr_node.type_entry = type_entry; | ||
| 1239 | |||
| 1240 | if (type_entry->id == TypeTableEntryIdInt) { | ||
| 1241 | // here the union has int64_t and uint64_t and we purposefully read | ||
| 1242 | // the uint64_t value in either case, because we want the twos | ||
| 1243 | // complement representation | ||
| 1244 | |||
| 1245 | return LLVMConstInt(type_entry->type_ref, | ||
| 1246 | node->data.number_literal.data.x_uint, | ||
| 1247 | type_entry->data.integral.is_signed); | ||
| 1248 | } else if (type_entry->id == TypeTableEntryIdFloat) { | ||
| 1249 | |||
| 1250 | return LLVMConstReal(type_entry->type_ref, | ||
| 1251 | node->data.number_literal.data.x_float); | ||
| 1252 | } else { | ||
| 1253 | zig_panic("bad number literal type"); | ||
| 1254 | } | ||
| 1255 | } | ||
| 1256 | case NodeTypeStringLiteral: | 1284 | case NodeTypeStringLiteral: |
| 1257 | { | 1285 | { |
| 1258 | Buf *str = &node->data.string_literal.buf; | 1286 | Buf *str = &node->data.string_literal.buf; |
| ... | @@ -1313,6 +1341,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -1313,6 +1341,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1313 | } | 1341 | } |
| 1314 | case NodeTypeStructValueExpr: | 1342 | case NodeTypeStructValueExpr: |
| 1315 | return gen_struct_val_expr(g, node); | 1343 | return gen_struct_val_expr(g, node); |
| 1344 | case NodeTypeCompilerFnType: | ||
| 1345 | return gen_compiler_fn_type(g, node); | ||
| 1316 | case NodeTypeRoot: | 1346 | case NodeTypeRoot: |
| 1317 | case NodeTypeRootExportDecl: | 1347 | case NodeTypeRootExportDecl: |
| 1318 | case NodeTypeFnProto: | 1348 | case NodeTypeFnProto: |
| ... | @@ -1326,7 +1356,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -1326,7 +1356,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1326 | case NodeTypeStructDecl: | 1356 | case NodeTypeStructDecl: |
| 1327 | case NodeTypeStructField: | 1357 | case NodeTypeStructField: |
| 1328 | case NodeTypeStructValueField: | 1358 | case NodeTypeStructValueField: |
| 1329 | case NodeTypeCompilerFnCall: | 1359 | case NodeTypeCompilerFnExpr: |
| 1330 | zig_unreachable(); | 1360 | zig_unreachable(); |
| 1331 | } | 1361 | } |
| 1332 | zig_unreachable(); | 1362 | zig_unreachable(); |
src/parser.cpp+47-12| ... | @@ -142,8 +142,10 @@ const char *node_type_str(NodeType node_type) { | ... | @@ -142,8 +142,10 @@ const char *node_type_str(NodeType node_type) { |
| 142 | return "StructValueExpr"; | 142 | return "StructValueExpr"; |
| 143 | case NodeTypeStructValueField: | 143 | case NodeTypeStructValueField: |
| 144 | return "StructValueField"; | 144 | return "StructValueField"; |
| 145 | case NodeTypeCompilerFnCall: | 145 | case NodeTypeCompilerFnExpr: |
| 146 | return "CompilerFnCall"; | 146 | return "CompilerFnExpr"; |
| 147 | case NodeTypeCompilerFnType: | ||
| 148 | return "CompilerFnType"; | ||
| 147 | } | 149 | } |
| 148 | zig_unreachable(); | 150 | zig_unreachable(); |
| 149 | } | 151 | } |
| ... | @@ -410,7 +412,10 @@ void ast_print(AstNode *node, int indent) { | ... | @@ -410,7 +412,10 @@ void ast_print(AstNode *node, int indent) { |
| 410 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name)); | 412 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name)); |
| 411 | ast_print(node->data.struct_val_field.expr, indent + 2); | 413 | ast_print(node->data.struct_val_field.expr, indent + 2); |
| 412 | break; | 414 | break; |
| 413 | case NodeTypeCompilerFnCall: | 415 | case NodeTypeCompilerFnExpr: |
| 416 | fprintf(stderr, "%s\n", node_type_str(node->type)); | ||
| 417 | break; | ||
| 418 | case NodeTypeCompilerFnType: | ||
| 414 | fprintf(stderr, "%s\n", node_type_str(node->type)); | 419 | fprintf(stderr, "%s\n", node_type_str(node->type)); |
| 415 | break; | 420 | break; |
| 416 | } | 421 | } |
| ... | @@ -996,7 +1001,32 @@ static void ast_parse_type_assume_amp(ParseContext *pc, int *token_index, AstNod | ... | @@ -996,7 +1001,32 @@ static void ast_parse_type_assume_amp(ParseContext *pc, int *token_index, AstNod |
| 996 | } | 1001 | } |
| 997 | 1002 | ||
| 998 | /* | 1003 | /* |
| 999 | CompileTimeFnCall : token(NumberSign) token(Symbol) token(LParen) Expression token(RParen) | 1004 | CompilerFnType : token(NumberSign) token(Symbol) token(LParen) Expression token(RParen) |
| 1005 | */ | ||
| 1006 | static AstNode *ast_parse_compiler_fn_type(ParseContext *pc, int *token_index, bool mandatory) { | ||
| 1007 | Token *token = &pc->tokens->at(*token_index); | ||
| 1008 | |||
| 1009 | if (token->id == TokenIdNumberSign) { | ||
| 1010 | *token_index += 1; | ||
| 1011 | } else if (mandatory) { | ||
| 1012 | ast_invalid_token_error(pc, token); | ||
| 1013 | } else { | ||
| 1014 | return nullptr; | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | Token *name_symbol = ast_eat_token(pc, token_index, TokenIdSymbol); | ||
| 1018 | ast_eat_token(pc, token_index, TokenIdLParen); | ||
| 1019 | |||
| 1020 | AstNode *node = ast_create_node(pc, NodeTypeCompilerFnType, token); | ||
| 1021 | ast_buf_from_token(pc, name_symbol, &node->data.compiler_fn_type.name); | ||
| 1022 | node->data.compiler_fn_type.type = ast_parse_type(pc, token_index); | ||
| 1023 | |||
| 1024 | ast_eat_token(pc, token_index, TokenIdRParen); | ||
| 1025 | return node; | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | /* | ||
| 1029 | CompilerFnExpr : token(NumberSign) token(Symbol) token(LParen) Expression token(RParen) | ||
| 1000 | */ | 1030 | */ |
| 1001 | static AstNode *ast_parse_compiler_fn_call(ParseContext *pc, int *token_index, bool mandatory) { | 1031 | static AstNode *ast_parse_compiler_fn_call(ParseContext *pc, int *token_index, bool mandatory) { |
| 1002 | Token *token = &pc->tokens->at(*token_index); | 1032 | Token *token = &pc->tokens->at(*token_index); |
| ... | @@ -1012,16 +1042,16 @@ static AstNode *ast_parse_compiler_fn_call(ParseContext *pc, int *token_index, b | ... | @@ -1012,16 +1042,16 @@ static AstNode *ast_parse_compiler_fn_call(ParseContext *pc, int *token_index, b |
| 1012 | Token *name_symbol = ast_eat_token(pc, token_index, TokenIdSymbol); | 1042 | Token *name_symbol = ast_eat_token(pc, token_index, TokenIdSymbol); |
| 1013 | ast_eat_token(pc, token_index, TokenIdLParen); | 1043 | ast_eat_token(pc, token_index, TokenIdLParen); |
| 1014 | 1044 | ||
| 1015 | AstNode *node = ast_create_node(pc, NodeTypeCompilerFnCall, token); | 1045 | AstNode *node = ast_create_node(pc, NodeTypeCompilerFnExpr, token); |
| 1016 | ast_buf_from_token(pc, name_symbol, &node->data.compiler_fn_call.name); | 1046 | ast_buf_from_token(pc, name_symbol, &node->data.compiler_fn_expr.name); |
| 1017 | node->data.compiler_fn_call.expr = ast_parse_expression(pc, token_index, true); | 1047 | node->data.compiler_fn_expr.expr = ast_parse_expression(pc, token_index, true); |
| 1018 | 1048 | ||
| 1019 | ast_eat_token(pc, token_index, TokenIdRParen); | 1049 | ast_eat_token(pc, token_index, TokenIdRParen); |
| 1020 | return node; | 1050 | return node; |
| 1021 | } | 1051 | } |
| 1022 | 1052 | ||
| 1023 | /* | 1053 | /* |
| 1024 | Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType | MaybeType | CompileTimeFnCall | 1054 | Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType | MaybeType | CompilerFnExpr |
| 1025 | PointerType : token(Ampersand) option(token(Const)) Type | 1055 | PointerType : token(Ampersand) option(token(Const)) Type |
| 1026 | ArrayType : token(LBracket) Type token(Semicolon) token(Number) token(RBracket) | 1056 | ArrayType : token(LBracket) Type token(Semicolon) token(Number) token(RBracket) |
| 1027 | */ | 1057 | */ |
| ... | @@ -1029,10 +1059,10 @@ static AstNode *ast_parse_type(ParseContext *pc, int *token_index) { | ... | @@ -1029,10 +1059,10 @@ static AstNode *ast_parse_type(ParseContext *pc, int *token_index) { |
| 1029 | Token *token = &pc->tokens->at(*token_index); | 1059 | Token *token = &pc->tokens->at(*token_index); |
| 1030 | AstNode *node = ast_create_node(pc, NodeTypeType, token); | 1060 | AstNode *node = ast_create_node(pc, NodeTypeType, token); |
| 1031 | 1061 | ||
| 1032 | AstNode *compiler_fn_call = ast_parse_compiler_fn_call(pc, token_index, false); | 1062 | AstNode *compiler_fn_expr = ast_parse_compiler_fn_call(pc, token_index, false); |
| 1033 | if (compiler_fn_call) { | 1063 | if (compiler_fn_expr) { |
| 1034 | node->data.type.type = AstNodeTypeTypeCompilerExpr; | 1064 | node->data.type.type = AstNodeTypeTypeCompilerExpr; |
| 1035 | node->data.type.compiler_expr = compiler_fn_call; | 1065 | node->data.type.compiler_expr = compiler_fn_expr; |
| 1036 | return node; | 1066 | return node; |
| 1037 | } | 1067 | } |
| 1038 | 1068 | ||
| ... | @@ -1238,7 +1268,7 @@ static AstNode *ast_parse_struct_val_expr(ParseContext *pc, int *token_index) { | ... | @@ -1238,7 +1268,7 @@ static AstNode *ast_parse_struct_val_expr(ParseContext *pc, int *token_index) { |
| 1238 | } | 1268 | } |
| 1239 | 1269 | ||
| 1240 | /* | 1270 | /* |
| 1241 | PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression | 1271 | PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression | CompilerFnType |
| 1242 | */ | 1272 | */ |
| 1243 | static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) { | 1273 | static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) { |
| 1244 | Token *token = &pc->tokens->at(*token_index); | 1274 | Token *token = &pc->tokens->at(*token_index); |
| ... | @@ -1317,6 +1347,11 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool | ... | @@ -1317,6 +1347,11 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool |
| 1317 | return block_expr_node; | 1347 | return block_expr_node; |
| 1318 | } | 1348 | } |
| 1319 | 1349 | ||
| 1350 | AstNode *compiler_fn_type = ast_parse_compiler_fn_type(pc, token_index, false); | ||
| 1351 | if (compiler_fn_type) { | ||
| 1352 | return compiler_fn_type; | ||
| 1353 | } | ||
| 1354 | |||
| 1320 | if (!mandatory) | 1355 | if (!mandatory) |
| 1321 | return nullptr; | 1356 | return nullptr; |
| 1322 | 1357 |
src/parser.hpp+10-3| ... | @@ -57,7 +57,8 @@ enum NodeType { | ... | @@ -57,7 +57,8 @@ enum NodeType { |
| 57 | NodeTypeStructField, | 57 | NodeTypeStructField, |
| 58 | NodeTypeStructValueExpr, | 58 | NodeTypeStructValueExpr, |
| 59 | NodeTypeStructValueField, | 59 | NodeTypeStructValueField, |
| 60 | NodeTypeCompilerFnCall, | 60 | NodeTypeCompilerFnExpr, |
| 61 | NodeTypeCompilerFnType, | ||
| 61 | }; | 62 | }; |
| 62 | 63 | ||
| 63 | struct AstNodeRoot { | 64 | struct AstNodeRoot { |
| ... | @@ -332,11 +333,16 @@ struct AstNodeStructValueExpr { | ... | @@ -332,11 +333,16 @@ struct AstNodeStructValueExpr { |
| 332 | ZigList<AstNode *> fields; | 333 | ZigList<AstNode *> fields; |
| 333 | }; | 334 | }; |
| 334 | 335 | ||
| 335 | struct AstNodeCompilerFnCall { | 336 | struct AstNodeCompilerFnExpr { |
| 336 | Buf name; | 337 | Buf name; |
| 337 | AstNode *expr; | 338 | AstNode *expr; |
| 338 | }; | 339 | }; |
| 339 | 340 | ||
| 341 | struct AstNodeCompilerFnType { | ||
| 342 | Buf name; | ||
| 343 | AstNode *type; | ||
| 344 | }; | ||
| 345 | |||
| 340 | struct AstNode { | 346 | struct AstNode { |
| 341 | enum NodeType type; | 347 | enum NodeType type; |
| 342 | int line; | 348 | int line; |
| ... | @@ -376,7 +382,8 @@ struct AstNode { | ... | @@ -376,7 +382,8 @@ struct AstNode { |
| 376 | AstNodeNumberLiteral number_literal; | 382 | AstNodeNumberLiteral number_literal; |
| 377 | AstNodeStructValueExpr struct_val_expr; | 383 | AstNodeStructValueExpr struct_val_expr; |
| 378 | AstNodeStructValueField struct_val_field; | 384 | AstNodeStructValueField struct_val_field; |
| 379 | AstNodeCompilerFnCall compiler_fn_call; | 385 | AstNodeCompilerFnExpr compiler_fn_expr; |
| 386 | AstNodeCompilerFnType compiler_fn_type; | ||
| 380 | Buf symbol; | 387 | Buf symbol; |
| 381 | bool bool_literal; | 388 | bool bool_literal; |
| 382 | } data; | 389 | } data; |
test/run_tests.cpp+4-3| ... | @@ -698,16 +698,17 @@ fn outer() -> isize { | ... | @@ -698,16 +698,17 @@ fn outer() -> isize { |
| 698 | } | 698 | } |
| 699 | )SOURCE", "OK\n"); | 699 | )SOURCE", "OK\n"); |
| 700 | 700 | ||
| 701 | add_simple_case("#typeof()", R"SOURCE( | 701 | add_simple_case("#sizeof() and #typeof()", R"SOURCE( |
| 702 | use "std.zig"; | 702 | use "std.zig"; |
| 703 | const x: u16 = 13; | 703 | const x: u16 = 13; |
| 704 | const z: #typeof(x) = 19; | 704 | const z: #typeof(x) = 19; |
| 705 | pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | 705 | pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 706 | const y: #typeof(x) = 120; | 706 | const y: #typeof(x) = 120; |
| 707 | print_str("OK\n"); | 707 | print_u64(#sizeof(#typeof(y))); |
| 708 | print_str("\n"); | ||
| 708 | return 0; | 709 | return 0; |
| 709 | } | 710 | } |
| 710 | )SOURCE", "OK\n"); | 711 | )SOURCE", "2\n"); |
| 711 | } | 712 | } |
| 712 | 713 | ||
| 713 | //////////////////////////////////////////////////////////////////////////////////// | 714 | //////////////////////////////////////////////////////////////////////////////////// |