diff --git a/src/parse.c b/src/parse.c index 36b8ddb..2f37a5e 100644 --- a/src/parse.c +++ b/src/parse.c @@ -285,32 +285,162 @@ AST *nct_parse_expression(Parser *P, int lOP) { expect(P, TOKEN_PAREN_R); } - - while(maybe(P, TOKEN_DOT)) { - assert(e->expression.type->type == TYPE_TYPE_RECORD); + + while(maybe(P, TOKEN_DOT) || maybe(P, TOKEN_PAREN_L) || maybe(P, TOKEN_SQUAREN_L)) { + Token op = P->tokens[P->i - 1]; - Token fieldTok = expect(P, TOKEN_IDENTIFIER); - - ASTExprDot *d = alloc_node(P, sizeof(*d)); - d->nodeKind = AST_EXPR_DOT; - d->a = (AST*) e; - - bool foundField = false; - - for(size_t f = 0; f < e->expression.type->record.fieldCount; f++) { - char *fieldName = e->expression.type->record.fieldNames[f]; - if(!strcmp(fieldName, fieldTok.content)) { - foundField = true; - d->type = e->expression.type->record.fieldTypes[f]; - d->b = strdup(fieldName); + if(op.type == TOKEN_DOT) { + while(type_is_any_pointer(e->expression.type)) { + AST *deref = alloc_node(P, sizeof(ASTExprUnaryOp)); + deref->nodeKind = AST_EXPR_UNARY_OP; + deref->exprUnOp.operator = UNOP_DEREF; + deref->exprUnOp.operand = (AST*) e; + deref->exprUnOp.type = type_dereference(e->expression.type); + + e = (AST*) deref; } - } - - if(!foundField) { - stahp(fieldTok.row, fieldTok.column, "Field %s does not exist.", fieldTok.content); - } - - e = (AST*) d; + + assert(e->expression.type->type == TYPE_TYPE_RECORD); + + Token fieldTok = expect(P, TOKEN_IDENTIFIER); + + ASTExprDot *d = alloc_node(P, sizeof(*d)); + d->nodeKind = AST_EXPR_DOT; + d->a = (AST*) e; + + bool foundField = false; + + for(size_t f = 0; f < e->expression.type->record.fieldCount; f++) { + char *fieldName = e->expression.type->record.fieldNames[f]; + if(!strcmp(fieldName, fieldTok.content)) { + foundField = true; + d->type = e->expression.type->record.fieldTypes[f]; + d->b = strdup(fieldName); + } + } + + if(!foundField) { + stahp(fieldTok.row, fieldTok.column, "Field %s does not exist.", fieldTok.content); + } + + e = (AST*) d; + } else if(op.type == TOKEN_PAREN_L) { + // Convert a call like foo() to (&foo)() + if(e->expression.type->type == TYPE_TYPE_FUNCTION) { + ASTExprUnaryOp *ref = alloc_node(P, sizeof(*ref)); + ref->nodeKind = AST_EXPR_UNARY_OP; + ref->type = type_pointer_wrap(e->expression.type); + ref->operator = UNOP_REF; + ref->operand = e; + e = (AST*) ref; + } + + if(e->expression.type->type != TYPE_TYPE_POINTER || e->expression.type->pointer.of->type != TYPE_TYPE_FUNCTION) { + stahp(P->tokens[P->i].row, P->tokens[P->i].column, "Only function types or function pointers may be called."); + } + + Type *ftype = e->expression.type->pointer.of; + + ASTExprCall *call = alloc_node(P, sizeof(*call)); + call->nodeKind = AST_EXPR_CALL; + call->type = ftype->function.ret; + call->what = e; + call->args = NULL; + + int argCount = 0; + + if(!maybe(P, TOKEN_PAREN_R)) { + while(peek(P, 0).type != TOKEN_PAREN_R && peek(P, 0).type != TOKEN_COMMA) { + call->args = realloc(call->args, (argCount + 1) * sizeof(AST*)); + call->args[argCount] = ast_cast_expr(nct_parse_expression(P, 0), ftype->function.args[argCount]); + + argCount++; + + if(maybe(P, TOKEN_PAREN_R)) { + break; + } else expect(P, TOKEN_COMMA); + } + } + + if(argCount != ftype->function.argCount) { + stahp(P->tokens[P->i].row, P->tokens[P->i].column, "Mismatched number of arguments"); + } + + e = (AST*) call; + } else if(op.type == TOKEN_SQUAREN_L) { + P->scope = scope_new(P->scope); + + P->i--; + + if(parse_parametrization(P)) { + // Generic type parametrization + + // Generic functions are not first-class + assert(e->nodeKind == AST_EXPR_VAR); + assert(e->exprVar.thing != NULL); + assert(e->exprVar.thing->kind == SCOPEITEM_SYMBOL); + + char *cname = parametrize_function_name(e->expression.type, e->exprVar.thing->data.symbol.name, P->scope); + + ScopeItem *cvte = scope_find(P->scope, cname); + + if(!cvte) { + stahp_token(&P->tokens[P->i], "Parametrization %s not found.", cname); + } + + e = exprvar(P, cvte); + } else { + // Array access + + expect(P, TOKEN_SQUAREN_L); + + ASTExprUnaryOp *ref = alloc_node(P, sizeof(*ref)); + ref->nodeKind = AST_EXPR_UNARY_OP; + ref->operator = UNOP_REF; + ref->operand = e; + ref->type = type_pointer_wrap(e->expression.type->array.of); + + ASTExprBinaryOp *child = alloc_node(P, sizeof(*child)); + child->nodeKind = AST_EXPR_BINARY_OP; + child->operands[0] = (AST*) ref; + child->operands[1] = nct_parse_expression(P, 0); + child->operator = BINOP_ADD; + child->type = ref->type; + + if(e->expression.type->type != TYPE_TYPE_ARRAY) { + stahp_token(&P->tokens[P->i], "Attempt to index a non-array type"); + } + + int typesize = type_size(e->expression.type->array.of); + if(typesize != 1) { + ASTExprPrimitive *scale = alloc_node(P, sizeof(*scale)); + scale->nodeKind = AST_EXPR_PRIMITIVE; + scale->type = type_u(8 * arch_gpr_size()); + scale->val = typesize; + + ASTExprBinaryOp *mul = alloc_node(P, sizeof(*mul)); + mul->nodeKind = AST_EXPR_BINARY_OP; + mul->type = child->operands[1]->expression.type; + mul->operator = BINOP_MUL; + mul->operands[0] = (AST*) scale; + mul->operands[1] = child->operands[1]; + + child->operands[1] = (AST*) mul; + } + + ASTExprUnaryOp *unop = alloc_node(P, sizeof(*unop)); + unop->nodeKind = AST_EXPR_UNARY_OP; + unop->type = e->expression.type->array.of; + unop->operator = UNOP_DEREF; + unop->operand = (AST*) child; + + expect(P, TOKEN_SQUAREN_R); + + e = (AST*) unop; + } + + P->scope = P->scope->parent; + } else abort(); } return e; @@ -369,128 +499,7 @@ AST *nct_parse_expression(Parser *P, int lOP) { } } else return nct_parse_expression(P, lOP + 1); } else if(lOP == 5) { - AST *ret = nct_parse_expression(P, lOP + 1); - - while(peek(P, 0).type == TOKEN_PAREN_L || peek(P, 0).type == TOKEN_SQUAREN_L) { - if(maybe(P, TOKEN_PAREN_L)) { - if(ret->expression.type->type == TYPE_TYPE_FUNCTION) { - ASTExprUnaryOp *ref = alloc_node(P, sizeof(*ref)); - ref->nodeKind = AST_EXPR_UNARY_OP; - ref->type = type_pointer_wrap(ret->expression.type); - ref->operator = UNOP_REF; - ref->operand = ret; - ret = (AST*) ref; - } - - if(ret->expression.type->type != TYPE_TYPE_POINTER || ret->expression.type->pointer.of->type != TYPE_TYPE_FUNCTION) { - stahp(P->tokens[P->i].row, P->tokens[P->i].column, "Only function types or function pointers may be called."); - } - - Type *ftype = ret->expression.type->pointer.of; - - ASTExprCall *call = alloc_node(P, sizeof(*call)); - call->nodeKind = AST_EXPR_CALL; - call->type = ftype->function.ret; - call->what = ret; - call->args = NULL; - - int argCount = 0; - - if(!maybe(P, TOKEN_PAREN_R)) { - while(peek(P, 0).type != TOKEN_PAREN_R && peek(P, 0).type != TOKEN_COMMA) { - call->args = realloc(call->args, (argCount + 1) * sizeof(AST*)); - call->args[argCount] = ast_cast_expr(nct_parse_expression(P, 0), ftype->function.args[argCount]); - - argCount++; - - if(maybe(P, TOKEN_PAREN_R)) { - break; - } else expect(P, TOKEN_COMMA); - } - } - - if(argCount != ftype->function.argCount) { - stahp(P->tokens[P->i].row, P->tokens[P->i].column, "Mismatched number of arguments"); - } - - ret = (AST*) call; - } else if(peek(P, 0).type == TOKEN_SQUAREN_L) { - - P->scope = scope_new(P->scope); - - if(parse_parametrization(P)) { - // Generic type parametrization - - // Generic functions are not first-class - assert(ret->nodeKind == AST_EXPR_VAR); - assert(ret->exprVar.thing != NULL); - assert(ret->exprVar.thing->kind == SCOPEITEM_SYMBOL); - - char *cname = parametrize_function_name(ret->expression.type, ret->exprVar.thing->data.symbol.name, P->scope); - - ScopeItem *cvte = scope_find(P->scope, cname); - - if(!cvte) { - stahp_token(&P->tokens[P->i], "Parametrization %s not found.", cname); - } - - ret = exprvar(P, cvte); - } else { - // Array access - - expect(P, TOKEN_SQUAREN_L); - - ASTExprUnaryOp *ref = alloc_node(P, sizeof(*ref)); - ref->nodeKind = AST_EXPR_UNARY_OP; - ref->operator = UNOP_REF; - ref->operand = ret; - ref->type = type_pointer_wrap(ret->expression.type->array.of); - - ASTExprBinaryOp *child = alloc_node(P, sizeof(*child)); - child->nodeKind = AST_EXPR_BINARY_OP; - child->operands[0] = (AST*) ref; - child->operands[1] = nct_parse_expression(P, 0); - child->operator = BINOP_ADD; - child->type = ref->type; - - if(ret->expression.type->type != TYPE_TYPE_ARRAY) { - stahp_token(&P->tokens[P->i], "Attempt to index a non-array type"); - } - - int typesize = type_size(ret->expression.type->array.of); - if(typesize != 1) { - ASTExprPrimitive *scale = alloc_node(P, sizeof(*scale)); - scale->nodeKind = AST_EXPR_PRIMITIVE; - scale->type = type_u(8 * arch_gpr_size()); - scale->val = typesize; - - ASTExprBinaryOp *mul = alloc_node(P, sizeof(*mul)); - mul->nodeKind = AST_EXPR_BINARY_OP; - mul->type = child->operands[1]->expression.type; - mul->operator = BINOP_MUL; - mul->operands[0] = (AST*) scale; - mul->operands[1] = child->operands[1]; - - child->operands[1] = (AST*) mul; - } - - ASTExprUnaryOp *unop = alloc_node(P, sizeof(*unop)); - unop->nodeKind = AST_EXPR_UNARY_OP; - unop->type = ret->expression.type->array.of; - unop->operator = UNOP_DEREF; - unop->operand = (AST*) child; - - expect(P, TOKEN_SQUAREN_R); - - ret = (AST*) unop; - } - - P->scope = P->scope->parent; - - } else abort(); - } - - return ret; + return nct_parse_expression(P, lOP + 1); } else if(lOP == 4) { AST *ret = nct_parse_expression(P, lOP + 1); @@ -582,35 +591,6 @@ AST *nct_parse_expression(Parser *P, int lOP) { } else if(lOP == 1) { AST *ret = nct_parse_expression(P, lOP + 1); - if(peek(P, 0).type == TOKEN_DOUBLE_AMPERSAND || peek(P, 0).type == TOKEN_DOUBLE_VERTICAL_BAR) { - while(1) { - BinaryOp op; - if(maybe(P, TOKEN_DOUBLE_AMPERSAND)) op = BINOP_LOGICAL_AND; - else if(maybe(P, TOKEN_DOUBLE_VERTICAL_BAR)) op = BINOP_LOGICAL_OR; - else break; - - ASTExprBinaryOp *astop = alloc_node(P, sizeof(*astop)); - astop->nodeKind = AST_EXPR_BINARY_OP; - astop->type = NULL; - astop->operator = op; - astop->operands[0] = ret; - - ASTExpr *operand = &(astop->operands[1] = nct_parse_expression(P, lOP + 1))->expression; - - if(operand->type->type != TYPE_TYPE_PRIMITIVE) { - stahp_token(&P->tokens[P->i], "Invalid combination of operator and operand types."); - } - - binop_implicit_cast(astop); - - ret = (AST*) astop; - } - } - - return ret; - } else if(lOP == 0) { - AST *ret = nct_parse_expression(P, lOP + 1); - if(peek(P, 0).type == TOKEN_DOUBLE_EQUALS || peek(P, 0).type == TOKEN_EXCLAMATION_EQUALS || peek(P, 0).type == TOKEN_LESS || peek(P, 0).type == TOKEN_GREATER || peek(P, 0).type == TOKEN_LEQUAL || peek(P, 0).type == TOKEN_GEQUAL) { while(1) { BinaryOp op; @@ -622,6 +602,33 @@ AST *nct_parse_expression(Parser *P, int lOP) { else if(maybe(P, TOKEN_GEQUAL)) op = BINOP_GEQUAL; else break; + ASTExprBinaryOp *astop = alloc_node(P, sizeof(*astop)); + astop->nodeKind = AST_EXPR_BINARY_OP; + astop->type = type_u(1); + astop->operator = op; + astop->operands[0] = ret; + + ASTExpr *operand = &(astop->operands[1] = nct_parse_expression(P, lOP + 1))->expression; + + if(operand->type->type != TYPE_TYPE_PRIMITIVE) { + stahp_token(&P->tokens[P->i], "Invalid combination of operator and operand types."); + } + + ret = (AST*) astop; + } + } + + return ret; + } else if(lOP == 0) { + AST *ret = nct_parse_expression(P, lOP + 1); + + if(peek(P, 0).type == TOKEN_DOUBLE_AMPERSAND || peek(P, 0).type == TOKEN_DOUBLE_VERTICAL_BAR) { + while(1) { + BinaryOp op; + if(maybe(P, TOKEN_DOUBLE_AMPERSAND)) op = BINOP_LOGICAL_AND; + else if(maybe(P, TOKEN_DOUBLE_VERTICAL_BAR)) op = BINOP_LOGICAL_OR; + else break; + ASTExprBinaryOp *astop = alloc_node(P, sizeof(*astop)); astop->nodeKind = AST_EXPR_BINARY_OP; astop->type = NULL;