aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast.c2
-rw-r--r--src/ast.h3
-rw-r--r--src/compile.c82
-rw-r--r--src/parse.c148
4 files changed, 123 insertions, 112 deletions
diff --git a/src/ast.c b/src/ast.c
index d4fd9569..b3506058 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -190,7 +190,7 @@ CORD ast_to_xml(ast_t *ast)
T(NonOptional, "<NonOptional>%r</NonOptional>", ast_to_xml(data.value))
T(DocTest, "<DocTest>%r%r</DocTest>", optional_tagged("expression", data.expr), optional_tagged("expected", data.expected))
T(Use, "<Use>%r%r</Use>", optional_tagged("var", data.var), xml_escape(data.path))
- T(InlineCCode, "<InlineCode>%r</InlineCode>", xml_escape(data.code))
+ T(InlineCCode, "<InlineCode>%r</InlineCode>", ast_list_to_xml(data.chunks))
T(Deserialize, "<Deserialize><type>%r</type>%r</Deserialize>", type_ast_to_xml(data.type), ast_to_xml(data.value))
T(Extend, "<Extend name=\"%s\">%r</Extend>", data.name, ast_to_xml(data.body))
T(ExplicitlyTyped, "<ExplicitlyTyped type=\"%r\">%r</ExplicitlyTyped>", type_to_cord(data.type), ast_to_xml(data.ast))
diff --git a/src/ast.h b/src/ast.h
index b48582f2..aeb418d9 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -19,6 +19,7 @@
#define FakeAST(ast_tag, ...) (new(ast_t, .tag=ast_tag, .__data.ast_tag={__VA_ARGS__}))
#define WrapAST(ast, ast_tag, ...) (new(ast_t, .file=(ast)->file, .start=(ast)->start, .end=(ast)->end, .tag=ast_tag, .__data.ast_tag={__VA_ARGS__}))
#define TextAST(ast, _str) WrapAST(ast, TextLiteral, .str=GC_strdup(_str))
+#define LiteralCode(code, ...) new(ast_t, .tag=InlineCCode, .__data.InlineCCode={.chunks=new(ast_list_t, .ast=FakeAST(TextLiteral, code)), __VA_ARGS__})
#define Match(x, _tag) ((x)->tag == _tag ? &(x)->__data._tag : (errx(1, __FILE__ ":%d This was supposed to be a " # _tag "\n", __LINE__), &(x)->__data._tag))
#define BINARY_OPERANDS(ast) ({ if (!is_binary_operation(ast)) errx(1, __FILE__ ":%d This is not a binary operation!", __LINE__); (ast)->__data.Plus; })
@@ -324,7 +325,7 @@ struct ast_s {
enum { USE_LOCAL, USE_MODULE, USE_SHARED_OBJECT, USE_HEADER, USE_C_CODE, USE_ASM } what;
} Use;
struct {
- CORD code;
+ ast_list_t *chunks;
struct type_s *type;
type_ast_t *type_ast;
} InlineCCode;
diff --git a/src/compile.c b/src/compile.c
index b49f4c49..cdfaf5c6 100644
--- a/src/compile.c
+++ b/src/compile.c
@@ -123,7 +123,7 @@ static bool promote(env_t *env, ast_t *ast, CORD *code, type_t *actual, type_t *
// Numeric promotions/demotions
if ((is_numeric_type(actual) || actual->tag == BoolType) && (is_numeric_type(needed) || needed->tag == BoolType)) {
- arg_ast_t *args = new(arg_ast_t, .value=FakeAST(InlineCCode, .code=*code, .type=actual));
+ arg_ast_t *args = new(arg_ast_t, .value=LiteralCode(*code, .type=actual));
binding_t *constructor = get_constructor(env, needed, args);
if (constructor) {
auto fn = Match(constructor->type, FunctionType);
@@ -555,7 +555,7 @@ static CORD compile_update_assignment(env_t *env, ast_t *ast)
*binop = *ast;
binop->tag = binop_tag(binop->tag);
if (needs_idemotency_fix)
- binop->__data.Plus.lhs = WrapAST(update.lhs, InlineCCode, .code="*lhs", .type=lhs_t);
+ binop->__data.Plus.lhs = LiteralCode("*lhs", .type=lhs_t);
update_assignment = CORD_all(lhs, " = ", compile_to_type(env, binop, lhs_t), ";");
}
@@ -1027,7 +1027,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
if (!is_idempotent(when->subject)) {
prefix = CORD_all("{\n", compile_declaration(subject_t, "_when_subject"), " = ", compile(env, subject), ";\n");
suffix = "}\n";
- subject = WrapAST(subject, InlineCCode, .type=subject_t, .code="_when_subject");
+ subject = LiteralCode("_when_subject", .type=subject_t);
}
CORD code = CORD_EMPTY;
@@ -1195,7 +1195,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
ast_t *update_var = new(ast_t);
*update_var = *test->expr;
- update_var->__data.PlusUpdate.lhs = WrapAST(update.lhs, InlineCCode, .code="(*expr)", .type=lhs_t); // UNSAFE
+ update_var->__data.PlusUpdate.lhs = LiteralCode("(*expr)", .type=lhs_t); // UNSAFE
test_code = CORD_all("({",
compile_declaration(Type(PointerType, lhs_t), "expr"), " = &(", compile_lvalue(env, update.lhs), "); ",
compile_statement(env, update_var), "; *expr; })");
@@ -1845,7 +1845,15 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
case Extern: return CORD_EMPTY;
case InlineCCode: {
auto inline_code = Match(ast, InlineCCode);
- return inline_code->code;
+ CORD code = CORD_EMPTY;
+ for (ast_list_t *chunk = inline_code->chunks; chunk; chunk = chunk->next) {
+ if (chunk->ast->tag == TextLiteral) {
+ code = CORD_all(code, Match(chunk->ast, TextLiteral)->cord);
+ } else {
+ code = CORD_all(code, compile(env, chunk->ast));
+ }
+ }
+ return code;
}
case Use: {
auto use = Match(ast, Use);
@@ -2060,8 +2068,8 @@ CORD compile_typed_array(env_t *env, ast_t *ast, type_t *array_type)
env_t *scope = item_type->tag == EnumType ? with_enum_scope(env, item_type) : fresh_scope(env);
static int64_t comp_num = 1;
const char *comprehension_name = String("arr$", comp_num++);
- ast_t *comprehension_var = FakeAST(InlineCCode, .code=CORD_all("&", comprehension_name),
- .type=Type(PointerType, .pointed=array_type, .is_stack=true));
+ ast_t *comprehension_var = LiteralCode(CORD_all("&", comprehension_name),
+ .type=Type(PointerType, .pointed=array_type, .is_stack=true));
Closure_t comp_action = {.fn=add_to_array_comprehension, .userdata=comprehension_var};
scope->comprehension_action = &comp_action;
CORD code = CORD_all("({ Array_t ", comprehension_name, " = {};");
@@ -2109,8 +2117,8 @@ CORD compile_typed_set(env_t *env, ast_t *ast, type_t *set_type)
static int64_t comp_num = 1;
env_t *scope = item_type->tag == EnumType ? with_enum_scope(env, item_type) : fresh_scope(env);
const char *comprehension_name = String("set$", comp_num++);
- ast_t *comprehension_var = FakeAST(InlineCCode, .code=CORD_all("&", comprehension_name),
- .type=Type(PointerType, .pointed=set_type, .is_stack=true));
+ ast_t *comprehension_var = LiteralCode(CORD_all("&", comprehension_name),
+ .type=Type(PointerType, .pointed=set_type, .is_stack=true));
CORD code = CORD_all("({ Table_t ", comprehension_name, " = {};");
Closure_t comp_action = {.fn=add_to_set_comprehension, .userdata=comprehension_var};
scope->comprehension_action = &comp_action;
@@ -2177,7 +2185,7 @@ CORD compile_typed_table(env_t *env, ast_t *ast, type_t *table_type)
static int64_t comp_num = 1;
env_t *scope = fresh_scope(env);
const char *comprehension_name = String("table$", comp_num++);
- ast_t *comprehension_var = FakeAST(InlineCCode, .code=CORD_all("&", comprehension_name),
+ ast_t *comprehension_var = LiteralCode(CORD_all("&", comprehension_name),
.type=Type(PointerType, .pointed=table_type, .is_stack=true));
CORD code = CORD_all("({ Table_t ", comprehension_name, " = {");
@@ -3129,10 +3137,9 @@ CORD compile(env_t *env, ast_t *ast)
EXPECT_POINTER("an", "array");
type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true);
type_t *fn_t = NewFunctionType(Type(IntType, .bits=TYPE_IBITS32), {.name="x", .type=item_ptr}, {.name="y", .type=item_ptr});
- ast_t *default_cmp = FakeAST(InlineCCode,
- .code=CORD_all("((Closure_t){.fn=generic_compare, .userdata=(void*)",
- compile_type_info(item_t), "})"),
- .type=Type(ClosureType, .fn=fn_t));
+ ast_t *default_cmp = LiteralCode(CORD_all("((Closure_t){.fn=generic_compare, .userdata=(void*)",
+ compile_type_info(item_t), "})"),
+ .type=Type(ClosureType, .fn=fn_t));
arg_t *arg_spec = new(arg_t, .name="item", .type=item_t,
.next=new(arg_t, .name="by", .type=Type(ClosureType, .fn=fn_t), .default_val=default_cmp));
CORD arg_code = compile_arguments(env, ast, arg_spec, call->args);
@@ -3141,10 +3148,9 @@ CORD compile(env_t *env, ast_t *ast)
EXPECT_POINTER("an", "array");
type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true);
type_t *fn_t = NewFunctionType(Type(IntType, .bits=TYPE_IBITS32), {.name="x", .type=item_ptr}, {.name="y", .type=item_ptr});
- ast_t *default_cmp = FakeAST(InlineCCode,
- .code=CORD_all("((Closure_t){.fn=generic_compare, .userdata=(void*)",
- compile_type_info(item_t), "})"),
- .type=Type(ClosureType, .fn=fn_t));
+ ast_t *default_cmp = LiteralCode(CORD_all("((Closure_t){.fn=generic_compare, .userdata=(void*)",
+ compile_type_info(item_t), "})"),
+ .type=Type(ClosureType, .fn=fn_t));
arg_t *arg_spec = new(arg_t, .name="by", .type=Type(ClosureType, .fn=fn_t), .default_val=default_cmp);
CORD arg_code = compile_arguments(env, ast, arg_spec, call->args);
return CORD_all("Array$heap_pop_value(", self, ", ", arg_code, ", ", compile_type(item_t), ", _, ",
@@ -3153,10 +3159,10 @@ CORD compile(env_t *env, ast_t *ast)
self = compile_to_pointer_depth(env, call->self, 0, call->args != NULL);
type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true);
type_t *fn_t = NewFunctionType(Type(IntType, .bits=TYPE_IBITS32), {.name="x", .type=item_ptr}, {.name="y", .type=item_ptr});
- ast_t *default_cmp = FakeAST(InlineCCode,
- .code=CORD_all("((Closure_t){.fn=generic_compare, .userdata=(void*)",
- compile_type_info(item_t), "})"),
- .type=Type(ClosureType, .fn=fn_t));
+ ast_t *default_cmp = LiteralCode(
+ CORD_all("((Closure_t){.fn=generic_compare, .userdata=(void*)",
+ compile_type_info(item_t), "})"),
+ .type=Type(ClosureType, .fn=fn_t));
arg_t *arg_spec = new(arg_t, .name="target", .type=item_t,
.next=new(arg_t, .name="by", .type=Type(ClosureType, .fn=fn_t), .default_val=default_cmp));
CORD arg_code = compile_arguments(env, ast, arg_spec, call->args);
@@ -3522,7 +3528,7 @@ CORD compile(env_t *env, ast_t *ast)
static int64_t next_id = 1;
ast_t *item = FakeAST(Var, String("$it", next_id++));
- ast_t *body = FakeAST(InlineCCode, .code="{}"); // placeholder
+ ast_t *body = LiteralCode("{}"); // placeholder
ast_t *loop = FakeAST(For, .vars=new(ast_list_t, .ast=item), .iter=reduction->iter, .body=body);
env_t *body_scope = for_scope(env, loop);
if (op == Equals || op == NotEquals || op == LessThan || op == LessThanOrEquals || op == GreaterThan || op == GreaterThanOrEquals) {
@@ -3542,8 +3548,8 @@ CORD compile(env_t *env, ast_t *ast)
);
ast_t *comparison = new(ast_t, .file=ast->file, .start=ast->start, .end=ast->end,
- .tag=op, .__data.Plus.lhs=FakeAST(InlineCCode, .code="prev", .type=item_value_type), .__data.Plus.rhs=item_value);
- body->__data.InlineCCode.code = CORD_all(
+ .tag=op, .__data.Plus.lhs=LiteralCode("prev", .type=item_value_type), .__data.Plus.rhs=item_value);
+ body->__data.InlineCCode.chunks = new(ast_list_t, .ast=FakeAST(TextLiteral, CORD_all(
"if (result == NONE_BOOL) {\n"
" prev = ", compile(body_scope, item_value), ";\n"
" result = yes;\n"
@@ -3554,7 +3560,7 @@ CORD compile(env_t *env, ast_t *ast)
" result = no;\n",
" break;\n",
" }\n",
- "}\n");
+ "}\n")));
code = CORD_all(code, compile_statement(env, loop), "\nresult;})");
return code;
} else if (op == Min || op == Max) {
@@ -3576,25 +3582,25 @@ CORD compile(env_t *env, ast_t *ast)
code = CORD_all(code, compile_declaration(key_type, superlative_key), ";\n");
ast_t *comparison = new(ast_t, .file=ast->file, .start=ast->start, .end=ast->end,
- .tag=cmp_op, .__data.Plus.lhs=FakeAST(InlineCCode, .code="key", .type=key_type),
- .__data.Plus.rhs=FakeAST(InlineCCode, .code=superlative_key, .type=key_type));
+ .tag=cmp_op, .__data.Plus.lhs=LiteralCode("key", .type=key_type),
+ .__data.Plus.rhs=LiteralCode(superlative_key, .type=key_type));
- body->__data.InlineCCode.code = CORD_all(
+ body->__data.InlineCCode.chunks = new(ast_list_t, .ast=FakeAST(TextLiteral, CORD_all(
compile_declaration(key_type, "key"), " = ", compile(key_scope, reduction->key), ";\n",
"if (!has_value || ", compile(body_scope, comparison), ") {\n"
" ", superlative, " = ", compile(body_scope, item), ";\n"
" ", superlative_key, " = key;\n"
" has_value = yes;\n"
- "}\n");
+ "}\n")));
} else {
ast_t *comparison = new(ast_t, .file=ast->file, .start=ast->start, .end=ast->end,
.tag=cmp_op, .__data.Plus.lhs=item,
- .__data.Plus.rhs=FakeAST(InlineCCode, .code=superlative, .type=item_t));
- body->__data.InlineCCode.code = CORD_all(
+ .__data.Plus.rhs=LiteralCode(superlative, .type=item_t));
+ body->__data.InlineCCode.chunks = new(ast_list_t, .ast=FakeAST(TextLiteral, CORD_all(
"if (!has_value || ", compile(body_scope, comparison), ") {\n"
" ", superlative, " = ", compile(body_scope, item), ";\n"
" has_value = yes;\n"
- "}\n");
+ "}\n")));
}
@@ -3634,16 +3640,16 @@ CORD compile(env_t *env, ast_t *ast)
}
ast_t *combination = new(ast_t, .file=ast->file, .start=ast->start, .end=ast->end,
- .tag=op, .__data.Plus.lhs=FakeAST(InlineCCode, .code="reduction", .type=reduction_type),
+ .tag=op, .__data.Plus.lhs=LiteralCode("reduction", .type=reduction_type),
.__data.Plus.rhs=item_value);
- body->__data.InlineCCode.code = CORD_all(
+ body->__data.InlineCCode.chunks = new(ast_list_t, .ast=FakeAST(TextLiteral, CORD_all(
"if (!has_value) {\n"
" reduction = ", compile(body_scope, item_value), ";\n"
" has_value = yes;\n"
"} else {\n"
" reduction = ", compile(body_scope, combination), ";\n",
early_out,
- "}\n");
+ "}\n")));
code = CORD_all(code, compile_statement(env, loop), "\nhas_value ? ", promote_to_optional(reduction_type, "reduction"),
" : ", compile_none(reduction_type), ";})");
@@ -3815,9 +3821,9 @@ CORD compile(env_t *env, ast_t *ast)
case InlineCCode: {
type_t *t = get_type(env, ast);
if (t->tag == VoidType)
- return CORD_all("{\n", Match(ast, InlineCCode)->code, "\n}");
+ return CORD_all("{\n", compile_statement(env, ast), "\n}");
else
- return Match(ast, InlineCCode)->code;
+ return compile_statement(env, ast);
}
case Use: code_err(ast, "Compiling 'use' as expression!");
case Defer: code_err(ast, "Compiling 'defer' as expression!");
diff --git a/src/parse.c b/src/parse.c
index 3b8f55bf..c31bea64 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -61,8 +61,8 @@ int op_tightness[] = {
};
static const char *keywords[] = {
- "_max_", "_min_", "and", "break", "continue", "defer", "deserialize", "do", "else", "enum",
- "extend", "extern", "for", "func", "if", "in", "inline", "lang", "mod", "mod1", "no", "none",
+ "C_code", "_max_", "_min_", "and", "break", "continue", "defer", "deserialize", "do", "else", "enum",
+ "extend", "extern", "for", "func", "if", "in", "lang", "mod", "mod1", "no", "none",
"not", "or", "pass", "return", "skip", "skip", "stop", "struct", "then", "unless", "use", "when",
"while", "xor", "yes",
};
@@ -147,6 +147,7 @@ static PARSER(parse_var);
static PARSER(parse_when);
static PARSER(parse_while);
static PARSER(parse_deserialize);
+static ast_list_t *_parse_text_helper(parse_ctx_t *ctx, const char **out_pos, char open_quote, char close_quote, char open_interp);
//
// Print a parse error and exit (or use the on_err longjmp)
@@ -1186,55 +1187,11 @@ PARSER(parse_bool) {
return NULL;
}
-PARSER(parse_text) {
- // ('"' ... '"' / "'" ... "'" / "`" ... "`")
- // "$" [name] [interp-char] quote-char ... close-quote
- const char *start = pos;
- const char *lang = NULL;
-
- // Escape sequence, e.g. \r\n
- if (*pos == '\\') {
- CORD cord = CORD_EMPTY;
- do {
- const char *c = unescape(ctx, &pos);
- cord = CORD_cat(cord, c);
- // cord = CORD_cat_char(cord, c);
- } while (*pos == '\\');
- return NewAST(ctx->file, start, pos, TextLiteral, .cord=cord);
- }
-
- char open_quote, close_quote, open_interp = '$';
- if (match(&pos, "\"")) { // Double quote
- open_quote = '"', close_quote = '"', open_interp = '$';
- } else if (match(&pos, "`")) { // Backtick
- open_quote = '`', close_quote = '`', open_interp = '$';
- } else if (match(&pos, "'")) { // Single quote
- open_quote = '\'', close_quote = '\'', open_interp = '\x03';
- } else if (match(&pos, "$")) { // Customized strings
- lang = get_id(&pos);
- // $"..." or $@"...."
- static const char *interp_chars = "~!@#$%^&*+=\\?";
- if (match(&pos, "$")) { // Disable interpolation with $
- open_interp = '\x03';
- } else if (strchr(interp_chars, *pos)) {
- open_interp = *pos;
- ++pos;
- } else if (*pos == '(') {
- open_interp = '@'; // For shell commands
- }
- static const char *quote_chars = "\"'`|/;([{<";
- if (!strchr(quote_chars, *pos))
- parser_err(ctx, pos, pos+1, "This is not a valid string quotation character. Valid characters are: \"'`|/;([{<");
- open_quote = *pos;
- ++pos;
- close_quote = closing[(int)open_quote] ? closing[(int)open_quote] : open_quote;
- } else {
- return NULL;
- }
-
+ast_list_t *_parse_text_helper(parse_ctx_t *ctx, const char **out_pos, char open_quote, char close_quote, char open_interp)
+{
+ const char *pos = *out_pos;
int64_t starting_indent = get_indent(ctx, pos);
int64_t string_indent = starting_indent + SPACES_PER_INDENT;
-
ast_list_t *chunks = NULL;
CORD chunk = CORD_EMPTY;
const char *chunk_start = pos;
@@ -1299,6 +1256,57 @@ PARSER(parse_text) {
REVERSE_LIST(chunks);
char close_str[2] = {close_quote, 0};
expect_closing(ctx, &pos, close_str, "I was expecting a ", close_quote, " to finish this string");
+ *out_pos = pos;
+ return chunks;
+}
+
+PARSER(parse_text) {
+ // ('"' ... '"' / "'" ... "'" / "`" ... "`")
+ // "$" [name] [interp-char] quote-char ... close-quote
+ const char *start = pos;
+ const char *lang = NULL;
+
+ // Escape sequence, e.g. \r\n
+ if (*pos == '\\') {
+ CORD cord = CORD_EMPTY;
+ do {
+ const char *c = unescape(ctx, &pos);
+ cord = CORD_cat(cord, c);
+ // cord = CORD_cat_char(cord, c);
+ } while (*pos == '\\');
+ return NewAST(ctx->file, start, pos, TextLiteral, .cord=cord);
+ }
+
+ char open_quote, close_quote, open_interp = '$';
+ if (match(&pos, "\"")) { // Double quote
+ open_quote = '"', close_quote = '"', open_interp = '$';
+ } else if (match(&pos, "`")) { // Backtick
+ open_quote = '`', close_quote = '`', open_interp = '$';
+ } else if (match(&pos, "'")) { // Single quote
+ open_quote = '\'', close_quote = '\'', open_interp = '\x03';
+ } else if (match(&pos, "$")) { // Customized strings
+ lang = get_id(&pos);
+ // $"..." or $@"...."
+ static const char *interp_chars = "~!@#$%^&*+=\\?";
+ if (match(&pos, "$")) { // Disable interpolation with $
+ open_interp = '\x03';
+ } else if (strchr(interp_chars, *pos)) {
+ open_interp = *pos;
+ ++pos;
+ } else if (*pos == '(') {
+ open_interp = '@'; // For shell commands
+ }
+ static const char *quote_chars = "\"'`|/;([{<";
+ if (!strchr(quote_chars, *pos))
+ parser_err(ctx, pos, pos+1, "This is not a valid string quotation character. Valid characters are: \"'`|/;([{<");
+ open_quote = *pos;
+ ++pos;
+ close_quote = closing[(int)open_quote] ? closing[(int)open_quote] : open_quote;
+ } else {
+ return NULL;
+ }
+
+ ast_list_t *chunks = _parse_text_helper(ctx, &pos, open_quote, close_quote, open_interp);
return NewAST(ctx->file, start, pos, TextJoin, .lang=lang, .children=chunks);
}
@@ -2258,34 +2266,30 @@ PARSER(parse_extern) {
PARSER(parse_inline_c) {
const char *start = pos;
- if (!match_word(&pos, "inline")) return NULL;
-
- spaces(&pos);
- if (!match_word(&pos, "C")) return NULL;
+ if (!match_word(&pos, "C_code")) return NULL;
spaces(&pos);
type_ast_t *type = NULL;
- if (match(&pos, ":"))
- type = expect(ctx, start, &pos, parse_type, "I couldn't parse the type for this inline C code");
-
- spaces(&pos);
- if (!match(&pos, "{"))
- parser_err(ctx, start, pos, "I expected a '{' here");
-
- int depth = 1;
- const char *c_code_start = pos;
- for (; *pos && depth > 0; ++pos) {
- if (*pos == '}') --depth;
- else if (*pos == '{') ++depth;
+ ast_list_t *chunks;
+ if (match(&pos, ":")) {
+ type = expect(ctx, start, &pos, parse_type, "I couldn't parse the type for this C_code code");
+ spaces(&pos);
+ if (!match(&pos, "("))
+ parser_err(ctx, start, pos, "I expected a '(' here");
+ chunks = new(ast_list_t, .ast=NewAST(ctx->file, pos, pos, TextLiteral, "({"),
+ .next=_parse_text_helper(ctx, &pos, '(', ')', '@'));
+ if (type) {
+ REVERSE_LIST(chunks);
+ chunks = new(ast_list_t, .ast=NewAST(ctx->file, pos, pos, TextLiteral, "; })"), .next=chunks);
+ REVERSE_LIST(chunks);
+ }
+ } else {
+ if (!match(&pos, "{"))
+ parser_err(ctx, start, pos, "I expected a '{' here");
+ chunks = _parse_text_helper(ctx, &pos, '{', '}', '@');
}
- if (depth != 0)
- parser_err(ctx, start, start+1, "I couldn't find the closing '}' for this inline C code");
-
- CORD c_code = GC_strndup(c_code_start, (size_t)((pos-1) - c_code_start));
- if (type)
- c_code = CORD_all("({ ", c_code, "; })");
- return NewAST(ctx->file, start, pos, InlineCCode, .code=c_code, .type_ast=type);
+ return NewAST(ctx->file, start, pos, InlineCCode, .chunks=chunks, .type_ast=type);
}
PARSER(parse_doctest) {