diff options
| author | Josh Wolfe <thejoshwolfe@gmail.com> | 2015-11-29 14:52:49 -0700 |
|---|---|---|
| committer | Josh Wolfe <thejoshwolfe@gmail.com> | 2015-11-29 14:52:49 -0700 |
| commit | 30442ed893c4477851d37c865eb978c4bf27c814 (patch) | |
| tree | 406d86f58bcda7ab68affb8c37c6787854338884 /src | |
| parent | 9a014b52ccc22d7ec24804f90993cfe08e3d20c4 (diff) | |
| parent | c1d77f2a231461d88ad493c92079cc571e565f87 (diff) | |
| download | zig-30442ed893c4477851d37c865eb978c4bf27c814.tar.gz zig-30442ed893c4477851d37c865eb978c4bf27c814.zip | |
merge conflicts
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen.cpp | 125 | ||||
| -rw-r--r-- | src/parser.cpp | 152 | ||||
| -rw-r--r-- | src/parser.hpp | 28 | ||||
| -rw-r--r-- | src/tokenizer.cpp | 9 | ||||
| -rw-r--r-- | src/tokenizer.hpp | 3 |
5 files changed, 216 insertions, 101 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index 5869ef8278..2193acafd5 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -306,9 +306,10 @@ static void find_declarations(CodeGen *g, AstNode *node) { case NodeTypeRoot: case NodeTypeBlock: case NodeTypeBinOpExpr: - case NodeTypeFnCall: + case NodeTypeFnCallExpr: case NodeTypeRootExportDecl: case NodeTypeCastExpr: + case NodeTypePrefixOpExpr: case NodeTypePrimaryExpr: case NodeTypeGroupedExpr: zig_unreachable(); @@ -369,6 +370,14 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) { } } +static Buf *hack_get_fn_call_name(CodeGen *g, AstNode *node) { + // Assume that the expression evaluates to a simple name and return the buf + // TODO after type checking works we should be able to remove this hack + assert(node->type == NodeTypePrimaryExpr); + assert(node->data.primary_expr.type == PrimaryExprTypeSymbol); + return &node->data.primary_expr.data.symbol; +} + static void analyze_node(CodeGen *g, AstNode *node) { switch (node->type) { case NodeTypeRoot: @@ -477,9 +486,9 @@ static void analyze_node(CodeGen *g, AstNode *node) { analyze_node(g, node->data.bin_op_expr.op1); analyze_node(g, node->data.bin_op_expr.op2); break; - case NodeTypeFnCall: + case NodeTypeFnCallExpr: { - Buf *name = &node->data.fn_call.name; + Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr); auto entry = g->fn_table.maybe_get(name); if (!entry) { @@ -489,7 +498,7 @@ static void analyze_node(CodeGen *g, AstNode *node) { FnTableEntry *fn_table_entry = entry->value; assert(fn_table_entry->proto_node->type == NodeTypeFnProto); int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length; - int actual_param_count = node->data.fn_call.params.length; + int actual_param_count = node->data.fn_call_expr.params.length; if (expected_param_count != actual_param_count) { add_node_error(g, node, buf_sprintf("wrong number of arguments. Expected %d, got %d.", @@ -497,8 +506,8 @@ static void analyze_node(CodeGen *g, AstNode *node) { } } - for (int i = 0; i < node->data.fn_call.params.length; i += 1) { - AstNode *child = node->data.fn_call.params.at(i); + for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) { + AstNode *child = node->data.fn_call_expr.params.at(i); analyze_node(g, child); } break; @@ -509,16 +518,17 @@ static void analyze_node(CodeGen *g, AstNode *node) { case NodeTypeCastExpr: zig_panic("TODO"); break; + case NodeTypePrefixOpExpr: + zig_panic("TODO"); + break; case NodeTypePrimaryExpr: switch (node->data.primary_expr.type) { case PrimaryExprTypeNumber: case PrimaryExprTypeString: case PrimaryExprTypeUnreachable: + case PrimaryExprTypeSymbol: // nothing to do break; - case PrimaryExprTypeFnCall: - analyze_node(g, node->data.primary_expr.data.fn_call); - break; case PrimaryExprTypeGroupedExpr: analyze_node(g, node->data.primary_expr.data.grouped_expr); break; @@ -625,33 +635,6 @@ static void add_debug_source_node(CodeGen *g, AstNode *node) { g->block_scopes.last())); } -static LLVMValueRef gen_fn_call(CodeGen *g, AstNode *fn_call_node) { - assert(fn_call_node->type == NodeTypeFnCall); - - Buf *name = &fn_call_node->data.fn_call.name; - FnTableEntry *fn_table_entry = g->fn_table.get(name); - assert(fn_table_entry->proto_node->type == NodeTypeFnProto); - int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length; - int actual_param_count = fn_call_node->data.fn_call.params.length; - assert(expected_param_count == actual_param_count); - - LLVMValueRef *param_values = allocate<LLVMValueRef>(actual_param_count); - for (int i = 0; i < actual_param_count; i += 1) { - AstNode *expr_node = fn_call_node->data.fn_call.params.at(i); - param_values[i] = gen_expr(g, expr_node); - } - - add_debug_source_node(g, fn_call_node); - LLVMValueRef result = LLVMZigBuildCall(g->builder, fn_table_entry->fn_value, - param_values, actual_param_count, fn_table_entry->calling_convention, ""); - - if (type_is_unreachable(fn_table_entry->proto_node->data.fn_proto.return_type)) { - return LLVMBuildUnreachable(g->builder); - } else { - return result; - } -} - static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str) { auto entry = g->str_table.maybe_get(str); if (entry) { @@ -696,21 +679,76 @@ static LLVMValueRef gen_primary_expr(CodeGen *g, AstNode *node) { case PrimaryExprTypeUnreachable: add_debug_source_node(g, node); return LLVMBuildUnreachable(g->builder); - case PrimaryExprTypeFnCall: - return gen_fn_call(g, prim_expr->data.fn_call); case PrimaryExprTypeGroupedExpr: return gen_expr(g, prim_expr->data.grouped_expr); case PrimaryExprTypeBlock: + zig_panic("TODO block in expression"); break; + case PrimaryExprTypeSymbol: + zig_panic("TODO variable reference"); + break; + } + + zig_unreachable(); +} + +static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { + assert(node->type == NodeTypeFnCallExpr); + + Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr); + + FnTableEntry *fn_table_entry = g->fn_table.get(name); + assert(fn_table_entry->proto_node->type == NodeTypeFnProto); + int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length; + int actual_param_count = node->data.fn_call_expr.params.length; + assert(expected_param_count == actual_param_count); + + LLVMValueRef *param_values = allocate<LLVMValueRef>(actual_param_count); + for (int i = 0; i < actual_param_count; i += 1) { + AstNode *expr_node = node->data.fn_call_expr.params.at(i); + param_values[i] = gen_expr(g, expr_node); } + add_debug_source_node(g, node); + LLVMValueRef result = LLVMZigBuildCall(g->builder, fn_table_entry->fn_value, + param_values, actual_param_count, fn_table_entry->calling_convention, ""); + + if (type_is_unreachable(fn_table_entry->proto_node->data.fn_proto.return_type)) { + return LLVMBuildUnreachable(g->builder); + } else { + return result; + } +} + +static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { + assert(node->type == NodeTypePrefixOpExpr); + assert(node->data.prefix_op_expr.primary_expr); + + LLVMValueRef expr = gen_expr(g, node->data.prefix_op_expr.primary_expr); + + switch (node->data.prefix_op_expr.prefix_op) { + case PrefixOpNegation: + add_debug_source_node(g, node); + return LLVMBuildNeg(g->builder, expr, ""); + case PrefixOpBoolNot: + { + LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr)); + add_debug_source_node(g, node); + return LLVMBuildICmp(g->builder, LLVMIntEQ, expr, zero, ""); + } + case PrefixOpBinNot: + add_debug_source_node(g, node); + return LLVMBuildNot(g->builder, expr, ""); + case PrefixOpInvalid: + zig_unreachable(); + } zig_unreachable(); } static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { assert(node->type == NodeTypeCastExpr); - LLVMValueRef expr = gen_primary_expr(g, node->data.cast_expr.primary_expr); + LLVMValueRef expr = gen_expr(g, node->data.cast_expr.prefix_op_expr); if (!node->data.cast_expr.type) return expr; @@ -968,6 +1006,12 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { return gen_return_expr(g, node); case NodeTypeCastExpr: return gen_cast_expr(g, node); + case NodeTypePrefixOpExpr: + return gen_prefix_op_expr(g, node); + case NodeTypeFnCallExpr: + return gen_fn_call_expr(g, node); + case NodeTypePrimaryExpr: + return gen_primary_expr(g, node); case NodeTypeRoot: case NodeTypeRootExportDecl: case NodeTypeFnProto: @@ -976,11 +1020,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { case NodeTypeParamDecl: case NodeTypeType: case NodeTypeBlock: - case NodeTypeFnCall: case NodeTypeExternBlock: case NodeTypeDirective: - case NodeTypePrimaryExpr: - return gen_primary_expr(g, node); case NodeTypeGroupedExpr: zig_unreachable(); } diff --git a/src/parser.cpp b/src/parser.cpp index 693cc6d2c0..34d7f4ae96 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -35,6 +35,16 @@ static const char *bin_op_str(BinOpType bin_op) { zig_unreachable(); } +static const char *prefix_op_str(PrefixOp prefix_op) { + switch (prefix_op) { + case PrefixOpInvalid: return "(invalid)"; + case PrefixOpNegation: return "-"; + case PrefixOpBoolNot: return "!"; + case PrefixOpBinNot: return "~"; + } + zig_unreachable(); +} + __attribute__ ((format (printf, 2, 3))) __attribute__ ((noreturn)) static void ast_error(Token *token, const char *format, ...) { @@ -70,8 +80,8 @@ const char *node_type_str(NodeType node_type) { return "Block"; case NodeTypeBinOpExpr: return "BinOpExpr"; - case NodeTypeFnCall: - return "FnCall"; + case NodeTypeFnCallExpr: + return "FnCallExpr"; case NodeTypeExternBlock: return "ExternBlock"; case NodeTypeDirective: @@ -84,6 +94,8 @@ const char *node_type_str(NodeType node_type) { return "PrimaryExpr"; case NodeTypeGroupedExpr: return "GroupedExpr"; + case NodeTypePrefixOpExpr: + return "PrefixOpExpr"; } zig_unreachable(); } @@ -188,10 +200,11 @@ void ast_print(AstNode *node, int indent) { ast_print(node->data.bin_op_expr.op1, indent + 2); ast_print(node->data.bin_op_expr.op2, indent + 2); break; - case NodeTypeFnCall: - fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.fn_call.name)); - for (int i = 0; i < node->data.fn_call.params.length; i += 1) { - AstNode *child = node->data.fn_call.params.at(i); + case NodeTypeFnCallExpr: + fprintf(stderr, "%s\n", node_type_str(node->type)); + ast_print(node->data.fn_call_expr.fn_ref_expr, indent + 2); + for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) { + AstNode *child = node->data.fn_call_expr.params.at(i); ast_print(child, indent + 2); } break; @@ -200,10 +213,15 @@ void ast_print(AstNode *node, int indent) { break; case NodeTypeCastExpr: fprintf(stderr, "%s\n", node_type_str(node->type)); - ast_print(node->data.cast_expr.primary_expr, indent + 2); + ast_print(node->data.cast_expr.prefix_op_expr, indent + 2); if (node->data.cast_expr.type) ast_print(node->data.cast_expr.type, indent + 2); break; + case NodeTypePrefixOpExpr: + fprintf(stderr, "%s %s\n", node_type_str(node->type), + prefix_op_str(node->data.prefix_op_expr.prefix_op)); + ast_print(node->data.prefix_op_expr.primary_expr, indent + 2); + break; case NodeTypePrimaryExpr: switch (node->data.primary_expr.type) { case PrimaryExprTypeNumber: @@ -217,10 +235,6 @@ void ast_print(AstNode *node, int indent) { case PrimaryExprTypeUnreachable: fprintf(stderr, "PrimaryExpr Unreachable\n"); break; - case PrimaryExprTypeFnCall: - fprintf(stderr, "PrimaryExpr FnCall\n"); - ast_print(node->data.primary_expr.data.fn_call, indent + 2); - break; case PrimaryExprTypeGroupedExpr: fprintf(stderr, "PrimaryExpr GroupedExpr\n"); ast_print(node->data.primary_expr.data.grouped_expr, indent + 2); @@ -229,6 +243,10 @@ void ast_print(AstNode *node, int indent) { fprintf(stderr, "PrimaryExpr Block\n"); ast_print(node->data.primary_expr.data.block, indent + 2); break; + case PrimaryExprTypeSymbol: + fprintf(stderr, "PrimaryExpr Symbol %s\n", + buf_ptr(&node->data.primary_expr.data.symbol)); + break; } break; case NodeTypeGroupedExpr: @@ -525,32 +543,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, int *token_index, bool } /* -FnCall : token(Symbol) token(LParen) list(Expression, token(Comma)) token(RParen) ; -*/ -static AstNode *ast_parse_fn_call(ParseContext *pc, int *token_index, bool mandatory) { - Token *fn_name = &pc->tokens->at(*token_index); - if (fn_name->id != TokenIdSymbol) { - if (mandatory) { - ast_invalid_token_error(pc, fn_name); - } else { - return nullptr; - } - } - - *token_index += 1; - - AstNode *node = ast_create_node(NodeTypeFnCall, fn_name); - - - ast_buf_from_token(pc, fn_name, &node->data.fn_call.name); - - ast_parse_fn_call_param_list(pc, *token_index, token_index, &node->data.fn_call.params); - - return node; -} - -/* -PrimaryExpression : token(Number) | token(String) | token(Unreachable) | FnCall | GroupedExpression | Block +PrimaryExpression : token(Number) | token(String) | token(Unreachable) | GroupedExpression | Block | token(Symbol) */ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) { Token *token = &pc->tokens->at(*token_index); @@ -572,6 +565,12 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool node->data.primary_expr.type = PrimaryExprTypeUnreachable; *token_index += 1; return node; + } else if (token->id == TokenIdSymbol) { + AstNode *node = ast_create_node(NodeTypePrimaryExpr, token); + node->data.primary_expr.type = PrimaryExprTypeSymbol; + ast_buf_from_token(pc, token, &node->data.primary_expr.data.symbol); + *token_index += 1; + return node; } AstNode *block_node = ast_parse_block(pc, token_index, false); @@ -590,14 +589,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool return node; } - AstNode *fn_call_node = ast_parse_fn_call(pc, token_index, false); - if (fn_call_node) { - AstNode *node = ast_create_node(NodeTypePrimaryExpr, token); - node->data.primary_expr.type = PrimaryExprTypeFnCall; - node->data.primary_expr.data.fn_call = fn_call_node; - return node; - } - if (!mandatory) return nullptr; @@ -605,20 +596,83 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool } /* -CastExpression : PrimaryExpression token(As) Type | PrimaryExpression +FnCallExpression : PrimaryExpression token(LParen) list(Expression, token(Comma)) token(RParen) | PrimaryExpression */ -static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bool mandatory) { +static AstNode *ast_parse_fn_call_expr(ParseContext *pc, int *token_index, bool mandatory) { AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, mandatory); if (!primary_expr) return nullptr; + Token *l_paren = &pc->tokens->at(*token_index); + if (l_paren->id != TokenIdLParen) + return primary_expr; + + AstNode *node = ast_create_node_with_node(NodeTypeFnCallExpr, primary_expr); + node->data.fn_call_expr.fn_ref_expr = primary_expr; + ast_parse_fn_call_param_list(pc, *token_index, token_index, &node->data.fn_call_expr.params); + + return node; +} + +static PrefixOp tok_to_prefix_op(Token *token) { + switch (token->id) { + case TokenIdBang: return PrefixOpBoolNot; + case TokenIdDash: return PrefixOpNegation; + case TokenIdTilde: return PrefixOpBinNot; + default: return PrefixOpInvalid; + } +} + +/* +PrefixOp : token(Not) | token(Dash) | token(Tilde) +*/ +static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool mandatory) { + Token *token = &pc->tokens->at(*token_index); + PrefixOp result = tok_to_prefix_op(token); + if (result == PrefixOpInvalid) { + if (mandatory) { + ast_invalid_token_error(pc, token); + } else { + return PrefixOpInvalid; + } + } + *token_index += 1; + return result; +} + +/* +PrefixOpExpression : PrefixOp FnCallExpression | FnCallExpression +*/ +static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory) { + Token *token = &pc->tokens->at(*token_index); + PrefixOp prefix_op = ast_parse_prefix_op(pc, token_index, false); + if (prefix_op == PrefixOpInvalid) + return ast_parse_fn_call_expr(pc, token_index, mandatory); + + AstNode *primary_expr = ast_parse_fn_call_expr(pc, token_index, true); + AstNode *node = ast_create_node(NodeTypePrefixOpExpr, token); + node->data.prefix_op_expr.primary_expr = primary_expr; + node->data.prefix_op_expr.prefix_op = prefix_op; + + return node; +} + + +/* +CastExpression : PrefixOpExpression token(as) Type | PrefixOpExpression +*/ +static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bool mandatory) { + AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, mandatory); + if (!prefix_op_expr) + return nullptr; + Token *as_kw = &pc->tokens->at(*token_index); if (as_kw->id != TokenIdKeywordAs) - return primary_expr; + return prefix_op_expr; *token_index += 1; AstNode *node = ast_create_node(NodeTypeCastExpr, as_kw); - node->data.cast_expr.primary_expr = primary_expr; + node->data.cast_expr.prefix_op_expr = prefix_op_expr; node->data.cast_expr.type = ast_parse_type(pc, *token_index, token_index); diff --git a/src/parser.hpp b/src/parser.hpp index b946aa33cd..1534e180e9 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -24,7 +24,6 @@ enum NodeType { NodeTypeParamDecl, NodeTypeType, NodeTypeBlock, - NodeTypeFnCall, NodeTypeExternBlock, NodeTypeDirective, NodeTypeReturnExpr, @@ -32,6 +31,8 @@ enum NodeType { NodeTypeCastExpr, NodeTypePrimaryExpr, NodeTypeGroupedExpr, + NodeTypePrefixOpExpr, + NodeTypeFnCallExpr, }; struct AstNodeRoot { @@ -117,8 +118,8 @@ struct AstNodeBinOpExpr { AstNode *op2; }; -struct AstNodeFnCall { - Buf name; +struct AstNodeFnCallExpr { + AstNode *fn_ref_expr; ZigList<AstNode *> params; }; @@ -138,7 +139,7 @@ struct AstNodeRootExportDecl { }; struct AstNodeCastExpr { - AstNode *primary_expr; + AstNode *prefix_op_expr; // if type is non-null, do cast, otherwise nothing AstNode *type; }; @@ -147,9 +148,9 @@ enum PrimaryExprType { PrimaryExprTypeNumber, PrimaryExprTypeString, PrimaryExprTypeUnreachable, - PrimaryExprTypeFnCall, PrimaryExprTypeGroupedExpr, PrimaryExprTypeBlock, + PrimaryExprTypeSymbol, }; struct AstNodePrimaryExpr { @@ -157,7 +158,7 @@ struct AstNodePrimaryExpr { union { Buf number; Buf string; - AstNode *fn_call; + Buf symbol; AstNode *grouped_expr; AstNode *block; } data; @@ -167,6 +168,18 @@ struct AstNodeGroupedExpr { AstNode *expr; }; +enum PrefixOp { + PrefixOpInvalid, + PrefixOpBoolNot, + PrefixOpBinNot, + PrefixOpNegation, +}; + +struct AstNodePrefixOpExpr { + PrefixOp prefix_op; + AstNode *primary_expr; +}; + struct AstNode { enum NodeType type; AstNode *parent; @@ -184,12 +197,13 @@ struct AstNode { AstNodeBlock block; AstNodeReturnExpr return_expr; AstNodeBinOpExpr bin_op_expr; - AstNodeFnCall fn_call; AstNodeExternBlock extern_block; AstNodeDirective directive; AstNodeCastExpr cast_expr; AstNodePrimaryExpr primary_expr; AstNodeGroupedExpr grouped_expr; + AstNodePrefixOpExpr prefix_op_expr; + AstNodeFnCallExpr fn_call_expr; } data; }; diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 1852dbf142..3cfab3288a 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -249,6 +249,10 @@ ZigList<Token> *tokenize(Buf *buf) { begin_token(&t, TokenIdPlus); end_token(&t); break; + case '~': + begin_token(&t, TokenIdTilde); + end_token(&t); + break; case '-': begin_token(&t, TokenIdDash); t.state = TokenizeStateSawDash; @@ -278,7 +282,7 @@ ZigList<Token> *tokenize(Buf *buf) { t.state = TokenizeStateEq; break; case '!': - begin_token(&t, TokenIdNot); + begin_token(&t, TokenIdBang); t.state = TokenizeStateBang; break; case '<': @@ -578,7 +582,8 @@ static const char * token_name(Token *token) { case TokenIdBoolOr: return "BoolOr"; case TokenIdBoolAnd: return "BoolAnd"; case TokenIdEq: return "Eq"; - case TokenIdNot: return "Not"; + case TokenIdBang: return "Bang"; + case TokenIdTilde: return "Tilde"; case TokenIdCmpEq: return "CmpEq"; case TokenIdCmpNotEq: return "CmpNotEq"; case TokenIdCmpLessThan: return "CmpLessThan"; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index 725429a18e..2c9ad61957 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -43,7 +43,8 @@ enum TokenId { TokenIdBinXor, TokenIdEq, TokenIdCmpEq, - TokenIdNot, + TokenIdBang, + TokenIdTilde, TokenIdCmpNotEq, TokenIdCmpLessThan, TokenIdCmpGreaterThan, |
