diff --git a/src/linearizer.c b/src/linearizer.c index a982979..57b360a 100644 --- a/src/linearizer.c +++ b/src/linearizer.c @@ -74,6 +74,11 @@ static void linearize_function(LinearizerState *linearizer); static Instruction *allocate_instruction(Proc *proc, enum opcode op, unsigned line_number); static void free_temp_pseudo(Proc *proc, Pseudo *pseudo, bool free_local); +static AstNode* astlist_get(AstNodeList *list, unsigned int i) +{ + return (AstNode*) raviX_ptrlist_nth_entry((struct PtrList *) list, i); +} + /** * Allocates a register by reusing a free'd register if possible otherwise * allocating a new one @@ -1537,9 +1542,14 @@ static void linearize_local_statement(Proc *proc, AstNode *stmt) static Pseudo *linearize_builtin_expression(Proc *proc, AstNode *expr) { + // For now the only built-in is C__new + if (expr->builtin_expr.token != TOK_C__new) { + handle_error(proc->linearizer->compiler_state, "feature not yet implemented"); + } Instruction *insn = allocate_instruction(proc, op_C__new, expr->line_number); - add_instruction_operand(proc, insn, allocate_constant_pseudo(proc, allocate_string_constant(proc, expr->builtin_expr.type_name))); - Pseudo *size_expr = linearize_expression(proc, expr->builtin_expr.size_expr); + const StringObject *type_name = astlist_get(expr->builtin_expr.arg_list, 0)->literal_expr.u.ts; + add_instruction_operand(proc, insn, allocate_constant_pseudo(proc, allocate_string_constant(proc, type_name))); + Pseudo *size_expr = linearize_expression(proc, astlist_get(expr->builtin_expr.arg_list, 1)); add_instruction_operand(proc, insn, size_expr); Pseudo *target = allocate_temp_pseudo(proc, RAVI_TUSERDATA); add_instruction_target(proc, insn, target); diff --git a/src/parser.c b/src/parser.c index 7c07309..b8b43c4 100644 --- a/src/parser.c +++ b/src/parser.c @@ -869,29 +869,39 @@ static AstNode *parse_primary_expression(ParserState *parser) return primary_expr; } -/* Parse C__new '(' string ',' expr ')' */ -static AstNode *parse_builtin_expression(ParserState *parser) +/* Parse builtins: + * C__new '(' string ',' expr ')' + */ +static AstNode *parse_builtin_expression(ParserState *parser, int token) { LexerState *ls = parser->ls; + if (token != TOK_C__new) { + raviX_syntaxerror(ls, "Unsupported builtin: expecting C__new"); + } + AstNode *builtin_expr = allocate_expr_ast_node(parser, EXPR_BUILTIN); builtin_expr->builtin_expr.type.type_code = RAVI_TUSERDATA; builtin_expr->builtin_expr.type.type_name = NULL; - builtin_expr->builtin_expr.type_name = NULL; - builtin_expr->builtin_expr.size_expr = NULL; + builtin_expr->builtin_expr.token = token; + builtin_expr->builtin_expr.arg_list = NULL; raviX_next(ls); checknext(ls, '('); - check(ls, TOK_STRING); - builtin_expr->builtin_expr.type_name = ls->t.seminfo.ts; - raviX_next(ls); + AstNode *expr1 = parse_expression(parser); + if (expr1->type != EXPR_LITERAL && expr1->literal_expr.type.type_code != RAVI_TSTRING) { + raviX_syntaxerror(ls, "Expected a size expression as second argument to C__new"); + } checknext(ls, ','); - builtin_expr->builtin_expr.size_expr = parse_expression(parser); - if (builtin_expr->builtin_expr.size_expr == NULL) { + AstNode *expr2 = parse_expression(parser); + if (expr2 == NULL) { raviX_syntaxerror(ls, "Expected a size expression as second argument to C__new"); } checknext(ls, ')'); + add_ast_node(parser->compiler_state, &builtin_expr->builtin_expr.arg_list, expr1); + add_ast_node(parser->compiler_state, &builtin_expr->builtin_expr.arg_list, expr2); + return builtin_expr; } @@ -903,7 +913,7 @@ static AstNode *parse_suffixed_expression(ParserState *parser) primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ int line = ls->linenumber; if (ls->t.token == TOK_C__new) { - return parse_builtin_expression(parser); + return parse_builtin_expression(parser, TOK_C__new); } AstNode *suffixed_expr = allocate_expr_ast_node(parser, EXPR_SUFFIXED); suffixed_expr->suffixed_expr.primary_expr = parse_primary_expression(parser); diff --git a/src/parser.h b/src/parser.h index a49901d..a5d6a1c 100644 --- a/src/parser.h +++ b/src/parser.h @@ -372,8 +372,8 @@ struct FunctionCallExpression { struct BuiltinExpression { /* Currently only for C__new but potentially could be other builtins */ BASE_EXPRESSION_FIELDS; - const StringObject *type_name; /* Name of the C struct type */ - AstNode *size_expr; /* Number of elements of type - > 1 means array */ + int token; + AstNodeList *arg_list; }; #undef BASE_EXPRESSION_FIELDS