aboutsummaryrefslogtreecommitdiff
path: root/src/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast.c')
-rw-r--r--src/ast.c375
1 files changed, 223 insertions, 152 deletions
diff --git a/src/ast.c b/src/ast.c
index a1bcac58..7367580c 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -7,43 +7,66 @@
#include "stdlib/tables.h"
#include "stdlib/text.h"
-static Text_t quoted_text(const char *text) {
- return Text$quoted(Text$from_str(text), false, Text("\""));
-}
+static Text_t quoted_text(const char *text) { return Text$quoted(Text$from_str(text), false, Text("\"")); }
CONSTFUNC const char *binop_method_name(ast_e tag) {
switch (tag) {
- case Power: case PowerUpdate: return "power";
- case Multiply: case MultiplyUpdate: return "times";
- case Divide: case DivideUpdate: return "divided_by";
- case Mod: case ModUpdate: return "modulo";
- case Mod1: case Mod1Update: return "modulo1";
- case Plus: case PlusUpdate: return "plus";
- case Minus: case MinusUpdate: return "minus";
- case Concat: case ConcatUpdate: return "concatenated_with";
- case LeftShift: case LeftShiftUpdate: return "left_shifted";
- case RightShift: case RightShiftUpdate: return "right_shifted";
- case UnsignedLeftShift: case UnsignedLeftShiftUpdate: return "unsigned_left_shifted";
- case UnsignedRightShift: case UnsignedRightShiftUpdate: return "unsigned_right_shifted";
- case And: case AndUpdate: return "bit_and";
- case Or: case OrUpdate: return "bit_or";
- case Xor: case XorUpdate: return "bit_xor";
+ case Power:
+ case PowerUpdate: return "power";
+ case Multiply:
+ case MultiplyUpdate: return "times";
+ case Divide:
+ case DivideUpdate: return "divided_by";
+ case Mod:
+ case ModUpdate: return "modulo";
+ case Mod1:
+ case Mod1Update: return "modulo1";
+ case Plus:
+ case PlusUpdate: return "plus";
+ case Minus:
+ case MinusUpdate: return "minus";
+ case Concat:
+ case ConcatUpdate: return "concatenated_with";
+ case LeftShift:
+ case LeftShiftUpdate: return "left_shifted";
+ case RightShift:
+ case RightShiftUpdate: return "right_shifted";
+ case UnsignedLeftShift:
+ case UnsignedLeftShiftUpdate: return "unsigned_left_shifted";
+ case UnsignedRightShift:
+ case UnsignedRightShiftUpdate: return "unsigned_right_shifted";
+ case And:
+ case AndUpdate: return "bit_and";
+ case Or:
+ case OrUpdate: return "bit_or";
+ case Xor:
+ case XorUpdate: return "bit_xor";
default: return NULL;
}
};
CONSTFUNC const char *binop_operator(ast_e tag) {
switch (tag) {
- case Multiply: case MultiplyUpdate: return "*";
- case Divide: case DivideUpdate: return "/";
- case Mod: case ModUpdate: return "%";
- case Plus: case PlusUpdate: return "+";
- case Minus: case MinusUpdate: return "-";
- case LeftShift: case LeftShiftUpdate: return "<<";
- case RightShift: case RightShiftUpdate: return ">>";
- case And: case AndUpdate: return "&";
- case Or: case OrUpdate: return "|";
- case Xor: case XorUpdate: return "^";
+ case Multiply:
+ case MultiplyUpdate: return "*";
+ case Divide:
+ case DivideUpdate: return "/";
+ case Mod:
+ case ModUpdate: return "%";
+ case Plus:
+ case PlusUpdate: return "+";
+ case Minus:
+ case MinusUpdate: return "-";
+ case LeftShift:
+ case LeftShiftUpdate: return "<<";
+ case RightShift:
+ case RightShiftUpdate: return ">>";
+ case And:
+ case AndUpdate: return "&";
+ case Or:
+ case OrUpdate: return "|";
+ case Xor:
+ case XorUpdate: return "^";
case Equals: return "==";
case NotEquals: return "!=";
case LessThan: return "<";
@@ -62,8 +85,7 @@ static Text_t tags_to_sexp(tag_ast_t *tags);
static Text_t optional_sexp(const char *tag, ast_t *ast);
static Text_t optional_type_sexp(const char *tag, type_ast_t *ast);
-Text_t ast_list_to_sexp(ast_list_t *asts)
-{
+Text_t ast_list_to_sexp(ast_list_t *asts) {
Text_t c = EMPTY_TEXT;
for (; asts; asts = asts->next) {
c = Texts(c, " ", ast_to_sexp(asts->ast));
@@ -74,8 +96,8 @@ Text_t ast_list_to_sexp(ast_list_t *asts)
Text_t arg_defs_to_sexp(arg_ast_t *args) {
Text_t c = Text("(args");
for (arg_ast_t *arg = args; arg; arg = arg->next) {
- c = Texts(c, " (arg ", arg->name ? quoted_text(arg->name) : Text("nil"),
- " ", type_ast_to_sexp(arg->type), " ", ast_to_sexp(arg->value), ")");
+ c = Texts(c, " (arg ", arg->name ? quoted_text(arg->name) : Text("nil"), " ", type_ast_to_sexp(arg->type), " ",
+ ast_to_sexp(arg->value), ")");
}
return Texts(c, ")");
}
@@ -84,8 +106,7 @@ Text_t arg_list_to_sexp(arg_ast_t *args) {
Text_t c = EMPTY_TEXT;
for (arg_ast_t *arg = args; arg; arg = arg->next) {
assert(arg->value && !arg->type);
- if (arg->name)
- c = Texts(c, " :", arg->name);
+ if (arg->name) c = Texts(c, " :", arg->name);
c = Texts(c, " ", ast_to_sexp(arg->value));
}
return c;
@@ -107,118 +128,163 @@ Text_t tags_to_sexp(tag_ast_t *tags) {
return c;
}
-Text_t type_ast_to_sexp(type_ast_t *t)
-{
+Text_t type_ast_to_sexp(type_ast_t *t) {
if (!t) return Text("nil");
switch (t->tag) {
-#define T(type, ...) case type: { __typeof(t->__data.type) data = t->__data.type; (void)data; return Texts(__VA_ARGS__); }
- T(UnknownTypeAST, "(UnknownType)")
- T(VarTypeAST, "(VarType \"", data.name, "\")")
- T(PointerTypeAST, "(PointerType \"", data.is_stack ? "stack" : "heap", "\" ", type_ast_to_sexp(data.pointed), ")")
- T(ListTypeAST, "(ListType ", type_ast_to_sexp(data.item), ")")
- T(SetTypeAST, "(SetType ", type_ast_to_sexp(data.item), ")")
- T(TableTypeAST, "(TableType ", type_ast_to_sexp(data.key), " ", type_ast_to_sexp(data.value), ")")
- T(FunctionTypeAST, "(FunctionType ", arg_defs_to_sexp(data.args), " ", type_ast_to_sexp(data.ret), ")")
- T(OptionalTypeAST, "(OptionalType ", type_ast_to_sexp(data.type), ")")
+#define T(type, ...) \
+ case type: { \
+ __typeof(t->__data.type) data = t->__data.type; \
+ (void)data; \
+ return Texts(__VA_ARGS__); \
+ }
+ T(UnknownTypeAST, "(UnknownType)");
+ T(VarTypeAST, "(VarType \"", data.name, "\")");
+ T(PointerTypeAST, "(PointerType \"", data.is_stack ? "stack" : "heap", "\" ", type_ast_to_sexp(data.pointed),
+ ")");
+ T(ListTypeAST, "(ListType ", type_ast_to_sexp(data.item), ")");
+ T(SetTypeAST, "(SetType ", type_ast_to_sexp(data.item), ")");
+ T(TableTypeAST, "(TableType ", type_ast_to_sexp(data.key), " ", type_ast_to_sexp(data.value), ")");
+ T(FunctionTypeAST, "(FunctionType ", arg_defs_to_sexp(data.args), " ", type_ast_to_sexp(data.ret), ")");
+ T(OptionalTypeAST, "(OptionalType ", type_ast_to_sexp(data.type), ")");
#undef T
default: return EMPTY_TEXT;
}
}
-Text_t optional_sexp(const char *name, ast_t *ast)
-{
+Text_t optional_sexp(const char *name, ast_t *ast) {
return ast ? Texts(" :", name, " ", ast_to_sexp(ast)) : EMPTY_TEXT;
}
-Text_t optional_type_sexp(const char *name, type_ast_t *ast)
-{
+Text_t optional_type_sexp(const char *name, type_ast_t *ast) {
return ast ? Texts(" :", name, " ", type_ast_to_sexp(ast)) : EMPTY_TEXT;
}
-Text_t ast_to_sexp(ast_t *ast)
-{
+Text_t ast_to_sexp(ast_t *ast) {
if (!ast) return Text("nil");
switch (ast->tag) {
-#define T(type, ...) case type: { __typeof(ast->__data.type) data = ast->__data.type; (void)data; return Texts(__VA_ARGS__); }
- T(Unknown, "(Unknown)")
- T(None, "(None)")
- T(Bool, "(Bool ", data.b ? "yes" : "no", ")")
- T(Var, "(Var ", quoted_text(data.name), ")")
- T(Int, "(Int ", quoted_text(ast_source(ast)), ")")
- T(Num, "(Num ", quoted_text(ast_source(ast)), ")")
- T(TextLiteral, Text$quoted(data.text, false, Text("\"")))
- T(TextJoin, "(Text", data.lang ? Texts(" :lang ", quoted_text(data.lang)) : EMPTY_TEXT, ast_list_to_sexp(data.children), ")")
- T(Path, "(Path ", quoted_text(data.path), ")")
- T(Declare, "(Declare ", ast_to_sexp(data.var), " ", type_ast_to_sexp(data.type), " ", ast_to_sexp(data.value), ")")
- T(Assign, "(Assign (targets ", ast_list_to_sexp(data.targets), ") (values ", ast_list_to_sexp(data.values), "))")
+#define T(type, ...) \
+ case type: { \
+ __typeof(ast->__data.type) data = ast->__data.type; \
+ (void)data; \
+ return Texts(__VA_ARGS__); \
+ }
+ T(Unknown, "(Unknown)");
+ T(None, "(None)");
+ T(Bool, "(Bool ", data.b ? "yes" : "no", ")");
+ T(Var, "(Var ", quoted_text(data.name), ")");
+ T(Int, "(Int ", quoted_text(ast_source(ast)), ")");
+ T(Num, "(Num ", quoted_text(ast_source(ast)), ")");
+ T(TextLiteral, Text$quoted(data.text, false, Text("\"")));
+ T(TextJoin, "(Text", data.lang ? Texts(" :lang ", quoted_text(data.lang)) : EMPTY_TEXT,
+ ast_list_to_sexp(data.children), ")");
+ T(Path, "(Path ", quoted_text(data.path), ")");
+ T(Declare, "(Declare ", ast_to_sexp(data.var), " ", type_ast_to_sexp(data.type), " ", ast_to_sexp(data.value),
+ ")");
+ T(Assign, "(Assign (targets ", ast_list_to_sexp(data.targets), ") (values ", ast_list_to_sexp(data.values),
+ "))");
#define BINOP(name) T(name, "(" #name " ", ast_to_sexp(data.lhs), " ", ast_to_sexp(data.rhs), ")")
- BINOP(Power) BINOP(PowerUpdate) BINOP(Multiply) BINOP(MultiplyUpdate) BINOP(Divide) BINOP(DivideUpdate) BINOP(Mod) BINOP(ModUpdate)
- BINOP(Mod1) BINOP(Mod1Update) BINOP(Plus) BINOP(PlusUpdate) BINOP(Minus) BINOP(MinusUpdate) BINOP(Concat) BINOP(ConcatUpdate)
- BINOP(LeftShift) BINOP(LeftShiftUpdate) BINOP(RightShift) BINOP(RightShiftUpdate) BINOP(UnsignedLeftShift) BINOP(UnsignedLeftShiftUpdate)
- BINOP(UnsignedRightShift) BINOP(UnsignedRightShiftUpdate) BINOP(And) BINOP(AndUpdate) BINOP(Or) BINOP(OrUpdate)
- BINOP(Xor) BINOP(XorUpdate) BINOP(Compare)
- BINOP(Equals) BINOP(NotEquals) BINOP(LessThan) BINOP(LessThanOrEquals) BINOP(GreaterThan) BINOP(GreaterThanOrEquals)
+ BINOP(Power);
+ BINOP(PowerUpdate);
+ BINOP(Multiply);
+ BINOP(MultiplyUpdate);
+ BINOP(Divide);
+ BINOP(DivideUpdate);
+ BINOP(Mod);
+ BINOP(ModUpdate);
+ BINOP(Mod1);
+ BINOP(Mod1Update);
+ BINOP(Plus);
+ BINOP(PlusUpdate);
+ BINOP(Minus);
+ BINOP(MinusUpdate);
+ BINOP(Concat);
+ BINOP(ConcatUpdate);
+ BINOP(LeftShift);
+ BINOP(LeftShiftUpdate);
+ BINOP(RightShift);
+ BINOP(RightShiftUpdate);
+ BINOP(UnsignedLeftShift);
+ BINOP(UnsignedLeftShiftUpdate);
+ BINOP(UnsignedRightShift);
+ BINOP(UnsignedRightShiftUpdate);
+ BINOP(And);
+ BINOP(AndUpdate);
+ BINOP(Or);
+ BINOP(OrUpdate);
+ BINOP(Xor);
+ BINOP(XorUpdate);
+ BINOP(Compare);
+ BINOP(Equals);
+ BINOP(NotEquals);
+ BINOP(LessThan);
+ BINOP(LessThanOrEquals);
+ BINOP(GreaterThan);
+ BINOP(GreaterThanOrEquals);
#undef BINOP
- T(Negative, "(Negative ", ast_to_sexp(data.value), ")")
- T(Not, "(Not ", ast_to_sexp(data.value), ")")
- T(HeapAllocate, "(HeapAllocate ", ast_to_sexp(data.value), ")")
- T(StackReference, "(StackReference ", ast_to_sexp(data.value), ")")
- T(Min, "(Min ", ast_to_sexp(data.lhs), " ", ast_to_sexp(data.rhs), optional_sexp("key", data.key), ")")
- T(Max, "(Max ", ast_to_sexp(data.lhs), " ", ast_to_sexp(data.rhs), optional_sexp("key", data.key), ")")
- T(List, "(List", ast_list_to_sexp(data.items), ")")
- T(Set, "(Set", ast_list_to_sexp(data.items), ")")
- T(Table, "(Table", optional_sexp("default", data.default_value), optional_sexp("fallback", data.fallback),
- ast_list_to_sexp(data.entries), ")")
- T(TableEntry, "(TableEntry ", ast_to_sexp(data.key), " ", ast_to_sexp(data.value), ")")
- T(Comprehension, "(Comprehension ", ast_to_sexp(data.expr), " (vars", ast_list_to_sexp(data.vars), ") ",
- ast_to_sexp(data.iter), " ", optional_sexp("filter", data.filter), ")")
- T(FunctionDef, "(FunctionDef ", ast_to_sexp(data.name), " ", arg_defs_to_sexp(data.args),
- optional_type_sexp("return", data.ret_type), " ", ast_to_sexp(data.body), ")")
- T(ConvertDef, "(ConvertDef ", arg_defs_to_sexp(data.args), " ", type_ast_to_sexp(data.ret_type), " ", ast_to_sexp(data.body), ")")
- T(Lambda, "(Lambda ", arg_defs_to_sexp(data.args), optional_type_sexp("return", data.ret_type), " ", ast_to_sexp(data.body), ")")
- T(FunctionCall, "(FunctionCall ", ast_to_sexp(data.fn), arg_list_to_sexp(data.args), ")")
- T(MethodCall, "(MethodCall ", ast_to_sexp(data.self), " ", quoted_text(data.name), arg_list_to_sexp(data.args), ")")
- T(Block, "(Block", ast_list_to_sexp(data.statements), ")")
- T(For, "(For (vars", ast_list_to_sexp(data.vars), ") ", ast_to_sexp(data.iter), " ", ast_to_sexp(data.body),
- " ", ast_to_sexp(data.empty), ")")
- T(While, "(While ", ast_to_sexp(data.condition), " ", ast_to_sexp(data.body), ")")
- T(Repeat, "(Repeat ", ast_to_sexp(data.body), ")")
- T(If, "(If ", ast_to_sexp(data.condition), " ", ast_to_sexp(data.body), optional_sexp("else", data.else_body), ")")
- T(When, "(When ", ast_to_sexp(data.subject), when_clauses_to_sexp(data.clauses), optional_sexp("else", data.else_body), ")")
- T(Reduction, "(Reduction ", quoted_text(binop_method_name(data.op)), " ", ast_to_sexp(data.key), " ", ast_to_sexp(data.iter), ")")
- T(Skip, "(Skip ", quoted_text(data.target), ")")
- T(Stop, "(Stop ", quoted_text(data.target), ")")
- T(Pass, "(Pass)")
- T(Defer, "(Defer ", ast_to_sexp(data.body), ")")
- T(Return, "(Return ", ast_to_sexp(data.value), ")")
- T(Extern, "(Extern \"", data.name, "\" ", type_ast_to_sexp(data.type), ")")
- T(StructDef, "(StructDef \"", data.name, "\" ", arg_defs_to_sexp(data.fields), " ", ast_to_sexp(data.namespace), ")")
- T(EnumDef, "(EnumDef \"", data.name, "\" (tags ", tags_to_sexp(data.tags), ") ", ast_to_sexp(data.namespace), ")")
- T(LangDef, "(LangDef \"", data.name, "\" ", ast_to_sexp(data.namespace), ")")
- T(Index, "(Index ", ast_to_sexp(data.indexed), " ", ast_to_sexp(data.index), ")")
- T(FieldAccess, "(FieldAccess ", ast_to_sexp(data.fielded), " \"", data.field, "\")")
- T(Optional, "(Optional ", ast_to_sexp(data.value), ")")
- T(NonOptional, "(NonOptional ", ast_to_sexp(data.value), ")")
- T(DocTest, "(DocTest ", ast_to_sexp(data.expr), optional_sexp("expected", data.expected), ")")
- T(Assert, "(Assert ", ast_to_sexp(data.expr), " ", optional_sexp("message", data.message), ")")
- T(Use, "(Use ", optional_sexp("var", data.var), " ", quoted_text(data.path), ")")
- T(InlineCCode, "(InlineCCode ", ast_list_to_sexp(data.chunks), optional_type_sexp("type", data.type_ast), ")")
- T(Deserialize, "(Deserialize ", type_ast_to_sexp(data.type), " ", ast_to_sexp(data.value), ")")
- T(Extend, "(Extend \"", data.name, "\" ", ast_to_sexp(data.body), ")")
- default: errx(1, "S-expressions are not implemented for this AST");
+ T(Negative, "(Negative ", ast_to_sexp(data.value), ")");
+ T(Not, "(Not ", ast_to_sexp(data.value), ")");
+ T(HeapAllocate, "(HeapAllocate ", ast_to_sexp(data.value), ")");
+ T(StackReference, "(StackReference ", ast_to_sexp(data.value), ")");
+ T(Min, "(Min ", ast_to_sexp(data.lhs), " ", ast_to_sexp(data.rhs), optional_sexp("key", data.key), ")");
+ T(Max, "(Max ", ast_to_sexp(data.lhs), " ", ast_to_sexp(data.rhs), optional_sexp("key", data.key), ")");
+ T(List, "(List", ast_list_to_sexp(data.items), ")");
+ T(Set, "(Set", ast_list_to_sexp(data.items), ")");
+ T(Table, "(Table", optional_sexp("default", data.default_value), optional_sexp("fallback", data.fallback),
+ ast_list_to_sexp(data.entries), ")");
+ T(TableEntry, "(TableEntry ", ast_to_sexp(data.key), " ", ast_to_sexp(data.value), ")");
+ T(Comprehension, "(Comprehension ", ast_to_sexp(data.expr), " (vars", ast_list_to_sexp(data.vars), ") ",
+ ast_to_sexp(data.iter), " ", optional_sexp("filter", data.filter), ")");
+ T(FunctionDef, "(FunctionDef ", ast_to_sexp(data.name), " ", arg_defs_to_sexp(data.args),
+ optional_type_sexp("return", data.ret_type), " ", ast_to_sexp(data.body), ")");
+ T(ConvertDef, "(ConvertDef ", arg_defs_to_sexp(data.args), " ", type_ast_to_sexp(data.ret_type), " ",
+ ast_to_sexp(data.body), ")");
+ T(Lambda, "(Lambda ", arg_defs_to_sexp(data.args), optional_type_sexp("return", data.ret_type), " ",
+ ast_to_sexp(data.body), ")");
+ T(FunctionCall, "(FunctionCall ", ast_to_sexp(data.fn), arg_list_to_sexp(data.args), ")");
+ T(MethodCall, "(MethodCall ", ast_to_sexp(data.self), " ", quoted_text(data.name), arg_list_to_sexp(data.args),
+ ")")
+ T(Block, "(Block", ast_list_to_sexp(data.statements), ")");
+ T(For, "(For (vars", ast_list_to_sexp(data.vars), ") ", ast_to_sexp(data.iter), " ", ast_to_sexp(data.body),
+ " ", ast_to_sexp(data.empty), ")");
+ T(While, "(While ", ast_to_sexp(data.condition), " ", ast_to_sexp(data.body), ")");
+ T(Repeat, "(Repeat ", ast_to_sexp(data.body), ")");
+ T(If, "(If ", ast_to_sexp(data.condition), " ", ast_to_sexp(data.body), optional_sexp("else", data.else_body),
+ ")");
+ T(When, "(When ", ast_to_sexp(data.subject), when_clauses_to_sexp(data.clauses),
+ optional_sexp("else", data.else_body), ")");
+ T(Reduction, "(Reduction ", quoted_text(binop_method_name(data.op)), " ", ast_to_sexp(data.key), " ",
+ ast_to_sexp(data.iter), ")");
+ T(Skip, "(Skip ", quoted_text(data.target), ")");
+ T(Stop, "(Stop ", quoted_text(data.target), ")");
+ T(Pass, "(Pass)");
+ T(Defer, "(Defer ", ast_to_sexp(data.body), ")");
+ T(Return, "(Return ", ast_to_sexp(data.value), ")");
+ T(Extern, "(Extern \"", data.name, "\" ", type_ast_to_sexp(data.type), ")");
+ T(StructDef, "(StructDef \"", data.name, "\" ", arg_defs_to_sexp(data.fields), " ", ast_to_sexp(data.namespace),
+ ")");
+ T(EnumDef, "(EnumDef \"", data.name, "\" (tags ", tags_to_sexp(data.tags), ") ", ast_to_sexp(data.namespace),
+ ")");
+ T(LangDef, "(LangDef \"", data.name, "\" ", ast_to_sexp(data.namespace), ")");
+ T(Index, "(Index ", ast_to_sexp(data.indexed), " ", ast_to_sexp(data.index), ")");
+ T(FieldAccess, "(FieldAccess ", ast_to_sexp(data.fielded), " \"", data.field, "\")");
+ T(Optional, "(Optional ", ast_to_sexp(data.value), ")");
+ T(NonOptional, "(NonOptional ", ast_to_sexp(data.value), ")");
+ T(DocTest, "(DocTest ", ast_to_sexp(data.expr), optional_sexp("expected", data.expected), ")");
+ T(Assert, "(Assert ", ast_to_sexp(data.expr), " ", optional_sexp("message", data.message), ")");
+ T(Use, "(Use ", optional_sexp("var", data.var), " ", quoted_text(data.path), ")");
+ T(InlineCCode, "(InlineCCode ", ast_list_to_sexp(data.chunks), optional_type_sexp("type", data.type_ast), ")");
+ T(Deserialize, "(Deserialize ", type_ast_to_sexp(data.type), " ", ast_to_sexp(data.value), ")");
+ T(Extend, "(Extend \"", data.name, "\" ", ast_to_sexp(data.body), ")");
+ default: errx(1, "S-expressions are not implemented for this AST");
#undef T
}
}
-const char *ast_to_sexp_str(ast_t *ast)
-{
- return Text$as_c_string(ast_to_sexp(ast));
-}
+const char *ast_to_sexp_str(ast_t *ast) { return Text$as_c_string(ast_to_sexp(ast)); }
-const char *ast_source(ast_t *ast)
-{
+const char *ast_source(ast_t *ast) {
if (!ast) return NULL;
size_t len = (size_t)(ast->end - ast->start);
char *source = GC_MALLOC_ATOMIC(len + 1);
@@ -227,10 +293,14 @@ const char *ast_source(ast_t *ast)
return source;
}
-PUREFUNC bool is_idempotent(ast_t *ast)
-{
+PUREFUNC bool is_idempotent(ast_t *ast) {
switch (ast->tag) {
- case Int: case Bool: case Num: case Var: case None: case TextLiteral: return true;
+ case Int:
+ case Bool:
+ case Num:
+ case Var:
+ case None:
+ case TextLiteral: return true;
case Index: {
DeclareMatch(index, ast, Index);
return is_idempotent(index->indexed) && index->index != NULL && is_idempotent(index->index);
@@ -243,15 +313,13 @@ PUREFUNC bool is_idempotent(ast_t *ast)
}
}
-void _visit_topologically(ast_t *ast, Table_t definitions, Table_t *visited, Closure_t fn)
-{
- void (*visit)(void*, ast_t*) = (void*)fn.fn;
+void _visit_topologically(ast_t *ast, Table_t definitions, Table_t *visited, Closure_t fn) {
+ void (*visit)(void *, ast_t *) = (void *)fn.fn;
if (ast->tag == StructDef) {
DeclareMatch(def, ast, StructDef);
- if (Table$str_get(*visited, def->name))
- return;
+ if (Table$str_get(*visited, def->name)) return;
- Table$str_set(visited, def->name, (void*)_visit_topologically);
+ Table$str_set(visited, def->name, (void *)_visit_topologically);
for (arg_ast_t *field = def->fields; field; field = field->next) {
if (field->type && field->type->tag == VarTypeAST) {
const char *field_type_name = Match(field->type, VarTypeAST)->name;
@@ -260,15 +328,13 @@ void _visit_topologically(ast_t *ast, Table_t definitions, Table_t *visited, Clo
_visit_topologically(dependency, definitions, visited, fn);
}
}
-
}
visit(fn.userdata, ast);
} else if (ast->tag == EnumDef) {
DeclareMatch(def, ast, EnumDef);
- if (Table$str_get(*visited, def->name))
- return;
+ if (Table$str_get(*visited, def->name)) return;
- Table$str_set(visited, def->name, (void*)_visit_topologically);
+ Table$str_set(visited, def->name, (void *)_visit_topologically);
for (tag_ast_t *tag = def->tags; tag; tag = tag->next) {
for (arg_ast_t *field = tag->fields; field; field = field->next) {
if (field->type && field->type->tag == VarTypeAST) {
@@ -283,16 +349,14 @@ void _visit_topologically(ast_t *ast, Table_t definitions, Table_t *visited, Clo
visit(fn.userdata, ast);
} else if (ast->tag == LangDef) {
DeclareMatch(def, ast, LangDef);
- if (Table$str_get(*visited, def->name))
- return;
+ if (Table$str_get(*visited, def->name)) return;
visit(fn.userdata, ast);
} else {
visit(fn.userdata, ast);
}
}
-void visit_topologically(ast_list_t *asts, Closure_t fn)
-{
+void visit_topologically(ast_list_t *asts, Closure_t fn) {
// Visit each top-level statement in topological order:
// - 'use' statements first
// - then typedefs
@@ -313,12 +377,11 @@ void visit_topologically(ast_list_t *asts, Closure_t fn)
}
}
- void (*visit)(void*, ast_t*) = (void*)fn.fn;
+ void (*visit)(void *, ast_t *) = (void *)fn.fn;
Table_t visited = {};
// First: 'use' statements in order:
for (ast_list_t *stmt = asts; stmt; stmt = stmt->next) {
- if (stmt->ast->tag == Use)
- visit(fn.userdata, stmt->ast);
+ if (stmt->ast->tag == Use) visit(fn.userdata, stmt->ast);
}
// Then typedefs in topological order:
for (ast_list_t *stmt = asts; stmt; stmt = stmt->next) {
@@ -334,27 +397,35 @@ void visit_topologically(ast_list_t *asts, Closure_t fn)
}
}
-CONSTFUNC bool is_binary_operation(ast_t *ast)
-{
+CONSTFUNC bool is_binary_operation(ast_t *ast) {
switch (ast->tag) {
case BINOP_CASES: return true;
default: return false;
}
}
-CONSTFUNC bool is_update_assignment(ast_t *ast)
-{
+CONSTFUNC bool is_update_assignment(ast_t *ast) {
switch (ast->tag) {
- case PowerUpdate: case MultiplyUpdate: case DivideUpdate: case ModUpdate: case Mod1Update:
- case PlusUpdate: case MinusUpdate: case ConcatUpdate: case LeftShiftUpdate: case UnsignedLeftShiftUpdate:
- case RightShiftUpdate: case UnsignedRightShiftUpdate: case AndUpdate: case OrUpdate: case XorUpdate:
- return true;
+ case PowerUpdate:
+ case MultiplyUpdate:
+ case DivideUpdate:
+ case ModUpdate:
+ case Mod1Update:
+ case PlusUpdate:
+ case MinusUpdate:
+ case ConcatUpdate:
+ case LeftShiftUpdate:
+ case UnsignedLeftShiftUpdate:
+ case RightShiftUpdate:
+ case UnsignedRightShiftUpdate:
+ case AndUpdate:
+ case OrUpdate:
+ case XorUpdate: return true;
default: return false;
}
}
-CONSTFUNC ast_e binop_tag(ast_e tag)
-{
+CONSTFUNC ast_e binop_tag(ast_e tag) {
switch (tag) {
case PowerUpdate: return Power;
case MultiplyUpdate: return Multiply;