diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-09-06 14:46:15 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-09-06 14:46:15 -0400 |
| commit | d8a48f64111f542f3afeb5d6e47ff092f9278d9f (patch) | |
| tree | 07c364503025bb2a26edd7b26f1ba9e8d25340f6 /src/ast.c | |
| parent | 12345a85d9c7d7a56ddf323247a4bdf347021b73 (diff) | |
| parent | 73246764f88f6f652316ee0c138a990d836698a7 (diff) | |
Merge branch 'main' into optional-list-indexing
Diffstat (limited to 'src/ast.c')
| -rw-r--r-- | src/ast.c | 151 |
1 files changed, 75 insertions, 76 deletions
@@ -5,77 +5,76 @@ #include "ast.h" #include "stdlib/datatypes.h" +#include "stdlib/optionals.h" #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("\"")); } - -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"; - default: return NULL; - } +const int op_tightness[NUM_AST_TAGS] = { + [Power] = 9, + [Multiply] = 8, + [Divide] = 8, + [Mod] = 8, + [Mod1] = 8, + [Plus] = 7, + [Minus] = 7, + [Concat] = 6, + [LeftShift] = 5, + [RightShift] = 5, + [UnsignedLeftShift] = 5, + [UnsignedRightShift] = 5, + [Min] = 4, + [Max] = 4, + [Equals] = 3, + [NotEquals] = 3, + [LessThan] = 2, + [LessThanOrEquals] = 2, + [GreaterThan] = 2, + [GreaterThanOrEquals] = 2, + [Compare] = 2, + [And] = 1, + [Or] = 1, + [Xor] = 1, }; -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 Equals: return "=="; - case NotEquals: return "!="; - case LessThan: return "<"; - case LessThanOrEquals: return "<="; - case GreaterThan: return ">"; - case GreaterThanOrEquals: return ">="; - default: return NULL; - } +const binop_info_t binop_info[NUM_AST_TAGS] = { + [Power] = {"power", "^"}, + [PowerUpdate] = {"power", "^="}, + [Multiply] = {"times", "*"}, + [MultiplyUpdate] = {"times", "*="}, + [Divide] = {"divided_by", "/"}, + [DivideUpdate] = {"divided_by", "/="}, + [Mod] = {"modulo", "mod"}, + [ModUpdate] = {"modulo", "mod="}, + [Mod1] = {"modulo1", "mod1"}, + [Mod1Update] = {"modulo1", "mod1="}, + [Plus] = {"plus", "+"}, + [PlusUpdate] = {"plus", "+="}, + [Minus] = {"minus", "-"}, + [MinusUpdate] = {"minus", "-="}, + [Concat] = {"concatenated_with", "++"}, + [ConcatUpdate] = {"concatenated_with", "++="}, + [LeftShift] = {"left_shifted", "<<"}, + [LeftShiftUpdate] = {"left_shifted", "<<="}, + [RightShift] = {"right_shifted", ">>"}, + [RightShiftUpdate] = {"right_shifted", ">>="}, + [UnsignedLeftShift] = {"unsigned_left_shifted", NULL}, + [UnsignedLeftShiftUpdate] = {"unsigned_left_shifted", NULL}, + [UnsignedRightShift] = {"unsigned_right_shifted", NULL}, + [UnsignedRightShiftUpdate] = {"unsigned_right_shifted", NULL}, + [And] = {"bit_and", "and"}, + [AndUpdate] = {"bit_and", "and="}, + [Or] = {"bit_or", "or"}, + [OrUpdate] = {"bit_or", "or="}, + [Xor] = {"bit_xor", "xor"}, + [XorUpdate] = {"bit_xor", "xor="}, + [Equals] = {NULL, "=="}, + [NotEquals] = {NULL, "!="}, + [LessThan] = {NULL, "<"}, + [LessThanOrEquals] = {NULL, "<="}, + [GreaterThan] = {NULL, ">"}, + [GreaterThanOrEquals] = {NULL, ">="}, + [Min] = {NULL, "_min_"}, + [Max] = {NULL, "_max_"}, }; static Text_t ast_list_to_sexp(ast_list_t *asts); @@ -86,6 +85,8 @@ 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); +static Text_t quoted_text(const char *text) { return Text$quoted(Text$from_str(text), false, Text("\"")); } + Text_t ast_list_to_sexp(ast_list_t *asts) { Text_t c = EMPTY_TEXT; for (; asts; asts = asts->next) { @@ -175,8 +176,8 @@ Text_t ast_to_sexp(ast_t *ast) { 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(Int, "(Int ", Text$quoted(ast_source(ast), false, Text("\"")), ")"); + T(Num, "(Num ", Text$quoted(ast_source(ast), false, Text("\"")), ")"); 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), ")"); @@ -255,7 +256,7 @@ Text_t ast_to_sexp(ast_t *ast) { ")"); 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), " ", + T(Reduction, "(Reduction ", quoted_text(binop_info[data.op].operator), " ", ast_to_sexp(data.key), " ", ast_to_sexp(data.iter), ")"); T(Skip, "(Skip ", quoted_text(data.target), ")"); T(Stop, "(Stop ", quoted_text(data.target), ")"); @@ -285,13 +286,9 @@ Text_t ast_to_sexp(ast_t *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) { - if (!ast) return NULL; - size_t len = (size_t)(ast->end - ast->start); - char *source = GC_MALLOC_ATOMIC(len + 1); - memcpy(source, ast->start, len); - source[len] = '\0'; - return source; +OptionalText_t ast_source(ast_t *ast) { + if (ast == NULL || ast->start == NULL || ast->end == NULL) return NONE_TEXT; + return Text$from_strn(ast->start, (size_t)(ast->end - ast->start)); } PUREFUNC bool is_idempotent(ast_t *ast) { @@ -400,6 +397,8 @@ void visit_topologically(ast_list_t *asts, Closure_t fn) { CONSTFUNC bool is_binary_operation(ast_t *ast) { switch (ast->tag) { + case Min: + case Max: case BINOP_CASES: return true; default: return false; } |
